匿名飛控線程初始化和調度是怎麼實現的

目錄

一、線程初始化

先看下Scheduler_Setup()函數,

二、任務調度器


函數在文件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()是結構體矩陣的第一列,是對應的要執行的線程函數。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章