FreeRTOS on Raspberry Pi Pico: Check the SDK Wait-and-Notify Contract

A synchronization primitive can protect its internal state correctly and still strand a task at the handoff between unlocking and waiting. In a Pico SDK and FreeRTOS integration, that handoff deserves its own review; replacing a spinlock or increasing a timeout does not necessarily address it.

This article focuses on the SDK's RTOS wait-and-notify contract. It uses Pico SDK 2.3.1 release notes and the official lock-core source inspected on October 19, 2026. The moving source branch is not treated as a certified description of every released kernel port.

Pico synchronization diagram separates protected state, atomic wait handoff, release-specific overrides and multi-waiter testing.
Original conceptual engineering diagram. Proposed review method, not a measured result.

Distinguish protected state from task waiting

The SDK's lock-core interface describes primitives that protect internal state with a spinlock, then release it while waiting or notifying. RTOS integration can override those operations so a waiting caller blocks as a task rather than merely waiting for a processor event.

Its contract requires the unlock-and-wait handoff to preserve a relevant notification. Waking is not itself permission to proceed: the primitive rechecks protected state and can wait again. These are separate properties, and both matter under contention.

For an application review, ask two questions. Does the waiting path let other runnable work execute as intended? And can a release notification be lost for a waiter crossing the handoff boundary? A simple uncontended mutex demonstration answers neither question well.

Read the release-specific interoperability warning

The Pico SDK 2.3.1 release notes discuss additional testing of FreeRTOS synchronization interoperability and rare race conditions in existing ports. They introduce `LOCK_INTERNAL_SPIN_UNLOCK_WITH_NOTIFY_WAKES_ALL` to describe the notification guarantee, together with an SDK workaround when overrides do not provide it. They also describe `PICO_TIME_USE_SLEEP_NOTIFIER` for routing SDK sleeps through the RTOS integration.

Do not set a capability flag merely to remove a workaround or improve a benchmark. The flag makes a statement about the implementation's behavior. That statement needs evidence from the exact override selected by the build, not a general belief that an RTOS semaphore should wake tasks correctly.

Equally, do not conclude that every FreeRTOS release is affected in the same way. Record the SDK revision, kernel port revision and relevant integration definitions before comparing a report with the release notes. A later fix or local port change can alter the applicable behavior.

Exercise more than one waiter

A useful proposed test creates several tasks contending for the same SDK primitive while unrelated work remains runnable. Arrange repeated transitions where a task is about to block as another context releases the resource. Track whether every eligible waiter eventually rechecks the state, rather than simply counting notifications sent.

This is a conceptual fault-exposure test, not a claim that a specific delay reliably reproduces the race. Instrumentation can change scheduling enough to hide a narrow window. Use bounded tests on a development target and keep the expected progress condition explicit.

Also test normal contention separately from a permanently held resource. A waiter that cannot proceed because the owner never releases is a different diagnosis from a waiter that remains asleep after a relevant release. Log the resource state and task progress without adding blocking diagnostics inside the synchronization path.

Keep sleep behavior in the same integration audit

SDK sleep calls and kernel task delays should not be assumed interchangeable merely because both postpone work. Verify how the selected SDK sleep path interacts with the port's wait hooks and whether unrelated tasks continue to run. Measure the actual build before attributing lost processing time to a scheduler defect.

The outcome should be a narrow integration finding: the selected overrides honor the required handoff semantics, or a specific gap remains to be fixed and retested. Changing application timeouts may reduce visible failures, but it cannot prove that notifications reach the waiters that depend on them.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *