概述
stm32可以外擴很大的sram,常見外部sram的初始化函數一般是c語言寫的,默認寫在main函數里面。stm32初始化首先進入匯編代碼startup_stm32f429xx.s,在匯編代碼中Reset_Handler(復位中斷服務程序)里面先調用了SystemInit,然后調用__main進行堆棧的初始化,最后才會跳轉到用戶main函數。調用SystemInit涉及到局部變量和函數調用,需要用到stack棧空間,如果我們簡單的將系統堆棧配置到外部sram,執行SystemInit時外部sram還沒有初始化,運行到這里程序就會進入hardfault卡死。
為了解決這個問題,首先可以將外部sram的初始化函數提前,放到SystemInit函數中調用,cube生成的stm32代碼已經為我們提供了這樣的接口,這樣__main就可以正確運行,然而這還沒有解決SystemInit本身執行的問題,我們需要保證SystemInit執行時使用STM32內部RAM。
具體步驟
(1).修改啟動代碼堆棧指針
在startup_stm32f429xx.s中,找到 __initial_sp這一行,改為如下內容
注意這里0x20000400 =內部主內存地址0x20000000+棧大小0x400,也就是說這個地址和Stack_Size有關,需要根據自己Stack_Size的設置來修改,這樣就強制指定了系統初始化的棧頂指針在內部內存,保證進入main函數之前的其它初始化函數調用堆棧正常使用。
(2).修改啟動代碼中堆的空間大小
注意這里的0x02000000的大小為32M,因為這里我們采用的SDRAM的芯片大小是32M,將此32M的空間全部用作堆(Heap)空間,也可以只用SDRAM芯片的一部分空間作為堆空間。
(3).添加宏定義使能DATA_IN_ExtSDRAM
在Keil軟件中的option,c/c++選項卡 define后面添加 DATA_IN_ExtSDRAM
(4).修改外部內存初始化代碼
假定外部內存初始化函數為SDRAM_Init(),修改system_stm32f4xx.c文件
找到如下內容,英文說明這個函數將在跳轉到main之前執行,可以讓外部內存被系統當做程序數據內存使用,包括堆棧,這就是關鍵了,接下來修改SystemInit_ExtMemCtl(void)函數,直接注釋掉里面的所有內容,改為如下內容
SystemInit_ExtMemCtl()函數是被SystemInit函數調用的,這樣執行完SystemInit后,再進入__main就可以初始化配置在外部內存的堆棧了。
(5).配置和使用外部內存空間
方式1
如果讓mdk自動分配內存,則打開option,target選項卡,右下角 read/write memory areas 添加內存塊,勾選RAM1,填入外部內存起始地址和大小即可
方式2
修改自定義的sct文件,添加如下字段,即可將系統堆(Heap),系統堆通過malloc函數申請容量,以及通過attribute標記為EXRAM的數據都放在外部內存
(6).編寫測試代碼查看申請系統堆的地址
cp = (char *)malloc(sizeof(char)*n);
memset(cp,0x36,sizeof(char)*n);
printf("\r\ncp_Addr=0x%x",cp);
查詢申請的堆空間的地址