📄 os_cpu.c
字号:
/********************************************************************
// uCOS-II 8051 Port
//
// written by
//
// Wai Chan
// Apr. 10 2001
*********************************************************************/
#define OS_CPU_GLOBALS
#include "includes.h"
void *OSTaskStkInit(void *task, void *pdata, void *ptos, INT16U opt);
void OSStartHighRdy();
void OSCtxSw();
void OSIntCtxSw();
void OSSetTickPerSec( INT16U ticks );
void OSSetTimer();
void OSInterruptInit();
#if OS_CPU_HOOKS_EN
void OSTaskCreateHook (OS_TCB *ptcb);
void OSTaskDelHook (OS_TCB *ptcb);
void OSTaskSwHook (void);
void OSTaskStatHook (void);
void OSTimeTickHook (void);
void OSTaskCreateHook (OS_TCB *ptcb)
{
ptcb = ptcb;
}
void OSTaskDelHook (OS_TCB *ptcb)
{
ptcb = ptcb;
}
void OSTaskSwHook (void)
{
}
void OSTaskStatHook (void)
{
}
void OSTimeTickHook (void)
{
}
#endif
/* The max ticks per second should be TIMER_TICKS_PER_SECOND */
void OSSetTickPerSec( INT16U ticks )
{
if ( ticks > TIMER_TICKS_PER_SECOND )
ticks = TIMER_TICKS_PER_SECOND;
OSTickFrequency = TIMER_TICKS_PER_SECOND / ticks;
}
void OSSetTimer()
{
/* Use Timer 0 Mode 0 */
TCON |= 0x10;
TMOD |= 0x00;
OSTickCtr = 0;
}
void OSInterruptInit()
{
/* for using monitor program, we only enables Time 0 Interrupt */
IE = 0x82;
}
INTERRUPT(_TF0_) _OSTickISR()
{
/* Check the tick frequency */
OSTickCtr++;
if ( OSTickCtr < OSTickFrequency )
{
return;
}
OSTickCtr = 0;
asm {
/* Increment OSIntNesting */
MOV DPTR,#OSIntNesting
MOVX A,[DPTR]
INC A
MOVX [DPTR],A
/* Process system tick */
LCALL OSTimeTick
/* Exit from interrupt */
LCALL OSIntExit
}
}
/*****************************************************************************
We are saving 0x7F-?stk bytes of internal ram onto the external stack. These bytes
include the internal stack. Here is what it looks like in the internal
stack after the timer interrupt.
+--------------------+
| ARG_LOW |
+--------------------+
| ARG_High |
+--------------------+
| Reture Address Low |
+--------------------+
| Reture Address High|
+--------------------+
| Reture Address Low |
+--------------------+
| Reture Address High|
+--------------------+
| PSW |
+--------------------+
| A |
+--------------------+
| B |
+--------------------+
| DPH |
+--------------------+
| DPL |
+--------------------+
| R0 |
+--------------------+
| R1 |
+--------------------+
| . |
+--------------------+
| . |
+--------------------+
| R7 |
+--------------------+
| . |
+--------------------+
| |
We are faking the return address bytes to be the task starting address
*****************************************************************************/
void *OSTaskStkInit(void *task, void *pdata, void *ptos, INT16U opt)
{
INT8U *stk, i;
INT16U *address;
INT8U total_bytes;
opt = opt;
asm {
MOV DPL,#ISTK_START
MOV DPH,#=ISTK_START
MOV A,#?stk
MOVX [DPTR],A
}
total_bytes = 0x7F-ISTK_START;
stk = (INT8U*)ptos;
/* mark all internal ram to be zero on the external stack */
for ( i = 0; i < total_bytes; i++ )
{
*stk-- = 0;
}
/* put argument address on the external stack */
stk = (INT8U*)ptos;
address = (INT16U*)(stk-total_bytes);
*address = (INT16U)pdata;
/* put return address on the external stack to simulate function call
so tasks can access the arguments on the stack */
stk = (INT8U*)ptos;
address = (INT16U*)(stk-total_bytes+2);
*address = (INT16U)task;
/* put return address on the external stack */
stk = (INT8U*)ptos;
address = (INT16U*)(stk-total_bytes+4);
*address = (INT16U)task;
/* put the internal stack pointer on the external stack */
stk = (INT8U*)ptos;
*stk = ISTK_START+19; /* stack starts at ?stk-1, we've faked 14 register
plus 2 bytes return address and 2 bytes argument.
so totally we have 18 bytes that has been
pushed on the stack */
/* Fake the initial internal stack pointer postion.
We have 12 general registers plus two bytes of
return address to be pushed on the stack.
Therefore the stack pointer should be pointing
to the starting position(?stk-1) plus 14 */
/* return the current stack pointer */
stk = (INT8U*)ptos;
return (void*)(stk-total_bytes);
}
void OSStartHighRdy()
{
asm {
/* Indicate the multitasking has started */
MOV DPTR,#OSRunning
MOVX A,[DPTR]
INC A
MOVX [DPTR],A
/* Call user function */
LCALL OSTaskSwHook
/* get stack pointer */
MOV DPL,#OSTCBHighRdy
MOV DPH,#=OSTCBHighRdy
MOVX A,[DPTR]
MOV R0,A,
INC DPTR
MOVX A,[DPTR]
MOV R1,A
MOV DPL,R0
MOV DPH,R1
MOVX A,[DPTR]
MOV ?stack,A
INC DPTR,
MOVX A,[DPTR]
MOV ?stack+1,A
/* pop all internal stack values from external stack back to internal ram */
MOV B,#0 We have 0x7F-?stk bytes to move starting from low to high
_HCpyIRAM MOV A,B
ADD A,#1
MOV B,A
ADD A,#?stk
MOV R0,A
MOV A,?stack
MOV DPL,A
MOV A,?stack+1
MOV DPH,A
MOVX A,[DPTR]
MOV [R0],A
MOV A,?stack
ADD A,#1
MOV ?stack,A
MOV A,?stack+1
ADDC A,#0
MOV ?stack+1,A
MOV A,B
CJNE A,#$7F-?stk,_HCpyIRAM
AJMP _HCpyDone
_HCpyDone
/* pop internal stack pointer */
MOV A,?stack
MOV DPL,A
MOV A,?stack+1
MOV DPH,A
MOVX A,[DPTR]
MOV SP,A
MOV A,?stack
ADD A,#1
MOV ?stack,A
MOV A,?stack+1
ADDC A,#0
MOV ?stack+1,A
/* now pop all registers from the fake internal stack */
POP 7
POP 6
POP 5
POP 4
POP 3
POP 2
POP 1
POP 0
POP DPL
POP DPH
POP B
POP A
POP PSW
}
}
void OSCtxSw()
{
asm {
PUSH PSW
PUSH A
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -