tonyp12 26 Posted April 14, 2016 Share Posted April 14, 2016 The idea is that any new firmware does not include the upper 512bytes of Flash,but as IRQ vectors will change with new firmware but is now part of the firmware-block as compiler Intvec have been moved -512 bytes down.If you put your custom Loader in the upper 512bytes too and as you never erase this block, much less chance of bricking. I guess opcode for BR could change from msp family? but this does work on a G2553.?CCS could use pragma location if it can not handle @ Not all vectors are available or used, so you should fill them with random value instead for the BSL password if you want some security. But at least the BSL password will now stay the same from reversions. static const unsigned int jumptable[49] @0xFF9E = { 0x4210,0xFDE0, // indirect BR &0x---- 0x4210,0xFDE2, 0x4210,0xFDE4, 0x4210,0xFDE6, 0x4210,0xFDE8, 0x4210,0xFDEA, 0x4210,0xFDEC, 0x4210,0xFDEE, 0x4210,0xFDF0, 0x4210,0xFDF2, 0x4210,0xFDF4, 0x4210,0xFDF6, 0x4210,0xFDF8, 0x4210,0xFDFA, 0x4210,0xFDFC, 0x4210,0xFDFE, 0x0000, // BSL signature 0xFF9E,0xFFA2, // real intvec 0xFFA6,0xFFAA, 0xFFAE,0xFFB2, 0xFFB6,0xFFBA, 0xFFBE,0xFFC2, 0xFFC6,0xFFCA, 0xFFCE,0xFFD2, 0xFFD6,0xFFDA }; int main( void ) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer if (jumptable[0] == 0xffff) {while(1){};}; // need to use array for something Override default location of linker file and make a copy of it and move it to local project folder and edit: // ------------------------------------- // Signature memory and interrupt vectors // -Z(CONST)SIGNATURE=FFDE-FFDF // used by BSL -Z(CODE)INTVEC=FDE0-FDFF // normally FFE0-FFFF -Z(CODE)RESET=FDFE-FDFF // normally FFFE-FFFF bluehash, oPossum, tripwire and 2 others 5 Quote Link to post Share on other sites
greeeg 460 Posted April 15, 2016 Share Posted April 15, 2016 Good solution. The larger msp chips feature a flag to move interrupt vectors into the top of RAM. This is used for the same purpose. But removes a few cycles of overhead. Quote Link to post Share on other sites
tonyp12 26 Posted April 24, 2016 Author Share Posted April 24, 2016 #include "msp430.h" #define UART_RX BIT1 #define UART_TX BIT2 #define UART_PORT(x) (P1 ##x) #define softintvec 0xC0004210 // start of flash + opcode for BR void bootloader_reset(void); void TXdata(char* pnt, int len); void bootloader_USCIAB0TX(void); void bootloader_flasherase(void); __interrupt void bootloaderRX_ISR(void); //-------------------- define structures -------------------- struct jumpstruct { const unsigned long branch[16]; const unsigned int bsl; const unsigned long* vector[16]; }; //-------------------- declare strings ---------------------- #pragma location = "BOOTSTRINGS" const char uartstring1[] = "run main, password anytime erases\r\n"; #pragma location = "BOOTSTRINGS" const char uartstring2[] = "Ready for Firmware\r\n"; //-------------------- reserve a fixed ram location --------- #pragma location = 0x200 __no_init char* passwordpnt; //-------------------- entry on reset ----------------------- #pragma location = "BOOTLOADER" void bootloader_reset(void) { asm(" MOV #SFE(CSTACK), SP"); // set stack pointer WDTCTL = WDTPW+WDTHOLD; if (CALBC1_1MHZ != 0xff){ // erased by mistake? BCSCTL1 = CALBC1_1MHZ; // Set DCO to factory calibrate 1MHz DCOCTL = CALDCO_1MHZ; } UCA0CTL1 = UCSWRST; // Set UCSWRST (hold USCI in Reset state) UCA0CTL1 |= UCSSEL_2; // Use SMCLK UCA0CTL0 = 0; // UART N,8,1 UCA0BR0 = 104; // upper register (9600) UCA0BR1 = 0; // the lower rate register UCA0MCTL = UCBRS1; // don't use modulation as it jitters UART_PORT(SEL) |= UART_TX + UART_RX; UART_PORT(SEL2) |= UART_TX + UART_RX; UCA0CTL1 &= ~UCSWRST; // relase reset, Initialize USCI state machine IE2 |= UCA0RXIE; // enable USCI_A0 RX interrupt if (*(int*)0xC01E != 0xffff){ // is reset vector filled in? TXdata((char*)&uartstring1, sizeof(uartstring1)-1); passwordpnt = (char*) &uartstring1; // use string1 as password __bis_SR_register(GIE); // so our RX_ISR can get data asm (" BR &0xC01E"); // indirect jump } TXdata((char*)&uartstring2, sizeof(uartstring2)-1); BCSCTL3 |= LFXT1S_2; // aclk = vloclk BCSCTL1 |= DIVA_3; // aclk divided by 8 WDTCTL = WDTPW+WDTCNTCL+WDTSSEL; // aclk sourced ~28sec __bis_SR_register(LPM3_bits); // trap it } //-------------------- uart byte tx routine ----------------- #pragma location = "BOOTLOADER" void TXdata(char* pnt, int len) { while(len--){ UCA0TXBUF = *pnt++; while (!(IFG2 & UCA0TXIFG)); } } //-------------------- UartRX sniffer ISR ------------------- #pragma location = "BOOTLOADER" __interrupt void bootloaderRX_ISR(void){ if (IFG2 & UCA0RXIFG){ // our USCI_A0 Recive Interrupt? if (UCA0RXBUF == *passwordpnt){ // a match? if (++passwordpnt == uartstring1+sizeof(uartstring1)-3){ bootloader_flasherase(); WDTCTL = WDTPW+WDTCNTCL+WDTSSEL; // reset the system __bis_SR_register_on_exit(LPM3_bits); } } else passwordpnt = (char*) &uartstring1; // reset it to the start if (*(int*)0xC00E != 0xffff){ // is USCIAB0RX vector filled in? IFG2 |= UCA0RXIFG; // if real routine needs it asm (" BR &0xC00E"); // indirect jump to user isr } } } //-------------------- flash erase blocks ------------------- #pragma location = "BOOTLOADER" void bootloader_flasherase(void){ int* pnt = (int*) 0xC000; // start of flash unsigned int i = 16*2-1; // erase 16K -512B WDTCTL = WDTPW+WDTHOLD; // no WDT __bic_SR_register(GIE); // so no interupt FCTL2 = FWKEY + FSSEL0 + FN1; // MCLK/3 for Flash Timing Generator FCTL3 = FWKEY; // Clear Lock bit while (i--){ FCTL1 = FWKEY + ERASE; // Set Erase bit *pnt = 0; // Dummy write to erase Flash block pnt += 256; // 256 ints up (e.g 512 bytes) } FCTL3 = FWKEY + LOCK; // Set LOCK bit } //-------------------- const rejumping real intvec ---------- #pragma location = "JUMPTABLE" const struct jumpstruct jumptable = { .branch[0] = softintvec + 0 * 0x20000u, .branch[1] = softintvec + 1 * 0x20000u, .branch[2] = softintvec + 2 * 0x20000u, .branch[3] = softintvec + 3 * 0x20000u, .branch[4] = softintvec + 4 * 0x20000u, .branch[5] = softintvec + 5 * 0x20000u, .branch[6] = softintvec + 6 * 0x20000u, .branch[7] = softintvec + 7 * 0x20000u, .branch[8] = softintvec + 8 * 0x20000u, .branch[9] = softintvec + 9 * 0x20000u, .branch[10] = softintvec + 10 * 0x20000u, .branch[11] = softintvec + 10 * 0x20000u, .branch[12] = softintvec + 12 * 0x20000u, .branch[13] = softintvec + 13 * 0x20000u, .branch[14] = softintvec + 14 * 0x20000u, .branch[15] = softintvec + 15 * 0x20000u, .bsl = 0x0000, .vector[0] = &jumptable.branch[0], .vector[1] = &jumptable.branch[1], .vector[2] = &jumptable.branch[2], .vector[3] = &jumptable.branch[3], .vector[4] = &jumptable.branch[4], .vector[5] = &jumptable.branch[5], .vector[6] = &jumptable.branch[6], .vector[7] = (unsigned long*) &bootloaderRX_ISR, .vector[8] = &jumptable.branch[8], .vector[9] = &jumptable.branch[9], .vector[10] = &jumptable.branch[10], .vector[11] = &jumptable.branch[11], .vector[12] = &jumptable.branch[12], .vector[13] = &jumptable.branch[13], .vector[14] = &jumptable.branch[14], .vector[15] = (unsigned long*) &bootloader_reset }; #pragma required=jumptable // tell compiler it's not a dead var Override linker location, copy it and edit the last sections so it looks like thisit moves intvec to just before code so firmware is just now one block including the vectors -Z(CONST)DATA16_C,DATA16_ID,TLS16_ID,DIFUNCT,CHECKSUM=C020-FDFF // normally C000-FFDD // ------------------------------------- // Code // -Z(CODE)CSTART,ISR_CODE,CODE_ID=C020-FDFF // normally C000-FFDD -P(CODE)CODE=C020-FDFF // normally C000-FFDD // ------------------------------------- // Signature memory and interrupt vectors // -Z(CONST)SIGNATURE=FFDE-FFDF -Z(CODE)INTVEC=C000-C01F // normally FFE0-FFFF -Z(CODE)RESET=C01E-C01F // normally FFFE-FFFF -Z(CODE)BOOTLOADER=FE00-FF5F // new addition -Z(CONST)BOOTSTRINGS=FF60-FF9D // new addition -Z(CONST)JUMPTABLE=FF9E-FFFF // new addition ?Done with IAR Workbench for G2553 The bootloaders Uart RX routine sniffs all incoming data so user can share uart for its intended purpose, so if you have a Cellular GSM module and you want remote firmware update capability ?this may be best near un-brickable way, as soon it detects the password it erase the Flash (except the boot loader block) and now it will go in to a waiting sequence for new firmware, It will send a text string ~28second to remind you. ?The firmware Flash Loader itself is not done yet, probably need to move up to a 1K size block to fit everything dubnet and oPossum 2 Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.