Generic TMTC bridge #39

Closed
opened 2020-04-18 13:01:25 +02:00 by muellerr · 5 comments
Owner

The TMTC bridge components for serial and ehternet communication have
a lot of common functions, which use the same FSFW functionalities. I wrote a common base class, which perforsm these common tasks and I think it would be a nice feature for the FSFW, for example inside the tmtcservices folder. The generic bridge is already used in the development process of SOURCE for both ethernet and UART communication.

Notes on how to use this enhancement:
The generic bridge is used by implementing the abstract functions of the bridge.

Label: Enhancement

The TMTC bridge components for serial and ehternet communication have a lot of common functions, which use the same FSFW functionalities. I wrote a common base class, which perforsm these common tasks and I think it would be a nice feature for the FSFW, for example inside the tmtcservices folder. The generic bridge is already used in the development process of SOURCE for both ethernet and UART communication. Notes on how to use this enhancement: The generic bridge is used by implementing the abstract functions of the bridge. Label: Enhancement
mohr added the
feature
label 2020-04-20 14:31:22 +02:00
Author
Owner

I think it would be a nice feature if a delay between sent packets (TM) and the number of TM packets sent per cycle could be specified (with approriate default values of course).
Right now, I have the issue that I have a timeout based serial reception and I tend to lose packets if theyre coming in really fast (even though frame handling is implemented, this is propably because the packets are still sent with consecutive driver calls instead of a packed frame with one call).
However, I have not found a way to call the osal wrapper function PeriodicTaskIF::sleepFor() because this method is not static.
UPDATE: The function is called delayTask and is included in TaskFactory, i just did not find it.

Alternatively, a delay can just be implemented in the child implementation of sendTm().

Right now, the default handleTc() function also assumes that only one packet is received from receiveTc(). Maybe there is a better or more generic approach to this.

I think it would be a nice feature if a delay between sent packets (TM) and the number of TM packets sent per cycle could be specified (with approriate default values of course). Right now, I have the issue that I have a timeout based serial reception and I tend to lose packets if theyre coming in really fast (even though frame handling is implemented, this is propably because the packets are still sent with consecutive driver calls instead of a packed frame with one call). However, I have not found a way to call the osal wrapper function `PeriodicTaskIF::sleepFor()` because this method is not static. UPDATE: The function is called delayTask and is included in TaskFactory, i just did not find it. Alternatively, a delay can just be implemented in the child implementation of sendTm(). Right now, the default handleTc() function also assumes that only one packet is received from receiveTc(). Maybe there is a better or more generic approach to this.
Owner

The better solution is to not use a timeout based reception in place of a framing layer (seriously, don't do that).

One way is to assume no data loss. Then, the SpacePackets (which I assume are used as TC and TM packets) can be parsed and used instead of a framing layer. Space packets contain a mandatory length field which allows, under the aforementioned assumption of no data loss, to recover packets from a datastream (FLP's ground segment uses this approach quite successful). Recovering from errors or data loss is suboptimal in this case.

Finding a general solution is not simple, as some lower transmission mechanics will support framing (UDP would be one example). Introducing a mandatory framing layer in the generic solution might introduce quite some unwanted overhead for some transmission layers.

I would suggest putting framing into the child implementation, not the generic base class, and assume in the base class that the child implementation will take care of it as it is the case right now.

The better solution is to not use a timeout based reception in place of a framing layer (seriously, don't do that). One way is to assume no data loss. Then, the SpacePackets (which I assume are used as TC and TM packets) can be parsed and used instead of a framing layer. Space packets contain a mandatory length field which allows, under the aforementioned assumption of no data loss, to recover packets from a datastream (FLP's ground segment uses this approach quite successful). Recovering from errors or data loss is suboptimal in this case. Finding a general solution is not simple, as some lower transmission mechanics will support framing (UDP would be one example). Introducing a mandatory framing layer in the generic solution might introduce quite some unwanted overhead for some transmission layers. I would suggest putting framing into the child implementation, not the generic base class, and assume in the base class that the child implementation will take care of it as it is the case right now.
Author
Owner

Okay, I am having a look at the framing solution right now to replace the timeout based solution (I am in fact losing packets..)

What exactly does data stream mean? Reading byte-for-byte?

Okay, but the last point sounds good. Another option would be to make a default framing solution that is still optional (setting in the ctor, default would be false) and the general base class would pack all packets in a frame and call the sendTm function with the frame instead of a single packet as provided arguments (as long as a given frame size is not exceeded, otherwise the FIFO would be used to send on next transmission).

Okay, I am having a look at the framing solution right now to replace the timeout based solution (I am in fact losing packets..) What exactly does data stream mean? Reading byte-for-byte? Okay, but the last point sounds good. Another option would be to make a default framing solution that is still optional (setting in the ctor, default would be false) and the general base class would pack all packets in a frame and call the sendTm function with the frame instead of a single packet as provided arguments (as long as a given frame size is not exceeded, otherwise the FIFO would be used to send on next transmission).
Owner

Yes, a datastream means getting byte after byte, instead of getting a complete datagram/packet/frame.

I think I can support an optional framing in the generic solution as many common transports (UART, TCP) might not support framing. Then, we could implement a generic decoder as well that can be reused (if you have not already done so).

I would suggest you look into DLE encoding as implemented in the fsfw , I use it alot, usually together with a ccitt crc16. For example encoding and decoding data transmitted between a PC and an Arduino.

It is also used on FLP for the communication between OBC and PLOC.

There is no definite standard for this (at least I do not know one), but I guess you can get it from the code. It basically means using 0x02 as frame start, 0x03 as frame end and escaping 0x02, 0x03, 0x0D and 0x10 within the frame by replacing it with 0x1042, 0x1043, 0x104D and 0x1010. With this you are able to identify frames within a datastream by looking for 0x02 and 0x03. Adding a checksum helps in filtering out random garbage.

Yes, a datastream means getting byte after byte, instead of getting a complete datagram/packet/frame. I think I can support an optional framing in the generic solution as many common transports (UART, TCP) might not support framing. Then, we could implement a generic decoder as well that can be reused (if you have not already done so). I would suggest you look into DLE encoding as implemented in the [fsfw ](https://egit.irs.uni-stuttgart.de/fsfw/fsfw/src/branch/master/globalfunctions/DleEncoder.h), I use it alot, usually together with a ccitt [crc16](https://egit.irs.uni-stuttgart.de/fsfw/fsfw/src/branch/master/globalfunctions/CRC.h#L8). For example [encoding](https://egit.irs.uni-stuttgart.de/mohr/fsfw_example/src/commit/59e49b5560f7eeae4fbf82378cd63876f3762510/mission/Arduino/ArduinoCommInterface.cpp#L141) and [decoding](https://egit.irs.uni-stuttgart.de/mohr/fsfw_example/src/commit/59e49b5560f7eeae4fbf82378cd63876f3762510/mission/Arduino/ArduinoCommInterface.cpp#L254) data transmitted between a PC and an [Arduino](https://egit.irs.uni-stuttgart.de/mohr/ArduinoIO). It is also used on FLP for the communication between OBC and PLOC. There is no definite standard for this (at least I do not know one), but I guess you can get it from the code. It basically means using 0x02 as frame start, 0x03 as frame end and escaping 0x02, 0x03, 0x0D and 0x10 within the frame by replacing it with 0x1042, 0x1043, 0x104D and 0x1010. With this you are able to identify frames within a datastream by looking for 0x02 and 0x03. Adding a checksum helps in filtering out random garbage.
Author
Owner

Sounds good. I will have a look at it.

Currently I am a simple serial framing solution in the child class first,
everything is better than timeout based solutions (which don't work, I'm loosing packets sometimes). It simply takes all messages in a cycle and packs them in a fixed size frame.

But datastream is an option too.

Sounds good. I will have a look at it. Currently I am a simple serial framing solution in the child class first, everything is better than timeout based solutions (which don't work, I'm loosing packets sometimes). It simply takes all messages in a cycle and packs them in a fixed size frame. But datastream is an option too.
Sign in to join this conversation.
No Milestone
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: fsfw/fsfw#39
No description provided.