完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
BootLoader是在操作系统内核运行之前运行的,主要功能是初始化硬件设备、建立内存空间映射图,从而将系统的软硬件环境带到一个合适状态,以便为最终调用操作系统内核准备好正确的环境。BIOS是windows的bootloader,u-boot等为常见的Linux开发版的bootloader。ARM内核芯片下载程序方式可分为三类;
1.下载器(J-Link,ST-Link等)直接下载 2.ISP(in-system programming)下载,以STM32为例,可在不使用下载器而通过如UART、I2C、SPI、USB等通讯接口配合芯片启动代码(.s文件)进行升级 3.IAP(In Application Programming)下载,即编写应用软件实现程序升级,使用bootloader即属于此方法 在产品中,IAP升级的方式较其余两种的优势在于不需要接触芯片,不需要进行硬件配置更改即可实现程序远程升级,有益之处显而易见。物联网技术中的OTA(Over the Air Technology)升级也是基于IAP原理,在bootloader中实现网络通讯与云端配合进行程序升级。 言归正传,为STM32写bootloader实现IAP升级。 首先建立概念,bootloader与应用程序之间是两个独立的程序,在自身运行时互不干扰对方。两者共用的资源是单片机flash。升级Demo以stm32f103c8做实验芯片,编程使用keil MDK,采用HAL库使用cubeMX生成代码基础配置。 第一步:编程实现程序跳转大概需要三个步骤: 1.关闭外设中断 2.重设中断向量表 3.设置起始堆栈地址,将sp指针指向app程序main函数地址 将三个功能放在fun_jump.c函数中, #include "fun_jump.h" #include "main.h" //设置栈顶地址 //addr:栈顶地址 __asm void MSR_MSP(u32 addr) { MSR MSP, r0 //set Main Stack value BX r14 } //跳转到应用程序段 //appxaddr:用户代码起始地址. void fun_jump(u32 appxaddr) { if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000) //检查栈顶地址是否合法. { jump2app=(void(*)())*(vu32*)(appxaddr+4); //用户代码区第二个字为程序开始地址(复位地址) MSR_MSP(*(vu32*)appxaddr); //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址) for(int i = 0; i < 8; i++) { NVIC->ICER = 0xFFFFFFFF; /* 关闭中断*/ NVIC->ICPR = 0xFFFFFFFF; /* 清除中断标志位 */ } jump2app(); //跳转到APP. } } fun_jump.h文件如下, #ifndef _FUN_JUMP_ #define _FUN_JUMP_ /*----------------------------------------------- 作者:HES 时间:18-5-8 功能:函数跳转。BootLoader使用 ------------------------------------------------*/ #define JUMP_ADDR 0x8002000 typedef unsigned int u32; typedef volatile unsigned int vu32; //指向指针的函数 static void (*jump2app)(); //跳转到应用程序段 //appxaddr:用户代码起始地址. void fun_jump(unsigned int appxaddr); #endif 在符合跳转条件时,调用调转函数fun_jump()即可实现跳转到JUMP_ADDR的地址执行app程序,JUMP_ADDR是app程序在flash中的起始地址。 第二步:设置keil软件 bootloader设置keil option如下,IROM1设置bootloader起始地址及大小,0x2000规定boot大小在8k以内 app程序设置keil option ,设置起始地址为0x8002000,大小可设置为flash size - boot size,此处设置了40k的大小限制。 几个注意点: 1.下载bootloader时,建议将下载器设置为全片擦除flash 2.以上两步操作完成,将下载器设置为部分擦除、下载app程序,bootloader使用延时方式实现直接跳转,可以检测跳转是否能实现 3.app程序中断不能正确触发,需要检查重设中断向量表部分,也可以在app程序初始化时进行重设向量表 SCB->VTOR = FLASH_BASE | 0x2000; //重设中断向量表 第三步:编写bootloader与电脑端搭配使用的上位机 实际使用时将升级功能集成在了产品上位机中,在进行升级测试时自己用python写了个简陋的上位机,实现电脑与产品之间的串口通讯,实现程序远程升级。 bootloader部分主要要做的工作: 1.跳转判断及跳转功能实现 2.与上位机之间的通讯及协议配合 3.数据传输校验及传输过程中的错误处理,断点续传 4.flash操作,擦除及写入 5.bootloader与程序之间的相互验证 2.与上位机之间的通讯可以采用串口、u***等方式。涉及的几个关键点有.bin文件生成、.bin文件读取及拆分与最后的传输过程。本demo采用自定义的协议,将1k数据拆分为16次进行传输,每次传输包的大小为64bytes. 传输过程进行包头检测、数据长度检测等,确保在.bin文件中的数据与包头刚好相同时,升级可以继续。 3.数据校验是不可缺少且很关键的一步,本demo使用的校验方法有a.每个传输包进行求和取余校验 b.传输完1k字节之后取1k字节数据的头尾进行对比校验 c.程序传输完成后上位机与bootloader之间进行.bin文件大小校验。错误处理即使boot可以将传输状态及时反馈给上位机,上位机对错误状态进行识别后作处理。终止升级or重新对本段数据进行发送。 4.限于flash擦除、写入只支持1k bytes数据整体操作,所以在传输过程中需要将数据积攒到1k之后再进行写入。 第5点,如果是自己测试玩或跳转条件是bootloader上电后延时等待更新信号(类似linux与windows),此步可忽略。但采用读取固定flash位检测标志位的方式决定是否需要更新,则需要慎重考虑。远程程序升级存在的问题之一是如果刷入了错误的不能运行的程序,上电之后程序卡死无法正确执行app或bootloader,那么只能进行拆机重新焼写boot。实现思路大概是bootloader与产品程序之前实现双向验证,app在初始化之前对boot的数据区(flash固定区域)进行识别、校验。校验通过后更改boot数据区的标志,作为app正确运行的标志。下一次上电是boot对标志进行检测,若标志没有被改动,则说明app运行失败或焼写如的错误的app,此时将始终保持boot状态不跳转,等待下次升级。双向验证中,有一方验证失败,则保持在bootloader状态,等待程序升级指令。 第5点涉及公司产品,本文及代码中已删除。 本demo上传至CSDN,实现的效果是LED在bootlaoder下慢速闪烁,在升级成功、跳转成功后闪烁频率变高。 配合上位机的升级流程: 1.下载bootlaoder到单片机,使用u***转ttl连接电脑与单片机串口 USART2 ->PA2 TX PA3 RX 2.修改upgrade.py文件中的打开bin文件的路径及bin文件名 如下 3.导入upgrade库,并打开串口,调用upgrade()函数 结果如下: 上述文件在附件中可下载. |
|
|
|
只有小组成员才能发言,加入小组>>
3278 浏览 9 评论
2956 浏览 16 评论
3456 浏览 1 评论
8988 浏览 16 评论
4050 浏览 18 评论
1102浏览 3评论
570浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
568浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2301浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1857浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 11:35 , Processed in 1.125821 second(s), Total 50, Slave 40 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号