1.存儲器,從例子說起
存儲器讀寫,cpu與芯片同步等等都需要參考設備的讀寫時序,並通過參考cpu系統時鍾,給出合理的讀寫周期。
這里以stm32f103zeT6讀寫外部CSRAM為例子加以說明。
選用用的CSRAM芯片的讀寫模式為同步非復用,頻率為36MHz,芯片掛在cpu的FSMC的BANK1 SRAM4區,其同步非復用
模式就不多講,具體參考《STM32F103ZET6》p51~p52。至於這個36MHz則需要進行對FSMC的讀寫時序進行控制。如何
控制呢?網上很多資料在這里都沒有詳細的說明,估計是很多網友覺得這個比較容易吧。但是當時我真是被這個問題
給搞的半死不活。后來沉下心來悉心研究了一段時間,終於知道是怎么配置這個36MHz了。
首先需要明確的是,stm32f10x固件庫提供了簡便的FSMC配置過程,我們可以利用一個結構體就進行配置,而不用
對具體的寄存器進行一位一位的填寫。具體的配置如下:
FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
FSMC_NORSRAMTimingInitTypeDef FSMC_NORSRAMTimingInitStructure;
//
FSMC_NORSRAMTimingInitStructure.FSMC_AddressSetupTime = 1;
FSMC_NORSRAMTimingInitStructure.FSMC_AddressHoldTime = 0;
FSMC_NORSRAMTimingInitStructure.FSMC_DataSetupTime = 2;
FSMC_NORSRAMTimingInitStructure.FSMC_BusTurnAroundDuration = 0; //總線恢復時間-19:16
/*系統選用PLL作為時鍾輸出源,而PLL頻率為72MHz,CRAM讀寫頻率為36MHz,所以采用2分頻*/
FSMC_NORSRAMTimingInitStructure.FSMC_CLKDivision = 1; //bit-23:20,分頻比為1,則存儲器讀寫周期為 1/2 SYSCLK
FSMC_NORSRAMTimingInitStructure.FSMC_DataLatency = 0; //bit27:24,(數據保持時間)對於CRAM這個參數必須為0
FSMC_NORSRAMTimingInitStructure.FSMC_AccessMode = FSMC_AccessMode_A; //訪問模式-只對FSMC_BCR1中EXTMOD位為1時起作用
//以下是配置FSMC_BCR1寄存器的各個位
FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4;
FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; //非復用MUXEN:bit1
FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_PSRAM; //MTYP-bit3:2存儲器類型
FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b; //存儲器數據總線寬度-bit5:4
FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;//BURSTEN-bit8 成組模式使能
FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable; //bit15這一位手冊里面保留...
FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low; //WAITPOL-bit9-等待信號極性
FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable; //WRAPMOD-bit10是否支持費對其成組模式
FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState; //WAITCFG-bit11
FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable; //WREN-bit12
FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable; //WAITEN-bit13-等待使能
FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable; //EXTMOD-bit14 讀寫時序不一致時設置
FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Enable; //同步寫-CBURSTRW(bit19)
FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &FSMC_NORSRAMTimingInitStructure;
FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &FSMC_NORSRAMTimingInitStructure;
FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);
/* Enable FSMC Bank1_SRAM4 Bank */
//根據PCB原理圖 CSRAM的片選信號ARM_325T_CS與PG12連接,而PG12則是FSMC_NE4
FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE);
上面的配置大部分都給出了明確的解釋,有些解釋比較書面化,如不能理解透徹還是參照《STM32F10XXX參考手冊》18章具體的
寄存器說明進行查閱。
這里只重點講下,時鍾配置,FSMC_NORSRAMTimingInitStructure.FSMC_CLKDivision = 1;這條語句,為什么配置為1?首先知
道這條命令的含義。FSMC_CLKDivision表示分頻比,而這個分頻的參考是SYSCLK,而我的初始化程序中將系統時鍾設置為72MHZ。
而這里CRAM讀寫頻率是36MHZ,所以要進行二分頻,根據手冊,二分頻則需要將FSMC_BTRx寄存器的CLKDIV(bit23~bit20)位配置為
1,即FSMC_NORSRAMTimingInitStructure.FSMC_CLKDivision = 1;這樣就ok了~
2.時鍾,從啟動程序說起
另外要說的是,我的開發工具是keil-uVersion4+rt-thread,這個非常好用,boot程序都已經寫好了的。查看其啟動程序,發現中
斷向量表的第二個向量放的是復位中斷,片段如下:
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler //復位中斷
系統一旦復位便進入復位中斷,並調用復位中斷處理程序,處理如下:
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
IMPORT SystemInit
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
我們可以看到,復位中斷處理首先調用的是SystemIint程序,再調用c庫函數_main,SystemInit也就是初始化我們的板子的運行環境,
包括時鍾,SRAM,FLASH等等,主要是時鍾這一塊。這個函數對HSE,HSI,PLL,以及系統時鍾進行配置。
這里只列出關於PLL和系統時鍾的配置
/*
硬件電路中HSE給的是12MHz(其實默認是8MHz,在stm32f10x中其取值范圍為4~16MHz,具體參考《STM32F103ZET6中文》p42)
*/
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
RCC_CFGR_PLLMULL));
//PLL 時鍾配置: PLLCLK = HSE * 6 = 72 MHz
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL6);
系統復位后,HSI被選為系統時鍾(HSI),而我們這里要選擇PLL作為SYSCLK的時鍾源,代碼如下:
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
這樣系統時鍾就是72MHz。
