MSP430技术论坛
直播中

寇昕

7年用户 248经验值
私信 关注
[问答]

求指导msp430的iap升级功能

关于msp430的iap升级功能哪个大神可以指导一下:1怎么分别修改boot和app的.xcl文件?2中断向量表是如何重定义的?

回帖(10)

潘斯凯

2019-4-19 08:38:20
1.首先 ,你先写个正常的IAP程序 ,假设FLASH 地址范围是4000-FFFF 不去改任何地址。 假设你Code占用FLASH 为 4000-6000 ,然后 先写你的IAP程序, 把数据保存到 B000,用工具读取FLASH 查看写 没问题 没问题 没问题。。。这是最基本的FLASH写,先吧这个做好(用 FET MSP 软件)。
2.然后,你写个正常的点灯程序测试没问题之后。
3.你用IAP程序 ,你把link文件里面吧4000改成B000(把相关的 数据都要去修改) ,意思是  代码存放位置是B000-FFFF。 这个是IAP程序的存储地址。
你打开生成的txt 程序 文件开头就是  @B000 这个是 程序的启动地址 ,最下面 @FFE0 这个是默认的中断地址对应-Z(CODE)INTVEC=FFE0-FFFF(中断区)-Z(CODE)RESET=FFFE-FFFF(复位)
这样,你把 你的程序用IAP下载到4000的地址,在查看是否成功。   
4.把点灯程序 地址改为 4000-AFFF(相关的也要改,先不要用任何中断),
你打开生成的txt 程序 文件开头就是 @4000 这个是 程序的启动地址 ,最下面 @AFE0 这个是默认的中断地址对应-Z(CODE)INTVEC=AFE0-AFFF(中断区)-Z(CODE)RESET=AFFE-AFFF(复位)
5.用你修改过地址的IAP 程序  下载这个点灯程序。下载完成后 mov 一下 PC 指向 AFFE ,正常情况下
指针指向 AFFE 后复位 PC 会指向 4000地址去运行,
6.都好了之后可以用中断了。
1)简单的东西可以使用位置定义,IAP和APP定义变量 在同一个地址,然后在IAP里面执行中断,例如计数什么的,你通过指针就可以在APP里面获取。(最好流出一段RAM 做地址定位)
例如:
//-Z(DATA)DATA16_I,DATA16_Z,DATA16_N,DATA16_HEAP+_DATA16_HEAP_SIZE=1100-38FF (正常的)
-Z(DATA)DATA16_I,DATA16_Z,DATA16_N,DATA16_HEAP+_DATA16_HEAP_SIZE=1300-38FF(例如保留1100-1300用代码去访问,程序 不会再这里面分配数据)
2)复杂点的 用中断调转 比如 FFE0出的中断 进入中断了 你直接 br &0xAFE0  跳转到你的虚拟中断地址,在APP里面 写处理函数就行了。其他中断都是一样的操作,只要你地址不写错。
举报

陈燕

2019-4-19 08:57:57
向量表在顶头0xFFFF
举报

h1654155275.5764

2019-4-19 09:07:00
这是真实地址,你把链接文件改成假设 DFFF你再boot里面做中断跳转
举报

李志刚

2019-4-19 09:16:30
谢谢指导
举报

李静

2019-4-19 09:24:35
这个是 IAP的
//-Z(CONST)DATA16_C,DATA16_ID,DIFUNCT,CHECKSUM=4000-FFDF
-Z(CONST)DATA16_C,DATA16_ID,DIFUNCT,CHECKSUM=F000-FFDF   
// -------------------------------------
// Code
//
//-Z(CODE)CSTART,ISR_CODE,CODE_ID=4000-FFDF
//-P(CODE)CODE=4000-FFDF
-Z(CODE)CSTART,ISR_CODE,CODE_ID=F000-FFDF            //数据 变量存储位置
-P(CODE)CODE=F000-FFDF                                           //代码 存储位置     
// -------------------------------------
// Interrupt vectors
//
-Z(CODE)INTVEC=FFE0-FFFF
-Z(CODE)RESET=FFFE-FFFF
这个是APP的
//-Z(CONST)DATA16_C,DATA16_ID,DIFUNCT,CHECKSUM=4000-FFDF
-Z(CONST)DATA16_C,DATA16_ID,DIFUNCT,CHECKSUM=4000-EFDF
// -------------------------------------
// Code
//
//-Z(CODE)CSTART,ISR_CODE,CODE_ID=4000-FFDF
//-P(CODE)CODE=4000-FFDF
-Z(CODE)CSTART,ISR_CODE,CODE_ID=4000-EFDF
-P(CODE)CODE=4000-EFDF
// -------------------------------------
// Interrupt vectors
//
-Z(CODE)INTVEC=EFE0-EFFF
-Z(CODE)RESET=EFFE-EFFF
举报

杨梦月

2019-4-19 09:44:24
修改了link文件后,本身代码里面要添加什么东西吗?
举报

连比斐

2019-4-19 09:50:57
[C] 纯文本查看 复制代码
#if __VER__ < 200#pragma codeseg(UPDATECODE)    //在IAR2.0以下的程序定位函数#endif#include #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 #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>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;      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

肖东菁

2019-4-19 10:02:10
7楼里面关于iap的代码是哪些呢?函数前面monitor 和__monitor 是把函数放特定地址的意思吗?
#if __VER__ < 200
monitor void RTU_Update_Usart(void)
#else
__monitor void RTU_Update_Usart(void)@"UPDATECODE"
#endif
举报

王若峰

2019-4-19 10:16:43
[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吧......
这样即使更新过程断了,下次上电还是会进入更新程序的直到更新完毕,细节地方自行研究
举报

陈艳

2019-4-19 10:27:22
谢谢大神的指导,写的非常详细,步骤也很清晰,再次感谢您的回答,让我学到了很多
举报

更多回帖

×
20
完善资料,
赚取积分