1. 總線架構
以互聯網大容量產品爲例,整體總線架構如下圖:
其中,
DCode,也即D-bus,顧名思義就是數據總線。它通過總線矩陣連接Contex-M3和閃存存儲器的數據接口,可用於常量加載(我的理解是RO DATA的訪問)和調試訪問(如何應用,尚未得知)。
ICode,指令總線,實現Contex-M3和閃存存儲器的指令接口的連接,用於程序RO CODE(.text)的讀取。
System,系統總線,實現外設總線到總線矩陣的連接。對內置SRAM就是通過系統總線訪問的。
DMA總線,連接DMA硬件的AHB主控接口到總線矩陣。
總線矩陣:DMA可以通過DMA總線訪問SRAM、閃存和外設。我們知道Contex-M3同樣可以通過DCode或者System總線訪問這些資料。爲了不讓兩者衝突,需要總線矩陣邏輯進行仲裁決斷。
AHB,通過總線矩陣和系統總線相連。再加上AHB/APB橋,構成了到外設的通道。從上圖可以看出,APB分爲兩種:APB1和APB2。這樣是爲了適應不同速率的外設,同時兼顧性能功耗的考慮。APB1的操作頻率限於36MHz,APB2操作於全速(最高72MHz)。
2. 存儲器組織
STM32F10XXX中flash,內置SRAM,片上寄存器等一起構成一個4GB的線性地址空間。數據採用小端格式存儲,即低字節位於低地址(兩低爲小端)。
下圖是片上外設寄存器的映射地址,這便是C程序中以下類型定義的來源。
<span style="font-size:12px;">#define PERIPH_BB_BASE ((u32)0x42000000)
#define SRAM_BB_BASE ((u32)0x22000000)
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)</span>
2.1 再來說一下bit-band的概念
它其實是8051就有的一個技術。它操作的是將某段地址區間的數據,把這些數據的每個bit映射到另外一個地址空間。這樣對映射後地址的訪問,就等同於映射之前bit的訪問。
Cortex™-M3存儲器映像包括兩個位段(bit-band)區。分別是:
0x2000_0000‐0x200F_FFFF(SRAM 區中的最低 1MB)
0x4000_0000‐0x400F_FFFF(片上外設區中的最低 1MB)
這兩個位段區將別名存儲器區中的每個字映射到位段存儲器區的一個位,在別名存儲區寫入一個字具有對位段區的目標位執行讀-改-寫(RCU)操作的相同效果。
在STM32F10xxx裏,外設寄存器和SRAM都被映射到一個位段區裏,這允許執行單一的位段的寫和讀操作。 下面的映射公式給出了別名區中的每個字是如何對應位帶區的相應位的:
bit_word_addr = bit_band_base + (byte_offset×32) + (bit_number×4)
其中:
所乘常數32和4是映射後的地址4字節對齊的緣故。
bit_word_addr是別名存儲器區中字的地址,它映射到某個目標位。
bit_band_base是別名區的起始地址。
byte_offset是包含目標位的字節在位段裏的序號
bit_number是目標位所在位置(0-31)
採用bit-band的優勢:
1. 直接操作bit位,加大方便的GBIO口等寄存器的控制。
2. RCU是原子操作,實現資源互斥訪問。
3. 使得代碼標書更加簡潔。
可以在C語句中運用bit-band功能。可以直接#define映射後地址區域,如:
<span style="font-size:12px;">#define DEVICE_REG0 ((volatile unsigned long *) (0x40000000))
#define DEVICE_REG0_BIT0 ((volatile unsigned long *) (0x42000000))
#define DEVICE_REG0_BIT1 ((volatile unsigned long *) (0x42000004))
*DEVICE_REG0_BIT1 = 0x1; // 通過位帶別名地址設置 bit1</span>
同時,在 GCC和 RealView MDK (即 Keil) 開發工具中,允許定義變量時手工指定其地址。
<span style="font-size:12px;">volatile unsigned long bbVarAry[7] __attribute__(( at(0x20003014) ));
volatile unsigned long* const pbbaVar= (void*)(0x22000000+0x3014*8*4);
pbbaVar[136]=1; //置位第 136號比特</span>
2.2 嵌入式閃存
結構圖如下:
在STM32F10xxx裏,可以通過BOOT[1:0]引腳選擇從主存儲塊,系統存儲器或者內置SRAM啓動程序運行。
另外,ST在生產線上往系統存儲器寫入內嵌的自舉程序,用於通過可用的串行接口對閃存存儲器進行重新編程。具體可參見