<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > μC/OS-II 移植筆記 2(FreeScale 68HCS12 核單片機)

          μC/OS-II 移植筆記 2(FreeScale 68HCS12 核單片機)

          作者: 時間:2016-11-20 來源:網(wǎng)絡 收藏
          2.2 OS_CPU_A.S

          首先是函數(shù)和全局變量的聲明。

          本文引用地址:http://www.ex-cimer.com/article/201611/318814.htm

          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


          然后是臨界區(qū)的相關代碼。


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


          下面的代碼是重點部分,首先是 OSStartHighRdy 函數(shù),雖然這個函數(shù)只在 OSStart 函數(shù)中被調用一次,在之后的程序生命周期中就再也用不到了,但這次調用至關重要,決定了用戶任務是否能被調度起來。因此代碼中給出的注釋盡可能的詳細,我想看過注釋后就不需要我解釋什么了。

          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 表示這是個中斷處理函數(shù),編譯器不為之保存任何寄存器內容。 雖然 OSStartHighRdy 并不是個真正的中斷處理函數(shù),但它模擬卻模擬了中斷處理函數(shù)的行為,函數(shù)結束時調用 rti 而不是 rts 命令。

          下面是任務切換的代碼,注釋已經(jīng)足夠的詳細了,如果有不明白的地方建議將 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


          可以看到,上面兩個函數(shù)公用了大部分的函數(shù)體。上面的代碼也可以直接寫到 OS_CPU_C.C 中,不過寫成 C 函數(shù)后就不能公用函數(shù)體了。

          最后一部分是時鐘中斷程序,我使用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 函數(shù),并且網(wǎng)上流傳的大多數(shù) 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--;/*需要這么調整一下棧頂?shù)刂?,否則存的第一個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 內核一個大的區(qū)別就是 SP 指向的是實棧頂。老的68HC11的移植代碼都是 *--wstk = XXXX。移植到68HC12 內核就要改為*wstk-- = XXXX。否則會浪費掉堆棧的前兩個字節(jié)。
          (2)先要執(zhí)行 ptos--;否則第一個雙字節(jié)會有一半溢出堆??臻g。
          (3)任務的參數(shù)傳遞是通過寄存器 D 的,而不是堆棧。網(wǎng)上代碼多數(shù)是:

          [cpp]view plaincopy
          1. *wstk--=(INT16U)p_arg;
          2. *wstk--=(INT16U)task;


          這樣參數(shù)是傳遞不進來的,只有像我的代碼中這樣寫才是正確的。
          (4)代碼中 *wstk-- = (INT16U)task; 重復了兩遍,千萬別以為這是我的筆誤。堆棧中先存的(INT16U)task實際上是 task 函數(shù)的返回地址。雖然 μC/OS-II 要求任務不能返回,但是作為 C 語言的調用約定,在調用一個 C 函數(shù)之前要將 C 函數(shù)的返回地址先入棧。因此我將 task 的地址重復了兩次,實際上第一的地址是什么都不重要,因為程序運行中覺得不會用到。甚至不要這行也行,還能節(jié)省堆棧中兩個字節(jié)的空間。不過我還是選擇了保留這行,使其看起來更加符合 C 語言的調用規(guī)范。

          除此之外,OS_CPU_C.C 還包括一系列的 Hook 函數(shù):

          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 版本中還沒出現(xiàn),我在這里這樣寫是為了移植到后面版本時更輕松。

          至此,移植代碼就基本完成了。不過這樣還不能運行,因為兩個中斷處理函數(shù)(OSCtxSw和OSTickISR)還沒有和對應的中斷產(chǎn)生關聯(lián)。將這二者關聯(lián)起來的方法有幾種,比如直接在 PRM 文件中制定,我用了種比較笨的辦法,從網(wǎng)上找了個 vector.c 文件,雖然看起來不是很優(yōu)雅,但確實是正確的代碼。


          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. };



          后記:
          當我完成全部移植工作并測試通過后,我又重新審視了一遍整個移植過程,發(fā)現(xiàn)走了許多彎路。這些彎路基本都是因為我對C編譯器的特性,尤其是內聯(lián)匯編的處理不熟悉造成的。比如中斷處理函數(shù),其實可以直接寫到 OS_CPU_C.C 中。就可以省略了 vector.c 文件了。其實我一開始也是這樣做的,但是最初的中斷處理函數(shù)混合了C 語句和匯編語句,產(chǎn)生了各種莫名奇妙的錯誤。比如下面的RTI中斷處理函數(shù)代碼:


          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. }


          對比后來的匯編代碼,其實已經(jīng)離成功很近了,只要將其中的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 文件了。但這里還是將這些本可以省略掉的代碼保留下來了,是想記錄下一條真實的探索路程。



          評論


          相關推薦

          技術專區(qū)

          關閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();