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.

MSP430F6726 Trap Interrupt and I2C Issues

Other Parts Discussed in Thread: MSP430F6726

Hi all,

i have to make 2 question i cannot understand using MSP430F6726 mcu.

The first question is regarding a fallback to a trap isr interrupt routine while debugging. So, please, what is the trap isr routine and how to handle it ? I see some issues exist for other model of msp430 but i cannot find anything for this model.

The second question is regarding the i2c stale on RX during falling edge of SCL signal (USCI37 of errata datasheet). Please, could someone give me an example code about how to handle at least one of the proposed workarounds on the errata datasheet ?

Thanks in advance.

Best Regards,

Luigi

  • The trap interrupt service routine is for interrupt vectors where you did not specify a module specific service routine for. Normally if you enable an interrupt for a module you want to interrupt the program flow to handle the interrupt reuqest in between and prioritized. So you would not enable the interrupt capability if not needed. If you do it (maybe as a fault in your code) and there is no vector for it, the program can do things you do not want because it has lost the information where to go next. The trap-ISR can be entered for every interrupt vector that do not has an own ISR giving the program a regular service routine with start and end which will lead to normal program execution after entering it. But beware of interrupts requested by flags that aren't cleared automatically when serviced - these have to be cleared manually. If you don't do that, the trap ISR is running in an endless-loop without coming back to your main-program again. Only higher prioritized interrupts can be executed in that case.

    Dennis
  • Hello Dennis,
    thanks so much for your very complete reply.
    The default Trap routine just enter in a never ending loop, so first i need to replace it with a custom version.
    I think this can be handled using #pragma vector directive but in my msp430f6726.h i have not any reference to this interrupt routine.
    I'm looking for how to handle this. After i make the custom routine is there any (simple) way to know from where the interrupt was generate ?

    Best Regards,
    Luigi

  • The trap routine isn't a never-ending loop itself. It can lead to it if the interrupt flag isn't cleared manually for those flags that aren't cleared automatically when serviced. Then your program jumps into the ISR, executes it and leaves it, but the flag is still set so the ISR is invoked again and so on.

    In general you should not enable the interrupt capabilities for a module you don't need interrupts for. Then you do not need to specify a service routine for it.

    If you want to specify one have a look at the .h file for the processor. In the end for your one there is:

    /************************************************************
    * Interrupt Vectors (offset from 0xFF80)
    ************************************************************/
    
    #pragma diag_suppress 1107
    #define VECTOR_NAME(name)             name##_ptr
    #define EMIT_PRAGMA(x)                _Pragma(#x)
    #define CREATE_VECTOR(name)           void * const VECTOR_NAME(name) = (void *)(long)&name
    #define PLACE_VECTOR(vector,section)  EMIT_PRAGMA(DATA_SECTION(vector,section))
    #define PLACE_INTERRUPT(func)         EMIT_PRAGMA(CODE_SECTION(func,".text:_isr"))
    #define ISR_VECTOR(func,offset)       CREATE_VECTOR(func); \
                                          PLACE_VECTOR(VECTOR_NAME(func), offset) \
                                          PLACE_INTERRUPT(func)
    
    
    #ifdef __ASM_HEADER__ /* Begin #defines for assembler */
    #define RTC_VECTOR              ".int40"                     /* 0xFFD0 RTC */
    #else
    #define RTC_VECTOR              (40 * 1u)                    /* 0xFFD0 RTC */
    #endif
    #ifdef __ASM_HEADER__ /* Begin #defines for assembler */
    #define LCD_C_VECTOR            ".int41"                     /* 0xFFD2 LCD C */
    #else
    #define LCD_C_VECTOR            (41 * 1u)                    /* 0xFFD2 LCD C */
    #endif
    #ifdef __ASM_HEADER__ /* Begin #defines for assembler */
    #define TIMER3_A1_VECTOR        ".int42"                     /* 0xFFD4 Timer3_A2 CC1, TA */
    #else
    #define TIMER3_A1_VECTOR        (42 * 1u)                    /* 0xFFD4 Timer3_A2 CC1, TA */
    #endif
    #ifdef __ASM_HEADER__ /* Begin #defines for assembler */
    #define TIMER3_A0_VECTOR        ".int43"                     /* 0xFFD8 Timer3_A2 CC0 */
    #else
    #define TIMER3_A0_VECTOR        (43 * 1u)                    /* 0xFFD8 Timer3_A2 CC0 */
    #endif
    #ifdef __ASM_HEADER__ /* Begin #defines for assembler */
    #define PORT2_VECTOR            ".int44"                     /* 0xFFDA Port 2 */
    #else
    #define PORT2_VECTOR            (44 * 1u)                    /* 0xFFDA Port 2 */
    #endif
    #ifdef __ASM_HEADER__ /* Begin #defines for assembler */
    #define TIMER2_A1_VECTOR        ".int45"                     /* 0xFFDC Timer2_A2 CC1, TA */
    #else
    #define TIMER2_A1_VECTOR        (45 * 1u)                    /* 0xFFDC Timer2_A2 CC1, TA */
    #endif
    #ifdef __ASM_HEADER__ /* Begin #defines for assembler */
    #define TIMER2_A0_VECTOR        ".int46"                     /* 0xFFDE Timer2_A2 CC0 */
    #else
    #define TIMER2_A0_VECTOR        (46 * 1u)                    /* 0xFFDE Timer2_A2 CC0 */
    #endif
    #ifdef __ASM_HEADER__ /* Begin #defines for assembler */
    #define PORT1_VECTOR            ".int47"                     /* 0xFFDE Port 1 */
    #else
    #define PORT1_VECTOR            (47 * 1u)                    /* 0xFFDE Port 1 */
    #endif
    #ifdef __ASM_HEADER__ /* Begin #defines for assembler */
    #define TIMER1_A1_VECTOR        ".int48"                     /* 0xFFE0 Timer1_A2 CC1, TA1 */
    #else
    #define TIMER1_A1_VECTOR        (48 * 1u)                    /* 0xFFE0 Timer1_A2 CC1, TA1 */
    #endif
    #ifdef __ASM_HEADER__ /* Begin #defines for assembler */
    #define TIMER1_A0_VECTOR        ".int49"                     /* 0xFFE2 Timer1_A2 CC0 */
    #else
    #define TIMER1_A0_VECTOR        (49 * 1u)                    /* 0xFFE2 Timer1_A2 CC0 */
    #endif
    #ifdef __ASM_HEADER__ /* Begin #defines for assembler */
    #define DMA_VECTOR              ".int50"                     /* 0xFFE4 DMA */
    #else
    #define DMA_VECTOR              (50 * 1u)                    /* 0xFFE4 DMA */
    #endif
    #ifdef __ASM_HEADER__ /* Begin #defines for assembler */
    #define AUX_VECTOR              ".int51"                     /* 0xFFE6 AUX Supply */
    #else
    #define AUX_VECTOR              (51 * 1u)                    /* 0xFFE6 AUX Supply */
    #endif
    #ifdef __ASM_HEADER__ /* Begin #defines for assembler */
    #define USCI_A2_VECTOR          ".int52"                     /* 0xFFE8 USCI A2 Receive/Transmit */
    #else
    #define USCI_A2_VECTOR          (52 * 1u)                    /* 0xFFE8 USCI A2 Receive/Transmit */
    #endif
    #ifdef __ASM_HEADER__ /* Begin #defines for assembler */
    #define USCI_A1_VECTOR          ".int53"                     /* 0xFFEA USCI A1 Receive/Transmit */
    #else
    #define USCI_A1_VECTOR          (53 * 1u)                    /* 0xFFEA USCI A1 Receive/Transmit */
    #endif
    #ifdef __ASM_HEADER__ /* Begin #defines for assembler */
    #define TIMER0_A1_VECTOR        ".int54"                     /* 0xFFEC Timer0_A2 CC1-CC2, TA */
    #else
    #define TIMER0_A1_VECTOR        (54 * 1u)                    /* 0xFFEC Timer0_A2 CC1-CC2, TA */
    #endif
    #ifdef __ASM_HEADER__ /* Begin #defines for assembler */
    #define TIMER0_A0_VECTOR        ".int55"                     /* 0xFFEE Timer0_A2 CC0 */
    #else
    #define TIMER0_A0_VECTOR        (55 * 1u)                    /* 0xFFEE Timer0_A2 CC0 */
    #endif
    #ifdef __ASM_HEADER__ /* Begin #defines for assembler */
    #define SD24B_VECTOR            ".int56"                     /* 0xFFF0 SD24B ADC */
    #else
    #define SD24B_VECTOR            (56 * 1u)                    /* 0xFFF0 SD24B ADC */
    #endif
    #ifdef __ASM_HEADER__ /* Begin #defines for assembler */
    #define ADC10_VECTOR            ".int57"                     /* 0xFFF2 ADC */
    #else
    #define ADC10_VECTOR            (57 * 1u)                    /* 0xFFF2 ADC */
    #endif
    #ifdef __ASM_HEADER__ /* Begin #defines for assembler */
    #define USCI_B0_VECTOR          ".int58"                     /* 0xFFF4 USCI B0 Receive/Transmit */
    #else
    #define USCI_B0_VECTOR          (58 * 1u)                    /* 0xFFF4 USCI B0 Receive/Transmit */
    #endif
    #ifdef __ASM_HEADER__ /* Begin #defines for assembler */
    #define USCI_A0_VECTOR          ".int59"                     /* 0xFFF6 USCI A0 Receive/Transmit */
    #else
    #define USCI_A0_VECTOR          (59 * 1u)                    /* 0xFFF6 USCI A0 Receive/Transmit */
    #endif
    #ifdef __ASM_HEADER__ /* Begin #defines for assembler */
    #define WDT_VECTOR              ".int60"                     /* 0xFFF8 Watchdog Timer */
    #else
    #define WDT_VECTOR              (60 * 1u)                    /* 0xFFF8 Watchdog Timer */
    #endif
    #ifdef __ASM_HEADER__ /* Begin #defines for assembler */
    #define UNMI_VECTOR             ".int61"                     /* 0xFFFA User Non-maskable */
    #else
    #define UNMI_VECTOR             (61 * 1u)                    /* 0xFFFA User Non-maskable */
    #endif
    #ifdef __ASM_HEADER__ /* Begin #defines for assembler */
    #define SYSNMI_VECTOR           ".int62"                     /* 0xFFFC System Non-maskable */
    #else
    #define SYSNMI_VECTOR           (62 * 1u)                    /* 0xFFFC System Non-maskable */
    #endif
    #ifdef __ASM_HEADER__ /* Begin #defines for assembler */
    #define RESET_VECTOR            ".reset"                     /* 0xFFFE Reset [Highest Priority] */
    #else
    #define RESET_VECTOR            (63 * 1u)                    /* 0xFFFE Reset [Highest Priority] */
    #endif

    There are the names for the ISR pragmas you have to use. Let's take the timer 0 a1 module for example. An interrupt service routine would look like this:

    // Timer0 A1 interrupt service routine
    #pragma vector = TIMER0_A1_VECTOR       // <- This is the name from the header-file
    __interrupt void Timer0_A1_ISR( void )  // <- __interrupt void <any name you want> ( void )
    {
      // Do something for the different flags
    }

    Why don't you have a look at the code-examples - there you can see how to set up different ISRs for different modules:

    www.ti.com/lit/zip/slac511

    Dennis

  • Yes, i got it!

    Thanks again for your reference,

    Luigi

  • You don't need a custom trap ISR (unless you want to put some signaling into it, like turning an LED on).
    Set a breakpoint in it. If it is ever hit, you know that you either enabled an IRQ you don't want - or enabled one intentionally but forgot to provide an ISR for it.
    On proper code, the trap ISR is never hit.
    If you plan to secure your code, you should add bogus values (including odd values) to all unused ISRs, as the BSL takes the vector table (or rather part of it) as password. Putting the address of a (no longer required) trap ISR into all unused vectors weakens the password.

    If you want to know which interrupt was called, you need to either check all the IFG bits of all possible modules in your trap ISR, or you provide a different trap ISR for each interrupt vector.

    Regarding USCI37, the first workaound is simple. If MCLK is >I2CCLK, just perform two reads of RXBUF. Since it takes at least one I2C clock cycle to receive the next byte, two consecutive reads are faster and do not risk reading the next byte accidentally.
    If MCLk is as slow as I2CCLk or slower (rare case) ensure that the next byte is already in the queue and the bus is stalled, before you perform the (single) RXBUF read.
  • Hi Jens-Michael,

    thanks for your feedback. To discover which of interrupt was called i implemented all unused interrupt vectors as an endless loop and i found anunwanted bug in my code :-)

    Also I will take into account your suggest to secure my code.

    About USCI37, i'm using dma transfer to exchange data from/to i2c bus, and i hope USCI37 doesn't apply in this way.

    Regards,

    Luigi

  • Normally, a DMA is carried out immediately. However, it is possible that a DMA is delayed because MCLK is off (LPM) and starting the DCO for MCLK takes some time.
    If the DMA is delayed by exactly 1/2 I2C clock cycle (or 1 cycle?), USCI37 does apply. However, I2C is quite slow so 1/2 I2C clock cycle is some µs. For I2CCLK <=100kHz you're on the safe side. If you I2C clock is faster, you shouldn't go into an LPM that disables the MCLK source. (e.g. LPM1/LPM2) while the transfer happens.

**Attention** This is a public forum