Why does my second core lock up when I try to pass data between the two of them?

Nov 02, 2026 Last reply: 6 hours ago 3 Replies

First reply

QuarryGuy

The spinning core issue you are seeing is almost certainly a memory visibility problem. When the big core writes data to a shared memory region that is configured as cacheable, it is likely staging that write in its own cache rather than committing it directly to the SRAM. The…

Read the full reply

I got one of the dual-core Nucleo boards a few weeks back and I'm stuck on somthing basic. The big core boots fine and blinks LEDs, no problem. The trouble starts when I release the second core and let them talk. I set aside a chunk of RAM for shared messages and tried flagging new data with the hardware semaphore peripheral. About half the time the smaller core just sits there spinning and never sees the flag flip. My guess is the cache on the big core is the culprit, like it writes the data but the other core reads a stale copy. I tried marking the shared area as non-cacheable in the linker script but honestly I'm guessing at the settings. Is that the right direction, or shold I be doing cache maintenace manually before each handoff? Also curious how people structure the messages themselves. Right now I just have a ring buffer with a head and tail index, and I keep reading that this can go wrong in wierd ways. Any pointers appreciated.


The spinning core issue you are seeing is almost certainly a memory visibility problem. When the big core writes data to a shared memory region that is configured as cacheable, it is likely staging that write in its own cache rather than committing it directly to the SRAM. The smaller core, looking at the same address, will only see the older, unwritten data in the physical memory because the cache line hasn't been flushed or invalidated. You have to explicitly manage this. The linker script hint was a good thought but usually not the whole solution. For the cache problem, instead of trying to force the whole section to be non-cacheable, which kills performance, you need to use the cache maintenance functions provided in the HAL. After the big core writes a new message into the shared RAM, it must call the specific functions that perform a 'clean and invalidate' operation on that memory region. This pushes the modified lines out of the M7's cache and into the actual RAM, guaranteeing the M4 sees the update. When the M4 finishes reading, it should also perform a clean or invalidate depending on its read pattern.

Regarding the ring buffer structure, you are right to be worried about the head and tail indices. Even if the data payload arrives correctly, if the indices are updated via simple writes, you introduce a race condition. One core might update the tail while the other is reading the head. You must use a lightweight locking mechanism or, better yet, rely on the atomic operations provided by the core's intrinsic functions to update those pointers. Simple increments aren't safe in a dual-core environment. It's about ensuring these pointer updates happen indivisibly.

One thing to check on your shared struct: the H7 stuffs 32 bytes into every memory line, so if your head and tail sit next to your payload data, writes to one can pull the others along for the ride. Pad the indices out so they live on thier own boundary and a lot of the weirdness goes away. I did that on a board I maintain at work, a modbus gateway that's been running two cores for about three years now, and the random corruption we used to see about once a week just stopped. Also look at having the small core sleep on the semaphore interrupt instead of burning cycles polling, it wakes up only when the big side releases.

One thing that bit me on a similar setup: make sure your flag variable is acutally marked volatile. I burned a whole afternoon once because the compiler kept the flag in a register inside the spinning loop, so it never re-read memory no matter what the other core did. No amount of cache fiddling fixes that. Also worth looking at OpenAMP or the IPCC peripheral if you'd rather not hand-roll the messaging. More setup upfront but it handles alot of the nasty details for you. What does your spin loop look like, just a while on the flag?

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required