小型调度框架

架构的运行机制

 

while (1)

{

task_handle();

}

 

voidtask_handle(void)

{

    uint8_t i;      

    for (i = 0; i < ARRAY_SIZE(tasks); ++i)

    {

        if ((is_task_set(tasks[i].id))

            ||(is_task_always_alive(tasks[i].flags)))

        {

            reset_task(tasks[i].id);

            tasks[i].handle(tasks[i].args);

        }

    }

}

从代码上来看这是一个轮询机制。

 

调度函数的条件有两个如下:

1)       is_task_set(tasks[i].id)

2)       is_task_always_alive(tasks[i].flags)

第一种调度的原理:

我们先看第一种条件的调度:

Ø  notify(tasks[i].id);

Ø  is_task_set(tasks[i].id)

Ø  reset_task(tasks[i].id)

 

 

 

structtask

{

    uint8_t id;

    uint8_t flags;

    void *args;

    void (*handle)(void *args);

};

 

对应于下列:

const struct tasktasks[] =

{        uint8_t id;          uint8_t flags;        void*args;     void (*handle)(void *args)

    {EV_TICK_LITTLE,     ALWAYS_ALIVE,     NULL,    sys_tick_little},  

    {EV_READ,            ALWAYS_ALIVE,     NULL,    read_rf_status_cmd},

    {EV_CONTROL_IR,           0,             NULL,     period_control_ir},

    {EV_100MS,                  0,             NULL,     task_100ms},//

    {EV_SEC,                    0,             NULL,     task_sec},

    {EV_TICK,            ALWAYS_ALIVE,     NULL,    sys_tick},

    {EV_REPORT_DATA,          0,            NULL,     report_data_rf},        

    {EV_USB_TASK,              0,            NULL,    handle_usb_task},

    {EV_3MS,                    0,             NULL,    task_3ms},

    {EV_6MS,                    0,             NULL,    task_6ms},

    {EV_12MS,                   0,             NULL,    task_12ms},

    {EV_CALIBRATE_GRY_ACC,   0,             NULL,    calibrate_gry_acc},

              

}; 

 

第一种条件下的调度原理,先看这个函数的展开:

Ø  notify(tasks[i].id);

#define notify(task_bit)         set_bit(task_monitor,task_bit)

#define set_bit(x, bit)        do{ __disable_irq();(x) |= 1 <<(bit);__enable_irq();}while(0)

注:执行置位的时候开启了总中断。

Ø  is_task_set(tasks[i].id)

#define is_task_set(task_bit)  is_bit_set(task_monitor, task_bit)

#define is_bit_set(x, bit)       ((x) & (1 << (bit)))

 

Ø  reset_task(tasks[i].id)

#define reset_task(task_bit)   reset_bit(task_monitor, task_bit)

#define reset_bit(x, bit)        do{ __disable_irq();(x) &= ~(1<< (bit));__enable_irq();}while(0)

 

 

上面这三个函数里,有一个共同的全局变量task_monitor,在代码里的定义为:

uint16_t task_monitor;

三个函数项目间的联系是通过这个全局变量task_monitor,从定义上看,这是一个16位的全局变量,也就意味着我们的框架最多可以调度16个任务,每一个任务占用一位。

16个任务对于一般的项目是够用了,如果不够用这个框架还可以扩展到32个任务,可以修改如下:

uint32_t  task_monitor;

 

下面是定义的ID号:

enum

{

    EV_TICK_LITTLE,

    EV_READ,

    EV_CONTROL_IR,

    EV_100MS,

    EV_SEC,

    EV_TICK,

    EV_MIN,

    EV_CALLBACK,

    EV_USB_TASK,

    EV_3MS,

    EV_6MS,

    EV_12MS,

    EV_CALIBRATE_GRY_ACC,

    EV_REPORT_DATA,

    EV_CALIBRATE_TRIGGER_AD

};

 

目前用到的是14个任务,从左往右,从上往下,是对应16位task_monitor;的从低位到高位,如下图对应:

EV_TICK_LITTLE

EV_READ

EV_CONTROL_IR

EV_100MS

EV_SEC

EV_TICK

EV_MIN

EV_CALLBACK

EV_USB_TASK

EV_3MS

EV_6MS

EV_12MS

EV_CALIBRATE_GRY_ACC

EV_REPORT_DATA

 

 

 

第一种情况下函数调度的调度原理如下:


task_monitor

is_task_set

USB等中断

reset_task

notify

调度对应的函数

定时器

 

 

 

 

 

 

 

 

 

 

 

第二种调度的原理以及定时任务的建立:

 

is_task_always_alive(tasks[i].flags

如果任务对应的flag 是ALWAYS_ALIVE,那么轮询到这个flag就会调用对应的函数。

const struct tasktasks[] =

{        uint8_t id;          uint8_t flags;        void*args;     void (*handle)(void *args)

    {EV_TICK_LITTLE,     ALWAYS_ALIVE,     NULL,    sys_tick_little},  

    {EV_READ,            ALWAYS_ALIVE,     NULL,    read_rf_status_cmd},

    {EV_CONTROL_IR,           0,             NULL,     period_control_ir},

    {EV_100MS,                  0,             NULL,     task_100ms},//

    {EV_SEC,                    0,             NULL,     task_sec},

    {EV_TICK,            ALWAYS_ALIVE,     NULL,    sys_tick},

    {EV_REPORT_DATA,          0,            NULL,     report_data_rf},        

    {EV_USB_TASK,              0,            NULL,    handle_usb_task},

    {EV_3MS,                    0,             NULL,    task_3ms},

    {EV_6MS,                    0,             NULL,    task_6ms},

    {EV_12MS,                   0,             NULL,    task_12ms},

    {EV_CALIBRATE_GRY_ACC,   0,             NULL,    calibrate_gry_acc},

              

}; 

从上面的任务看使用ALWAYS_ALIVE的任务有三个分别是sys_tick_little,read_rf_status_cmd,sys_tick 。

sys_tick_little和sys_tick是用来驱动定时任务的。

 

sys_tick函数驱动的任务:

 

 

 

 

 

 

 

sys_tick_little

notify(EV_12MS)

 

notify(EV_3MS)

notify(EV_6MS)

 

sys_tick

notify(EV_MIN)

 

notify(EV_100MS)

notify(EV_SEC)

 

定时调度任务是用time2来进行计时的。

 

 
TIME2

_sys_tick

last_tick

sys_tick

notify(EV_MIN)

 

notify(EV_SEC)

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值