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 code ... __delay_cycles()

Other Parts Discussed in Thread: MSP430G2553

Does "__delay_cycles()" rely on interrupts? ... would there be a problem if I disabled interrupts before this function is called?

  • If you look at the generated assembly code, a call to for example __delay_cycles(1000) becomes

            JMP     ??main_1
    ??main_1:
    MOV.W #0x14b, R15
    ??main_0:
    ADD.W #0xffff, R15
    JC ??main_0

    in other words, it decomposes into a series of adds and compares, which clearly does not rely on interrupts.

    Tony

  • Actually, if interrupt is enabled, the interrupts will add more delays.

  • old_cow_yellow said:

    Actually, if interrupt is enabled, the interrupts will add more delays.

    Unless an interrupt happens that has no ISR, then lim delay -> inf.

  • It is a good practice to provide interrupt handlers for every interrupt vector (especially unused ones) when you enable interrupts and need to go to the last bit of security.

  • Thanks for the responses.

  • Jan said:
    It is a good practice to provide interrupt handlers for every interrupt vector (especially unused ones) when you enable interrupts and need to go to the last bit of security.

    Indeed. However, this is not trivial. Unless you indeed write several independent ISRs.
    MSPGCC had the habit of auto-generating a 'unexpected' ISR, and filling all interrupt vectors with their address.

  • Jens-Michael Gross said:

    Indeed. However, this is not trivial. Unless you indeed write several independent ISRs.

    Actually it's quite possible to provide multiple interrupt vectors with dummy ISR, if you're willing to use some vendor extensions (yeah yeah, hope you appreciate the irony ;)

    See the following example for the MSP430G2553 on IAR Embedded

    typedef void (*pointer_to_ISR)();

    __interrupt void fillerISR(void) {
    }

    __interrupt void nmi_ (void)
    {
    // some code
    IFG1 &= ~NMIIFG; // Reclear NMI flag in case bounce
    IE1 |= NMIIE; // Enable NMI
    }

    #ifdef __ICC430__
    #pragma location=0xffe4
    #endif
    extern const pointer_to_ISR isr[]= {
    (pointer_to_ISR)fillerISR, // PORT1_VECTOR
    (pointer_to_ISR)fillerISR, // PORT2_VECTOR
    (pointer_to_ISR)fillerISR, // UNUSED
    (pointer_to_ISR)fillerISR, // ADC10_VECTOR
    (pointer_to_ISR)fillerISR, // USCIAB0TX_VECTOR
    (pointer_to_ISR)fillerISR, // USCIAB0RX_VECTOR
    (pointer_to_ISR)fillerISR, // TIMER0_A1_VECTOR
    (pointer_to_ISR)fillerISR, // TIMER0_A0_VECTOR
    (pointer_to_ISR)fillerISR, // WDT_VECTOR
    (pointer_to_ISR)fillerISR, // COMPARATORA_VECTOR
    (pointer_to_ISR)fillerISR, // TIMER1_A1_VECTOR
    (pointer_to_ISR)fillerISR, // TIMER1_A0_VECTOR
    (pointer_to_ISR)nmi_ // NMI_VECTOR
    };

    Of course this gets a wee bit problematic on CPUX what with the 20-bit function pointers an' all.

    What do you guys think?

    Tony

  • TonyKao said:
    Of course this gets a wee bit problematic on CPUX what with the 20-bit function pointers an' all.

    Well, (pointer_to_ISR) should take care of the 16 bit address, and the __interrupt should tell the linker to place the ISR into lower mem, so this won't be a problem.

    The main problem with such a dummy ISR is that it won't help much. Unless the ISR clears all IFG bits, it will exit and then immediately re-enter in an endless loop. So without debugger and breakpoint on it, it won't help fixing anything.

  • Jens-Michael Gross said:

    The main problem with such a dummy ISR is that it won't help much. Unless the ISR clears all IFG bits, it will exit and then immediately re-enter in an endless loop. So without debugger and breakpoint on it, it won't help fixing anything.

    You can do something like this

    __interrupt void fillerISR(void) {
      if(IFG2)
        __no_operation();
      else if(P1IFG)
        __no_operation();
      else if(P2IFG)
        __no_operation();
      else if(TA0CTL & TAIFG)
        __no_operation();
      //etc etc
      else {
        __no_operation();
      }
    }

    Which would help you to find out where the spurious interrupt came from instead of hunting through all the peripheral registers.

    Also it's just a more organized way of making sure you have all your necessary interrupt vectors (IMO anyway :).

    Tony

    Edit: gah the forum format is messed up for code snippets...

  • TonyKao said:
    You can do something like this

    Well, this isn't far from writing an ISR for each vector - which wouldn't need messing with the vector table then :)
    I'd say there is no 'optimum' solution.

    However, unwanted interrupts shouldn't appear at all in proper code. :)

    You could write a library with ISRs for each and every interrupt which handles all IFG bits. If you declare them as weak references, any ISR you write in your project should then replace the 'default one'. However, the names must be identicval, and the #pragma is in the library, not in the application code then.

  • "However, unwanted interrupts shouldn't appear at all in proper code. :)"

    I'd just like to point out that the code could be perfect and well tested however if an EMC event occurs it may cause hardware to the micro to act abnormally. We saw our micro become susceptible to Burst testing which then cause our pour little micro to reset for many reasons: brown out, watchdog time outs, etc.

    Without an approach like Jens mentioned we wouldn't be able to:

      1) Know an event outside of our normal operation occured.
      2) Know where it came from.

     

**Attention** This is a public forum