I have come across a very obscure problem. I have a UART running, which collects bytes and interrupts the code to transfer the byte into a circular buffer (nothing exceptional here) and increments the byte count/write pointer.
In my main code loop I periodically check to see if there is a byte received, if so it hangs around a little longer to wait for a second byte to be received (this second byte is sent immediately after the first so it's a very short time). In reality i'm looking for a 5A 5A pair which indicates the start of a new message.
Alowing the program to free run (ie I don't actually read back anything from the buffer), the interrupt triggers and copies my data into the buffer (the debugger shows it and for my test set up I only receive one message), execution is normal.
However, if I put a while() loop in to just hang around for a bit (okay, I'll admit this is debug grade but the proper implementation with a timer doesn't work any better).
volatile uint32_t u32Counter = 0;
while(u32Counter < 0xFFFF);
running this code totally blocks this (and all other interrupts in the M4) from running. Similar code with a timer driving a flag is also totally blocked. However the code runs normally, eventually exits and returns to the rest of the execution (where the systick has also stopped and only the super loop runs).
I am at a bit of a loss as to where to start as I have never known interrupts be disabled by while loops. My interrupts still seem to be enabled although I haven't managed to identify a global interrupt disable/enable to check.
The code is being compiled in Rowley Crossworks, uses the SDK supplied by NXP (i'd tell you what version but I can't find one) and otherwise seems to run normally. I wouldn't consider myself a beginner - I've been writing code for some years. I am however foxed on this (inherited) project and would welcome any pointers (no pun intended).
volatile uint32_t u32Counter = 0;
while(u32Counter < 0xFFFF);
As it stands, this code will never exit - unless u32Counter is being set elsewhere in your code - which you don't state.
If this code is being executed in an interrupt handler with a high priority, that would prevent any other interrupt from firing. Also, if you DISABLE_IRQ() before the code, this would also prevent any interrupts firing.
But, unless you can provide more information, and especially code that reproduces the issue, then we can only guess.
Note that the code *on its own* will not prevent interrupts.
I appreciate your comments - as I said I have been writing code for a number of decades now so that slight error in the post is just that. It probably isn't obvious from the example but it was just psuedo code to stress that I am doing nothing at all hardware related at the point that these interrupts get blocked or disabled. With that in mind however, such an eternal loop should still not stop the interrupt from firing.
You have hit on the issue though - I cannot provide more information. The only two interrupts in use on the M4 core are the systick and the UART. The M4 doesn't even really do much either and it doesn't crash completely - the timeout described for example would time out and then code would return to the while(1) in main().
I initialise and use the UART in an identical way as I use my UART0 in the M0 core and when this little blocking loop isn't running, it does correctly receive the data suggesting the baud rate isnt an issue (besides which, the other interrupts break too - the systick and if I implement them, the hardware timers).
I can't post much code because it contains sensitive IP, however considering the power of the M4 core, I'm doing very little in it (I'm actually considering porting the whole thing to the M4 core - the twin core processor is a legacy of my predecessor on the project) and I'm certainly not trying to do anything super complex or clever. But I suppose for now I am just looking for a few ideas of registers which might offer information on how the interrupts are working, perhaps areas of code that might be of interest and maybe something that suggests I am not going completely mad.
UART - related communication often hangs or "crashes" if error conditions are not handled. I have quite a bit of experience here with other Cortex M devices.
Unless error flags like overrun, parity, or noise are not cleared, no further Rx event will occur.
Thanks for that, this is an avenue I have been exploring however its unlikely that this would cause all interrupts to stop... or is it?! When these flags are set, do they cause the interrupt to be entered repeatedly in immediate succession? If I toggle a debug LED, I am not seeing the LED signal constantly toggling.
On very close inspection (running the empty systick interrupt except for toggling an LED pin on a GPIO), the systick debug LED actually stops running when I begin transmitting data from the serial port.
I've added a sketch from the logic analyser which shows this happening - the red dot is approximately where the next systick should occur. The TX and RX are however identical to the apparently working UART in the M0 and the same as the examples from NXP.
I would need to read the UART section of of my LPC54xxx controller more closely.
I mostly referring to experience with STM32 devices.
In many cases, users do only enable interrupts for Rx (and Tx). Error interrupts are separate, and can be enable - or not. If not, the error conditions are only reflected in status flags, but do not raise interrupts. And im most UART peripherals I know, those error conditions prevent any further Rx/Tx interrupt.
In my projects I usually ignore such errors in HAL code and handle it on protocol level. Thus I usually enable error interrupts, but do nothing else than clear the flags in case.
It would be really handy if you could explain what you are *really* doing. You are dropping some hints about running something on M4 and something else on M0 - this is potentially really important. Leaving out important details like this makes it impossible to even make a guess as to what you have done wrong.
So, could you please state the problem again, but this time explain how you have split the app across processors.
Unfortunately I can't do that as it is commercially sensitive. However, I also don't feel that I'm really looking for a second pair of eyes on the code - I'm seeking gotchas on how the peripherals and interrupt controllers work on these dual core processors that could cause something strange like this. Given the complexity of the chip and the brevity with which it is described in the manual, I'm sure there are quite a number. After all, the documentation on how to set up a dual core project isn't even especially clear, accurate or up to date despite it being a nightmare that even someone of experience couldn't work out intuitively. Even the three areas of SRAM and how they are intended for use are not particularly well documented. Sure, we can do what we like with them, but there must have been some original intent at the design phase.
Perhaps there are none, but given the simplicity of the rest of the code, my coding experience and what a pain I have found working with this processor and driver library to be, my first stop is (unusually) questioning the chip on this occasion or at least looking at ways to debug it effectively. After all, creating a while loop as I described isn't going to write to 0x0000000 or accidentally write a value to a hardware register. And there are other tools I can use to support that like moving the memory location of the variable being iterated, changing optimisation levels so that things are jiggled around in memory or even using the hardware timer to replace the software loop.
I have fully working serial ports in several other NXP devices. It turns out the way to resolve this problem is to follow NXPs own advice and ignore the second core. I don't think it's a system that works especially well! Two processors and dual port RAM is more predictable, better documented and easier to control, particularly if there are peripherals in use on both cores.
I appreciate everyone else's help too. Thanks.