Skip to content

Commit b594dac

Browse files
authored
Add How-To guide for adding a Custom Framing Protocol (#3635)
* Add How-To Implement a Custom Framing Protocol guide * Nitpicks * Fix link * Clarify and extend docs
1 parent de50149 commit b594dac

1 file changed

Lines changed: 157 additions & 0 deletions

File tree

docs/how-to/custom-framing.md

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
# Implement a Framing Protocol
2+
3+
This How-To Guide provides a step-by-step guide to implementing a custom framing protocol in F Prime Flight Software.
4+
5+
The default [F Prime Protocol](../../Svc/FprimeProtocol/docs/sdd.md) is a lightweight protocol used to get development started quickly with a low-overhead communications protocol that the [F Prime GDS](https://github.com/nasa/fprime-gds) understands. However, as projects mature, there may be a need to implement a framing protocol that fits mission requirements. This document provides an overview of how to implement a custom framing protocol in F Prime Flight Software, and how to integrate it with the F Prime GDS.
6+
7+
## Overview
8+
9+
This guide demonstrates how to implement a custom framing protocol, referred to here as **MyCustomProtocol**. The protocol defines how data is wrapped (framed) for transmission and how frames are validated and unpacked (deframed) on reception.
10+
11+
A reference implementation of a custom framing protocol (the "Decaf Protocol") is available in the `fprime-examples` repository:
12+
- [C++ CustomFraming Example](https://github.com/nasa/fprime-examples/tree/devel/FlightExamples/CustomFraming)
13+
- [GDS Plugin Example](https://github.com/nasa/fprime-examples/tree/devel/GdsExamples/gds-plugins/src/framing)
14+
15+
This guide is divided into two main sections: flight software implementation and GDS integration. Note that if you are aiming to integrate with another GDS and do not wish to use the F´ GDS, you can skip the GDS section.
16+
17+
## Flight Software Implementation
18+
19+
To implement a custom framing protocol in F´, will need to implement the following:
20+
- **Framer**: A component that wraps payload data into frames for transmission.
21+
- **Deframer**: A component that unpacks received frames, extracts the payload data, and validate the frame.
22+
- **FrameDetector** (optional): A helper class that detects the start and end of frames in a stream of data, if your transport is stream-based (e.g., TCP, UART).
23+
24+
The following examples will walk through the implementation of a custom framer and deframer for a hypothetical **MyCustomProtocol** protocol. Implementation details are left to the reader, but examples of such implementations can be found in the [fprime-examples repository](https://github.com/nasa/fprime-examples/tree/devel/FlightExamples/CustomFraming), or within the F´ codebase itself ([Svc.FprimeFramer](../../Svc/FprimeFramer/docs/sdd.md) and [Svc.FprimeDeframer](../../Svc/FprimeDeframer/docs/sdd.md)).
25+
26+
1. **Define the Framer and Deframer FPP Components**
27+
28+
Framer and Deframer components should implement the FPP interfaces by including them.
29+
30+
In `MyCustomFramer.fpp`:
31+
```
32+
passive component MyCustomFramer {
33+
include "path/to/fprime/Svc/Interfaces/FramerInterface.fppi"
34+
[...]
35+
}
36+
```
37+
And in `MyCustomDeframer.fpp`:
38+
```
39+
@ Deframer implementation for MyCustomProtocol
40+
passive component MyCustomDeframer {
41+
include "path/to/fprime/Svc/Interfaces/DeframerInterface.fppi"
42+
[...]
43+
}
44+
```
45+
46+
2. **Implement the Framer C++ Component**
47+
48+
Implement the required handler functions:
49+
```cpp
50+
// ...existing code...
51+
void MyCustomFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) {
52+
// TODO: Implement framing logic
53+
}
54+
55+
void MyCustomFramer ::comStatusIn_handler(FwIndexType portNum, Fw::Success& condition) {
56+
this->comStatusOut_out(portNum, condition); // pass comStatus through (unless project requires otherwise)
57+
}
58+
59+
void MyCustomFramer ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) {
60+
// TODO: handle return of data ownership
61+
// For example, if component required to allocate from a buffer manager, return the buffer to the manager
62+
}
63+
// ...existing code...
64+
```
65+
66+
3. **Implement the Deframer C++ Component**
67+
68+
Similarly, implement the required handler functions:
69+
```cpp
70+
// ...existing code...
71+
void MyCustomDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) {
72+
// TODO: Implement deframing logic
73+
}
74+
75+
void MyCustomDeframer ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) {
76+
// TODO: handle return of data ownership
77+
}
78+
// ...existing code...
79+
```
80+
81+
4. **(Optional) Implement a Frame Detector**
82+
83+
_When is this not needed?_
84+
If your communications manager component always receives complete frames, you do not need to implement frame detection. This can be the case when using radios with built-in frame synchronization or when another subsystem handles frame delimiting.
85+
86+
_When is this needed?_
87+
If your data transport is stream-based (for example, relying on TCP or UART), or if you cannot guarantee that frames will always be received in full, you must implement a mechanism to delimit frames. F Prime provides this capability with the [Svc.FrameAccumulator](../../Svc/FrameAccumulator/docs/sdd.md) component, which uses a circular buffer and a helper `FrameDetector` to identify complete frames in the data stream.
88+
89+
To use the `Svc.FrameAccumulator`, you need to configure it with a FrameDetector that detects when a frame is present:
90+
**MyCustomFrameDetector.hpp**
91+
```cpp
92+
#include <Svc/FrameDetector/FrameDetector.hpp>
93+
94+
class MyCustomFrameDetector : public Svc::FrameDetector {
95+
public:
96+
Svc::FrameDetector::Status detect(const Types::CircularBuffer& data, FwSizeType& size_out) const override;
97+
};
98+
```
99+
100+
**MyCustomFrameDetector.cpp**
101+
```cpp
102+
// ...existing code...
103+
Svc::FrameDetector::Status MyCustomFrameDetector::detect(const Types::CircularBuffer& data, FwSizeType& size_out) const {
104+
// TODO: Implement frame boundary detection
105+
// Refer to the Svc.FrameDetector documentation for details on how to implement this
106+
return Svc::FrameDetector::NO_FRAME_DETECTED;
107+
}
108+
// ...existing code...
109+
```
110+
111+
Then configure the `Svc.FrameAccumulator` component to use your custom frame detector in your Topology CPP:
112+
**Top/Topology.cpp**
113+
```cpp
114+
#include <path/to/MyCustomFrameDetector.hpp>
115+
// ...existing code...
116+
MyCustomFrameDetector frameDetector;
117+
// ...existing code...
118+
frameAccumulator.configure(frameDetector, 1, mallocator, 2048);
119+
```
120+
121+
122+
## F´ GDS Implementation
123+
124+
To support your custom protocol in the F´ GDS, implement a GDS framing plugin. The GDS plugin system allows you to customize GDS behavior with user-provided code. For new framing protocols, you will need to implement a plugin that extends the `FramerDeframer`. This is further documented in the [How-To Develop a GDS Plugin Guide](./develop-gds-plugins.md) and [F Prime GDS Framing Plugin reference](../reference/gds-plugins/framing.md).
125+
126+
For example, in Python:
127+
128+
```python
129+
from fprime_gds.common.communication.framing import FramerDeframer
130+
from fprime_gds.plugin.definitions import gds_plugin
131+
132+
@gds_plugin(FramerDeframer)
133+
class MyCustomFramerDeframer(FramerDeframer):
134+
"""GDS plugin for MyCustomProtocol framing"""
135+
def frame(self, data):
136+
# TODO: Implement framing logic
137+
return frame
138+
139+
def deframe(self, data, no_copy=False):
140+
# TODO: Implement deframing logic
141+
return packet, leftover_data, discarded_data
142+
```
143+
144+
Make sure to [package and install the plugin in your virtual environment](./develop-gds-plugins.md#packaging-and-testing-plugins) for the GDS to be able to load it, then run it:
145+
146+
```
147+
fprime-gds --framing-selection MyCustomFramerDeframer
148+
```
149+
150+
## References
151+
152+
- [C++ CustomFraming Example](https://github.com/nasa/fprime-examples/tree/devel/FlightExamples/CustomFraming)
153+
- [GDS Plugin Example](https://github.com/nasa/fprime-examples/tree/devel/GdsExamples/gds-plugins/src/framing)
154+
- [F Prime GDS Framing Plugin](../reference/gds-plugins/framing.md)
155+
- [F Prime Communication Adapter Interface](../reference/communication-adapter-interface.md)
156+
- [F Prime GDS Plugin Development](https://fprime.jpl.nasa.gov/devel/docs/how-to/develop-gds-plugins/)
157+

0 commit comments

Comments
 (0)