Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TI MSP430 Interrupt Problems After UART Code Port

I am using the MSP430F2013 processor for an application, which doesn't have a UART. I need a UART, and so I used the TI's sample code "msp430x20x3_ta_uart2400.c" to emulate one using the Timer module. This all worked fine (compiled with IAR Embedded Workbench), having tested it using PuTTY to transmit characters to a development board and a loopback to echo them to the terminal.

That was a de-risking exercise, and now I've come to port that code into my application's state machine. Having done this, I'm having issues surrounding the timer interrupts and low power sleep modes. Here's the snippet of my code around the entry into the low power (sleep) mode:

// Prepare the UART to receive one byte.
prepare_receiver();

// Enter low power mode 1.
__bis_SR_register(LPM1_bits + GIE);

// Check whether the full message has been received.
if(true == get_message_complete())
{
    process_event(e_euart_message_received, NULL);
}

What I'm seeing on the debugger (C-Spy) is that sometimes it will execute the bis_SR_register() line on first entry and then go to the if statement, i.e., ignoring the fact that I've asked it to go to sleep. On other occasions, when it does go to sleep when it should, the ISR triggers correctly and eventually brings me back to the if statement to continue program execution (as I'm expecting). However, if I try to step to the next statement, the application freezes on that first line, i.e., I can't advance.

I can't think of anything functionally different from TI's example that I'm doing, so I figure my problem must be something to do with how I've ported it. For example, my Timer ISR and the code I've posted here are in different compilation units - would this sort of decision have any bearing on things? I'm aware my question might be a little vague but unfortunately I can't post all of my code, so instead I'm looking for someone with MSP experience who might be able to suggest some things to look at or some potential pitfalls that I may have fallen into.

like image 232
Ed King Avatar asked Jan 16 '23 13:01

Ed King


2 Answers

Debugging interrupts with C-Spy in Low Power Mode is going to be tricky. According to Section A.3 Debugging (C-Spy) - IAR User's Guide:

5) C-SPY can debug applications that utilize interrupts and low power modes

But there are some "gotchas" that you should be aware of that may be causing your headaches.

In particular:

14) When C-SPY has control of the device, the CPU is ON (that is, it is not in low-power mode) regardless of the settings of the low-power mode bits in the status register. Any low-power mode conditions are restored prior to Step or Go. Consequently, do not measure the power consumed by the device while C-SPY has control of the device. Instead, run your application using Go with JTAG released

19) C-SPY utilizes the system clock to control the device during debugging. Therefore, device counters, etc., that are clocked by the Main System Clock (MCLK) are affected when C-SPY has control of the device. Special precautions are taken to minimize the effect upon the Watchdog Timer. The CPU core registers are preserved. All other clock sources (SMCLK, ACLK) and peripherals continue to operate normally during emulation. In other words, the Flash Emulation Tool is a partially intrusive tool.

Devices that support clock control (Emulator → Advanced → Clock Control) can further minimize these effects by selecting to stop the clock(s) during debugging

24) Peripheral bits that are cleared when read during normal program execution (that is, interrupt flags) are cleared when read while being debugged (that is, memory dump, peripheral registers).

When using certain MSP430 devices (such as MSP430F15x, MSP430F16x, MSP430F43x, and MSP430F44x devices), bits do not behave this way (that is, the bits are not cleared by C-SPY read operations).

26) While single stepping with active and enabled interrupts, it can appear that only the interrupt service routine (ISR) is active (that is, the non-ISR code never appears to execute, and the single step operation always stops on the first line of the ISR). However, this behavior is correct because the device always processes an active and enabled interrupt before processing non-ISR (that is, mainline) code. A workaround for this behavior is, while within the ISR, to disable the GIE bit on the stack so that interrupts are disabled after exiting the ISR. This permits the non-ISR code to be debugged (but without interrupts). Interrupts can later be reenabled by setting GIE in the status register in the Register window.

On devices with the clock control emulation feature, it may be possible to suspend a clock between single steps and delay an interrupt request (Emulator → Advanced → Clock Control).

One thing to try is commenting out all the low power code and seeing if your UART code works like that. Then go back and try re-enabling the low power mode.

like image 57
embedded.kyle Avatar answered Jan 18 '23 02:01

embedded.kyle


The answer to this question lies in the debugging setup and more specifically what types of breakpoints are being used. I had quite a complex series of macros that were running on program upload, which set various hooks into memory for testing purposes. These hooks relied on software breakpoints being created, which would then call functions outside of the application. I have seen no problem in using these breakpoints in normal use, however their existence means that the debugging session doesn't run in real-time (i.e., the device is under control of the host PC). This, for a reason yet not completely known to me, caused problems when trying to debug interrupts and low power modes. (I suspect that if I was to look a bit deeper, I would see the need to use clock control whilst debugging, but I'll save that for another day).

So, to solve this problem and allow me to debug my interrupt and low power mode heavy code, which I'd ported into my larger application state machine, I had to do the following:

  1. Disable software breakpoints within IAR.
    They're not actually enabled by default, but if you've been doing clever things with macros like I had, you probably would've needed to enable them, since there just aren't enough hardware breakpoints available in most MSP430s (for instance, I only have two in the MSP430F2013, and C-SPY more often than not hogs one of those!). The obvious downside to this is that debugging becomes a bit more laborious, but at least it's reliable.
  2. Remove links to .mac Macro files.
    In other words, if you're using macros, don't. In my case, this meant that I had to hack some state machine logic in order to force myself down a certain route (that previously the macro had been doing for me). This clearly isn't ideal, but it will allow you to debug the interrupt/low power mode code. The macros can then be re-enabled afterwards.

So it turned out that there wasn't a problem with my port after all. I'm not particularly happy with this hacky solution, but at least it's a step forward. If I have the time, I'll investigate to see if I can work out a way of using software breakpoints and add to this answer.

like image 27
Ed King Avatar answered Jan 18 '23 02:01

Ed King