Jump to content
43oh

tonyp12

Members
  • Content Count

    14
  • Joined

  • Last visited

  • Days Won

    6

Reputation Activity

  1. Like
    tonyp12 got a reaction from agaelema in Basic MSP430 GPIO Macros   
    As all gio registers start with port and then OUT, IN, IE etc, example: P1OUT, with some macro word scrambling you can do this:
    #define read & // words for common gpio interaction #define clear &= ~ #define set |= #define toggle ^= #define Button1(y,x) (P1 ##x y BIT0) // PORT and PIN (ignore the ##x y) #define BlueLED(y,x) (P2 ##x y BIT5) To use them: BlueLED(set,DIR); BlueLED(clear,OUT); Button1(clear,DIR);                       // a input Button1(set,OUT);                         // pull-up resistor Button1(set,REN);                           Button1(set,IES);                         // falling edge button1(clear,IFG); Button1(set,IE);                           
  2. Like
    tonyp12 got a reaction from Rickta59 in Basic MSP430 GPIO Macros   
    As all gio registers start with port and then OUT, IN, IE etc, example: P1OUT, with some macro word scrambling you can do this:
    #define read & // words for common gpio interaction #define clear &= ~ #define set |= #define toggle ^= #define Button1(y,x) (P1 ##x y BIT0) // PORT and PIN (ignore the ##x y) #define BlueLED(y,x) (P2 ##x y BIT5) To use them: BlueLED(set,DIR); BlueLED(clear,OUT); Button1(clear,DIR);                       // a input Button1(set,OUT);                         // pull-up resistor Button1(set,REN);                           Button1(set,IES);                         // falling edge button1(clear,IFG); Button1(set,IE);                           
  3. Like
    tonyp12 got a reaction from Fmilburn in Basic MSP430 GPIO Macros   
    As all gio registers start with port and then OUT, IN, IE etc, example: P1OUT, with some macro word scrambling you can do this:
    #define read & // words for common gpio interaction #define clear &= ~ #define set |= #define toggle ^= #define Button1(y,x) (P1 ##x y BIT0) // PORT and PIN (ignore the ##x y) #define BlueLED(y,x) (P2 ##x y BIT5) To use them: BlueLED(set,DIR); BlueLED(clear,OUT); Button1(clear,DIR);                       // a input Button1(set,OUT);                         // pull-up resistor Button1(set,REN);                           Button1(set,IES);                         // falling edge button1(clear,IFG); Button1(set,IE);                           
  4. Like
    tonyp12 got a reaction from bluehash in Hard intvec rejumping through Soft intvec for Firmware updates   
    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
  5. Like
    tonyp12 got a reaction from oPossum in Hard intvec rejumping through Soft intvec for Firmware updates   
    #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
  6. Like
    tonyp12 got a reaction from pine in Hard intvec rejumping through Soft intvec for Firmware updates   
    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
  7. Like
    tonyp12 got a reaction from dubnet in Hard intvec rejumping through Soft intvec for Firmware updates   
    #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
  8. Like
    tonyp12 got a reaction from greeeg in Hard intvec rejumping through Soft intvec for Firmware updates   
    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
  9. Like
    tonyp12 got a reaction from tripwire in Hard intvec rejumping through Soft intvec for Firmware updates   
    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
  10. Like
    tonyp12 got a reaction from oPossum in Hard intvec rejumping through Soft intvec for Firmware updates   
    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
  11. Like
    tonyp12 got a reaction from agaelema in tiny msp430 preemptive multitasking system   
    Tested on G2553 Launchpad with IAR, I recommend G2955 with 1K RAM if you want more than 3 task
    #include "msp430.h" #include "common.h" //=========================(C) Tony Philipsson 2016 ======================= funcpnt const taskpnt[]={ task1, task2, task3, // <- PUT YOUR TASKS HERE }; const int stacksize[tasks] = {28}; // a blank value defaults to 24 stack words //========================================================================= int taskstackpnt[tasks]; unsigned int taskdelay[tasks]; char taskrun; int main( void ) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer if (CALBC1_8MHZ != 0xff){ // erased by mistake? BCSCTL1 = CALBC1_8MHZ; // Set DCO to factory calibrate 1MHz DCOCTL = CALDCO_8MHZ; } int* multistack = (int*) __get_SP_register(); int i=0; while(i<tasks-1){ int j = stacksize[i]; if (!j) j = 24; multistack -= j; *(multistack) = (int) taskpnt[++i]; // prefill in PC *(multistack-1) = GIE; // prefill in SR taskstackpnt[i] = (int) multistack-26; // needs 12 dummy push words } WDTCTL = WDTPW+WDTTMSEL+WDTCNTCL; // 4ms interval at 8MHz smclk IE1 |= WDTIE; __bis_SR_register(GIE); asm ("br &taskpnt"); // indirect jmp to first task } //============= TASK SWITCHER ISR ============= #pragma vector = WDT_VECTOR __raw __interrupt void taskswitcher(void) { asm ("push R15\n push R14\n push R13\n push R12\n" "push R11\n push R10\n push R9\n push R8\n" "push R7\n push R6\n push R5\n push R4"); taskstackpnt[taskrun] = __get_SP_register(); if (++taskrun == tasks) taskrun = 0; __set_SP_register(taskstackpnt[taskrun]); asm ("pop R4\n pop R5\n pop R6\n pop R7\n" "pop R8\n pop R9\n pop R10\n pop R11\n" "pop R12\n pop R13\n pop R14\n pop R15"); } #include "msp430.h" #include "common.h" __task void task1(void){ P1DIR |= BIT0; while(1){ __delay_cycles(800000); P1OUT |= BIT0; __delay_cycles(800000); P1OUT &=~BIT0; } } #include "msp430.h" #include "common.h" __task void task2(void){ P1DIR |= BIT6; while(1){ __delay_cycles(1200000); P1OUT |= BIT6; __delay_cycles(1200000); P1OUT &=~BIT6; } } #include "msp430.h" #include "common.h" unsigned int fibo(int); __task void task3(void){ int temp = 0; while(1){ fibo(++temp); } } unsigned int fibo(int n){ if (n < 2) return n; else return (fibo(n-1) + fibo(n-2)); } #ifndef COMMON_H_ #define COMMON_H_ #define tasks (sizeof(taskpnt)/2) __task void task1(void); __task void task2(void); __task void task3(void); typedef __task void (*funcpnt)(void); #endif
  12. Like
    tonyp12 got a reaction from tripwire in tiny msp430 preemptive multitasking system   
    preemptive means that the code (e.g.each task that is pretty much its own main.c) does not know it is sharing a single mcu core.
    it does not need to say "i take a pause now so next task can go on", you can even run two instances of the same task (though not really useful)
     
    A higher power takes over and switch tasks.
    Sure there is stuff to add like system_sleep and priority and maybe even new task and end task etc.
     
    I plan to show how to use a 512Hz mems osc to NMI pin, so task switching can not be overridden by (maybe mistakenly) disabling GIE.

    ?wiki: Preemptive multitasking
    wiki: Cooperative multitasking
     
    P.S I also have a Cooperative multitasking system that uses a Event Machine in main.c and each (up to 16) tasks are all State Machines (switch/case) as that is a good time slicer.
    ?What I like about that is that I know I have exclusivity while I'm doing my thing so no race conditions.
    ?And very little overhead so better for battery-operation as task that needs to use a time-constant can sleep from 1ms to 64sec independently keeping in LPM3 95% of the time
  13. Like
    tonyp12 got a reaction from spirilis in tiny msp430 preemptive multitasking system   
    preemptive means that the code (e.g.each task that is pretty much its own main.c) does not know it is sharing a single mcu core.
    it does not need to say "i take a pause now so next task can go on", you can even run two instances of the same task (though not really useful)
     
    A higher power takes over and switch tasks.
    Sure there is stuff to add like system_sleep and priority and maybe even new task and end task etc.
     
    I plan to show how to use a 512Hz mems osc to NMI pin, so task switching can not be overridden by (maybe mistakenly) disabling GIE.

    ?wiki: Preemptive multitasking
    wiki: Cooperative multitasking
     
    P.S I also have a Cooperative multitasking system that uses a Event Machine in main.c and each (up to 16) tasks are all State Machines (switch/case) as that is a good time slicer.
    ?What I like about that is that I know I have exclusivity while I'm doing my thing so no race conditions.
    ?And very little overhead so better for battery-operation as task that needs to use a time-constant can sleep from 1ms to 64sec independently keeping in LPM3 95% of the time
  14. Like
    tonyp12 got a reaction from veryalive in tiny msp430 preemptive multitasking system   
    Tested on G2553 Launchpad with IAR, I recommend G2955 with 1K RAM if you want more than 3 task
    #include "msp430.h" #include "common.h" //=========================(C) Tony Philipsson 2016 ======================= funcpnt const taskpnt[]={ task1, task2, task3, // <- PUT YOUR TASKS HERE }; const int stacksize[tasks] = {28}; // a blank value defaults to 24 stack words //========================================================================= int taskstackpnt[tasks]; unsigned int taskdelay[tasks]; char taskrun; int main( void ) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer if (CALBC1_8MHZ != 0xff){ // erased by mistake? BCSCTL1 = CALBC1_8MHZ; // Set DCO to factory calibrate 1MHz DCOCTL = CALDCO_8MHZ; } int* multistack = (int*) __get_SP_register(); int i=0; while(i<tasks-1){ int j = stacksize[i]; if (!j) j = 24; multistack -= j; *(multistack) = (int) taskpnt[++i]; // prefill in PC *(multistack-1) = GIE; // prefill in SR taskstackpnt[i] = (int) multistack-26; // needs 12 dummy push words } WDTCTL = WDTPW+WDTTMSEL+WDTCNTCL; // 4ms interval at 8MHz smclk IE1 |= WDTIE; __bis_SR_register(GIE); asm ("br &taskpnt"); // indirect jmp to first task } //============= TASK SWITCHER ISR ============= #pragma vector = WDT_VECTOR __raw __interrupt void taskswitcher(void) { asm ("push R15\n push R14\n push R13\n push R12\n" "push R11\n push R10\n push R9\n push R8\n" "push R7\n push R6\n push R5\n push R4"); taskstackpnt[taskrun] = __get_SP_register(); if (++taskrun == tasks) taskrun = 0; __set_SP_register(taskstackpnt[taskrun]); asm ("pop R4\n pop R5\n pop R6\n pop R7\n" "pop R8\n pop R9\n pop R10\n pop R11\n" "pop R12\n pop R13\n pop R14\n pop R15"); } #include "msp430.h" #include "common.h" __task void task1(void){ P1DIR |= BIT0; while(1){ __delay_cycles(800000); P1OUT |= BIT0; __delay_cycles(800000); P1OUT &=~BIT0; } } #include "msp430.h" #include "common.h" __task void task2(void){ P1DIR |= BIT6; while(1){ __delay_cycles(1200000); P1OUT |= BIT6; __delay_cycles(1200000); P1OUT &=~BIT6; } } #include "msp430.h" #include "common.h" unsigned int fibo(int); __task void task3(void){ int temp = 0; while(1){ fibo(++temp); } } unsigned int fibo(int n){ if (n < 2) return n; else return (fibo(n-1) + fibo(n-2)); } #ifndef COMMON_H_ #define COMMON_H_ #define tasks (sizeof(taskpnt)/2) __task void task1(void); __task void task2(void); __task void task3(void); typedef __task void (*funcpnt)(void); #endif
  15. Like
    tonyp12 got a reaction from oPossum in tiny msp430 preemptive multitasking system   
    ?{28}; is the same thing as {28,0,0} and 28 was just random number to show something
    so if you forget to fill in all stack sizes for each task I will give you 24 words (48bytes)
     
    A minimum should  be 14 words if your task don't use the stack at all.
     
    -26, as I cast the address to (int) it's now a byte space referenced
    If I wrapped  it first
    (int) (multistack-13); it will be word referenced as it is a int pointer, probably should wrap it for next time,
    ?So I'm just adjusting the stack pointer to include the PC,SR and the 12 pop's it will see on first entry (only done for task2+)
    That is 14 words but Pop is post increment, it works if I do  -13 words
    the registers will have random data first time, but as task have not started doing anything yet it should not care.

    a POP R15 is actual a: MOV.W @R1+,R15
  16. Like
    tonyp12 got a reaction from enl in tiny msp430 preemptive multitasking system   
    Tested on G2553 Launchpad with IAR, I recommend G2955 with 1K RAM if you want more than 3 task
    #include "msp430.h" #include "common.h" //=========================(C) Tony Philipsson 2016 ======================= funcpnt const taskpnt[]={ task1, task2, task3, // <- PUT YOUR TASKS HERE }; const int stacksize[tasks] = {28}; // a blank value defaults to 24 stack words //========================================================================= int taskstackpnt[tasks]; unsigned int taskdelay[tasks]; char taskrun; int main( void ) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer if (CALBC1_8MHZ != 0xff){ // erased by mistake? BCSCTL1 = CALBC1_8MHZ; // Set DCO to factory calibrate 1MHz DCOCTL = CALDCO_8MHZ; } int* multistack = (int*) __get_SP_register(); int i=0; while(i<tasks-1){ int j = stacksize[i]; if (!j) j = 24; multistack -= j; *(multistack) = (int) taskpnt[++i]; // prefill in PC *(multistack-1) = GIE; // prefill in SR taskstackpnt[i] = (int) multistack-26; // needs 12 dummy push words } WDTCTL = WDTPW+WDTTMSEL+WDTCNTCL; // 4ms interval at 8MHz smclk IE1 |= WDTIE; __bis_SR_register(GIE); asm ("br &taskpnt"); // indirect jmp to first task } //============= TASK SWITCHER ISR ============= #pragma vector = WDT_VECTOR __raw __interrupt void taskswitcher(void) { asm ("push R15\n push R14\n push R13\n push R12\n" "push R11\n push R10\n push R9\n push R8\n" "push R7\n push R6\n push R5\n push R4"); taskstackpnt[taskrun] = __get_SP_register(); if (++taskrun == tasks) taskrun = 0; __set_SP_register(taskstackpnt[taskrun]); asm ("pop R4\n pop R5\n pop R6\n pop R7\n" "pop R8\n pop R9\n pop R10\n pop R11\n" "pop R12\n pop R13\n pop R14\n pop R15"); } #include "msp430.h" #include "common.h" __task void task1(void){ P1DIR |= BIT0; while(1){ __delay_cycles(800000); P1OUT |= BIT0; __delay_cycles(800000); P1OUT &=~BIT0; } } #include "msp430.h" #include "common.h" __task void task2(void){ P1DIR |= BIT6; while(1){ __delay_cycles(1200000); P1OUT |= BIT6; __delay_cycles(1200000); P1OUT &=~BIT6; } } #include "msp430.h" #include "common.h" unsigned int fibo(int); __task void task3(void){ int temp = 0; while(1){ fibo(++temp); } } unsigned int fibo(int n){ if (n < 2) return n; else return (fibo(n-1) + fibo(n-2)); } #ifndef COMMON_H_ #define COMMON_H_ #define tasks (sizeof(taskpnt)/2) __task void task1(void); __task void task2(void); __task void task3(void); typedef __task void (*funcpnt)(void); #endif
  17. Like
    tonyp12 got a reaction from zeke in tiny msp430 preemptive multitasking system   
    Tested on G2553 Launchpad with IAR, I recommend G2955 with 1K RAM if you want more than 3 task
    #include "msp430.h" #include "common.h" //=========================(C) Tony Philipsson 2016 ======================= funcpnt const taskpnt[]={ task1, task2, task3, // <- PUT YOUR TASKS HERE }; const int stacksize[tasks] = {28}; // a blank value defaults to 24 stack words //========================================================================= int taskstackpnt[tasks]; unsigned int taskdelay[tasks]; char taskrun; int main( void ) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer if (CALBC1_8MHZ != 0xff){ // erased by mistake? BCSCTL1 = CALBC1_8MHZ; // Set DCO to factory calibrate 1MHz DCOCTL = CALDCO_8MHZ; } int* multistack = (int*) __get_SP_register(); int i=0; while(i<tasks-1){ int j = stacksize[i]; if (!j) j = 24; multistack -= j; *(multistack) = (int) taskpnt[++i]; // prefill in PC *(multistack-1) = GIE; // prefill in SR taskstackpnt[i] = (int) multistack-26; // needs 12 dummy push words } WDTCTL = WDTPW+WDTTMSEL+WDTCNTCL; // 4ms interval at 8MHz smclk IE1 |= WDTIE; __bis_SR_register(GIE); asm ("br &taskpnt"); // indirect jmp to first task } //============= TASK SWITCHER ISR ============= #pragma vector = WDT_VECTOR __raw __interrupt void taskswitcher(void) { asm ("push R15\n push R14\n push R13\n push R12\n" "push R11\n push R10\n push R9\n push R8\n" "push R7\n push R6\n push R5\n push R4"); taskstackpnt[taskrun] = __get_SP_register(); if (++taskrun == tasks) taskrun = 0; __set_SP_register(taskstackpnt[taskrun]); asm ("pop R4\n pop R5\n pop R6\n pop R7\n" "pop R8\n pop R9\n pop R10\n pop R11\n" "pop R12\n pop R13\n pop R14\n pop R15"); } #include "msp430.h" #include "common.h" __task void task1(void){ P1DIR |= BIT0; while(1){ __delay_cycles(800000); P1OUT |= BIT0; __delay_cycles(800000); P1OUT &=~BIT0; } } #include "msp430.h" #include "common.h" __task void task2(void){ P1DIR |= BIT6; while(1){ __delay_cycles(1200000); P1OUT |= BIT6; __delay_cycles(1200000); P1OUT &=~BIT6; } } #include "msp430.h" #include "common.h" unsigned int fibo(int); __task void task3(void){ int temp = 0; while(1){ fibo(++temp); } } unsigned int fibo(int n){ if (n < 2) return n; else return (fibo(n-1) + fibo(n-2)); } #ifndef COMMON_H_ #define COMMON_H_ #define tasks (sizeof(taskpnt)/2) __task void task1(void); __task void task2(void); __task void task3(void); typedef __task void (*funcpnt)(void); #endif
  18. Like
    tonyp12 got a reaction from Frida in tiny msp430 preemptive multitasking system   
    Tested on G2553 Launchpad with IAR, I recommend G2955 with 1K RAM if you want more than 3 task
    #include "msp430.h" #include "common.h" //=========================(C) Tony Philipsson 2016 ======================= funcpnt const taskpnt[]={ task1, task2, task3, // <- PUT YOUR TASKS HERE }; const int stacksize[tasks] = {28}; // a blank value defaults to 24 stack words //========================================================================= int taskstackpnt[tasks]; unsigned int taskdelay[tasks]; char taskrun; int main( void ) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer if (CALBC1_8MHZ != 0xff){ // erased by mistake? BCSCTL1 = CALBC1_8MHZ; // Set DCO to factory calibrate 1MHz DCOCTL = CALDCO_8MHZ; } int* multistack = (int*) __get_SP_register(); int i=0; while(i<tasks-1){ int j = stacksize[i]; if (!j) j = 24; multistack -= j; *(multistack) = (int) taskpnt[++i]; // prefill in PC *(multistack-1) = GIE; // prefill in SR taskstackpnt[i] = (int) multistack-26; // needs 12 dummy push words } WDTCTL = WDTPW+WDTTMSEL+WDTCNTCL; // 4ms interval at 8MHz smclk IE1 |= WDTIE; __bis_SR_register(GIE); asm ("br &taskpnt"); // indirect jmp to first task } //============= TASK SWITCHER ISR ============= #pragma vector = WDT_VECTOR __raw __interrupt void taskswitcher(void) { asm ("push R15\n push R14\n push R13\n push R12\n" "push R11\n push R10\n push R9\n push R8\n" "push R7\n push R6\n push R5\n push R4"); taskstackpnt[taskrun] = __get_SP_register(); if (++taskrun == tasks) taskrun = 0; __set_SP_register(taskstackpnt[taskrun]); asm ("pop R4\n pop R5\n pop R6\n pop R7\n" "pop R8\n pop R9\n pop R10\n pop R11\n" "pop R12\n pop R13\n pop R14\n pop R15"); } #include "msp430.h" #include "common.h" __task void task1(void){ P1DIR |= BIT0; while(1){ __delay_cycles(800000); P1OUT |= BIT0; __delay_cycles(800000); P1OUT &=~BIT0; } } #include "msp430.h" #include "common.h" __task void task2(void){ P1DIR |= BIT6; while(1){ __delay_cycles(1200000); P1OUT |= BIT6; __delay_cycles(1200000); P1OUT &=~BIT6; } } #include "msp430.h" #include "common.h" unsigned int fibo(int); __task void task3(void){ int temp = 0; while(1){ fibo(++temp); } } unsigned int fibo(int n){ if (n < 2) return n; else return (fibo(n-1) + fibo(n-2)); } #ifndef COMMON_H_ #define COMMON_H_ #define tasks (sizeof(taskpnt)/2) __task void task1(void); __task void task2(void); __task void task3(void); typedef __task void (*funcpnt)(void); #endif
  19. Like
    tonyp12 got a reaction from Rickta59 in tiny msp430 preemptive multitasking system   
    Tested on G2553 Launchpad with IAR, I recommend G2955 with 1K RAM if you want more than 3 task
    #include "msp430.h" #include "common.h" //=========================(C) Tony Philipsson 2016 ======================= funcpnt const taskpnt[]={ task1, task2, task3, // <- PUT YOUR TASKS HERE }; const int stacksize[tasks] = {28}; // a blank value defaults to 24 stack words //========================================================================= int taskstackpnt[tasks]; unsigned int taskdelay[tasks]; char taskrun; int main( void ) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer if (CALBC1_8MHZ != 0xff){ // erased by mistake? BCSCTL1 = CALBC1_8MHZ; // Set DCO to factory calibrate 1MHz DCOCTL = CALDCO_8MHZ; } int* multistack = (int*) __get_SP_register(); int i=0; while(i<tasks-1){ int j = stacksize[i]; if (!j) j = 24; multistack -= j; *(multistack) = (int) taskpnt[++i]; // prefill in PC *(multistack-1) = GIE; // prefill in SR taskstackpnt[i] = (int) multistack-26; // needs 12 dummy push words } WDTCTL = WDTPW+WDTTMSEL+WDTCNTCL; // 4ms interval at 8MHz smclk IE1 |= WDTIE; __bis_SR_register(GIE); asm ("br &taskpnt"); // indirect jmp to first task } //============= TASK SWITCHER ISR ============= #pragma vector = WDT_VECTOR __raw __interrupt void taskswitcher(void) { asm ("push R15\n push R14\n push R13\n push R12\n" "push R11\n push R10\n push R9\n push R8\n" "push R7\n push R6\n push R5\n push R4"); taskstackpnt[taskrun] = __get_SP_register(); if (++taskrun == tasks) taskrun = 0; __set_SP_register(taskstackpnt[taskrun]); asm ("pop R4\n pop R5\n pop R6\n pop R7\n" "pop R8\n pop R9\n pop R10\n pop R11\n" "pop R12\n pop R13\n pop R14\n pop R15"); } #include "msp430.h" #include "common.h" __task void task1(void){ P1DIR |= BIT0; while(1){ __delay_cycles(800000); P1OUT |= BIT0; __delay_cycles(800000); P1OUT &=~BIT0; } } #include "msp430.h" #include "common.h" __task void task2(void){ P1DIR |= BIT6; while(1){ __delay_cycles(1200000); P1OUT |= BIT6; __delay_cycles(1200000); P1OUT &=~BIT6; } } #include "msp430.h" #include "common.h" unsigned int fibo(int); __task void task3(void){ int temp = 0; while(1){ fibo(++temp); } } unsigned int fibo(int n){ if (n < 2) return n; else return (fibo(n-1) + fibo(n-2)); } #ifndef COMMON_H_ #define COMMON_H_ #define tasks (sizeof(taskpnt)/2) __task void task1(void); __task void task2(void); __task void task3(void); typedef __task void (*funcpnt)(void); #endif
  20. Like
    tonyp12 got a reaction from sq7bti in tiny msp430 preemptive multitasking system   
    Tested on G2553 Launchpad with IAR, I recommend G2955 with 1K RAM if you want more than 3 task
    #include "msp430.h" #include "common.h" //=========================(C) Tony Philipsson 2016 ======================= funcpnt const taskpnt[]={ task1, task2, task3, // <- PUT YOUR TASKS HERE }; const int stacksize[tasks] = {28}; // a blank value defaults to 24 stack words //========================================================================= int taskstackpnt[tasks]; unsigned int taskdelay[tasks]; char taskrun; int main( void ) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer if (CALBC1_8MHZ != 0xff){ // erased by mistake? BCSCTL1 = CALBC1_8MHZ; // Set DCO to factory calibrate 1MHz DCOCTL = CALDCO_8MHZ; } int* multistack = (int*) __get_SP_register(); int i=0; while(i<tasks-1){ int j = stacksize[i]; if (!j) j = 24; multistack -= j; *(multistack) = (int) taskpnt[++i]; // prefill in PC *(multistack-1) = GIE; // prefill in SR taskstackpnt[i] = (int) multistack-26; // needs 12 dummy push words } WDTCTL = WDTPW+WDTTMSEL+WDTCNTCL; // 4ms interval at 8MHz smclk IE1 |= WDTIE; __bis_SR_register(GIE); asm ("br &taskpnt"); // indirect jmp to first task } //============= TASK SWITCHER ISR ============= #pragma vector = WDT_VECTOR __raw __interrupt void taskswitcher(void) { asm ("push R15\n push R14\n push R13\n push R12\n" "push R11\n push R10\n push R9\n push R8\n" "push R7\n push R6\n push R5\n push R4"); taskstackpnt[taskrun] = __get_SP_register(); if (++taskrun == tasks) taskrun = 0; __set_SP_register(taskstackpnt[taskrun]); asm ("pop R4\n pop R5\n pop R6\n pop R7\n" "pop R8\n pop R9\n pop R10\n pop R11\n" "pop R12\n pop R13\n pop R14\n pop R15"); } #include "msp430.h" #include "common.h" __task void task1(void){ P1DIR |= BIT0; while(1){ __delay_cycles(800000); P1OUT |= BIT0; __delay_cycles(800000); P1OUT &=~BIT0; } } #include "msp430.h" #include "common.h" __task void task2(void){ P1DIR |= BIT6; while(1){ __delay_cycles(1200000); P1OUT |= BIT6; __delay_cycles(1200000); P1OUT &=~BIT6; } } #include "msp430.h" #include "common.h" unsigned int fibo(int); __task void task3(void){ int temp = 0; while(1){ fibo(++temp); } } unsigned int fibo(int n){ if (n < 2) return n; else return (fibo(n-1) + fibo(n-2)); } #ifndef COMMON_H_ #define COMMON_H_ #define tasks (sizeof(taskpnt)/2) __task void task1(void); __task void task2(void); __task void task3(void); typedef __task void (*funcpnt)(void); #endif
  21. Like
    tonyp12 got a reaction from jazz in tiny msp430 preemptive multitasking system   
    Tested on G2553 Launchpad with IAR, I recommend G2955 with 1K RAM if you want more than 3 task
    #include "msp430.h" #include "common.h" //=========================(C) Tony Philipsson 2016 ======================= funcpnt const taskpnt[]={ task1, task2, task3, // <- PUT YOUR TASKS HERE }; const int stacksize[tasks] = {28}; // a blank value defaults to 24 stack words //========================================================================= int taskstackpnt[tasks]; unsigned int taskdelay[tasks]; char taskrun; int main( void ) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer if (CALBC1_8MHZ != 0xff){ // erased by mistake? BCSCTL1 = CALBC1_8MHZ; // Set DCO to factory calibrate 1MHz DCOCTL = CALDCO_8MHZ; } int* multistack = (int*) __get_SP_register(); int i=0; while(i<tasks-1){ int j = stacksize[i]; if (!j) j = 24; multistack -= j; *(multistack) = (int) taskpnt[++i]; // prefill in PC *(multistack-1) = GIE; // prefill in SR taskstackpnt[i] = (int) multistack-26; // needs 12 dummy push words } WDTCTL = WDTPW+WDTTMSEL+WDTCNTCL; // 4ms interval at 8MHz smclk IE1 |= WDTIE; __bis_SR_register(GIE); asm ("br &taskpnt"); // indirect jmp to first task } //============= TASK SWITCHER ISR ============= #pragma vector = WDT_VECTOR __raw __interrupt void taskswitcher(void) { asm ("push R15\n push R14\n push R13\n push R12\n" "push R11\n push R10\n push R9\n push R8\n" "push R7\n push R6\n push R5\n push R4"); taskstackpnt[taskrun] = __get_SP_register(); if (++taskrun == tasks) taskrun = 0; __set_SP_register(taskstackpnt[taskrun]); asm ("pop R4\n pop R5\n pop R6\n pop R7\n" "pop R8\n pop R9\n pop R10\n pop R11\n" "pop R12\n pop R13\n pop R14\n pop R15"); } #include "msp430.h" #include "common.h" __task void task1(void){ P1DIR |= BIT0; while(1){ __delay_cycles(800000); P1OUT |= BIT0; __delay_cycles(800000); P1OUT &=~BIT0; } } #include "msp430.h" #include "common.h" __task void task2(void){ P1DIR |= BIT6; while(1){ __delay_cycles(1200000); P1OUT |= BIT6; __delay_cycles(1200000); P1OUT &=~BIT6; } } #include "msp430.h" #include "common.h" unsigned int fibo(int); __task void task3(void){ int temp = 0; while(1){ fibo(++temp); } } unsigned int fibo(int n){ if (n < 2) return n; else return (fibo(n-1) + fibo(n-2)); } #ifndef COMMON_H_ #define COMMON_H_ #define tasks (sizeof(taskpnt)/2) __task void task1(void); __task void task2(void); __task void task3(void); typedef __task void (*funcpnt)(void); #endif
  22. Like
    tonyp12 got a reaction from Fmilburn in tiny msp430 preemptive multitasking system   
    Tested on G2553 Launchpad with IAR, I recommend G2955 with 1K RAM if you want more than 3 task
    #include "msp430.h" #include "common.h" //=========================(C) Tony Philipsson 2016 ======================= funcpnt const taskpnt[]={ task1, task2, task3, // <- PUT YOUR TASKS HERE }; const int stacksize[tasks] = {28}; // a blank value defaults to 24 stack words //========================================================================= int taskstackpnt[tasks]; unsigned int taskdelay[tasks]; char taskrun; int main( void ) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer if (CALBC1_8MHZ != 0xff){ // erased by mistake? BCSCTL1 = CALBC1_8MHZ; // Set DCO to factory calibrate 1MHz DCOCTL = CALDCO_8MHZ; } int* multistack = (int*) __get_SP_register(); int i=0; while(i<tasks-1){ int j = stacksize[i]; if (!j) j = 24; multistack -= j; *(multistack) = (int) taskpnt[++i]; // prefill in PC *(multistack-1) = GIE; // prefill in SR taskstackpnt[i] = (int) multistack-26; // needs 12 dummy push words } WDTCTL = WDTPW+WDTTMSEL+WDTCNTCL; // 4ms interval at 8MHz smclk IE1 |= WDTIE; __bis_SR_register(GIE); asm ("br &taskpnt"); // indirect jmp to first task } //============= TASK SWITCHER ISR ============= #pragma vector = WDT_VECTOR __raw __interrupt void taskswitcher(void) { asm ("push R15\n push R14\n push R13\n push R12\n" "push R11\n push R10\n push R9\n push R8\n" "push R7\n push R6\n push R5\n push R4"); taskstackpnt[taskrun] = __get_SP_register(); if (++taskrun == tasks) taskrun = 0; __set_SP_register(taskstackpnt[taskrun]); asm ("pop R4\n pop R5\n pop R6\n pop R7\n" "pop R8\n pop R9\n pop R10\n pop R11\n" "pop R12\n pop R13\n pop R14\n pop R15"); } #include "msp430.h" #include "common.h" __task void task1(void){ P1DIR |= BIT0; while(1){ __delay_cycles(800000); P1OUT |= BIT0; __delay_cycles(800000); P1OUT &=~BIT0; } } #include "msp430.h" #include "common.h" __task void task2(void){ P1DIR |= BIT6; while(1){ __delay_cycles(1200000); P1OUT |= BIT6; __delay_cycles(1200000); P1OUT &=~BIT6; } } #include "msp430.h" #include "common.h" unsigned int fibo(int); __task void task3(void){ int temp = 0; while(1){ fibo(++temp); } } unsigned int fibo(int n){ if (n < 2) return n; else return (fibo(n-1) + fibo(n-2)); } #ifndef COMMON_H_ #define COMMON_H_ #define tasks (sizeof(taskpnt)/2) __task void task1(void); __task void task2(void); __task void task3(void); typedef __task void (*funcpnt)(void); #endif
  23. Like
    tonyp12 got a reaction from gsutton in tiny msp430 preemptive multitasking system   
    a ISR always have way to trick the RETI by modifying the SR values on stack.
     
    I trick the RETI with a different stack location , task 1 have a stack as normal as first entry in to ISR the PC,SR and R15-R4 are push'ed
    ?
    But for the other tasks I have to preset the PC and SR in the "fake" stack for its first entry in
    and also offset the stack pointer as it will see 12 pop's the first time without seeing the 12 push'es yet.
     
    I plan to add system_delay() so task can asked to be put on hold, though it will be hard to calculate a actual time if other tasks also do that at the same time.
    maybe even enter LPM0 if all task are on timeout for this 4ms interval.
  24. Like
    tonyp12 got a reaction from oPossum in tiny msp430 preemptive multitasking system   
    Tested on G2553 Launchpad with IAR, I recommend G2955 with 1K RAM if you want more than 3 task
    #include "msp430.h" #include "common.h" //=========================(C) Tony Philipsson 2016 ======================= funcpnt const taskpnt[]={ task1, task2, task3, // <- PUT YOUR TASKS HERE }; const int stacksize[tasks] = {28}; // a blank value defaults to 24 stack words //========================================================================= int taskstackpnt[tasks]; unsigned int taskdelay[tasks]; char taskrun; int main( void ) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer if (CALBC1_8MHZ != 0xff){ // erased by mistake? BCSCTL1 = CALBC1_8MHZ; // Set DCO to factory calibrate 1MHz DCOCTL = CALDCO_8MHZ; } int* multistack = (int*) __get_SP_register(); int i=0; while(i<tasks-1){ int j = stacksize[i]; if (!j) j = 24; multistack -= j; *(multistack) = (int) taskpnt[++i]; // prefill in PC *(multistack-1) = GIE; // prefill in SR taskstackpnt[i] = (int) multistack-26; // needs 12 dummy push words } WDTCTL = WDTPW+WDTTMSEL+WDTCNTCL; // 4ms interval at 8MHz smclk IE1 |= WDTIE; __bis_SR_register(GIE); asm ("br &taskpnt"); // indirect jmp to first task } //============= TASK SWITCHER ISR ============= #pragma vector = WDT_VECTOR __raw __interrupt void taskswitcher(void) { asm ("push R15\n push R14\n push R13\n push R12\n" "push R11\n push R10\n push R9\n push R8\n" "push R7\n push R6\n push R5\n push R4"); taskstackpnt[taskrun] = __get_SP_register(); if (++taskrun == tasks) taskrun = 0; __set_SP_register(taskstackpnt[taskrun]); asm ("pop R4\n pop R5\n pop R6\n pop R7\n" "pop R8\n pop R9\n pop R10\n pop R11\n" "pop R12\n pop R13\n pop R14\n pop R15"); } #include "msp430.h" #include "common.h" __task void task1(void){ P1DIR |= BIT0; while(1){ __delay_cycles(800000); P1OUT |= BIT0; __delay_cycles(800000); P1OUT &=~BIT0; } } #include "msp430.h" #include "common.h" __task void task2(void){ P1DIR |= BIT6; while(1){ __delay_cycles(1200000); P1OUT |= BIT6; __delay_cycles(1200000); P1OUT &=~BIT6; } } #include "msp430.h" #include "common.h" unsigned int fibo(int); __task void task3(void){ int temp = 0; while(1){ fibo(++temp); } } unsigned int fibo(int n){ if (n < 2) return n; else return (fibo(n-1) + fibo(n-2)); } #ifndef COMMON_H_ #define COMMON_H_ #define tasks (sizeof(taskpnt)/2) __task void task1(void); __task void task2(void); __task void task3(void); typedef __task void (*funcpnt)(void); #endif
  25. Like
    tonyp12 got a reaction from dubnet in tiny msp430 preemptive multitasking system   
    Tested on G2553 Launchpad with IAR, I recommend G2955 with 1K RAM if you want more than 3 task
    #include "msp430.h" #include "common.h" //=========================(C) Tony Philipsson 2016 ======================= funcpnt const taskpnt[]={ task1, task2, task3, // <- PUT YOUR TASKS HERE }; const int stacksize[tasks] = {28}; // a blank value defaults to 24 stack words //========================================================================= int taskstackpnt[tasks]; unsigned int taskdelay[tasks]; char taskrun; int main( void ) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer if (CALBC1_8MHZ != 0xff){ // erased by mistake? BCSCTL1 = CALBC1_8MHZ; // Set DCO to factory calibrate 1MHz DCOCTL = CALDCO_8MHZ; } int* multistack = (int*) __get_SP_register(); int i=0; while(i<tasks-1){ int j = stacksize[i]; if (!j) j = 24; multistack -= j; *(multistack) = (int) taskpnt[++i]; // prefill in PC *(multistack-1) = GIE; // prefill in SR taskstackpnt[i] = (int) multistack-26; // needs 12 dummy push words } WDTCTL = WDTPW+WDTTMSEL+WDTCNTCL; // 4ms interval at 8MHz smclk IE1 |= WDTIE; __bis_SR_register(GIE); asm ("br &taskpnt"); // indirect jmp to first task } //============= TASK SWITCHER ISR ============= #pragma vector = WDT_VECTOR __raw __interrupt void taskswitcher(void) { asm ("push R15\n push R14\n push R13\n push R12\n" "push R11\n push R10\n push R9\n push R8\n" "push R7\n push R6\n push R5\n push R4"); taskstackpnt[taskrun] = __get_SP_register(); if (++taskrun == tasks) taskrun = 0; __set_SP_register(taskstackpnt[taskrun]); asm ("pop R4\n pop R5\n pop R6\n pop R7\n" "pop R8\n pop R9\n pop R10\n pop R11\n" "pop R12\n pop R13\n pop R14\n pop R15"); } #include "msp430.h" #include "common.h" __task void task1(void){ P1DIR |= BIT0; while(1){ __delay_cycles(800000); P1OUT |= BIT0; __delay_cycles(800000); P1OUT &=~BIT0; } } #include "msp430.h" #include "common.h" __task void task2(void){ P1DIR |= BIT6; while(1){ __delay_cycles(1200000); P1OUT |= BIT6; __delay_cycles(1200000); P1OUT &=~BIT6; } } #include "msp430.h" #include "common.h" unsigned int fibo(int); __task void task3(void){ int temp = 0; while(1){ fibo(++temp); } } unsigned int fibo(int n){ if (n < 2) return n; else return (fibo(n-1) + fibo(n-2)); } #ifndef COMMON_H_ #define COMMON_H_ #define tasks (sizeof(taskpnt)/2) __task void task1(void); __task void task2(void); __task void task3(void); typedef __task void (*funcpnt)(void); #endif
×
×
  • Create New...