新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 五大ARM存儲器之一:協處理器CP15

        五大ARM存儲器之一:協處理器CP15

        作者: 時間:2016-11-20 來源:網絡 收藏
        ARM存儲系統有非常靈活的體系結構,可以適應不同的嵌入式應用系統的需要。ARM存儲器系統可以使用簡單的平板式地址映射機制(就像一些簡單的單片機一樣,地址空間的分配方式是固定的,系統中各部分都使用物理地址),也可以使用其他技術提供功能更為強大的存儲系統。比如:

          · 系統可能提供多種類型的存儲器件,如FLASH、ROM、SRAM等;

        本文引用地址:http://www.104case.com/article/201611/318977.htm

          · Caches技術;

        · 寫緩存技術(write buffers);

          · 虛擬內存和I/O地址映射技術。

        大多數的系統通過下面的方法之一實現對復雜存儲系統的管理。

        · 使能Cache,縮小處理器和存儲系統速度差別,從而提高系統的整體性能。

           · 使用內存映射技術實現虛擬空間到物理空間的映射。這種映射機制對嵌入式系統非常重要。通常嵌入式 系統程序存放在ROM/FLASH中,這樣系統斷電后程序能夠得到保存。但是通常ROM/FLASH與SDRAM相比,速度 慢很多,而且基于ARM的嵌入式系統中通常把異常中斷向量表放在RAM中。利用內存映射機制可以滿足這種需 要。在系統加電時,將ROM/FLASH映射為地址0,這樣可以進行一些初始化處理;當這些初始化處理完成后將 SDRAM映射為地址0,并把系統程序加載到SDRAM中運行,這樣很好地滿足嵌入式系統的需要。

          · 引入存儲保護機制,增強系統的安全性。

          · 引入一些機制保證將I/O操作映射成內存操作后,各種I/O操作能夠得到正確的結果。在簡單存儲系統中, 不存在這樣問題。而當系統引入了Cache和write buffer后,就需要一些特別的措施。

        在ARM系統中,要實現對存儲系統的管理通常是使用協處理器CP15,它通常也被稱為系統控制協處理器(System Control Coprocessor)。

        ARM的存儲器系統是由多級構成的,每級都有特定的容量和速度。圖1顯示了存儲器的層次結構。

        ① 寄存器。處理器寄存器組可看作是存儲器層次的頂層。這些寄存器被集成在處理器內核中,在系統中提供最快的存儲器訪問。典型的ARM處理器有多個32位寄存器,其訪問時間為ns量級。

          

        圖1 存儲器的層次結構

        ② 緊耦合存儲器TCM。為彌補Cache訪問的不確定性增加的存儲器。TCM是一種快速SDRAM,它緊挨內核,并且保證取指和數據操作的時鐘周期數,這一點對一些要求確定行為的實時算法是很重要的。TCM位于存儲器地址映射中,可作為快速存儲器來訪問。

         ?、?片上Cache存儲器的容量在8KB~32KB之間,訪問時間大約為10ns。

          ④ 高性能的ARM結構中,可能存在第二級片外Cache,容量為幾百KB,訪問時間為幾十ns。

          ⑤ DRAM。主存儲器可能是幾MB到幾十MB的動態存儲器,訪問時間大約為100ns。

         ?、?后援存儲器,通常是硬盤,可能從幾百MB到幾個GB,訪問時間為幾十ms。

          注意TCM和SRAM在技術上相同,但在結構排列上不同;TCM在片上,而SRAM在板上。

        協處理器CP15

          ARM處理器支持16個協處理器。在程序執行過程中,每個協處理器忽略屬于ARM處理器和其他協處理器的指令。當一個協處理器硬件不能執行屬于它的協處理器指令時,將產生一個未定義指令異常中斷,在該異常中斷處理程序中,可以通過軟件模擬該硬件操作。比如,如果系統不包含向量浮點運算器,則可以選擇浮點運算軟件模擬包來支持向量浮點運算。

        CP15,即通常所說的系統控制協處理器(System Control Coprocesssor)。它負責完成大部分的存儲系統管理。除了CP15外,在具體的各種存儲管理機制中可能還會用到其他的一些技術,如在MMU中除CP15外,還使用了頁表技術等。

          在一些沒有標準存儲管理的系統中,CP15是不存在的。在這種情況下,針對協處理器CP15的操作指令將被視為未定義指令,指令的執行結果不可預知。

          CP15包含16個32位寄存器,其編號為0~15。實際上對于某些編號的寄存器可能對應多個物理寄存器,在指令中指定特定的標志位來區分這些物理寄存器。這種機制有些類似于ARM中的寄存器,當處于不同的處理器模式時,某些相同編號的寄存器對應于不同的物理寄存器。

        CP15中的寄存器可能是只讀的,也可能是只寫的,還有一些是可讀可寫的。在對協處理器寄存器進行操作時,需要注意以下幾個問題。

          · 寄存器的訪問類型(只讀/只寫/可讀可寫)。

          · 不同的訪問引發的不同功能。

          · 相同編號的寄存器是否對應不同的物理寄存器。

          · 寄存器的具體作用。

        CP15寄存器訪問指令

          通常對協處理器CP15的訪問使用以下兩種指令。

          MCR:將ARM寄存器的值寫入CP15寄存器中;

          MRC:將CP15寄存器的值寫入ARM寄存器中。

          注意通過協處理器訪問指令CDP、LDC和STC指令對協處理器CP15進行訪問將產生不可預知的結果。

          其中,CDP為協處理器數據操作指令,這個指令初始化一些與協處理器相關的操作;

          LDC為一個或多個字的協處理器數據讀取指令,此指令從存儲器讀取數據到指定的協處理器中;

          STC為一個或多個32位字的協處理器數據寫入指令,此指令初始化一個協處理器的寫操作,從給定的協處理器把數據傳送到存儲器中。

        指令MCR和MRC指令訪問CP15寄存器使用通用語法。

          語法格式為:

          MCR{《cond》} p15,《opcode1=0》,《Rd》,《CRn》,《CRm》{,《opcode2》}

          MRC{《cond》} p15,《opcode1=0》,《Rd》,《CRn》,《CRm》{,《opcode2》}

          其中:

          《cond》為指令的執行條件。當《cond》條件域為空時,指令無條件執行;

          《opcode1》在標準的MRC指令中,為協處理器的《opcode1》,即操作數1。對于CP15來說,此操作數恒為0,即0b000。當針對CP15的MRC指令中《opcode1》不為0時,指令的操作結果不可預知;

          《Rd》為ARM寄存器,在ARM和協處理器交換數據時使用。在MRC指令中作為目的寄存器,在MCR中作為源寄存器。

          注意r15不能作為ARM寄存器出現在MRC或MCR指令中,如果r15作為《Rd》出現在這里,那么指令的執行結果不可預知。

          《CRn》是CP15協處理器指令中用到的主要寄存器。在MRC指令中為源寄存器,在MCR中為目的寄存器。CP15協處理器的寄存器c0、c1、…、c15均可出現在這里。

          《CRm》是附加的協處理器寄存器,用于區分同一個編號的不同物理寄存器和訪問類型。當指令中不需要提供附加信息時,將《CRm》指定為C0,否則指令的操作結果不可預知。

          《opcode2》提供附加信息,用于區分同一個編號的不同物理寄存器,當指令中沒有指定附加信息時,省略《opcode2》或者將其指定為0,否則指令的操作結果不可預知。

          MCR和MRC指令只能操作在特權模式下,如果處理器運行在用戶模式,指令的執行結果不可預知。

          注意在用戶模式下,如果要訪問系統控制協處理器,通常的做法是由操作系統提供SWI軟中斷調用來完成系統模式的切換。由于不同型號的ARM處理器對此管理差別很大,所以建議用戶在應用時將SWI作為一個獨立的模塊來管理并向上提供通用接口,以屏蔽不同型號處理器之間的差異。

          例1給出了一個典型的利用SWI進行模式切換的例子。

        【例1】

          典型的在SWI中進行模式切換的例子。利用此例,調用SWI 0來完成系統模式切換。

          EHT_SWI

          LDR sp,=EHT_Exception_Stack ;更新SWI堆棧指針

          ADD sp,sp,#EXCEPTION_SIZE ;得到棧頂指針

          STMDB sp!,{r0-r2,lr} ;保存程序中用到的寄存器

        MRS r0,SPSR ;得到SPSR

          STMDB sp!,{r0} ;保持SPSR

          LDR r0,[lr,#-4] ;計算SWI指令地址

          BIC r0,r0,#0xFF000000 ;提取中斷向量號

          CMP r0,#MAX_SWI ;檢測中斷向量范圍

          LDRLS pc,[pc,r0,LSL #2] ;如果在范圍內,跳轉到軟中斷向量表

          B EHT_SWI_Exit ;為定義的SWI指令出口

          EHT_Jump_Table

          DCD EHT_SU_Switch

          DCD EHT_Disable_Interrupts

        ;*********************************************************************************

          ;用戶可在此添加更多的自定義軟中斷,在此SWI0作為系統保留的軟中斷,調用例程EHT_SU_Switch,來進行模式切換

         ??;*********************************************************************************

          EHT_SU_Switch

          MMU_DISABLE ;轉換前禁用MMU

          LDMIA sp!,{r0} ;從堆棧中取出SPSR

          BIC r0,r0,#MODE_MASK ;清除模式位

          ORR r0,r0,#SYS_MODE ;設置程序狀態字的supper模式位

          STMDB sp!,{r0} ;從新將SPSR放入堆棧

          B EHT_SWI_Exit

          EHT_Disable_Interrupts

          LDMIA sp!,{r0} ;從堆棧中讀出SPSR

          ORR r0,r0,#LOCKOUT ;禁止中斷

          STMDB sp!,{r0} ;存儲SPSR到中斷

          ; B EHT_SWI_Exit

          EHT_SWI_Exit

          LDMIA sp!,{r0} ;從堆棧中讀出SPSR

          MSR SPSR_cf,r0 ;將SPSR放入SPSR_cf

          LDMIA sp!,{r0-r2,pc}^ ;寄存器出棧并返回

          END

        1.2 CP15中的寄存器

          表1給出了CP15主要寄存器的功能和作用。

          表1 CP15寄存器

        寄存器編號

        基本作用

        在MMU中的作用

        在PU中的作用

        0

        ID編碼(只讀)

        ID編碼和cache類型

        1

        控制位(可讀寫)

        各種控制位

        2

        存儲保護和控制

        地址轉換表基地址

        Cachability的控制位

        3

        存儲保護和控制

        域訪問控制位

        Bufferablity控制位

        4

        存儲保護和控制

        保留

        保留

        5

        存儲保護和控制

        內存失效狀態

        訪問權限控制位

        6

        存儲保護和控制

        內存失效地址

        保護區域控制

        7

        高速緩存和寫緩存

        高速緩存和寫緩存控制

        8

        存儲保護和控制

        TLB控制

        保留

        9

        高速緩存和寫緩存

        高速緩存鎖定

        10

        存儲保護和控制

        TLB鎖定

        保留

        11

        保留

        12

        保留

        13

        進程標識符

        進程標識符

        14

        保留

        15

        因不同設計而異

        因不同設計而異

        因不同設計而異

        1.3 寄存器c0
        寄存器c0包含的是ARM本身或芯片生產廠商的一些標識信息。當使用MRC指令讀c0寄存器時,根據第二個操作碼opcode2的不同,讀出的標識符也是不同的。操作碼與標識符的對應關系如表2所示。寄存器c0是只讀寄存器,當用MCR指令對其進行寫操作時,指令的執行結果不可預知。
        表2 操作碼和標識符的對應關系

        opcode_2編碼

        對應的標識符號寄存器

        0b000

        主標識符寄存器

        0b001

        cache類型標識符寄存器

        其他

        保留

        在操作碼opcode2的取值中,主標識符(opcode2=0)是強制定義的,其他標識符由芯片的生產廠商定義。如果操作碼opcode2指定的值未定義,指令將返回主標識符。其他標識符的值應與主標識符的值不同,可以由軟件編程來實現,同時讀取主標識符和其他標識符,并將兩者的值進行比較。如果兩個標識符值相同,說明未定義該標識符;如果兩個標識符值不同,說明定義了該標識符,并且得到該標識符的值。

        (1)主標識符寄存器

          當協處理器指令對CP15進行操作,并且操作碼opcode=2時,處理器的主標識符將被讀出。從主標識符中,可以確定ARM體系結構的版本型號。同時也可以參考由芯片生產廠商定義的其他標識符,來獲得更詳細的信息。

          在主標識信息中,bit[15:12]區分了不同的處理器版本:

          · 如果bit[15:12]為0x0,說明處理器是ARM7之前的處理器;

          · 如果bit[15:12]為0x7,說明處理器為ARM7處理器;

          · 如果bit[15:12]為其他值,說明處理器為ARM7之后的處理器。

          對于ARM7之后的處理器,其標識符的編碼格式如圖2所示。

          其中各部分的編碼含義說明如下。

          bit[3:0]:包含生產廠商定義的處理器版本型號。

          bit[15:4]:生產廠商定義的產品主編號,可能的取值為0x0~0x7。

          bit[19:16]:ARM體系的版本號,可能的取值如表3(其他值由ARM公司保留將來使用)所示。

          

          圖2 ARM7之后處理器標識符編碼

        表3 bit[19:16]與ARM版本號

         可能的取值 版 本 號

          0x1 ARM體系版本4

          0x2 ARM體系版本4T

          0x3 ARM體系版本5

          0x4 ARM體系版本5T

          0x5 ARM體系版本5TE

        bit[23:20]:生產廠商定義的產品子編號。當產品主編號相同時,使用子編號區分不同的產品子類,如產品中不同的cache的大小。

        bit[31:24]:生產廠商的編號現已定義的如表4所示。其他的值ARM公司保留將來使用。

         表4 bit[31:24]值與ARM生產廠商

          可能的取值 ARM芯片生產廠商

          0x41 (A)ARM公司

          0x44 (D)Digital Equipment

          0x69 (i)Intel公司

         對于ARM7系統的處理器,其主標識符的編碼如圖3所示。

          

          圖3 ARM7處理器標識符編碼

         其中各部分的含義說明如下。

          bit[3:0]:包含生產廠商定義的處理器版本型號。

          bit[15:4]:生產廠商定義的產品主編號,其最高4位的值為0x7。

          bit[22:16]:生產商定義的產品子編號。當產品的主編號相同時,使用子編號區分不同的產品子類,如產品中不同的產品子類、不同產品中高速緩存的大小。

          bit[23]:ARM7處理器支持下面兩種ARM體系的版本號。0x0代表ARM體系版本3;0x1代表ARM體系版本4T。

          bit[31:24]:生產廠商的編號已定義的如表5所示,其他的值ARM公司保留將來使用。

          表5 bit[31:24]值與ARM生產廠商

          可能的取值ARM芯片生產廠商

          0x41(A)ARM公司

          0x44(D)Digital Equipment

          0x69(i)Intel公司

          對于ARM7系統的處理器,其主標識符的編碼如圖4所示。

          

          圖4 ARM7之前處理器標識符編碼

          其中各部分的含義說明如下。

          bit[3:0]:包含生產廠商定義的處理器版本型號。

          bit[31:4]:處理器標識符及其含義如表6所示。

          表6 ARM之后處理器標識符與含義

          處理器標識符含 義

          0x4156030ARM3(體系版本2)

          0x4156060ARM600(ARM體系版本3)

          0x4156061ARM610(ARM體系版本3)

          0x4156062ARM620(ARM體系版本3)

        (2)Cache類型標識符寄存器

          如前所述,對于指令MRC來說,當協處理器寄存器為r0,而第二操作數opcode2為0b001時,指令讀取值為Cache類型,即可以用下面的指令將處理器的Cache類型標識符寄存器的內容讀取到寄存器r0中。

          MRC P15,0,r0,c0,c0,1

          Cache類型標識符定義了關于Cache的信息,具體內容如下所述。

          · 系統中的數據Cache和指令Cache是分開的還是統一的。

          · Cache的容量、塊大小以及相聯特性。

          · Cache類型是直(write-through)寫還是回寫(write-back)。

          · 對于回寫(write-back)類型的Cache如何有效清除Cache內容。

          · Cache是否支持內容鎖定。

          Cache類型標識符寄存器各控制字段的含義編碼格式如圖5所示。

          

          圖5 Cache屬性寄存器標識符編碼格式

        其中各控制字段的含義說明如下。

          屬性字段(ctype):指定沒有在S位、數據Cache相關屬性位、指令Cache相關屬性類中指定的屬性,其具體編碼參見表7。

          表7 Cache類型標識符寄存器屬性字段含義

          編 碼 Cache類型 Cache內容清除方法 Cache內容鎖定方法

          0b0000 直寫 不需要內容清除 不支持

          0b0001 回寫 數據塊讀取 不支持

          0b0010 回寫 由寄存器定義 不支持

          0b0110 回寫 由寄存器定義 支持格式A,見后

          0b0111 回寫 由寄存器定義 支持格式B,見后

          S位:定義系統中的數據Cache和指令Cache是分開的還是統一的。如果S=0,說明指令Cache和數據Cache是統一的,如果S=1,則說明數據Cache和指令Cache是分離的。

          數據Cache相關屬性:定義了數據Cache容量、行大小和相聯(associativity)特性(如果S≠0)。

          指令Cache相關屬性:定義了指令Cache容量、行大小和相聯(associativity)特性(如果S≠0)。

          數據Cache相關屬性和指令Cache相關屬性分別占用控制字段[23:12]和[11:0],它們的結構相同,圖6以指令Cache為例,顯示了編碼結構。

         

          圖6 指令Cache編碼結構

          其中,各部分的含義說明如下。

          bit[11:9]:保留用于將來使用。

          bit[8:6]:定義Cache的容量,其編碼格式及含義如表8所示。

        表8 類型標識符寄存器控制字段bit[8:6]含義

          編 碼 M=0時的含義 M=1時的含義

          0b000 0.5KB 0.75KB

          0b00 11KB 1.5KB

          0b010 2KB 3KB

          0b011 4KB 6KB

          0b100 8KB 12KB

          0b101 16KB 24KB

          0b110 32KB 48KB

          0b111 64KB 96KB

          bit[1:0]:定義Cache的塊大小,其編碼格式及含義如表9所示。

        表9 類型標識符寄存器控制字段bit[1:0]含義

          編 碼 Cache塊大小

          0b00 2個字(8字節)

          0b01 4個字(16字節)

          0b10 8個字(32字節)

          0b11 16個字(64字節)

         bit[5:3]:定義了Cache的相聯屬性,其編碼格式及含義如表10所示。

          表10 類型標識符寄存器控制字段bit[5:3]含義

        編 碼 M=0時的含義 M=1時的含義

        0b000 1路相聯 (直接映射)沒有Cache

          0b001 2路相聯 3路相聯

          0b010 4路相聯 6路相聯

          0b011 8路相聯 12路相聯

          0b1001 6路相聯 24路相聯

          0b101 32路相聯 48路相聯

          0b110 64路相聯 96路相聯

          0b111 128路相聯 192路相聯

        1.4 寄存器c1

          CP15中的寄存器c1包括以下控制功能:

          · 禁止/使能MMU以及其他與存儲系統有關的功能;

          · 配置存儲系統以及ARM處理器中相關的工作。

          注意在寄存器c1中包含了一些沒有使用的位,這些位在將來可能被擴展其他功能時使用。因此為了編寫代碼在將來更高版本的ARM處理器中仍可以使用,在修改寄存器c1中的位時應該使用“讀取-修改特定位-寫入”的操作序列。

        當對寄存器c1進行讀操作時,指令中CRm和opcode2的值將被處理器忽略,所以要人工將其置位為0。

          例2用MRC/MCR指令將協處理器寄存器c1的值進行讀取和寫入。

        【例2】

          MRC P15,0,r0,c1,0,0 ;將寄存器c1的值讀取到ARM寄存器r0中

          MCR P15,0,r0,c1,0,0 ;將ARM寄存器r0的值寫入寄存器c1

          圖7顯示了寄存器c1的編碼格式。

          

          圖7 寄存器c1編碼格式

          寄存器c1各控制字段的含義如表11所示。

          表11 寄存器c1中各控制位字段的含義

          C1中的控制位含 義

          M(bit[0])禁止/使能MMU或者MPU

          0:禁止MMU或者MPU

          1:使能MMU或者MPU

          如果系統中沒有MMU或者MPU,讀取時該位返回0,寫入時忽略

          A(bit[1])對于可以選擇是否支持內存訪問時地址對齊檢查的系統,本位禁止/使能地址對齊檢查功能

          0:禁止地址對齊檢查功能

          1:使能地址對齊檢查功能

          對寄存器進行寫操作時,忽略該位

          C(bit[2])當數據Cache和指令Cache分開時,本控制位禁止/使能數據Cache。

          當數據Cache和指令Cache統一時,該控制位禁止/使能整個Cache

          0:禁止Cache

          1:使能Cache

          如果系統中不含Cache,讀取時該位返回0,寫入時忽略

          當系統中Cache不能禁止時,讀取返回1,寫入時忽略

          W(bit[3])禁止/使能寫緩存

          0:禁止寫緩存

          1:使能寫緩存

          如果系統中不含寫緩存,讀取時該位返回0,寫入時忽略

          當系統中的寫緩存不能禁止時,讀取時該位返回0,寫入時忽略

          P(bit[4])對于向前兼容26位ARM處理器,本控制位控制PRGC32控制信號

          0:異常中斷處理程序進入32位地址模式

          1:異常中斷處理程序進入26位地址模式

          如果系統不支持向前兼容26位地址,讀取該位時返回1,寫入時被忽略

          D(bit[5])對于向前兼容26位ARM處理器,本控制位控制DATA32控制信號

          0:禁止26位地址異常檢查

          1:使能26位地址異常檢測

          如果系統不支持向前兼容26位地址,讀取該位時返回1,寫入時被忽略

          L(bit[6])對于ARMv3及以前版本,本控制位可以控制處理器的中止模式

          0:選擇早期中止模式

          1:選擇后期中止模式

          對于以后的處理器讀取該位時返回1,寫入時忽略

          B(bit[7])對于存儲系統同時支持大/小端(big-endian/little-endian)的ARM處理器,該控制位配置系統使用哪種內存模式

          0:使用小端(little-endian)

          1:使用大端(big-endian)

          對于只支持小端(little-endian)的系統,讀取時該位返回0,寫入時忽略

          對于只支持大端(big-endian)的系統,讀取時該位返回1,寫入時忽略

          S(bit[8])支持MMU的存儲系統中,本控制位用作系統保護

          R(bit[9])支持MMU的存儲系統中,本控制位用作ROM保護

          F(bit[10])本控制位由生產廠商定義

          Z(bit[11])對于支持跳轉預測的ARM系統,本控制位禁止/使能跳轉預測功能

          0:禁止跳轉預測功能

          1:使能跳轉預測功能

          對于不支持跳轉預測的ARM系統,讀取時該位返回0,寫入時忽略

          I(bit[12])當數據Cache和指令Cache是分開的,本控制位禁止/使能指令Cache

          0:禁止指令Cache

          1:使能指令Cache

          如果系統中使用統一的指令Cache和數據Cache或者系統中不含Cache,讀取該位時返回0,寫入時忽略該位

          當系統中的指令Cache不能禁止時,讀取該位返回1,寫入時忽略該位

          V(bit[13])支持高端異常向量表的系統中,本控制位控制向量表的位置

          0:選擇0x00000000~0x0000001c

          1:選擇0Xffff0000~0xffff001c

          對于不支持高端中斷向量表的系統,讀取時返回0,寫入時忽略

          RR(bit[14])如果系統中Cache的淘汰算法可以選擇的話,本控制位選擇淘汰算法

          0:選擇常規的淘汰算法,如隨機淘汰算法

          1:選擇預測性的淘汰算法,如輪轉(round-robin)淘汰算法

          如果系統中淘汰算法不可選擇,寫入該位時被忽略,讀取該位時,根據其淘汰算法是否可以比較簡單地預測最壞情況返回1或者0

          L4(bit[15])ARM版本5及以上的版本中,本控制位可以提供兼容以前的ARM版本的功能

          0:保持當前ARM版本的正常功能

          1:對于一些根據跳轉地址的bit[0]進行狀態切換的指令,忽略bit[0],不進行狀態切換,保持和以前ARM版本兼容

          此控制位可以影響以下指令:LDM、LDR和POP

          對于ARM版本5以前的處理器,該位沒有使用,應作為UNP/SBZP

          對于ARM版本5以后的處理器,如果不支持向前兼容的屬性,讀取時該位返回0,寫入時忽略

          Bit(bit[31:16])這些位保留將來使用,應為UNP/SBZP




        評論


        技術專區

        關閉
        主站蜘蛛池模板: 咸宁市| 全椒县| 东台市| 浏阳市| 高邮市| 高尔夫| 青浦区| 淅川县| 辽中县| 通化县| 渑池县| 昂仁县| 饶阳县| 肃宁县| 磴口县| 盱眙县| 土默特左旗| 兴海县| 湟源县| 鄂伦春自治旗| 梁平县| 绵阳市| 肥西县| 城步| 巴南区| 乌拉特前旗| 凤凰县| 桓仁| 布拖县| 宁德市| 时尚| 临颍县| 芒康县| 郯城县| 印江| 克山县| 罗甸县| 平凉市| 湖口县| 玉山县| 封开县|