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

8
Sys.h
View File

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

View File

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

13
Task.h
View File

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