DSP

基于CCS工程MSP430串口升级(一)

2019-07-13 16:46发布

第一次接触MSP430的芯片,第一次使用CCS开发环境,花了将近一个星期的时间,才把MSP430串口升级做出来。 同样分成BOOT,APP,上位机,三个部分来讲解。

BOOT

  1. 在lnk_msp430fg479.cmd中修改BOOT Flash的起始地址(0xF000~0xFFE0),将近4K的Flash
MEMORY { SFR : origin = 0x0000, length = 0x0010 PERIPHERALS_8BIT : origin = 0x0010, length = 0x00F0 PERIPHERALS_16BIT : origin = 0x0100, length = 0x0100 RAM : origin = 0x0200, length = 0x0800 INFOA : origin = 0x10C0, length = 0x0040 INFOB : origin = 0x1080, length = 0x0040 INFOC : origin = 0x1040, length = 0x0040 INFOD : origin = 0x1000, length = 0x0040 // FLASH : origin = 0x1100, length = 0xEEE0 FLASH : origin = 0xF000, length = 0x0FE0 INT00 : origin = 0xFFE0, length = 0x0002 INT01 : origin = 0xFFE2, length = 0x0002 INT02 : origin = 0xFFE4, length = 0x0002 INT03 : origin = 0xFFE6, length = 0x0002 INT04 : origin = 0xFFE8, length = 0x0002 INT05 : origin = 0xFFEA, length = 0x0002 INT06 : origin = 0xFFEC, length = 0x0002 INT07 : origin = 0xFFEE, length = 0x0002 INT08 : origin = 0xFFF0, length = 0x0002 INT09 : origin = 0xFFF2, length = 0x0002 INT10 : origin = 0xFFF4, length = 0x0002 INT11 : origin = 0xFFF6, length = 0x0002 INT12 : origin = 0xFFF8, length = 0x0002 INT13 : origin = 0xFFFA, length = 0x0002 INT14 : origin = 0xFFFC, length = 0x0002 RESET : origin = 0xFFFE, length = 0x0002 }
  1. 中断向量重映射,BOOT中断函数跳转到APP中断函数
// Timer A0 interrupt service routine #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=TIMERA0_VECTOR __interrupt void Timer_A (void) #elif defined(__GNUC__) void __attribute__ ((interrupt(TIMERA0_VECTOR))) Timer_A (void) #else #error Compiler not supported! #endif { asm(" br &0xEFEC;"); } #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=SD16A_VECTOR __interrupt void SD16ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(SD16A_VECTOR))) SD16ISR (void) #else #error Compiler not supported! #endif { asm(" br &0xEFEE;"); } // Watchdog Timer interrupt service routine #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=WDT_VECTOR __interrupt void watchdog_timer(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(WDT_VECTOR))) watchdog_timer (void) #else #error Compiler not supported! #endif { asm(" br &0xEFF4;"); } #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=USCIAB0RX_VECTOR __interrupt void USCI_A0_rx (void) #elif defined(__GNUC__) void __attribute__ ((interrupt(USCIAB0RX_VECTOR))) USCI_A0_rx (void) #else #error Compiler not supported! #endif { // printf("%c",UCA0RXBUF); // if(isBoot==2) // { // u16 rxAddr = 0xBFF2 ; // ((void (*)(void))appAddr)(); asm(" br &0xEFF2;"); // } // else // { // rx_buf[rx_buf_index++] = UCA0RXBUF; // if(rx_buf_index>=RX_SIZE) // rx_buf_index = 0; // } }
  1. 这边需要注意的一点是,APP和BOOT的中断函数不要有冲突,有重复。比如APP有串口接收中断,BOOT就不能有串口接收中断。至于为什么,后面再解释。在这里,APP的内容比较多,必须要有串口接收中断提高实时性,那就只能委屈BOOT轮询串口缓冲。
while(1) { // delay_ms(1000); for(i=0;i<0x7fff;i++) { if(IFG2&UCA0RXIFG) { i=0; rx_buf[rx_buf_index++] = UCA0RXBUF; if(rx_buf_index>=RX_SIZE) rx_buf_index = 0; } } if(rx_buf_index > 5) { if(rx_buf[0]==MODBUS_DO) { crc = CRC16(rx_buf, rx_buf_index-2); if(crc == ((rx_buf[rx_buf_index-1]<<8)|rx_buf[rx_buf_index-2])) { switch(rx_buf[1]) { case 0x03: Modbus_Function_3(); break; case 0x10: Modbus_Function_10(); break; case 0x45: Modbus_Function_45(); break; } } } rx_buf_index = 0; } }
  1. Flash读写,MSP430FG479这款MCU,一个片区512字节,所以需要整片512字节的擦除写入。每次写入前,先把该片区的512字节读取到缓存中,再将需要修改的内容填充到缓存中,最后一次将512字节写入Flash片区
    在这里插入图片描述
void Flash_SecureWrite(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite) { int i=0; u16 offsetAddr = WriteAddr%512; u16 baseAddr = WriteAddr-offsetAddr; FLASH_Read(baseAddr, tx_buf, 512); for(i=0; i
  1. 拷贝结束后,BOOT跳转到APP。
void Boot2App(void) { // u16 appAddr = 0xBFFE ;// 0x1200 FLASH_Read(PROJECT_VERSION_ADDR,(u8 *)projectVersion,0x10); FLASH_Read(FLASH_OTA_STATUS_ADDR,(u8 *)&isBoot,2);//App(0) or Boot(1) if(isBoot==0) { if(strstr(projectVersion,"AquaDO")) { isBoot = 2; delay_ms(1000); rs485_send("Boot2App ",strlen("Boot2App ")); asm(" mov &0xEFFE,PC;"); // asm(" mov #0xBFFE,PC;"); // asm(" mov #0x1200,PC;"); // asm(" br &0x1200;"); // asm(" LB 0x1200"); // ((void (*)(void))appAddr)(); } } } 在这里插入图片描述