新聞中心

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

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

        作者: 時間:2016-11-20 來源:網絡 收藏
        2.2 OS_CPU_A.S

        首先是函數和全局變量的聲明。

        本文引用地址:http://www.104case.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


        然后是臨界區的相關代碼。


        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--;否則第一個雙字節會有一半溢出堆??臻g。
        (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 文件了。但這里還是將這些本可以省略掉的代碼保留下來了,是想記錄下一條真實的探索路程。



        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 五河县| 兖州市| 正蓝旗| 石门县| 蒙阴县| 建瓯市| 汉中市| 岑巩县| 黄山市| 扎囊县| 巴南区| 赤城县| 永泰县| 弋阳县| 德庆县| 秦安县| 台北市| 赤城县| 高清| 鸡东县| 兴化市| 晋中市| 大化| 天水市| 曲靖市| 宝应县| 额尔古纳市| 湖南省| 合肥市| 普安县| 吉林省| 波密县| 沈丘县| 吴堡县| 绍兴县| 吉安市| 个旧市| 泽库县| 丰原市| 肥乡县| 台安县|