您的位置:首页 > 其它

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

2011-08-23 17:22 267 查看
前一段时间移植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 ; 注释掉这里的代码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: