Minimal, embedded-optimized implementation of the SpaceWire packet and network layers (ECSS-E-ST-50-12C) carrying the CCSDS Packet Transfer Protocol (ECSS-E-ST-50-53C).
Standards Compliance
ECSS-E-ST-50-12C Rev.1: SpaceWire — links, nodes, routers and networks
ECSS-E-ST-50-53C: SpaceWire — CCSDS packet transfer protocol
ECSS-E-ST-50-51C: SpaceWire — protocol identification (Protocol ID 0x02)
CCSDS 133.0-B-2: Space Packet Protocol — the packet being carried; supplied by
the application through the payload adapter, not implemented here
Features
Core Protocol Implementation
Network layer: SpaceWire packets and routing — path (0–31) and logical
(32–254) addressing with header deletion (ECSS-E-ST-50-12C §5.6.8)
CCSDS Packet Transfer Protocol: encapsulation/extraction of the carried
packet with EOP/EEP receive status (ECSS-E-ST-50-53C)
Payload adapter: the carried packet is reached through three overridable
hooks, so the application plugs in its own Space Packet implementation
Scope (hardware boundary)
This is a packet- and network-layer library. The character/signal and
data-link levels — character encoding and parity, data-strobe signalling, link
initialisation and flow control, and EOP/EEP generation and detection — are
provided by the SpaceWire hardware CODEC. EOP/EEP are exchanged with this
library as out-of-band metadata, not as bytes within packet buffers.
Design Principles
Minimal footprint: small static library, no dynamic allocation
Zero allocation: stack- and caller-owned buffers only
Standalone: no external dependencies
Portable: C99; the only compiler-specific item is the weak-symbol
attribute behind SW_WEAK (GNU-compatible by default, overridable)
Standards-driven: no non-standard framing or checksums on the wire
A C99 compiler. The build must be warning-free under both gcc and
clang; CI checks both.
make and ar
Optional: gcovr for coverage, clang-format for the format check
Pick the compiler with CC:
make CC=gcc
make CC=clang
The Makefile builds with -Werror and a strict warning set (-Wall -Wextra -Wpedantic -Wconversion -Wshadow and others), so any warning fails the build.
OPT sets the optimisation flags (default -O2), e.g. make OPT="-O0 -g".
Do not set CFLAGS on the command line or in the environment: it replaces the
Makefile’s whole flag set, including the include path, -std=c99, -Werror and
the warnings. Use OPT for optimisation or instrumentation flags instead.
Build Everything
make all
Build Library Only
make lib
# Produces: build/lib/libspacewire.a (static) and build/lib/libspacewire.so (shared)
Build Example
make example
./build/bin/spacewire_example
Run Tests
make test
Two binaries are built and run: build/bin/spacewire_tests uses the default
payload hooks, and build/bin/spacewire_override_tests replaces them with its
own.
Sanitizers
make sanitize
make sanitize CC=clang
Rebuilds the library, both test binaries and the example with AddressSanitizer
and UndefinedBehaviorSanitizer (leak detection on, every report fatal), runs
them, and prints one result line per binary. Program output is shown only on
failure. The instrumented build goes to build/sanitize/ and is removed
afterwards.
Coverage (HTML)
make coverage-html
Requires gcovr. Runs make clean first, so any existing build/ output is
removed. It then builds instrumented tests in build/coverage-build/, runs
both test binaries, and writes the report to build/coverage/index.html.
Coverage of src/ must be 100% line and 100% branch; below that the
command still writes the report, then exits non-zero.
Formatting
Code style is defined in .clang-format. Check every C file
with:
The packet transfer layer never looks inside the packet it carries. It sizes,
serialises and parses it through three hooks declared in
include/spacewire_payload.h:
Hook
Purpose
sw_payload_size()
Serialised size of a payload object
sw_payload_serialize()
Write a payload object into the output buffer
sw_payload_parse()
Fill a payload object from a received buffer
The library ships weak default hooks in src/weak/ that treat the payload as
raw octets (sw_payload_raw_t), so it works on its own. To carry a structured
protocol, define the same three functions in the application; they replace the
defaults at link time. An application that compiles the library sources itself
and overrides all three hooks can leave src/weak/ out of its build.
The overrides must be linked as an object file. Overrides that exist only
inside a static library are silently ignored by the linker.
Because the hooks are resolved at link time, one program carries one payload
type: every sw_ptp_encode() and sw_ptp_decode() call in it uses the same
three hooks. Carrying two different protocols in one image would need the
application to dispatch on its own payload object inside the hooks.
sw_router_t: 784 bytes — a 256-entry routing table (3 B/entry) plus
counters
Thread Safety
Packet and routing operations work entirely on caller-owned state passed
by pointer and take no internal locks, so independent objects can be used from
independent tasks. The one shared item is the library’s statistics block:
sw_ptp_encode and sw_ptp_decode update a process-global counter (read
via sw_ptp_get_statistics, cleared via sw_ptp_reset_statistics), which is not
thread-safe. In a multi-task system, serialise the encode/decode/statistics
calls or confine them to a single task.
The same block is shared by every link: a node with more than one SpaceWire link,
such as a nominal and a redundant one, cannot read per-link figures from it and
has to count per link itself.
Limitations and Extensions
The library implements the packet and network layers; the following are out of
scope or not yet implemented:
Character/signal and data-link levels — provided by the SpaceWire hardware CODEC
Building and validating the carried CCSDS Space Packet — provided by the
application through the payload adapter
Time-codes, broadcast codes and distributed interrupts (ECSS-E-ST-50-12C §5.6.3–5.6.5)
Packet forwarding: the router makes the routing decision (output port, and
whether to delete the leading address); moving the packet is left to the
caller or the hardware. Wormhole routing and arbitration (§5.6.8.7–5.6.8.8)
are therefore out of scope
Group adaptive routing (§5.6.8.9): one output port per logical address
Packet multicast (§5.6.8.10)
Routing switch reset and port time-out (§5.6.8.11–5.6.8.12)
Guaranteed delivery — per ECSS-E-ST-50-53C the service is unconfirmed and
incomplete (no acknowledgement, retransmission or QoS)
These can be added as needed for specific mission requirements.
References
ECSS-E-ST-50-12C Rev.1 — SpaceWire: links, nodes, routers and networks
ECSS-E-ST-50-53C — SpaceWire: CCSDS packet transfer protocol
EmbeddedSpaceWire
Minimal, embedded-optimized implementation of the SpaceWire packet and network layers (ECSS-E-ST-50-12C) carrying the CCSDS Packet Transfer Protocol (ECSS-E-ST-50-53C).
Standards Compliance
0x02)Features
Core Protocol Implementation
Scope (hardware boundary)
This is a packet- and network-layer library. The character/signal and data-link levels — character encoding and parity, data-strobe signalling, link initialisation and flow control, and EOP/EEP generation and detection — are provided by the SpaceWire hardware CODEC. EOP/EEP are exchanged with this library as out-of-band metadata, not as bytes within packet buffers.
Design Principles
SW_WEAK(GNU-compatible by default, overridable)Project Structure
Building
Requirements
makeandargcovrfor coverage,clang-formatfor the format checkPick the compiler with
CC:The Makefile builds with
-Werrorand a strict warning set (-Wall -Wextra -Wpedantic -Wconversion -Wshadowand others), so any warning fails the build.OPTsets the optimisation flags (default-O2), e.g.make OPT="-O0 -g".Do not set
CFLAGSon the command line or in the environment: it replaces the Makefile’s whole flag set, including the include path,-std=c99,-Werrorand the warnings. UseOPTfor optimisation or instrumentation flags instead.Build Everything
Build Library Only
Build Example
Run Tests
Two binaries are built and run:
build/bin/spacewire_testsuses the default payload hooks, andbuild/bin/spacewire_override_testsreplaces them with its own.Sanitizers
Rebuilds the library, both test binaries and the example with AddressSanitizer and UndefinedBehaviorSanitizer (leak detection on, every report fatal), runs them, and prints one result line per binary. Program output is shown only on failure. The instrumented build goes to
build/sanitize/and is removed afterwards.Coverage (HTML)
Requires
gcovr. Runsmake cleanfirst, so any existingbuild/output is removed. It then builds instrumented tests inbuild/coverage-build/, runs both test binaries, and writes the report tobuild/coverage/index.html. Coverage ofsrc/must be 100% line and 100% branch; below that the command still writes the report, then exits non-zero.Formatting
Code style is defined in .clang-format. Check every C file with:
Drop
--dry-run --Werrorand add-ito reformat in place.Continuous Integration
.github/workflows/ci.yml runs on every push to
mainand on every pull request:makewith gcc and with clang: libraries, both test binaries, examplemake coverage-html; fails below 100% line or branch; report uploaded as an artifactmake sanitizewith gcc and with clang.cand.hfile matches.clang-formatRun the same checks locally before pushing.
Clean
Quick Start
See examples/main.c.
Payload Adapter
The packet transfer layer never looks inside the packet it carries. It sizes, serialises and parses it through three hooks declared in include/spacewire_payload.h:
sw_payload_size()sw_payload_serialize()sw_payload_parse()The library ships weak default hooks in
src/weak/that treat the payload as raw octets (sw_payload_raw_t), so it works on its own. To carry a structured protocol, define the same three functions in the application; they replace the defaults at link time. An application that compiles the library sources itself and overrides all three hooks can leavesrc/weak/out of its build.The overrides must be linked as an object file. Overrides that exist only inside a static library are silently ignored by the linker.
Because the hooks are resolved at link time, one program carries one payload type: every
sw_ptp_encode()andsw_ptp_decode()call in it uses the same three hooks. Carrying two different protocols in one image would need the application to dispatch on its own payload object inside the hooks.docs/space_packet_integration.md shows the overrides for CCSDS Space Packets using EmbeddedSpacePacket.
Memory Usage
Figures for x86-64, gcc
-O2:.text, default payload hooks included); no dynamic allocation, all buffers caller-owned.bss), the CCSDS PTP statistics blocksw_ptp_frame_t: 16 bytes (CCSDS PTP addressing fields)sw_router_t: 784 bytes — a 256-entry routing table (3 B/entry) plus countersThread Safety
Packet and routing operations work entirely on caller-owned state passed by pointer and take no internal locks, so independent objects can be used from independent tasks. The one shared item is the library’s statistics block:
sw_ptp_encodeandsw_ptp_decodeupdate a process-global counter (read viasw_ptp_get_statistics, cleared viasw_ptp_reset_statistics), which is not thread-safe. In a multi-task system, serialise the encode/decode/statistics calls or confine them to a single task.The same block is shared by every link: a node with more than one SpaceWire link, such as a nominal and a redundant one, cannot read per-link figures from it and has to count per link itself.
Limitations and Extensions
The library implements the packet and network layers; the following are out of scope or not yet implemented:
These can be added as needed for specific mission requirements.
References
License
See LICENSE file.