你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【安富莱STM32F407之uCOS-III教程】第9章 μCOS-III系统移植文...

[复制链接]
baiyongbin2009 发布时间:2014-12-22 16:52
阅读主题, 点击返回1楼
收藏 评论11 发布时间:2014-12-22 16:52
11个回答
baiyongbin2009 回答时间:2014-12-22 17:19:38
9.4.3      PendSV中断
    关于PendSV中断,我们在第4章和第5章已经非常详细的讲解了,这里主要是给大家分析一下任务切换的处理过程,这个中断函数的前面有英文的注释说的非常好,大家有必要看一下。
  1. ;********************************************************************************************************
  2. ;                                       HANDLE PendSV EXCEPTION
  3. ;                                   void OS_CPU_PendSVHandler(void)
  4. ;
  5. ; Note(s) : 1) PendSV is used to cause a context switch.  This is a recommended method for performing
  6. ;              context switches with Cortex-M3.  This is because the Cortex-M3 auto-saves half of the
  7. ;              processor context on any exception, and restores same on return from exception.  So only
  8. ;              saving of R4-R11 is required and fixing up the stack pointers.  Using the PendSV exception
  9. ;              this way means that context saving and restoring is identical whether it is initiated from
  10. ;              a thread or occurs due to an interrupt or exception.
  11. ;
  12. ;           2) Pseudo-code is:
  13. ;              a) Get the process SP, if 0 then skip (goto d) the saving part (first context switch);
  14. ;              b) Save remaining regs r4-r11 on process stack;
  15. ;              c) Save the process SP in its TCB, OSTCBCurPtr->OSTCBStkPtr = SP;
  16. ;              d) Call OSTaskSwHook();
  17. ;              e) Get current high priority, OSPrioCur = OSPrioHighRdy;
  18. ;              f) Get current ready thread TCB, OSTCBCurPtr = OSTCBHighRdyPtr;
  19. ;              g) Get new process SP from TCB, SP = OSTCBHighRdyPtr->OSTCBStkPtr;
  20. ;              h) Restore R4-R11 from new process stack;
  21. ;              i) Perform exception return which will restore remaining context.
  22. ;
  23. ;           3) On entry into PendSV handler:
  24. ;              a) The following have been saved on the process stack (by processor):
  25. ;                 xPSR, PC, LR, R12, R0-R3
  26. ;              b) Processor mode is switched to Handler mode (from Thread mode)
  27. ;              c) Stack is Main stack (switched from Process stack)
  28. ;              d) OSTCBCurPtr      points to the OS_TCB of the task to suspend
  29. ;                 OSTCBHighRdyPtr  points to the OS_TCB of the task to resume
  30. ;
  31. ;           4) Since PendSV is set to lowest priority in the system (by OSStartHighRdy() above), we
  32. ;              know that it will only be run when no other exception or interrupt is active, and
  33. ;              therefore safe to assume that context being switched out was using the process stack (PSP).
  34. ;********************************************************************************************************

  35. OS_CPU_PendSVHandler
  36.     CPSID   I                                           ; Prevent interruption during context switch
  37.     MRS     R0, PSP                                     ; PSP is process stack pointer
  38.     CBZ     R0, OS_CPU_PendSVHandler_nosave             ; Skip register save the first time

  39.     SUBS    R0, R0, #0x20                               ; Save remaining regs r4-11 on process stack
  40.     STM     R0, {R4-R11}

  41.     LDR     R1, =OSTCBCurPtr                            ; OSTCBCurPtr->OSTCBStkPtr = SP;
  42.     LDR     R1, [R1]
  43.     STR     R0, [R1]                                     ; R0 is SP of process being switched out

  44.                                                      ; At this point, entire context of process has been saved
  45. OS_CPU_PendSVHandler_nosave
  46.     PUSH    {R14}                                               ; Save LR exc_return value
  47.     LDR     R0, =OSTaskSwHook                                   ; OSTaskSwHook();
  48.     BLX     R0
  49.     POP     {R14}

  50.     LDR     R0, =OSPrioCur                                      ; OSPrioCur   = OSPrioHighRdy;
  51.     LDR     R1, =OSPrioHighRdy
  52.     LDRB    R2, [R1]
  53.     STRB    R2, [R0]

  54.     LDR     R0, =OSTCBCurPtr                                    ; OSTCBCurPtr = OSTCBHighRdyPtr;
  55.     LDR     R1, =OSTCBHighRdyPtr
  56.     LDR     R2, [R1]
  57.     STR     R2, [R0]

  58.     LDR     R0, [R2]                                            ; R0 is new process SP; SP = OSTCBHighRdyPtr->StkPtr;
  59.     LDM     R0, {R4-R11}                                        ; Restore r4-11 from new process stack
  60.     ADDS    R0, R0, #0x20
  61.     MSR     PSP, R0                                             ; Load PSP with new process SP
  62.     ORR     LR, LR, #0x04                                       ; Ensure exception return uses process stack
  63.     CPSIE   I
  64.     BX      LR                                                  ; Exception return will restore remaining context

  65.     END
复制代码
    这里PendSV中断的主要作用就是保存当前任务的现场,恢复下一个任务的寄存器,从而切换到下一个任务中执行程序,并保证退出PendSV后使用的是PSP (任务堆栈指针)。下面先把这些汇编代码解释一下:
  1. OS_CPU_PendSVHandler                       ;xPSR, PC, LR, R12, R0-R3已自动保存入栈
  2. CPSID   I                                  ;任务切换期间需要关中断
  3. MRS     R0, PSP                            ;R0 = PSP
  4. CBZ     R0, OS_CPU_PendSVHandler_nosave    ;如果PSP==0跳转到OS_CPU_PendSVHandler_nosave去执行 在多任务
  5. ;的初始化时PSP被初始化为0,表示任务是第一次运行,不需要压栈

  6. /********************************将当前的任务寄存器入栈*********************************************/
  7. SUBS    R0, R0, #0x20        ;R0 -= 0x20 保存R4-R11到任务堆栈 共32个字节            
  8. STM     R0, {R4-R11}         ;压栈R4-R11
  9. LDR     R1, =OSTCBCur        ;获取OSTCBCur->OSTCBStkPtr,
  10. ;OSTCBStkPtr是OSTCBCur 中的第一个变量                           
  11. LDR     R1, [R1]             ;R1 = *R1 (R1 = OSTCBCur)
  12. STR     R0, [R1]             ;*R1 = R0 (*OSTCBCur = SP)
  13.                              ;将当前任务的堆栈保存到自己的任务控制块
  14. ;OSTCBCur->OSTCBStkPtr = PSP
  15. ;程序运行此位置,已经保存了当前任务的寄存器。
  16.                            
  17. OS_CPU_PendSVHandler_nosave
  18. PUSH    {R14}                ;R14 入栈
  19. LDR     R0, =OSTaskSwHook    ;OSTaskSwHook(); R0 = &OSTaskSwHook
  20. BLX     R0                   ;调用OSTaskSwHook()
  21. POP     {R14}                ;恢复R14

  22. /********************************加载要执行任务的寄存器*********************************************/
  23. LDR     R0, =OSPrioCur      ;R0 = &OSPrioCur
  24. LDR     R1, =OSPrioHighRdy  ;R1 = &OSPrioHighRdy
  25. LDRB    R2, [R1]            ;R2 = *R1
  26. STRB    R2, [R0]            ;*R0 = R2
  27.                             ;上面这四句函数的功能就是OSPrioCur = OSPrioHighRdy

  28. LDR     R0, =OSTCBCur       ;R0 = &OSTCBCur
  29. LDR     R1, =OSTCBHighRdy   ;R1 = &OSTCBHighRdy
  30. LDR     R2, [R1]            ;R2 = *R1
  31. STR     R2, [R0]            ;*R0 = R2
  32. ;上面这四句函数的功能就是OSTCBCur = OSTCBHighRdy

  33. LDR     R0, [R2]            ;R0 = *R2 也就是R0 = OSTCBHighRdy又因为SP = OSTCBHighRdy->OSTCBStkPtr
  34.                             ;这条指令的含义就是R0=PSP。
  35. LDM     R0, {R4-R11}        ;从任务堆栈恢复R4-R11
  36. ADDS    R0, R0, #0x20       ;调整R0 += 0x20
  37. MSR     PSP, R0             ;PSP = R0
  38. ORR     LR, LR, #0x04     ; 确保LR位2为1,返回后使用进程堆栈PSP
  39. CPSIE   I                 ; 开中断
  40. BX      LR                ; 中断返回,剩下的8个寄存器会自动的出栈。
  41. END
复制代码
    为了帮助大家更好的理解这个过程,这里举一个简单的例子:
  l 第一步:开始多任务后,系统就会从咱们上面说的OSStartHighRdy进入到PendSV中断,进入中断前使用的是MSP,也就是说自动入栈的8个寄存器被压入到MSP所指向的堆栈空间。
  l 第二步:进入中断后开始MSP(因为中断程序中只能使用MSP,而不能使用PSP)。由于是第一次进入执行PendSV,剩下的8个需要手动入栈的寄存器不需要执行入栈操作(为什么不需要入栈操作? 因为第一次执行PendSV前的函数只是μCOS-III的初始化,而不是需要执行的任务,所以现场不需要保存)。
  l 第三步:获得当前需要执行的最高优先级任务A后,程序就会从任务A的堆栈空间恢复需要手动入栈的8个寄存器R4-R11,在退出PendSV后,剩下的8个寄存器内容会自动得到恢复。由于前面初始化任务堆栈的时候,已经指定了任务的地址,所以这时就能正确的切换到任务A中。
  l 第四步:当任务A被挂起或者其它的原因,系统再次进入到PendSV中断,进入中断前自动入栈的8个寄存器已经被保存到任务A的堆栈空间,进入中断后再将剩余8个需要手动入栈的8个寄存器推入任务A的堆栈空间,并保存PSP到任务A的TCB控制块,剩下执行的操作就和第三步相同了,获取另一个需要执行的高优先级任务B。初学的同学一定要不这个过程分析透,并牢记。这个过程很重要,要不任务怎么切换的都不知道。

baiyongbin2009 回答时间:2014-12-22 17:20:39
9.5  总结
    希望初学的同学将文章所讲的三个文件自行分析一下,特别是PendSV中断函数的内容。本期教程的内容理解透了,对于后面学习源码大有裨益。

参考资料:
1.       www.micrium.com

12

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版