发 帖  
原厂入驻New
对于UCOS2.86移植到Cortex_M3的遇到的一些问题怎么解决
37 cpu
分享
首先我把我有疑问的这段代码挑选出来,然后选出里面有疑问的代码:
OS_CPU_PendSVHandler             ;xPSR, PC, LR, R12, R0-R3 已自动保存
    CPSID   I                    ;任务切换期间需要关中断
    MRS     R0, PSP              ;R0 = PSP
    ;如果PSP == 0,跳到OS_CPU_PendSVHandler_nosave 执行 #1
    CBZ     R0, OS_CPU_PendSVHandler_nosave   
    ;保存R4-R11 到任务堆栈
    SUBS    R0, R0, #0x20        ;R0 -= 0x20                          
    STM     R0, {R4-R11}         ;保存 R4-R11到任务堆栈
    ;OSTCBCur->OSTCBStkPtr = SP;
    LDR     R1, =OSTCBCur        ;R1 = &OSTCBCur
    LDR     R1, [R1]             ;R1 = *R1 (R1 = OSTCBCur)
    STR     R0, [R1]             ;*R1 = R0 (*OSTCBCur = SP) #2                        
OS_CPU_PendSVHandler_nosave
;调用OSTaskSwHook()
   USH    {R14}                ;保存R14,因为后面要调用函数            
   LDR     R0, =OSTaskSwHook    ;R0 = &OSTaskSwHook  
    BLX     R0                   ;调用OSTaskSwHook()
    POP     {R14}                ;恢复 R14
    ;OSPrioCur = OSPrioHighRdy;
    LDR     R0, =OSPrioCur       ;R0 = &OSPrioCur
    LDR     R1, =OSPrioHighRdy   ;R1 = &OSPrioHighRdy
    LDRB    R2, [R1]             ;R2 = *R1 (R2 = OSPrioHighRdy)
    STRB    R2, [R0]             ;*R0 = R2 (OSPrioCur = OSPrioHighRdy)
    ;OSTCBCur = OSTCBHighRdy;
    LDR     R0, =OSTCBCur        ;R0 = &OSTCBCur      
    LDR     R1, =OSTCBHighRdy    ;R1 = &OSTCBHighRdy
    LDR     R2, [R1]             ;R2 = *R1 (R2 = OSTCBHighRdy)
    STR     R2, [R0]             ;*R0 = R2 (OSTCBCur = OSTCBHighRdy)
    LDR     R0, [R2]             ;R0 = *R2 (R0 = OSTCBHighRdy), 此时 R0是新任
  的 SP
  ;SP = OSTCBHighRdy->OSTCBStkPtr #3  
  LDM     R0, {R4-R11}   ;从任务堆栈SP恢复R4-R11
  ADDS    R0, R0, #0x20  ;R0 += 0x20
  MSR     SP, R0    SP = R0,用新任务的 SP加载PSP
  ORR     LR, LR, #0x04 ;确保 LR 位2 为 1,返回后使用进程堆栈 #4  
  CPSIE   I                    ;开中断
  BX      LR                   ;中断返回
  END
然后下面这些是我的不解之处,希望能有人帮忙解答出来:
移植ucosii 所遇到的疑问:
1、在任务调度函数中void  OS_Sched (void)有这么两行代码:
          void  OS_Sched (void){
                                。。。。。。。。。。。//省略
                                IF (OSPrioHighRdy != OSPrioCur) {
                OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
                                。。。。。。。。。。。。//省略
                         }
为什么只要判断就绪的最高优先级任务不是当前任务就可以了呢?UCOS不是可剥夺型的内核嘛?应该是就绪任务表中的最高优先级任务小于或者说优先级高于当前任务,就进行任务切换嘛?
2、在os_cpu_a.asm文件中的PendSV 中断处理函数OS_CPU_PendSVHandler里面有这么一段话:
;保存R4-R11 到任务堆栈
SUBS    R0, R0, #0x20        ;R0 -= 0x20      //有疑问的地方
//为什么要先让R0=R0-20?
    STM     R0, {R4-R11}         ;保存 R4-R11到任务堆栈
;OSTCBCur->OSTCBStkPtr = SP;
    LDR     R1, =OSTCBCur        ;R1 = &OSTCBCur
    LDR     R1, [R1]             ;R1 = *R1 (R1 = OSTCBCur)
STR     R0, [R1]             ;*R1 = R0 (*OSTCBCur = SP) #2   
(加颜色为有疑问的地方。)为什么要先让R0=R0-20?
3、在os_cpu_a.asm文件中的PendSV 中断处理函数OS_CPU_PendSVHandler的最后几句代码里面有这么一条代码:
ORR     LR, LR, #0x04 ;确保 LR 位2 为 1,返回后使用进程堆栈 #4
为什么在这里要确保LR的位2为1?
有人这么解释的“因为在中断处理函数中使用的是 MSP,所以在返回任务后必须使用PSP,所以LR位2 必须为 1。”但是如果这么样的话,我又有疑问了,是使用MSP还是PSP不是由CONTROL[1]决定的嘛?
0
2020-5-22 14:48:17   评论 分享淘帖 邀请回答
12个回答
SUBS    R0, R0, #0x20        ;R0 -= 0x20      //有疑问的地方
//为什么要先让R0=R0-20?
解答:
        因为0x20=32,所以R0=R0-32,相当于向后移动一个单元(一个字长)。
这个是我后来突然想到的,如果不对,求指正。。。 
2020-5-22 09:24:20 评论

举报

对于疑问1,我突然想出来了:
    其实不用做比较的原因不是其他的函数做了这个工作,是因为连当前运行的任务也在整个就绪任务表中,就绪的任务变为运行态以后,并没用把他从就绪表中删除,所以就绪任务表中最高就绪优先级的任务只用两种情况一种是比当前运行态的任务优先级高的任务进入了就绪态,一个就是当前运行的任务。就绪的任务只有当调用OSTaskDel()或者OSTaskSuspend()以后,才会从就绪表中删除。
    呵呵,想了好久才想到这个原因,不知道对不对?如果不正确,请指正。
    看着自己在这里提的问,半天没人回答,是不是因为提的太笨了点呢?呵呵...
2020-5-22 09:35:50 评论

举报

2020-5-22 09:47:27 评论

举报

回复【4楼】发烧友:
--------------------------------
呵呵,这个我看过了,就是因为在看的过程中,对一些代码有疑问,所以才发帖的,不过还是十分感激你的回复,呵呵
对于疑问3,我现在也找到相关资料,在<<Cortex-M3权威指南>>的最后附录E中,E.2(设计Fault服务例程)中的E.2.2.2上报入栈的PC一节中有范例,通过LR.2来确定当时使用的是MSP还是PSP。
2020-5-22 09:55:13 评论

举报

看看邵贝贝的书第三章任务调度,这里是为了避免对当前任务进行没要的任务调度,很有研究代码的精神。
2020-5-22 10:04:54 评论

举报

顶,邵贝贝那可是权威啊!呵呵!
2020-5-22 10:15:46 评论

举报

回复【楼主位】lihaiping1603:
--------------------------
对于3,,应该是字节对齐,确定是THUMB状态还是ARM状态
2020-5-22 10:30:00 评论

举报

我也遇到过这样类似的问题
2020-5-22 10:37:09 评论

举报

非常感谢!正在找的资料!
2020-5-22 10:50:50 评论

举报

我也是初学ucos,我的理解是这样的 
问题1:
 ucos-ii是可剥夺内核,始终最先运行优先级最高的任务,除非中断或者自动放弃CPU控制权,所以在任务切换时只要当前任务不是最高优先级,就会做任务切换。
问题2:
  CM3是向下满栈的,也就是向下增长的,每入栈一字节之前,SP减1;这里需要入栈R4~R11共8个32位寄存器的值,也就是32个字节,所以自减32也即是0x20
问题3:
  ucosii 不区分特权级和用户级,程序始终工作在特权级;MSP、PSP两个堆栈指针的切换是全自动的,就在出入异常服务例程时由硬件处理。MSP是异常处理来用,PSP任务程序来用,所以返回时需要切换到PSP
2020-5-22 10:59:03 评论

举报

谢谢楼主,我也对疑问3疑惑不解,看到你这个终于找到了答案!
2020-5-22 11:07:02 评论

举报

CORTEX-M3内核权威手册中讲到了,在进入中断时,  LR的用法将被重新解释,其值也被更新成一种特殊的值,称为“EXC_RETURN”,
并且在异常返回时使用。 EXC_RETURN的二进制值除了最低4位外全为1,而其最低4位则有另外的含义,可以参考表9.3 EXC_RETURN位段详解,图片咋发啊,自己查看下内核权威手册吧
<img id="aimg_yHwkH"  class="zoom" file="http://pan.baidu.com/s/1slymnO5"  lazyloadthumb="1" border="0" alt="">
2020-5-22 11:21:44 评论

举报

只有小组成员才能发言,加入小组>>

244个成员聚集在这个小组

加入小组

创建小组步骤

关闭

站长推荐 上一条 /7 下一条

快速回复 返回顶部 返回列表