S32k144 简易 Bootloader

TOPS

原创版权,转载请注明出处!

内容目录

一、理论
1、 复位流程
2、 内存分布
二、 实战 — boot
1、 工具:keil JLINK
2、 新建工程
3、 修改脚本
4、 修改代码
5、 编译下载
6、现象
三、 实战 — app
1、 新建工程
2、 修改脚本
3、 修改代码
4、 编译下载
5、 在线仿真
注意:
问题:
总结
参考文献:

一、理论

1、 复位流程

在离开复位状态后,Cortex-M 做的第一件事就是读取下列两个 32 位整数的值:
1、从地址 0x0000,0000 处取出 MSP 的初始值。</li>
2、从地址 0x0000,0004 处取出 PC 的初始值——这个值是复位向量,LSB 必须是1,然后从这个值所对应的地址处取指。

图 1.1 复位序列.jpg

在 0 地址处提供 MSP 的初始值,然后紧跟着就是向量表。向量表中的数值是 32位的地址,而不是跳转指令。向量表的第一个条目指向复位后应执行的第一条指令。

图 1.2 初始化MSP及PC初始化一个范例.jpg

因为 Cortex-M 使用的是向下生长的满栈,所以 MSP 的初始值必须是堆栈内存的末地址加1。举例来说,如果你的堆栈区域在 0x20007C00-0x20007FFF 之间,那么 MSP 的初始值就必须是 0x20008000。
向量表跟随在 MSP 的初始值之后——也就是第 2 个表目。要注意因为 cortex-m 是在Thumb 态下执行,所以向量表中的每个数值都必须把 LSB 置1(也就是奇数)。正是因为这个原因,图 3.18 中使用 0x101 来表达地址 0x100。当 0x100 处的指令得到执行后,就正式开始了程序的执行。在此之前初始化 MSP 是必需的,因为可能第1条指令还没来得及执行,就发生了 NMI 或是其它 fault。MSP 初始化好后就已经为它们的服务例程准备好了堆栈。

2、 内存分布

图 1.3 flash 内存分配图.jpg

需要修改工程中内存分配的脚本实现以上效果,这里是使用两个工程设计,一个为 bootloader 工程,一个为 app 工程。

二、 实战 — boot

1、 工具:keil JLINK

使用 S32DS 开发也可以,但是 S32DS 使用 jlink 下载程序的时候,芯片容易锁死,而且飞思卡尔的芯片锁死之后,解锁都比较麻烦,所以暂时选择 keil 开发。

2、 新建工程

使用 keil 建立 s32k144 工程并不难,只是 s32k144 与其他的芯片稍微有点不一样,除了有一个汇编文件的启动文件之外,还有几个源文件,源文件的作用主要是从 flash 复制代码到 ram 中,初始化 bss 段,关闭看门狗,配置时钟等。

图 2.1 新建工程.jpg
图 2.2 保存工程.jpg
图 2.3 选择芯片类型.jpg
图 2.4 选择固件以及启动代码.jpg

上图红色部分务必勾选。

图 2.5 工程目录结构.jpg

红色框部分即使内存分配脚本,这是待会儿需要修改的。工程建立好了之后,还需要进行一些配置。

图 2.6 内存配置.jpg

在搞 STM32 的时候,有时候修改的就是这里,这里可以修改内存分配,但是我们这次使用的是用户脚本,不是默认内存配置,所以这里不需要修改。当然还有生成 hex 文件、调试工具的选择、输出目录等配置也需要进行,这里就不一一列举了,

图 2.7 用户脚本选择.jpg

红色部分不要勾选,紫色部分需要手动找到这个脚本,我们把代码下载到 flash 就选择 flash 脚本,下载到 ram 就选择 ram 脚本。

图 2.8 下载配置.jpg

红色部分最好不勾选,因为如果直接使用在 keil 下载的话,这个选项在下载 app 代码的时候,会全部擦除 flash,这时候 boot 会遭殃,会导致起不来,配置基本配置好了,接下来就是修改脚本了。

3、 修改脚本

Boot 的脚本基本不用怎么修改,就是修改一下 Boot 结束地址,这里开辟给 boot 的大小是 0x4000,相当于 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、 修改代码

代码的修改主要是集中在,跳转函数,需要定义一个函数指针类型,还要注意 Cortex-m 复位跳转序列。

#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;
}

重点应该就是这句话:
jump2app = (bootloader_fun)(uint32_t)(APP_ADDR + 4);
APP 地址加上 4 ,就是因为 CORTEX-M 复位序列的 PC 指针位置的偏移量就是偏移 4,(uint32_t)(APP_ADDR + 4) 进行强制类型转换,(bootloader_fun)(uint32_t*)(APP_ADDR+4) 取址,相当于取 0x4004 地址的值,放到 PC 指针,可能需要主义的还有一个就是 C 语言的语法,C 语言里面,函数名称就是函数的入口地址,也就是说函数名称其实也是一个指针,所以后面一句:jump2app();就是相当于执行一个函数。这样就可以跳转了。

5、 编译下载

编译就没啥问题,下载就有两种方式,一种是直接在keil 上下载,这个很简单了,例外一个就是单独打开 segger 下载,这时候需要配置一下这个软件:

图 2.9 segger 配置.jpg
图 2.10 选择芯片.jpg

然后把编译生成的 hex 文件,直接拖到页面里面就可以了,按 F5 就可以下载了,boot的下载没有什么特别的要求,两个都可以下载。

图 2.11 编译完成.jpg

6、现象

下载之后,可以看到小灯闪了 5 下就不闪了,说明执行到了后面的跳转程序。

三、 实战 — app

1、 新建工程

建立工程和 boot 一样的过程,这里就不再赘述了。

图 3.1 app 目录结构.jpg

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 脚本的修改稍微多一点,每个对应的偏移地址都需要改,向量表的地址,text 段的地址等。

3、 修改代码

代码基本就是正常的代码,不用做任何的操作就可以了。

4、 编译下载

编译和 boot 一样,下载的话,如果没勾选 erase full chip ,可以直接下载,也可以使用 segger 下载。

5、 在线仿真

如果 app 的代码只是下载,那每次调试都会比较麻烦,都得编译成 hex 文件再下载才能验证,因为脚本修改了向量表的地址,直接在线调试是不行的,这样就很不方便开发了,网路上有网友通过修改一个脚本,让 keil 识别到我们已经修改过的向量表的地址,在工程目录新建 flashoffset.ini 文件,内容如下:

图 3.2 app 在线调试脚本.jpg

在 keil 配置里面导入这个文件

图 3.3 导入在线调试脚本.jpg

这样就可以就行在线调试了,就和正常开发一样方便了。

注意:

每个工程编译完了之后,最好是查看 .map 文件,看一下内存分配是否都在划定的内存里面

图 3.4 app 工程的 .map 文件.jpg

也算是一种调试信息手段吧。

问题:

这个 bootloader 整个流程虽然可以走通,但是还有问题,如果 app 工程开启了中断,app 的程序会跑飞。原因是什么呢?这个就是第一节说的 cortex-m 复位序列。

1、 boot 中断未关;
2、接收升级文件驱动未提供;
3、Flash 驱动未提供;
4、App 程序重新定位向量表的基地址未修改。

总结

虽然上述通过 keil 软件,以及它的分散脚本实现了简单的 bootloader 和 app 在线调试功能,这个只是一个简易的 bootloader,还有很多功能未添加,也有很多地方还需要完善,目前这个只是能跑一个简单的流程,只是帮助理解一下。

参考文献:

《Cortex-M3 权威指南》

代码下载:
https://pan.baidu.com/s/1fF3N_qpvMNtZOFGcB-HuIQ 密码: 3ouv
https://pan.baidu.com/s/1TsZtd38C8hcLsVjJ113G5w 密码:3tqg

微信公众号:depthkernel
关注可了解更多嵌入式的教程。问题或建议,请公众号留言;
QQ 群:135924744
如果你觉得对你有帮助,欢迎关注公众号

微信公众号
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,219评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,363评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,933评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,020评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,400评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,640评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,896评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,597评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,327评论 1 244
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,581评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,072评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,399评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,054评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,849评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,672评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,585评论 2 270

推荐阅读更多精彩内容