MSP430F149单片机-IAP升级
文章目录
- MSP430F149单片机-IAP升级
- 序言
- 功能设计
- 地址分配
- Flash擦写
- App跳转
- 中断向量表的偏移
MSP430F149单片机-IAP升级
序言
系统设计的总体构想是,通过无线的方式,将需要升级的二进制文件直接下载到相应的地址空间,然后让单片机系统自动执行IAP升级。
TI公司的MSP430系列单片机是具有很高实用性价值的产品,在诸多领域得到广泛应用,主打其超低功耗的特性,16位的数据总线宽度,加上RISC指令集。IAP(In Application Programming)是用户自己的程序在运行过程中对用户Flash的部分区域进行烧写,目的是为了在产品发布后可以方便地通过预留地通信口对产品中地固件程序进行更新升级。
要实现IAP的功能,通常需要在设计固件时,编写两个项目:第一个项目程序不执行正常的功能操作。而只是通过某种通信信道(如UART)接收程序或数据(可执行的HEX文件),执行对第二部分代码的更新;第二个项目才是真正的功能代码。这两部分项目代码同时烧录在用户的Flash当中,当芯片上电时,首先运行至第一个项目代码,然后再跳转至第二个项目代码。
根据IAP的特性以及MSP430没有自带IAP的特点,需要自行编写IAP程序进行片内Flash的擦写,下面详细介绍如何进行IAP升级的设计。
比较重要的几个点包括:
- Bootloader的功能设计
- App和Bootloader的地址分配
- App程序的Flash写入
- Bootloader和App的跳转
- Bootloader和App中断向量的映射
功能设计
Bootloader是单片机上电时首先运行的程序。定时3s后芯片没有处于接收升级文件的状态的话,就会自动跳转至App程序继续运行。
Bootloader流程图:
地址分配
MSP430F149的Flash空间从 0x1000H - 0xFFFFH. 其中 0xFFE0H - 0xFFFFH 的32个Bytes用来存放中断向量.
对Flash的空间如下规划:
Bootloader:
0xF000H - 0xFFFFH | 4kB |
---|
App1:
0x2000H - 0x5FFFH | 16kB |
---|
App2:
0xF000H - 0xFFFFH | 16kB |
---|
想让仿真器能够直接烧写到对应的地址,需要对配置文件进行一定的修改.
以Bootloader为例,在IAR软件中需要在 Linker 中设置使用自己的xcl配置文件,然后用文本编辑器打开xcl文件修改.
存放 Code 和 Data 的区域是 0xF000H - 0xFFDFH, 而 0xFFE0H - 0xFFFFH 是中断向量的地址, 也是触发中断时, 硬件会前往的地址。 对应于App,其存放 Code 和 Data 的区域是 0x2000H - 0x5FDFH, 0x5FE0H - 0x5FFFH 存放App1的用户中断代码,0x5FFEH是App1的复位向量。
Flash擦写
TI提供了FLash擦写的例程,其中核心代码如下。
void write_SegA (unsigned char* value, unsigned char offset)
{unsigned char *Flash_ptr; // Flash pointerunsigned int i;Flash_ptr = (unsigned char *)(APP2_FLASH + 0x200*offset); // Initialize Flash pointerFCTL1 = FWKEY + ERASE; // Set Erase bitFCTL3 = FWKEY; // Clear Lock bit*Flash_ptr = 0; // Dummy write to erase Flash segmentFCTL1 = FWKEY + WRT; // Set WRT bit for write operationfor (i=0; i<512; i++){*Flash_ptr++ = *value++; // Write value to flash}FCTL1 = FWKEY; // Clear WRT bitFCTL3 = FWKEY + LOCK; // Set LOCK bit
}void copy_A2B (void)
{unsigned char *Flash_ptrA; // Segment A pointerunsigned char *Flash_ptrB; // Segment B pointerunsigned char i;unsigned char j;Flash_ptrA = (unsigned char *) APP2_FLASH; // Initialize Flash segment A pointerFlash_ptrB = (unsigned char *) APP1_FLASH; // Initialize Flash segment B pointerFCTL1 = FWKEY + ERASE; // Set Erase bitFCTL3 = FWKEY; // Clear Lock bit*Flash_ptrB = 0; // Dummy write to erase Flash segment BFCTL1 = FWKEY + WRT; // Set WRT bit for write operationfor (i=0; i<128; i++){for (j=0; j<128; j++){*Flash_ptrB++ = *Flash_ptrA++; // Copy value segment A to segment B}}FCTL1 = FWKEY; // Clear WRT bitFCTL3 = FWKEY + LOCK; // Set LOCK bit
}
需要注意的是,芯片对Flash最小的擦写单位是一个 Segment. 参考MSP430的芯片手册,通常一个Segment是 512个字节,除了用来存放用户信息的 Information Memory(128 Bytes) 和 最后一个 Segment n(256 Bytes). 这也是我们选择把 0x2000H 作为 App1 起始地址的原因——便于擦写Flash代码的书写。
App跳转
使用芯片手册中提到的BR指令,可以实现运行代码的变更。即,将目标地址放入PC寄存器。
代码如下所示:
asm("BR &0x5FFE")
目标地址是App1的 复位(Reset) 中断向量,随后程序会运行到App1的主程序中。
中断向量表的偏移
在 Stm32 中,可以使用 SCB->VTOR 实现中断向量表的偏移,例如在 systeminit 函数中 VECT_TAB_OFFSET 宏定义控制偏移位置
#ifdef VECT_TAB_SRAMSCV->VTOR = SRAM_BASE | VECT_TAB_OFFSET /* Vector Table Relocation in Internal SRAM*/
#elseSCV->VTOR = FLASH_BASE | VECT_TAB_OFFSET /*Vector Table Relocation in Flash*/
#endif
但是MSP430F149这款芯片并没有类似的配置寄存器。发生中断时,芯片进入的是硬件的复位地址 0xFFE0H - 0xFFFFH,根据不同的中断进入不同的地址。所以只能在Bootloader的中断中使用类似于 asm(“BR &0xXXXX”) 这样的指令跳转到App中的中断服务函数,例如
Bootloader:
#pragma vector=UART1RX_VECTOR
__interrupt void UART1_RX_ISR(void)
{// APP1串口1接收中断向量if( *((unsigned char*)(0x09FD)) == 0x20 ) {asm("BR &0x5FE6;");}else if(updating == 1) {RecBuf[index++] = U1RXBUF;}else if(U1RXBUF == 0xAA) {updating = 1;Print_Str_485("Start Receiving!\r\n");}
}
App1:
#pragma vector=UART1RX_VECTOR
__interrupt void UART1_RX_ISR(void)
{RS485Buf[Index1++] = U1RXBUF;asm("POP R15;");asm("POP R15;");asm("POP R15;");asm("POP R15;");
}
需要注意的有两点:
- 芯片从Bootloader跳转到App的复位函数进行复位后,会清除之前Bootloader保存的RAM变量(例如可能计划用来判断程序是否进入App的标志位);也不能将该变量保存到Flash当中,不然Flash不会自动清除,当意外再次上电时,芯片在Bootloader却会认为自己在App中。所以此处,我们采用CPU的SP指针判断跳转进入中断的地址是否是来自0x20开头的代码段,从而判断是否是App的中断(我的App只是很小的代码,没有超出0x2XXXH)
- 另外在Bootloader反汇编出来的代码中可以看到,在执行用户代码之前,会有一系列用户入栈的操作,这在跳转到App的中断服务函数之后,没有进行出栈的操作,从而导致程序跑飞(重要). 所以只要在App的中断服务函数的最后执行相应数量的出栈操作,就不会使得 RETI 函数执行出错。
MSP430F149单片机-IAP升级相关推荐
- 关于STM32单片机IAP升级中if(((*(__IO uint32_t*)ulAddr_App) 0x2FFE0000) == 0x20000000)语句的理解
没有标题 初见if(((*(__IO uint32_t*)ulAddr_App) & 0x2FFE0000) == 0x20000000) 语句理解 语句功能 为什么ulAddr_App里存的 ...
- STM32F103C8T6单片机IAP升级
关于IAP升级的方法和原理,网上已经有很多资料了,这块就不再说了,现在就将bootloader和app配置方法整理如下: APP程序就是一个简单的LED闪烁. APP设置为从FLASH中启动: STM ...
- 瑞萨单片机iap串口升级boot程序与app程序合并的工程构建-学习记录
MCU型号: R7F0C004 编辑软件:CS+ for CC boot区程序地址分配:0x0000-0x1ffff app区程序地址分配: 0x2000-0xfffff 复制一份常规的app程序,然 ...
- 差分升级 增量升级 单片机 STM32 IAP升级OTA升级,物联网车联网可用
差分升级 增量升级 单片机 STM32 IAP升级OTA升级,物联网车联网可用 介绍博客 https://blog.csdn.net/zhou74281/article/details/1177776 ...
- 51单片机IAP在线升级
51单片机IAP在线升级 爱矽半导体E85F3325单片机IAP在线升级教程,此处可查看更新及demo下载 文章目录 前言 一.ROM资源 二.KEIL有关知识 1.BL51连接器: 2.LX51连接 ...
- iap升级问题 stm32f103r8_STM32的基于串口的IAP固件升级与加密
大家好,我是川楠,最近,在问答频道上看到有人对IAP升级心存疑惑.恰好,我本人在这方面的做过功课,也实战使用到很多的项目上,所以我就来为大家做个抛砖引玉吧. 本次例程,我用的是STM32F103VET ...
- 完成MSP430的IAP升级程序(总结)
这几天测试写好的IAP升级程序,真是一个糟,能将程序下载进去,但无法运行. 经过各种测试,修改终于找到了问题的原因,现在大致总结下我在写IAP程序的时候 遇到的问题和解决方案.首先要实现单片机的IAP ...
- STM32 IAP升级(bootLoader)
STM32 IAP升级(bootLoader) 今天给大家做一个STM32F系列的IAP 升级, 网上有不少例子,我这里字数有点多如果看请耐心看完,如果嫌麻烦可以看其他的帖子 我这边以103为例子,用 ...
- 嵌入式开发<单片机软件升级>
嵌入式开发<单片机软件升级> 前言 一.单片机软件升级方式 二.IAP升级原理 1.FLASH区域划分 2. FLASH各个区域作用 三.IAP软件BOOT设计 1. 第一种设计方法 2. ...
- 快速应用RT-Thread IAP升级功能
快速应用RT-Thread IAP升级功能 参考官方文档 步骤一准备bootload APP项目设置及代码修改 下载RTT源码 修改main.c 增加分区表配置文件 依据分区表的配置修改flash驱动 ...
最新文章
- 扩展屏幕没有连接,但程序窗口还在扩展屏幕上,在看不到这个屏幕的情况下,把程序窗口拉回来的方法
- Git复习(八)之快速理解Git结构
- Ubuntu 18.04 搭建 gitlab服务器记录
- P1739 表达式括号匹配
- docker --- 梳理 Dockerfile docker-compose.yml
- ksu7对讲机调频软件_数字对讲机的群呼功能原理是什么?你了解多少?
- HDU 1566 Count the Colors 树状树组 区间更新 单点求值
- Windows 7中的远程桌面增强(Graphics Remoting, Remote Desktop)
- elixir官方入门教程 递归
- aliyun redis 链接超时_超详细的Redis入门指导
- ranger文件管理器修改默认文本编辑器为vim
- Python实验二——制作可视化标准计算器
- 使用visjs制作网络拓扑图
- 连接策略与搜索引擎优化
- 三角形面积的两种计算方法
- ios和android前景!阿里面试100%会问到的JVM,架构师必备技能
- MATLAB人工神经网络的手写数字识别系统
- 央行:居民购房意愿仍持续上升
- HTML常见标签的用法
- Qomo OpenProject Field Test 4发布!