目录
函数在文件Ano_Scheduler.c中,Scheduler_Setup()初始化后,在while循环中执行Scheduler_Run()
一、线程初始化
先看下Scheduler_Setup()函数,
void Scheduler_Setup(void)
{
uint8_t index = 0;
//初始化任务表
for(index=0;index < TASK_NUM;index++)
{
//计算每个任务的延时周期数
sched_tasks[index].interval_ticks = TICK_PER_SECOND/sched_tasks[index].rate_hz;
//最短周期为1,也就是1ms
if(sched_tasks[index].interval_ticks < 1)
{
sched_tasks[index].interval_ticks = 1;
}
}
}
for循环里执行的次数TASK_NUM,是个宏定义
#define TASK_NUM (sizeof(sched_tasks)/sizeof(sched_task_t))
sched_tasks是线程的结构体数组
static sched_task_t sched_tasks[] =
{
{Loop_1000Hz,1000, 0, 0},
{Loop_500Hz , 500, 0, 0},
{Loop_200Hz , 200, 0, 0},
{Loop_100Hz , 100, 0, 0},
{Loop_50Hz , 50, 0, 0},
{Loop_20Hz , 20, 0, 0},
{Loop_2Hz , 2, 0, 0},
};
typedef struct
{
void(*task_func)(void);
uint16_t rate_hz;
uint16_t interval_ticks;
uint32_t last_run;
}sched_task_t;
sched_task_t是结构体声明,用结构体数组的长度除以一个结构体的长度就得到数组的线程数量TASK_NUM
for循环里
sched_tasks[index].interval_ticks = TICK_PER_SECOND/sched_tasks[index].rate_hz;
计算的interval_ticks是线程结构体中的时间间隔及运行周期,
查找定义 TICK_PER_SECOND 是每秒滴答次数
#define TICK_PER_SECOND 1000
rate_hz是结构体矩阵的第二列,表示运行的频率,这样线程运行周期就等于总次数除以运行的频率。
if判断指定最小周期等于1ms
二、任务调度器
Scheduler_Run()是在while循环中一直执行着
//这个函数放到main函数的while(1)中,不停判断是否有线程应该执行
void Scheduler_Run(void)
{
uint8_t index = 0;
//循环判断所有线程,是否应该执行
for(index=0;index < TASK_NUM;index++)
{
//获取系统当前时间,单位MS
uint32_t tnow = SysTick_GetTick();
//进行判断,如果当前时间减去上一次执行的时间,大于等于该线程的执行周期,则执行线程
if(tnow - sched_tasks[index].last_run >= sched_tasks[index].interval_ticks)
{
//更新线程的执行时间,用于下一次判断
sched_tasks[index].last_run = tnow;
//执行线程函数,使用的是函数指针
sched_tasks[index].task_func();
}
}
}
TASK_NUM上面说过,for循环还是逐个线程去判断
如果当前时间减去上一次执行的时间,大于等于该线程的执行周期
线程上次运行就等于当前时间,然后执行线程函数,task_func()是结构体矩阵的第一列,是对应的要执行的线程函数。