较大的Sys.Delay也需要进行时间任务调度,默认以50us作为边界

This commit is contained in:
nnhy 2015-10-05 12:36:35 +00:00
parent 43cd70a28d
commit dbd64c0fac
4 changed files with 52 additions and 46 deletions

39
Sys.cpp
View File

@ -449,8 +449,8 @@ void TSys::ToHex(byte* buf, byte* src, uint len)
// 任务
#include "Task.h"
// 创建任务,返回任务编号。priority优先级dueTime首次调度时间usperiod调度间隔us-1表示仅处理一次
uint TSys::AddTask(Action func, void* param, Int64 dueTime, Int64 period, string name)
// 创建任务,返回任务编号。dueTime首次调度时间msperiod调度间隔ms-1表示仅处理一次
uint TSys::AddTask(Action func, void* param, int dueTime, int period, string name)
{
return Task::Scheduler()->Add(func, param, dueTime, period, name);
}
@ -461,7 +461,7 @@ void TSys::RemoveTask(uint& taskid)
taskid = 0;
}
bool TSys::SetTask(uint taskid, bool enable, int usNextTime)
bool TSys::SetTask(uint taskid, bool enable, int msNextTime)
{
if(!taskid) return false;
@ -471,7 +471,7 @@ bool TSys::SetTask(uint taskid, bool enable, int usNextTime)
task->Enable = enable;
// 可以安排最近一次执行的时间比如0表示马上调度执行
if(usNextTime >= 0) task->NextTime = Time.Current() + usNextTime;
if(msNextTime >= 0) task->NextTime = Time.Current() + msNextTime;
// 如果系统调度器处于Sleep让它立马退出
if(enable) Task::Scheduler()->Sleeping = false;
@ -480,7 +480,7 @@ bool TSys::SetTask(uint taskid, bool enable, int usNextTime)
}
// 改变任务周期
bool TSys::SetTaskPeriod(uint taskid, Int64 period)
bool TSys::SetTaskPeriod(uint taskid, int period)
{
if(!taskid) return false;
@ -511,10 +511,10 @@ void TSys::Start()
Task::Scheduler()->Start();
}
void TimeSleep(uint ms)
void TimeSleep(uint us)
{
// 在这段时间里面,去处理一下别的任务
if(Sys.Started)
if(Sys.Started && us != 0 && us >= 50)
{
TaskScheduler* sc = Task::Scheduler();
// 记录当前正在执行任务
@ -522,32 +522,32 @@ void TimeSleep(uint ms)
TimeCost tc;
// 实际可用时间。100us一般不够调度新任务留给硬件等待
int total = ms;
int total = us;
// 如果休眠时间足够长,允许多次调度其它任务
while(true)
{
// 统计这次调度的时间,累加作为当前任务的休眠时间
TimeCost tc2;
sc->Execute(total);
sc->Execute(total / 1000);
total -= tc2.Elapsed();
if(total <= 0) break;
}
int cost = tc.Elapsed();
int ct = tc.Elapsed();
if(task)
{
sc->Current = task;
task->SleepTime += cost;
task->SleepTime += ct;
}
if(cost >= ms) return;
if(ct >= us) return;
ms -= cost;
us -= ct;
}
if(ms) Time.Sleep(ms);
if(us) Time.Delay(us);
}
void TSys::Sleep(uint ms)
@ -558,10 +558,10 @@ void TSys::Sleep(uint ms)
else
{
#if DEBUG
if(ms > 1000) debug_printf("Sys::Sleep 设计错误,睡眠%dms太长超过1000ms建议使用多线程Thread", ms);
if(ms > 1000) debug_printf("Sys::Sleep 设计错误,睡眠%dms太长", ms);
#endif
TimeSleep(ms);
TimeSleep(ms * 1000);
}
}
@ -573,10 +573,13 @@ void TSys::Delay(uint us)
else
{
#if DEBUG
if(us > 1000000) debug_printf("Sys::Sleep 设计错误,睡眠%dus太长超过1000ms建议使用多线程Thread", us);
if(us > 1000000) debug_printf("Sys::Sleep 设计错误,睡眠%dus太长", us);
#endif
Time.Delay(us);
if(us < 50)
Time.Delay(us);
else
TimeSleep(us);
}
}
#endif

8
Sys.h
View File

@ -120,13 +120,13 @@ private:
int _Index; // MCU在型号表中的索引
public:
// 创建任务返回任务编号。dueTime首次调度时间usperiod调度间隔us-1表示仅处理一次
uint AddTask(Action func, void* param, Int64 dueTime = 0, Int64 period = 0, string name = NULL);
// 创建任务返回任务编号。dueTime首次调度时间msperiod调度间隔ms-1表示仅处理一次
uint AddTask(Action func, void* param, int dueTime = 0, int period = 0, string name = NULL);
void RemoveTask(uint& taskid);
// 设置任务的开关状态同时运行指定任务最近一次调度的时间0表示马上调度
bool SetTask(uint taskid, bool enable, int usNextTime = -1);
bool SetTask(uint taskid, bool enable, int msNextTime = -1);
// 改变任务周期
bool SetTaskPeriod(uint taskid, Int64 period);
bool SetTaskPeriod(uint taskid, int period);
void Start(); // 开始系统大循环
Func OnStart;
};

View File

@ -11,6 +11,7 @@ Task::Task()
CpuTime = 0;
SleepTime = 0;
Cost = 0;
CostMs = 0;
MaxCost = 0;
Enable = true;
Event = false;
@ -45,19 +46,20 @@ bool Task::Execute(ulong now)
// 累加任务执行次数和时间
Times++;
int cost = tc.Elapsed();
if(cost < 0) debug_printf("cost = %d \r\n", cost);
if(cost < 0) cost = -cost;
//if(cost > 0)
int ct = tc.Elapsed();
if(ct < 0) debug_printf("cost = %d \r\n", ct);
if(ct < 0) ct = -ct;
//if(ct > 0)
{
cost -= SleepTime;
if(cost > MaxCost) MaxCost = cost;
CpuTime += cost;
ct -= SleepTime;
if(ct > MaxCost) MaxCost = ct;
CpuTime += ct;
Cost = CpuTime / Times;
CostMs = Cost / 1000;
}
#if DEBUG
if(cost > 500000) debug_printf("Task::Execute 任务 %d [%d] 执行时间过长 %dms 睡眠 %dms\r\n", ID, Times, cost, SleepTime);
if(ct > 500000) debug_printf("Task::Execute 任务 %d [%d] 执行时间过长 %dus 睡眠 %dus\r\n", ID, Times, ct, SleepTime);
#endif
// 如果只是一次性任务,在这里清理
@ -71,17 +73,17 @@ bool Task::Execute(ulong now)
// 显示状态
void Task::ShowStatus()
{
debug_printf("Task::%s \t%d [%d] \t平均 %dms ", Name, ID, Times, Cost);
debug_printf("Task::%s \t%d [%d] \t平均 %dus ", Name, ID, Times, Cost);
if(Cost < 1000) debug_printf("\t");
debug_printf("\t最大 %dms ", MaxCost);
debug_printf("\t最大 %dus ", MaxCost);
if(MaxCost < 1000) debug_printf("\t");
debug_printf("\t周期 ");
if(Period >= 1000)
debug_printf("%ds", (int)(Period / 1000));
debug_printf("%ds", Period / 1000);
else
debug_printf("%dms", (int)Period);
debug_printf("%dms", Period);
if(!Enable) debug_printf(" 禁用");
debug_printf("\r\n");
}
@ -236,7 +238,7 @@ void TaskScheduler::Execute(uint msMax)
if((task->NextTime <= now || task->NextTime < 0)
// 并且任务的平均耗时要足够调度才安排执行避免上层是Sleep时超出预期时间
&& Time.Current() + task->Cost <= end)
&& Time.Current() + task->CostMs <= end)
{
task->Execute(now);
@ -255,12 +257,12 @@ void TaskScheduler::Execute(uint msMax)
}
}
int cost = tc.Elapsed();
int ct = tc.Elapsed();
if(Cost > 0)
Cost = (Cost + cost) / 2;
Cost = (Cost + ct) >> 1;
else
Cost = cost;
if(cost > MaxCost) MaxCost = cost;
Cost = ct;
if(ct > MaxCost) MaxCost = ct;
// 如果有最小时间,睡一会吧
now = Time.Current(); // 当前时间
@ -281,7 +283,7 @@ void TaskScheduler::ShowStatus(void* param)
{
TaskScheduler* host = (TaskScheduler*)param;
debug_printf("Task::ShowStatus 平均 %dms 最大 %dms 系统启动 ", host->Cost, host->MaxCost);
debug_printf("Task::ShowStatus 平均 %dus 最大 %dus 系统启动 ", host->Cost, host->MaxCost);
Time.Now().Show(true);
IArray<Task>& ts = *(host->_Tasks);

13
Task.h
View File

@ -25,10 +25,11 @@ public:
Int64 NextTime; // 下一次执行时间ms
int Times; // 执行次数
int CpuTime; // 总耗费时间
int SleepTime; // 当前睡眠时间
int Cost; // 平均执行时间
int MaxCost; // 最大执行时间
int CpuTime; // 总耗费时间us
int SleepTime; // 当前睡眠时间us
int Cost; // 平均执行时间us
int CostMs; // 平均执行时间ms
int MaxCost; // 最大执行时间us
bool Enable; // 是否启用
bool Event; // 是否只执行一次后暂停的事件型任务
@ -63,8 +64,8 @@ public:
bool Running; // 是否正在运行
bool Sleeping; // 如果当前处于Sleep状态马上停止并退出
int Cost; // 平均执行时间
int MaxCost; // 最大执行时间
int Cost; // 平均执行时间us
int MaxCost; // 最大执行时间us
TaskScheduler(string name = NULL);
~TaskScheduler();