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.

MSP430FR5969: multiple interrupts set-up

Part Number: MSP430FR5969

Hi Team, 

Good day. I am posting this inquiry on behalf of the customer.

"I'm using an MSP430FR5969 for a project. I have several tasks that need to be performed at different specific times so I have multiple interrupts set up to take me to those tasks at the appropriate intervals.

Then I have another task that gets done whenever the other tasks aren't working.
I have the A/D converter sampling a signal input at 256 Hz. So I have a timer that gives me an interrupt at 256 Hz. This interrupt service starts the A/D Converter and then returns from the interrupt
When the A/D converter is finished, it generates a MEM0 interrupt, and I go get that value and save it to FRAM
I'm then wanting to display this signal on a 128x128 display, so I only display every 4th MEM0 interrupt.
This gives me roughly 2 seconds of display on the screen. After 128 displayed values, I clear the screen and start over. This goes on "forever"
Meanwhile, I'm calculating a value based on that incoming data that gets updated occasionally. So I want to display a line of text with that calculated value whenever it changes, which is not synchronous at all
Want I want to do is sit in a loop calculating this value that changes asynchronously, display it whenever it changes, and get interrupted out of that part of my code whenever one of the other interrupts happens."
Please help to advise. Thank you for extending your help.
Kind regards, 
Marvin
  • Hi Marvin,

    This is not an uncommon program flow for embedded programming, and based on their description I'd say there's no need to overthink it. 

    The asynchronous/continuous operations can be performed inside a never ending while loop within main. You can also set flags to handle certain data inside the ISRs, and when the while loop is returned to it will execute the corresponding code. 

        while (1)
        {
            if(flag1){
                //handle condition 1
                flag1 = false;
            }
            else if(flag2){
                //handle condition 2
                flag2 = false;
            }
            ///.... etc.
            
            //Insert code to be performed continuosly
        }
    

    They can also do other basic operations within the ISR other than setting flags, but its advisable to keep them as short as possible to avoid timing issues. 

    Best Regards,
    Brandon Fisher

  • Hi Brandon, 

    Thank you for your prompt response. Please see the feedback from our customer.

    "The response was kinda on the right path, but my question is more about how to continue processing in the main loop after starting the interrupts.

    I have Timer B0 set to interrupt on at 250 Hz rate. When that interrupt occurs, that ISR merely starts a new A/D Conversion and returns. When the A/D Conversion is done, that ISR reads the value from MEM0 and puts it into an array. Originally, I was also having this ISR do all the processing of the digitized data, but I'm pretty sure there's too much to do in 1/256th of a second.

    Since the bulk of the processing work only needs to be done every 1/2 sec, I have now set up Timer A0 to generate an interrupt every 0.5 seconds. Inside this ISR, my intention is to do the minimum needed with interrupts disabled, then enable interrupts and continue processing. If Timer B0 interrupts again, that's fine - it'll start another ADC cycle and then RTI; the ADC will complete & interrupt will occur & save MEM0; and I'll go back to my processing. The array is big enough to hold several seconds of samples.

    At the end of the Time B0 and ADC ISR's, I have this code:
    __bis_SR_register(LPM0_bits + GIE); // LPM0, ADC12_B_ISR will force exit
    __no_operation(); // For debugger

    If the processor goes into LPM0 but returns to the Timer A0 ISR, does it automatically come out of LPM0?
    When it's OK to allow interrupts in Timer A0 ISR, how do I do that? Is it as simple as calling
    __enable_interrupt();
    __no_operation();"

    Your support is much appreciated. Thank you for extending your help.
    Kind regards, 
    Marvin
  • Hi Marvin,

    The TB0 interrupt vector is  higher priority than TIMA0 interrupts in this device, so this can function this way naturally, but it isn't ideal to nest* ISRs like this, as time spent in the other ISR will add to the total execution time of their TA ISR. 

    They can continue in the main loop (i.e. come out of LPM0) by adding a call to the __bic_SR_register_on_exit intrinsic. Dennis provides a very good explanation of how this works in this thread: https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1016520/msp430fr2433-inquiry-about-__bis_sr_register-and-__bic_sr_register_on_exit

    I feel like there is still the option of using the Timer A if they want to time when these calculations occur, just to set a flag that causes the calculations to start when you return to your main loop. If TIMB/ADC interrupt occurs during that, then you will return to where you were executing in the loop and just continue.

    Best Regards,
    Brandon Fisher

  • Hi Brandon, 

    Thank you for your response. Please see the feedback from our customer.


    "Based on the information you've shared, here's the basic flow I'm going to try:

    MAIN():
    Set up ADC12 to write to ADC12MEM0
    Set up TB0 for 256 Hz interrupt
    Start TB0
    __enable_interrupts()
    __no_operation()

    while (1) {
    while (sample_count == current_sample_count)
    Wait for ADC to generate another value
    Perform necessary work on the value in array[current_sample_count]
    current_sample_count++
    If current_sample_count > max, currnet_sample_count = 0
    }

    TB0 ISR:
    Start ADC12
    __bic_SR_register_on_exit(LPM3_bits)
    __no_operation()

    ADC12MEM0 ISR:
    Read MEM0 into array[sample_count)
    sample_count++
    If sample_count > max, sample_count = 0
    __bic_SR_register_on_exit(LPM3_bits)
    __no_operation()


    This means MSP doesn't ever go into LPM0 but I'm not worried about that in my application. I could perhaps go into LPM0 during the "Wait for ADC to generate another value" loop."

    Thank you for extending your help. Your support is much appreciated.

    Kind regards, 

    Marvin

  • Hi Marvin,

    This seems like it would work to me. As they said, dropping into a LPM is an option when they are not processing anymore data. 

    Best Regards,
    Brandon Fisher

  • Hi Brandon, 

    Please see the feedback from our customer. 

    "I checked out the response in E2E. I had gone ahead with my plan and that seems to be working quite well. It was good to get some validation from Brandon, though.

    Thanks so much for your help, and please thank Brandon for me!"

    Your support is much appreciated. Thank you for your help.

    Kind regards, 

    Marvin 

  • Thanks for sharing their feedback Marvin. I will go ahead and close this thread for now, but feel free to post again if any more assistance is needed.

    Best Regards,
    Brandon Fisher

**Attention** This is a public forum