This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430-GCC-OPENSOURCE: GCC 9.2.0.50 msp430fr5994.ld .lowtext bugfix

Part Number: MSP430-GCC-OPENSOURCE
Other Parts Discussed in Thread: MSP430FR5994, MSP430FR2476, MSP430FR2676, MSP430FR50431, MSP430FR5043, MSP430FR5962, MSP430FR5964, MSP430FR5992, MSP430FR59941, MSP430FR6005, MSP430FR6007, MSP430FR6035, MSP430FR60371, MSP430FR6037, MSP430FR60431, MSP430FR6043, MSP430FR6045, MSP430FR60471, MSP430FR6047

Hi,

this minimal example compiled for MSP430FR5994 using MSP430 GCC 9.2.0.50 (both on CCS Cloud and on our computer)
fails to blink the LED.

#include <msp430.h> 

int main(void)
{
    WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer
    P1DIR |= BIT0;
    PM5CTL0 &= ~LOCKLPM5;
	
    TA4CTL = MC__STOP | TACLR;
    TA4CCR0 = 31250; // 4 times per second
    TA4CCTL0 = CCIE; // TA4CCR0 interrupt enabled
    TA4CTL = TASSEL__SMCLK | ID__8 | MC__UP; // SMCLK/8, UP mode
    __enable_interrupt();
    do {} while(1);
    return 0;
}

void __interrupt_vec(TIMER4_A0_VECTOR)
Timer4_A0_ISR (void) {
   P1OUT ^= BIT0;
}

After comparison with other linker scripts in include/ directory, the default linker script msp430fr5994.ld is believed to be the cause,
as the interrupt routine is placed in ".lowtext" section that then goes somewhere in RAM, but is expected to be in FRAM.

Proposed fix seems to place the ".lowtext" in correct memory section.

--- msp430-gcc-9.2.0.50/include/msp430fr5994.ld
+++ fixed_msp430fr5994.ld
@@ -415,29 +415,29 @@
   .lower.text :
   {
     . = ALIGN(2);
     *(.lower.text.* .lower.text)
   } > FRAM

   .text :
   {
     PROVIDE (_start = .);

     . = ALIGN(2);
     KEEP (*(SORT(.crt_*)))

     . = ALIGN(2);
-    *(.lower.text.* .lower.text)
+    KEEP (*(.lowtext))

     . = ALIGN(2);
     *(.text .stub .text.* .gnu.linkonce.t.* .text:*)
     /* See the note in .rodata section about why we do not have this line here:

         *(.either.text.* .either.text)

     */

     KEEP (*(.text.*personality*))
     /* .gnu.warning sections are handled specially by elf32.em.  */
     *(.gnu.warning)
     *(.interp .hash .dynsym .dynstr .gnu.version*)
     PROVIDE (__etext = .);

Any feedback on this?
Best regards
Petr

  • Hi,

    Thanks for reporting this.

    When the -mlarge flag is used to select the large memory model, ISRs are put into the .lowtext section by the compiler, to ensure they are always in lower memory and so have an address which fits in the 16-bit slots in the vector table.

    Indeed, a rule to match the .lowtext section is missing from the FR5994 linker script. Your patch fixes that, and puts .lowtext in a section which will always be in lower memory.

    In fact, the .lowtext rule is missing from linker scripts for the following devices:

    • msp430fr2476
    • msp430fr2676
    • msp430fr50431
    • msp430fr5043
    • msp430fr5962
    • msp430fr5964
    • msp430fr5992
    • msp430fr59941
    • msp430fr5994
    • msp430fr6005
    • msp430fr6007
    • msp430fr6035
    • msp430fr60371
    • msp430fr6037
    • msp430fr60431
    • msp430fr6043
    • msp430fr6045
    • msp430fr60471
    • msp430fr6047

    The linker scripts are auto-generated by TI, so I don't have any insight into why only these devices have this particular bug.

    I will report this to them and hopefully it gets fixed as soon as possible.

    Regards,

**Attention** This is a public forum