ucos-II在44b0上的移植(解决不断重启问题)

来源:互联网 发布:sql语句获取当前时间 编辑:程序博客网 时间:2024/05/16 23:50

        前一段时间移植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  ; 注释掉这里的代码

原创粉丝点击