Board logo

标题: ucos-II在44b0上的移植(解决不断重启问题) [打印本页]

作者: look_w    时间: 2017-10-24 20:23     标题: ucos-II在44b0上的移植(解决不断重启问题)

前一段时间移植UCOS-II到三星的44b0处理器上(源代码使用配套光碟的代码),发现处理器不断重启,找错找了大概一个星期(汗一个),上网找了很久,才找到解决方案。下面说明一下问题所在以及解决方法:        在时钟节拍中断中进行任务切换时,需要用到一个零时存储单元 SAVED_LR 来存储返回地址 lr 。 而 SAVED_LR 原来在 OS_CPU_A.S 中是这样定义的 SAVED_LR DCD 0, 注意没有任何指明 SAVED_LR 在存储空间中的位置的相关代码。这样 SAVED_LR 将被定义在程序代码段中。 当在仿真器上调试时,所有程序代码段都在 SDRAM 中,这样当需要将 lr 保存在 SAVED_LR 中时,实际上是对 SDRAM 进行写操作,该操作成功,程序可以正常运行。 当将生成的 BIN 文件烧写到 FLASH 中后运行是,程序代码段在 FLASH 中,这样当需要将 lr 保存在 SAVED_LR 中时,实际上是对 FLASH 进行写操作,该操作当然不会成功,导致程序不会正常运 行。由 SAVED_LR 定义时知,SAVED_LR 中的内容固化为0,所以对任务堆栈压栈操作时,没有将正确的返回地址压栈,而将返回地址0压栈。最后当第二次调用 OSTimeDlyHMSM() 进行任务切换时,返回地址0弹出到 lr 寄存器,导致系统重启。 解决方法: 将 SAVED_LR 定义到数据段即可。具体操作有多种方法。我是这样做的:在 ucos_ii.h 中定义全局变量OS_EXT  INT32U      SAVED_LR;, 在OS_CPU_A.S 中引用(加入 IMPORT SAVED_LR),部分代码如下:(SAVED_LR 在内存分配的地址可以用ADS编译软件查看,步骤如下:在DebugRel Settings中选择ARM Linker,然后选择Listings选项卡,在Listings中勾选Symbols即可,最后重新编译工程。在弹出的Errors & Warnings窗口中可查看SAVED_LR 在内存中的地址。)
_CON_SW
LDMIA sp!,{r0-r11,lr}
SUB lr, lr, #4
stmfd sp!, {r0} ;tufei add
ldr r0, =SAVED_LR ;tufei add
STR lr, [r0] ;tufei modify
;STR lr, SAVED_LR ;STR lr, [pc, #SAVED_LR-.-8]
ldmfd sp!, {r0} ;tufei add ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Change Supervisor mode ;!!!r12 register don't preserved. (r12 that PC of task)
MRS lr, SPSR
AND lr, lr, #0xFFFFFFE0
ORR lr, lr, #0x13
MSR CPSR_cxsf, lr ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Now Supervisor mode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
STR r12, [sp, #-8] ; saved r12
LDR r12, =SAVED_LR ;tufei modify
;LDR r12, SAVED_LR ;LDR r12, [pc, #SAVED_LR-.-8]
ldr r12, [r12] ;tufei add
STMFD sp!, {r12} ; r12 that PC of task
SUB sp, sp, #4 ; inclease stack point
LDMIA sp!, {r12} ; restore r12
STMFD sp!, {lr} ; save lr
STMFD sp!, {r0-r12} ; save register file and ret address
MRS r4, CPSR
STMFD sp!, {r4} ; save current PSR
MRS r4, SPSR ; YYY+
STMFD sp!, {r4} ; YYY+ save SPSR ; OSPrioCur = OSPrioHighRdy
LDR r4, addr_OSPrioCur
LDR r5, addr_OSPrioHighRdy
LDRB r6, [r5]
STRB r6, [r4] ; Get current task TCB address
LDR r4, addr_OSTCBCur
LDR r5, [r4]
STR sp, [r5] ; store sp in preempted tasks's TCB ; Get highest priority task TCB address
LDR  r6, addr_OSTCBHighRdy
LDR r6, [r6]
LDR sp, [r6] ; get new task's stack pointer ; OSTCBCur = OSTCBHighRdy
STR r6, [r4] ; set new current task TCB address
LDMFD sp!, {r4} ; YYY+ ;
AND r4, r4, #0xFFFFFF20 ;
ORR r4, r4, #0x13
MSR SPSR_cxsf, r4 ; YYY+
LDMFD sp!, {r4} ; YYY+ ;
AND r4, r4, #0xFFFFFF20 ;
ORR r4, r4, #0x13
MSR CPSR_cxsf, r4 ; YYY+
LDMFD sp!, {r0-r12, lr, pc} ; YYY+

;SAVED_LR  DCD  0  ; 注释掉这里的代码




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0