Skip to content

Commit a87f99a

Browse files
update README
docs: Rewrite README to match EmbeddedSpaceWire structure and depth
2 parents 3ce6f75 + 8742416 commit a87f99a

1 file changed

Lines changed: 247 additions & 39 deletions

File tree

README.md

Lines changed: 247 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,260 @@
11
# EmbeddedSpacePacket
2-
Minimum CCSDS SpacePacket implementation in C for embedded applications.
32

4-
Contents
5-
- tiny header and implementation in `include/` and `src/`
6-
- example in `examples/`
7-
- simple host test in `tests/`
8-
- `Makefile` to build library, example and test
3+
Minimal, embedded-optimized implementation of the **CCSDS Space Packet Protocol** in C,
4+
following the international standard.
95

10-
Build & run (host):
6+
## Standards Compliance
117

12-
1. Build everything:
8+
- **CCSDS 133.0-B-2**: Space Packet Protocol
139

14-
make
10+
## Features
1511

16-
2. Run example:
12+
### Core Protocol Implementation
1713

18-
./examples/spacepacket_example
14+
- **Primary Header**: 6-byte CCSDS-compliant header with version, type, APID, sequence
15+
control and packet length fields
16+
- **Secondary Header**: Optional application-defined secondary header with configurable
17+
length
18+
- **Sequence Control**: Segmentation flags (unsegmented, first, continuation, last) and
19+
14-bit sequence counter
20+
- **CRC-16-CCITT**: Optional CRC over secondary header and payload, signalled by a flag
21+
in the secondary header
22+
- **Serializer / Parser**: Symmetric encode and decode paths with big-endian network byte
23+
order
1924

20-
3. Run tests:
25+
### Design Principles
2126

22-
./tests/ctest
27+
- **Minimal footprint**: Single header + single source file
28+
- **Zero allocation**: Stack-based, no dynamic memory in the library
29+
- **Embedded-optimized**: No external dependencies, no OS primitives
30+
- **Portable**: Pure C11, big-endian network byte order for all header fields
31+
- **Safe**: Input validation on every public API entry point
2332

24-
Notes
25-
- This is a minimal, small-footprint implementation designed for embedded use.
26-
- The primary header implemented is CCSDS-like (6 bytes). The packet length field
27-
in the header stores `payload_len - 1` when serializing and the parser reconstructs
28-
`payload_len = header_length + 1`.
33+
## Project Structure
2934

30-
CCSDS Space Packet (brief)
31-
- **Primary header (6 bytes):** bytes 0-1 hold version (3 bits), packet type (1 bit),
32-
secondary header flag (1 bit) and APID (11 bits). Bytes 2-3 are the sequence control
33-
field: segmentation/sequence flags (2 bits) and packet sequence count (14 bits). Bytes
34-
4-5 are the Packet Length field (16 bits) which encodes the length of the Packet Data
35-
Field minus 1 (i.e., PacketLength = N-1 where N is data-field octets).
36-
- **Packet Data Field:** follows the primary header and contains an optional secondary
37-
header (if the secondary header flag is set) followed by user/application data.
38-
- **Secondary header:** optional, format and semantics are application-dependent (time
39-
tags, service headers, etc.). The presence is indicated by the secondary header flag.
40-
- **Segmentation/Sequence Flags:** indicate if the packet is standalone (unsegmented),
41-
first, continuation or last segment when a logical packet is split over multiple
42-
sequence counts.
43-
- **APID (Application Process ID):** identifies the source/consumer application or
44-
logical stream of packets.
45-
- **Error control:** CCSDS Space Packet by itself does not mandate a particular CRC in
46-
the primary header; error control is usually provided in lower or higher layers or
47-
via application-specific fields. This repository adds an optional CRC covering the
48-
secondary header and payload as an example.
35+
```
36+
EmbeddedSpacePacket/
37+
├── include/
38+
│ └── space_packet.h # Public API and types
39+
├── src/
40+
│ └── space_packet.c # Serializer, parser, CRC and helpers
41+
├── examples/
42+
│ └── main.c # Example: build, serialize and parse a packet
43+
├── tests/
44+
│ ├── cunit.h # Minimal test framework
45+
│ └── unit_tests.c # Unit tests
46+
├── Makefile
47+
└── README.md
48+
```
4949

50+
## Building
5051

51-
Links:
52-
- https://ccsds.org/Pubs/133x0b2e2.pdf (CCSDS Space Packet Standard)
52+
### Build Everything
53+
54+
```bash
55+
make
56+
```
57+
58+
Builds the static library, the example binary and the test binary.
59+
60+
### Build Library Only
61+
62+
```bash
63+
make lib
64+
# Produces: libspacepacket.a
65+
```
66+
67+
### Build Example
68+
69+
```bash
70+
make example
71+
./examples/spacepacket_example
72+
```
73+
74+
### Run Tests
75+
76+
```bash
77+
make ctest
78+
./tests/ctest
79+
```
80+
81+
### Clean
82+
83+
```bash
84+
make clean
85+
```
86+
87+
## Quick Start
88+
89+
### Create and Serialize a Space Packet
90+
91+
```c
92+
#include "space_packet.h"
93+
#include <stdio.h>
94+
#include <string.h>
95+
96+
int main(void) {
97+
const uint8_t payload[] = {'H', 'e', 'l', 'l', 'o', ' ', 'S', 'P'};
98+
99+
/* Secondary header: flags byte (LSB=1 requests CRC), length byte (0 extra bytes) */
100+
const uint8_t sec_hdr[] = {0x01, 0x00};
101+
102+
sp_packet_t pkt;
103+
sp_packet_init(&pkt);
104+
sp_set_primary_header(&pkt,
105+
0, /* version */
106+
0, /* type: telemetry */
107+
1, /* secondary header present */
108+
0x100, /* APID */
109+
SP_SEQ_FLAG_UNSEGMENTED, /* sequence flags */
110+
1 /* sequence count */
111+
);
112+
sp_set_secondary_header(&pkt, sec_hdr, sizeof(sec_hdr));
113+
sp_set_payload(&pkt, payload, sizeof(payload));
114+
115+
uint8_t buf[256];
116+
size_t n = sp_packet_build_frame(&pkt, buf, sizeof(buf));
117+
if (n == 0) {
118+
printf("Serialization failed\n");
119+
return 1;
120+
}
121+
printf("Serialized %zu bytes\n", n);
122+
return 0;
123+
}
124+
```
125+
126+
### Parse an Incoming Packet
127+
128+
```c
129+
sp_packet_t parsed;
130+
if (sp_packet_parse(&parsed, buf, n)) {
131+
printf("APID: 0x%03X, seq count: %u, payload: %u bytes\n",
132+
parsed.ph.apid,
133+
parsed.ph.seq_count,
134+
parsed.payload_len);
135+
} else {
136+
printf("Parse failed (bad length, corrupt CRC, etc.)\n");
137+
}
138+
```
139+
140+
### Compute a CRC Independently
141+
142+
```c
143+
uint16_t crc = sp_crc16_ccitt(data, data_len);
144+
printf("CRC-16-CCITT: 0x%04X\n", crc);
145+
```
146+
147+
## API Reference
148+
149+
### Lifecycle
150+
151+
```c
152+
/* Zero-initialize a packet structure. */
153+
void sp_packet_init(sp_packet_t *pkt);
154+
```
155+
156+
### Building a Packet
157+
158+
```c
159+
/* Set primary header fields (values are masked to valid bit widths). */
160+
void sp_set_primary_header(sp_packet_t *pkt,
161+
uint8_t version,
162+
uint8_t type,
163+
uint8_t sec_hdr_flag,
164+
uint16_t apid,
165+
sp_seq_flag_t seq_flags,
166+
uint16_t seq_count);
167+
168+
/* Set secondary header (pointer into application-owned memory). */
169+
void sp_set_secondary_header(sp_packet_t *pkt,
170+
const uint8_t *sec_hdr,
171+
uint16_t sec_hdr_len);
172+
173+
/* Set payload (pointer into application-owned memory). */
174+
void sp_set_payload(sp_packet_t *pkt,
175+
const uint8_t *payload,
176+
uint16_t payload_len);
177+
178+
/* Serialize to buffer. Returns bytes written, or 0 on error. */
179+
size_t sp_packet_build_frame(const sp_packet_t *pkt,
180+
uint8_t *buf,
181+
size_t buf_len);
182+
```
183+
184+
### Low-Level Serialization
185+
186+
```c
187+
/* Required output buffer size for the given packet. */
188+
size_t sp_packet_serialize_size(const sp_packet_t *pkt);
189+
190+
/* Serialize into buf. Returns bytes written, or 0 on error. */
191+
size_t sp_packet_serialize(const sp_packet_t *pkt,
192+
uint8_t *buf,
193+
size_t buf_len);
194+
195+
/* Parse buf into out. out->payload points into buf (no copy). */
196+
/* Returns 1 on success, 0 on failure (short buffer, bad CRC, etc.). */
197+
int sp_packet_parse(sp_packet_t *out, uint8_t *buf, size_t buf_len);
198+
```
199+
200+
### Utilities
201+
202+
```c
203+
/* CRC-16-CCITT (polynomial 0x1021, init 0xFFFF). */
204+
uint16_t sp_crc16_ccitt(const uint8_t *data, size_t len);
205+
```
206+
207+
### Types
208+
209+
```c
210+
typedef enum {
211+
SP_SEQ_FLAG_UNSEGMENTED = 0,
212+
SP_SEQ_FLAG_FIRST_SEGMENT = 1,
213+
SP_SEQ_FLAG_CONTINUING_SEGMENT = 2,
214+
SP_SEQ_FLAG_LAST_SEGMENT = 3
215+
} sp_seq_flag_t;
216+
```
217+
218+
## Memory Usage (Estimated)
219+
220+
- **Library (stripped)**: < 2 KB
221+
- **`sp_packet_t` struct**: ~40 bytes (stack)
222+
- **Serialization buffer**: 6 bytes header + secondary header + payload + 2 bytes CRC
223+
- **No heap usage**: all allocations are caller-supplied
224+
225+
## CCSDS Space Packet — Protocol Notes
226+
227+
- **Primary header (6 bytes):** bytes 0–1 hold version (3 bits), packet type (1 bit),
228+
secondary header flag (1 bit) and APID (11 bits). Bytes 2–3 are the sequence control
229+
field: segmentation flags (2 bits) and packet sequence count (14 bits). Bytes 4–5 are
230+
the Packet Length field (16 bits) which encodes the number of Packet Data Field octets
231+
minus 1.
232+
- **Packet Data Field:** follows the primary header; contains an optional secondary
233+
header and user/application data.
234+
- **Secondary header:** optional, application-defined. Presence is indicated by the
235+
secondary header flag. Format: byte 0 = flags (LSB = 1 requests CRC), byte 1 =
236+
number of additional secondary header bytes, followed by that many bytes.
237+
- **Segmentation flags:** indicate whether a packet is standalone (`UNSEGMENTED`),
238+
or the first, continuation, or last segment of a segmented logical packet.
239+
- **APID (Application Process ID):** 11-bit identifier for the source or consumer
240+
application / logical data stream.
241+
- **CRC:** CCSDS Space Packet does not mandate CRC in the primary header. This library
242+
provides an opt-in CRC-16-CCITT covering the secondary header and payload, enabled by
243+
setting the LSB of the secondary header flags byte.
244+
245+
## Limitations
246+
247+
Current implementation focuses on core protocol features:
248+
249+
- No fragmentation / reassembly logic (sequence flag tracking is left to the application)
250+
- CRC is only supported when a secondary header is present
251+
- No thread safety (external locking required in multi-threaded contexts)
252+
- Parser does not copy payload; the caller must keep the source buffer alive
253+
254+
## References
255+
256+
- [CCSDS 133.0-B-2: Space Packet Protocol](https://ccsds.org/Pubs/133x0b2e2.pdf)
257+
258+
## License
259+
260+
See LICENSE file.

0 commit comments

Comments
 (0)