关于裸机多任务
Posted GXTon
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于裸机多任务相关的知识,希望对你有一定的参考价值。
// 任务结构
typedef
struct
_TASK_COMPONENTS
{
uint8 Run;
// 程序运行标记:0-不运行,1运行
uint8 Timer;
// 计时器
uint8 ItvTime;
// 任务运行间隔时间
void
(*TaskHook)(
void
);
// 要运行的任务函数
} TASK_COMPONENTS;
// 任务定义
//定时器中断函数
void
TaskRemarks(
void
)
{
uint8 i;
for
(i=0; i<TASKS_MAX; i++)
// 逐个任务时间处理
{
if
(TaskComps[i].Timer)
// 时间不为0
{
TaskComps[i].Timer--;
// 减去一个节拍
if
(TaskComps[i].Timer == 0)
// 时间减完了
{
TaskComps[i].Timer = TaskComps[i].ItvTime;
// 恢复计时器值,从新下一次
TaskComps[i].Run = 1;
// 任务可以运行
}
}
}
}
/**************************************************************************************
* FunctionName : TaskProcess()
* Description : 任务处理
* EntryParameter : None
* ReturnValue : None
**************************************************************************************/
void
TaskProcess(
void
)
{
uint8 i;
for
(i=0; i<TASKS_MAX; i++)
// 逐个任务时间处理
{
if
(TaskComps[i].Run)
// 时间不为0
{
TaskComps[i].TaskHook();
// 运行任务
TaskComps[i].Run = 0;
// 标志清0
}
}
}
static
TASK_COMPONENTS TaskComps[] =
{
{0, 60, 60, TaskDisplayClock},
// 显示时钟
{0, 20, 20, TaskKeySan},
// 按键扫描
{0, 30, 30, TaskDispStatus},
// 显示工作状态
// 这里添加你的任务。。。。
};
这个就要靠你自己编码了 ,既然在滴答中断中做任务调度,那么只需在延时的滴答时间内不去做该任务的调度即可,这样不就是实现了延时挂起任务了吗 做一个实现延时并且挂起任务的函数api
刚才找到了那个案例,看了下还真是大循环……并不适合我现在做的这个多任务并行产品上,会考虑用OS去解决这个问题……
不过就是心理有疑问:不用OS能不能很好的解决这些问题呢?又不用额外开个定时器呢?
之前裸跑做复杂应用的时候难道都是像mini的综合历程一样很费劲的写菜单数据结构再来个大循环?要真是这样上OS确实是上上之策
总想把不懂得东西搞清楚……有时候太爱钻牛角尖,自己跟自己过不去
不过就是心理有疑问:不用OS能不能很好的解决这些问题呢?又不用额外开个定时器呢?
之前裸跑做复杂应用的时候难道都是像mini的综合历程一样很费劲的写菜单数据结构再来个大循环?要真是这样上OS确实是上上之策
总想把不懂得东西搞清楚……有时候太爱钻牛角尖,自己跟自己过不去
都说ucos商业要钱,freertos不要钱……那么ucos怎么知道我在产品上用没用他的系统呢?
“小的延时通过死等实现,对于大于最小时间片(1ms)的延时,是不是在delay的地方重新对TaskComps.Timer进行赋值呢?”
这个问题是你提出来的吧?别的不说,先考虑IIC时序,有部分延时是超过1ms的,那请问你怎么解决这个时序的延时?想不通的话看看我上面的截图吧,我的测试代码是最小延时节拍是1ms,只要你的IIC延时大于1ms,可以直接像操作系统那样子调用PROCESS_DELAY来实现
楼主,你贴的代码,是属于时间触发的嵌入式系统构架!
然而,楼主你的理解本质上是错的!
原因:TaskProcess这个函数就不应该在中断里运行,而是应该在主循环运行!
结构是:IRQ:TaskRemarks
Main Loop:TaskProcess
这是典型的前台负责系统滴答,后台负责任务轮询调度!
然后:在设计任务的时候,设计任务时单次运行时间应该越短越好!
除时序延时外的延时都尽量去除而采用状态转移(状态机)来处理!
假如要发送一个hello
如果while(print(hello))这种形式是最笨的设计方法!
用switch ---h---e---l---l---o把hello分成5次发送,发送不要死等标记,发送成功退出,不发送成功照样退出!
设计的时候考虑消费者生产者原则!认清辅助和主线任务,必要的时候要做取舍(偏心)!
然而,楼主你的理解本质上是错的!
原因:TaskProcess这个函数就不应该在中断里运行,而是应该在主循环运行!
结构是:IRQ:TaskRemarks
Main Loop:TaskProcess
这是典型的前台负责系统滴答,后台负责任务轮询调度!
然后:在设计任务的时候,设计任务时单次运行时间应该越短越好!
除时序延时外的延时都尽量去除而采用状态转移(状态机)来处理!
假如要发送一个hello
如果while(print(hello))这种形式是最笨的设计方法!
用switch ---h---e---l---l---o把hello分成5次发送,发送不要死等标记,发送成功退出,不发送成功照样退出!
设计的时候考虑消费者生产者原则!认清辅助和主线任务,必要的时候要做取舍(偏心)!
出问题那是设计者笨!
任务的运行期间出现中断是必然的事情,这个时候就需要你来保护了(原子保护)
这个正点原子保护在你们用的OS中有个名词,叫临界区!
以上是关于关于裸机多任务的主要内容,如果未能解决你的问题,请参考以下文章
#yyds干货盘点# Java | 关于synchronized相关理解