Automated summary
Governs OpenSkyhawk firmware work (STM32 PanelBridge/PanelGroup and RP2040 SimGateway) by enforcing the three-tier architecture, NODE_ID conventions, and routing to the authoritative FirmwarePlan/TechSpec documents.
Strengths
- Precise document map that avoids bulk-loading the spec and points to the single relevant file
- Explicit durable conventions: NODE_ID via build_flags, STM32F103C8/CB variants, expander access through classes rather than registers
- Clear boundary with neighbouring skills (pcb-design owns electrical wiring) and mandatory Doxygen on public API
- Availability guard that falls back to conventions and Firmware/Libraries/ code when the specs are missing from a partial checkout
Limitations
- Tightly bound to the OpenSkyhawk repository; most paths and conventions are meaningless outside it
- The supplied SKILL.md is truncated mid-sentence in the library/test layout section
- Assumes prior embedded experience (CAN, MCP23017, ADS1115) and offers project rules rather than background explanation
Use it whenever a task touches OpenSkyhawk firmware, a PlatformIO project, the CAN protocol, NODE_ID assignment, or PanelGroup input/output classes.
Avoid it for generic embedded work outside OpenSkyhawk, or for board wiring design, which belongs to the pcb-design skill.
Security analysis
SafeThis is a purely declarative documentation/router skill for an avionics-simulator firmware project. It contains no executable commands, no shell invocations, no network fetches, no credential handling, and no destructive operations. The only tool reference is a CI checker script mentioned descriptively. Listing it poses no execution risk.
No concerns found
How this analysis is madeExamples
I need to add a new PanelGroup node for the caution-light panel. Claim the next free NODE_ID in Firmware/NODE_IDS.md, create the PlatformIO project with -DNODE_ID in build_flags, and implement the two switches and one LED using the PanelGroup input/output classes as described in 05-panelgroup-api.md.PanelGroup node 7 never receives control packets from PanelBridge. Read 02-can-protocol.md and 09-startup-resync-diagnostics.md, then explain how NODE_ID filtering and the SYNC_REQ/READY handshake should behave and where my implementation likely diverges.Add a new analog axis to the RP2040 SimGateway for the radar elevation knob: use the HIDAxis class per 07-simgateway-api.md, wire it to the ADS1115 through the existing firmware class, and add the matching test sketch under the library test layout.name: firmware description: OpenSkyhawk firmware — STM32 (PanelBridge, PanelGroup) and RP2040 (SimGateway). Use when writing or changing firmware, PlatformIO projects, CAN protocol, NODE_ID assignment, DCS-BIOS integration, HID, panel sketches, shared libraries or their test sketches, or interacting with MCP23017/ADS1115 through the firmware classes (PanelGroup input/output classes). PanelGroup work is the most common interaction.
Firmware
Three-tier architecture:
PC ──USB HID + USB CDC(250k)── RP2040 SimGateway ──UART 250k── STM32 PanelBridge (NODE 0, CAN master)
└─CAN 500k─ PanelGroup nodes (NODE 1–63)
Authoritative spec — route here, don't bulk-load
Firmware/ScratchPad/FirmwarePlan/ is the authoritative firmware specification (the what:
contracts, data flows, decisions) and supersedes any firmware content in docs/_source/.
Firmware/ScratchPad/TechSpec/ holds the how (public API, class structure, method signatures).
Open the one relevant doc via the maps below rather than reading everything.
FirmwarePlan document map (read FirmwarePlan/README.md for the full index):
00-decisions.md— why each choice was made01-system-overview.md— topology, library roles, data-flow narrative02-can-protocol.md— CAN frame IDs,NODE_ID,ControlPacketwire format, TX queue03-uart-usb-hid-protocol.md— UART mux, HID frame format, USB identity04-dcs-bios-integration.md—controlIdspace,DCSIN_*, input-map generator rules05-panelgroup-api.md—PinRef, MCP23017 management, all input & output classes06-panelbridge-api.md— node tracking, export listener, input dispatch, SYNC_REQ07-simgateway-api.md—HIDAxis/HIDButton, relay contract, HID dispatch08-hardware-firmware-contracts.md— STM32 pin assignments, DRV8833 ~SLEEP, ADS111509-startup-resync-diagnostics.md— boot sequences, SYNC_REQ/READY, DIAG frames10-implementation-plan.md/11-open-issues.md— phased plan / deferred items
TechSpec: one file per library/class (CANProtocol, STM32Board, PanelBridge,
SimGateway, HIDControls, A4ECGenerator, and PanelGroup/{PinRef, PanelGroup, Inputs/*, Outputs/*}). Each cites its FirmwarePlan section. See TechSpec/README.md.
Availability guard: these specs are committed but may be absent in a partial checkout —
if Firmware/ScratchPad/FirmwarePlan/ is missing, rely on the conventions below plus the
committed code under Firmware/Libraries/.
Durable conventions (always apply)
- MCU variant:
STM32F103C8(64 KB) is the default for CAN avionics nodes; useSTM32F103CB(128 KB) only where flash demands it (PanelBridge runs the full DCS-BIOS input map). Use full part numbers in prose, never theCBT6ordering code orC8/CBshorthand. - NODE_ID: compile-time only —
build_flags = -DNODE_ID=Ninplatformio.ini, never a#defineinmain.cpp. 0 = PanelBridge; 1–63 = PanelGroup nodes. Claim the next free number inFirmware/NODE_IDS.mdin the same PR that starts the work; never reuse one.tools/check_node_ids.pyenforces this in CI. - Expander access is via classes, not registers: the
PanelGrouplibrary owns MCP23017 integration; ADS1115 viaADS1115.h. Instantiate input classes (Switch2Pos,Switch3Pos,RotarySwitch,SwitchMultiPos,AnalogInput,RotaryEncoder, …) and output classes (LED,IntegerOutput,SwitecX25Output, …) on aPinRef. The electrical wiring of those parts belongs to thepcb-designskill. - Timing: each class calls
millis()directly and keeps its ownuint32_ttimestamp — no shared clock. - Docblocks: Doxygen style on every public class/method/enum/non-obvious constant
(
@brief,@paramwith units,@return,@notefor ISR/timing constraints). Private members use plain//. - Library + test layout: each library is
Firmware/Libraries/<Name>/with alibrary.json; its tests are a standalone projectFirmware/Tests/<Name>/usingsrc_dir = tests, an[env_base]section, and onebuild_src_filterper scenario. SeeTechSpec/README.md. - Implementation order (dependencies flow down): HIDControls → A4EC → CANProtocol → STM32Board → PanelBridge / SimGateway → PanelGroup (PinRef → PanelGroup → Inputs/Outputs).
- Header ownership — keep shared headers single-purpose.
HIDControls.his HID controlId constants only;CANProtocol.howns CAN frame transport (incl.NodeHealthPayload). The cross-node status contract —NODE_STATUS_*(DCS-BIOS reporting),NodeHealthFlag,NodeFaultCode, andFaultSource— lives in the neutralNodeStatuslibrary, because every node type shares it (PanelGroup, PanelBridge, PDU) and it's broader than "health." Never shape a cross-node contract around one flavor (PanelGroup.h/OutputBase) or the HID namespace (D14). - Fault sources feed a node aggregator; no producer owns node health. A fault-producing object
(
DrumDisplay, a PDU rail monitor, a PanelBridge host-link watchdog) inheritsOpenSkyhawk::FaultSource(NodeStatus.h), self-registers, and reports cachedfaultCode()(aNodeFaultCode) + localfaultDetail()(DiagSerial-only string, never on the wire). The node-level aggregator walksFaultSource::head()→ setsHEALTH_n.faultId+ DEGRADED.OutputBasegets no fault API — an output is just one possible fault source, not special. - Includes: direct for what you use, but don't couple upward. Prefer a direct
#includeof a symbol's defining header over relying on a fragile transitive path — but if adding that include would drag a low-level/UI class into a heavier or conceptually-wrong layer, that's a signal the symbol is placed wrong (see the two rules above), not that you should hide it behind a transitive include. Don't add an include already reliably provided by a header the file must include anyway. - Spec-sync in the same PR. Any change to a public firmware API — struct/enum, class method,
wire format,
#definecontract — updates the authoritativeFirmwarePlan/+TechSpec/doc in the same PR, listed as a deliverable and self-checked before push. The spec is source of truth; drift defeats it. Grep the old value/claim before pushing. - Toolchain: PlatformIO. STM32 =
platform = ststm32,framework = arduino. RP2040 =earlephilhowercore with-DUSE_TINYUSB. - C++ standard: any project using
DrumDisplayneeds-std=gnu++20+build_unflags = -std=gnu++17— itsDrumReadoutdescriptors are C++20 designated initializers. Already baked into thePanelGroupscaffold template, so B6 sketches get it by default; add it explicitly to a standalone test project. The whole PanelGroup dep stack (U8g2 / MCP23017 / ADS1X15) is gnu++20-clean.
Verify
Build the affected project(s) with platformio run -d <project>; exercise each class in
isolation via its Firmware/Tests/<Name>/ sketch before integration.
From the file to a first result
The download contains exactly the content displayed on this page. This copy may differ from the latest version in the source repository.
View the source and supporting filesThis download contains SKILL.md only. Any scripts, references, templates and dependencies are not included. Get the required files from the source, preserving their directory structure, before continuing.
1. Download the file
Download SKILL.mdFrom the root of a test project, save the file as .skill-downloads/stm32-rp2040-firmware-development-mrwak9ej/SKILL.md, or use the command below. This folder is for inspecting the skill before installation.
Command for macOS/Linux or WSL: requires a POSIX shell and curl. On Windows without WSL, use the download button and create the folder manually.
mkdir -p '.skill-downloads/stm32-rp2040-firmware-development-mrwak9ej' && curl --fail --show-error --location 'https://skills-guides.com/api/skills/stm32-rp2040-firmware-development-mrwak9ej/download' --output '.skill-downloads/stm32-rp2040-firmware-development-mrwak9ej/SKILL.md.part' && mv '.skill-downloads/stm32-rp2040-firmware-development-mrwak9ej/SKILL.md.part' '.skill-downloads/stm32-rp2040-firmware-development-mrwak9ej/SKILL.md'2. Check prerequisites
Read SKILL.md before using it. If it references scripts or external services, inspect them and prepare the required access in your test environment.
No recognized prerequisites section in this file. This does not mean it is self-contained: libraries, tools and access requirements may be mentioned elsewhere in the content or source repository.
The platforms on this page are catalog indications. The paths below follow tool documentation; they do not prove this skill has been run in those tools. No minimum tool version is confirmed for this listing.
3. Load the skill
After inspection, copy the complete folder into your project using one of the commands below, then open a new tool session. The command stops if a folder with the same name already exists: compare the files before replacing it.
Claude Code
test -f '.skill-downloads/stm32-rp2040-firmware-development-mrwak9ej/SKILL.md' && test -s '.skill-downloads/stm32-rp2040-firmware-development-mrwak9ej/SKILL.md' && mkdir -p '.claude/skills' && test ! -e '.claude/skills/firmware' && cp -R '.skill-downloads/stm32-rp2040-firmware-development-mrwak9ej' '.claude/skills/firmware'Cursor
test -f '.skill-downloads/stm32-rp2040-firmware-development-mrwak9ej/SKILL.md' && test -s '.skill-downloads/stm32-rp2040-firmware-development-mrwak9ej/SKILL.md' && mkdir -p '.cursor/skills' && test ! -e '.cursor/skills/firmware' && cp -R '.skill-downloads/stm32-rp2040-firmware-development-mrwak9ej' '.cursor/skills/firmware'Codex
test -f '.skill-downloads/stm32-rp2040-firmware-development-mrwak9ej/SKILL.md' && test -s '.skill-downloads/stm32-rp2040-firmware-development-mrwak9ej/SKILL.md' && mkdir -p '.agents/skills' && test ! -e '.agents/skills/firmware' && cp -R '.skill-downloads/stm32-rp2040-firmware-development-mrwak9ej' '.agents/skills/firmware'OpenSkills
OpenSkills must already be installed. The local install/read procedure is checked with OpenSkills 1.5.0, which requires Node.js ≥ 20.6.0. Catalog slugs are not resolved automatically.
Official OpenSkills installationopenskills install './.skill-downloads/stm32-rp2040-firmware-development-mrwak9ej'openskills read 'stm32-rp2040-firmware-development-mrwak9ej'Reading should display the installed file content and its base directory. It does not run the skill or install its dependencies.
For an agent that reads AGENTS.md, then sync the index. This command changes AGENTS.md: review the diff before using it.
openskills syncManual method or another tool: attach SKILL.md to a conversation, or open it in an agent that can read files. Include any required supporting resources. No universal folder is recognized by every tool.
4. Try a first task
Use a short, synthetic input: an API endpoint, a small document or an interface brief. In a new conversation, attach the file or give the agent its path, then adapt this request:
Read .skill-downloads/stm32-rp2040-firmware-development-mrwak9ej/SKILL.md and apply its instructions to this example: [describe a test input]. Identify any missing files, dependencies or access. Produce the result requested by the skill without inventing data or running unreviewed scripts.Expected result: output matching the skill instructions, or a precise list of missing prerequisites. A read confirmation alone does not validate a first use. If an external resource is unavailable, that path remains untested.
React Hook Form Best Practices
Development
Master React Hook Form: avoid anti-patterns, manage subscriptions, and handle reset, dirty state, and controlled inputs correctly.
Emotion to Mantine Migration
Development
Migrate Emotion styled-components to Mantine components with style props and CSS modules. Use when converting .styled.tsx files or removing @emotion imports.
Scope Creep Detector
Development
Analyzes git diffs against a stated intent to detect scope creep, unrelated files, broad PRs, and oversized changes, then suggests keep, split, or justify actions.