Skip to content

Commit ccc2e2f

Browse files
Merge pull request #9 from OpenSpaceCode/dev/maintain-update
General maintanence update - new release
2 parents 8fec1c8 + c8710af commit ccc2e2f

22 files changed

Lines changed: 2027 additions & 490 deletions

‎.clang-format‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
Language: C
2+
Language: Cpp
33
BasedOnStyle: LLVM
44

55
# Indentation
@@ -13,7 +13,7 @@ ColumnLimit: 100
1313

1414
# Braces
1515
BreakBeforeBraces: Allman
16-
InsertBraces: false
16+
InsertBraces: true
1717

1818
# Spaces
1919
SpaceAfterCStyleCast: false

‎.github/workflows/ci.yml‎

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
8+
jobs:
9+
unit-tests:
10+
name: Unit tests (${{ matrix.cc }})
11+
runs-on: ubuntu-latest
12+
strategy:
13+
fail-fast: false
14+
matrix:
15+
cc: [gcc, clang]
16+
steps:
17+
- uses: actions/checkout@v4
18+
- name: Build library, examples and run unit tests
19+
run: make all test CC=${{ matrix.cc }}
20+
- name: Run examples
21+
run: |
22+
./build/bin/tm_example
23+
./build/bin/tc_example
24+
./build/segment_header/tm_example
25+
./build/segment_header/tc_example
26+
27+
coverage:
28+
name: Coverage (100% line and branch)
29+
runs-on: ubuntu-latest
30+
steps:
31+
- uses: actions/checkout@v4
32+
- name: Install gcovr
33+
run: sudo apt-get update && sudo apt-get install -y gcovr
34+
- name: Build instrumented tests and generate report
35+
run: make coverage-html
36+
- name: Enforce 100% line and branch coverage
37+
run: >
38+
gcovr -r . --filter src
39+
--fail-under-line 100
40+
--fail-under-branch 100
41+
- name: Upload HTML report
42+
if: always()
43+
uses: actions/upload-artifact@v4
44+
with:
45+
name: coverage-html
46+
path: build/coverage/
47+
if-no-files-found: ignore
48+
49+
sanitizers:
50+
name: ASan + UBSan
51+
runs-on: ubuntu-latest
52+
env:
53+
ASAN_OPTIONS: detect_leaks=1:abort_on_error=1
54+
UBSAN_OPTIONS: print_stacktrace=1
55+
steps:
56+
- uses: actions/checkout@v4
57+
- name: Build and run unit tests and examples under ASan and UBSan
58+
run: make sanitize

‎.gitignore‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,5 @@ dkms.conf
5858
build/
5959
obj/
6060
bin/
61-
.github/
6261
.vscode/
62+
TODO.md

‎LICENSE‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@
186186
same "printed page" as the copyright notice for easier
187187
identification within third-party archives.
188188

189-
Copyright [yyyy] [name of copyright owner]
189+
Copyright 2026 OpenSpaceCode contributors
190190

191191
Licensed under the Apache License, Version 2.0 (the "License");
192192
you may not use this file except in compliance with the License.

‎Makefile‎

Lines changed: 82 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1-
CC = gcc
2-
CFLAGS ?= -O2 -Iinclude -Wall -Wextra -Wpedantic -Wshadow \
1+
CC ?= cc
2+
# Optimisation / instrumentation flags; overridden by the sanitize target and by
3+
# tools/coverage_html.sh
4+
OPT ?= -O2
5+
SANITIZE_OPT = -O1 -g -fno-omit-frame-pointer -fsanitize=address,undefined \
6+
-fno-sanitize-recover=all
7+
# Stronger warnings for code quality; any warning fails the build
8+
CFLAGS ?= $(OPT) -Iinclude -Werror -Wall -Wextra -Wpedantic -Wconversion -Wshadow \
39
-Wcast-align -Wcast-qual -Wpointer-arith -Wformat=2 \
410
-Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wundef \
5-
-std=c11
11+
-std=c99
612
LDFLAGS =
713

814
SRC_DIR = src
@@ -12,18 +18,31 @@ TEST_DIR = tests
1218
BUILD_DIR = build
1319
OBJ_DIR = $(BUILD_DIR)/obj
1420
BIN_DIR = $(BUILD_DIR)/bin
21+
SANITIZE_DIR = $(BUILD_DIR)/sanitize
1522

1623
SRCS = $(wildcard $(SRC_DIR)/*.c)
1724
OBJS = $(patsubst $(SRC_DIR)/%.c,$(OBJ_DIR)/%.o,$(SRCS))
1825

26+
# Headers are prerequisites of everything that includes them, so editing one rebuilds
27+
# the objects, examples and tests that depend on it.
28+
PUBLIC_HEADERS = $(wildcard $(INC_DIR)/*.h)
29+
EXAMPLE_HEADERS = $(wildcard $(EXAMPLES_DIR)/*.h)
30+
TEST_HEADERS = $(wildcard $(TEST_DIR)/*.h)
31+
1932
EXAMPLES = $(wildcard $(EXAMPLES_DIR)/*.c)
2033
EXAMPLE_BINS = $(patsubst $(EXAMPLES_DIR)/%.c,$(BIN_DIR)/%,$(EXAMPLES))
2134
TEST_SRCS = $(wildcard $(TEST_DIR)/*.c)
2235
TEST_BIN = $(BIN_DIR)/unit_tests
36+
# The unit tests and the examples are built a second time with the optional TC Segment
37+
# Header compiled in. That build has its own directory, so its coverage data stays apart
38+
# from the default one.
39+
SEGMENT_DIR = $(BUILD_DIR)/segment_header
40+
SEGMENT_TEST_BIN = $(SEGMENT_DIR)/unit_tests
41+
SEGMENT_EXAMPLE_BINS = $(patsubst $(EXAMPLES_DIR)/%.c,$(SEGMENT_DIR)/%,$(EXAMPLES))
2342

2443
LIB = $(BUILD_DIR)/libsdlp.a
2544

26-
.PHONY: all clean examples lib unit-tests test coverage-html
45+
.PHONY: all clean example examples lib unit-tests test coverage-html sanitize
2746

2847
all: lib examples
2948

@@ -32,20 +51,33 @@ lib: $(LIB)
3251
$(LIB): $(OBJS)
3352
ar rcs $@ $^
3453

35-
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
54+
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(PUBLIC_HEADERS) | $(OBJ_DIR)
3655
$(CC) $(CFLAGS) -c $< -o $@
3756

38-
examples: $(EXAMPLE_BINS)
57+
examples: $(EXAMPLE_BINS) $(SEGMENT_EXAMPLE_BINS)
58+
59+
# Build the examples and run the ones linked against the library as `make lib` builds it.
60+
example: examples
61+
@for example in $(EXAMPLE_BINS); do ./$$example || exit 1; done
3962

40-
unit-tests: $(TEST_BIN)
63+
unit-tests: $(TEST_BIN) $(SEGMENT_TEST_BIN)
4164

42-
$(BIN_DIR)/%: $(EXAMPLES_DIR)/%.c $(LIB) | $(BIN_DIR)
65+
$(BIN_DIR)/%: $(EXAMPLES_DIR)/%.c $(EXAMPLE_HEADERS) $(PUBLIC_HEADERS) $(LIB) | $(BIN_DIR)
4366
$(CC) $(CFLAGS) $< $(LIB) -o $@ $(LDFLAGS)
4467

45-
# Compile the sources and tests together with TC_SEGMENT_HEADER_ENABLED so the
46-
# segment-header code paths are built and exercised.
47-
$(TEST_BIN): $(SRCS) $(TEST_SRCS) | $(BIN_DIR)
48-
$(CC) $(CFLAGS) -DTC_SEGMENT_HEADER_ENABLED $(SRCS) $(TEST_SRCS) -o $@ $(LDFLAGS)
68+
# Segment-header configuration: the library is built without it, so its sources are
69+
# compiled together with each example, all with SDLP_TC_SEGMENT_HEADER_ENABLED.
70+
$(SEGMENT_DIR)/%: $(EXAMPLES_DIR)/%.c $(EXAMPLE_HEADERS) $(PUBLIC_HEADERS) $(SRCS) | $(SEGMENT_DIR)
71+
$(CC) $(CFLAGS) -DSDLP_TC_SEGMENT_HEADER_ENABLED $< $(SRCS) -o $@ $(LDFLAGS)
72+
73+
# Default configuration: the tests link the library exactly as `make lib` builds it.
74+
$(TEST_BIN): $(TEST_SRCS) $(TEST_HEADERS) $(PUBLIC_HEADERS) $(LIB) | $(BIN_DIR)
75+
$(CC) $(CFLAGS) $(TEST_SRCS) $(LIB) -o $@ $(LDFLAGS)
76+
77+
# Segment-header configuration: the library is built without it, so the sources are
78+
# compiled together with the tests, all with SDLP_TC_SEGMENT_HEADER_ENABLED.
79+
$(SEGMENT_TEST_BIN): $(SRCS) $(TEST_SRCS) $(TEST_HEADERS) $(PUBLIC_HEADERS) | $(SEGMENT_DIR)
80+
$(CC) $(CFLAGS) -DSDLP_TC_SEGMENT_HEADER_ENABLED $(SRCS) $(TEST_SRCS) -o $@ $(LDFLAGS)
4981

5082
$(BUILD_DIR):
5183
mkdir -p $(BUILD_DIR)
@@ -57,12 +89,48 @@ $(OBJ_DIR): | $(BUILD_DIR)
5789
$(BIN_DIR): | $(BUILD_DIR)
5890
mkdir -p $(BIN_DIR)
5991

92+
$(SEGMENT_DIR): | $(BUILD_DIR)
93+
mkdir -p $(SEGMENT_DIR)
94+
6095
clean:
61-
rm -rf $(BUILD_DIR) obj bin libsdlp.a
96+
rm -rf $(BUILD_DIR)
6297

6398
coverage-html:
6499
bash tools/coverage_html.sh
65100

101+
# Rebuild everything with ASan + UBSan and run the unit tests and the examples.
102+
# Program output is shown only on failure; sanitizer reports go to stderr and are always
103+
# visible. The instrumented build is removed afterwards, on success and on failure.
104+
sanitize:
105+
@$(MAKE) --no-print-directory clean >/dev/null
106+
@$(MAKE) --no-print-directory lib examples unit-tests OPT="$(SANITIZE_OPT)" >/dev/null \
107+
|| { $(MAKE) --no-print-directory clean >/dev/null; exit 1; }
108+
@mkdir -p $(SANITIZE_DIR)
109+
@echo "Sanitizers (ASan + UBSan):"
110+
@./$(TEST_BIN) >$(SANITIZE_DIR)/unit_tests.log \
111+
&& echo " library via unit tests : no errors detected" \
112+
|| { cat $(SANITIZE_DIR)/unit_tests.log; \
113+
echo " library via unit tests : FAILED"; \
114+
$(MAKE) --no-print-directory clean >/dev/null; exit 1; }
115+
@./$(SEGMENT_TEST_BIN) >$(SANITIZE_DIR)/unit_tests_segment_header.log \
116+
&& echo " library via unit tests (segment header) : no errors detected" \
117+
|| { cat $(SANITIZE_DIR)/unit_tests_segment_header.log; \
118+
echo " library via unit tests (segment header) : FAILED"; \
119+
$(MAKE) --no-print-directory clean >/dev/null; exit 1; }
120+
@for example in $(EXAMPLE_BINS) $(SEGMENT_EXAMPLE_BINS); do \
121+
name=$$(basename $$example); \
122+
case $$example in $(SEGMENT_DIR)/*) name="$$name (segment header)";; esac; \
123+
log=$(SANITIZE_DIR)/$$(echo $$example | tr '/' '_').log; \
124+
./$$example >$$log \
125+
&& printf " library via %-27s : no errors detected\n" "$$name" \
126+
|| { cat $$log; printf " library via %-27s : FAILED\n" "$$name"; \
127+
$(MAKE) --no-print-directory clean >/dev/null; exit 1; }; \
128+
done
129+
@$(MAKE) --no-print-directory clean >/dev/null
130+
@echo "Result: PASS"
131+
66132
test: unit-tests
67-
@echo "Running unit tests (TC_SEGMENT_HEADER_ENABLED)..."
133+
@echo "Running unit tests (default configuration)..."
68134
@./$(TEST_BIN)
135+
@echo "Running unit tests (SDLP_TC_SEGMENT_HEADER_ENABLED)..."
136+
@./$(SEGMENT_TEST_BIN)

‎README.md‎

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,22 @@ Minimal, embedded-optimized implementation of **CCSDS Space Data Link Protocol (
1818
- **TM Secondary Header**: Optional Transfer Frame Secondary Header (1–63 data octets) via `sdlp_tm_set_secondary_header`, signaled by the Secondary Header Flag and parsed automatically on decode
1919
- **TM Operational Control Field**: Optional 4-octet OCF carried verbatim via `sdlp_tm_set_ocf` (the caller decides whether to set the OCF Flag); its content, e.g. a CLCW, is mission-specific and left to the application
2020
- **TC Frame Types**: Type-AD/BD/BC frames via `sdlp_tc_set_frame_type`, plus Unlock and Set V(R) control-command helpers (`sdlp_tc_create_unlock_frame`, `sdlp_tc_create_set_vr_frame`)
21-
- **TC Segment Header**: Optional MAP-based segmentation support (enabled with `TC_SEGMENT_HEADER_ENABLED`)
21+
- **TC Segment Header**: Optional MAP-based segmentation support (enabled with `SDLP_TC_SEGMENT_HEADER_ENABLED`)
2222

2323
### Design Principles
2424

2525
- **Minimal footprint**: Small library size (stripped)
2626
- **Zero allocation**: Stack-based, no dynamic memory
27-
- **Embedded-optimized**: Pure C11, no external dependencies
28-
- **Portable**: Standard C11, big-endian network byte order
27+
- **Embedded-optimized**: Pure C99, no external dependencies
28+
- **Portable**: Standard C99, big-endian network byte order
2929

3030
## Project Structure
3131

3232
```
3333
EmbeddedSDLP/
34+
├── .github/
35+
│ └── workflows/
36+
│ └── ci.yml # CI: unit tests, coverage gate, sanitizers
3437
├── include/
3538
│ ├── sdlp_common.h # Common definitions and error codes
3639
│ ├── sdlp_tm.h # TM frame definitions
@@ -50,15 +53,15 @@ EmbeddedSDLP/
5053
│ └── unit_tests.c # Test entry point (aggregates per-module results)
5154
├── tools/
5255
│ └── coverage_html.sh # Coverage (HTML) report generator
53-
├── docs/
54-
│ ├── 132x0b3_TM_SDLP.pdf # CCSDS 132.0-B-3 standard
55-
│ └── 232x0b4e1c1_TC_SDLP.pdf # CCSDS 232.0-B-4 standard
5656
├── Makefile
5757
└── README.md
5858
```
5959

6060
## Building
6161

62+
Warnings are treated as errors (`-Werror`). The build is checked with both `gcc` and
63+
`clang`; select the compiler with `make CC=clang`.
64+
6265
### Build Everything
6366

6467
```bash
@@ -69,6 +72,8 @@ This will create:
6972
- `build/libsdlp.a` - Static library
7073
- `build/bin/tm_example` - TM frame example
7174
- `build/bin/tc_example` - TC frame example
75+
- `build/segment_header/tm_example` and `build/segment_header/tc_example` - the same
76+
examples built with the optional TC Segment Header (`SDLP_TC_SEGMENT_HEADER_ENABLED`)
7277

7378
### Build Library Only
7479

@@ -80,7 +85,8 @@ make lib
8085
### Build Examples
8186

8287
```bash
83-
make examples
88+
make examples # build only
89+
make example # build, then run tm_example and tc_example
8490
```
8591

8692
### Run Tests
@@ -89,6 +95,9 @@ make examples
8995
make test
9096
```
9197

98+
The unit tests are built and run twice: against the library as `make lib` builds it, and
99+
again with the optional TC Segment Header compiled in (`SDLP_TC_SEGMENT_HEADER_ENABLED`).
100+
92101
### Coverage (HTML)
93102

94103
Requires `gcovr` installed in your system:
@@ -103,12 +112,25 @@ Generate coverage report:
103112
make coverage-html
104113
```
105114

115+
The command fails unless line and branch coverage of `src/` are both 100% in each of the
116+
two build configurations (without and with the TC Segment Header). It rebuilds the unit
117+
tests from scratch with the Makefile's own flags plus coverage instrumentation.
118+
106119
Output report:
107120

108121
```text
109122
build/coverage/index.html
110123
```
111124

125+
### Sanitizers (ASan + UBSan)
126+
127+
```bash
128+
make sanitize # rebuild with ASan + UBSan, run tests and examples, then clean up
129+
```
130+
131+
The target starts from a clean build and removes `build/` again when it finishes, so a
132+
coverage report generated earlier is deleted with it.
133+
112134
### Clean
113135

114136
```bash
@@ -122,9 +144,9 @@ Look at the examples/
122144
## Memory Usage (Estimated)
123145

124146
- **Library (stripped)**: < 5 KB
125-
- **Per TM frame buffer**: `TM_PRIMARY_HEADER_SIZE` (6) + optional secondary header (≤ 64) + data + optional OCF (4) + 2 bytes FECF
126-
- **Per TC frame buffer**: `TC_PRIMARY_HEADER_SIZE` (5) + optional segment header (1) + data + 2 bytes FECF
127-
- **Maximum data per frame**: `TM_MAX_DATA_SIZE` = 1024 bytes (TM); `TC_MAX_DATA_SIZE` = 1017 bytes (TC — the whole frame is capped at 1024 octets per CCSDS 232.0-B-4; one less when the TC segment header is enabled)
147+
- **Per TM frame buffer**: `SDLP_TM_PRIMARY_HEADER_SIZE` (6) + optional secondary header (≤ 64) + data + optional OCF (4) + 2 bytes FECF
148+
- **Per TC frame buffer**: `SDLP_TC_PRIMARY_HEADER_SIZE` (5) + optional segment header (1) + data + 2 bytes FECF
149+
- **Maximum data per frame**: `SDLP_TM_MAX_DATA_SIZE` = 1024 bytes (TM); `SDLP_TC_MAX_DATA_SIZE` = 1017 bytes (TC — the whole frame is capped at 1024 octets per CCSDS 232.0-B-4; one less when the TC segment header is enabled)
128150

129151
## Limitations and Extensions
130152

@@ -136,14 +158,17 @@ Current implementation focuses on core protocol features:
136158
- No SDLS (Space Data Link Security) option
137159
- No TM Only-Idle-Data (OID) frame generation or PN randomization
138160
- TM Transfer Frames are variable length; the mission-fixed frame length must be enforced by the caller
139-
- TM frame counts are kept per Master Channel / Virtual Channel in fixed static state (up to `TM_MAX_MASTER_CHANNELS` Master Channels; not thread-safe)
161+
- The 2-octet FECF is always emitted, although both standards make it optional
162+
- The TC Segment Header is a build-time switch for all Virtual Channels, not per Virtual Channel; it changes `sdlp_tc_frame_t`, so build the library and the application with the same setting
163+
- Decoders do not check the Transfer Frame Version Number
164+
- TM frame counts are kept per Master Channel / Virtual Channel in fixed static state (not thread-safe). At most `SDLP_TM_MAX_MASTER_CHANNELS` (default 8) Spacecraft IDs are tracked; `sdlp_tm_create_frame` returns `SDLP_ERROR_NO_RESOURCE` for one more, and `sdlp_tm_reset_frame_counts` empties the table
140165

141166
These can be extended as needed for specific mission requirements.
142167

143168
## References
144169

145-
- CCSDS 132.0-B-3: TM Space Data Link Protocol ([docs/132x0b3_TM_SDLP.pdf](docs/132x0b3_TM_SDLP.pdf))
146-
- CCSDS 232.0-B-4: TC Space Data Link Protocol ([docs/232x0b4e1c1_TC_SDLP.pdf](docs/232x0b4e1c1_TC_SDLP.pdf))
170+
- [CCSDS 132.0-B-3: TM Space Data Link Protocol](https://public.ccsds.org/Pubs/132x0b3.pdf)
171+
- [CCSDS 232.0-B-4: TC Space Data Link Protocol](https://public.ccsds.org/Pubs/232x0b4e1c1.pdf)
147172

148173
## License
149174

‎docs/132x0b3_TM_SDLP.pdf‎

-872 KB
Binary file not shown.

‎docs/232x0b4e1c1_TC_SDLP.pdf‎

-1020 KB
Binary file not shown.

0 commit comments

Comments
 (0)