TOPS
原創(chuàng)版權(quán),轉(zhuǎn)載請注明出處!
內(nèi)容目錄
一伯诬、理論
1商源、 復(fù)位流程
2、 內(nèi)存分布
二鸯旁、 實戰(zhàn) — boot
1、 工具:keil JLINK
2、 新建工程
3泣港、 修改腳本
4暂殖、 修改代碼
5、 編譯下載
6爷速、現(xiàn)象
三央星、 實戰(zhàn) — app
1、 新建工程
2惫东、 修改腳本
3莉给、 修改代碼
4、 編譯下載
5廉沮、 在線仿真
注意:
問題:
總結(jié)
參考文獻:
一颓遏、理論
1、 復(fù)位流程
在離開復(fù)位狀態(tài)后滞时,Cortex-M 做的第一件事就是讀取下列兩個 32 位整數(shù)的值:
1叁幢、從地址 0x0000,0000 處取出 MSP 的初始值。</li>
2坪稽、從地址 0x0000,0004 處取出 PC 的初始值——這個值是復(fù)位向量曼玩,LSB 必須是1,然后從這個值所對應(yīng)的地址處取指窒百。
在 0 地址處提供 MSP 的初始值黍判,然后緊跟著就是向量表。向量表中的數(shù)值是 32位的地址篙梢,而不是跳轉(zhuǎn)指令顷帖。向量表的第一個條目指向復(fù)位后應(yīng)執(zhí)行的第一條指令。
因為 Cortex-M 使用的是向下生長的滿棧渤滞,所以 MSP 的初始值必須是堆棧內(nèi)存的末地址加1贬墩。舉例來說,如果你的堆棧區(qū)域在 0x20007C00-0x20007FFF 之間妄呕,那么 MSP 的初始值就必須是 0x20008000陶舞。
向量表跟隨在 MSP 的初始值之后——也就是第 2 個表目。要注意因為 cortex-m 是在Thumb 態(tài)下執(zhí)行趴腋,所以向量表中的每個數(shù)值都必須把 LSB 置1(也就是奇數(shù))吊说。正是因為這個原因,圖 3.18 中使用 0x101 來表達(dá)地址 0x100优炬。當(dāng) 0x100 處的指令得到執(zhí)行后颁井,就正式開始了程序的執(zhí)行。在此之前初始化 MSP 是必需的蠢护,因為可能第1條指令還沒來得及執(zhí)行雅宾,就發(fā)生了 NMI 或是其它 fault。MSP 初始化好后就已經(jīng)為它們的服務(wù)例程準(zhǔn)備好了堆棧葵硕。
2眉抬、 內(nèi)存分布
需要修改工程中內(nèi)存分配的腳本實現(xiàn)以上效果贯吓,這里是使用兩個工程設(shè)計,一個為 bootloader 工程蜀变,一個為 app 工程悄谐。
二、 實戰(zhàn) — boot
1库北、 工具:keil JLINK
使用 S32DS 開發(fā)也可以爬舰,但是 S32DS 使用 jlink 下載程序的時候,芯片容易鎖死寒瓦,而且飛思卡爾的芯片鎖死之后情屹,解鎖都比較麻煩,所以暫時選擇 keil 開發(fā)杂腰。
2垃你、 新建工程
使用 keil 建立 s32k144 工程并不難,只是 s32k144 與其他的芯片稍微有點不一樣喂很,除了有一個匯編文件的啟動文件之外惜颇,還有幾個源文件,源文件的作用主要是從 flash 復(fù)制代碼到 ram 中少辣,初始化 bss 段官还,關(guān)閉看門狗,配置時鐘等毒坛。
上圖紅色部分務(wù)必勾選。
紅色框部分即使內(nèi)存分配腳本林说,這是待會兒需要修改的煎殷。工程建立好了之后,還需要進行一些配置腿箩。
在搞 STM32 的時候豪直,有時候修改的就是這里,這里可以修改內(nèi)存分配珠移,但是我們這次使用的是用戶腳本弓乙,不是默認(rèn)內(nèi)存配置,所以這里不需要修改钧惧。當(dāng)然還有生成 hex 文件暇韧、調(diào)試工具的選擇、輸出目錄等配置也需要進行浓瞪,這里就不一一列舉了懈玻,
紅色部分不要勾選,紫色部分需要手動找到這個腳本乾颁,我們把代碼下載到 flash 就選擇 flash 腳本涂乌,下載到 ram 就選擇 ram 腳本艺栈。
紅色部分最好不勾選,因為如果直接使用在 keil 下載的話湾盒,這個選項在下載 app 代碼的時候湿右,會全部擦除 flash,這時候 boot 會遭殃罚勾,會導(dǎo)致起不來毅人,配置基本配置好了,接下來就是修改腳本了荧库。
3堰塌、 修改腳本
Boot 的腳本基本不用怎么修改,就是修改一下 Boot 結(jié)束地址分衫,這里開辟給 boot 的大小是 0x4000场刑,相當(dāng)于 16K 的大小。
#if (defined(__ram_vector_table__))
#define __ram_vector_table_size__ 0x00000400
#else
#define __ram_vector_table_size__ 0x00000000
#endif
#define m_interrupts_start 0x00000000
#define m_interrupts_size 0x00000400
#define m_flash_config_start 0x00000400
#define m_flash_config_size 0x00000010
#define m_text_start 0x00000410
//#define m_text_size 0x0007FBF0
#define m_text_size 0x00002000
#define m_interrupts_ram_start 0x1FFF8000
#define m_interrupts_ram_size __ram_vector_table_size__
#define m_data_start (m_interrupts_ram_start+m_interrupts_ram_size)
#define m_data_size (0x00008000 - m_interrupts_ram_size)
#define m_data_2_start 0x20000000
#define m_data_2_size 0x00007000
4蚪战、 修改代碼
代碼的修改主要是集中在牵现,跳轉(zhuǎn)函數(shù),需要定義一個函數(shù)指針類型邀桑,還要注意 Cortex-m 復(fù)位跳轉(zhuǎn)序列瞎疼。
#include "S32K144.h" /* include peripheral declarations S32K144 */
#include "clocks_and_modes.h"
#include "gpio_led.h"
#define APP_ADDR 0x00004000
/******************************************************************************
*Local variables
******************************************************************************/
typedef void (*bootloader_fun)(void);
bootloader_fun jump2app;
void delay(volatile int cycles)
{
/* Delay function - do nothing for a number of cycles */
while(cycles--);
}
int main(void)
{
SOSC_init_8MHz(); /* Initialize system oscilator for 8 MHz xtal */
SPLL_init_160MHz(); /* Initialize SPLL to 160 MHz with 8 MHz SOSC */
NormalRUNmode_80MHz(); /* Init clocks: 80 MHz sysclk & core, 40 MHz bus, 20 MHz flash */
LED_PORT_init();
for(;;){
for(int i = 0;i < 5;i++){
led_triggle(2,1); /* turn on red LED */
led_triggle(1,0); /* turn on green LED */
led_triggle(0,0); /* turn on blue LED */
delay(720000);
delay(720000);
led_triggle(2,0); /* turn on red LED */
led_triggle(1,0); /* turn on green LED */
led_triggle(0,0); /* turn on blue LED */
delay(720000);
delay(720000);
}
jump2app = (bootloader_fun)*(uint32_t*)(APP_ADDR + 4);
jump2app();
}
return 0;
}
重點應(yīng)該就是這句話:
jump2app = (bootloader_fun)(uint32_t)(APP_ADDR + 4);
APP 地址加上 4 ,就是因為 CORTEX-M 復(fù)位序列的 PC 指針位置的偏移量就是偏移 4壁畸,(uint32_t)(APP_ADDR + 4) 進行強制類型轉(zhuǎn)換贼急,(bootloader_fun)(uint32_t*)(APP_ADDR+4) 取址,相當(dāng)于取 0x4004 地址的值捏萍,放到 PC 指針太抓,可能需要主義的還有一個就是 C 語言的語法,C 語言里面令杈,函數(shù)名稱就是函數(shù)的入口地址走敌,也就是說函數(shù)名稱其實也是一個指針,所以后面一句:jump2app();就是相當(dāng)于執(zhí)行一個函數(shù)逗噩。這樣就可以跳轉(zhuǎn)了掉丽。
5、 編譯下載
編譯就沒啥問題异雁,下載就有兩種方式捶障,一種是直接在keil 上下載,這個很簡單了纲刀,例外一個就是單獨打開 segger 下載残邀,這時候需要配置一下這個軟件:
然后把編譯生成的 hex 文件,直接拖到頁面里面就可以了,按 F5 就可以下載了芥挣,boot的下載沒有什么特別的要求驱闷,兩個都可以下載。
6空免、現(xiàn)象
下載之后空另,可以看到小燈閃了 5 下就不閃了,說明執(zhí)行到了后面的跳轉(zhuǎn)程序蹋砚。
三扼菠、 實戰(zhàn) — app
1、 新建工程
建立工程和 boot 一樣的過程坝咐,這里就不再贅述了循榆。
2、 修改腳本
腳本位置:$(工程目錄)144_app\RTE\Device\S32K144UAxxxLLx 下
#if (defined(__ram_vector_table__))
#define __ram_vector_table_size__ 0x00000400
#else
#define __ram_vector_table_size__ 0x00000000
#endif
//#define m_interrupts_start 0x00000000
#define m_interrupts_start 0x00004000
#define m_interrupts_size 0x00000400
//#define m_flash_config_start 0x00000400
#define m_flash_config_start 0x00004400
#define m_flash_config_size 0x00000010
//#define m_text_start 0x00000410
#define m_text_start 0x00004410
//#define m_text_size 0x0007FBF0
#define m_text_size 0x0002FBF0
#define m_interrupts_ram_start 0x1FFF8000
#define m_interrupts_ram_size __ram_vector_table_size__
#define m_data_start (m_interrupts_ram_start + m_interrupts_ram_size)
#define m_data_size (0x00008000 - m_interrupts_ram_size)
#define m_data_2_start 0x20000000
#define m_data_2_size 0x00007000
App 腳本的修改稍微多一點墨坚,每個對應(yīng)的偏移地址都需要改秧饮,向量表的地址,text 段的地址等泽篮。
3盗尸、 修改代碼
代碼基本就是正常的代碼,不用做任何的操作就可以了帽撑。
4泼各、 編譯下載
編譯和 boot 一樣,下載的話亏拉,如果沒勾選 erase full chip 扣蜻,可以直接下載,也可以使用 segger 下載及塘。
5弱贼、 在線仿真
如果 app 的代碼只是下載,那每次調(diào)試都會比較麻煩磷蛹,都得編譯成 hex 文件再下載才能驗證,因為腳本修改了向量表的地址溪烤,直接在線調(diào)試是不行的味咳,這樣就很不方便開發(fā)了,網(wǎng)路上有網(wǎng)友通過修改一個腳本檬嘀,讓 keil 識別到我們已經(jīng)修改過的向量表的地址槽驶,在工程目錄新建 flashoffset.ini 文件,內(nèi)容如下:
在 keil 配置里面導(dǎo)入這個文件
這樣就可以就行在線調(diào)試了鸳兽,就和正常開發(fā)一樣方便了掂铐。
注意:
每個工程編譯完了之后,最好是查看 .map 文件,看一下內(nèi)存分配是否都在劃定的內(nèi)存里面
也算是一種調(diào)試信息手段吧全陨。
問題:
這個 bootloader 整個流程雖然可以走通爆班,但是還有問題,如果 app 工程開啟了中斷辱姨,app 的程序會跑飛柿菩。原因是什么呢?這個就是第一節(jié)說的 cortex-m 復(fù)位序列雨涛。
1枢舶、 boot 中斷未關(guān);
2替久、接收升級文件驅(qū)動未提供凉泄;
3、Flash 驅(qū)動未提供蚯根;
4后众、App 程序重新定位向量表的基地址未修改。
總結(jié)
參考文獻:
《Cortex-M3 權(quán)威指南》
代碼下載:
https://pan.baidu.com/s/1fF3N_qpvMNtZOFGcB-HuIQ 密碼: 3ouv
https://pan.baidu.com/s/1TsZtd38C8hcLsVjJ113G5w 密碼:3tqg
微信公眾號:depthkernel
關(guān)注可了解更多嵌入式的教程陡蝇。問題或建議,請公眾號留言;
QQ 群:135924744
如果你覺得對你有幫助哮肚,歡迎關(guān)注公眾號