了解更多关于bootloader 的C语言实现,请加我QQ: 1273623966 (验证信息请填 bootloader)

欢迎咨询或定制bootloader(在线升级程序)。

  到目前为止,“自己用C语言写 xxx serial bootloader"已经有7篇博文了,7篇博文,7款不同的MCU。今天给大家介绍第8款MCU的串口bootloader, 也就是NXP S32K116 serial boot-loader。 NXP S32K116 是ARM Cortex-M0 内核的32-bit MCU。 有丰富的外设,卓越的性能以及成熟的工具链。特别是NXP的Processor Expert,一个非常不错的工具。我的这个bootloader 的底层驱动都是用Processor Expert自动生成的。我只需要写中间层和bootloader应用层的代码。看完S32Kxxx datasheet和S32Kxxx reference manual,才开始写bootloader,整个实现过程除了"bootloader jumping to application"卡了一段时间,一切都非常顺利。Processor Expert确实可以节省不少时间。但NXP S32Kxxx 开发环境也有不足的地方,比如IDE S32DS (S32 design studio) 非常慢,电脑配置不高的话容易卡死。还有就是S32DS 不支持simulator debug。 一定要有硬件板才可以debug.

  Bootloader 是独立的一个程序,和Application分别存储在ROM中不同的区间,不能有重叠。我的S32K116 bootloader 是放置在头部,区间范围为:0x00000000~0x00003FFF. Application的区间范围为:0x00004000~0x0001FFFF. 为此分别对Bootloader 和Application的linker script做了一下改动。

Bootloader linker script 的改动如下:

MEMORY
{/* Flash */m_interrupts          (RX)  : ORIGIN = 0x00000000, LENGTH = 0x000000C0m_flash_config        (RX)  : ORIGIN = 0x00000400, LENGTH = 0x00000010m_text                (RX)  : ORIGIN = 0x00000410, LENGTH = 0x00003BF0/* SRAM_L *//* SRAM_U */m_data                (RW)  : ORIGIN = 0x20000000, LENGTH = 0x000020C0m_data_2              (RW)  : ORIGIN = 0x200020C0, LENGTH = 0x00001740
}

Application linker script 的改动如下:

MEMORY
{/* Flash */m_interrupts          (RX)  : ORIGIN = 0x00004000, LENGTH = 0x000000C0m_flash_config        (RX)  : ORIGIN = 0x00004400, LENGTH = 0x00000010m_text                (RX)  : ORIGIN = 0x00004410, LENGTH = 0x0001BBF0/* SRAM_L */m_custom              (RW)  : ORIGIN = 0x1FFFFC00, LENGTH = 0x00000400/* SRAM_U */m_data                (RW)  : ORIGIN = 0x20000000, LENGTH = 0x000020C0m_data_2              (RW)  : ORIGIN = 0x200020C0, LENGTH = 0x00001740
}

  Bootloader实现Application的更新需要上位机的协助,上位机一般是PC端的host 软件工具。我的S32K116 bootloader 使用的上位机是HyperTerminal.  HyperTerminal 可以建立串口连接,传输Application 的Hex文件。并可以配置传输方式为每发送一行delay 50ms, 这样可以预留时间让bootloader处理数据完成烧写。使用HyperTerminal可以省掉开发专门的上位机时间,但是由于传送方式是纯文本发送,没有使用协议,没有应答机制。某种意义上讲是不可靠的。并且速度慢,一般不可以用于量产产品,只能用于学习或内部人员使用。

  Bootloader程序是MCU的程序,MCU一上电就进入Bootloader。Bootloader程序先完成CLOCK, PIN, UART 初始化,然后就运行一个Bootloader状态机,状态机如下所示:

        switch (bootState){case BOOT_HANDSHAKE:mbootStatus = M_Bootloader_Handshake();if (mbootStatus == BT_OK){bootState = BOOT_INIT;}else if (mbootStatus == BT_HS_TIMEOUT){mbootStatus = BT_DONE;bootState = BOOT_JUMPTO_APP;}break;case BOOT_INIT:LPUART_DRV_SendDataPolling(INST_LPUART1,(uint8_t*)bootInitMsg,strlen((char*)bootInitMsg));mbootStatus = M_Bootloader_Init();if (mbootStatus == BT_OK){LPUART_DRV_SendDataPolling(INST_LPUART1,(uint8_t*)bootJobDoneMsg,strlen((char*)bootJobDoneMsg));bootState = BOOT_ERASE;}break;case BOOT_ERASE:LPUART_DRV_SendDataPolling(INST_LPUART1,(uint8_t*)bootEraseMsg,strlen((char*)bootEraseMsg));mbootStatus = M_Bootloader_Erase();if (mbootStatus == BT_OK){LPUART_DRV_SendDataPolling(INST_LPUART1,(uint8_t*)bootJobDoneMsg,strlen((char*)bootJobDoneMsg));bootState = BOOT_RECEIVE;LPUART_DRV_SendDataPolling(INST_LPUART1,(uint8_t*)bootPrgmMsg,strlen((char*)bootPrgmMsg));}break;case BOOT_RECEIVE:mbootStatus = M_Bootloader_Receive();if (mbootStatus == BT_OK){LPUART_DRV_SendDataPolling(INST_LPUART1,(uint8_t*)bootFbHdrMsg,strlen((char*)bootFbHdrMsg));LPUART_DRV_SendDataPolling(INST_LPUART1,(uint8_t*)lineRcdBuf,LINE_RECORD_BUF_SIZE);bootState = BOOT_PROGRAM;}break;case BOOT_PROGRAM:mbootStatus = M_Bootloader_Write();if (mbootStatus == BT_BUSY){bootState = BOOT_RECEIVE;}else if (mbootStatus == BT_OK){bootState = BOOT_PREJUMP;}break;case BOOT_PREJUMP:mbootStatus = Prejump_To_Application();if (mbootStatus == BT_OK){bootState = BOOT_JUMPTO_APP;LPUART_DRV_SendDataPolling(INST_LPUART1,(uint8_t*)bootPrgmDoneMsg,strlen((char*)bootPrgmDoneMsg));}break;case BOOT_JUMPTO_APP:mbootStatus = BT_DONE;//LPUART_DRV_Deinit(INST_LPUART1);//Jump_To_Application(*((uint32_t*)APP_START_ADDRESS),*((uint32_t*)APP_JUMP_ADDRESS));break;default:break;}

总共7个状态:BOOT_HANDSHAKE,BOOT_INIT,BOOT_ERASE,BOOT_RECEIVE,BOOT_PROGRAM,BOOT_PREJUMP,BOOT_JUMPTO_APP。
BOOT_HANDSHAKE:初始状态,数秒6秒,收到更新请求就切换状态为BOOT_INIT,超时就切换状态为BOOT_JUMPTO_APP,出错就重启。

BOOT_INIT: 初始化flash, 成功就切换状态为BOOT_ERASE,出错就重启。                                                    

BOOT_ERASE:擦除flash的Application区间,成功就切换状态BOOT_RECEIVE,出错就重启。                                      

BOOT_RECEIVE:接收Hex数据,每成功接收一行数据,就切换状态为BOOT_PROGRAM,出错就重启。           

BOOT_PROGRAM:解析数据,数据ready就完成烧写,如果数据是最后一行数据,就切换状态为BOOT_PREJUMP,否则切回BOOT_RECEIVE,出错就重启。          

BOOT_PREJUMP: 检查数据并处理未处理的数据,成功则切换状态为BOOT_JUMPTO_APP,出错就重启。                                 

BOOT_JUMPTO_APP: 设置Application中断向量,设置Application的Stack首地址。跳转到Application Reset 向量地址。                                    

Jump_To_Application这个函数功能很简单,却花了很多时间,Application已经烧写完成,始终无法跳转过去,包括NXP官网上bootloader例程的跳转方法也不行,后来经过不断试错,总算成功了,最终实现如下:

void Jump_To_Application(uint32_t userSP)
{void (*entry)(void);uint32_t pc;if(userSP == 0xFFFFFFFF){return;}else{/* Set up stack pointer */__asm("msr msp, r0");__asm("msr psp, r0");/* Relocate vector table */S32_SCB->VTOR = (uint32_t)APP_START_ADDRESS;/* Jump to application PC */pc = *((volatile uint32_t *)(APP_START_ADDRESS + 4));entry = (void (*)(void))pc;entry();}
}

Bootloader 的开发环境:

IDE: S32DS

Compiler: S32DS 自带的gcc

Hardware:  S32K116 EVB

SDK:   S32DS/S32SDK_S32K116_EAR_1.8.7

自己用C语言写NXP S32K116 serial bootloader相关推荐

  1. 自己用C语言写RL78 serial bootloader

    自己用C语言写RL78 serial bootloader 了解更多关于bootloader 的C语言实现,请加我QQ: 1273623966 (验证信息请填 bootloader),欢迎咨询或定制b ...

  2. 用C语言写PHP扩展

     用C语言写PHP扩展 1:预定义 在home目录,也可以其他任意目录,写一个文件,例如caleng_module.def 内容是你希望定义的函数名以及参数: int a(int x,int y) s ...

  3. 看看现在大型网站都是用什么语言写的 ?

    看看现在大型网站都是用什么语言写的 ? 不排除一个网站用多种技术!如淘宝是Java + php,底层是java,表现层是php.新浪,网易,腾讯应该也是用了多种技术. 据说是这样的:php,新浪,雅虎 ...

  4. 会写代码的AI开源了!C语言写得比Codex还要好,掌握12种编程语言丨CMU

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 萧箫 发自 凹非寺 量子位 | 公众号 QbitAI 比Codex还 ...

  5. 大学生只会用C语言写简单的计算怎么办?

    大学生会用C语言写几个简单的计算太正常了,有些人直到毕业了都写不出什么程序. 这个也是大多数应届生的一个现状. 在学校的时候不知道要好好学习,等马上会接受社会毒打时才发现自己一无是处,然后开始临时抱佛 ...

  6. c++ 小游戏_C/C++编程笔记:C语言写推箱子小游戏,大一学习C语言练手项目

    C语言,作为大多数人的第一门编程语言,重要性不言而喻,很多编程习惯,逻辑方式在此时就已经形成了.这个是我在大一学习 C语言 后写的推箱子小游戏,自己的逻辑能力得到了提升,在这里同大家分享这个推箱子小游 ...

  7. C语言写一函数交换两变量的值

    C语言写一函数交换两变量的值 #include <stdio.h> void swap(int *p1, int *p2); // 形参,只声明 int main(){int a=5, b ...

  8. Go语言写的解析器(支持json,linq,sql,net,http等)

    Monkey程序语言 Monkey v2.0版本已发布. monkey v2.0 增加了如下内容: 新增 short arrow(->)支持(类似C#的lambda表达式) 增加 列表推导和哈希 ...

  9. c语言的十进制转十六进制字符串,用c语言写一个函数把十进制转换成十六进制,该如何处理...

    用c语言写一个函数把十进制转换成十六进制 用c语言写一个函数把十进制转换成十六进制 网上找到一些,感觉有占乱 分享到: ------解决方案-------------------- #include ...

最新文章

  1. linux 如何查看应用程序进程号、端口
  2. 一次堆外内存泄露的排查过程
  3. 《黑客秘笈——渗透测试实用指南(第2版)》—第2章2.7节总结
  4. 【Linux】解决Linux上解压jdk报错gzip: stdin: not in gzip format
  5. SpringBoot拦截器配置
  6. 能写个简单的oa系统java_基于jsp的轻量级OA系统-JavaEE实现轻量级OA系统 - java项目源码...
  7. boost正则表达式库简单介绍
  8. 使用runtime跳转界面
  9. Mac无法正常使用共享屏幕功能的解决办法
  10. ppt插入 html,PPT中嵌入网页的方法:使用webbrowser控件
  11. android 内存uss rss,内存VSS/RSS/PSS/USS名词解释
  12. 支付宝app支付对接1
  13. 数据结构与算法3 树(上)树与树的表示
  14. 给你的网页加个二次元老婆吧
  15. 购买虚拟服务器费用入什么科目,购买的云服务器费用入什么科目
  16. 平台卡卷API文档分享
  17. 拼多多2020届数据分析面试题合集
  18. Python二手房价格预测(三)——二手房价格预测模型baseline
  19. 集群01之xshell链接liux 更改ip 网关及dns 主机名称
  20. Dimension finie有限元-ECPKn

热门文章

  1. 工具篇——1、TMUX
  2. 用navicat访问linux数据库,成功实现Navicat访问Linux中安装的MySQL数据库
  3. android o 结构光流程,【OPPOFindX评测】O-Face 3D结构光:最科幻的交互方式-中关村在线...
  4. 国产化Kettle、JDK、MySQL下载安装操作步骤
  5. 关于2020年全国大学生电子设计竞赛 ——信息科技前沿专题邀请赛(瑞萨杯)竞赛时间调整的通知
  6. 如何在css文件中使用本地ttf/woff/woff2字体?
  7. html5+Css3 做一个婚纱网页
  8. LINUX信息安全系统设计基础第一周学习总结
  9. 数据压缩作业二:PNG图像格式分析
  10. 用4种方法完成计算机的关闭,在Win10中的4种自动关闭的方法 | MOS86