📄 ucosmcfa.s
字号:
/********************************************************************/
/** Unit : uCOSMCFa **/
/** **/
/** Description : This unit contains the assembler functions for **/
/** the ColdFire port of uC/OS. These perform context switching **/
/** and handle the timer ticks. **/
/** **/
/** Version History : **/
/** **/
/** A0.01 Initial version started 15/09/97 **/
/** **/
/** Copyright (c) 1997 David Fiddes, D.J.Fiddes@hw.ac.uk **/
/********************************************************************/
/********************************************************************/
/** A note for the interested: **/
/** **/
/** I've use the movem.l (%a7),%d0-%d7/%a0-%a6, lea 60(%a7)%a7 **/
/** construct in place of the traditional 68xxx **/
/** movem.l (%a7)+,%d0-%d7/%a0-%a6. It is perfectly in order to **/
/** push/pop individual registers using movem.l (%a7)+,%d2 , etc. **/
/** but it's a bit slower (and more verbose) **/
/** **/
/** The lea instruction is required because the ColdFire can't **/
/** push multiple registers directly to the stack... **/
/********************************************************************/
.text
.global OSStartHighRdy
.global OSCtxSw
.global OSIntCtxSw
.global OSTickISR
.extern OSIntEnter
.extern OSIntExit
.extern OSTimeTick
.extern OSTCBCur
.extern OSTCBHighRdy
/********************************************************************/
/** Procedure : OSStartHighRdy **/
/** **/
/** The procedure gets the highest priority task then loads its **/
/** stack before restoring all of the registers and doing an RTE **/
/** to actually start the task. Called directly from uC/OS **/
/********************************************************************/
OSStartHighRdy:
move.l (OSTCBHighRdy),%a1 |Get highest prio. task
move.l %a1,(OSTCBCur)
move.l (%a1),%a7 |Get ptr to top of stack
movem.l (%a7),%d0-%d7/%a0-%a6 |Store all the regs
lea 60(%a7),%a7 |Advance the stack pointer
rte |Return to task
/********************************************************************/
/** Procedure : OSCtxSw **/
/** **/
/** The procedure is installed as an interrupt handler and called **/
/** using a TRAP instruction within the uC/OS scheduler to swap **/
/** contexts at the task level. **/
/********************************************************************/
OSCtxSw:
lea -60(%a7),%a7
movem.l %d0-%d7/%a0-%a6,(%a7)
move.l (OSTCBCur),%a1 |Save stack ptr in TCB
move.l %a7,(%a1)
move.l (OSTCBHighRdy),%a1 |Point to HI Prio. Task Rdy
move.l %a1,(OSTCBCur) |This is now current TCB
move.l (%a1),%A7 |Get new task's stack ptr
movem.l (%a7),%d0-%d7/%a0-%a6
lea 60(%a7),%a7
rte |Return to new task
/********************************************************************/
/** Procedure : OSIntCtxSw **/
/** **/
/** The procedure is called by when the uC/OS wants to return to **/
/** a different task at interrupt time. Used primarily within the **/
/** timer tick interrupt. **/
/********************************************************************/
OSIntCtxSw:
adda.l #16,%a7 |For C -O2 -> -O4 optimisation level
| adda.l #20,%a7 |For unoptimsed C (Something to do with frame pointers being optimised out in OSIntExit)
/*
* Note: the stack adjustment compensates for the following:
*
* OSIntExit call 4
* OSIntExit stack frame adjust 4 <- goes to 0 for -O2
* OSIntExit locals 3 * 4 = 8
* OSIntCtxSw call 4
* ---
* 20 or 16
*
* The interrupt context save and the full register set must
* be on the stack in the correct order prior to the OSIntExit call
*/
move.l (OSTCBCur),%a1 |Save stack ptr in TCB
move.l %a7,(%a1)
move.l (OSTCBHighRdy),%a1 |Point to HI Prio. Task Rdy
move.l %a1,(OSTCBCur) |This is now current TCB
move.l (%a1),%a7 |Get new task's stack ptr
movem.l (%a7),%d0-%d7/%a0-%a6
lea 60(%a7),%a7
rte |Return to new task
/********************************************************************/
/** Procedure : OSTickISR **/
/** **/
/** The procedure is installed as the timer tick ISR and called **/
/** each time TIMER1 on the MCF5206 reaches it's reference value. **/
/** It stores the current context before calling the uC/OS int **/
/** nesting logic and timer tick routine which can cause the **/
/** context to change. Use this as an example of how to write **/
/** ISRs in uC/OS. **/
/********************************************************************/
OSTickISR:
lea -60(%a7),%a7
movem.l %d0-%d7/%a0-%a6,(%a7)
move.l #0x10000111,%a0 |Reset the timer chip (hard coded Timer1.TER reg value - bad)
move.b #0x03,(%a0)
jsr OSIntEnter
jsr OSTimeTick
jsr OSIntExit
movem.l (%a7),%d0-%d7/%a0-%a6
lea 60(%a7),%a7
rte
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -