⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os.c

📁 一个真正微型操作系统,比uCOS更小,只支持16个任务,但速度更快,所占资源更少.
💻 C
字号:
/* ******************************************************* */
/*                           OS.h                          */
/* ******************************************************* */
typedef unsigned char  BOOLEAN;
typedef unsigned char  INT8U;
typedef signed   char  INT8S;
typedef unsigned short INT16U;
typedef signed   short INT16S;
typedef unsigned int   INT32U;
typedef signed   int   INT32S;
typedef struct   os_tcb
{   INT16U         *pOSTCBStkPtr;
    struct os_tcb  *pOSTCBNext;
    INT16U          usOSTCBDly;
    INT8U           ucOSTCBStat;
    INT8U           ucOSTCBPrio;
    INT16U          usOSTCBMask;
}   OS_TCB;

/* ***************** Basis definitions ***************** */
#define TRUE                  1
#define FALSE                 0
#define OS_ENTER_CRITICAL()   asm(" MOVE SR,-(A7)\n ORI #$0400,SR\n ANDI #$FCFF,SR\n")
#define OS_EXIT_CRITICAL()    asm(" MOVE (A7)+,SR\n")
#define OS_TASK_SW()          asm(" TRAP #15\n")
#define OS_INITIAL_SR         0x2000
#define OS_TRAP_NBR           15

#define OS_DOG_PRIO           0
#define OS_STAT_PRIO          14
#define OS_IDLE_PRIO          15
#define OS_TASK_DOG_STK_SIZE  512
#define OS_TASK_IDLE_STK_SIZE 512
#define OS_TASK_STAT_STK_SIZE 512

#define OS_PRIO_SELF          0xFF
#define OS_STAT_RDY           0x00
#define OS_STAT_SEM           0x01
#define OS_STAT_MBOX          0x02
#define OS_STAT_Q             0x04
#define OS_STAT_SUSPEND       0x08

#define OS_TICKS_FRESH_DOG    4
#define OS_TICKS_PER_SEC      100
#define OS_REFRESH_DOG()      SWSR=0x55;SWSR=0xAA

/* ******************** Error codes ******************** */
#define OS_NO_ERR               0
#define OS_ERR_EVENT_TYPE       1
#define OS_ERR_PEND_ISR         2
#define OS_TIMEOUT              10
#define OS_TASK_NOT_EXIST       11
#define OS_MBOX_FULL            20
#define OS_Q_FULL               30
#define OS_PRIO_EXIST           40
#define OS_PRIO_ERR             41
#define OS_PRIO_INVALID         42
#define OS_SEM_OVF              50
#define OS_TASK_DEL_ERR         60
#define OS_TASK_DEL_IDLE        61
#define OS_TASK_DEL_REQ         62
#define OS_TASK_DEL_ISR         63
#define OS_NO_MORE_TCB          70
#define OS_TIME_NOT_DLY         80
#define OS_TIME_INVALID_MINUTES 81
#define OS_TIME_INVALID_SECONDS 82
#define OS_TIME_INVALID_MILLI   83
#define OS_TIME_ZERO_DLY        84
#define OS_TASK_SUSPEND_PRIO    90
#define OS_TASK_SUSPEND_IDLE    91
#define OS_TASK_RESUME_PRIO     100
#define OS_TASK_NOT_SUSPENDED   101
#define OS_MEM_INVALID_PART     110
#define OS_MEM_INVALID_BLKS     111
#define OS_MEM_INVALID_SIZE     112
#define OS_MEM_NO_FREE_BLKS     113
#define OS_MEM_FULL             114
#define OS_TASK_OPT_ERR         130

/* ******************* const Section ******************* */
INT16U const usOSMaskTbl[16] = {
    0x0001, 0x0002, 0x0004, 0x0008,
    0x0010, 0x0020, 0x0040, 0x0080,
    0x0100, 0x0200, 0x0400, 0x0800,
    0x1000, 0x2000, 0x4000, 0x8000 };

INT8U const ucOSUnMapTbl[256] = {
    0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };

/* ***************** zerovars Section ****************** */
BOOLEAN bOSRunning;
INT8U   ucOSIntNesting,
        ucOSPrioCur,
        ucOSPrioHighRdy;
INT16U  usOSRdyIndex,
        usOSCPUUsage,
        usOSDogStackUsage,
        usOSIdleStackUsage,
        usOSStatStackUsage;
INT32U  uiOSIdleCtrMax,
        uiOSIdleCtrRun,
        uiOSIdleCtr,
        uiOSTime;
OS_TCB *pOSTCBHighRdy,
       *pOSTCBCur,
       *pOSTCBFree,
       *pOSTCBPrioTbl[16],
        sOSTCBTbl[16];

/* ******************* vars Section ******************** */
INT16U  OSTaskDogStk[OS_TASK_DOG_STK_SIZE]   = {0};
INT16U  OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE] = {0};
INT16U  OSTaskStatStk[OS_TASK_STAT_STK_SIZE] = {0};

/* *************** Functions Prototypes **************** */
void    OSInit(void);
void    OSSched(void);
void    OSStart(void);
void    OSStatInit(void);
void    OSTaskIdle(void);
void    OSTaskWatchDog(void);
void    OSTaskStat(void);
void    OSTimeTick(void);
INT8U   OSTaskCreate(void (*task), INT16U *pbot, INT16U *ptop, INT8U prio);
INT8U   OSTaskSuspend(INT8U prio);
INT8U   OSTaskResume(INT8U prio);
INT8U   OSIntTaskResume(INT8U prio);
void    OSTimeDly(INT16U ticks);
INT8U   OSTimeDlyResume(INT8U prio);
INT8U   OSIntTimeDlyResume(INT8U prio);
INT16U  OSCheckStack(INT16U *pbot, INT16U size);
INT32U  OSTimeGet(void);
void    OSTimeSet(INT32U ticks);
extern  void OSStartHighRdy(void);

/* ******************************************************* */
/*                           OS.c                          */
/* ******************************************************* */

void OSInit (void)
{   INT16U i;

    bOSRunning         = FALSE;
    ucOSIntNesting     = 0;
    ucOSPrioCur        = 0;
    ucOSPrioHighRdy    = 0;
    usOSRdyIndex       = 0;
    usOSCPUUsage       = 0;
    usOSDogStackUsage  = 0;
    usOSIdleStackUsage = 0;
    usOSStatStackUsage = 0;
    uiOSIdleCtrMax     = 0;
    uiOSIdleCtrRun     = 0;
    uiOSIdleCtr        = 0;
    uiOSTime           = 0;
    pOSTCBHighRdy      = (OS_TCB *)0;
    pOSTCBCur          = (OS_TCB *)0;
    pOSTCBFree         = &sOSTCBTbl[0];
    for (i=0; i<16; i++)
    {   pOSTCBPrioTbl[i]          = (OS_TCB *)0;
    }
    for (i=0; i<16; i++)
    {   sOSTCBTbl[i].pOSTCBStkPtr = (INT16U *)0;
        sOSTCBTbl[i].usOSTCBDly   = 0;
        sOSTCBTbl[i].ucOSTCBStat  = OS_STAT_SUSPEND;
        sOSTCBTbl[i].ucOSTCBPrio  = 0xFF;
        sOSTCBTbl[i].usOSTCBMask  = 0;
    }
    for (i=0; i<15; i++)
    {   sOSTCBTbl[i].pOSTCBNext   = &sOSTCBTbl[i+1];
    }
    sOSTCBTbl[15].pOSTCBNext      = (OS_TCB *)0;
    OSTaskCreate(OSTaskIdle,
                 &OSTaskIdleStk[0],
                 &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE-1],
                 OS_IDLE_PRIO);
    OSTaskCreate(OSTaskStat, 
                 &OSTaskStatStk[0],
                 &OSTaskStatStk[OS_TASK_STAT_STK_SIZE-1],
                 OS_STAT_PRIO);
    OSTaskCreate(OSTaskWatchDog,
                 &OSTaskDogStk[0],
                 &OSTaskDogStk[OS_TASK_DOG_STK_SIZE-1],
                 OS_DOG_PRIO);
}

void OSSched (void)
{
    OS_ENTER_CRITICAL();
    if (ucOSIntNesting == 0)
    {   if (usOSRdyIndex & 0x00FF)
             ucOSPrioHighRdy = ucOSUnMapTbl[usOSRdyIndex & 0x00FF];
        else ucOSPrioHighRdy = ucOSUnMapTbl[usOSRdyIndex >> 8] + 8;
        if (ucOSPrioHighRdy != ucOSPrioCur)
        {   pOSTCBHighRdy = pOSTCBPrioTbl[ucOSPrioHighRdy];
            OS_TASK_SW();
        }
    }
    OS_EXIT_CRITICAL();
}

void OSStart (void)
{   
    if (bOSRunning == FALSE)
    {   if (usOSRdyIndex & 0x00FF)
             ucOSPrioHighRdy = ucOSUnMapTbl[usOSRdyIndex & 0x00FF];
        else ucOSPrioHighRdy = ucOSUnMapTbl[usOSRdyIndex >> 8] + 8;
        ucOSPrioCur   = ucOSPrioHighRdy;
        pOSTCBHighRdy = pOSTCBPrioTbl[ucOSPrioHighRdy];
        pOSTCBCur     = pOSTCBHighRdy;
        OSStartHighRdy();
    }
}

void OSStatInit (void)
{   OSTimeDly (2);
    uiOSIdleCtr = 0;
    OSTimeDly (OS_TICKS_PER_SEC);
    uiOSIdleCtrMax = uiOSIdleCtr;
}

void OSTaskIdle (void)
{
    for (;;)
    {   uiOSIdleCtr++;
    }
}

void OSTimeTick (void)
{   OS_TCB *ptcb;

    ptcb = &sOSTCBTbl[0];
    while (ptcb->ucOSTCBPrio != 0xFF)
    {   if (ptcb->usOSTCBDly != 0)
        {   if (--ptcb->usOSTCBDly == 0)
            {   if (ptcb->ucOSTCBStat & OS_STAT_SUSPEND)
                     ptcb->usOSTCBDly = 1;
                else usOSRdyIndex |= ptcb->usOSTCBMask;
            }
        }
        if ((ptcb = ptcb->pOSTCBNext) == (OS_TCB *)0)
            break;
    }
    uiOSTime ++;
}

INT8U OSTaskCreate (void (*task), INT16U *pbot, INT16U *ptop, INT8U prio)
{   INT32U  *pstk32;
    INT16U  *pstk16;
    OS_TCB  *ptcb;

    if (prio >= 16) return (OS_PRIO_INVALID);
    if (pOSTCBPrioTbl[prio] == (OS_TCB *)0)
    {   pstk32    = (INT32U *)((INT32U)ptop & (INT32U)0xFFFFFFFC);
        *--pstk32 = (INT32U)task;
        pstk16    = (INT16U *)pstk32;
        *--pstk16 = (INT16U)(0x0080 + 4 * OS_TRAP_NBR);
        pstk32    = (INT32U *)pstk16;
        *--pstk32 = (INT32U)task;
        pstk16    = (INT16U *)pstk32;
        *--pstk16 = (INT16U)OS_INITIAL_SR;
        pstk32    = (INT32U *)pstk16;
        *--pstk32 = (INT32U)0x00A600A6;
        *--pstk32 = (INT32U)0x00A500A5;
        *--pstk32 = (INT32U)0x00A400A4;
        *--pstk32 = (INT32U)0x00A300A3;
        *--pstk32 = (INT32U)0x00A200A2;
        *--pstk32 = (INT32U)0x00A100A1;
        *--pstk32 = (INT32U)0x00A000A0;
        *--pstk32 = (INT32U)0x00D700D7;
        *--pstk32 = (INT32U)0x00D600D6;
        *--pstk32 = (INT32U)0x00D500D5;
        *--pstk32 = (INT32U)0x00D400D4;
        *--pstk32 = (INT32U)0x00D300D3;
        *--pstk32 = (INT32U)0x00D200D2;
        *--pstk32 = (INT32U)0x00D100D1;
        *--pstk32 = (INT32U)0x00D000D0;
        for (pstk16 = (INT16U *)pstk32-1; pstk16 >= pbot; pstk16--)
        {   *pstk16 = 0;
        }
        if ((ptcb = pOSTCBFree) != (OS_TCB *)0)
        {   pOSTCBFree          = ptcb->pOSTCBNext;
            ptcb->pOSTCBStkPtr  = (INT16U *)pstk32;
            ptcb->usOSTCBDly    = 0;
            ptcb->ucOSTCBStat   = OS_STAT_RDY;
            ptcb->ucOSTCBPrio   = prio;
            ptcb->usOSTCBMask   = usOSMaskTbl[prio];
            pOSTCBPrioTbl[prio] = ptcb;
            usOSRdyIndex       |= usOSMaskTbl[prio];
            if (bOSRunning) OSSched();
            return (OS_NO_ERR);
        }
        else
        {   return (OS_NO_MORE_TCB);
        }
    }
    return (OS_PRIO_EXIST);
}

INT8U OSTaskSuspend (INT8U prio)
{   BOOLEAN  self;
    OS_TCB  *ptcb;

    if (prio >= 15 && prio != OS_PRIO_SELF)
    {   return (OS_PRIO_INVALID);
    }
    OS_ENTER_CRITICAL();
    if (prio == OS_PRIO_SELF)
    {   prio = pOSTCBCur->ucOSTCBPrio;
        self = TRUE;
    }
    else if (prio == pOSTCBCur->ucOSTCBPrio)
    {   self = TRUE;
    }
    else
    {   self = FALSE;
    }
    if ((ptcb = pOSTCBPrioTbl[prio]) == (OS_TCB *)0)
    {   OS_EXIT_CRITICAL();
        return (OS_TASK_SUSPEND_PRIO);
    }
    else
    {   usOSRdyIndex      &= ~ptcb->usOSTCBMask;
        ptcb->ucOSTCBStat |= OS_STAT_SUSPEND;
        OS_EXIT_CRITICAL();
        if (self == TRUE) OSSched();
        return (OS_NO_ERR);
    }
}

INT8U OSTaskResume (INT8U prio)
{   OS_TCB *ptcb;

    if (prio >= 15) return (OS_PRIO_INVALID);
    OS_ENTER_CRITICAL();
    if ((ptcb = pOSTCBPrioTbl[prio]) == (OS_TCB *)0)
    {   OS_EXIT_CRITICAL();
        return (OS_TASK_RESUME_PRIO);
    }
    else if (ptcb->ucOSTCBStat & OS_STAT_SUSPEND)
    {   if (((ptcb->ucOSTCBStat &= ~OS_STAT_SUSPEND)==OS_STAT_RDY) &&
             (ptcb->usOSTCBDly  == 0))
        {   usOSRdyIndex |= ptcb->usOSTCBMask;
            OS_EXIT_CRITICAL();
            OSSched();
        }
        else
        {   OS_EXIT_CRITICAL();
        }
        return (OS_NO_ERR);
    }
    else
    {   OS_EXIT_CRITICAL();
        return (OS_TASK_NOT_SUSPENDED);
    }
}

INT8U OSIntTaskResume (INT8U prio)
{   OS_TCB *ptcb;

    if (prio >= 15) return (OS_PRIO_INVALID);
    OS_ENTER_CRITICAL();
    if ((ptcb = pOSTCBPrioTbl[prio]) == (OS_TCB *)0)
    {   OS_EXIT_CRITICAL();
        return (OS_TASK_RESUME_PRIO);
    }
    else if (ptcb->ucOSTCBStat & OS_STAT_SUSPEND)
    {   if (((ptcb->ucOSTCBStat &= ~OS_STAT_SUSPEND)==OS_STAT_RDY) &&
             (ptcb->usOSTCBDly  == 0))
        {   usOSRdyIndex |= ptcb->usOSTCBMask;
        }
        OS_EXIT_CRITICAL();
        return (OS_NO_ERR);
    }
    else
    {   OS_EXIT_CRITICAL();
        return (OS_TASK_NOT_SUSPENDED);
    }
}

void OSTimeDly (INT16U ticks)
{   if (ticks > 0)
    {   OS_ENTER_CRITICAL();
        usOSRdyIndex &= ~pOSTCBCur->usOSTCBMask;
        pOSTCBCur->usOSTCBDly = ticks;
        OS_EXIT_CRITICAL();
        OSSched();
    }
}

INT8U OSTimeDlyResume (INT8U prio)
{   OS_TCB *ptcb;

    if (prio >= 15) return (OS_PRIO_INVALID);
    OS_ENTER_CRITICAL();
    if ((ptcb = pOSTCBPrioTbl[prio]) == (OS_TCB *)0)
    {   OS_EXIT_CRITICAL();
        return (OS_TASK_NOT_EXIST);
    }
    else if (ptcb->usOSTCBDly != 0)
    {   ptcb->usOSTCBDly = 0;
        if (ptcb->ucOSTCBStat & OS_STAT_SUSPEND)
        {   OS_EXIT_CRITICAL();
        }
        else
        {   usOSRdyIndex |= ptcb->usOSTCBMask;
            OS_EXIT_CRITICAL();
            OSSched();
        }
        return (OS_NO_ERR);
    }
    else
    {   OS_EXIT_CRITICAL();
        return (OS_TIME_NOT_DLY);
    }
}

INT8U OSIntTimeDlyResume (INT8U prio)
{   OS_TCB *ptcb;

    if (prio >= 15) return (OS_PRIO_INVALID);
    OS_ENTER_CRITICAL();
    if ((ptcb = pOSTCBPrioTbl[prio]) == (OS_TCB *)0)
    {   OS_EXIT_CRITICAL();
        return (OS_TASK_NOT_EXIST);
    }
    else if (ptcb->usOSTCBDly != 0)
    {   ptcb->usOSTCBDly  = 0;
        if (!(ptcb->ucOSTCBStat & OS_STAT_SUSPEND))
        {   usOSRdyIndex |= ptcb->usOSTCBMask;
        }
        OS_EXIT_CRITICAL();
        return (OS_NO_ERR);
    }
    else
    {   OS_EXIT_CRITICAL();
        return (OS_TIME_NOT_DLY);
    }
}

INT16U OSCheckStack (INT16U *pbot, INT16U size)
{   register INT16U  free, *pchk;

    pchk = pbot;
    for (free = size; free > 0; free--)
    {   if (*pchk++ != 0)
            break;
    }
    if (size == 0)
         return 0;
    else return (free * 100 / size);
}

INT32U OSTimeGet (void)
{   return uiOSTime;
}

void OSTimeSet (INT32U ticks)
{   uiOSTime = ticks;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -