您的位置 首页 制造

μC/OS-II 移植笔记 2(FreeScale 68HCS12 核单片机)

2.2OS_CPU_A.S首先是函数和全局变量的声明。;************************************************************************

2.2 OS_CPU_A.S

首先是函数和全局变量的声明。

  1. ;***************************************************************************
  2. ;PUBLICDECLARATIONS
  3. ;***************************************************************************
  4. xdefOSCPUSaveSR
  5. xdefOSCPURestoreSR
  6. xdefOSStartHighRdy
  7. xdefOSCtxSw
  8. xdefOSIntCtxSw
  9. xdefOSTickISR
  10. ;***************************************************************************
  11. ;EXTERNALDECLARATIONS
  12. ;***************************************************************************
  13. xrefOSIntExit
  14. xrefOSIntNesting
  15. xrefOSPrioCur
  16. xrefOSPrioHighRdy
  17. xrefOSRunning
  18. xrefOSTaskSwHook
  19. xrefOSTCBCur
  20. xrefOSTCBHighRdy
  21. xrefOSTimeTick

然后是临界区的相关代码。

  1. OSCPUSaveSR:
  2. tfrccr,b;Itsassumedthat8-bitreturnvalueisinregisterB
  3. sei;Disableinterrupts
  4. rts;ReturntocallerwithBcontainingthepreviousCCR
  5. OSCPURestoreSR:
  6. tfrb,ccr;BcontainstheCCRvaluetorestore,movetoCCR
  7. rts

下面的代码是要点部分,首先是 OSStartHighRdy 函数,尽管这个函数只在 OSStart 函数中被调用一次,在之后的程序生命周期中就再也用不到了,但这次调用至关重要,决议了用户使命是否能被调度起来。因而代码中给出的注释尽可能的具体,我想看过注释后就不需求我解说什么了。

  1. ;***********************************************************************
  2. ;STARTHIGHESTPRIORITYTASKREADY-TO-RUN
  3. ;
  4. ;Description:ThisfunctioniscalledbyOSStart()tostart
  5. ;thehighestprioritytaskthatwascreatedbyyour
  6. ;applicationbeforecallingOSStart().
  7. ;
  8. ;Arguments:none
  9. ;
  10. ;Note(s):1)Thestackframeisassumedtolookasfollows:
  11. ;
  12. ;OSTCBHighRdy->OSTCBStkPtr+0CCR
  13. ;+1B
  14. ;+2A
  15. ;+3X(H)
  16. ;+4X(L)
  17. ;+5Y(H)
  18. ;+6Y(L)
  19. ;+7PC(H)
  20. ;+8PC(L)
  21. ;
  22. ;2)OSStartHighRdy()MUST:
  23. ;a)CallOSTaskSwHook()then,
  24. ;b)SetOSRunningtoTRUE,
  25. ;c)Switchtothehighestprioritytaskbyloading
  26. ;thestackpointerofthehighestprioritytask
  27. ;intotheSPregisterandexecutean
  28. ;RTIinstruction.
  29. ;************************************************************************
  30. OSStartHighRdy:
  31. jsrOSTaskSwHook;4~,调用OSTaskSwHook
  32. ldab#$01;2~,OSRunning=1
  33. stabOSRunning;4~
  34. ldxOSTCBHighRdy;3~,将OSTCBHighRdy的地址放到寄存器X
  35. lds0,x;3~,将OSTCBHighRdy->OSTCBStkPtr放到SP
  36. nop
  37. rti;4~,Runtask

其实上面的代码也能够放到OS_CPU_C.C 中,下面是个示例:

  1. #pragmaCODE_SEGNON_BANKED
  2. #pragmaTRAP_PROCSAVE_NO_REGS
  3. voidOSStartHighRdy(void)
  4. {
  5. __asmjsrOSTaskSwHook;//OSTaskSwHook();
  6. __asmldab#$01;
  7. __asmstabOSRunning;//OSRunning=TRUE;
  8. __asm
  9. {
  10. ldxOSTCBHighRdy
  11. lds0,x
  12. nop
  13. }
  14. }

上面代码中 #pragma TRAP_PROC SAVE_NO_REGS 一共这是个中止处理函数,编译器不为之保存任何寄存器内容。 尽管 OSStartHighRdy 并不是个实在的中止处理函数,但它模仿却模仿了中止处理函数的行为,函数结束时调用 rti 而不是 rts 指令。

下面是使命切换的代码,注释现已满足的具体了,如果有不明白的当地主张将 Jean J.Labrosse 的书再细心读读。

  1. OSCtxSw:
  2. ldyOSTCBCur;3~,OSTCBCur->OSTCBStkPtr=StackPointer
  3. sts0,y
  4. OSIntCtxSw:
  5. jsrOSTaskSwHook;4~,Callusertaskswitchhook
  6. ldxOSTCBHighRdy;3~,OSTCBCur=OSTCBHighRdy
  7. stxOSTCBCur
  8. ldabOSPrioHighRdy;3~,OSPrioCur=OSPrioHighRdy
  9. stabOSPrioCur
  10. lds0,x;3~,LoadSPinto68HC12
  11. nop
  12. rti;8~,Runtask

能够看到,上面两个函数共用了大部分的函数体。上面的代码也能够直接写到 OS_CPU_C.C 中,不过写成 C 函数后就不能共用函数体了。

最终一部分是时钟中止程序,我运用RTI中止作为周期性时钟源。

  1. OSTickISR:
  2. incOSIntNesting;4~,NotifyuC/OS-IIaboutISR
  3. ldabOSIntNesting;4~,if(OSIntNesting==1){
  4. cmpb#$01
  5. bneOSTickISR1
  6. ldyOSTCBCur;OSTCBCur->OSTCBStkPtr=StackPointer
  7. sts0,y;}
  8. OSTickISR1:
  9. BSET$37,#128;CRGFLG_RTIF=1,这句是反汇编出来的,应该没错
  10. jsrOSTimeTick
  11. jsrOSIntExit;6~+,NotifyuC/OS-IIaboutendofISR
  12. rti;12~,Returnfrominterrupt,nohigherprioritytasksready.

中止程序的大部分代码都比较简答,只需下面这句我下了番功夫才写出来:
BSET $37, #128
与这行代码功用相同的 C 代码是:CRGFLG_RTIF = 1
我将 C代码直接生成汇编代码的结果是:BSET _CRGFLG,#128
可是直接拿到汇编文件中却无法编译,提示说 _CRGFLG 没有界说。一番查找才确认了_CRGFLG = 0x37。

2.3 OS_CPU_C.C
我们大部分的移植代码都放到了汇编文件中,OS_CPU_C.C 中的作业就很少了。OS_CPU_C.C 最重要的作业是 OSTaskStkInit 函数,而且网上撒播的大多数 68HC12 内核的移植代码的这部分都或多或少的有问题。下面先给出我的代码:

  1. OS_STK*OSTaskStkInit(void(*task)(void*pd),void*p_arg,OS_STK*ptos,INT16Uopt)
  2. {
  3. INT16U*wstk;
  4. INT8U*bstk;
  5. (void)opt;/*optisnotused,preventwarning*/
  6. ptos–;/*需求这么调整一下栈顶地址,不然存的榜首个int16的低Byte会溢出仓库*/
  7. wstk=(INT16U*)ptos;/*Loadstackpointer*/
  8. *wstk–=(INT16U)task;/*Returnaddress.Format:PCH:PCL*/
  9. *wstk–=(INT16U)task;/*Returnaddress.Format:PCH:PCL*/
  10. *wstk–=(INT16U)0x2222;/*YRegister*/
  11. *wstk–=(INT16U)0x1111;/*XRegister*/
  12. *wstk=(INT16U)p_arg;/*Simulatecalltofunctionwithargument(InDRegister)*/
  13. bstk=(INT8U*)wstk;/*ConvertWORDptrtoBYTEptrtosetCCR*/
  14. bstk–;
  15. *bstk=(0xC0);/*CCRRegister(DisableSTOPinstructionandXIRQ)*/
  16. return((OS_STK*)bstk);/*Returnpointertonewtop-of-stack*/
  17. }

其间有几点需求特别注意:
(1)68HC12 内核与 68HC11 内核一个大的差异便是 SP 指向的是实栈顶。老的68HC11的移植代码都是 *–wstk = XXXX。移植到68HC12 内核就要改为*wstk– = XXXX。不然会糟蹋掉仓库的前两个字节。
(2)先要碑文 ptos–;不然榜首个双字节会有一半溢出仓库空间。
(3)使命的参数传递是经过寄存器 D 的,而不是仓库。网上代码多数是:

[cpp]view plaincopy

  1. *wstk–=(INT16U)p_arg;
  2. *wstk–=(INT16U)task;

这样参数是传递不进来的,只需像我的代码中这样写才是正确的。
(4)代码中 *wstk– = (INT16U)task; 重复了两遍,千万别以为这是我的笔误。仓库中先存的(INT16U)task实际上是 task 函数的回来地址。尽管 μC/OS-II 要求使命不能回来,可是作为 C 言语的调用约好,在调用一个 C 函数之前要将 C 函数的回来地址先入栈。因而我将 task 的地址重复了两次,实际上榜首的地址是什么都不重要,由于程序运转中觉得不会用到。乃至不要这行也行,还能节约仓库中两个字节的空间。不过我仍是挑选了保存这行,使其看起来愈加契合 C 言语的调用标准。

除此之外,OS_CPU_C.C 还包含一系列的 Hook 函数:

  1. #ifOS_CPU_HOOKS_EN>0&&OS_VERSION>203
  2. voidOSInitHookBegin(void)
  3. {
  4. #ifOS_TMR_EN>0
  5. OSTmrCtr=0;
  6. #endif
  7. }
  8. voidOSInitHookEnd(void)
  9. {
  10. }
  11. #endif
  12. #ifOS_CPU_HOOKS_EN>0
  13. voidOSTaskCreateHook(OS_TCB*ptcb)
  14. {
  15. #ifOS_APP_HOOKS_EN>0
  16. App_TaskCreateHook(ptcb);
  17. #else
  18. (void)ptcb;
  19. #endif
  20. }
  21. voidOSTaskDelHook(OS_TCB*ptcb)
  22. {
  23. #ifOS_APP_HOOKS_EN>0
  24. App_TaskDelHook(ptcb);
  25. #else
  26. (void)ptcb;
  27. #endif
  28. }
  29. voidOSTaskStatHook(void)
  30. {
  31. #ifOS_APP_HOOKS_EN>0
  32. App_TaskStatHook();
  33. #endif
  34. }
  35. voidOSTaskSwHook(void)
  36. {
  37. #ifOS_APP_HOOKS_EN>0
  38. App_TaskSwHook();
  39. #endif
  40. }
  41. #endif
  42. #ifOS_CPU_HOOKS_EN>0&&OS_VERSION>=251
  43. voidOSTaskIdleHook(void)
  44. {
  45. #ifOS_APP_HOOKS_EN>0
  46. App_TaskIdleHook();
  47. #endif
  48. }
  49. #endif
  50. #ifOS_CPU_HOOKS_EN>0&&OS_VERSION>203
  51. voidOSTCBInitHook(OS_TCB*ptcb)
  52. {
  53. #ifOS_APP_HOOKS_EN>0
  54. App_TCBInitHook(ptcb);
  55. #else
  56. (void)ptcb;/*Preventcompilerwarning*/
  57. #endif
  58. }
  59. #endif
  60. #ifOS_CPU_HOOKS_EN>0
  61. voidOSTimeTickHook(void)
  62. {
  63. #ifOS_APP_HOOKS_EN>0
  64. App_TimeTickHook();
  65. #endif
  66. #ifOS_TMR_EN>0
  67. OSTmrCtr++;
  68. if(OSTmrCtr>=(OS_TICKS_PER_SEC/OS_TMR_CFG_TICKS_PER_SEC))
  69. {
  70. OSTmrCtr=0;
  71. OSTmrSignal();
  72. }
  73. #endif
  74. }
  75. #endif

代码中 OS_APP_HOOKS_EN 和 OS_TMR_EN 在v2.52 版别中还没呈现,我在这儿这样写是为了移植到后边版别时更轻松。

至此,移植代码就根本完结了。不过这样还不能运转,由于两个中止处理函数(OSCtxSw和OSTickISR)还没有和对应的中止发生相关。将这二者相关起来的方法有几种,比方直接在 PRM 文件中拟定,我用了种比较笨的方法,从网上找了个 vector.c 文件,尽管看起来不是很高雅,但确实是正确的代码。

  1. /*******************************************************************
  2. *
  3. *FreescaleMC9S12DP256ISRVectorDefinitions
  4. *
  5. *FileName:vectors.c
  6. *Version:1.0
  7. *Date:Jun/22/2004
  8. *Programmer:EricShufro
  9. ********************************************************************/
  10. /********************************************************************
  11. *EXTERNALISRFUNCTIONPROTOTYPES
  12. *********************************************************************/
  13. externvoidnear_Startup(void);/*StartupRoutine.*/
  14. externvoidnearOSTickISR(void);/*OSTimeTickRoutine.*/
  15. externvoidnearOSCtxSw(void);/*OSContectSwitchRoutine.*/
  16. externvoidnearSCI1_ISR(void);/*SCI1Routine.*/
  17. externvoidnearSCI0_ISR(void);/*SCI0Routine.*/
  18. /*
  19. ************************************************************************
  20. *DUMMYINTERRUPTSERVICEROUTINES
  21. *
  22. *Description:Whenaspuriousinterruptoccurs,theprocessorwill
  23. *jumptothededicateddefaulthandlerandstaythere
  24. *sothatthesourceinterruptmaybeidentifiedand
  25. *debugged.
  26. *
  27. *Notes:DoNotModify
  28. ************************************************************************
  29. */
  30. #pragmaCODE_SEG__NEAR_SEGNON_BANKED
  31. __interruptvoidsoftware_trap64(void){for(;;);}
  32. __interruptvoidsoftware_trap63(void){for(;;);}
  33. __interruptvoidsoftware_trap62(void){for(;;);}
  34. __interruptvoidsoftware_trap61(void){for(;;);}
  35. __interruptvoidsoftware_trap60(void){for(;;);}
  36. __interruptvoidsoftware_trap59(void){for(;;);}
  37. __interruptvoidsoftware_trap58(void){for(;;);}
  38. __interruptvoidsoftware_trap57(void){for(;;);}
  39. __interruptvoidsoftware_trap56(void){for(;;);}
  40. __interruptvoidsoftware_trap55(void){for(;;);}
  41. __interruptvoidsoftware_trap54(void){for(;;);}
  42. __interruptvoidsoftware_trap53(void){for(;;);}
  43. __interruptvoidsoftware_trap52(void){for(;;);}
  44. __interruptvoidsoftware_trap51(void){for(;;);}
  45. __interruptvoidsoftware_trap50(void){for(;;);}
  46. __interruptvoidsoftware_trap49(void){for(;;);}
  47. __interruptvoidsoftware_trap48(void){for(;;);}
  48. __interruptvoidsoftware_trap47(void){for(;;);}
  49. __interruptvoidsoftware_trap46(void){for(;;);}
  50. __interruptvoidsoftware_trap45(void){for(;;);}
  51. __interruptvoidsoftware_trap44(void){for(;;);}
  52. __interruptvoidsoftware_trap43(void){for(;;);}
  53. __interruptvoidsoftware_trap42(void){for(;;);}
  54. __interruptvoidsoftware_trap41(void){for(;;);}
  55. __interruptvoidsoftware_trap40(void){for(;;);}
  56. __interruptvoidsoftware_trap39(void){for(;;);}
  57. __interruptvoidsoftware_trap38(void){for(;;);}
  58. __interruptvoidsoftware_trap37(void){for(;;);}
  59. __interruptvoidsoftware_trap36(void){for(;;);}
  60. __interruptvoidsoftware_trap35(void){for(;;);}
  61. __interruptvoidsoftware_trap34(void){for(;;);}
  62. __interruptvoidsoftware_trap33(void){for(;;);}
  63. __interruptvoidsoftware_trap32(void){for(;;);}
  64. __interruptvoidsoftware_trap31(void){for(;;);}
  65. __interruptvoidsoftware_trap30(void){for(;;);}
  66. __interruptvoidsoftware_trap29(void){for(;;);}
  67. __interruptvoidsoftware_trap28(void){for(;;);}
  68. __interruptvoidsoftware_trap27(void){for(;;);}
  69. __interruptvoidsoftware_trap26(void){for(;;);}
  70. __interruptvoidsoftware_trap25(void){for(;;);}
  71. __interruptvoidsoftware_trap24(void){for(;;);}
  72. __interruptvoidsoftware_trap23(void){for(;;);}
  73. __interruptvoidsoftware_trap22(void){for(;;);}
  74. __interruptvoidsoftware_trap21(void){for(;;);}
  75. __interruptvoidsoftware_trap20(void){for(;;);}
  76. __interruptvoidsoftware_trap19(void){for(;;);}
  77. __interruptvoidsoftware_trap18(void){for(;;);}
  78. __interruptvoidsoftware_trap17(void){for(;;);}
  79. __interruptvoidsoftware_trap16(void){for(;;);}
  80. __interruptvoidsoftware_trap15(void){for(;;);}
  81. __interruptvoidsoftware_trap14(void){for(;;);}
  82. __interruptvoidsoftware_trap13(void){for(;;);}
  83. __interruptvoidsoftware_trap12(void){for(;;);}
  84. __interruptvoidsoftware_trap11(void){for(;;);}
  85. __interruptvoidsoftware_trap10(void){for(;;);}
  86. __interruptvoidsoftware_trap09(void){for(;;);}
  87. __interruptvoidsoftware_trap08(void){for(;;);}
  88. __interruptvoidsoftware_trap07(void){for(;;);}
  89. __interruptvoidsoftware_trap06(void){for(;;);}
  90. __interruptvoidsoftware_trap05(void){for(;;);}
  91. __interruptvoidsoftware_trap04(void){for(;;);}
  92. __interruptvoidsoftware_trap03(void){for(;;);}
  93. __interruptvoidsoftware_trap02(void){for(;;);}
  94. __interruptvoidsoftware_trap01(void){for(;;);}
  95. #pragmaCODE_SEGDEFAULT
  96. /***********************************************************************
  97. *INTERRUPTVECTORS
  98. ***********************************************************************/
  99. typedefvoid(*neartIsrFunc)(void);
  100. consttIsrFunc_vect[]@0xFF80={/*Interrupttable*/
  101. software_trap63,/*63RESERVED*/
  102. software_trap62,/*62RESERVED*/
  103. software_trap61,/*61RESERVED*/
  104. software_trap60,/*60RESERVED*/
  105. software_trap59,/*59RESERVED*/
  106. software_trap58,/*58RESERVED*/
  107. software_trap57,/*57PWMEmergencyShutdown*/
  108. software_trap56,/*56PortPInterrupt*/
  109. software_trap55,/*55CAN4transmit*/
  110. software_trap54,/*54CAN4receive*/
  111. software_trap53,/*53CAN4errors*/
  112. software_trap52,/*52CAN4wake-up*/
  113. software_trap51,/*51CAN3transmit*/
  114. software_trap50,/*50CAN3receive*/
  115. software_trap49,/*49CAN3errors*/
  116. software_trap48,/*48CAN3wake-up*/
  117. software_trap47,/*47CAN2transmit*/
  118. software_trap46,/*46CAN2receive*/
  119. software_trap45,/*45CAN2errors*/
  120. software_trap44,/*44CAN2wake-up*/
  121. software_trap43,/*43CAN1transmit*/
  122. software_trap42,/*42CAN1receive*/
  123. software_trap41,/*41CAN1errors*/
  124. software_trap40,/*40CAN1wake-up*/
  125. software_trap39,/*39CAN0transmit*/
  126. software_trap38,/*38CAN0receive*/
  127. software_trap37,/*37CAN0errors*/
  128. software_trap36,/*36CAN0wake-up*/
  129. software_trap35,/*35FLASH*/
  130. software_trap34,/*34EEPROM*/
  131. software_trap33,/*33SPI2*/
  132. software_trap32,/*32SPI1*/
  133. software_trap31,/*31IICBus*/
  134. software_trap30,/*30BDLC*/
  135. software_trap29,/*29CRGSelfClockMode*/
  136. software_trap28,/*28CRGPLLlock*/
  137. software_trap27,/*27PulseAccumulatorBOverflow*/
  138. software_trap26,/*26ModulusDownCounterunderflow*/
  139. software_trap25,/*25PortH*/
  140. software_trap24,/*24PortJ*/
  141. software_trap23,/*23ATD1*/
  142. software_trap22,/*22ATD0*/
  143. SCI1_ISR,/*21SC11*/
  144. SCI0_ISR,/*20SCI0*/
  145. software_trap19,/*19SPI0*/
  146. software_trap18,/*18Pulseaccumulatorinputedge*/
  147. software_trap17,/*17PulseaccumulatorAoverflow*/
  148. software_trap16,/*16EnhancedCaptureTimerOverflow*/
  149. software_trap15,/*15EnhancedCaptureTimerchannel7*/
  150. software_trap14,/*14EnhancedCaptureTimerchannel6*/
  151. software_trap13,/*13EnhancedCaptureTimerchannel5*/
  152. software_trap12,/*12EnhancedCaptureTimerchannel4*/
  153. software_trap11,/*11EnhancedCaptureTimerchannel3*/
  154. software_trap10,/*10EnhancedCaptureTimerchannel2*/
  155. software_trap09,/*09EnhancedCaptureTimerchannel1*/
  156. software_trap08,/*08EnhancedCaptureTimerchannel0*/
  157. OSTickISR,/*07RealTimeInterrupt*/
  158. software_trap06,/*06IRQ*/
  159. software_trap05,/*05XIRQ*/
  160. OSCtxSw,/*04SWI-BreakpointonHCS12SerialMon.*/
  161. software_trap03,/*03Unimplementedinstructiontrap*/
  162. software_trap02,/*02COPfailurereset*/
  163. software_trap01//,/*01Clockmonitorfailreset*/
  164. //_Startup/*00Resetvector*/
  165. };

跋文:
当我完结悉数移植作业并测试经过后,我又从头审视了一遍整个移植进程,发现走了许多弯路。这些弯路根本都是由于我对C编译器的特性,尤其是内联汇编的处理不熟悉形成的。比方中止处理函数,其实能够直接写到 OS_CPU_C.C 中。就能够省掉了 vector.c 文件了。其实我一开始也是这样做的,可是开始的中止处理函数混合了C 查办和汇编查办,发生了各种莫名美妙的过错。比方下面的RTI中止处理函数代码:

  1. interruptVectorNumber_VrtivoidOSTickISR(void)
  2. {
  3. OSIntNesting++;//4~,NotifyuC/OS-IIaboutISR
  4. if(OSIntNesting==1)
  5. {
  6. __asm
  7. {
  8. ldxOSTCBCur//3~,OSTCBCur->OSTCBStkPtr=StackPointer
  9. sts0,x//3~,}
  10. }
  11. }
  12. CRGFLG_RTIF=1;//clearinterruptflag.
  13. OSTimeTick();//6~+,CalluC/OS-IIstickupdatingfunction
  14. OSIntExit();//6~+,NotifyuC/OS-IIaboutendofISR
  15. }

比照后来的汇编代码,其实现已离成功很近了,只需将其间的C 查办悉数用汇编写成来功德圆满了:

  1. interruptVectorNumber_VrtivoidOSTickISR(void)
  2. {
  3. __asm
  4. {
  5. incOSIntNesting
  6. ldabOSIntNesting
  7. cmpb#$01
  8. bneOSTickISR1
  9. ldxOSTCBCur
  10. sts0,x
  11. OSTickISR1:
  12. BSET_CRGFLG,#128
  13. jsrOSTimeTick
  14. jsrOSIntExit
  15. }
  16. }

其他的代码也相同,都这样改写后就彻底不需求 vector.c 文件了。但这儿仍是将这些本能够省掉掉的代码保存下来了,是想记载下一条实在的探究旅程。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/bandaoti/zhizao/264132.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部