Critical sections stop working when external RAM is used

I have a board that uses an EFM32GG Cortex-M3. It has 128K of internal SRAM, and 1 MB of external SRAM connected via the MCU’s external bus interface. Until recently, I’ve only used the internal SRAM, and FreeRTOS was working very smoothly. I recently tried to start using the external SRAM, so I set the option to use this in the linker script. My bootloader would then initialize the external bus interface, and the application starts. The code to set up the EBI is provided by the board manufacturer’s BSP, but was only tested for bare metal applications.

Initially, it seemed that the application was working well, but I was getting some strange behavior. After some investigation, it seemed that critical sections were not working correctly. I’ve noticed this behavior in two areas:

  • My _write() functions write strings to the SWO coming in from printf’s. In it I use vTaskSuspendAll() and xTaskResumeAll() to ensure that only one task can write to the console at a time. When the program was running in the internal SRAM, I never got two strings overlapping each other, but when running on the external SRAM, I noticed this happening. This indicated to me that these functions were not working correctly.
  • I have a function that uses taskENTER_CRITICAL() and taskEXIT_CRITICAL to add data to a queue and set a boolean to true. an ISR then consumes the data in the queue and sets the boolean to false when complete. This is working correctly with no race conditions at all when running on internal SRAM, but on the external SRAM, I get a race condition soon after starting the application, indicating that there’s a problem with the critical section.

I would like some guidance on the cause of this. I am at a loss as to what is causing this… shouldn’t memory coherence and synchronization instructions in ARM be the same with external SRAM?

I believe you are barking up a wrong tree. If the critical section was not working, you would experience very frequent and random crashes in many parts of your system as the CS is used heavily for system serialization.

Can we see your code?

well, with the way it’s running… while the code is not crashing, things are definitely not working as they should. Perhaps I described it wrong, when I said that it “seemed like it’s working well”, it looked like the tasks were running and none of them crashed. I was not getting error messages, etc. But things that involved the critical sections (and there arent a lot of them) definitely were affected, and that doesn’t result in any errors. I’ve only noticed this problem by chance when I saw two tasks overlapping each other in printf’s

Unfortunately, I cannot share any code. But even if I could, I’m not sure what I should be sharing. Perhaps I can provide examples of what I’m doing

No, don’t bother then. Incomplete code is worse than no code at all. At best just as uninformative. Except, of course, if you reduce your code to a bare minimum publishable example that exposes the problem. That would be grade a and may very well get you on the right track right there.

Best of luck!

1 Like

Try entering the critical section and never exit:

taskENTER_CRITICAL();
for( ;; );

Put breakpoints in other tasks and ISRs and see if those are getting hit. This will help in conforming if taskENTER_CRITICAL() is working as expected.

1 Like

I think this is the best approach; very well, I will try to do that.

But first, I’ll do this:

Great idea, thank you. Why didn’t I think of this…

Thank you, I have a path forward now.