专家
公告
财富商城
电子网
旗下网站
首页
问题库
专栏
标签库
话题
专家
NEW
门户
发布
提问题
发文章
TI
求指导msp430的iap升级功能
2019-07-15 15:08
发布
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
站内问答
/
TI MCU
10587
10
1007
关于msp430的iap升级功能哪个大神可以指导一下:1怎么分别修改boot和app的.xcl文件?2中断向量表是如何重定义的?
友情提示:
此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
10条回答
tuiming817
1楼-- · 2019-07-16 08:02
[C]
纯文本查看
复制代码
#if __VER__ < 200#pragma codeseg(UPDATECODE) //在IAR2.0以下的程序定位函数#endif#include <msp430x14x.h>#include "hportini.h" /*warning:以下内容不能更改!!!!*/#define Upadte_Mode_Usart 0x01#define Upadte_Mode_GPRS 0x02#define Upadte_USART0 0x10#define Upadte_USART1 0x11#define Upadte_XTL_4M 0x21#define Upadte_XTL_8M 0x22 #define Upadte_Port1 0x31#define Upadte_Port2 0x32#define Upadte_Port3 0x33#define Upadte_Port4 0x34#define Upadte_Port5 0x35#define Upadte_Port6 0x36#define Upadte_BIT0 BIT0#define Upadte_BIT1 BIT1#define Upadte_BIT2 BIT2#define Upadte_BIT3 BIT3#define Upadte_BIT4 BIT4#define Upadte_BIT5 BIT5#define Upadte_BIT6 BIT6#define Upadte_BIT7 BIT7#define Upadte_PortBaud_2400 0x90#define Upadte_PortBaud_4800 0x91#define Upadte_PortBaud_9600 0x92#define Upadte_PortBaud_19200 0x93#define Upadte_PortBaud_38400 0x94#define Upadte_PortBaud_57600 0x95#define Upadte_PortBaud_115200 0x96#if __VER__ < 200#include <update.h>#else#include "hupdate.h"#endif #if (Upadte_USARTx == Upadte_USART0) #define Update_RXBUFx RXBUF0 #define Update_TXBUFx TXBUF0 #define Update_UCTLx UCTL0 #define Update_UTCTLx UTCTL0 #define Update_URCTLx URCTL0 #define Update_UBR0x UBR00 #define Update_UBR1x UBR10 #define Update_UMCTLx UMCTL0 #define Update_MEx ME1 #define Update_UTXEx UTXE0 #define Update_URXEx URXE0 #define Update_IFGx IFG1 #define Update_URXIFGx URXIFG0 #define Update_Usart_PortIni P3SEL|=(BIT4+BIT5); P3DIR|=BIT4; P3DIR&=~BIT5 #elif (Upadte_USARTx == Upadte_USART1) #define Update_RXBUFx RXBUF1 #define Update_TXBUFx TXBUF1 #define Update_UCTLx UCTL1 #define Update_UTCTLx UTCTL1 #define Update_URCTLx URCTL1 #define Update_UBR0x UBR01 #define Update_UBR1x UBR11 #define Update_UMCTLx UMCTL1 #define Update_MEx ME2 #define Update_UTXEx UTXE1 #define Update_URXEx URXE1 #define Update_IFGx IFG2 #define Update_URXIFGx URXIFG1 #define Update_Usart_PortIni P3SEL|=(BIT6+BIT7); P3DIR|=BIT6; P3DIR&=~BIT7 #else#error "Upadte_USARTx define error!"#endif #if (Upadte_CleDog_Portx == Upadte_Port1) #define Upadte_CleDog_SEL P1SEL #define Upadte_CleDog_DIR P1DIR #define Upadte_CleDog_PxOUT P1OUT#elif (Upadte_CleDog_Portx == Upadte_Port2) #define Upadte_CleDog_SEL P2SEL #define Upadte_CleDog_DIR P2DIR #define Upadte_CleDog_PxOUT P2OUT#elif (Upadte_CleDog_Portx == Upadte_Port3) #define Upadte_CleDog_SEL P3SEL #define Upadte_CleDog_DIR P3DIR #define Upadte_CleDog_PxOUT P3OUT#elif (Upadte_CleDog_Portx == Upadte_Port4) #define Upadte_CleDog_SEL P4SEL #define Upadte_CleDog_DIR P4DIR #define Upadte_CleDog_PxOUT P4OUT#elif (Upadte_CleDog_Portx == Upadte_Port5) #define Upadte_CleDog_SEL P5SEL #define Upadte_CleDog_DIR P5DIR #define Upadte_CleDog_PxOUT P5OUT#elif (Upadte_CleDog_Portx == Upadte_Port6) #define Upadte_CleDog_SEL P6SEL #define Upadte_CleDog_DIR P6DIR #define Upadte_CleDog_PxOUT P6OUT#else#error "Upadte_CleDog_Portx define error!"#endif#if (Upadte_485CS_Portx == Upadte_Port1) #define Upadte_485CS_SEL P1SEL #define Upadte_485CS_DIR P1DIR #define Upadte_485CS_PxOUT P1OUT#elif (Upadte_485CS_Portx == Upadte_Port2) #define Upadte_485CS_SEL P2SEL #define Upadte_485CS_DIR P2DIR #define Upadte_485CS_PxOUT P2OUT#elif (Upadte_485CS_Portx == Upadte_Port3) #define Upadte_485CS_SEL P3SEL #define Upadte_485CS_DIR P3DIR #define Upadte_485CS_PxOUT P3OUT#elif (Upadte_485CS_Portx == Upadte_Port4) #define Upadte_485CS_SEL P4SEL #define Upadte_485CS_DIR P4DIR #define Upadte_485CS_PxOUT P4OUT#elif (Upadte_485CS_Portx == Upadte_Port5) #define Upadte_485CS_SEL P5SEL #define Upadte_485CS_DIR P5DIR #define Upadte_485CS_PxOUT P5OUT#elif (Upadte_485CS_Portx == Upadte_Port6) #define Upadte_485CS_SEL P6SEL #define Upadte_485CS_DIR P6DIR #define Upadte_485CS_PxOUT P6OUT#else#error "Upadte_485CS_Portx define error!"#endif#define Update_485CS_high Upadte_485CS_PxOUT |=Upadte_485CS_BITx#define Update_485CS_low Upadte_485CS_PxOUT &=(~Upadte_485CS_BITx)monitor void Port_Update(void);monitor void Update_init_comm(void);monitor void Update_Erase_Flash(unsigned short Flash_Start,unsigned char Times);monitor void Update_Time_Control(unsigned char Timer);monitor void Upadte_WriteYB(char *str,unsigned char strlen);monitor void Update_Delay(char dd);monitor void Update_Cle_Dog(void);#if __VER__ < 200monitor void RTU_Update_Usart(void)#else__monitor void RTU_Update_Usart(void)@"UPDATECODE"#endif{ IE1=0; IE2=0; //-------------- P1SEL &=~BIT2; P1DIR |=BIT2;//输出 //--------------- WDTCTL = WDTPW + WDTHOLD; // Stop WDT Update_Erase_Flash(0xFF00,1);//擦中断向量 FCTL1 = FWKEY + WRT; FCTL3 = FWKEY; //为防止更新过程中 传输终止,把初始PC改成 Port_Update()的入口 //这样当传输终止或者突然断电导致程序重新启动的 程序将从 Net_Update() 开始执行 *(int *)0xFFFE=0xFFD0;//此数据为Net_Update()的入口 //*(long *)0xFFD0=0x0A004031;//mov.w #0A00,SP; *(long *)0xFFD0=0x39004031; //*(long *)0xFFD4=0x115A12B0;//CALL Update_Upadte; *(long *)0xFFD4=0x406E12B0; while ((FCTL3 & BUSY) == BUSY); FCTL3 = FWKEY + LOCK; Port_Update();}/*//////////////////////////串口更新说明//////////////////////////////程序入口只有一个:输入"+LANDSLANDS""+LANDSTESTA""U"之后进入一旦进入此程序则只有一个出口:当程序更新完成并校验通过!要求更新过程中不能断电:当用户收到"115200!Ready!"字样后一直到出现"Sucess!"字样期间断电则程序不能恢复!!!!当程序传输过程中丢数了,即传输完成后没有出现"Sucess!"字样则需要等待约 1.5 分钟,出现 "Afresh!115200!Ready!"后再发送文件!当传输完成后显示 "Fail"字样则直接再次发送文件如果更新一次成功,一般情况下,115200只需要 5S 时间*/#if __VER__ < 200monitor void Port_Update(void)#else__monitor void Port_Update(void)@"UPDATECODE"#endif{unsigned char bt,i; unsigned short crc,flag,flash,j,num; char Str[7]; char Int_[32]; IE1=0; IE2=0; WDTCTL=WDTPW+WDTHOLD; /* IO脚初始化 喂狗脚 */ Upadte_CleDog_SEL &= ~Upadte_CleDog_BITx; Upadte_CleDog_DIR |= Upadte_CleDog_BITx; /* 485 片选引脚初始化 */ Upadte_485CS_SEL &= ~Upadte_485CS_BITx; Upadte_485CS_DIR |= Upadte_485CS_BITx; BCSCTL1 &= ~XTS; // ACLK = LFXT1 = low XTAL 32768 BCSCTL2 = 0; //init_port(); //Open_4M(); BCSCTL1 &= 0x7f; // xt2 on j=10; do { j--; IFG1 &= ~OFIFG; // Clear OSCFault flag Update_Cle_Dog(); for (i = 0xFF; i > 0; i--); // Time for flag to set }while((j!=0)&&((IFG1 & OFIFG) != 0)); // OSCFault flag still set? //if (j==0) WDTCTL=0; //晶体失败 BCSCTL2 |= SELM1+SELS; // MCLK = SMCLK = XT2 Update_init_comm();//发送 "Ready!" Str[0]=0x0A; Str[1]=82; Str[2]=101; Str[3]=97; Str[4]=100; Str[5]=121; Str[6]=33; Upadte_WriteYB(Str,7); Update_Erase_Flash(0x4400,93);//0x4400-0xFE00 flag=0; flash=0; crc=0x0003;//防止接收2个数就跳出 while 循环 FCTL1 = FWKEY + WRT; FCTL3 = FWKEY; //接收数据 , 写到FLASH 里/*数据结构:数据长度2个字节 + @2000~@FFDF若干字节 + @ffe0~@ffff中断向量32个字节 + crc校验两个字节////////////////数据长度\\\\\\\*/ Update_Time_Control(0x90); //??长时间收不到串口数据就重新启动,大约1分钟 do {bt=Update_RXBUFx; //接收程序的长度 switch(flag) {case 0:num=(bt<<8)&0xff00;break; case 1:num=num | bt;crc=num+32;break;//num长度是 @2000~@ffe0 之间字节个数 + 数据长度2 default:if(flag<num) {while ((FCTL3 & BUSY) == BUSY); *(char*)(0x43FE+flag)=bt;//从0x4E00开始写入(定义的数据区) } else Int_[flash++]=bt;//中断向量 break; } flag++; Update_Time_Control(0x5); }while(flag<crc);//中断向量32字节 crc两个字节 while ((FCTL3 & BUSY) == BUSY); FCTL3 = FWKEY + LOCK; //CRC校验是否相等,相等了退出,否则重新更新 flash=Update_RXBUFx; Update_Time_Control(0x5); bt=Update_RXBUFx; flash =((flash<<8)&0xFF00)|(bt&0x00FF); crc=0xffff; //预置16位寄存器为十六进制FFFF(即全为1)。称此寄存器为CRC寄存器 //计算CRC校验 for(j=0;j<num;j++) { Update_Cle_Dog(); //bt=*(char*)(0x1FFE+j);bt=*(char*)(0x43FE+j); if(j==0) bt=(num>>8)&0x00ff; if(j==1) bt=num&0x00ff; crc^= bt; //把第一个8位数据与16位CRC寄存器的低位相异或,把结果放于CRC寄存器 for(i=0;i<8;i++) { flag=crc & 0x0001; //检查最低位 crc>>=1; // 把寄存器的内容右移一位(朝低位),用0填补最高位 if(flag==0x0001) crc ^= 0xa001; //*如果最低位为1:CRC寄存器与多项式A001(1010 00000000 0001)进行异或 } } for(j=0;j<32;j++) {bt=Int_[j]; crc^= bt; //把第一个8位数据与16位CRC寄存器的低位相异或,把结果放于CRC寄存器 for(i=0;i<8;i++) { flag=crc & 0x0001; //检查最低位 crc>>=1; // 把寄存器的内容右移一位(朝低位),用0填补最高位 if(flag==0x0001) crc ^= 0xa001; //S如果最低位为1:CRC寄存器与多项式A001(1010 00000000 0001)进行异或 } } if(crc==flash) {Str[0]=83; Str[1]=117; Str[2]=99; Str[3]=101; Str[4]=115; Str[5]=115; Str[6]=33; Upadte_WriteYB(Str,7); Update_Erase_Flash(0xFFE0,1);//一旦传输结束则将中断向量的32字节恢复 FCTL1 = FWKEY + WRT; FCTL3 = FWKEY; flash=0xFFE0; for(i=0;i<32;i++) {Update_Cle_Dog(); while ((FCTL3 & BUSY) == BUSY); *(char*)(flash++)=Int_
; } while ((FCTL3 & BUSY) == BUSY); FCTL3 = FWKEY + LOCK; Update_Delay(10); } else { Str[0]=70; Str[1]=97; Str[2]=105; Str[3]=108; Str[4]=33; Str[5]=0x0A; Str[6]=0x0A; Upadte_WriteYB(Str,7); Update_Delay(10); }////////////////////////////////////////////////////////////////////////////////////////////////////////////////看门狗重新启动//////////////// WDTCTL &= 0xA57E;//~WDTPW ~WDTHOLD OPEN WDT TO RESTART while(1);}//comport 1 init:#if __VER__ < 200monitor void Update_init_comm(void)#else__monitor void Update_init_comm(void)@"UPDATECODE"#endif { #if (Upadte_XTL == Upadte_XTL_4M) #if (Upadte_PortBaud == Upadte_PortBaud_9600)//波特率设置 Update_UBR0x = 0xA0; Update_UBR1x = 0x01; Update_UMCTLx = 0xC0; #elif (Upadte_PortBaud == Upadte_PortBaud_19200)Update_UBR0x = 0xd0; Update_UBR1x = 0x0; Update_UMCTLx = 0x3; #elif (Upadte_PortBaud == Upadte_PortBaud_115200) Update_UBR0x = 0x22; Update_UBR1x = 0x00; Update_UMCTLx = 0xED; #else #error "Upadte_PortBaud define error!" #endif#elif (Upadte_XTL == Upadte_XTL_8M) #if (Upadte_PortBaud == Upadte_PortBaud_9600)//波特率设置 Update_UBR0x = 0x41; Update_UBR1x = 0x03; Update_UMCTLx = 0x00; #elif (Upadte_PortBaud == Upadte_PortBaud_115200) Update_UBR0x = 0x45; Update_UBR1x = 0x00; Update_UMCTLx = 0x4A; #else #error "Upadte_PortBaud define error!" #endif#else #error "Upadte_XTL define error!"#endif Update_UCTLx = CHAR+SWRST ; Update_UTCTLx = SSEL0+SSEL1; Update_URCTLx = 0x00; Update_MEx = Update_UTXEx+Update_URXEx; Update_UCTLx &=~ SWRST; Update_Usart_PortIni;}// 1100~19FF 存放升级程序#if __VER__ < 200monitor void Update_Erase_Flash(unsigned short Flash_Start,unsigned char Times)#else__monitor void Update_Erase_Flash(unsigned short Flash_Start,unsigned char Times)@"UPDATECODE"#endif{unsigned short i; unsigned char bt; i=Flash_Start; FCTL2 = FWKEY + FSSEL0 +FN0; //分频 FCTL3 = FWKEY; for(bt=0;bt<Times;bt++) {Update_Cle_Dog(); FCTL1 = FWKEY + ERASE; //擦除一段,因为多段擦除会把 UPDATECODE 段也一起擦除 while ( (FCTL3 & BUSY) == BUSY); //等待FLASH空闲********************************* *((char*)i)=0; //段内地址任意写,启动擦除 i+=0x200; } while ((FCTL3 & BUSY) == BUSY); FCTL3 = FWKEY + LOCK;}#if __VER__ < 200monitor void Update_Time_Control(unsigned char Timer)#else__monitor void Update_Time_Control(unsigned char Timer)@"UPDATECODE"#endif{ unsigned int Time_tt; unsigned char Str[7]; while(Timer--) {Time_tt=0xFFFF; while(Time_tt!=0) {Update_Cle_Dog(); if((Update_IFGx&Update_URXIFGx)==0x00) Time_tt--; else {Update_IFGx&=~Update_URXIFGx;return;} } } //规定时间内没有数据收到,则要求用户重新发送,终端重新就绪 //Afresh! Str[0]=65; Str[1]=102; Str[2]=114; Str[3]=101; Str[4]=115; Str[5]=104; Str[6]=33; Upadte_WriteYB(Str,7); Update_Delay(10); WDTCTL &= 0xA57E;//~WDTPW ~WDTHOLD OPEN WDT TO RESTART while(1);}#if __VER__ < 200monitor void Upadte_WriteYB(char *str,unsigned char strlen)#else__monitor void Upadte_WriteYB(char *str,unsigned char strlen)@"UPDATECODE"#endif{unsigned char i; Update_485CS_high; for(i=0;i<strlen;i++){ Update_TXBUFx=str
; while ((Update_UTCTLx&0x01)==0); } Update_485CS_low;}#if __VER__ < 200monitor void Update_Delay(char dd)#else__monitor void Update_Delay(char dd)@"UPDATECODE"#endif{int j; char i; for(i=0;i<dd;i++) { for(j=0;j<0xFFFF;j++); Update_Cle_Dog(); }}#if __VER__ < 200monitor void Update_Cle_Dog(void)#else__monitor void Update_Cle_Dog(void)@"UPDATECODE"#endif{ Upadte_CleDog_PxOUT|=Upadte_CleDog_BITx; //车机的喂狗IO是6.3 //rtu 6.0 _NOP(); Upadte_CleDog_PxOUT&=~Upadte_CleDog_BITx; }
加载中...
ctwywjer
2楼-- · 2019-07-16 09:15
精彩回答 2 元偷偷看……
加载中...
BJJRTD
3楼-- · 2019-07-16 15:15
[C]
纯文本查看
复制代码
//为防止更新过程中 传输终止,把初始PC改成 Port_Update()的入口 //这样当传输终止或者突然断电导致程序重新启动的 程序将从 Net_Update() 开始执行 *(int *)0xFFFE=0xFFD0;//此数据为Net_Update()的入口 //*(long *)0xFFD0=0x0A004031;//mov.w #0A00,SP; *(long *)0xFFD0=0x39004031; //*(long *)0xFFD4=0x115A12B0;//CALL Update_Upadte; *(long *)0xFFD4=0x406E12B0;
另一个帖子中这三句话比较难理解,下面是作者说的话:
这个不难,思路就是把你的更新程序强制编译到固定地址空间,主程序判断条件进入更新程序后,更新程序擦除主程序区,然后外部接收要更新的代码往里写就行了,当然,更新程序所在空间是不能擦除的。
如果考虑更新过程中更新失败的情况,那你就要了解430的启动过程,在进入更新程序的时候,先将要复位要执行的指令写到中断向量区,如果更新不成功,那么每次上电让它强制进你的更新程序,知道更新完毕。
你需要了解的有启动过程、中断向量等。给你三句关键程序,结合启动过程好好研究研究吧
*(int *)0xFFFE=0xFFD0;//430复位去0XFFFE取指令,这地址值是多少就跳到多少地址执行下一条指令,即复位后去0XFFFD取指令
*(long *)0xFFD0=0x0A004031;//mov.w #0A00,SP;//在下一条指令的地方写入要执行的指令,这是固定的,执行完后地址偏移4继续执行
*(long *)0xFFD4=0x117c12B0;//这句的意思就是第三条指令要调用更新程序了,117c就是更新程序的主函数所在的地址,12B0是调用函数指令
下面就开始IAP吧......
这样即使更新过程断了,下次上电还是会进入更新程序的直到更新完毕,细节地方自行研究
加载中...
pipompipom
4楼-- · 2019-07-16 16:06
谢谢大神的指导,写的非常详细,步骤也很清晰,再次感谢您的回答,让我学到了很多
加载中...
上一页
1
2
一周热门
更多
>
相关问题
CPLD的方波输出
4 个回答
11个版本Quartus II 软件下载,安装包网盘合集,附教程,47G!
20 个回答
请大家帮忙到21IC发展大家谈支持我申请新版面
20 个回答
【通知】21ic中国电子网服务条款 (所有人员必读)
1 个回答
满载而归乙亥年,大展鸿途庚子年---集签赢好礼
20 个回答
携手ADI,踏上电子工程师之巅—车辆电气化视频,答题领奖!
1 个回答
如何提升论坛质量,看你了!
20 个回答
【最终名单】二姨家喊你来拿100份新年大礼啦~
20 个回答
相关文章
×
关闭
采纳回答
向帮助了您的网友说句感谢的话吧!
非常感谢!
确 认
×
关闭
编辑标签
最多设置5个标签!
TI
保存
关闭
×
关闭
举报内容
检举类型
检举内容
检举用户
检举原因
广告推广
恶意灌水
回答内容与提问无关
抄袭答案
其他
检举说明(必填)
提交
关闭
×
关闭
您已邀请
15
人回答
查看邀请
擅长该话题的人
回答过该话题的人
我关注的人
#if __VER__ < 200#pragma codeseg(UPDATECODE) //在IAR2.0以下的程序定位函数#endif#include <msp430x14x.h>#include "hportini.h" /*warning:以下内容不能更改!!!!*/#define Upadte_Mode_Usart 0x01#define Upadte_Mode_GPRS 0x02#define Upadte_USART0 0x10#define Upadte_USART1 0x11#define Upadte_XTL_4M 0x21#define Upadte_XTL_8M 0x22 #define Upadte_Port1 0x31#define Upadte_Port2 0x32#define Upadte_Port3 0x33#define Upadte_Port4 0x34#define Upadte_Port5 0x35#define Upadte_Port6 0x36#define Upadte_BIT0 BIT0#define Upadte_BIT1 BIT1#define Upadte_BIT2 BIT2#define Upadte_BIT3 BIT3#define Upadte_BIT4 BIT4#define Upadte_BIT5 BIT5#define Upadte_BIT6 BIT6#define Upadte_BIT7 BIT7#define Upadte_PortBaud_2400 0x90#define Upadte_PortBaud_4800 0x91#define Upadte_PortBaud_9600 0x92#define Upadte_PortBaud_19200 0x93#define Upadte_PortBaud_38400 0x94#define Upadte_PortBaud_57600 0x95#define Upadte_PortBaud_115200 0x96#if __VER__ < 200#include <update.h>#else#include "hupdate.h"#endif #if (Upadte_USARTx == Upadte_USART0) #define Update_RXBUFx RXBUF0 #define Update_TXBUFx TXBUF0 #define Update_UCTLx UCTL0 #define Update_UTCTLx UTCTL0 #define Update_URCTLx URCTL0 #define Update_UBR0x UBR00 #define Update_UBR1x UBR10 #define Update_UMCTLx UMCTL0 #define Update_MEx ME1 #define Update_UTXEx UTXE0 #define Update_URXEx URXE0 #define Update_IFGx IFG1 #define Update_URXIFGx URXIFG0 #define Update_Usart_PortIni P3SEL|=(BIT4+BIT5); P3DIR|=BIT4; P3DIR&=~BIT5 #elif (Upadte_USARTx == Upadte_USART1) #define Update_RXBUFx RXBUF1 #define Update_TXBUFx TXBUF1 #define Update_UCTLx UCTL1 #define Update_UTCTLx UTCTL1 #define Update_URCTLx URCTL1 #define Update_UBR0x UBR01 #define Update_UBR1x UBR11 #define Update_UMCTLx UMCTL1 #define Update_MEx ME2 #define Update_UTXEx UTXE1 #define Update_URXEx URXE1 #define Update_IFGx IFG2 #define Update_URXIFGx URXIFG1 #define Update_Usart_PortIni P3SEL|=(BIT6+BIT7); P3DIR|=BIT6; P3DIR&=~BIT7 #else#error "Upadte_USARTx define error!"#endif #if (Upadte_CleDog_Portx == Upadte_Port1) #define Upadte_CleDog_SEL P1SEL #define Upadte_CleDog_DIR P1DIR #define Upadte_CleDog_PxOUT P1OUT#elif (Upadte_CleDog_Portx == Upadte_Port2) #define Upadte_CleDog_SEL P2SEL #define Upadte_CleDog_DIR P2DIR #define Upadte_CleDog_PxOUT P2OUT#elif (Upadte_CleDog_Portx == Upadte_Port3) #define Upadte_CleDog_SEL P3SEL #define Upadte_CleDog_DIR P3DIR #define Upadte_CleDog_PxOUT P3OUT#elif (Upadte_CleDog_Portx == Upadte_Port4) #define Upadte_CleDog_SEL P4SEL #define Upadte_CleDog_DIR P4DIR #define Upadte_CleDog_PxOUT P4OUT#elif (Upadte_CleDog_Portx == Upadte_Port5) #define Upadte_CleDog_SEL P5SEL #define Upadte_CleDog_DIR P5DIR #define Upadte_CleDog_PxOUT P5OUT#elif (Upadte_CleDog_Portx == Upadte_Port6) #define Upadte_CleDog_SEL P6SEL #define Upadte_CleDog_DIR P6DIR #define Upadte_CleDog_PxOUT P6OUT#else#error "Upadte_CleDog_Portx define error!"#endif#if (Upadte_485CS_Portx == Upadte_Port1) #define Upadte_485CS_SEL P1SEL #define Upadte_485CS_DIR P1DIR #define Upadte_485CS_PxOUT P1OUT#elif (Upadte_485CS_Portx == Upadte_Port2) #define Upadte_485CS_SEL P2SEL #define Upadte_485CS_DIR P2DIR #define Upadte_485CS_PxOUT P2OUT#elif (Upadte_485CS_Portx == Upadte_Port3) #define Upadte_485CS_SEL P3SEL #define Upadte_485CS_DIR P3DIR #define Upadte_485CS_PxOUT P3OUT#elif (Upadte_485CS_Portx == Upadte_Port4) #define Upadte_485CS_SEL P4SEL #define Upadte_485CS_DIR P4DIR #define Upadte_485CS_PxOUT P4OUT#elif (Upadte_485CS_Portx == Upadte_Port5) #define Upadte_485CS_SEL P5SEL #define Upadte_485CS_DIR P5DIR #define Upadte_485CS_PxOUT P5OUT#elif (Upadte_485CS_Portx == Upadte_Port6) #define Upadte_485CS_SEL P6SEL #define Upadte_485CS_DIR P6DIR #define Upadte_485CS_PxOUT P6OUT#else#error "Upadte_485CS_Portx define error!"#endif#define Update_485CS_high Upadte_485CS_PxOUT |=Upadte_485CS_BITx#define Update_485CS_low Upadte_485CS_PxOUT &=(~Upadte_485CS_BITx)monitor void Port_Update(void);monitor void Update_init_comm(void);monitor void Update_Erase_Flash(unsigned short Flash_Start,unsigned char Times);monitor void Update_Time_Control(unsigned char Timer);monitor void Upadte_WriteYB(char *str,unsigned char strlen);monitor void Update_Delay(char dd);monitor void Update_Cle_Dog(void);#if __VER__ < 200monitor void RTU_Update_Usart(void)#else__monitor void RTU_Update_Usart(void)@"UPDATECODE"#endif{ IE1=0; IE2=0; //-------------- P1SEL &=~BIT2; P1DIR |=BIT2;//输出 //--------------- WDTCTL = WDTPW + WDTHOLD; // Stop WDT Update_Erase_Flash(0xFF00,1);//擦中断向量 FCTL1 = FWKEY + WRT; FCTL3 = FWKEY; //为防止更新过程中 传输终止,把初始PC改成 Port_Update()的入口 //这样当传输终止或者突然断电导致程序重新启动的 程序将从 Net_Update() 开始执行 *(int *)0xFFFE=0xFFD0;//此数据为Net_Update()的入口 //*(long *)0xFFD0=0x0A004031;//mov.w #0A00,SP; *(long *)0xFFD0=0x39004031; //*(long *)0xFFD4=0x115A12B0;//CALL Update_Upadte; *(long *)0xFFD4=0x406E12B0; while ((FCTL3 & BUSY) == BUSY); FCTL3 = FWKEY + LOCK; Port_Update();}/*//////////////////////////串口更新说明//////////////////////////////程序入口只有一个:输入"+LANDSLANDS""+LANDSTESTA""U"之后进入一旦进入此程序则只有一个出口:当程序更新完成并校验通过!要求更新过程中不能断电:当用户收到"115200!Ready!"字样后一直到出现"Sucess!"字样期间断电则程序不能恢复!!!!当程序传输过程中丢数了,即传输完成后没有出现"Sucess!"字样则需要等待约 1.5 分钟,出现 "Afresh!115200!Ready!"后再发送文件!当传输完成后显示 "Fail"字样则直接再次发送文件如果更新一次成功,一般情况下,115200只需要 5S 时间*/#if __VER__ < 200monitor void Port_Update(void)#else__monitor void Port_Update(void)@"UPDATECODE"#endif{unsigned char bt,i; unsigned short crc,flag,flash,j,num; char Str[7]; char Int_[32]; IE1=0; IE2=0; WDTCTL=WDTPW+WDTHOLD; /* IO脚初始化 喂狗脚 */ Upadte_CleDog_SEL &= ~Upadte_CleDog_BITx; Upadte_CleDog_DIR |= Upadte_CleDog_BITx; /* 485 片选引脚初始化 */ Upadte_485CS_SEL &= ~Upadte_485CS_BITx; Upadte_485CS_DIR |= Upadte_485CS_BITx; BCSCTL1 &= ~XTS; // ACLK = LFXT1 = low XTAL 32768 BCSCTL2 = 0; //init_port(); //Open_4M(); BCSCTL1 &= 0x7f; // xt2 on j=10; do { j--; IFG1 &= ~OFIFG; // Clear OSCFault flag Update_Cle_Dog(); for (i = 0xFF; i > 0; i--); // Time for flag to set }while((j!=0)&&((IFG1 & OFIFG) != 0)); // OSCFault flag still set? //if (j==0) WDTCTL=0; //晶体失败 BCSCTL2 |= SELM1+SELS; // MCLK = SMCLK = XT2 Update_init_comm();//发送 "Ready!" Str[0]=0x0A; Str[1]=82; Str[2]=101; Str[3]=97; Str[4]=100; Str[5]=121; Str[6]=33; Upadte_WriteYB(Str,7); Update_Erase_Flash(0x4400,93);//0x4400-0xFE00 flag=0; flash=0; crc=0x0003;//防止接收2个数就跳出 while 循环 FCTL1 = FWKEY + WRT; FCTL3 = FWKEY; //接收数据 , 写到FLASH 里/*数据结构:数据长度2个字节 + @2000~@FFDF若干字节 + @ffe0~@ffff中断向量32个字节 + crc校验两个字节////////////////数据长度\\\\\\\*/ Update_Time_Control(0x90); //??长时间收不到串口数据就重新启动,大约1分钟 do {bt=Update_RXBUFx; //接收程序的长度 switch(flag) {case 0:num=(bt<<8)&0xff00;break; case 1:num=num | bt;crc=num+32;break;//num长度是 @2000~@ffe0 之间字节个数 + 数据长度2 default:if(flag<num) {while ((FCTL3 & BUSY) == BUSY); *(char*)(0x43FE+flag)=bt;//从0x4E00开始写入(定义的数据区) } else Int_[flash++]=bt;//中断向量 break; } flag++; Update_Time_Control(0x5); }while(flag<crc);//中断向量32字节 crc两个字节 while ((FCTL3 & BUSY) == BUSY); FCTL3 = FWKEY + LOCK; //CRC校验是否相等,相等了退出,否则重新更新 flash=Update_RXBUFx; Update_Time_Control(0x5); bt=Update_RXBUFx; flash =((flash<<8)&0xFF00)|(bt&0x00FF); crc=0xffff; //预置16位寄存器为十六进制FFFF(即全为1)。称此寄存器为CRC寄存器 //计算CRC校验 for(j=0;j<num;j++) { Update_Cle_Dog(); //bt=*(char*)(0x1FFE+j);bt=*(char*)(0x43FE+j); if(j==0) bt=(num>>8)&0x00ff; if(j==1) bt=num&0x00ff; crc^= bt; //把第一个8位数据与16位CRC寄存器的低位相异或,把结果放于CRC寄存器 for(i=0;i<8;i++) { flag=crc & 0x0001; //检查最低位 crc>>=1; // 把寄存器的内容右移一位(朝低位),用0填补最高位 if(flag==0x0001) crc ^= 0xa001; //*如果最低位为1:CRC寄存器与多项式A001(1010 00000000 0001)进行异或 } } for(j=0;j<32;j++) {bt=Int_[j]; crc^= bt; //把第一个8位数据与16位CRC寄存器的低位相异或,把结果放于CRC寄存器 for(i=0;i<8;i++) { flag=crc & 0x0001; //检查最低位 crc>>=1; // 把寄存器的内容右移一位(朝低位),用0填补最高位 if(flag==0x0001) crc ^= 0xa001; //S如果最低位为1:CRC寄存器与多项式A001(1010 00000000 0001)进行异或 } } if(crc==flash) {Str[0]=83; Str[1]=117; Str[2]=99; Str[3]=101; Str[4]=115; Str[5]=115; Str[6]=33; Upadte_WriteYB(Str,7); Update_Erase_Flash(0xFFE0,1);//一旦传输结束则将中断向量的32字节恢复 FCTL1 = FWKEY + WRT; FCTL3 = FWKEY; flash=0xFFE0; for(i=0;i<32;i++) {Update_Cle_Dog(); while ((FCTL3 & BUSY) == BUSY); *(char*)(flash++)=Int_; } while ((FCTL3 & BUSY) == BUSY); FCTL3 = FWKEY + LOCK; Update_Delay(10); } else { Str[0]=70; Str[1]=97; Str[2]=105; Str[3]=108; Str[4]=33; Str[5]=0x0A; Str[6]=0x0A; Upadte_WriteYB(Str,7); Update_Delay(10); }////////////////////////////////////////////////////////////////////////////////////////////////////////////////看门狗重新启动//////////////// WDTCTL &= 0xA57E;//~WDTPW ~WDTHOLD OPEN WDT TO RESTART while(1);}//comport 1 init:#if __VER__ < 200monitor void Update_init_comm(void)#else__monitor void Update_init_comm(void)@"UPDATECODE"#endif { #if (Upadte_XTL == Upadte_XTL_4M) #if (Upadte_PortBaud == Upadte_PortBaud_9600)//波特率设置 Update_UBR0x = 0xA0; Update_UBR1x = 0x01; Update_UMCTLx = 0xC0; #elif (Upadte_PortBaud == Upadte_PortBaud_19200)Update_UBR0x = 0xd0; Update_UBR1x = 0x0; Update_UMCTLx = 0x3; #elif (Upadte_PortBaud == Upadte_PortBaud_115200) Update_UBR0x = 0x22; Update_UBR1x = 0x00; Update_UMCTLx = 0xED; #else #error "Upadte_PortBaud define error!" #endif#elif (Upadte_XTL == Upadte_XTL_8M) #if (Upadte_PortBaud == Upadte_PortBaud_9600)//波特率设置 Update_UBR0x = 0x41; Update_UBR1x = 0x03; Update_UMCTLx = 0x00; #elif (Upadte_PortBaud == Upadte_PortBaud_115200) Update_UBR0x = 0x45; Update_UBR1x = 0x00; Update_UMCTLx = 0x4A; #else #error "Upadte_PortBaud define error!" #endif#else #error "Upadte_XTL define error!"#endif Update_UCTLx = CHAR+SWRST ; Update_UTCTLx = SSEL0+SSEL1; Update_URCTLx = 0x00; Update_MEx = Update_UTXEx+Update_URXEx; Update_UCTLx &=~ SWRST; Update_Usart_PortIni;}// 1100~19FF 存放升级程序#if __VER__ < 200monitor void Update_Erase_Flash(unsigned short Flash_Start,unsigned char Times)#else__monitor void Update_Erase_Flash(unsigned short Flash_Start,unsigned char Times)@"UPDATECODE"#endif{unsigned short i; unsigned char bt; i=Flash_Start; FCTL2 = FWKEY + FSSEL0 +FN0; //分频 FCTL3 = FWKEY; for(bt=0;bt<Times;bt++) {Update_Cle_Dog(); FCTL1 = FWKEY + ERASE; //擦除一段,因为多段擦除会把 UPDATECODE 段也一起擦除 while ( (FCTL3 & BUSY) == BUSY); //等待FLASH空闲********************************* *((char*)i)=0; //段内地址任意写,启动擦除 i+=0x200; } while ((FCTL3 & BUSY) == BUSY); FCTL3 = FWKEY + LOCK;}#if __VER__ < 200monitor void Update_Time_Control(unsigned char Timer)#else__monitor void Update_Time_Control(unsigned char Timer)@"UPDATECODE"#endif{ unsigned int Time_tt; unsigned char Str[7]; while(Timer--) {Time_tt=0xFFFF; while(Time_tt!=0) {Update_Cle_Dog(); if((Update_IFGx&Update_URXIFGx)==0x00) Time_tt--; else {Update_IFGx&=~Update_URXIFGx;return;} } } //规定时间内没有数据收到,则要求用户重新发送,终端重新就绪 //Afresh! Str[0]=65; Str[1]=102; Str[2]=114; Str[3]=101; Str[4]=115; Str[5]=104; Str[6]=33; Upadte_WriteYB(Str,7); Update_Delay(10); WDTCTL &= 0xA57E;//~WDTPW ~WDTHOLD OPEN WDT TO RESTART while(1);}#if __VER__ < 200monitor void Upadte_WriteYB(char *str,unsigned char strlen)#else__monitor void Upadte_WriteYB(char *str,unsigned char strlen)@"UPDATECODE"#endif{unsigned char i; Update_485CS_high; for(i=0;i<strlen;i++){ Update_TXBUFx=str; while ((Update_UTCTLx&0x01)==0); } Update_485CS_low;}#if __VER__ < 200monitor void Update_Delay(char dd)#else__monitor void Update_Delay(char dd)@"UPDATECODE"#endif{int j; char i; for(i=0;i<dd;i++) { for(j=0;j<0xFFFF;j++); Update_Cle_Dog(); }}#if __VER__ < 200monitor void Update_Cle_Dog(void)#else__monitor void Update_Cle_Dog(void)@"UPDATECODE"#endif{ Upadte_CleDog_PxOUT|=Upadte_CleDog_BITx; //车机的喂狗IO是6.3 //rtu 6.0 _NOP(); Upadte_CleDog_PxOUT&=~Upadte_CleDog_BITx; }
//为防止更新过程中 传输终止,把初始PC改成 Port_Update()的入口 //这样当传输终止或者突然断电导致程序重新启动的 程序将从 Net_Update() 开始执行 *(int *)0xFFFE=0xFFD0;//此数据为Net_Update()的入口 //*(long *)0xFFD0=0x0A004031;//mov.w #0A00,SP; *(long *)0xFFD0=0x39004031; //*(long *)0xFFD4=0x115A12B0;//CALL Update_Upadte; *(long *)0xFFD4=0x406E12B0;
另一个帖子中这三句话比较难理解,下面是作者说的话:
这个不难,思路就是把你的更新程序强制编译到固定地址空间,主程序判断条件进入更新程序后,更新程序擦除主程序区,然后外部接收要更新的代码往里写就行了,当然,更新程序所在空间是不能擦除的。
如果考虑更新过程中更新失败的情况,那你就要了解430的启动过程,在进入更新程序的时候,先将要复位要执行的指令写到中断向量区,如果更新不成功,那么每次上电让它强制进你的更新程序,知道更新完毕。
你需要了解的有启动过程、中断向量等。给你三句关键程序,结合启动过程好好研究研究吧
*(int *)0xFFFE=0xFFD0;//430复位去0XFFFE取指令,这地址值是多少就跳到多少地址执行下一条指令,即复位后去0XFFFD取指令
*(long *)0xFFD0=0x0A004031;//mov.w #0A00,SP;//在下一条指令的地方写入要执行的指令,这是固定的,执行完后地址偏移4继续执行
*(long *)0xFFD4=0x117c12B0;//这句的意思就是第三条指令要调用更新程序了,117c就是更新程序的主函数所在的地址,12B0是调用函数指令
下面就开始IAP吧......
这样即使更新过程断了,下次上电还是会进入更新程序的直到更新完毕,细节地方自行研究
一周热门 更多>