当前位置:首页 > 单片机 > 单片机
[导读] 第一篇在项目开发中,至关重要的是保证产品运行的可靠,如果遇到异常,能否恢复很重要,而不是像砖头一样,程序死在某个地方。固件升级的原理就是重写向量表,在引导区更新app区的flash,然后跳转app区

第一篇


在项目开发中,至关重要的是保证产品运行的可靠,如果遇到异常,能否恢复很重要,而不是像砖头一样,程序死在某个地方。固件升级的原理就是重写向量表,在引导区更新app区的flash,然后跳转app区。实际开发中就会有以下问题:


1.如果MCU复位,比如POR,PDR,WDT等复位,都会使sp指针指向复位地址。那么MCU从引导区执行,如果APP区程序有效,应该如何控制程序跳转到APP区。


2.如果APP区或者引导区接受新固件,在更新APP区flash时,如果此时MCU发生掉电,当再次上电后,MCU该如何执行。或许有人说,我们有外部的EEP或者外部的FLASH,会使用状态和标志去记录当时MCU操作flash的状态,当然这些状态和标志有校验,并且存储到外部EEP或FLASH。上电后我们会判断校验,然后读出来作为依据。在理想情况下,这样做非常完美,但是MCU在运行中,什么情况都可能发生。比如电源掉的很快,那么算出来的校验有什么意义,还怎么保证写到EEP或FLASH的可靠性,特别是有外部FLASH,几ma的


电流MCU瞬时根本扛不住。即使是EEP,就算将引导区配置成最低功耗,这种意外也是不可避免的,此时的标志和状态只是徒劳。那么会造成一种MCU假死状态,滞留在引导区,然后死循环。如果要解除,只能通过仿真器进入仿真模式,更改变量值去解除。而这样的后果就违背了升级的初衷和产品的可靠。


3.对于新固件的更新,是接收全部数据再更新还是接收部分数据更新FLASH,这个具体依据自己使用的硬件资源,不过重点还是在于第二点的处理。


4.如果升级过程中,传输数据或读取数据突然中断,或者新的固件验证失败,那么这些操作该如何恢复,而不至于MCU假死。



自己实践中的处理,总结了如下几条:

1.首先我们要明白MCU复位后是要从复位执行,并且MCU中断后,会跳转到实际中断向量地址,也就是向量区重写。在应用区如果有中断发生,MCU会跳转到中断原始地址,通过跳转指令执行位于应用区实际的中断处理函数。例如我使用的是MSP430的FR6972,它的FRAM分配是0x4400-0x13FFF,它的向量区地址在0xFF80-0xFFFF。假如分成两个区,引导区0xF000-0xFFFF,APP区0x7C00-0xEFFF。现在程序执行在0x7C00-0xEFFF的应用区,此时MCU响应了一个中断,假设这个中断函数的入口地址是0xEFF2,按照常理,MCU也应该执行这个地址的内容,实际上,MCU会跳转到这个中断的原始中断向量地址0xFFF2,因为0xEF80-0xEFFF只是我们虚拟的中断向量地址,0xFF80-0xFFFF才是真正的中断向量区。这也是为什么要在引导区重写中断向量,如

#pragmavector=WDT_VECTOR

__interruptvoidWDT_ISR(void)//0xFFF2

{

asm("br&0xEFF2;");

}

执行中断,栈会保存sp等寄存器的内容,执行完后会恢复,继续执行APP区程序。

2.不管是引导区和APP区,MCU的寄存器地址都是固定的,ram的地址也是一样的,但是FLASH是各自独立的,不能重叠。特别注意的是,在引导区和APP区处理全局变量或静态变量时,一定要初始化,或者依据校验从存储器恢复,因为跳转(非中断跳转)会导致这些变量是乱的。

3.要明白编译出的文件格式,知道数据要写到MCU中FLASH的地址。例如MSP430编译出的文件:

@F000

01020304050607

@F008

314000248C00081C3E4017023F400000

B013B4FE8C00001C8D0000F03E400700

……

@FFC6

38F03EF044F04AF050F056F05CF062F0

68F06EF074F07AF080F086F08CF092F0

98F09EF0A4F0AAF0B0F0

@FFF2

B6F0BCF0C2F0C8F0CEF0D4F008F0

q

@后的内容是代码段的地址,是说明段数据要写入的地址,这些地址不需要写入到FLASH中。地址的分配与link文件分配有关。

-Z(CONST)DATA16_C,DATA16_ID,TLS16_ID,DIFUNCT,CHECKSUM=F000-FF7F

-Z(CONST)DATA20_C,DATA20_ID,CODE_ID=F000-FF7F

-Z(CODE)CSTART,ISR_CODE,CODE16=F000-FF7F

-P(CODE)CODE=F000-FF7F

-Z(CONST)SIGNATURE=FF80-FF8F

-Z(CONST)JTAGSIGNATURE=FF80-FF83

-Z(CONST)BSLSIGNATURE=FF84-FF87

-Z(CONST)IPESIGNATURE=FF88-FF8F

-Z(CODE)INTVEC=FF90-FFFF

-Z(CODE)RESET=FFFE-FFFF

像-z,-p这些都是编译指令,(data)(const)(code)都是说明修饰,DATA16_C,DATA16_ID等都是数据段类型描述。

q就是结束标志。

例如stm8l编译出的我文件格式:

:108000008200FBA0820166548200FE8D82016655CB//起始地址是0x8000

:108010008200FEA78200FEA8820126B18200F1C77D//起始地址是0x8010

:108020008200FEA98200FEAA820113AA8200F38ABE//起始地址是0x8020

:108030008200F5C68200F6EB8200FEAB8200EFD82C//起始地址是0x8030

:108040008200F5F982014AE38200FEAC8200FEADB7//起始地址是0x8040

:108050008200FEAE820136958200FEAF8201164399//起始地址是0x8050

:108060008200FEB082012E8B8200FEB18200F24BB4//起始地址是0x8060

:108070008200FEB28200FEB38200FEB48200FEB532//起始地址是0x8070

……

:108610008D011DBB3D002608BE042602BE0626E9CC

:0F862000BE042602BE06260435020000B60087FF

:10862F00AE013CBF00905FAE01648D00FC0E725F27

:10863F00016435820165725F016635020167350895

……

我们可以很容易百度hex文件格式说明,Hex文件是可以烧录到MCU中,被MCU执行的一种文件格式。整个文件以行为单位,每行以冒号开头,内容全部为16进制码。例如”:1000080080318B1E0828092820280B1D0C280D2854”。

第一个字节0x10表示本行数据的长度,“80318B1E0828092820280B1D0C280D28”。

第二,三个字节0x00,0x08表示本行数据的起始地址。

第四个字节0x00表示数据类型,数据类型说明:

'00'DataRrecord:用来记录数据,HEX文件的大部分记录都是数据记录

'01'EndofFileRecord:用来标识文件结束,放在文件的最后,标识HEX文件的结尾

'02'ExtendedSegmentAddressRecord:用来标识扩展段地址的记录

'03'StartSegmentAddressRecord:开始段地址记录

'04'ExtendedLinearAddressRecord:用来标识扩展线性地址的记录

'05'StartLinearAddressRecord:开始线性地址记录

理解了这些文件的内容,我们就知道了向量区需要些的内容,这点很重要。同时我们可以根据自己的通信协议进行扩展,重新转换这些内容,传输到MCU中进行固件升级。

4.原始的中断向量最好与引导区在一个区域,在引导区执行,最好关闭中断响应,通过查询的标志位的方式来处理。引导区的作用就是实现APP区的FLASH更新,中断的跳转。如果将原始向量区分配到APP区,会导致需要很大的外部存储空间接受新的固件,而且程序的设计也会头重脚轻,不建议使用。

5.如何保证固件更新的成功率,和解决擦写FLASH出现的异常,最好的操作就是先擦写APP区的向量区内容,更新完APP区FLASH,最后写复位向量内容。这样可以省去很多的判断流程,即使中途更新失败,或者掉电,MCU上电后也可以继续更新固件,并且出错率很低。像MSP430,烧写FLASH或者仿真下载,如果烧写时选择默认Memmoryoption,那么FLASH默认的值是0xFF。当知道分配的APP区的起始地址后,就判断复位向量值是否为0xFF,如果是则说明APP区没有内容,则不跳转,接受或更新固件。如果不是,一般情况下APP区是有内容的,则执行跳转。

6.在实现固件升级时,最好测试指针类型长度,因为选择的数据模式不同,访问不到0x10000以上的地址。比如MSP430的,如果选择mid,所有的指针类型长度占2byte,这样能访问的最大地址是0xFFFF,只有选择large,才可以访问0x10000以上的地址,但是相应的代码面会增加,因为函数列表的内容就扩大了一倍多,还有其他指针操作。Stm8l区分的就是near和far,就052r8分好几种大小的flash,可以在stm8l15x.h中更改宏。还有就是对内存的操作,需要注意对齐补齐,特别是32位机,像cortex-0内核。比如我经常使用

#defineM8(adr)(*((FARuint8_t*)(adr)))

#defineM16(adr)(*((FARuint16_t*)(adr)))

#defineM32(adr)(*((FARuint32_t*)(adr)))

FAR只是一种修饰。可以省略,也可以使用volitale。

7.合并引导区和APP区文件,然后通过烧程器烧录完整文件。关键就是只保留一个结束标志。
第二篇

以下我会通过实例代码来说明,如果有不足,请大家提出建议。

这是stm8L引导区的main()函数。

voidmain()

{

//禁止中断使能

disableInterrupts();

Clk_Config();

IO_Config();

LCD_Config();

//解锁FLASH操作

FLASH->PUKR=FLASH_RASS_KEY1;

FLASH->PUKR=FLASH_RASS_KEY2;

//从存储区读出数据

FLASH_ByteRead(start_EEPROM1ADDR,(uint8_t*)&ImagePara,sizeof(Image));

//使用CRC校验,返回0没错误

if(TestAdjust((uint8_t*)&ImagePara,sizeof(Image))==0)

jumpflasg=1;

//0x01初始化状态,判断口状态,因为我使用的CPU卡

if((jumpflasg==1)&&(ImagePara.CurState==0x01)&&((GPIOC->IDR&0x02)==0))

{

//擦除APP区向量

FLASHEraseBlock(APPST_BLOCK_NUM,FLASH_MemType_Program);

//擦除整个APP区

FlashErase(APPST_BLOCK_NUM,0xEF80);

}

//如果向量地址有效,跳转引导区

if(ResetVectorValid()==1)

{

asm("LDWX,SP");

asm("LDA,$FF");

asm("LDXL,A");

asm("LDWSP,X");

asm("JPF$9000");

}

//显示boot

{

LCD->RAM[3]=0x40;

LCD->RAM[4]=0x10;

LCD->RAM[7]=0xFC;

LCD->RAM[8]=0x01;

LCD->RAM[10]=0xC0;

LCD->RAM[11]=0x3F;

}

while(1)

{

//禁止中断

disableInterrupts();

//实时判校验

if(TestAdjust((uint8_t*)&ImagePara,sizeof(Image)))

FLASH_ByteRead(start_EEPROM1ADDR,(uint8_t*)&ImagePara,sizeof(Image));

//如果有卡标志

if((GPIOC->IDR&0x02)==0)

{

//如果读卡没错误

if(carderr!=1)

{

Delayms(10);

//读卡第一个块内容,包含我的块个数和校验和

carderr=Read_ImageInfo();

if(carderr!=1)

{

//更新flash,按块操作

while((++ImagePara.Block_dyn)<=ImagePara.Block_static)

{

//读CPU卡内容,更新flash

if(Read_Image(ImagePara.Block_dyn)==FALSE)

{

carderr=1;

break;

}

}

if(carderr!=1)

{

//最后写入向量区

if(Get_Vector()==FALSE)

{

carderr=1;

}

}

if(carderr!=1)

{

//验证块的状态

if(Verify_Image()==FALSE)

{

//校验失败

ImagePara.CurState=0x02;

}

else

{

//校验成功

ImagePara.CurState=0x03;

}

//算校验,更新数据

adjust_write((uint8_t*)&ImagePara,start_EEPROM1ADDR,sizeof(Image));

}

}

}

}

else

{

if(ImagePara.CurState==0x02)

{

memset((uint8_t*)&ImagePara,0,sizeof(Image));

ImagePara.CurState=0x01;

adjust_write((uint8_t*)&ImagePara,start_EEPROM1ADDR,sizeof(Image));

}

carderr=0;

}

if(carderr==1)

LCD->RAM[12]=0x40;

else

LCD->RAM[12]=0x00;

if(ImagePara.CurState==0x03)

{

asm("LDWX,SP");

asm("LDA,$FF");

asm("LDXL,A");

asm("LDWSP,X");

asm("JPF$9000");

}

}

}

这是MSP430引导区main()函数

voidmain()

{

WDTCTL=WDTPW|WDTHOLD;

Init_cmu();

Init_uart_Mbus();

Init_uart_HW();

Test_Image();

if(TestAdjust((uint8*)&ImagPara,sizeof(Image))==0)

jumpflag=1;

if((jumpflag==1)&&(ImagPara.curstate==0x04))

Flash_Erase(APP_VECSTARTADDR,APP_VECLEN);

if(ResetVectorValid()==1)

asm("mov&0xEFFE,PC;");

while(1)

{

__disable_interrupt();

Test_Image();

CommPara_Mbus.chbuff=&Buff_MBUS[0];

CommPara_HW.chbuff=&Buff_HW[0];

if(UCA1IFG&UCRXIFG)

{

UCA1IFG&=~UCRXIFG;

StreamHandler_putChar((CommData*)&CommPara_Mbus,UCA1RXBUF);

}

if(UCA0IFG&UCRXIFG)

{

UCA0IFG&=~UCRXIFG;

StreamHandler_putChar((CommData*)&CommPara_HW,UCA0RXBUF);

}

ApplayerHandler();

if(ImagPara.curstate==0x04)

{

Flash_Erase(APP_VECSTARTADDR,APP_VECLEN);

Flash_Erase(APP_CODESTARTADDR,APPSIZE);

EEP_TO_FRAM();

if(Flash_check()==0)

{

ImagPara.curstate=0x05;

}

else

{

ImagPara.curstate=0x06;

}

adjust_write((uint8*)&ImagPara,IMAGE_ADDR,sizeof(Image));

}

if(ImagPara.curstate==0x06)

{

asm("mov&0xEFFE,PC;");

}

}

}

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭