关于裸机多任务

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确实是上上之策
总想把不懂得东西搞清楚……有时候太爱钻牛角尖,自己跟自己过不去
 
 
都说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次发送,发送不要死等标记,发送成功退出,不发送成功照样退出!
设计的时候考虑消费者生产者原则!认清辅助和主线任务,必要的时候要做取舍(偏心)!
 
 

出问题那是设计者笨!
任务的运行期间出现中断是必然的事情,这个时候就需要你来保护了(原子保护)
这个正点原子保护在你们用的OS中有个名词,叫临界区!
 
 
 

以上是关于关于裸机多任务的主要内容,如果未能解决你的问题,请参考以下文章

单片机裸机 vs RTOS多线程

#yyds干货盘点# Java | 关于synchronized相关理解

译文:18个实用的JavaScript代码片段,助你快速处理日常编程任务

Cortex-M裸机环境下临界区保护的三种实现

Cortex-M裸机环境下临界区保护的三种实现

多线程 Thread 线程同步 synchronized