反反复复弄了一个多星期,参考了不少资料,终于让ucos在自己的板子上跑起来了。期间遇到了不少问题,还好坚持下来,挺 了过去.....复习一下,记录下来,以当后用:
1.在ads中建产工程,进入工程界面后,先建立两个组,一个为命名为ucosii,另一个为s3c2410。
ucosii,下再建两个组,一个为arm,添加移植要修改的三个文件,另一个sourc则添加与处理器无关的 ucos源文件。
s3c2410下主要存放一些与开发板初始化等有关的文件。
2.移植的重点主要在三个有处理器有关的文件os_cpu.h,os_cpu_a.s 和os_cpu_c.c三个文件的编写。
(1)根据书上的移植说明及相关的参考文件,os_cpu.h的编写最简单,主要是定义一些数据类型以及开关中断的 方法等;
(2) os_cpu_c.c这个文件中,有不少钩子函数,都默认为空函数即可,无需编写.只有一个很重要的函数需要动手编写,即任务堆栈初始化函数 ostaskstkinit,它在任务创建时用来对任务堆栈的初始化工作,可以采用软中断或函数调用的方式来完成.
os_stk *ostaskstkinit (void (*task)(void *pd), void *p_arg, os_stk *ptos, int16u opt)
{
os_stk *stk;
opt = opt; /* 'opt' is not used, prevent warning */
stk = ptos; /* load stack pointer */
*(stk) = (os_stk)task; /* entry point */
*(--stk) = (int32u)0; /* lr */
*(--stk) = (int32u)0; /* r12 */
*(--stk) = (int32u)0; /* r11 */
*(--stk) = (int32u)0; /* r10 */
*(--stk) = (int32u)0; /* r9 */
*(--stk) = (int32u)0; /* r8 */
*(--stk) = (int32u)0; /* r7 */
*(--stk) = (int32u)0; /* r6 */
*(--stk) = (int32u)0; /* r5 */
*(--stk) = (int32u)0; /* r4 */
*(--stk) = (int32u)0; /* r3 */
*(--stk) = (int32u)0; /* r2 */
*(--stk) = (int32u)0; /* r1 */
*(--stk) = (int32u)p_arg; /* r0 : argument arm的第一个参数存放在r0中 */
*(--stk) = (int32u)0x00000013l; /* cpsr (svc mode, enable both irq and fiq interrupts) */
return (stk);
}
(3).os_cpu_a.s文件中需要编写四个汇编函数: osstarthighrdy, osctxsw, ostickisr , osintctxsw
;*********************************************************************************************************/
import osrunning //在本文件中要用到别的文件中定义的变量,要import导入
import ostcbcur
import ostcbhighrdy
import ospriocur
import ospriohighrdy
import osintnesting
import osintenter
import osintexit
import ostaskswhook
import ostimetick
import handleeint0
export osstarthighrdy //在本汇编文件中定义实现的函数或变量用export导出,在别的文件中只要用时,
export osctxsw //用extern(.c文件)或import(.s文件)声明
export ostickisr
export osintctxsw
export oscpusavesr
export oscpurestoresr
export os_cpu_irq_isr
area ucos_arm, code, readonly
;*********************************************************************************************************
; start multitasking
; void osstarthighrdy(void)
;
; the stack frame is assumed to look as follows:
;
; entry point(task name) (high memory)
; lr(r14)
; r12
; r11
; r10
; r9
; r8
; r7
; r6
; r5
; r4
; r3
; r2
; r1
; r0 : argument
; ostcbhighrdy->ostcbstkptr --> cpsr (low memory)
;
; note : osstarthighrdy() must:
; a) call ostaskswhook() then,
; b) set osrunning to true,
; c) switch to the highest priority task.
;********************************************************************************************************** */
osstarthighrdy
;----------------------------------------------------------------------------------
; 下面的代码功能:osrunning = true;
;----------------------------------------------------------------------------------
msr cpsr_cxsf,#svcmode|noint ;switch to svc mode with irq&fiq disable
bl ostaskswhook ;call user define task switch hook
ldr r0, =osrunning ; osrunning =true
mov r1, #1
strb r1, [r0]
;----------------------------------------------------------------------------------
; sp = ostcbhighrdy->ostcbstkptr;得到将要恢复运行任务的堆栈指针
;----------------------------------------------------------------------------------
ldr r0, =ostcbhighrdy ;堆栈指针在任务控制块偏移量为0的地方
ldr r0, [r0]
ldr sp, [r0]
;----------------------------------------------------------------------------------
; prepare to return to proper mode 从新任务堆栈中恢复处理器的所有寄存器
;----------------------------------------------------------------------------------
ldmfd sp!, {r0}
msr spsr_cxsf, r0
ldmfd sp!, {r0-r12, lr, pc}^
;**********************************************************************************************************
; perform a context switch (from task level)任务级任务切换
; void osctxsw(void)
;
; note(s): 1) upon entry:
; ostcbcur points to the os_tcb of the task to suspend
; ostcbhighrdy points to the os_tcb of the task to resume
;
; 2) the stack frame of the task to suspend looks as follows:
;
; pc (high memory)
; lr(r14)
; r12
; r11
; r10
; r9
; r8
; r7
; r6
; r5
; r4
; r3
; r2
; r1
; r0
; ostcbcur->ostcbstkptr ----> cpsr (low memory)
;
;
; 3) the stack frame of the task to resume looks as follows:
;
; pc (high memory)
; lr(r14)
; r12
; r11
; r10
; r9
; r8
; r7
; r6
; r5
; r4
; r3
; r2
; r1
; r0
; ostcbhighrdy->ostcbstkptr ----> cpsr (low memory)
;*********************************************************************************************************/
osctxsw
stmfd sp!, {lr} ;pc
stmfd sp!, {r0-r12, lr} ;r0-r12 lr
mrs r0, cpsr ;push cpsr
stmfd sp!, {r0}
;----------------------------------------------------------------------------------
; ostcbcur->ostcbstkptr = sp 在当前任务控制块中保存当前任务的堆栈指针
;----------------------------------------------------------------------------------
ldr r0, =ostcbcur
ldr r0, [r0]
str sp, [r0]
;----------------------------------------------------------------------------------
; ostaskswhook();
;---------------------------------------------------------------------------------
bl ostaskswhook
;----------------------------------------------------------------------------------
; ostcbcur = ostcbhighrdy; 将指向当前任务的指针指向要恢复的任务//ostcbcur:pointer to highest priority tcb r-to-r
;----------------------------------------------------------------------------------
ldr r0, =ostcbhighrdy
ldr r1, =ostcbcur
ldr r0, [r0]
str r0, [r1]
;----------------------------------------------------------------------------------
; ospriocur = ospriohighrdy; 将新任务的优先级赋给当前任务的优先级//ospriohighrdy: priority of highest priority task
;----------------------------------------------------------------------------------
ldr r0, =ospriohighrdy
ldr r1, =ospriocur
ldrb r0, [r0]
strb r0, [r1]
;----------------------------------------------------------------------------------
; ostcbhighrdy->ostcbstkptr;得到将要运行的任务的堆栈指针
;----------------------------------------------------------------------------------
ldr r0, =ostcbhighrdy
ldr r0, [r0]
ldr sp, [r0]
;----------------------------------------------------------------------------------
;restore new task context 从新任务中恢复处理器的寄存器
;----------------------------------------------------------------------------------
ldmfd sp!, {r0} ;pop cpsr
msr spsr_cxsf, r0
ldmfd sp!, {r0-r12, lr, pc}^
*********************************************************************************************************
; tick handler
; description: 此处为时钟节拍中断处理函数
;过程简介:当初始化时钟源(采用timer0),开始中断后。定时时间到,产生中断,cpu进入 irq模式,pc跳转到0x18处,经过中断源查询后,调用os_cpu_irq_isr ,在os_cpu_irq_isr 中切换为管理模后保存处理器寄存器后,再经查询跳转到些正式进行中断服务程序处理,然后返回(中断处理及切换最难:后详解)
; this handles all the timer0(int_timer0) interrupt which is used to generate the uc/os-ii tick.
;*********************************************************************************************************/
ostickisr
;----------------------------------------------------------------------------------
;;保存处理器的值;
;----------------------------------------------------------------------------------
mov r5,lr
;----------------------------------------------------------------------------------
;调用osintenter or 将osiintnesting加1
;----------------------------------------------------------------------------------
mov r1, #1 ;清除中断标志
mov r1, r1, lsl #10 ; timer0 source pending reg.timer0为位10
ldr r0, =srcpnd ;源未决寄存器中有中断时,相应位置1,
ldr r2, [r0]
orr r1, r1,r2
str r1, [r0]
ldr r0, =intpnd ;中断未决寄存器中只保存未屏蔽的具有最高优先级的一位中断标志
ldr r1, [r0]
str r1, [r0]
;----------------------------------------------------------------------------------
; ostimetick();
;----------------------------------------------------------------------------------
bl ostimetick
mov pc, r5 ; return
;*********************************************************************************************************
; perform a context switch (from an isr)
; void osintctxsw(void)
;
; description: 1) this code performs a context switch if a higher priority task has been made ready-to-run
; during an isr.
;
; 2) the stack frame of the task to suspend looks as follows:
;
; pc (high memory)
; lr(r14)
; r12
; r11
; r10
; r9
; r8
; r7
; r6
; r5
; r4
; r3
; r2
; r1
; r0
;
; ostcbcur->ostcbstkptr ----> cpsr (low memory)
;
;
; 3) the stack frame of the task to resume looks as follows:
;
; pc (high memory)
; lr(r14)
; r12
; r11
; r10
; r9
; r8
; r7
; r6
; r5
; r4
; r3
; r2
; r1
; r0
; ostcbhighrdy->ostcbstkptr ----> cpsr (low memory)
;*********************************************************************************************************/
osintctxsw
;----------------------------------------------------------------------------------
; call ostaskswhook();
;----------------------------------------------------------------------------------
bl ostaskswhook
;----------------------------------------------------------------------------------
; ostcbcur = ostcbhighrdy;
;----------------------------------------------------------------------------------
ldr r0, =ostcbhighrdy
ldr r1, =ostcbcur
ldr r0, [r0]
str r0, [r1]
;----------------------------------------------------------------------------------
; ospriocur = ospriohighrdy;
;----------------------------------------------------------------------------------
ldr r0, =ospriohighrdy
ldr r1, =ospriocur
ldrb r0, [r0]
strb r0, [r1]
;----------------------------------------------------------------------------------
; sp = ostcbhighrdy->ostcbstkptr;
;----------------------------------------------------------------------------------
ldr r0, =ostcbhighrdy
ldr r0, [r0]
ldr sp, [r0]
;----------------------------------------------------------------------------------
; restore new task context
;----------------------------------------------------------------------------------
ldmfd sp!, {r0} ;pop cpsr
msr spsr_cxsf, r0
ldmfd sp!, {r0-r12, lr, pc}^
os_cpu_irq_isr
stmfd sp!, {r1-r3} ; use r1-r3 as temporary registers,push r1-r3 to irq stack
;----------------------------------------------------------------------------
; r1--sp
; r2--pc
; r3--spsr
;------------------------------------------------------------------------
mov r1, sp
add sp, sp, #12 ;adjust irq stack pointer,因为保存了r1-r3,,sp_irq往下移了,为了以后中断使用
;要用到中断堆栈,故此处需要调整回去到其开始定义的地方
sub r2, lr, #4 ;adjust pc for return address to task
mrs r3, spsr ; copy spsr (task cpsr)
msr cpsr_cxsf, #svcmode|noint ;change to svc mode
; save task''s context onto old task''s stack
stmfd sp!, {r2} ; push task''s pc
stmfd sp!, {r4-r12, lr} ; push task''s lr,r12-r4
ldmfd r1!, {r4-r6} ; load task''s r1-r3 from irq stack
stmfd sp!, {r4-r6} ; push task''s r1-r3 to svc stack
stmfd sp!, {r0} ; push task''s r0 to svc stack
stmfd sp!, {r3} ; push task''s cpsr
ldr r0,=osintnesting ;osintnesting ,将中断嵌套层数加1
ldrb r1,[r0]
add r1,r1,#1
strb r1,[r0]
//下面几句此处为2.5以上实现中断嵌套 与编译器无关的精彩改进之处。可以中断嵌套后无需调整堆栈指针sp
;其原理就是在最外层中断时,把sp保存到任务控制块的堆栈中:ostcbcur->ostcbstkptr=sp,把sp所指堆栈赋给ostcbstkptr即ostcbcur->ostcbstkptr指向的刚发生中断时的堆栈,以后不管是否发生中断嵌套,使得sp发 生变化。都只需要任务恢复时从此恢复任务的sp,使用有用的堆栈,而不用去理后面中断嵌套发生的堆栈变化(对任务来说无用)
cmp r1,#1 ;{if(osintnesting==1){; 则将被中断任务的堆栈指针保存在被中断任务的任务任务控制块中
bne �
ldr r4,=ostcbcur ;ostcbcur->ostcbstkptr=sp;以免中断退出调用高优先级任务后破坏堆栈指针,
;避免调整堆栈指针的麻烦
ldr r5,[r4]
str sp,[r5] ;}
1
msr cpsr_c,#irqmode|noint ;change to irq mode to use irq stack to handle interrupt
ldr r0, =intoffset ;根据中断偏移寄存器中的值为查到中断源号,再跳转到相应的中断服务中程序中去;
ldr r0, [r0]
ldr r1, irqisrvect
mov lr, pc ; save lr befor jump to the c function we need return back
ldr pc, [r1, r0, lsl #2] ; call os_cpu_irq_isr_handler();
msr cpsr_c,#svcmode|noint ;change to svc mode
bl osintexit ;call osintexit
ldmfd sp!,{r4} ;pop the task''s cpsr
msr spsr_cxsf,r4
ldmfd sp!,{r0-r12,lr,pc}^ ;pop new task''s context
irqisrvect dcd handleeint0
;*********************************************************************************************************
;采用第三种方法处理开关中断
oscpusavesr
mrs r0, cpsr ; set irq and fiq bits in cpsr to disable all interrupts
orr r1, r0, #0xc0
msr cpsr_c, r1
mrs r1, cpsr ; confirm that cpsr contains the proper interrupt disable flags
and r1, r1, #0xc0
cmp r1, #0xc0
bne oscpusavesr ; not properly disabled (try again)
mov pc, lr ; disabled, return the original cpsr contents in r0
oscpurestoresr
msr cpsr_c, r0
mov pc, lr
end
上述为编写与处理器有关的三个文件,要使ocos在板上运行起来,还得做一些板子初始化方面的工作。如2410的启动加载文件就是必需的,还有 mmu初始等....后继续
『本文转载自网络,u球体育app下载的版权归原作者所有,如有侵权请联系删除』