STM32外部存儲器使用資料,很有參考價值
最近在學習一些gui方面的操作,并且是要跑os的;突然就發現自己的硬件平臺的內部SRAM資源不夠用了(硬件平臺:戰艦V2,stm32f103ze、外擴SRAM:1M);怎么破,那只能把外部的SRAM給用起來,不用就是浪費啊,要知道SRAM可是不便宜啊; 然后就開始借鑒了配套例程:外部SRAM的使用;通過fsmc來控制實現,外部sram可以正常使用了,但是我想嘗試下其他的方法來使用外部的SRAM: 1、 不使用attribute關鍵字來實現變量等在外部的分配,讓編譯器自己來完全支配,這樣我們就不用計算我們指定的地址是否會重合等問題; 2、 讓內部的64K SRAM、外部的1M SRAM都能用,而且讓編譯器自己處理使用; 3、 完全不使用內部的SRAM,只使用外部的SRAM
上網上查閱一些資料后,發現這個需要在2010年就有了,而且當時網友遇到的問題,我在實驗中也遇到了,關鍵是前面的帖子,也沒有很明確或是清晰的給出解釋,有的帖子給的方法是可以實現要求的,但是沒有說為什么這樣可以,所以我自己一邊實驗一邊驗證,下面把自己遇到的問題和現象做一個記錄: 1、 按照網友的方法來配置,讓編譯器自動處理SRAM的使用 (1) 實驗前提,例程采用配套例程的:37外部SRAM實驗;外部SRAM的初始化使用system_stm32f10x.c官方提供的fsmc初始化; (2) 工程配置 開啟system_stm32f10x.c中的fsmc初始化外部SRAM函數; 配置工程中SRAM的分配,注意:SRAM部分有兩塊,兩個√ 注意去掉main文件中的testsram[]的屬性定義 (3) 實驗結果,程序正常執行; 鏈接加載控制文件內容: 工程的map文件,如果對map文件不熟悉的可以自行查閱資料 是不是很明顯:一大堆的變量和數據段都分配在了內部的SRAM,只有一個.bss段分配到了外部的SRAM 0x68000000地址處,為什么會這樣,因為內部放不下了啊,另外咱們的testsram數組是沒有初始化的,你試一下在定義時就初始化,看看地址有什么變化;要理解這里的原理,就需要對分散加載文件有深入的了解了,自行查找;
2、 完全不使用內部SRAM,只使用外部SRAM (1) 工程配置和上面的實驗一致,只修改一個部分,去掉內部SRAM的配置 (2) 編譯測試 編譯是沒有任何問題的,下載驗證吧,程序跑不起來,失敗了; 在線jlink調試一下: 看到了吧,死在這里和,硬件fault了;先不解釋為什么; (3) 解決問題的過程 之前在網上搜到一些建議,但是我還是選擇了,先用jlink調試一下看看; 我在用jlink在線調試操作過程是: 第一步:單步調試,看一下是哪里進入了硬件fault;我在void SystemInit (void)函數中增加了一些調試 目的是看一下,這的fsmc對外部的SRAM的操作是否正確,結果是正確的,說明官方的fsmc初始化沒有問題,此時外部的SRAM已經可以正常使用了; 第二步:繼續單步調試,發現是在這個地方進入了硬件fault了:static void SetSysClockTo72(void)函數的退出時 到這里你在執行單步一次,就會進入硬件fault,可以確定了是在函數返回時進入硬件fault,這里先不解釋原因;
第三步:我借鑒了一下網友的建議,如下: 工程配置不用改動任何地方,還是只配置外部SRAM作為唯一的選擇,注意這里和 的配置是不一樣的,它的同時配置了外部和內部SRAM,如果這樣那他所做的操作就有些多余了,不用修改啟動文件就可以啊,就和我上面第1中的工程配置一樣啊,編譯器自己就可以處理了,不用你在修改啟動文件啊,這也是該貼下面很多網友說不用修改啟動文件中的 __initial_sp EQU 0x20000000 + Stack_Size 也可以正常運行;如果你按照下面的工程配置,再不添加啟動文件中的__initial_sp EQU 0x20000000 + Stack_Size設置,你試一下可以正常運行嗎?答案是:不能; 工程配置不變: 修改啟動文件startup_stm32f10x_hd.s中的關于棧的位置定義:等價于強制把復位后的棧指針指向內部的SRAM位置處
好了,其它一切不變,編譯下載吧
第四步:下載驗證 成功運行程序 Sct文件內容:完全是把數據段放在了外部的SRAM中; Map文件內容:所有數據段都在了外部SRAM上面;
到這里,你會有疑問吧,那我們剛才設置啟動文件中__initial_sp EQU 0x20000000 + Stack_Size的目的是啥啊,為啥在配置不變情況下,不加程序就不正常,加了就可以正常運行;后面解釋,先附張圖,自己先分析一下
這里分享一個巧合事件: 我在2、完全不使用內部SRAM,只使用外部SRAM -> (3)解決問題的過程 -> 第三步 中給出的結論:如果你按照我的工程配置,只啟用外部sram配置選項,然后你又不設置啟動文件中棧指針的設置,程序是不會正常啟動的; 有的朋友可能在實驗中會出現,即按照只使用外部sram配置,且不添加啟動文件設置,程序也正常啟動了,會說我的結論是錯的,其實結論是對的,你這個配置下能正常運行程序,完全是個巧合,下面給出巧合呈現方法: 第一步:按照下面的配置、下載、運行程序,系統正常運行,沒有任何問題
第二步:你為了推翻我的結論,在工程配置不變的情況下,只修改了啟動文件的配置,刪除了對棧指針的設置 接下來編譯、燒寫程序,進行驗證(注意這個過程前提是,你的平臺還在上次的程序下正常上電運行,這里直接按照第二步的設置編譯后,用jlink下載驗證,為了說明問題我把兩次的程序作了小處理,說明確實是連個不同的程序;上面的LCD上顯示是"WarShip ZG008",這里我們顯示是 "WarShip ZG009") 程序正常運行了,你的結論是錯的,別急:此時你把平臺的電源斷掉,在上電看看,程序能正常運行嗎,不能吧; 原因我還沒有深究,預估是,當你的平臺正常運行下,你用jilink在線下載程序時,外設的配置還會保持之前的狀態,至少fsmc的配置沒有改變,仍然可以操作外部的sram,所以你刪除了啟動文件的配置后,下載程序仍正常運行,斷電后在上電,就不行了;這里只是我的猜測,還沒有驗證;
到這里,大家是否明白了,這一切的設置,是不是都離不開一個東西:sp
3、 上面實驗現象分析 第一步:要清楚,cm3的內核是在上電后進入復位中斷處理,但是復位中斷的pc值可不是存儲在0x0000 0000 地址,而是下一個4字節的位置,0x0000 0000存儲的是sp的棧指針; 第二步:通過調試,你可以看到,程序進入上電復位中斷后,先跳轉到SystemInit()函數,調試截圖如下: LDR R0, =SystemInit BLX R0 當單步執行 BLX r0后,注意觀察左邊寄存器的變化,以及上面的匯編語句: 看到了:R13的sp值改變了,因為發生了函數調用,需要保存上下文環境,所有有PUSH的操作,切記,這里對棧進行了操作,即入棧,那么當你從systeminit()函數返回時,就要涉及到出站,這點很重要,這就是你進入硬件fault的根源;
第三步:分析上面工程配置1中的設置, 這種配置,你只改變了SRAM的配置,讓外部和內部的都啟用,讓編譯器自己解決分配問題;通過map文件你可以很清楚:編譯器把大部分的數據段都還是放在了內部SRAM中,包括主要的__initial_sp棧頂指針,只把一個很大的內部sram放不下的main.c中定義的testsram[]放在了外部sram; 此時,堆棧指針在內部sram中,所以在復位中斷中的函數調用引發的入棧、出棧可以完全正常運行;
第四步:分析上面工程2中的配置 這里分兩種情況,工程配置不變下,是否設置啟動文件的__initial_sp EQU 0x20000000 + Stack_Size; (1) 不修改啟動文件中的棧的設置 此時通過編譯后的map和調試文件可以知道: 當調用LDR R0, =SystemInit BLX R0 后會發生入棧的push操作,注意觀察此時的R13的數值:0x680F 4AF8;已經指向了外部的sram; 此處發生了push入棧操作,但是重點是此時我們還沒有對外部sram進行操作啊,試問你這個入棧能成功嗎,不能,那么里面的數值是函數返回后的下一條PC值嗎,肯定不是,是個垃圾值;然后,你調用pop操作,將一個垃圾值給了PC,那只能進入硬件fault了;
那我們找到了問題的根源,那咋改進呢:首先要明白一點,開發板硬件上電復位前,我們是無法完成STM32對外部SRAM的配置,只能上電后進行配置了才可以使用。也就是說,只有正常的硬件復位序列完成后,我們可以在Reset_Handler(復位中斷服務程序)中完成對SRAM的配置,但是在這之前,局部變量和函數調用用到的Stack棧空間,我們都得使用STM32內部SRAM,明白了這點,很重要; (2) 修改啟動文件,設置 __initial_sp EQU 0x20000000 + Stack_Size 此時,我們分析編譯后的map、調試信息: 注意觀察:此時的map中數據段信息,沒有__initial_sp的值;我們在看一下,調試時的信息: 很清晰:此時發生函數調用時,我們使用的棧指向了內部的sram控件,R13 = 0x2000 0400;所以當發生push、pop操作時,數據都是正確的,PC也可以得到正確的數值,從而按流程執行; 所以我們在啟動文件中添加的那一條:__initial_sp EQU 0x20000000 + Stack_Size很重要,就是強制把棧定義在了內部的sram中了,雖然通過map文件我們可以看到,在外部的sram中我們也分配了heap、stack的空間,但是我們的sp指針沒有指向他們,其實這里還有很多擴展的空間;
到這里,分析完了,外部sram的用法,以及為什么會出現這種現象,其中涉及到map文件的解析;以及分散加載。Sct的知識,沒有做仔細分析,合理安排、設計分散加載文件可以讓你的工程的鏈接、加載更加符合你的設計要求,所以在工程設置中,IDE才允許我們設置使用自己定義的.sct文件;有時間,后面再細分析;
以上圖文的Word格式文檔下載(內容和本網頁上的一模一樣,方便大家保存):
12 STM32的外部SRAM使用的總結.docx
(1.78 MB, 下載次數: 3)
2023-12-4 09:33 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|