用在PIC18、PIC33時發現一些問題,做了修改,同時加入windows平台下的模擬程式。
主程式:
#define TASK_NUM 4
extern void SimInit(void);
extern void Task1(void);
extern void Task2(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;
unsigned int Task_Delay_Count[TASK_NUM];
unsigned int Task_Skip_Count[TASK_NUM];
void (*TaskFunc[TASK_NUM])(void);
void (*TaskResumeFunc[TASK_NUM])(void);
// O.S functions
void InitSystem(void)
{
unsigned char i;
FuncID = 0;
for ( i= 0; i< TASK_NUM ; i++)
{
Task_Delay_Count[i] = Task_Skip_Count[i] = 0;
TaskFunc[i] = TaskResumeFunc[i] = Dummy;
}
TaskFunc[1] = Task1;
TaskFunc[2] = Task2;
}
void Dummy(void)
{
return;
}
void Task_Set_Next(void (*p_func)(void))
{
TaskFunc[FuncID]=p_func;
}
void Task_Set_Other_Task(unsigned char id, void (*p_func)(void))
{
DIS_INTR();
TaskFunc[id]=p_func;
ENA_INTR();
}
void Task_Delay_Ms_Next(unsigned int n, void (*p_func)(void))
{
if (! n ) n = 1;
TaskResumeFunc[FuncID]=p_func;
TaskFunc[FuncID] = Dummy; // to sleep
DIS_INTR();
Task_Delay_Count[FuncID] = n;
ENA_INTR();
}
static void Dummy_Skip(void)
{
if ( Task_Skip_Count[FuncID] )
{
Task_Skip_Count[FuncID]--;
if (! Task_Skip_Count[FuncID]) TaskFunc[FuncID]=TaskResumeFunc[FuncID];
}
}
void Task_Set_Skip_Next(unsigned int n, void (*p_func)(void))
{
if (! n ) n = 1;
TaskResumeFunc[FuncID]=p_func;
TaskFunc[FuncID] = Dummy_Skip; // to sleep
Task_Skip_Count[FuncID] = n;
}
// O.S functions end
// main loop
void main(void)
{
INIT_DEVICE();
InitSystem();
while (1)
{
register void (*Current_Func)(void);
DIS_INTR();
Current_Func = TaskFunc[FuncID]; // may break with interrupt
ENA_INTR();
// Trace System Code maybe add here
Current_Func();
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_Delay_Count[i] )
{
Task_Delay_Count[i]--;
if (! Task_Delay_Count[i]) TaskFunc[i]=TaskResumeFunc[i]; // wake up function
}
}
}
給其他C檔案用的引入檔mt.h
extern void Task_Set_Next(void (*p_func)(void));
extern void Task_Set_Other_Task(unsigned char id, void (*p_func)(void));
extern void Task_Delay_Ms_Next(unsigned int n, void (*p_func)(void));
extern void Task_Set_Skip_Next(unsigned int n, void (*p_func)(void));
Windows下模擬用程式
#include <windows.h>
#include <winbase.h>
extern void TimeTick(void);
HANDLE OSSemaphore;
DWORD WINAPI OSTickW32 ( LPVOID lpParameter );
HANDLE OSTick32Handle;
void SimInit(void)
{
DWORD dwID;
OSSemaphore = CreateSemaphore( NULL, 1, 1, NULL );
OSTick32Handle = CreateThread( NULL, 0, OSTickW32, 0, 0, &dwID );
SetPriorityClass(OSTick32Handle,THREAD_PRIORITY_HIGHEST);
SetThreadPriority(OSTick32Handle,THREAD_PRIORITY_HIGHEST);
}
DWORD WINAPI OSTickW32( LPVOID lpParameter )
{
while(1)
{
TimeTick();
Sleep(1);
}
return 0;
}
void OS_SLEEP(unsigned int count)
{
Sleep(count);
}
void OS_INIT_CRITICAL(void)
{
return;
}
void OS_ENTER_CRITICAL(void)
{
WaitForSingleObject( OSSemaphore, INFINITE );
}
void OS_EXIT_CRITICAL(void)
{
ReleaseSemaphore( OSSemaphore, 1, NULL );
}
測試用程式
#include <stdio.h>
#include "mt.h"
void Task1(void)
{
printf("G");
Task_Delay_Ms_Next(100,Task1);
}
void Task2(void)
{
printf("z");
Task_Delay_Ms_Next(33,Task2);
}
測試畫面
要記得請使用多核心下去跑,因為本來就不是給Windows用的,所以會用掉一個核心。