在STM32上運行時發現,可以不使用DIS_INTR()這個巨集。
因為這個在原子操作下已無需要。
後來就將Task管理,從function pointer改為原子操作下的資料。
結果發現,還可以進一步省下記憶體。
另外Skip方式也改了,改到主程式去做。現在不會跳去Dummy(),檢查完畢就移到下一個工作去。
新增功能有
WakeUp(i),可以從中斷程式中呼叫,所以可以設定只由中斷叫醒的Task,免去使用全域變數做溝通。
Sleep_Next(p_func),Task沉睡,設定醒來時執行函式,只能由WakeUp(i)叫醒。
新版本程式如下:
#include "mt.h"
#define TASK_NUM 4
extern void SimInit(void);
extern void Task1(void);
extern void Task2(void);
extern void Task3(void);
extern void OS_ENTER_CRITICAL(void);
extern void OS_EXIT_CRITICAL(void);
#define INIT_DEVICE() SimInit()
#define DIS_INTR() OS_ENTER_CRITICAL()
#define ENA_INTR() OS_EXIT_CRITICAL()
// O.S function declaim
void Dummy(void);
unsigned char FuncID;
volatile unsigned char Task_State[TASK_NUM];
unsigned short Task_Delay_Count[TASK_NUM];
void (*TaskFunc[TASK_NUM])(void);
// O.S functions
void InitSystem(void)
{
unsigned char i;
FuncID = 0;
for ( i= 0; i< TASK_NUM ; i++)
{
Task_State[i] = TASK_RUNNING;
Task_Delay_Count[i] = 0;
TaskFunc[i] = Dummy;
}
TaskFunc[1] = Task1;
TaskFunc[2] = Task2;
TaskFunc[3] = Task3;
}
void Sleep_Next(void (*p_func)(void))
{
TaskFunc[FuncID] = p_func;
Task_State[FuncID] = TASK_WAIT;
}
void WakeUp(unsigned char n)
{
Task_State[n] = TASK_RUNNING;
}
void Task_Set_Next(void (*p_func)(void))
{
TaskFunc[FuncID]=p_func;
}
void Dummy(void)
{
Sleep_Next(Dummy);
}
void Task_Delay_Ms_Next(unsigned int n, void (*p_func)(void))
{
if (! n ) n = 1;
TaskFunc[FuncID] = p_func;
Task_Delay_Count[FuncID] = n;
Task_State[FuncID] = TASK_DELAY;
}
void Task_Set_Skip_Next(unsigned int n, void (*p_func)(void))
{
if (! n ) n = 1;
TaskFunc[FuncID] = p_func;
Task_Delay_Count[FuncID] = n;
Task_State[FuncID] = TASK_SKIP;
}
// O.S functions end
// main loop
void main(void)
{
INIT_DEVICE();
InitSystem();
while (1)
{
switch (Task_State[FuncID])
{
case TASK_RUNNING :
TaskFunc[FuncID]();
break;
case TASK_SKIP :
if ( Task_Delay_Count[FuncID] )
{
Task_Delay_Count[FuncID]--;
if (! Task_Delay_Count[FuncID]) WakeUp(FuncID);
}
break;
default:
break;
}
if ( ++FuncID >= TASK_NUM ) FuncID = 0;
}
}
void TimeTick(void) // This is timer interrupt
{
unsigned char i;
for ( i=0; i< TASK_NUM; i++)
{
if ( Task_State[i] == TASK_DELAY )
{
if ( Task_Delay_Count[i] )
{
Task_Delay_Count[i]--;
if (! Task_Delay_Count[i]) WakeUp(i);
}
}
}
}
// Begin User Tasks
mt.h內容為
void Sleep_Next(void (*p_func)(void));
void WakeUp(unsigned char n);
void Task_Set_Next(void (*p_func)(void));
void Task_Delay_Ms_Next(unsigned int n, void (*p_func)(void));
void Task_Set_Skip_Next(unsigned int n, void (*p_func)(void));
// Task State
#define TASK_RUNNING 0
#define TASK_SKIP 1
#define TASK_DELAY 2
#define TASK_WAIT 3
實驗程式如下:
#include < stdio.h >
#include "mt.h"
void Task1(void)
{
printf("G");
Task_Delay_Ms_Next(10,Task1);
}
void Task2(void)
{
printf("z");
Task_Delay_Ms_Next(1,Task2);
}
void Task3(void)
{
printf(".");
Task_Set_Skip_Next(60000,Task3);
}
Windows模擬結果