📄 os.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 + -