TOPS

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

内容目录

一、理论

1、 复位流程

在离开复位状态后,Cortex-M 做的第一件事就是读取下列两个 32 位整数的值:

1、从地址 0x0000,0000 处取出 MSP 的初始值。

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 程序重新定位向量表的基地址未修改。

总结

参考文献:

《Cortex-M3 权威指南》

微信公众号:

微信公众号

s32k144 isystem linux,S32k144 简易 Bootloader相关推荐

  1. s32k144 isystem linux,S32K144之时钟配置

    一般来说,时钟精度.稳定性取决于所采用的时钟源,就MCU S32K来说如内部振荡器SIRC,FIRC,128KLPO,外部晶振等,跟所使用的外设(FTM, LPIT,LPT,RTC等)和哪一路输出时钟 ...

  2. SAMSUNG S3C2440的简易BootLoader ㈢

    SAMSUNG S3C2440的简易BootLoader ㈢ 2010年06月05日 [b]SAMSUNG S3C2440的简易BootLoader ㈢[/b] [b][/b] [b]第三部分:源代码 ...

  3. linux进度条脚本,Linux下简易进度条的实现代码

    在生活中,进度条是很常见的,那么,进度条是如何实现的呢? 首先,进度条的动态是利用人眼视觉暂留效果的.实际上是如下过程: 先输出:[=     ]表示进度是1%,刷新之后 再输出:[==    ].. ...

  4. linux根文件系统的移植 课程设计,linux课程设计bootloader的移植.doc

    linux课程设计bootloader的移植 嵌 入 式 Linux 课 程 设 计 报 告 课题:嵌入式Linux下的bootloader之u-boot的移植 姓名: 胡欢 专业班级: 电信三班 学 ...

  5. linux服务器安装gmt,linux GMT简易安装

    linux GMT简易安装 近来无事,研究下GMT吧,windows,linux或OS都可以安装GMT,各有千秋,都挺麻烦,不搞得你晕头转向,誓不罢休!好了,闲话少叙,回归正题! 我就把我倒腾的lin ...

  6. linux系统需要占多大的内存,linux启动过程Bootloader、kernel

    256M可以推1080P屏幕 128M可以基本运行并安装 256M可以勉强开启特效 512M流畅运行特效 当然内存越大越好,特效与显卡也有关系 和windows相比,当然linux对内存的需求小 Bo ...

  7. chroot环境怎么重启linux,linux下简易chroot环境的塔建

    有些人想利用chroot来提高系统的安全性,但chroot后的目录也需要一个linux/unix的环境,最直接的方法就是copy整个系统到chroot后的目录,但这样很容易copy大量不需要的东西,而 ...

  8. LINUX下简易网站压力测试--Webbench小记

    Webbench是一款小巧实用的网站压力测试工具,它是由 Lionbridge公司开发的.它的标准测试主要有两项内容:每秒钟相应请求数和每秒钟传输数据量.它最多可以模拟3万个并发连接去测试网站的负载能 ...

  9. QQ for Linux试用简易报告(yksoft1版)

    飞鸽传书 新闻来源:yksoft's system home 年初曾经发过QQ for Mac早期版本的试用报告,在7月的最后一天,我也准备写写有关QQ for Linux最新公开版的体验报告. 我现 ...

最新文章

  1. 让UpdatePanel支持文件上传(2):服务器端组件
  2. 汇编: 在代码中安排自己定义的数据,栈空间
  3. 如何实现tm同时监控多个状态的改变_广电机房监控系统【斯必得智慧机房】
  4. lstm代码_只需5行代码!LSTM时间序列建模以及预测
  5. 保存到redis的字符串类型出现斜杆_深入浅出Redis:这次从Redis底层数据结构开始...
  6. 键盘事件与JS Filter
  7. Oracle 分析函数row_number() over (partition by order by )
  8. 信息系统综合知识二 信息化基础知识
  9. 新手指南|欢迎来到CSDN
  10. 低代码大势所趋,RDP报表3.0应运而生
  11. swfobject2.2参数详解
  12. android倒计时服务,Android倒计时器——CountDownTimer
  13. FreeCAD源码分析:TechDraw模块
  14. “大数据”查询平台利用抖音导流,存个人信息泄露或倒卖风险
  15. 简单Python爬取链接二手房信息
  16. html: a标签中的href的作用
  17. iOS微信小程序网页请求走error问题
  18. 在win10本地开发springboot项目能上传图片,并能通过URL直接从浏览器访问,但是部署到服务器上后能上传文件,但是通过浏览器无法访问图片
  19. taptap模拟器在电脑上能用吗?
  20. LTE学习:PHICH(二)

热门文章

  1. xml文件导入wps_怎么用wpsExcel表打开xml文档
  2. MAX31865模块PT100两线制测温
  3. 相机参数估计值如何计算?
  4. 小知识·typec耳机原理
  5. 解决elementUI上传多张图片出现闪动的bug
  6. Gbit以太交换BCM56504
  7. CV赛事|“华为云杯”2020深圳开放数据应用创新大赛•生活垃圾图片分类
  8. Python基础练习题目
  9. 关于一次mac维修的经历
  10. 视频分析代码douyin