2011年9月4日 星期日

簡單多工2版

用在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用的,所以會用掉一個核心。

1 則留言:

  1. PIC18/PIC33直接用MPLAB來模擬不是最準確 最方便嗎?? 為何要改成windows平台下的模擬程式??
    [版主回覆11/08/2012 13:26:19]在Windows下可以試用才能推廣,這是行銷手法。
    而且在Windows下的debugger都很先進,我都是在Windows下做除錯的,測試才移往MCU。
    這個架構到了第三版時,完全不用理會中斷程式對於系統的干涉。
    因為是全C語言,所以處理器從8位元到32位元皆可以用。
    唯一要處理的只有時基中斷。
    這個系統已經是幾個產品在用的,也沒有什麼問題。

    回覆刪除