📄 os_cpu_a.asm
字号:
//************************************************************
// 单位: 华中科技大学光电子工程系
// 作者: 张利
// 文件: OS_CPU_A.asm for unsp
//*************************************************************
.include hardware.inc
.external _OSTCBCur
.external _OSTCBHighRdy
.external _OSRunning
.external _OSPrioCur
.external _OSPrioHighRdy
.external _OSTaskSwHook
.external _OSIntEnter
.external _OSIntExit
.external _OSTimeTick
.public _OSStartHighRdy
.public _OSIntCtxSw
.public _OSCtxSw
.public _OSTickISR
PUSHALL: .MACRO
PUSH R5 to [sp]
PUSH R4 to [sp]
PUSH R3 to [sp]
PUSH R2 to [sp]
PUSH R1 to [sp]
.ENDM
POPALL: .MACRO
POP R1 from [sp]
POP R2 from [sp]
POP R3 from [sp]
POP R4 from [sp]
POP R5 from [sp]
.ENDM
.isram
OSStack: .dw 50 dup(?)
.define OSStkStart OSStack+50
//**************************************************************
// 堆栈结构:
// 任务堆栈: 系统堆栈: OSStkStart -> | | |
// ---------- SP -> ----------
// |OSTCBCur| /---->| | |
// ---------- | ----------
// | |
// | |
// \---->|OSTCBCur->OSTCBStkPtr| |
// ----------------------- |
// | |
// | ---------- |
// | | | |<-----
// | ----------
// \---------->| 长度 | 低地址
// ----------
//****************************************************************
.code
_OSStartHighRdy:
CALL _OSTaskSwHook
OSCtxSw_in:
// OSTCBStrPtr -->R1
// OSTCBStrPtr 是TCB结构的第一项,所以就是OSTCBCur指想的内存单元
// R1为任务堆栈的头指针
R1=[_OSTCBCur]
// R2中为任务堆栈头地址存放的第一条内容,是堆栈的长度
R1=[R1]
R2=[R1]
// R3为系统堆栈的高位地址+1
R3=OSStkStart
restore_stack:
R1+=1
R3-=1
R4=[R1]
[R3]=R4
R2-=1
JNZ restore_stack
// 调整堆栈指针
R3-=1
SP=R3
// OSRunning =TRUE
R1=0x0001
[_OSRunning]=R1
POPALL
INT FIQ
INT IRQ
RETI
//***************************************************************
_OSCtxSw:
// 将所有寄存器压栈
PUSHALL
OSIntCtxSw_in:
// 求出系统堆栈的长度 ,并将其存入 R2
R1=SP
R2=OSStkStart
R1+=1
R2=R2-R1
// R1 <-- OSTCBStkPtr
// R1 为任务堆栈的头指针
R1=[_OSTCBCur]
// 首先将系统堆栈长度保存在任务堆栈中
R1=[R1]
[R1]=R2
// 得到堆栈的起始地址
R3=OSStkStart
// 保存系统堆栈到任务堆栈
save_stack:
R3-=1
R1+=1
R4=[R3]
[R1]=R4
R2-=1
JNZ save_stack
CALL _OSTaskSwHook
// OSTCBCur = OSTCBHighRdy
R1=[_OSTCBHighRdy]
[_OSTCBCur]=R1
// OSPrioCur = OSPrioHighRdy
R1=[_OSPrioHighRdy]
[_OSPrioCur]=R1
JMP OSCtxSw_in
//*********************************************************************
// 仅需调整SP指针,然后进行任务切换
//*********************************************************************
_OSIntCtxSw:
R1=SP
R1+=0x0007 //多压栈的偏移量,由于不懂凌阳编译器的编译原理,该量是
// 郁闷了 n 久才调出来的,呜呜~~~
SP=R1
JMP OSIntCtxSw_in
//********************************************************************
// 打开SPACE061A的时间基准信号中断
//********************************************************************
_OSTickISR:
R1=0x0001
[P_INT_Ctrl]=R1
RETF
//********************************************************************
// 该中断采用SPACE061A的时间基准信号产生调度信号
// 注意要 在程序开始前对该中断初始化
//********************************************************************
.text
.public _IRQ6
_IRQ6:
nop
PUSHALL
R1=0x0001
test R1,[P_INT_Ctrl]
JZ OUT
R1=0x0001
[P_INT_Clear]=R1
CALL _OSIntEnter
CALL _OSTimeTick
CALL _OSIntExit
OUT:
R1=0x0001
[P_INT_Clear]=R1
POPALL
RETI
//**********************************************************************
// 用户函数写在下面
//
//**********************************************************************
.public _SerialInit
_SerialInit:
R1=0x0480
[P_IOB_Attrib]=R1
R1=0x0400
[P_IOB_Dir]=R1
R1=0x0000
[P_UART_BaudScalarLow]=R1
R1=0x0005
[P_UART_BaudScalarHigh]=R1
R1=0x0000
[P_UART_Command1]=R1
R1=0x00c0
[P_UART_Command2]=R1
retf
.public _Output
_Output:
INT OFF
bp=sp
R1=[bp+3]
R2=[bp+4]
TxRDY:
R4=[P_UART_Command2]
r4&=0x0040
JZ TxRDY
R3=[R1]
[P_UART_Data]=R3
R1+=1
R2-=1
JNZ TxRDY
INT FIQ
INT IRQ
retf
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -