ormus-solutions/libreembed-claude-code/rtos-patterns
- community
Checking that the SKILL.md file is still in the repository.
FreeRTOS and Zephyr reference: priority inversion taxonomy, deferred interrupt processing, watchdog kick patterns, mutex vs. semaphore choice, stack sizing, FreeRTOSConfig.h settings, the stack overflow hook, and rate monotonic analysis. Use when designing, reviewing, or debugging RTOS firmware.
Install
npx vskill@latest install ormus-solutions/libreembed-claude-code/rtos-patternsSKILL.md
RTOS patterns library
Reference patterns for FreeRTOS + Zephyr task design. Use as a lookup when designing or reviewing RTOS firmware.
Priority inversion taxonomy
Three forms exist; the agent distinguishes them:
1. Unbounded priority inversion (the bad one)
H blocks on resource R held by L. M (between H and L in priority) preempts L. H is now blocked for as long as M runs — unbounded.
Fix: priority inheritance (FreeRTOS mutex, Zephyr mutex) OR priority ceiling (declare R's ceiling = highest task that ever uses R).
2. Bounded priority inversion
H blocks on R held by L. L holds R for time T. H is delayed by T. T is bounded if L's critical section is bounded.
Fix: ensure L's critical section is short and bounded. Don't sleep, don't block, don't make long calls while holding R.
3. Chain blocking
H blocks on R1 held by L1. L1 blocks on R2 held by L2. H is delayed by L2's critical section + L1's critical section.
Fix: priority ceiling protocol on R1 + R2 (every holder runs at the highest possible blocker priority). Or use a single mutex / message passing.
Deferred interrupt processing (DIP) pattern
When an ISR has work that exceeds "set a flag, post a semaphore":
Use direct-to-task notification (FreeRTOS) or k_sem_give from ISR (Zephyr) for lowest-latency DIP.
Watchdog kick patterns
Pattern 1: Single low-priority kicker
Catches: total system hang. Misses: single-task hang.
Pattern 2: Heartbeat aggregator
Catches: single-task hang (any task that doesn't post heartbeat in its expected window). Misses: deadlock where all tasks post heartbeats but make no real progress.
Pattern 3: Window watchdog (WWDG)
Hardware that resets if kicked too soon. Catches runaway loops that fire kicks too often.
Use when: code paths exist where a loop might erroneously kick the watchdog repeatedly.
Mutex vs. semaphore decision
Picking the wrong primitive is a common bug source.
| Use case | Primitive | |
|---|---|---|
| Protect shared mutable state | Mutex (with priority inheritance) | |
| Resource counting (N units) | Counting semaphore | |
| Signal "event happened" from ISR to task | Binary semaphore or direct task notification | |
| Producer-consumer with data | Queue or stream buffer | |
| Multiple tasks wait for one of N events | Event group | |
| One-shot "system initialized" broadcast | Event group with all-tasks-set pattern |
Critical: don't use a counting semaphore as a mutex. Counting semaphores don't have priority inheritance in FreeRTOS. Mutex is what you want for mutual exclusion.
Stack-size sizing recipe
- Build with
-fstack-usage. Per-function stack usage lands in.sufiles next to each.o. - Walk the call graph from each task's entry point. Sum the deepest path.
- Add the worst-case ISR preemption stack — sum of ALL ISR stack usages (since any can preempt any task).
- For Cortex-M with FPU, add 132 bytes for lazy FP stacking on first FP use.
- Multiply by 1.3 for safety margin. 1.5 if you're not sure about the ISR worst-case.
- Round up to a nice boundary (multiple of 64 or 128 bytes).
In Zephyr, CONFIG_THREAD_STACK_INFO=y lets k_thread_stack_space_get report runtime stack high-water marks. Use this in development to validate the sizing.
In FreeRTOS, uxTaskGetStackHighWaterMark does the same.
Task design heuristics
How many tasks?
The minimum that gives you:
- One task per truly concurrent activity (truly = different rates, different deadlines, different blocking patterns)
- Not one task per concept. Two tasks where one would do doubles overhead.
- A separate watchdog/health task — usually warranted even if it could fold into the main loop.
A common over-decomposition: separate tasks for "read sensor" and "process sensor data" when one task can do both. The processing is data-dependent on the read; there's no concurrency to exploit.
Priority assignment
Reserve highest priority for the work that MUST run on time. Don't add tasks at the top of the priority stack without reason — they cost determinism.
When to use software timers vs. tasks
Software timer (FreeRTOS) / kernel timer (Zephyr): use when:
- The action is short (< 1 ms of work)
- The action doesn't need its own stack
- The action is periodic
Use a task when:
- The action is long
- The action can block
- The action has its own state machine
The timer callback runs in the timer task's context (FreeRTOS) — sharing a stack with other timer callbacks. A long callback delays all other timer callbacks.
Common mistakes catalog
"My task isn't running"
Check in order:
- Did you call
vTaskStartScheduler()/ start the scheduler? - Is the task's priority higher than any task that's busy-running?
- Is the task blocked on something that's never signaled?
- Did
xTaskCreatesucceed? Check the return code. - Is the stack overflowing? Enable
configCHECK_FOR_STACK_OVERFLOWand provide a hook.
"System resets randomly"
Check:
- Watchdog firing — instrument the watchdog hook to log task heartbeats before reset
- Hard fault — install a fault handler that dumps the LR + PC to UART before reset
- Stack overflow — enable stack overflow checking
- Bus fault from invalid pointer — check that DMA buffers haven't been freed or moved
"Task X works on its own but fails when other tasks are running"
Inversion / starvation. Walk the priority graph.
"ISR latency too long"
- Don't
printfin an ISR. - Don't take mutexes in an ISR (technically illegal; will assert in debug builds).
- Don't do floating-point work in an ISR unless you've configured lazy FP stacking.
- Check if you have nested interrupts disabled (
__disable_irqin some code path).
"Memory corruption on shared global"
You're using a shared global without protection. Either:
- Switch to message passing (queue or stream buffer).
- Protect with a mutex.
- If single-writer + single-reader + atomic-size: use
volatile+ memory barriers and pray (only OK for very simple cases).
Code patterns
FreeRTOS and Zephyr patterns for production embedded firmware.
Producer/Consumer with Queue and Backpressure
Mutex-Protected Shared Resource
FreeRTOS Config Settings
Critical FreeRTOSConfig.h settings for production:
Stack Overflow Hook
Rate Monotonic Priority Assignment
Rate Monotonic (RM) theorem: assign priority inversely to period. Shorter period = higher priority.
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 90 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingplugins/rtos-patterns/skills/rtos-patterns/SKILL.md
Popularity
- 7-day trend score
- 0
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/ormus-solutions/libreembed-claude-code/rtos-patterns)