From 7311cbceadbeb1185cd43d3ee01babd3a99f1b6c Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 30 Apr 2025 12:14:39 -0700 Subject: [PATCH 01/95] First pass at Svc + TcpClient implementation --- Drv/Interfaces/ByteStreamDriverInterface.fppi | 5 ++- Drv/TcpClient/TcpClient.fpp | 3 ++ Drv/TcpClient/TcpClientComponentImpl.cpp | 4 ++ Drv/TcpClient/TcpClientComponentImpl.hpp | 8 ++++ Ref/Top/topology.fpp | 40 ++++++++++--------- Svc/ComStub/ComStub.cpp | 4 ++ Svc/ComStub/ComStub.fpp | 3 ++ Svc/ComStub/ComStub.hpp | 7 ++++ Svc/FileUplink/FileUplink.cpp | 8 ++-- Svc/FileUplink/FileUplink.fpp | 4 +- Svc/FileUplink/FileUplink.hpp | 3 +- Svc/FprimeDeframer/FprimeDeframer.cpp | 13 ++++-- Svc/FprimeDeframer/FprimeDeframer.fpp | 7 +++- Svc/FprimeDeframer/FprimeDeframer.hpp | 9 +++++ Svc/FprimeRouter/FprimeRouter.cpp | 9 ++++- Svc/FprimeRouter/FprimeRouter.fpp | 3 -- Svc/FprimeRouter/FprimeRouter.hpp | 9 +++++ Svc/FrameAccumulator/FrameAccumulator.cpp | 12 ++++-- Svc/FrameAccumulator/FrameAccumulator.fpp | 3 +- Svc/FrameAccumulator/FrameAccumulator.hpp | 8 ++++ Svc/Interfaces/ComInterface.fppi | 9 ++++- Svc/Interfaces/FrameAccumulatorInterface.fppi | 6 +++ Svc/Interfaces/RouterInterface.fppi | 8 +++- 23 files changed, 140 insertions(+), 45 deletions(-) diff --git a/Drv/Interfaces/ByteStreamDriverInterface.fppi b/Drv/Interfaces/ByteStreamDriverInterface.fppi index e2a22f149bb..7fa4f3e4487 100644 --- a/Drv/Interfaces/ByteStreamDriverInterface.fppi +++ b/Drv/Interfaces/ByteStreamDriverInterface.fppi @@ -7,5 +7,8 @@ @ Invoke this port to send data out the driver guarded input port $send: Fw.BufferSend - @ Port invoked to return ownership of sent data back to the sender + @ Port returning ownership of data received on $send port output port dataReturnOut: Drv.ByteStreamData + + @ Port receiving back ownership of data sent out on $recv port + sync input port bufferReturnIn: Fw.BufferSend diff --git a/Drv/TcpClient/TcpClient.fpp b/Drv/TcpClient/TcpClient.fpp index e9ad3152e0c..38537ee4c0c 100644 --- a/Drv/TcpClient/TcpClient.fpp +++ b/Drv/TcpClient/TcpClient.fpp @@ -6,5 +6,8 @@ module Drv { @ Allocation for received data output port allocate: Fw.BufferGet + @ Deallocation of allocated buffers + output port deallocate: Fw.BufferSend + } } diff --git a/Drv/TcpClient/TcpClientComponentImpl.cpp b/Drv/TcpClient/TcpClientComponentImpl.cpp index 1d74886bb0b..b1c14e74fe5 100644 --- a/Drv/TcpClient/TcpClientComponentImpl.cpp +++ b/Drv/TcpClient/TcpClientComponentImpl.cpp @@ -94,4 +94,8 @@ void TcpClientComponentImpl::send_handler(const FwIndexType portNum, Fw::Buffer& this->dataReturnOut_out(0, fwBuffer, returnStatus); } +void TcpClientComponentImpl::bufferReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) { + this->deallocate_out(0, fwBuffer); +} + } // end namespace Drv diff --git a/Drv/TcpClient/TcpClientComponentImpl.hpp b/Drv/TcpClient/TcpClientComponentImpl.hpp index becf5968d20..26df15461f9 100644 --- a/Drv/TcpClient/TcpClientComponentImpl.hpp +++ b/Drv/TcpClient/TcpClientComponentImpl.hpp @@ -126,6 +126,14 @@ class TcpClientComponentImpl final : public TcpClientComponentBase, public Socke */ void send_handler(const FwIndexType portNum, Fw::Buffer& fwBuffer) override; + //! Handler implementation for bufferReturnIn + //! + //! Port receiving back ownership of data sent out on $recv port + void bufferReturnIn_handler(FwIndexType portNum, //!< The port number + Fw::Buffer& fwBuffer //!< The buffer + ) override; + + Drv::TcpClientSocket m_socket; //!< Socket implementation // Member variable to store the buffer size diff --git a/Ref/Top/topology.fpp b/Ref/Top/topology.fpp index 36eff8549ce..7202d56e3e4 100644 --- a/Ref/Top/topology.fpp +++ b/Ref/Top/topology.fpp @@ -163,25 +163,29 @@ module Ref { } connections Uplink { - - comDriver.allocate -> commsBufferManager.bufferGetCallee - comDriver.$recv -> comStub.drvDataIn - comStub.comDataOut -> frameAccumulator.dataIn - - frameAccumulator.frameOut -> deframer.framedIn - frameAccumulator.bufferAllocate -> commsBufferManager.bufferGetCallee + # ComDriver buffer allocations + comDriver.allocate -> commsBufferManager.bufferGetCallee + comDriver.deallocate -> commsBufferManager.bufferSendIn + # ComDriver <-> ComStub + comDriver.$recv -> comStub.drvDataIn + comStub.bufferReturnOut -> comDriver.bufferReturnIn + # ComStub <-> FrameAccumulator + comStub.comDataOut -> frameAccumulator.dataIn # Update needed: ComInterface needs to emit ComDataWithContext ? + frameAccumulator.bufferReturnOut -> comStub.bufferReturnIn + # FrameAccumulator buffer allocations frameAccumulator.bufferDeallocate -> commsBufferManager.bufferSendIn - deframer.bufferDeallocate -> commsBufferManager.bufferSendIn - deframer.deframedOut -> fprimeRouter.dataIn - - fprimeRouter.commandOut -> cmdDisp.seqCmdBuff - fprimeRouter.fileOut -> fileUplink.bufferSendIn - fprimeRouter.bufferDeallocate -> commsBufferManager.bufferSendIn - - cmdDisp.seqCmdStatus -> fprimeRouter.cmdResponseIn - - fileUplink.bufferSendOut -> commsBufferManager.bufferSendIn - + frameAccumulator.bufferAllocate -> commsBufferManager.bufferGetCallee + # FrameAccumulator <-> Deframer + frameAccumulator.frameOut -> deframer.framedIn + deframer.dataReturnOut -> frameAccumulator.dataReturnIn + # Deframer <-> Router + deframer.deframedOut -> fprimeRouter.dataIn + fprimeRouter.dataReturnOut -> deframer.dataReturnIn + # Router <-> CmdDispatcher/FileUplink + fprimeRouter.commandOut -> cmdDisp.seqCmdBuff + cmdDisp.seqCmdStatus -> fprimeRouter.cmdResponseIn + fprimeRouter.fileOut -> fileUplink.bufferSendIn + fileUplink.bufferSendOut -> fprimeRouter.fileBufferReturnIn } connections DataProducts { diff --git a/Svc/ComStub/ComStub.cpp b/Svc/ComStub/ComStub.cpp index d05b919008e..be86a50fc6d 100644 --- a/Svc/ComStub/ComStub.cpp +++ b/Svc/ComStub/ComStub.cpp @@ -70,4 +70,8 @@ void ComStub ::dataReturnIn_handler(FwIndexType portNum, //!< The port number } } +void ComStub ::bufferReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) { + this->bufferReturnOut_out(0, fwBuffer); +} + } // end namespace Svc diff --git a/Svc/ComStub/ComStub.fpp b/Svc/ComStub/ComStub.fpp index 57d5eab852e..9fe20dbd544 100644 --- a/Svc/ComStub/ComStub.fpp +++ b/Svc/ComStub/ComStub.fpp @@ -19,5 +19,8 @@ module Svc { @ Callback from drvDataOut (retrieving status and ownership of sent buffer) sync input port dataReturnIn: Drv.ByteStreamData + @ Returning ownership of buffer that came in on drvDataIn + output port bufferReturnOut: Fw.BufferSend + } } diff --git a/Svc/ComStub/ComStub.hpp b/Svc/ComStub/ComStub.hpp index 7db4ba0c5da..421f70f42d8 100644 --- a/Svc/ComStub/ComStub.hpp +++ b/Svc/ComStub/ComStub.hpp @@ -55,6 +55,13 @@ class ComStub final : public ComStubComponentBase { /*!< The port number*/ Fw::Buffer& recvBuffer, const Drv::ByteStreamStatus& recvStatus) override; + //! Handler implementation for bufferReturnIn + //! + //! Port receiving back ownership of buffer sent out on comDataOut + void bufferReturnIn_handler(FwIndexType portNum, //!< The port number + Fw::Buffer& fwBuffer //!< The buffer + ) override; + //! Handler implementation for dataReturnIn //! //! Buffer ownership and status returning from a Driver "send" operation diff --git a/Svc/FileUplink/FileUplink.cpp b/Svc/FileUplink/FileUplink.cpp index 1e7f051d6ba..e66a7381b8c 100644 --- a/Svc/FileUplink/FileUplink.cpp +++ b/Svc/FileUplink/FileUplink.cpp @@ -36,11 +36,11 @@ FileUplink ::~FileUplink() {} // Handler implementations for user-defined typed input ports // ---------------------------------------------------------------------- -void FileUplink ::bufferSendIn_handler(const FwIndexType portNum, Fw::Buffer& buffer) { +void FileUplink ::bufferSendIn_handler(const FwIndexType portNum, Fw::Buffer& buffer, const ComCfg::FrameContext& context) { // If packet is too small to contain a packet type, log + deallocate and return if (buffer.getSize() < sizeof(FwPacketDescriptorType)) { this->log_WARNING_HI_InvalidPacketReceived(Fw::ComPacket::FW_PACKET_UNKNOWN); - this->bufferSendOut_out(0, buffer); + this->bufferSendOut_out(0, buffer, context); return; } @@ -52,7 +52,7 @@ void FileUplink ::bufferSendIn_handler(const FwIndexType portNum, Fw::Buffer& bu // If packet type is not a file packet, log + deallocate and return if (packetType != Fw::ComPacket::FW_PACKET_FILE) { this->log_WARNING_HI_InvalidPacketReceived(packetType); - this->bufferSendOut_out(0, buffer); + this->bufferSendOut_out(0, buffer, context); return; } @@ -83,7 +83,7 @@ void FileUplink ::bufferSendIn_handler(const FwIndexType portNum, Fw::Buffer& bu break; } } - this->bufferSendOut_out(0, buffer); + this->bufferSendOut_out(0, buffer, context); } void FileUplink ::pingIn_handler(const FwIndexType portNum, U32 key) { diff --git a/Svc/FileUplink/FileUplink.fpp b/Svc/FileUplink/FileUplink.fpp index bcafa6afde2..8267c61c71f 100644 --- a/Svc/FileUplink/FileUplink.fpp +++ b/Svc/FileUplink/FileUplink.fpp @@ -8,10 +8,10 @@ module Svc { # ---------------------------------------------------------------------- @ Buffer send in - async input port bufferSendIn: Fw.BufferSend + async input port bufferSendIn: Svc.ComDataWithContext @ Buffer send out - output port bufferSendOut: Fw.BufferSend + output port bufferSendOut: Svc.ComDataWithContext @ Ping in async input port pingIn: Svc.Ping diff --git a/Svc/FileUplink/FileUplink.hpp b/Svc/FileUplink/FileUplink.hpp index 3bc5faa161d..ae17f6454b1 100644 --- a/Svc/FileUplink/FileUplink.hpp +++ b/Svc/FileUplink/FileUplink.hpp @@ -219,7 +219,8 @@ namespace Svc { //! void bufferSendIn_handler( const FwIndexType portNum, //!< The port number - Fw::Buffer& buffer //!< Buffer wrapping data + Fw::Buffer& buffer, //!< Buffer wrapping data + const ComCfg::FrameContext& context ); //! Handler implementation for pingIn diff --git a/Svc/FprimeDeframer/FprimeDeframer.cpp b/Svc/FprimeDeframer/FprimeDeframer.cpp index 0622e9c0d33..0fa2227e54e 100644 --- a/Svc/FprimeDeframer/FprimeDeframer.cpp +++ b/Svc/FprimeDeframer/FprimeDeframer.cpp @@ -29,7 +29,7 @@ void FprimeDeframer ::framedIn_handler(FwIndexType portNum, Fw::Buffer& data, co if (data.getSize() < FprimeProtocol::FrameHeader::SERIALIZED_SIZE + FprimeProtocol::FrameTrailer::SERIALIZED_SIZE) { // Incoming buffer is not long enough to contain a valid frame (header+trailer) this->log_WARNING_HI_InvalidBufferReceived(); - this->bufferDeallocate_out(0, data); // drop the frame + this->dataReturnOut_out(0, data, context); // drop the frame return; } @@ -46,7 +46,7 @@ void FprimeDeframer ::framedIn_handler(FwIndexType portNum, Fw::Buffer& data, co const FprimeProtocol::FrameHeader defaultValue; if (header.getstartWord() != defaultValue.getstartWord()) { this->log_WARNING_HI_InvalidStartWord(); - this->bufferDeallocate_out(0, data); + this->dataReturnOut_out(0, data, context); // drop the frame return; } // We expect the frame size to be size of header + body (of size specified in header) + trailer @@ -54,7 +54,7 @@ void FprimeDeframer ::framedIn_handler(FwIndexType portNum, Fw::Buffer& data, co FprimeProtocol::FrameTrailer::SERIALIZED_SIZE; if (data.getSize() < expectedFrameSize) { this->log_WARNING_HI_InvalidLengthReceived(); - this->bufferDeallocate_out(0, data); + this->dataReturnOut_out(0, data, context); // drop the frame return; } @@ -77,7 +77,7 @@ void FprimeDeframer ::framedIn_handler(FwIndexType portNum, Fw::Buffer& data, co // Check that the CRC in the trailer of the frame matches the computed CRC if (trailer.getcrcField() != computedCrc.asBigEndianU32()) { this->log_WARNING_HI_InvalidChecksum(); - this->bufferDeallocate_out(0, data); + this->dataReturnOut_out(0, data, context); // drop the frame return; } @@ -91,4 +91,9 @@ void FprimeDeframer ::framedIn_handler(FwIndexType portNum, Fw::Buffer& data, co this->deframedOut_out(0, data, context); } +void FprimeDeframer ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer, const ComCfg::FrameContext& context) { + this->dataReturnOut_out(0, fwBuffer, context); +} + + } // namespace Svc diff --git a/Svc/FprimeDeframer/FprimeDeframer.fpp b/Svc/FprimeDeframer/FprimeDeframer.fpp index ad8d1b9f005..1762afa8d11 100644 --- a/Svc/FprimeDeframer/FprimeDeframer.fpp +++ b/Svc/FprimeDeframer/FprimeDeframer.fpp @@ -10,8 +10,11 @@ module Svc { include "../Interfaces/DeframerInterface.fppi" - @ Port for deallocating dropped frames - output port bufferDeallocate: Fw.BufferSend + @ Port for returning ownership of received frame buffers + output port dataReturnOut: Svc.ComDataWithContext + + @ Port receiving back ownership of sent frame buffers + sync input port dataReturnIn: Svc.ComDataWithContext @ An invalid frame was received (too short to be a frame) event InvalidBufferReceived \ diff --git a/Svc/FprimeDeframer/FprimeDeframer.hpp b/Svc/FprimeDeframer/FprimeDeframer.hpp index f6313777c79..fb2b1394be4 100644 --- a/Svc/FprimeDeframer/FprimeDeframer.hpp +++ b/Svc/FprimeDeframer/FprimeDeframer.hpp @@ -39,6 +39,15 @@ class FprimeDeframer final : public FprimeDeframerComponentBase { void framedIn_handler(FwIndexType portNum, //!< The port number Fw::Buffer& data, const ComCfg::FrameContext& context) override; + + //! Handler implementation for dataReturnIn + //! + //! Port receiving back ownership of sent frame buffers + void dataReturnIn_handler(FwIndexType portNum, //!< The port number + Fw::Buffer& data, //!< The buffer + const ComCfg::FrameContext& context) override; + + }; } // namespace Svc diff --git a/Svc/FprimeRouter/FprimeRouter.cpp b/Svc/FprimeRouter/FprimeRouter.cpp index 660c1b8e3cc..6120b5a3dd1 100644 --- a/Svc/FprimeRouter/FprimeRouter.cpp +++ b/Svc/FprimeRouter/FprimeRouter.cpp @@ -61,7 +61,7 @@ void FprimeRouter ::dataIn_handler(FwIndexType portNum, Fw::Buffer& packetBuffer // send the file packet. Otherwise take no action. if (this->isConnected_fileOut_OutputPort(0)) { // Send the packet buffer - this->fileOut_out(0, packetBuffer); + this->fileOut_out(0, packetBuffer, context); // Transfer ownership of the packetBuffer to the receiver deallocate = false; } @@ -83,7 +83,7 @@ void FprimeRouter ::dataIn_handler(FwIndexType portNum, Fw::Buffer& packetBuffer if (deallocate) { // Deallocate the packet buffer - this->bufferDeallocate_out(0, packetBuffer); + this->dataReturnOut_out(0, packetBuffer, context); } } @@ -93,4 +93,9 @@ void FprimeRouter ::cmdResponseIn_handler(FwIndexType portNum, const Fw::CmdResponse& response) { // Nothing to do } + +void FprimeRouter ::fileBufferReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer, const ComCfg::FrameContext& context) { + this->dataReturnOut_out(0, fwBuffer, context); +} + } // namespace Svc diff --git a/Svc/FprimeRouter/FprimeRouter.fpp b/Svc/FprimeRouter/FprimeRouter.fpp index baff261a9d1..7bfa9edb56f 100644 --- a/Svc/FprimeRouter/FprimeRouter.fpp +++ b/Svc/FprimeRouter/FprimeRouter.fpp @@ -10,9 +10,6 @@ module Svc { @ Port for forwarding non-recognized packet types output port unknownDataOut: Svc.ComDataWithContext - @ Port for deallocating buffers - output port bufferDeallocate: Fw.BufferSend - @ An error occurred while serializing a com buffer event SerializationError( status: U32 @< The status of the operation diff --git a/Svc/FprimeRouter/FprimeRouter.hpp b/Svc/FprimeRouter/FprimeRouter.hpp index cb3bed691af..70a0f632ed2 100644 --- a/Svc/FprimeRouter/FprimeRouter.hpp +++ b/Svc/FprimeRouter/FprimeRouter.hpp @@ -44,6 +44,15 @@ class FprimeRouter final : public FprimeRouterComponentBase { U32 cmdSeq, //!< The command sequence number const Fw::CmdResponse& response //!< The command response ) override; + + //! Handler implementation for fileBufferReturnIn + //! + //! Port for receiving ownership back of buffers sent on fileOut + void fileBufferReturnIn_handler(FwIndexType portNum, //!< The port number + Fw::Buffer& fwBuffer, //!< The buffer + const ComCfg::FrameContext& context + ) override; + }; } // namespace Svc diff --git a/Svc/FrameAccumulator/FrameAccumulator.cpp b/Svc/FrameAccumulator/FrameAccumulator.cpp index 7243b51ebb5..0bd6395a699 100644 --- a/Svc/FrameAccumulator/FrameAccumulator.cpp +++ b/Svc/FrameAccumulator/FrameAccumulator.cpp @@ -55,9 +55,8 @@ void FrameAccumulator ::dataIn_handler(FwIndexType portNum, Fw::Buffer& buffer) if (buffer.isValid()) { this->processBuffer(buffer); } - // TODO: rework the uplink deallocation logic to use the bufferReturn chaining pattern - // Deallocate the buffer - this->bufferDeallocate_out(0, buffer); + // Return ownership of the incoming buffer (FrameAccumulator allocates its own buffers to hold frames) + this->bufferReturnOut_out(0, buffer); } void FrameAccumulator ::processBuffer(Fw::Buffer& buffer) { @@ -163,4 +162,11 @@ void FrameAccumulator ::processRing() { } } } + +void FrameAccumulator ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer, const ComCfg::FrameContext& context) { + // Frame buffer ownership is returned to the component. Component had allocated with a buffer manager, + // so we return it to the buffer manager for deallocation + this->bufferDeallocate_out(0, fwBuffer); +} + } // namespace Svc diff --git a/Svc/FrameAccumulator/FrameAccumulator.fpp b/Svc/FrameAccumulator/FrameAccumulator.fpp index 8a4b76cbc36..10fe2251e13 100644 --- a/Svc/FrameAccumulator/FrameAccumulator.fpp +++ b/Svc/FrameAccumulator/FrameAccumulator.fpp @@ -7,8 +7,7 @@ module Svc { # ---------------------------------------------------------------------- include "../Interfaces/FrameAccumulatorInterface.fppi" - - @ Port for deallocating buffers received on dataIn. + @ Port for deallocating buffers holding extracted frames output port bufferDeallocate: Fw.BufferSend @ Port for allocating buffer to hold extracted frame diff --git a/Svc/FrameAccumulator/FrameAccumulator.hpp b/Svc/FrameAccumulator/FrameAccumulator.hpp index 9635ec4a42e..099b6eae4a6 100644 --- a/Svc/FrameAccumulator/FrameAccumulator.hpp +++ b/Svc/FrameAccumulator/FrameAccumulator.hpp @@ -52,6 +52,14 @@ class FrameAccumulator final : public FrameAccumulatorComponentBase { void dataIn_handler(FwIndexType portNum, //!< The port number Fw::Buffer& recvBuffer) override; + //! Handler implementation for bufferReturnIn + //! + //! Port receiving ownership back of buffers sent on frameOut + void dataReturnIn_handler(FwIndexType portNum, //!< The port number + Fw::Buffer& fwBuffer, //!< The buffer + const ComCfg::FrameContext& context //!< The context object + ) override; + PRIVATE: //! \brief process raw buffer //! \return raw data buffer diff --git a/Svc/Interfaces/ComInterface.fppi b/Svc/Interfaces/ComInterface.fppi index 7d34b8412bc..4d6542ca7f9 100644 --- a/Svc/Interfaces/ComInterface.fppi +++ b/Svc/Interfaces/ComInterface.fppi @@ -6,7 +6,9 @@ sync input port comDataIn: Svc.ComDataWithContext @ Data received from the wire (coming out of the component) -output port comDataOut: Fw.BufferSend +output port comDataOut: Fw.BufferSend +# TODO: problem here: if there's a radio component and no FrameAccumulator needed, +# We likely need comDataOut to be Svc.ComDataWithContext so it can be fed directly into a Deframer ? @ Status of the last transmission output port comStatusOut: Fw.SuccessCondition @@ -15,5 +17,8 @@ output port comStatusOut: Fw.SuccessCondition # Memory management # ---------------------------------------------------------------------- -@ Returning ownership of data that came in on comDataIn +@ Port returning ownership of data that came in on comDataIn output port dataReturnOut: Svc.ComDataWithContext + +@ Port receiving back ownership of buffer sent out on comDataOut +sync input port bufferReturnIn: Fw.BufferSend diff --git a/Svc/Interfaces/FrameAccumulatorInterface.fppi b/Svc/Interfaces/FrameAccumulatorInterface.fppi index 72f1635e085..9a1979d1d72 100644 --- a/Svc/Interfaces/FrameAccumulatorInterface.fppi +++ b/Svc/Interfaces/FrameAccumulatorInterface.fppi @@ -3,3 +3,9 @@ guarded input port dataIn: Fw.BufferSend @ Port for sending an extracted frame out output port frameOut: Svc.ComDataWithContext + +@ Port for returning ownership of buffers received on dataIn +output port bufferReturnOut: Fw.BufferSend + +@ Port receiving back ownership of buffers sent on frameOut +sync input port dataReturnIn: Svc.ComDataWithContext diff --git a/Svc/Interfaces/RouterInterface.fppi b/Svc/Interfaces/RouterInterface.fppi index dafb91b0bbb..14455a223e4 100644 --- a/Svc/Interfaces/RouterInterface.fppi +++ b/Svc/Interfaces/RouterInterface.fppi @@ -2,10 +2,16 @@ sync input port dataIn: Svc.ComDataWithContext @ Port for sending file packets as Fw::Buffer (ownership passed to receiver) -output port fileOut: Fw.BufferSend +output port fileOut: Svc.ComDataWithContext @ Port for sending command packets as Fw::ComBuffers output port commandOut: Fw.Com @ Port for receiving command responses from a command dispatcher (can be a no-op) sync input port cmdResponseIn: Fw.CmdResponse + +@ Port for receiving ownership back of buffers sent on fileOut +sync input port fileBufferReturnIn: Svc.ComDataWithContext + +@ Port for returning ownership of data (includes Fw.Buffer) received on dataIn +output port dataReturnOut: Svc.ComDataWithContext From 0ae7ba9578558272c0c4dcf9b43ce10256a10629 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 30 Apr 2025 13:15:34 -0700 Subject: [PATCH 02/95] Tmp work --- Svc/CCSDS/CMakeLists.txt | 2 + Svc/CCSDS/SpacePacketDeframer/CMakeLists.txt | 44 +++++++++ .../SpacePacketDeframer.cpp | 90 +++++++++++++++++++ .../SpacePacketDeframer.fpp | 35 ++++++++ .../SpacePacketDeframer.hpp | 47 ++++++++++ Svc/CCSDS/SpacePacketDeframer/docs/sdd.md | 66 ++++++++++++++ Svc/CCSDS/Types/CMakeLists.txt | 28 ++++++ Svc/CCSDS/Types/Types.fpp | 37 ++++++++ Svc/CMakeLists.txt | 1 + 9 files changed, 350 insertions(+) create mode 100644 Svc/CCSDS/CMakeLists.txt create mode 100644 Svc/CCSDS/SpacePacketDeframer/CMakeLists.txt create mode 100644 Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp create mode 100644 Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp create mode 100644 Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp create mode 100644 Svc/CCSDS/SpacePacketDeframer/docs/sdd.md create mode 100644 Svc/CCSDS/Types/CMakeLists.txt create mode 100644 Svc/CCSDS/Types/Types.fpp diff --git a/Svc/CCSDS/CMakeLists.txt b/Svc/CCSDS/CMakeLists.txt new file mode 100644 index 00000000000..616c26b44b7 --- /dev/null +++ b/Svc/CCSDS/CMakeLists.txt @@ -0,0 +1,2 @@ +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Types/") +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/SpacePacketDeframer/") diff --git a/Svc/CCSDS/SpacePacketDeframer/CMakeLists.txt b/Svc/CCSDS/SpacePacketDeframer/CMakeLists.txt new file mode 100644 index 00000000000..745f38e7bcf --- /dev/null +++ b/Svc/CCSDS/SpacePacketDeframer/CMakeLists.txt @@ -0,0 +1,44 @@ +#### +# FPrime CMakeLists.txt: +# +# SOURCE_FILES: combined list of source and autocoding files +# MOD_DEPS: (optional) module dependencies +# UT_SOURCE_FILES: list of source files for unit tests +# +# More information in the F´ CMake API documentation: +# https://fprime.jpl.nasa.gov/latest/documentation/reference +# +#### + +set(SOURCE_FILES + "${CMAKE_CURRENT_LIST_DIR}/SpacePacketDeframer.fpp" + "${CMAKE_CURRENT_LIST_DIR}/SpacePacketDeframer.cpp" +) + +# Uncomment and add any modules that this component depends on, else +# they might not be available when cmake tries to build this component. +# +# Module names are derived from the path from the nearest project/library/framework +# root when not specifically overridden by the developer. i.e. The module defined by +# `Ref/SignalGen/CMakeLists.txt` will be named `Ref_SignalGen`. `Ref/SignalGen` +# is an acceptable alternative and will be internally converted to `Ref_SignalGen`. +# + +set(MOD_DEPS + Svc_CCSDS_Types +) + +register_fprime_module() + + +### Unit Tests ### +# set(UT_SOURCE_FILES +# "${CMAKE_CURRENT_LIST_DIR}/SpacePacketDeframer.fpp" +# "${CMAKE_CURRENT_LIST_DIR}/test/ut/SpacePacketDeframerTestMain.cpp" +# "${CMAKE_CURRENT_LIST_DIR}/test/ut/SpacePacketDeframerTester.cpp" +# ) +# set(UT_MOD_DEPS +# STest +# ) +# set(UT_AUTO_HELPERS ON) +# register_fprime_ut() diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp new file mode 100644 index 00000000000..b7543d8f590 --- /dev/null +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp @@ -0,0 +1,90 @@ +// ====================================================================== +// \title SpacePacketDeframer.cpp +// \author thomas-bc +// \brief cpp file for SpacePacketDeframer component implementation class +// ====================================================================== + +#include "Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp" +#include "Svc/CCSDS/Types/SpacePacketHeaderSerializableAc.hpp" + +namespace Svc { + +namespace CCSDS { + +// ---------------------------------------------------------------------- +// Component construction and destruction +// ---------------------------------------------------------------------- + +SpacePacketDeframer ::SpacePacketDeframer(const char* const compName) : SpacePacketDeframerComponentBase(compName) {} + +SpacePacketDeframer ::~SpacePacketDeframer() {} + +// ---------------------------------------------------------------------- +// Handler implementations for typed input ports +// ---------------------------------------------------------------------- + +void SpacePacketDeframer ::framedIn_handler(FwIndexType portNum, Fw::Buffer& data, CommsCfg::FrameContext& context) { + // ################################ + // CCSDS SpacePacket Format: + // 6 octets - Primary Header + // 0-65536 octets - Data Field (with optional secondary header) + + // CCSDS SpacePacket Primary Header: + // 3b - 000 - (PVN) Packet Version Number + // 1b - 0/1 - (PT) Packet Type + // 1b - 0/1 - (SHF) Secondary Header Flag + // 11b - n/a - (APID) Application Process ID + // 2b - 00 - Sequence Flag + // 14b - n/a - Sequence Count + // 16b - n/a - Packet Data Length + // ################################ + + FW_ASSERT(data.getSize() >= Svc::CCSDS::Types::SpacePacketHeader::SERIALIZED_SIZE, data.getSize()); + + CCSDS::Types::SpacePacketHeader header; + Fw::SerializeStatus status = data.getDeserializer().deserialize(header); + FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); + + U16 apid = header.getpacketIdentification() & 0x07FF; + + // // Read first byte from ring + // U8 byte = data.getData()[0]; + // // Unpack Packet Version Number (PVN) + // U8 pvn = (byte & 0xE0) >> 5; // 0xE0 = 0b11100000 + // // Unpack Packet Type (PT) + // U8 pt = (byte & 0x10) >> 4; // 0x10 = 0b00010000 + // // Unpack Secondary Header Flag (SHF) + // U8 shf = (byte & 0x08) >> 3; // 0x08 = 0b00001000 + + // // Unpack APID + // U16 apid = ((byte & 0x07) << 8); // 0x07 = 0b00000111 + // byte = data.getData()[1]; + // apid |= byte; + context.setapid(apid); + + // Sequence flag + byte = data.getData()[2]; + U8 seq_flag = (byte & 0xC0) >> 6; // 0xC0 = 0b11000000 + + // Sequence count + U16 seq_count = (byte & 0x3F) << 8; // 0x3F = 0b00111111 + byte = data.getData()[3]; + seq_count |= byte; + + // Packet length + byte = data.getData()[4]; + U16 pkt_length = byte << 8; + byte = data.getData()[5]; + pkt_length |= byte; + + + // Set data buffer to be of the encapsulated data: HEADER (6 bytes) | PACKET DATA + data.setData(data.getData() + Svc::CCSDS::Types::SpacePacketHeader::SERIALIZED_SIZE); + data.setSize(pkt_length); + + this->deframedOut_out(0, data, context); +} + +} // namespace CCSDS + +} // namespace Svc diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp new file mode 100644 index 00000000000..c12dce2c2b9 --- /dev/null +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp @@ -0,0 +1,35 @@ +module Svc { +module CCSDS { + @ Deframer for the CCSDS Space Packet protocol + passive component SpacePacketDeframer { + + include "../../Interfaces/DeframerInterface.fppi" + + @ Port for deallocating dropped frames + output port bufferDeallocate: Fw.BufferSend + + ############################################################################### + # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # + ############################################################################### + @ Port for requesting the current time + time get port timeCaller + + @ Port for sending textual representation of events + text event port logTextOut + + @ Port for sending events to downlink + event port logOut + + @ Port for sending telemetry channels to downlink + telemetry port tlmOut + + @ Port to return the value of a parameter + param get port prmGetOut + + @ Port to set the value of a parameter + param set port prmSetOut + + } + +} # end CCSDS +} # end Svc diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp new file mode 100644 index 00000000000..0de8fa31fa2 --- /dev/null +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp @@ -0,0 +1,47 @@ +// ====================================================================== +// \title SpacePacketDeframer.hpp +// \author thomas-bc +// \brief hpp file for SpacePacketDeframer component implementation class +// ====================================================================== + +#ifndef Svc_CCSDS_SpacePacketDeframer_HPP +#define Svc_CCSDS_SpacePacketDeframer_HPP + +#include "Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframerComponentAc.hpp" + +namespace Svc { + +namespace CCSDS { + +class SpacePacketDeframer final : public SpacePacketDeframerComponentBase { + public: + // ---------------------------------------------------------------------- + // Component construction and destruction + // ---------------------------------------------------------------------- + + //! Construct SpacePacketDeframer object + SpacePacketDeframer(const char* const compName //!< The component name + ); + + //! Destroy SpacePacketDeframer object + ~SpacePacketDeframer(); + + PRIVATE: + // ---------------------------------------------------------------------- + // Handler implementations for typed input ports + // ---------------------------------------------------------------------- + + //! Handler implementation for framedIn + //! + //! Port to receive framed data, with optional context + void framedIn_handler(FwIndexType portNum, //!< The port number + Fw::Buffer& data, + CommsCfg::FrameContext& context) override; + +}; + +} // namespace CCSDS + +} // namespace Svc + +#endif diff --git a/Svc/CCSDS/SpacePacketDeframer/docs/sdd.md b/Svc/CCSDS/SpacePacketDeframer/docs/sdd.md new file mode 100644 index 00000000000..210f713e75b --- /dev/null +++ b/Svc/CCSDS/SpacePacketDeframer/docs/sdd.md @@ -0,0 +1,66 @@ +# CCSDS::SpacePacketDeframer + +Deframer for the CCSDS Space Packet protocol + +## Usage Examples +Add usage examples here + +### Diagrams +Add diagrams here + +### Typical Usage +And the typical usage of the component here + +## Class Diagram +Add a class diagram here + +## Port Descriptions +| Name | Description | +|---|---| +|---|---| + +## Component States +Add component states in the chart below +| Name | Description | +|---|---| +|---|---| + +## Sequence Diagrams +Add sequence diagrams here + +## Parameters +| Name | Description | +|---|---| +|---|---| + +## Commands +| Name | Description | +|---|---| +|---|---| + +## Events +| Name | Description | +|---|---| +|---|---| + +## Telemetry +| Name | Description | +|---|---| +|---|---| + +## Unit Tests +Add unit test descriptions in the chart below +| Name | Description | Output | Coverage | +|---|---|---|---| +|---|---|---|---| + +## Requirements +Add requirements in the chart below +| Name | Description | Validation | +|---|---|---| +|---|---|---| + +## Change Log +| Date | Description | +|---|---| +|---| Initial Draft | \ No newline at end of file diff --git a/Svc/CCSDS/Types/CMakeLists.txt b/Svc/CCSDS/Types/CMakeLists.txt new file mode 100644 index 00000000000..cc029842e0b --- /dev/null +++ b/Svc/CCSDS/Types/CMakeLists.txt @@ -0,0 +1,28 @@ +#### +# FPrime CMakeLists.txt: +# +# SOURCE_FILES: combined list of source and autocoding files +# MOD_DEPS: (optional) module dependencies +# UT_SOURCE_FILES: list of source files for unit tests +# +# More information in the F´ CMake API documentation: +# https://fprime.jpl.nasa.gov/latest/documentation/reference/ +#### + +set(SOURCE_FILES + "${CMAKE_CURRENT_LIST_DIR}/Types.fpp" +) + +# Uncomment and add any modules that this module depends on, else +# they might not be available when cmake tries to build this module. +# +# Module names are derived from the path from the nearest project/library/framework +# root when not specifically overridden by the developer. i.e. The module defined by +# `Ref/SignalGen/CMakeLists.txt` will be named `Ref_SignalGen`. `Ref/SignalGen` +# is an acceptable alternative and will be internally converted to `Ref_SignalGen`. +# +#set(MOD_DEPS +# MyPackage_MyOtherModule +#) + +register_fprime_module() diff --git a/Svc/CCSDS/Types/Types.fpp b/Svc/CCSDS/Types/Types.fpp new file mode 100644 index 00000000000..0ddbdce7300 --- /dev/null +++ b/Svc/CCSDS/Types/Types.fpp @@ -0,0 +1,37 @@ +module Svc { +module CCSDS { +module Types { + + # ------------------------------------------------ + # Frame header types + # ------------------------------------------------ + # Note: FPP does not currently support bit fields, so these structs may contain fields + # that are compoed of multiple bitfields. One should mask the individual FPP types + # with the approriate mask to + + module SpacePacketMasks { + constant PvnMask = 0xE000 @< 0b1110000000000000 + constant PktTypeMask = 0x1000 @< 0b0001000000000000 + constant SecHdrMask = 0x0800 @< 0b0000100000000000 + constant ApidMask = 0x07FF @< 0b0000011111111111 + } + + @ Describes the frame header format for the SpacePacket communications protocol + struct SpacePacketHeader { + packetIdentification: U16, @< 3 bits PVN | 1 bit Pkt type | 1 bit Sec Hdr | 11 bit APID + packetSequenceControl: U16, @< 2 bits Sequence flags | 14 bits packet seq count (or name) + packetDataLength: U16 @< 16 bits length + } + + @ Describes the frame header format for a Telecommand (TC) Transfer Frame header + struct TCFrameHeader { + flagsAndScId: U16, @< 2 bits Frame V. | 1 bit bypass | 1 bit ctrl | 2 bit rsvd | 10 bits spacecraft ID + vcIdAndLength: U16, @< 6 bits Virtual Channel ID | 10 bits Frame Length + frameSequenceNbr: U8 @< 8 bits Frame Sequence Number + } + + + +} +} +} \ No newline at end of file diff --git a/Svc/CMakeLists.txt b/Svc/CMakeLists.txt index 6ebfef10f15..c07f023f863 100644 --- a/Svc/CMakeLists.txt +++ b/Svc/CMakeLists.txt @@ -65,3 +65,4 @@ add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/PosixTime/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/LinuxTimer/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Version/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/FpySequencer/") +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/CCSDS/") From e60ffad4ebc7f6a7f94177eb2fe505c18537759b Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 30 Apr 2025 15:30:12 -0700 Subject: [PATCH 03/95] Revert FileUplink changes --- Svc/FileUplink/FileUplink.cpp | 8 ++++---- Svc/FileUplink/FileUplink.fpp | 4 ++-- Svc/FileUplink/FileUplink.hpp | 3 +-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Svc/FileUplink/FileUplink.cpp b/Svc/FileUplink/FileUplink.cpp index e66a7381b8c..1e7f051d6ba 100644 --- a/Svc/FileUplink/FileUplink.cpp +++ b/Svc/FileUplink/FileUplink.cpp @@ -36,11 +36,11 @@ FileUplink ::~FileUplink() {} // Handler implementations for user-defined typed input ports // ---------------------------------------------------------------------- -void FileUplink ::bufferSendIn_handler(const FwIndexType portNum, Fw::Buffer& buffer, const ComCfg::FrameContext& context) { +void FileUplink ::bufferSendIn_handler(const FwIndexType portNum, Fw::Buffer& buffer) { // If packet is too small to contain a packet type, log + deallocate and return if (buffer.getSize() < sizeof(FwPacketDescriptorType)) { this->log_WARNING_HI_InvalidPacketReceived(Fw::ComPacket::FW_PACKET_UNKNOWN); - this->bufferSendOut_out(0, buffer, context); + this->bufferSendOut_out(0, buffer); return; } @@ -52,7 +52,7 @@ void FileUplink ::bufferSendIn_handler(const FwIndexType portNum, Fw::Buffer& bu // If packet type is not a file packet, log + deallocate and return if (packetType != Fw::ComPacket::FW_PACKET_FILE) { this->log_WARNING_HI_InvalidPacketReceived(packetType); - this->bufferSendOut_out(0, buffer, context); + this->bufferSendOut_out(0, buffer); return; } @@ -83,7 +83,7 @@ void FileUplink ::bufferSendIn_handler(const FwIndexType portNum, Fw::Buffer& bu break; } } - this->bufferSendOut_out(0, buffer, context); + this->bufferSendOut_out(0, buffer); } void FileUplink ::pingIn_handler(const FwIndexType portNum, U32 key) { diff --git a/Svc/FileUplink/FileUplink.fpp b/Svc/FileUplink/FileUplink.fpp index 8267c61c71f..bcafa6afde2 100644 --- a/Svc/FileUplink/FileUplink.fpp +++ b/Svc/FileUplink/FileUplink.fpp @@ -8,10 +8,10 @@ module Svc { # ---------------------------------------------------------------------- @ Buffer send in - async input port bufferSendIn: Svc.ComDataWithContext + async input port bufferSendIn: Fw.BufferSend @ Buffer send out - output port bufferSendOut: Svc.ComDataWithContext + output port bufferSendOut: Fw.BufferSend @ Ping in async input port pingIn: Svc.Ping diff --git a/Svc/FileUplink/FileUplink.hpp b/Svc/FileUplink/FileUplink.hpp index ae17f6454b1..75067e0d9ad 100644 --- a/Svc/FileUplink/FileUplink.hpp +++ b/Svc/FileUplink/FileUplink.hpp @@ -219,8 +219,7 @@ namespace Svc { //! void bufferSendIn_handler( const FwIndexType portNum, //!< The port number - Fw::Buffer& buffer, //!< Buffer wrapping data - const ComCfg::FrameContext& context + Fw::Buffer& buffer //!< Buffer wrapping data ); //! Handler implementation for pingIn From 56dc6596226466cd71d04094d5925625d446c909 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 30 Apr 2025 15:46:09 -0700 Subject: [PATCH 04/95] Add copy (with allocation/deallocation) to FprimeRouter to simplify buffer management --- Ref/Top/topology.fpp | 3 +++ Svc/FprimeRouter/FprimeRouter.cpp | 30 +++++++++++++---------------- Svc/FprimeRouter/FprimeRouter.fpp | 8 ++++++++ Svc/FprimeRouter/FprimeRouter.hpp | 3 +-- Svc/Interfaces/RouterInterface.fppi | 20 ++++++++++++------- 5 files changed, 38 insertions(+), 26 deletions(-) diff --git a/Ref/Top/topology.fpp b/Ref/Top/topology.fpp index 7202d56e3e4..49bc10b34be 100644 --- a/Ref/Top/topology.fpp +++ b/Ref/Top/topology.fpp @@ -181,6 +181,9 @@ module Ref { # Deframer <-> Router deframer.deframedOut -> fprimeRouter.dataIn fprimeRouter.dataReturnOut -> deframer.dataReturnIn + # Router buffer allocations + fprimeRouter.bufferAllocate -> commsBufferManager.bufferGetCallee + fprimeRouter.bufferDeallocate -> commsBufferManager.bufferSendIn # Router <-> CmdDispatcher/FileUplink fprimeRouter.commandOut -> cmdDisp.seqCmdBuff cmdDisp.seqCmdStatus -> fprimeRouter.cmdResponseIn diff --git a/Svc/FprimeRouter/FprimeRouter.cpp b/Svc/FprimeRouter/FprimeRouter.cpp index 6120b5a3dd1..2315e241f5d 100644 --- a/Svc/FprimeRouter/FprimeRouter.cpp +++ b/Svc/FprimeRouter/FprimeRouter.cpp @@ -32,9 +32,6 @@ void FprimeRouter ::dataIn_handler(FwIndexType portNum, Fw::Buffer& packetBuffer status = esb.deserialize(packetType); } - // Whether to deallocate the packet buffer - bool deallocate = true; - // Process the packet if (status == Fw::FW_SERIALIZE_OK) { U8* const packetData = packetBuffer.getData(); @@ -57,13 +54,16 @@ void FprimeRouter ::dataIn_handler(FwIndexType portNum, Fw::Buffer& packetBuffer } // Handle a file packet case Fw::ComPacket::FW_PACKET_FILE: { - // If the file uplink output port is connected, - // send the file packet. Otherwise take no action. + // If the file uplink output port is connected, send the file packet. Otherwise take no action. if (this->isConnected_fileOut_OutputPort(0)) { - // Send the packet buffer - this->fileOut_out(0, packetBuffer, context); - // Transfer ownership of the packetBuffer to the receiver - deallocate = false; + // Copy buffer into a new allocated buffer. This lets us return the original buffer with dataReturnOut, + // and FprimeRouter can handle the deallocation of the file buffer when it returns on filebufferReturnIn + Fw::Buffer packetBufferCopy = this->bufferAllocate_out(0, packetBuffer.getSize()); + auto copySerializer = packetBufferCopy.getSerializer(); + status = copySerializer.serialize(packetBuffer.getData(), packetBuffer.getSize(), Fw::Serialization::OMIT_LENGTH); + FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); + // Send the copied buffer out. It will come back on fileBufferReturnIn once the receiver is done with it + this->fileOut_out(0, packetBufferCopy); } break; } @@ -72,8 +72,6 @@ void FprimeRouter ::dataIn_handler(FwIndexType portNum, Fw::Buffer& packetBuffer // connected, forward packet and context for further processing if (this->isConnected_unknownDataOut_OutputPort(0)) { this->unknownDataOut_out(0, packetBuffer, context); - // Transfer ownership of the packetBuffer to the receiver - deallocate = false; } } } @@ -81,10 +79,8 @@ void FprimeRouter ::dataIn_handler(FwIndexType portNum, Fw::Buffer& packetBuffer this->log_WARNING_HI_DeserializationError(status); } - if (deallocate) { - // Deallocate the packet buffer - this->dataReturnOut_out(0, packetBuffer, context); - } + // Return ownership of the incoming packetBuffer + this->dataReturnOut_out(0, packetBuffer, context); } void FprimeRouter ::cmdResponseIn_handler(FwIndexType portNum, @@ -94,8 +90,8 @@ void FprimeRouter ::cmdResponseIn_handler(FwIndexType portNum, // Nothing to do } -void FprimeRouter ::fileBufferReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer, const ComCfg::FrameContext& context) { - this->dataReturnOut_out(0, fwBuffer, context); +void FprimeRouter ::fileBufferReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) { + this->bufferDeallocate_out(0, fwBuffer); } } // namespace Svc diff --git a/Svc/FprimeRouter/FprimeRouter.fpp b/Svc/FprimeRouter/FprimeRouter.fpp index 7bfa9edb56f..ca8055ffbcc 100644 --- a/Svc/FprimeRouter/FprimeRouter.fpp +++ b/Svc/FprimeRouter/FprimeRouter.fpp @@ -8,8 +8,16 @@ module Svc { include "../Interfaces/RouterInterface.fppi" @ Port for forwarding non-recognized packet types + @ Ownership of the buffer is retained by the FprimeRouter, meaning receiving + @ components should either process data synchronously, or copy the data if needed output port unknownDataOut: Svc.ComDataWithContext + @ Port for allocating buffers + output port bufferAllocate: Fw.BufferGet + + @ Port for deallocating buffers + output port bufferDeallocate: Fw.BufferSend + @ An error occurred while serializing a com buffer event SerializationError( status: U32 @< The status of the operation diff --git a/Svc/FprimeRouter/FprimeRouter.hpp b/Svc/FprimeRouter/FprimeRouter.hpp index 70a0f632ed2..6a21bb8369e 100644 --- a/Svc/FprimeRouter/FprimeRouter.hpp +++ b/Svc/FprimeRouter/FprimeRouter.hpp @@ -49,8 +49,7 @@ class FprimeRouter final : public FprimeRouterComponentBase { //! //! Port for receiving ownership back of buffers sent on fileOut void fileBufferReturnIn_handler(FwIndexType portNum, //!< The port number - Fw::Buffer& fwBuffer, //!< The buffer - const ComCfg::FrameContext& context + Fw::Buffer& fwBuffer //!< The buffer ) override; }; diff --git a/Svc/Interfaces/RouterInterface.fppi b/Svc/Interfaces/RouterInterface.fppi index 14455a223e4..19b0aec680c 100644 --- a/Svc/Interfaces/RouterInterface.fppi +++ b/Svc/Interfaces/RouterInterface.fppi @@ -1,17 +1,23 @@ +# --------------------------------------------- +# Router <-> Deframers +# --------------------------------------------- @ Receiving data (Fw::Buffer) to be routed with optional context to help with routing sync input port dataIn: Svc.ComDataWithContext +@ Port for returning ownership of data (includes Fw.Buffer) received on dataIn +output port dataReturnOut: Svc.ComDataWithContext + +# --------------------------------------------- +# Router <-> CmdDispatch/FileUplink +# --------------------------------------------- @ Port for sending file packets as Fw::Buffer (ownership passed to receiver) -output port fileOut: Svc.ComDataWithContext +output port fileOut: Fw.BufferSend + +@ Port for receiving ownership back of buffers sent on fileOut +sync input port fileBufferReturnIn: Fw.BufferSend @ Port for sending command packets as Fw::ComBuffers output port commandOut: Fw.Com @ Port for receiving command responses from a command dispatcher (can be a no-op) sync input port cmdResponseIn: Fw.CmdResponse - -@ Port for receiving ownership back of buffers sent on fileOut -sync input port fileBufferReturnIn: Svc.ComDataWithContext - -@ Port for returning ownership of data (includes Fw.Buffer) received on dataIn -output port dataReturnOut: Svc.ComDataWithContext From 8bc06f3e01b1a53d74e26640d96c44701ba0b0a8 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 30 Apr 2025 16:12:28 -0700 Subject: [PATCH 05/95] Update FprimeRouter UTs --- .../test/ut/FprimeRouterTestMain.cpp | 5 +++ .../test/ut/FprimeRouterTester.cpp | 35 +++++++++++++++---- .../test/ut/FprimeRouterTester.hpp | 12 +++++++ 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/Svc/FprimeRouter/test/ut/FprimeRouterTestMain.cpp b/Svc/FprimeRouter/test/ut/FprimeRouterTestMain.cpp index 98688b89aff..08053af6a3c 100644 --- a/Svc/FprimeRouter/test/ut/FprimeRouterTestMain.cpp +++ b/Svc/FprimeRouter/test/ut/FprimeRouterTestMain.cpp @@ -28,6 +28,11 @@ TEST(FprimeRouter, TestRouteUnknownPacketUnconnected) { Svc::FprimeRouterTester tester(true); tester.testRouteUnknownPacketUnconnected(); } +TEST(FprimeRouter, TestBufferReturn) { + COMMENT("Deallocate a returning buffer"); + Svc::FprimeRouterTester tester; + tester.testBufferReturn(); +} TEST(FprimeRouter, TestCommandResponse) { COMMENT("Handle a command response (no-op)"); Svc::FprimeRouterTester tester; diff --git a/Svc/FprimeRouter/test/ut/FprimeRouterTester.cpp b/Svc/FprimeRouter/test/ut/FprimeRouterTester.cpp index 34aac1ce3cc..4c893b8e12b 100644 --- a/Svc/FprimeRouter/test/ut/FprimeRouterTester.cpp +++ b/Svc/FprimeRouter/test/ut/FprimeRouterTester.cpp @@ -33,7 +33,8 @@ void FprimeRouterTester ::testRouteComInterface() { ASSERT_from_commandOut_SIZE(1); // one command packet emitted ASSERT_from_fileOut_SIZE(0); // no file packet emitted ASSERT_from_unknownDataOut_SIZE(0); // no unknown data emitted - ASSERT_from_bufferDeallocate_SIZE(1); // command packets are deallocated by the router + ASSERT_from_dataReturnOut_SIZE(1); // data ownership should always be returned + ASSERT_from_bufferAllocate_SIZE(0); // no buffer allocation for Com packets } void FprimeRouterTester ::testRouteFileInterface() { @@ -41,7 +42,8 @@ void FprimeRouterTester ::testRouteFileInterface() { ASSERT_from_commandOut_SIZE(0); // no command packet emitted ASSERT_from_fileOut_SIZE(1); // one file packet emitted ASSERT_from_unknownDataOut_SIZE(0); // no unknown data emitted - ASSERT_from_bufferDeallocate_SIZE(0); // no deallocation (file packets' ownership is transferred to the receiver) + ASSERT_from_dataReturnOut_SIZE(1); // data ownership should always be returned + ASSERT_from_bufferAllocate_SIZE(1); // file packet was copied into a new allocated buffer } void FprimeRouterTester ::testRouteUnknownPacket() { @@ -49,7 +51,8 @@ void FprimeRouterTester ::testRouteUnknownPacket() { ASSERT_from_commandOut_SIZE(0); // no command packet emitted ASSERT_from_fileOut_SIZE(0); // no file packet emitted ASSERT_from_unknownDataOut_SIZE(1); // one unknown data emitted - ASSERT_from_bufferDeallocate_SIZE(0); // no deallocation (unknown data ownership is transferred to the receiver) + ASSERT_from_dataReturnOut_SIZE(1); // data ownership should always be returned + ASSERT_from_bufferAllocate_SIZE(0); // no buffer allocation for unknown packets } void FprimeRouterTester ::testRouteUnknownPacketUnconnected() { @@ -57,7 +60,15 @@ void FprimeRouterTester ::testRouteUnknownPacketUnconnected() { ASSERT_from_commandOut_SIZE(0); // no command packet emitted ASSERT_from_fileOut_SIZE(0); // no file packet emitted ASSERT_from_unknownDataOut_SIZE(0); // zero unknown data emitted - ASSERT_from_bufferDeallocate_SIZE(1); // test that buffer is deallocated when output port is not connected + ASSERT_from_dataReturnOut_SIZE(1); // data ownership should always be returned + ASSERT_from_bufferAllocate_SIZE(0); // no buffer allocation for unknown packets +} + +void FprimeRouterTester ::testBufferReturn() { + U8 data[1]; + Fw::Buffer buffer(data, sizeof(data)); + this->invoke_to_fileBufferReturnIn(0, buffer); + ASSERT_from_bufferDeallocate_SIZE(1); // incoming buffer should be deallocated } void FprimeRouterTester ::testCommandResponse() { @@ -87,15 +98,27 @@ void FprimeRouterTester::connectPortsExceptUnknownData() { this->component.set_logOut_OutputPort(0, this->get_from_logOut(0)); this->component.set_logTextOut_OutputPort(0, this->get_from_logTextOut(0)); this->component.set_timeCaller_OutputPort(0, this->get_from_timeCaller(0)); - // Connect typed input ports this->connect_to_cmdResponseIn(0, this->component.get_cmdResponseIn_InputPort(0)); this->connect_to_dataIn(0, this->component.get_dataIn_InputPort(0)); - + this->connect_to_fileBufferReturnIn(0, this->component.get_fileBufferReturnIn_InputPort(0)); // Connect typed output ports + this->component.set_bufferAllocate_OutputPort(0, this->get_from_bufferAllocate(0)); this->component.set_bufferDeallocate_OutputPort(0, this->get_from_bufferDeallocate(0)); this->component.set_commandOut_OutputPort(0, this->get_from_commandOut(0)); + this->component.set_dataReturnOut_OutputPort(0, this->get_from_dataReturnOut(0)); this->component.set_fileOut_OutputPort(0, this->get_from_fileOut(0)); } +// ---------------------------------------------------------------------- +// Port handler overrides +// ---------------------------------------------------------------------- +Fw::Buffer FprimeRouterTester::from_bufferAllocate_handler(FwIndexType portNum, U32 size) { + this->pushFromPortEntry_bufferAllocate(size); + this->m_buffer.setData(this->m_buffer_slot); + this->m_buffer.setSize(size); + ::memset(this->m_buffer.getData(), 0, size); + return this->m_buffer; +} + } // namespace Svc diff --git a/Svc/FprimeRouter/test/ut/FprimeRouterTester.hpp b/Svc/FprimeRouter/test/ut/FprimeRouterTester.hpp index dd62d51fe2e..bc32e6a4a77 100644 --- a/Svc/FprimeRouter/test/ut/FprimeRouterTester.hpp +++ b/Svc/FprimeRouter/test/ut/FprimeRouterTester.hpp @@ -56,6 +56,9 @@ class FprimeRouterTester : public FprimeRouterGTestBase { //! Route a packet of unknown type void testRouteUnknownPacketUnconnected(); + //! Deallocate a returning buffer + void testBufferReturn(); + //! Invoke the command response input port void testCommandResponse(); @@ -76,6 +79,12 @@ class FprimeRouterTester : public FprimeRouterGTestBase { //! Mock the reception of a packet of a specific type void mockReceivePacketType(Fw::ComPacket::ComPacketType packetType); + // ---------------------------------------------------------------------- + // Port handler overrides + // ---------------------------------------------------------------------- + //! Overriding bufferAllocate handler to be able to request a buffer in component tests + Fw::Buffer from_bufferAllocate_handler(FwIndexType portNum, U32 size) override; + private: // ---------------------------------------------------------------------- // Member variables @@ -83,6 +92,9 @@ class FprimeRouterTester : public FprimeRouterGTestBase { //! The component under test FprimeRouter component; + + Fw::Buffer m_buffer; // buffer to be returned by mocked bufferAllocate call + U8 m_buffer_slot[64]; }; } // namespace Svc From 0b69b1fbd2ef5ab8321b9255031f1040ebdf1df5 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 30 Apr 2025 16:18:38 -0700 Subject: [PATCH 06/95] Update FprimeDeframer UTs --- Svc/FileUplink/FileUplink.hpp | 2 +- .../test/ut/FprimeDeframerTestMain.cpp | 5 +++++ .../test/ut/FprimeDeframerTester.cpp | 22 ++++++++++++++----- .../test/ut/FprimeDeframerTester.hpp | 3 +++ .../test/ut/FprimeRouterTester.cpp | 2 ++ 5 files changed, 27 insertions(+), 7 deletions(-) diff --git a/Svc/FileUplink/FileUplink.hpp b/Svc/FileUplink/FileUplink.hpp index 75067e0d9ad..3bc5faa161d 100644 --- a/Svc/FileUplink/FileUplink.hpp +++ b/Svc/FileUplink/FileUplink.hpp @@ -219,7 +219,7 @@ namespace Svc { //! void bufferSendIn_handler( const FwIndexType portNum, //!< The port number - Fw::Buffer& buffer //!< Buffer wrapping data + Fw::Buffer& buffer //!< Buffer wrapping data ); //! Handler implementation for pingIn diff --git a/Svc/FprimeDeframer/test/ut/FprimeDeframerTestMain.cpp b/Svc/FprimeDeframer/test/ut/FprimeDeframerTestMain.cpp index 43d85aa2618..ccf09fce2c0 100644 --- a/Svc/FprimeDeframer/test/ut/FprimeDeframerTestMain.cpp +++ b/Svc/FprimeDeframer/test/ut/FprimeDeframerTestMain.cpp @@ -37,6 +37,11 @@ TEST(FprimeDeframer, testIncorrectCrc) { tester.testIncorrectCrc(); } +TEST(FprimeDeframer, testDataReturn) { + Svc::FprimeDeframerTester tester; + tester.testDataReturn(); +} + int main(int argc, char** argv) { STest::Random::seed(); ::testing::InitGoogleTest(&argc, argv); diff --git a/Svc/FprimeDeframer/test/ut/FprimeDeframerTester.cpp b/Svc/FprimeDeframer/test/ut/FprimeDeframerTester.cpp index c56b6a4b45e..cf506b17e5a 100644 --- a/Svc/FprimeDeframer/test/ut/FprimeDeframerTester.cpp +++ b/Svc/FprimeDeframer/test/ut/FprimeDeframerTester.cpp @@ -35,7 +35,7 @@ void FprimeDeframerTester ::testNominalFrame() { this->mockReceiveData(data, sizeof(data)); ASSERT_from_deframedOut_SIZE(1); // something emitted on deframedOut - ASSERT_from_bufferDeallocate_SIZE(0); // nothing emitted on bufferDeallocate + ASSERT_from_dataReturnOut_SIZE(0); // nothing emitted on dataReturnOut // Assert that the data that was emitted on deframedOut is equal to Data field above (randomByte) ASSERT_EQ(this->fromPortHistory_deframedOut->at(0).data.getData()[0], randomByte); ASSERT_EVENTS_SIZE(0); // no events emitted @@ -49,7 +49,7 @@ void FprimeDeframerTester ::testIncorrectLengthToken() { this->mockReceiveData(data, sizeof(data)); ASSERT_from_deframedOut_SIZE(0); // nothing emitted on deframedOut - ASSERT_from_bufferDeallocate_SIZE(1); // invalid buffer was deallocated + ASSERT_from_dataReturnOut_SIZE(1); // invalid buffer was deallocated // Check which event was emitted ASSERT_EVENTS_SIZE(1); // exactly 1 event emitted ASSERT_EVENTS_InvalidLengthReceived_SIZE(1); // event was emitted for invalid length @@ -63,7 +63,7 @@ void FprimeDeframerTester ::testIncorrectStartWord() { this->mockReceiveData(data, sizeof(data)); ASSERT_from_deframedOut_SIZE(0); // nothing emitted on deframedOut - ASSERT_from_bufferDeallocate_SIZE(1); // invalid buffer was deallocated + ASSERT_from_dataReturnOut_SIZE(1); // invalid buffer was deallocated // Check which event was emitted ASSERT_EVENTS_SIZE(1); // exactly 1 event emitted ASSERT_EVENTS_InvalidStartWord_SIZE(1); // event was emitted for invalid start word @@ -74,7 +74,7 @@ void FprimeDeframerTester ::testIncorrectCrc() { U8 data[13] = {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; this->mockReceiveData(data, sizeof(data)); ASSERT_from_deframedOut_SIZE(0); // nothing emitted on deframedOut - ASSERT_from_bufferDeallocate_SIZE(1); // invalid buffer was deallocated + ASSERT_from_dataReturnOut_SIZE(1); // invalid buffer was deallocated // Check which event was emitted ASSERT_EVENTS_SIZE(1); // exactly 1 event emitted ASSERT_EVENTS_InvalidChecksum_SIZE(1); // event was emitted for invalid checksum @@ -85,7 +85,7 @@ void FprimeDeframerTester::testTruncatedFrame() { U8 data[11] = {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; this->mockReceiveData(data, sizeof(data)); ASSERT_from_deframedOut_SIZE(0); // nothing emitted on deframedOut - ASSERT_from_bufferDeallocate_SIZE(1); // invalid buffer was deallocated + ASSERT_from_dataReturnOut_SIZE(1); // invalid buffer was deallocated // Check which event was emitted ASSERT_EVENTS_SIZE(1); // exactly 1 event emitted ASSERT_EVENTS_InvalidBufferReceived_SIZE(1); // event was emitted for invalid buffer @@ -95,12 +95,22 @@ void FprimeDeframerTester::testZeroSizeFrame() { // Send an empty frame, too short to be valid this->mockReceiveData(nullptr, 0); ASSERT_from_deframedOut_SIZE(0); // nothing emitted on deframedOut - ASSERT_from_bufferDeallocate_SIZE(1); // invalid buffer was deallocated + ASSERT_from_dataReturnOut_SIZE(1); // invalid buffer was deallocated // Check which event was emitted ASSERT_EVENTS_SIZE(1); // exactly 1 event emitted ASSERT_EVENTS_InvalidBufferReceived_SIZE(1); // event was emitted for invalid buffer } +void FprimeDeframerTester::testDataReturn() { + U8 data[1]; + Fw::Buffer buffer(data, sizeof(data)); + ComCfg::FrameContext nullContext; + this->invoke_to_dataReturnIn(0, buffer, nullContext); + ASSERT_from_dataReturnOut_SIZE(1); // incoming buffer should be deallocated + ASSERT_EQ(this->fromPortHistory_dataReturnOut->at(0).data.getData(), data); + ASSERT_EQ(this->fromPortHistory_dataReturnOut->at(0).data.getSize(), sizeof(data)); +} + // ---------------------------------------------------------------------- // Test Helpers // ---------------------------------------------------------------------- diff --git a/Svc/FprimeDeframer/test/ut/FprimeDeframerTester.hpp b/Svc/FprimeDeframer/test/ut/FprimeDeframerTester.hpp index 08bac6a7b91..6818bbdf2a5 100644 --- a/Svc/FprimeDeframer/test/ut/FprimeDeframerTester.hpp +++ b/Svc/FprimeDeframer/test/ut/FprimeDeframerTester.hpp @@ -58,6 +58,9 @@ class FprimeDeframerTester : public FprimeDeframerGTestBase { //! Test receiving a frame with an incorrect Crc field void testIncorrectCrc(); + //! Test bufferReturn passthrough + void testDataReturn(); + private: // ---------------------------------------------------------------------- // Helper functions diff --git a/Svc/FprimeRouter/test/ut/FprimeRouterTester.cpp b/Svc/FprimeRouter/test/ut/FprimeRouterTester.cpp index 4c893b8e12b..44c51ad5343 100644 --- a/Svc/FprimeRouter/test/ut/FprimeRouterTester.cpp +++ b/Svc/FprimeRouter/test/ut/FprimeRouterTester.cpp @@ -69,6 +69,8 @@ void FprimeRouterTester ::testBufferReturn() { Fw::Buffer buffer(data, sizeof(data)); this->invoke_to_fileBufferReturnIn(0, buffer); ASSERT_from_bufferDeallocate_SIZE(1); // incoming buffer should be deallocated + ASSERT_EQ(this->fromPortHistory_bufferDeallocate->at(0).fwBuffer.getData(), data); + ASSERT_EQ(this->fromPortHistory_bufferDeallocate->at(0).fwBuffer.getSize(), sizeof(data)); } void FprimeRouterTester ::testCommandResponse() { From 678fd453c62c5500dde28598fdb4d474fbc39004 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 30 Apr 2025 16:25:41 -0700 Subject: [PATCH 07/95] Update FrameAccumulator UTs --- .../test/ut/FrameAccumulatorTestMain.cpp | 4 +++ .../test/ut/FrameAccumulatorTester.cpp | 26 +++++++++++++------ .../test/ut/FrameAccumulatorTester.hpp | 3 +++ 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/Svc/FrameAccumulator/test/ut/FrameAccumulatorTestMain.cpp b/Svc/FrameAccumulator/test/ut/FrameAccumulatorTestMain.cpp index c84b984d42b..5f29fd93a1c 100644 --- a/Svc/FrameAccumulator/test/ut/FrameAccumulatorTestMain.cpp +++ b/Svc/FrameAccumulator/test/ut/FrameAccumulatorTestMain.cpp @@ -42,6 +42,10 @@ TEST(FrameAccumulator, testAccumulateBuffersEmitManyFrames) { tester.testAccumulateBuffersEmitManyFrames(); } +TEST(FrameAccumulator, testBufferReturnDeallocation) { + Svc::FrameAccumulatorTester tester; + tester.testBufferReturnDeallocation(); +} int main(int argc, char** argv) { STest::Random::seed(); diff --git a/Svc/FrameAccumulator/test/ut/FrameAccumulatorTester.cpp b/Svc/FrameAccumulator/test/ut/FrameAccumulatorTester.cpp index b0b96c2b14d..8588711710a 100644 --- a/Svc/FrameAccumulator/test/ut/FrameAccumulatorTester.cpp +++ b/Svc/FrameAccumulator/test/ut/FrameAccumulatorTester.cpp @@ -42,7 +42,7 @@ void FrameAccumulatorTester ::testFrameDetected() { // Receive the buffer on dataIn this->invoke_to_dataIn(0, buffer); // Checks - ASSERT_from_bufferDeallocate_SIZE(1); // input buffer was deallocated + ASSERT_from_bufferReturnOut_SIZE(1); // input buffer ownership was returned ASSERT_from_frameOut_SIZE(1); // frame was sent ASSERT_EQ(this->component.m_inRing.get_allocated_size(), 0); // no data left in ring buffer ASSERT_EQ(this->fromPortHistory_frameOut->at(0).data.getSize(), buffer_size); // all data was sent out @@ -58,7 +58,7 @@ void FrameAccumulatorTester ::testMoreDataNeeded() { // Receive the buffer on dataIn this->invoke_to_dataIn(0, buffer); // Checks - ASSERT_from_bufferDeallocate_SIZE(1); // input buffer was deallocated + ASSERT_from_bufferReturnOut_SIZE(1); // input buffer ownership was returned ASSERT_from_frameOut_SIZE(0); // frame was not sent (waiting on more data) ASSERT_EQ(this->component.m_inRing.get_allocated_size(), buffer_size); // data left in ring buffer } @@ -73,7 +73,7 @@ void FrameAccumulatorTester ::testNoFrameDetected() { // Receive the buffer on dataIn this->invoke_to_dataIn(0, buffer); // Checks - ASSERT_from_bufferDeallocate_SIZE(1); // input buffer was deallocated + ASSERT_from_bufferReturnOut_SIZE(1); // input buffer ownership was returned ASSERT_from_frameOut_SIZE(0); // No frame was sent out ASSERT_EQ(this->component.m_inRing.get_allocated_size(), 0); // all data was consumed and discarded } @@ -86,7 +86,7 @@ void FrameAccumulatorTester ::testReceiveZeroSizeBuffer() { // Receive the buffer on dataIn this->invoke_to_dataIn(0, buffer); // Checks - ASSERT_from_bufferDeallocate_SIZE(1); // input buffer was deallocated + ASSERT_from_bufferReturnOut_SIZE(1); // input buffer ownership was returned ASSERT_from_frameOut_SIZE(0); // No frame was sent out ASSERT_EQ(this->component.m_inRing.get_allocated_size(), 0); // No data in ring buffer ASSERT_EQ(this->component.m_inRing.m_head_idx, 0); @@ -109,7 +109,7 @@ void FrameAccumulatorTester ::testAccumulateTwoBuffers() { this->invoke_to_dataIn(0, buffer2); // Checks - ASSERT_from_bufferDeallocate_SIZE(2); // both input buffers deallocated + ASSERT_from_bufferReturnOut_SIZE(2); // both input buffers ownership were returned ASSERT_from_frameOut_SIZE(1); // Exactly one frame was sent out ASSERT_EQ(this->component.m_inRing.get_allocated_size(), 0); // No data in ring buffer } @@ -119,7 +119,7 @@ void FrameAccumulatorTester ::testAccumulateBuffersEmitFrame() { U32 buffer_count = 0; this->mockAccumulateFullFrame(frame_size, buffer_count); // Checks - ASSERT_from_bufferDeallocate_SIZE(buffer_count); // all input buffers deallocated + ASSERT_from_bufferReturnOut_SIZE(buffer_count); // all input buffers ownership were returned ASSERT_from_frameOut_SIZE(1); // Exactly one frame was sent out ASSERT_EQ(this->component.m_inRing.get_allocated_size(), 0); // No data left in ring buffer ASSERT_EQ(this->fromPortHistory_frameOut->at(0).data.getSize(), frame_size); // accumulated buffer size @@ -137,17 +137,27 @@ void FrameAccumulatorTester ::testAccumulateBuffersEmitManyFrames() { this->mockAccumulateFullFrame(frame_size, buffer_count); total_buffer_received += buffer_count; - ASSERT_from_bufferDeallocate_SIZE(total_buffer_received); // all input buffers deallocated + ASSERT_from_bufferReturnOut_SIZE(total_buffer_received); // all input buffers returned ASSERT_from_frameOut_SIZE(i+1); // Exactly one frame was sent out ASSERT_EQ(this->component.m_inRing.get_allocated_size(), 0); // No data left in ring buffer ASSERT_EQ(this->fromPortHistory_frameOut->at(i).data.getSize(), frame_size); // accumulated buffer size } // Final checks - ASSERT_from_bufferDeallocate_SIZE(total_buffer_received); // all input buffers deallocated + ASSERT_from_bufferReturnOut_SIZE(total_buffer_received); // all input buffers returned ASSERT_from_frameOut_SIZE(max_iters); // Exactly max_iters frames were sent out ASSERT_EQ(this->component.m_inRing.get_allocated_size(), 0); // No data left in ring buffer } +void FrameAccumulatorTester ::testBufferReturnDeallocation() { + U8 data[1]; + Fw::Buffer buffer(data, sizeof(data)); + ComCfg::FrameContext ignoredContext; + this->invoke_to_dataReturnIn(0, buffer, ignoredContext); + ASSERT_from_bufferDeallocate_SIZE(1); // incoming buffer should be deallocated + ASSERT_EQ(this->fromPortHistory_bufferDeallocate->at(0).fwBuffer.getData(), data); + ASSERT_EQ(this->fromPortHistory_bufferDeallocate->at(0).fwBuffer.getSize(), sizeof(data)); +} + // ---------------------------------------------------------------------- // Helper functions // ---------------------------------------------------------------------- diff --git a/Svc/FrameAccumulator/test/ut/FrameAccumulatorTester.hpp b/Svc/FrameAccumulator/test/ut/FrameAccumulatorTester.hpp index 8101edfbe06..191990b7ec2 100644 --- a/Svc/FrameAccumulator/test/ut/FrameAccumulatorTester.hpp +++ b/Svc/FrameAccumulator/test/ut/FrameAccumulatorTester.hpp @@ -63,6 +63,9 @@ class FrameAccumulatorTester : public FrameAccumulatorGTestBase { //! Test accumulation of multiple random-size buffer into frames successively void testAccumulateBuffersEmitManyFrames(); + //! Test returning ownership of a buffer + void testBufferReturnDeallocation(); + private: // ---------------------------------------------------------------------- // Helper functions From 66d5a91a921eac5e200a1a7d409976a9324e1864 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 30 Apr 2025 16:29:01 -0700 Subject: [PATCH 08/95] Update ComStub UTs --- Svc/ComStub/test/ut/ComStubTestMain.cpp | 5 +++++ Svc/ComStub/test/ut/ComStubTester.cpp | 10 ++++++++++ Svc/ComStub/test/ut/ComStubTester.hpp | 3 +++ 3 files changed, 18 insertions(+) diff --git a/Svc/ComStub/test/ut/ComStubTestMain.cpp b/Svc/ComStub/test/ut/ComStubTestMain.cpp index 80531e4a563..bdd7611e2d0 100644 --- a/Svc/ComStub/test/ut/ComStubTestMain.cpp +++ b/Svc/ComStub/test/ut/ComStubTestMain.cpp @@ -20,6 +20,11 @@ TEST(Nominal, Fail) { tester.test_fail(); } +TEST(Nominal, BufferReturn) { + Svc::ComStubTester tester; + tester.test_buffer_return(); +} + TEST(OffNominal, Retry) { Svc::ComStubTester tester; tester.test_retry(); diff --git a/Svc/ComStub/test/ut/ComStubTester.cpp b/Svc/ComStub/test/ut/ComStubTester.cpp index a86a5e0df15..d201561914c 100644 --- a/Svc/ComStub/test/ut/ComStubTester.cpp +++ b/Svc/ComStub/test/ut/ComStubTester.cpp @@ -149,6 +149,16 @@ void ComStubTester ::test_retry_reset() { ASSERT_from_drvDataOut_SIZE(expected_drvDataOut_count); // no drvDataOut sent when OP_OK } +void ComStubTester ::test_buffer_return() { + U8 data[1]; + Fw::Buffer buffer(data, sizeof(data)); + this->invoke_to_bufferReturnIn(0, buffer); + ASSERT_from_bufferReturnOut_SIZE(1); // incoming buffer should be returned + ASSERT_EQ(this->fromPortHistory_bufferReturnOut->at(0).fwBuffer.getData(), data); + ASSERT_EQ(this->fromPortHistory_bufferReturnOut->at(0).fwBuffer.getSize(), sizeof(data)); +} + + // ---------------------------------------------------------------------- // Handlers for typed from ports // ---------------------------------------------------------------------- diff --git a/Svc/ComStub/test/ut/ComStubTester.hpp b/Svc/ComStub/test/ut/ComStubTester.hpp index a4b00d02268..130f195fedb 100644 --- a/Svc/ComStub/test/ut/ComStubTester.hpp +++ b/Svc/ComStub/test/ut/ComStubTester.hpp @@ -60,6 +60,9 @@ class ComStubTester : public ComStubGTestBase { //! void test_retry_reset(); + //! Tests buffer is returned + //! + void test_buffer_return(); private: // ---------------------------------------------------------------------- // Handlers for typed from ports From 6566ae9b8866b28e0ebed3c649eb9f0695d7ac8d Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 30 Apr 2025 16:38:53 -0700 Subject: [PATCH 09/95] Update missing Drv and UTs --- Drv/LinuxUartDriver/LinuxUartDriver.cpp | 5 +++++ Drv/LinuxUartDriver/LinuxUartDriver.fpp | 3 +++ Drv/LinuxUartDriver/LinuxUartDriver.hpp | 6 ++++++ Drv/TcpClient/test/ut/TcpClientTester.cpp | 9 +++++++++ Drv/TcpClient/test/ut/TcpClientTester.hpp | 2 ++ Drv/TcpServer/TcpServer.fpp | 3 +++ Drv/TcpServer/TcpServerComponentImpl.cpp | 4 ++++ Drv/TcpServer/TcpServerComponentImpl.hpp | 7 +++++++ Drv/TcpServer/test/ut/TcpServerTestMain.cpp | 5 +++++ Drv/TcpServer/test/ut/TcpServerTester.cpp | 9 +++++++++ Drv/TcpServer/test/ut/TcpServerTester.hpp | 2 ++ Svc/ComStub/test/ut/ComStubTester.cpp | 1 - 12 files changed, 55 insertions(+), 1 deletion(-) diff --git a/Drv/LinuxUartDriver/LinuxUartDriver.cpp b/Drv/LinuxUartDriver/LinuxUartDriver.cpp index 8e304e7765c..9eb4204bac0 100644 --- a/Drv/LinuxUartDriver/LinuxUartDriver.cpp +++ b/Drv/LinuxUartDriver/LinuxUartDriver.cpp @@ -314,6 +314,11 @@ void LinuxUartDriver ::send_handler(const FwIndexType portNum, Fw::Buffer& serBu dataReturnOut_out(0, serBuffer, status); } + +void LinuxUartDriver::bufferReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) { + this->deallocate_out(0, fwBuffer); +} + void LinuxUartDriver ::serialReadTaskEntry(void* ptr) { FW_ASSERT(ptr != nullptr); Drv::ByteStreamStatus status = ByteStreamStatus::OTHER_ERROR; // added by m.chase 03.06.2017 diff --git a/Drv/LinuxUartDriver/LinuxUartDriver.fpp b/Drv/LinuxUartDriver/LinuxUartDriver.fpp index 38b8078172e..203574bd756 100644 --- a/Drv/LinuxUartDriver/LinuxUartDriver.fpp +++ b/Drv/LinuxUartDriver/LinuxUartDriver.fpp @@ -11,6 +11,9 @@ module Drv { @ Allocation port used for allocating memory in the receive task output port allocate: Fw.BufferGet + @ Deallocation of allocated buffers + output port deallocate: Fw.BufferSend + # ---------------------------------------------------------------------- # Special ports # ---------------------------------------------------------------------- diff --git a/Drv/LinuxUartDriver/LinuxUartDriver.hpp b/Drv/LinuxUartDriver/LinuxUartDriver.hpp index 7e98ba0ff2f..936490998e0 100644 --- a/Drv/LinuxUartDriver/LinuxUartDriver.hpp +++ b/Drv/LinuxUartDriver/LinuxUartDriver.hpp @@ -96,6 +96,12 @@ class LinuxUartDriver final : public LinuxUartDriverComponentBase { void send_handler(FwIndexType portNum, /*!< The port number*/ Fw::Buffer& serBuffer); + //! Handler implementation for bufferReturnIn + //! + //! Port receiving back ownership of data sent out on $recv port + void bufferReturnIn_handler(FwIndexType portNum, //!< The port number + Fw::Buffer& fwBuffer //!< The buffer + ) override; PlatformIntType m_fd; //!< file descriptor returned for I/O device U32 m_allocationSize; //!< size of allocation request to memory manager diff --git a/Drv/TcpClient/test/ut/TcpClientTester.cpp b/Drv/TcpClient/test/ut/TcpClientTester.cpp index dd9ae9b741a..dbd2631ff82 100644 --- a/Drv/TcpClient/test/ut/TcpClientTester.cpp +++ b/Drv/TcpClient/test/ut/TcpClientTester.cpp @@ -180,6 +180,15 @@ void TcpClientTester ::test_no_automatic_recv_connection() { server.terminate(server_fd); } +void TcpClientTester ::test_buffer_deallocation() { + U8 data[1]; + Fw::Buffer buffer(data, sizeof(data)); + this->invoke_to_bufferReturnIn(0, buffer); + ASSERT_from_deallocate_SIZE(1); // incoming buffer should be deallocated + ASSERT_EQ(this->fromPortHistory_deallocate->at(0).fwBuffer.getData(), data); + ASSERT_EQ(this->fromPortHistory_deallocate->at(0).fwBuffer.getSize(), sizeof(data)); +} + // ---------------------------------------------------------------------- // Handler overrides for typed from ports // ---------------------------------------------------------------------- diff --git a/Drv/TcpClient/test/ut/TcpClientTester.hpp b/Drv/TcpClient/test/ut/TcpClientTester.hpp index 392d0c9b4da..09db5e8486f 100644 --- a/Drv/TcpClient/test/ut/TcpClientTester.hpp +++ b/Drv/TcpClient/test/ut/TcpClientTester.hpp @@ -67,6 +67,8 @@ namespace Drv { void test_with_loop(U32 iterations, bool recv_thread=false); + void test_buffer_deallocation(); + private: // ---------------------------------------------------------------------- diff --git a/Drv/TcpServer/TcpServer.fpp b/Drv/TcpServer/TcpServer.fpp index 49fdfcc248d..ce2df810a76 100644 --- a/Drv/TcpServer/TcpServer.fpp +++ b/Drv/TcpServer/TcpServer.fpp @@ -6,5 +6,8 @@ module Drv { @ Allocation for received data output port allocate: Fw.BufferGet + @ Deallocation of allocated buffers + output port deallocate: Fw.BufferSend + } } diff --git a/Drv/TcpServer/TcpServerComponentImpl.cpp b/Drv/TcpServer/TcpServerComponentImpl.cpp index 3e42151f93a..3709b450507 100644 --- a/Drv/TcpServer/TcpServerComponentImpl.cpp +++ b/Drv/TcpServer/TcpServerComponentImpl.cpp @@ -142,4 +142,8 @@ void TcpServerComponentImpl::send_handler(const FwIndexType portNum, Fw::Buffer& this->dataReturnOut_out(0, fwBuffer, returnStatus); } +void TcpServerComponentImpl::bufferReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) { + this->deallocate_out(0, fwBuffer); +} + } // end namespace Drv diff --git a/Drv/TcpServer/TcpServerComponentImpl.hpp b/Drv/TcpServer/TcpServerComponentImpl.hpp index b6d500b8b6f..28ac5ecb964 100644 --- a/Drv/TcpServer/TcpServerComponentImpl.hpp +++ b/Drv/TcpServer/TcpServerComponentImpl.hpp @@ -161,6 +161,13 @@ class TcpServerComponentImpl final : public TcpServerComponentBase, public Socke */ void send_handler(const FwIndexType portNum, Fw::Buffer& fwBuffer) override; + //! Handler implementation for bufferReturnIn + //! + //! Port receiving back ownership of data sent out on $recv port + void bufferReturnIn_handler(FwIndexType portNum, //!< The port number + Fw::Buffer& fwBuffer //!< The buffer + ) override; + Drv::TcpServerSocket m_socket; //!< Socket implementation FwSizeType m_allocation_size; //!< Member variable to store the buffer size diff --git a/Drv/TcpServer/test/ut/TcpServerTestMain.cpp b/Drv/TcpServer/test/ut/TcpServerTestMain.cpp index e60f75c3d0e..c1b739007c3 100644 --- a/Drv/TcpServer/test/ut/TcpServerTestMain.cpp +++ b/Drv/TcpServer/test/ut/TcpServerTestMain.cpp @@ -4,6 +4,11 @@ #include "TcpServerTester.hpp" +TEST(Nominal, TcpServerBufferDeallocation) { + Drv::TcpServerTester tester; + tester.test_buffer_deallocation(); +} + TEST(Nominal, TcpServerBasicMessaging) { Drv::TcpServerTester tester; tester.test_basic_messaging(); diff --git a/Drv/TcpServer/test/ut/TcpServerTester.cpp b/Drv/TcpServer/test/ut/TcpServerTester.cpp index 05052d43183..4d9f9072102 100644 --- a/Drv/TcpServer/test/ut/TcpServerTester.cpp +++ b/Drv/TcpServer/test/ut/TcpServerTester.cpp @@ -217,6 +217,15 @@ void TcpServerTester ::test_no_automatic_recv_connection() { this->component.terminate(); } +void TcpServerTester ::test_buffer_deallocation() { + U8 data[1]; + Fw::Buffer buffer(data, sizeof(data)); + this->invoke_to_bufferReturnIn(0, buffer); + ASSERT_from_deallocate_SIZE(1); // incoming buffer should be deallocated + ASSERT_EQ(this->fromPortHistory_deallocate->at(0).fwBuffer.getData(), data); + ASSERT_EQ(this->fromPortHistory_deallocate->at(0).fwBuffer.getSize(), sizeof(data)); +} + // ---------------------------------------------------------------------- // Handlers for typed from ports // ---------------------------------------------------------------------- diff --git a/Drv/TcpServer/test/ut/TcpServerTester.hpp b/Drv/TcpServer/test/ut/TcpServerTester.hpp index 3d749da6200..f8434ad0fee 100644 --- a/Drv/TcpServer/test/ut/TcpServerTester.hpp +++ b/Drv/TcpServer/test/ut/TcpServerTester.hpp @@ -75,6 +75,8 @@ namespace Drv { void test_no_automatic_send_connection(); void test_no_automatic_recv_connection(); + + void test_buffer_deallocation(); bool wait_on_change(bool open, U32 iterations); bool wait_on_started(bool open, U32 iterations); diff --git a/Svc/ComStub/test/ut/ComStubTester.cpp b/Svc/ComStub/test/ut/ComStubTester.cpp index d201561914c..4987c5ac675 100644 --- a/Svc/ComStub/test/ut/ComStubTester.cpp +++ b/Svc/ComStub/test/ut/ComStubTester.cpp @@ -158,7 +158,6 @@ void ComStubTester ::test_buffer_return() { ASSERT_EQ(this->fromPortHistory_bufferReturnOut->at(0).fwBuffer.getSize(), sizeof(data)); } - // ---------------------------------------------------------------------- // Handlers for typed from ports // ---------------------------------------------------------------------- From 75638b01cef59986d77466462e8a9b605787d47b Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 30 Apr 2025 17:12:01 -0700 Subject: [PATCH 10/95] Update ComInterface to use ComDataWithContext on output --- Ref/Top/topology.fpp | 2 +- Svc/ComStub/ComStub.cpp | 3 ++- Svc/ComStub/test/ut/ComStubTester.cpp | 8 ++++--- Svc/FrameAccumulator/FrameAccumulator.cpp | 3 ++- Svc/FrameAccumulator/FrameAccumulator.hpp | 5 +++-- .../test/ut/FrameAccumulatorTester.cpp | 22 ++++++++++++------- Svc/Interfaces/ComInterface.fppi | 4 +--- Svc/Interfaces/FrameAccumulatorInterface.fppi | 2 +- 8 files changed, 29 insertions(+), 20 deletions(-) diff --git a/Ref/Top/topology.fpp b/Ref/Top/topology.fpp index 49bc10b34be..55adb4c27ef 100644 --- a/Ref/Top/topology.fpp +++ b/Ref/Top/topology.fpp @@ -170,7 +170,7 @@ module Ref { comDriver.$recv -> comStub.drvDataIn comStub.bufferReturnOut -> comDriver.bufferReturnIn # ComStub <-> FrameAccumulator - comStub.comDataOut -> frameAccumulator.dataIn # Update needed: ComInterface needs to emit ComDataWithContext ? + comStub.comDataOut -> frameAccumulator.dataIn frameAccumulator.bufferReturnOut -> comStub.bufferReturnIn # FrameAccumulator buffer allocations frameAccumulator.bufferDeallocate -> commsBufferManager.bufferSendIn diff --git a/Svc/ComStub/ComStub.cpp b/Svc/ComStub/ComStub.cpp index be86a50fc6d..0b80361a09d 100644 --- a/Svc/ComStub/ComStub.cpp +++ b/Svc/ComStub/ComStub.cpp @@ -41,7 +41,8 @@ void ComStub::drvDataIn_handler(const FwIndexType portNum, Fw::Buffer& recvBuffer, const Drv::ByteStreamStatus& recvStatus) { if (recvStatus.e == Drv::ByteStreamStatus::OP_OK) { - this->comDataOut_out(0, recvBuffer); + ComCfg::FrameContext emptyContext; // ComStub knows nothing about the received bytes, so use an empty context + this->comDataOut_out(0, recvBuffer, emptyContext); } } diff --git a/Svc/ComStub/test/ut/ComStubTester.cpp b/Svc/ComStub/test/ut/ComStubTester.cpp index 4987c5ac675..14adee34f12 100644 --- a/Svc/ComStub/test/ut/ComStubTester.cpp +++ b/Svc/ComStub/test/ut/ComStubTester.cpp @@ -60,9 +60,10 @@ void ComStubTester ::test_basic() { ASSERT_from_drvDataOut(0, buffer); // Uplink + ComCfg::FrameContext emptyContext; invoke_to_drvDataIn(0, buffer, Drv::ByteStreamStatus::OP_OK); ASSERT_from_comDataOut_SIZE(1); - ASSERT_from_comDataOut(0, buffer); + ASSERT_from_comDataOut(0, buffer, emptyContext); } void ComStubTester ::test_fail() { @@ -163,8 +164,9 @@ void ComStubTester ::test_buffer_return() { // ---------------------------------------------------------------------- void ComStubTester ::from_comDataOut_handler(const FwIndexType portNum, - Fw::Buffer& recvBuffer) { - this->pushFromPortEntry_comDataOut(recvBuffer); + Fw::Buffer& recvBuffer, + const ComCfg::FrameContext& context) { + this->pushFromPortEntry_comDataOut(recvBuffer, context); } void ComStubTester ::from_comStatusOut_handler(const FwIndexType portNum, Fw::Success& condition) { diff --git a/Svc/FrameAccumulator/FrameAccumulator.cpp b/Svc/FrameAccumulator/FrameAccumulator.cpp index 0bd6395a699..4937738ef93 100644 --- a/Svc/FrameAccumulator/FrameAccumulator.cpp +++ b/Svc/FrameAccumulator/FrameAccumulator.cpp @@ -50,9 +50,10 @@ void FrameAccumulator ::cleanup() { // Handler implementations for user-defined typed input ports // ---------------------------------------------------------------------- -void FrameAccumulator ::dataIn_handler(FwIndexType portNum, Fw::Buffer& buffer) { +void FrameAccumulator ::dataIn_handler(FwIndexType portNum, Fw::Buffer& buffer, const ComCfg::FrameContext& context) { // Check whether there is data to process if (buffer.isValid()) { + // The buffer is not necessarily a full frame, so the attached context has no meaning and we ignore it this->processBuffer(buffer); } // Return ownership of the incoming buffer (FrameAccumulator allocates its own buffers to hold frames) diff --git a/Svc/FrameAccumulator/FrameAccumulator.hpp b/Svc/FrameAccumulator/FrameAccumulator.hpp index 099b6eae4a6..0465aff69a2 100644 --- a/Svc/FrameAccumulator/FrameAccumulator.hpp +++ b/Svc/FrameAccumulator/FrameAccumulator.hpp @@ -48,9 +48,10 @@ class FrameAccumulator final : public FrameAccumulatorComponentBase { //! Handler implementation for dataIn //! - //! Receives raw data from a ByteStreamDriver, ComStub, or other buffer producing component + //! Receive stream of bytes from a ComInterface component void dataIn_handler(FwIndexType portNum, //!< The port number - Fw::Buffer& recvBuffer) override; + Fw::Buffer& recvBuffer, + const ComCfg::FrameContext& context) override; //! Handler implementation for bufferReturnIn //! diff --git a/Svc/FrameAccumulator/test/ut/FrameAccumulatorTester.cpp b/Svc/FrameAccumulator/test/ut/FrameAccumulatorTester.cpp index 8588711710a..c079cf148df 100644 --- a/Svc/FrameAccumulator/test/ut/FrameAccumulatorTester.cpp +++ b/Svc/FrameAccumulator/test/ut/FrameAccumulatorTester.cpp @@ -37,10 +37,11 @@ void FrameAccumulatorTester ::testFrameDetected() { U32 buffer_size = STest::Random::lowerUpper(1, 1024); U8 data[buffer_size]; Fw::Buffer buffer(data, buffer_size); + ComCfg::FrameContext context; // Set the mock detector to report success of size_out = buffer_size this->mockDetector.set_next_result(FrameDetector::Status::FRAME_DETECTED, buffer_size); // Receive the buffer on dataIn - this->invoke_to_dataIn(0, buffer); + this->invoke_to_dataIn(0, buffer, context); // Checks ASSERT_from_bufferReturnOut_SIZE(1); // input buffer ownership was returned ASSERT_from_frameOut_SIZE(1); // frame was sent @@ -53,10 +54,11 @@ void FrameAccumulatorTester ::testMoreDataNeeded() { U32 buffer_size = STest::Random::lowerUpper(1, 1024); U8 data[buffer_size]; Fw::Buffer buffer(data, buffer_size); + ComCfg::FrameContext context; // Set the mock detector to report more data needed this->mockDetector.set_next_result(FrameDetector::Status::MORE_DATA_NEEDED, buffer_size + 1); // Receive the buffer on dataIn - this->invoke_to_dataIn(0, buffer); + this->invoke_to_dataIn(0, buffer, context); // Checks ASSERT_from_bufferReturnOut_SIZE(1); // input buffer ownership was returned ASSERT_from_frameOut_SIZE(0); // frame was not sent (waiting on more data) @@ -68,10 +70,11 @@ void FrameAccumulatorTester ::testNoFrameDetected() { U32 buffer_size = STest::Random::lowerUpper(1, 1024); U8 data[buffer_size]; Fw::Buffer buffer(data, buffer_size); + ComCfg::FrameContext context; // Set the mock detector this->mockDetector.set_next_result(FrameDetector::Status::NO_FRAME_DETECTED, 0); // Receive the buffer on dataIn - this->invoke_to_dataIn(0, buffer); + this->invoke_to_dataIn(0, buffer, context); // Checks ASSERT_from_bufferReturnOut_SIZE(1); // input buffer ownership was returned ASSERT_from_frameOut_SIZE(0); // No frame was sent out @@ -83,8 +86,9 @@ void FrameAccumulatorTester ::testReceiveZeroSizeBuffer() { // Prepare a zero size buffer U8 data[1] = {0}; Fw::Buffer buffer(data, 0); + ComCfg::FrameContext context; // Receive the buffer on dataIn - this->invoke_to_dataIn(0, buffer); + this->invoke_to_dataIn(0, buffer, context); // Checks ASSERT_from_bufferReturnOut_SIZE(1); // input buffer ownership was returned ASSERT_from_frameOut_SIZE(0); // No frame was sent out @@ -99,14 +103,15 @@ void FrameAccumulatorTester ::testAccumulateTwoBuffers() { U8 data2[buffer2_size]; Fw::Buffer buffer1(data1, buffer1_size); Fw::Buffer buffer2(data2, buffer2_size); + ComCfg::FrameContext context; this->mockDetector.set_next_result(FrameDetector::Status::MORE_DATA_NEEDED, buffer2_size); // Receive the buffer on dataIn - this->invoke_to_dataIn(0, buffer1); + this->invoke_to_dataIn(0, buffer1, context); // Next result is detection of a full frame, size = buffer1_size + buffer2_size this->mockDetector.set_next_result(FrameDetector::Status::FRAME_DETECTED, buffer1_size + buffer2_size ); // Receive the buffer on dataIn - this->invoke_to_dataIn(0, buffer2); + this->invoke_to_dataIn(0, buffer2, context); // Checks ASSERT_from_bufferReturnOut_SIZE(2); // both input buffers ownership were returned @@ -173,6 +178,7 @@ void FrameAccumulatorTester ::mockAccumulateFullFrame(U32& frame_size, U32& buff U32 buffer_size; Fw::Buffer buffer(data, 0); U32 accumulated_size = 0; + ComCfg::FrameContext context; // Send multiple buffers with MORE_DATA_NEEDED for (U32 i = 0; i < iters; i++) { @@ -181,7 +187,7 @@ void FrameAccumulatorTester ::mockAccumulateFullFrame(U32& frame_size, U32& buff buffer.setSize(buffer_size); // Detector reports MORE_DATA_NEEDED and size needed bigger than accumulated size so far this->mockDetector.set_next_result(FrameDetector::Status::MORE_DATA_NEEDED, accumulated_size + 1); - this->invoke_to_dataIn(0, buffer); + this->invoke_to_dataIn(0, buffer, context); } // Send last buffer with FRAME_DETECTED @@ -191,7 +197,7 @@ void FrameAccumulatorTester ::mockAccumulateFullFrame(U32& frame_size, U32& buff // Send last buffer with finally FRAME_DETECTED and total accumulated + last buffer this->mockDetector.set_next_result(FrameDetector::Status::FRAME_DETECTED, accumulated_size); // Receive the last buffer on dataIn - this->invoke_to_dataIn(0, buffer); + this->invoke_to_dataIn(0, buffer, context); frame_size = accumulated_size; buffer_count = iters + 1; } diff --git a/Svc/Interfaces/ComInterface.fppi b/Svc/Interfaces/ComInterface.fppi index 4d6542ca7f9..137c6718381 100644 --- a/Svc/Interfaces/ComInterface.fppi +++ b/Svc/Interfaces/ComInterface.fppi @@ -6,9 +6,7 @@ sync input port comDataIn: Svc.ComDataWithContext @ Data received from the wire (coming out of the component) -output port comDataOut: Fw.BufferSend -# TODO: problem here: if there's a radio component and no FrameAccumulator needed, -# We likely need comDataOut to be Svc.ComDataWithContext so it can be fed directly into a Deframer ? +output port comDataOut: Svc.ComDataWithContext @ Status of the last transmission output port comStatusOut: Fw.SuccessCondition diff --git a/Svc/Interfaces/FrameAccumulatorInterface.fppi b/Svc/Interfaces/FrameAccumulatorInterface.fppi index 9a1979d1d72..5222b47206c 100644 --- a/Svc/Interfaces/FrameAccumulatorInterface.fppi +++ b/Svc/Interfaces/FrameAccumulatorInterface.fppi @@ -1,5 +1,5 @@ @ Receive raw bytes from a ComInterface (e.g. ComStub) -guarded input port dataIn: Fw.BufferSend +guarded input port dataIn: Svc.ComDataWithContext @ Port for sending an extracted frame out output port frameOut: Svc.ComDataWithContext From e2449af6be5fd03072ab195efa8e9f92b522d1f5 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 30 Apr 2025 17:17:11 -0700 Subject: [PATCH 11/95] Update Ref/RPI topology --- Drv/LinuxUartDriver/LinuxUartDriver.hpp | 2 +- RPI/Top/topology.fpp | 61 ++++++++++++++----------- Ref/Top/topology.fpp | 33 ++++++------- 3 files changed, 52 insertions(+), 44 deletions(-) diff --git a/Drv/LinuxUartDriver/LinuxUartDriver.hpp b/Drv/LinuxUartDriver/LinuxUartDriver.hpp index 936490998e0..e4435190488 100644 --- a/Drv/LinuxUartDriver/LinuxUartDriver.hpp +++ b/Drv/LinuxUartDriver/LinuxUartDriver.hpp @@ -94,7 +94,7 @@ class LinuxUartDriver final : public LinuxUartDriverComponentBase { //! Handler implementation for serialSend //! void send_handler(FwIndexType portNum, /*!< The port number*/ - Fw::Buffer& serBuffer); + Fw::Buffer& serBuffer) override; //! Handler implementation for bufferReturnIn //! diff --git a/RPI/Top/topology.fpp b/RPI/Top/topology.fpp index 750e3b20e17..d19d5ff6df6 100644 --- a/RPI/Top/topology.fpp +++ b/RPI/Top/topology.fpp @@ -63,26 +63,26 @@ module RPI { # ---------------------------------------------------------------------- connections Downlink { - eventLogger.PktSend -> comQueue.comPacketQueueIn[0] - chanTlm.PktSend -> comQueue.comPacketQueueIn[1] + eventLogger.PktSend -> comQueue.comPacketQueueIn[0] + chanTlm.PktSend -> comQueue.comPacketQueueIn[1] fileDownlink.bufferSendOut -> comQueue.bufferQueueIn[0] - comQueue.queueSend -> framer.dataIn + comQueue.queueSend -> framer.dataIn comQueue.bufferReturnOut[0] -> fileDownlink.bufferReturn - framer.dataReturnOut -> comQueue.bufferReturnIn + framer.dataReturnOut -> comQueue.bufferReturnIn[0] - framer.bufferAllocate -> commsBufferManager.bufferGetCallee + framer.bufferAllocate -> commsBufferManager.bufferGetCallee framer.bufferDeallocate -> commsBufferManager.bufferSendIn - framer.dataOut -> comStub.comDataIn - comStub.dataReturnOut -> framer.dataReturnIn + framer.dataOut -> comStub.comDataIn + comStub.dataReturnOut -> framer.dataReturnIn comDriver.dataReturnOut -> comStub.dataReturnIn - comDriver.ready -> comStub.drvConnected + comDriver.ready -> comStub.drvConnected comStub.drvDataOut -> comDriver.$send comStub.comStatusOut -> framer.comStatusIn - framer.comStatusOut -> comQueue.comStatusIn + framer.comStatusOut -> comQueue.comStatusIn } connections FaultProtection { @@ -125,15 +125,6 @@ module RPI { rpiDemo.SpiReadWrite -> spiDrv.SpiReadWrite } - connections MemoryAllocations { - comDriver.allocate -> commsBufferManager.bufferGetCallee - fileUplink.bufferSendOut -> commsBufferManager.bufferSendIn - frameAccumulator.bufferAllocate -> commsBufferManager.bufferGetCallee - frameAccumulator.bufferDeallocate -> commsBufferManager.bufferSendIn - fprimeRouter.bufferDeallocate -> commsBufferManager.bufferSendIn - deframer.bufferDeallocate -> commsBufferManager.bufferSendIn - } - connections UART { rpiDemo.UartBuffers -> uartBufferManager.bufferSendIn rpiDemo.UartWrite -> uartDrv.$send @@ -143,16 +134,32 @@ module RPI { } connections Uplink { - comDriver.$recv -> comStub.drvDataIn - comStub.comDataOut -> frameAccumulator.dataIn - + # ComDriver buffer allocations + comDriver.allocate -> commsBufferManager.bufferGetCallee + comDriver.deallocate -> commsBufferManager.bufferSendIn + # ComDriver <-> ComStub + comDriver.$recv -> comStub.drvDataIn + comStub.bufferReturnOut -> comDriver.bufferReturnIn + # ComStub <-> FrameAccumulator + comStub.comDataOut -> frameAccumulator.dataIn + frameAccumulator.bufferReturnOut -> comStub.bufferReturnIn + # FrameAccumulator buffer allocations + frameAccumulator.bufferDeallocate -> commsBufferManager.bufferSendIn + frameAccumulator.bufferAllocate -> commsBufferManager.bufferGetCallee + # FrameAccumulator <-> Deframer frameAccumulator.frameOut -> deframer.framedIn - deframer.deframedOut -> fprimeRouter.dataIn - - fprimeRouter.commandOut -> cmdDisp.seqCmdBuff - fprimeRouter.fileOut -> fileUplink.bufferSendIn - - cmdDisp.seqCmdStatus -> fprimeRouter.cmdResponseIn + deframer.dataReturnOut -> frameAccumulator.dataReturnIn + # Deframer <-> Router + deframer.deframedOut -> fprimeRouter.dataIn + fprimeRouter.dataReturnOut -> deframer.dataReturnIn + # Router buffer allocations + fprimeRouter.bufferAllocate -> commsBufferManager.bufferGetCallee + fprimeRouter.bufferDeallocate -> commsBufferManager.bufferSendIn + # Router <-> CmdDispatcher/FileUplink + fprimeRouter.commandOut -> cmdDisp.seqCmdBuff + cmdDisp.seqCmdStatus -> fprimeRouter.cmdResponseIn + fprimeRouter.fileOut -> fileUplink.bufferSendIn + fileUplink.bufferSendOut -> fprimeRouter.fileBufferReturnIn } } diff --git a/Ref/Top/topology.fpp b/Ref/Top/topology.fpp index 55adb4c27ef..9ef10fbd018 100644 --- a/Ref/Top/topology.fpp +++ b/Ref/Top/topology.fpp @@ -92,28 +92,29 @@ module Ref { # ---------------------------------------------------------------------- connections Downlink { - dpCat.fileOut -> fileDownlink.SendFile + # Data Products + dpCat.fileOut -> fileDownlink.SendFile fileDownlink.FileComplete -> dpCat.fileDone - - eventLogger.PktSend -> comQueue.comPacketQueueIn[Ports_ComPacketQueue.EVENTS] - tlmSend.PktSend -> comQueue.comPacketQueueIn[Ports_ComPacketQueue.TELEMETRY] - fileDownlink.bufferSendOut -> comQueue.bufferQueueIn[0] + # Inputs to ComQueue (events, telemetry, file) + eventLogger.PktSend -> comQueue.comPacketQueueIn[0] + tlmSend.PktSend -> comQueue.comPacketQueueIn[1] + fileDownlink.bufferSendOut -> comQueue.bufferQueueIn[0] comQueue.bufferReturnOut[0] -> fileDownlink.bufferReturn - - comQueue.queueSend -> fprimeFramer.dataIn + # ComQueue <-> Framer + comQueue.queueSend -> fprimeFramer.dataIn fprimeFramer.dataReturnOut -> comQueue.bufferReturnIn - fprimeFramer.comStatusOut -> comQueue.comStatusIn - - fprimeFramer.bufferAllocate -> commsBufferManager.bufferGetCallee + fprimeFramer.comStatusOut -> comQueue.comStatusIn + # Buffer Management for Framer + fprimeFramer.bufferAllocate -> commsBufferManager.bufferGetCallee fprimeFramer.bufferDeallocate -> commsBufferManager.bufferSendIn - - fprimeFramer.dataOut -> comStub.comDataIn + # Framer <-> ComStub + fprimeFramer.dataOut -> comStub.comDataIn comStub.dataReturnOut -> fprimeFramer.dataReturnIn - comStub.comStatusOut -> fprimeFramer.comStatusIn - - comStub.drvDataOut -> comDriver.$send + comStub.comStatusOut -> fprimeFramer.comStatusIn + # ComStub <-> ComDriver + comStub.drvDataOut -> comDriver.$send comDriver.dataReturnOut -> comStub.dataReturnIn - comDriver.ready -> comStub.drvConnected + comDriver.ready -> comStub.drvConnected } connections FaultProtection { From 84d5afe49aa939efa11aec5de78705709edc12f0 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 30 Apr 2025 17:20:43 -0700 Subject: [PATCH 12/95] Fix spelling --- Svc/FprimeRouter/FprimeRouter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Svc/FprimeRouter/FprimeRouter.cpp b/Svc/FprimeRouter/FprimeRouter.cpp index 2315e241f5d..1c7e30dec55 100644 --- a/Svc/FprimeRouter/FprimeRouter.cpp +++ b/Svc/FprimeRouter/FprimeRouter.cpp @@ -57,7 +57,7 @@ void FprimeRouter ::dataIn_handler(FwIndexType portNum, Fw::Buffer& packetBuffer // If the file uplink output port is connected, send the file packet. Otherwise take no action. if (this->isConnected_fileOut_OutputPort(0)) { // Copy buffer into a new allocated buffer. This lets us return the original buffer with dataReturnOut, - // and FprimeRouter can handle the deallocation of the file buffer when it returns on filebufferReturnIn + // and FprimeRouter can handle the deallocation of the file buffer when it returns on fileBufferReturnIn Fw::Buffer packetBufferCopy = this->bufferAllocate_out(0, packetBuffer.getSize()); auto copySerializer = packetBufferCopy.getSerializer(); status = copySerializer.serialize(packetBuffer.getData(), packetBuffer.getSize(), Fw::Serialization::OMIT_LENGTH); From 57f4c0fa59a00ddcce66a0eaa0b4be64df33a7e8 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 30 Apr 2025 18:03:45 -0700 Subject: [PATCH 13/95] Fix test typo --- Svc/ComStub/test/ut/ComStubTester.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Svc/ComStub/test/ut/ComStubTester.hpp b/Svc/ComStub/test/ut/ComStubTester.hpp index 130f195fedb..508f334b38c 100644 --- a/Svc/ComStub/test/ut/ComStubTester.hpp +++ b/Svc/ComStub/test/ut/ComStubTester.hpp @@ -71,7 +71,9 @@ class ComStubTester : public ComStubGTestBase { //! Handler for from_comDataOut //! void from_comDataOut_handler(const FwIndexType portNum, //!< The port number - Fw::Buffer& recvBuffer); + Fw::Buffer& recvBuffer, + const ComCfg::FrameContext& context //!< The context + ); //! Handler for from_comStatusOut //! From db4d33c6255c65e4acd82d7f23d0ded5cc22a8ee Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 30 Apr 2025 18:12:01 -0700 Subject: [PATCH 14/95] Update Udp component and UTs --- Drv/Udp/Udp.fpp | 2 ++ Drv/Udp/UdpComponentImpl.cpp | 4 ++++ Drv/Udp/UdpComponentImpl.hpp | 18 +++++++++++++----- Drv/Udp/test/ut/UdpTestMain.cpp | 5 +++++ Drv/Udp/test/ut/UdpTester.cpp | 9 +++++++++ Drv/Udp/test/ut/UdpTester.hpp | 3 +++ 6 files changed, 36 insertions(+), 5 deletions(-) diff --git a/Drv/Udp/Udp.fpp b/Drv/Udp/Udp.fpp index 7d49930350a..08f27cf8297 100644 --- a/Drv/Udp/Udp.fpp +++ b/Drv/Udp/Udp.fpp @@ -5,5 +5,7 @@ module Drv { output port allocate: Fw.BufferGet + output port deallocate: Fw.BufferSend + } } diff --git a/Drv/Udp/UdpComponentImpl.cpp b/Drv/Udp/UdpComponentImpl.cpp index 109b29f6427..a0576786032 100644 --- a/Drv/Udp/UdpComponentImpl.cpp +++ b/Drv/Udp/UdpComponentImpl.cpp @@ -103,4 +103,8 @@ void UdpComponentImpl::send_handler(const FwIndexType portNum, Fw::Buffer& fwBuf this->dataReturnOut_out(0, fwBuffer, returnStatus); } +void UdpComponentImpl::bufferReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) { + this->deallocate_out(0, fwBuffer); +} + } // end namespace Drv diff --git a/Drv/Udp/UdpComponentImpl.hpp b/Drv/Udp/UdpComponentImpl.hpp index 38ced2d4731..f511b97d338 100644 --- a/Drv/Udp/UdpComponentImpl.hpp +++ b/Drv/Udp/UdpComponentImpl.hpp @@ -99,7 +99,7 @@ class UdpComponentImpl : public UdpComponentBase, public SocketComponentHelper { * * \return IpSocket reference */ - IpSocket& getSocketHandler(); + IpSocket& getSocketHandler() override; /** * \brief returns a buffer to fill with data @@ -109,7 +109,7 @@ class UdpComponentImpl : public UdpComponentBase, public SocketComponentHelper { * * \return Fw::Buffer to fill with data */ - Fw::Buffer getBuffer(); + Fw::Buffer getBuffer() override; /** * \brief sends a buffer to be filled with data @@ -119,12 +119,12 @@ class UdpComponentImpl : public UdpComponentBase, public SocketComponentHelper { * * \return Fw::Buffer filled with data to send out */ - void sendBuffer(Fw::Buffer buffer, SocketIpStatus status); + void sendBuffer(Fw::Buffer buffer, SocketIpStatus status) override; /** * \brief called when the IPv4 system has been connected */ - void connected(); + void connected() override; PRIVATE: @@ -146,7 +146,15 @@ class UdpComponentImpl : public UdpComponentBase, public SocketComponentHelper { * \param portNum: fprime port number of the incoming port call * \param fwBuffer: buffer containing data to be sent */ - void send_handler(const FwIndexType portNum, Fw::Buffer& fwBuffer); + void send_handler(const FwIndexType portNum, Fw::Buffer& fwBuffer) override; + + + //! Handler implementation for bufferReturnIn + //! + //! Port receiving back ownership of data sent out on $recv port + void bufferReturnIn_handler(FwIndexType portNum, //!< The port number + Fw::Buffer& fwBuffer //!< The buffer + ) override; Drv::UdpSocket m_socket; //!< Socket implementation diff --git a/Drv/Udp/test/ut/UdpTestMain.cpp b/Drv/Udp/test/ut/UdpTestMain.cpp index 606c7ea9084..ca44c2858e5 100644 --- a/Drv/Udp/test/ut/UdpTestMain.cpp +++ b/Drv/Udp/test/ut/UdpTestMain.cpp @@ -24,6 +24,11 @@ TEST(Reconnect, UdpReceiveThreadReconnect) { tester.test_advanced_reconnect(); } +TEST(Reconnect, UdpBufferDeallocation) { + Drv::UdpTester tester; + tester.test_buffer_deallocation(); +} + int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/Drv/Udp/test/ut/UdpTester.cpp b/Drv/Udp/test/ut/UdpTester.cpp index 460b27e59d6..3392e44d15d 100644 --- a/Drv/Udp/test/ut/UdpTester.cpp +++ b/Drv/Udp/test/ut/UdpTester.cpp @@ -158,6 +158,15 @@ void UdpTester ::test_advanced_reconnect() { test_with_loop(10, true); // Up to 10 * RECONNECT_MS } +void UdpTester ::test_buffer_deallocation() { + U8 data[1]; + Fw::Buffer buffer(data, sizeof(data)); + this->invoke_to_bufferReturnIn(0, buffer); + ASSERT_from_deallocate_SIZE(1); // incoming buffer should be deallocated + ASSERT_EQ(this->fromPortHistory_deallocate->at(0).fwBuffer.getData(), data); + ASSERT_EQ(this->fromPortHistory_deallocate->at(0).fwBuffer.getSize(), sizeof(data)); +} + // ---------------------------------------------------------------------- // Handlers for typed from ports // ---------------------------------------------------------------------- diff --git a/Drv/Udp/test/ut/UdpTester.hpp b/Drv/Udp/test/ut/UdpTester.hpp index 85ea3ec1247..1405decef75 100644 --- a/Drv/Udp/test/ut/UdpTester.hpp +++ b/Drv/Udp/test/ut/UdpTester.hpp @@ -69,6 +69,9 @@ namespace Drv { //! void test_advanced_reconnect(); + //! Test buffer deallocation + void test_buffer_deallocation(); + // Helpers void test_with_loop(U32 iterations, bool recv_thread=false); From 52dc98d23e0800984b822481b28f7c48b1416df9 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Thu, 1 May 2025 12:58:22 -0700 Subject: [PATCH 15/95] Rename data ports and standardize "Return" naming pattern --- Drv/ByteStreamDriverModel/docs/sdd.md | 2 +- Drv/Interfaces/ByteStreamDriverInterface.fppi | 4 +- Drv/LinuxUartDriver/LinuxUartDriver.cpp | 4 +- Drv/LinuxUartDriver/LinuxUartDriver.hpp | 4 +- Drv/TcpClient/TcpClientComponentImpl.cpp | 4 +- Drv/TcpClient/TcpClientComponentImpl.hpp | 4 +- Drv/TcpClient/test/ut/TcpClientTester.cpp | 6 +- Drv/TcpServer/TcpServerComponentImpl.cpp | 4 +- Drv/TcpServer/TcpServerComponentImpl.hpp | 4 +- Drv/TcpServer/test/ut/TcpServerTester.cpp | 6 +- Drv/Udp/UdpComponentImpl.cpp | 4 +- Drv/Udp/UdpComponentImpl.hpp | 4 +- Drv/Udp/test/ut/UdpTester.cpp | 6 +- RPI/Top/topology.fpp | 28 +++--- Ref/Top/topology.fpp | 85 ++++++++++--------- Svc/ComQueue/ComQueue.cpp | 8 +- Svc/ComQueue/ComQueue.fpp | 5 +- Svc/ComQueue/ComQueue.hpp | 4 +- Svc/ComQueue/docs/sdd.md | 4 +- Svc/ComQueue/test/ut/ComQueueTestMain.cpp | 2 +- Svc/ComQueue/test/ut/ComQueueTester.cpp | 24 +++--- Svc/ComQueue/test/ut/ComQueueTester.hpp | 2 +- Svc/ComStub/ComStub.cpp | 16 ++-- Svc/ComStub/ComStub.fpp | 16 ++-- Svc/ComStub/ComStub.hpp | 24 +++--- Svc/ComStub/docs/sdd.md | 18 ++-- Svc/ComStub/test/ut/ComStubTester.cpp | 80 ++++++++--------- Svc/ComStub/test/ut/ComStubTester.hpp | 8 +- Svc/FprimeDeframer/FprimeDeframer.cpp | 4 +- Svc/FprimeDeframer/FprimeDeframer.hpp | 2 +- Svc/FprimeDeframer/docs/sdd.md | 12 +-- .../test/ut/FprimeDeframerTester.cpp | 18 ++-- Svc/FrameAccumulator/FrameAccumulator.cpp | 6 +- Svc/FrameAccumulator/FrameAccumulator.hpp | 2 +- Svc/FrameAccumulator/docs/sdd.md | 6 +- .../test/ut/FrameAccumulatorTester.cpp | 38 ++++----- Svc/Interfaces/ComInterface.fppi | 12 +-- Svc/Interfaces/DeframerInterface.fppi | 4 +- Svc/Interfaces/FrameAccumulatorInterface.fppi | 4 +- 39 files changed, 246 insertions(+), 242 deletions(-) diff --git a/Drv/ByteStreamDriverModel/docs/sdd.md b/Drv/ByteStreamDriverModel/docs/sdd.md index 304d1a807cd..2eb17a9c185 100644 --- a/Drv/ByteStreamDriverModel/docs/sdd.md +++ b/Drv/ByteStreamDriverModel/docs/sdd.md @@ -8,7 +8,7 @@ The outgoing stream is represented by the input `send` port; other components ca ### Send The manager component (for example a radio manager) initiates the transfer of send data by calling the "send" port. -The caller will provide a `Fw::Buffer` containing the data to send. The driver component **must** perform a callback on its `dataReturnOut` port to return the status of that send as well as returning ownership of the `Fw::Buffer` to the caller. +The caller will provide a `Fw::Buffer` containing the data to send. The driver component **must** perform a callback on its `sendReturnOut` port to return the status of that send as well as returning ownership of the `Fw::Buffer` to the caller. These responses are an enumeration whose values are described in the following table: | Value | Description | Buffer Ownership | diff --git a/Drv/Interfaces/ByteStreamDriverInterface.fppi b/Drv/Interfaces/ByteStreamDriverInterface.fppi index 7fa4f3e4487..a2d28f765f6 100644 --- a/Drv/Interfaces/ByteStreamDriverInterface.fppi +++ b/Drv/Interfaces/ByteStreamDriverInterface.fppi @@ -8,7 +8,7 @@ guarded input port $send: Fw.BufferSend @ Port returning ownership of data received on $send port - output port dataReturnOut: Drv.ByteStreamData + output port sendReturnOut: Drv.ByteStreamData @ Port receiving back ownership of data sent out on $recv port - sync input port bufferReturnIn: Fw.BufferSend + sync input port recvReturnIn: Fw.BufferSend diff --git a/Drv/LinuxUartDriver/LinuxUartDriver.cpp b/Drv/LinuxUartDriver/LinuxUartDriver.cpp index 9eb4204bac0..baf809c9a3d 100644 --- a/Drv/LinuxUartDriver/LinuxUartDriver.cpp +++ b/Drv/LinuxUartDriver/LinuxUartDriver.cpp @@ -311,11 +311,11 @@ void LinuxUartDriver ::send_handler(const FwIndexType portNum, Fw::Buffer& serBu } } // Return the buffer back to the caller - dataReturnOut_out(0, serBuffer, status); + sendReturnOut_out(0, serBuffer, status); } -void LinuxUartDriver::bufferReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) { +void LinuxUartDriver::recvReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) { this->deallocate_out(0, fwBuffer); } diff --git a/Drv/LinuxUartDriver/LinuxUartDriver.hpp b/Drv/LinuxUartDriver/LinuxUartDriver.hpp index e4435190488..498490f2193 100644 --- a/Drv/LinuxUartDriver/LinuxUartDriver.hpp +++ b/Drv/LinuxUartDriver/LinuxUartDriver.hpp @@ -96,10 +96,10 @@ class LinuxUartDriver final : public LinuxUartDriverComponentBase { void send_handler(FwIndexType portNum, /*!< The port number*/ Fw::Buffer& serBuffer) override; - //! Handler implementation for bufferReturnIn + //! Handler implementation for recvReturnIn //! //! Port receiving back ownership of data sent out on $recv port - void bufferReturnIn_handler(FwIndexType portNum, //!< The port number + void recvReturnIn_handler(FwIndexType portNum, //!< The port number Fw::Buffer& fwBuffer //!< The buffer ) override; diff --git a/Drv/TcpClient/TcpClientComponentImpl.cpp b/Drv/TcpClient/TcpClientComponentImpl.cpp index b1c14e74fe5..e7f0e47231e 100644 --- a/Drv/TcpClient/TcpClientComponentImpl.cpp +++ b/Drv/TcpClient/TcpClientComponentImpl.cpp @@ -91,10 +91,10 @@ void TcpClientComponentImpl::send_handler(const FwIndexType portNum, Fw::Buffer& break; } // Return the buffer and status to the caller - this->dataReturnOut_out(0, fwBuffer, returnStatus); + this->sendReturnOut_out(0, fwBuffer, returnStatus); } -void TcpClientComponentImpl::bufferReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) { +void TcpClientComponentImpl::recvReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) { this->deallocate_out(0, fwBuffer); } diff --git a/Drv/TcpClient/TcpClientComponentImpl.hpp b/Drv/TcpClient/TcpClientComponentImpl.hpp index 26df15461f9..72fcf604bdf 100644 --- a/Drv/TcpClient/TcpClientComponentImpl.hpp +++ b/Drv/TcpClient/TcpClientComponentImpl.hpp @@ -126,10 +126,10 @@ class TcpClientComponentImpl final : public TcpClientComponentBase, public Socke */ void send_handler(const FwIndexType portNum, Fw::Buffer& fwBuffer) override; - //! Handler implementation for bufferReturnIn + //! Handler implementation for recvReturnIn //! //! Port receiving back ownership of data sent out on $recv port - void bufferReturnIn_handler(FwIndexType portNum, //!< The port number + void recvReturnIn_handler(FwIndexType portNum, //!< The port number Fw::Buffer& fwBuffer //!< The buffer ) override; diff --git a/Drv/TcpClient/test/ut/TcpClientTester.cpp b/Drv/TcpClient/test/ut/TcpClientTester.cpp index dbd2631ff82..d5c507d2779 100644 --- a/Drv/TcpClient/test/ut/TcpClientTester.cpp +++ b/Drv/TcpClient/test/ut/TcpClientTester.cpp @@ -80,8 +80,8 @@ void TcpClientTester ::test_with_loop(U32 iterations, bool recv_thread) { m_data_buffer.setSize(sizeof(m_data_storage)); size = Drv::Test::fill_random_buffer(m_data_buffer); invoke_to_send(0, m_data_buffer); - ASSERT_from_dataReturnOut_SIZE(i + 1); - Drv::ByteStreamStatus status = this->fromPortHistory_dataReturnOut->at(i).status; + ASSERT_from_sendReturnOut_SIZE(i + 1); + Drv::ByteStreamStatus status = this->fromPortHistory_sendReturnOut->at(i).status; EXPECT_EQ(status, ByteStreamStatus::OP_OK); Drv::Test::receive_all(server, server_fd, buffer, size); Drv::Test::validate_random_buffer(m_data_buffer, buffer); @@ -183,7 +183,7 @@ void TcpClientTester ::test_no_automatic_recv_connection() { void TcpClientTester ::test_buffer_deallocation() { U8 data[1]; Fw::Buffer buffer(data, sizeof(data)); - this->invoke_to_bufferReturnIn(0, buffer); + this->invoke_to_recvReturnIn(0, buffer); ASSERT_from_deallocate_SIZE(1); // incoming buffer should be deallocated ASSERT_EQ(this->fromPortHistory_deallocate->at(0).fwBuffer.getData(), data); ASSERT_EQ(this->fromPortHistory_deallocate->at(0).fwBuffer.getSize(), sizeof(data)); diff --git a/Drv/TcpServer/TcpServerComponentImpl.cpp b/Drv/TcpServer/TcpServerComponentImpl.cpp index 3709b450507..15137a99e0f 100644 --- a/Drv/TcpServer/TcpServerComponentImpl.cpp +++ b/Drv/TcpServer/TcpServerComponentImpl.cpp @@ -139,10 +139,10 @@ void TcpServerComponentImpl::send_handler(const FwIndexType portNum, Fw::Buffer& break; } // Return the buffer and status to the caller - this->dataReturnOut_out(0, fwBuffer, returnStatus); + this->sendReturnOut_out(0, fwBuffer, returnStatus); } -void TcpServerComponentImpl::bufferReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) { +void TcpServerComponentImpl::recvReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) { this->deallocate_out(0, fwBuffer); } diff --git a/Drv/TcpServer/TcpServerComponentImpl.hpp b/Drv/TcpServer/TcpServerComponentImpl.hpp index 28ac5ecb964..1268e7c73c3 100644 --- a/Drv/TcpServer/TcpServerComponentImpl.hpp +++ b/Drv/TcpServer/TcpServerComponentImpl.hpp @@ -161,10 +161,10 @@ class TcpServerComponentImpl final : public TcpServerComponentBase, public Socke */ void send_handler(const FwIndexType portNum, Fw::Buffer& fwBuffer) override; - //! Handler implementation for bufferReturnIn + //! Handler implementation for recvReturnIn //! //! Port receiving back ownership of data sent out on $recv port - void bufferReturnIn_handler(FwIndexType portNum, //!< The port number + void recvReturnIn_handler(FwIndexType portNum, //!< The port number Fw::Buffer& fwBuffer //!< The buffer ) override; diff --git a/Drv/TcpServer/test/ut/TcpServerTester.cpp b/Drv/TcpServer/test/ut/TcpServerTester.cpp index 4d9f9072102..b064bd926b2 100644 --- a/Drv/TcpServer/test/ut/TcpServerTester.cpp +++ b/Drv/TcpServer/test/ut/TcpServerTester.cpp @@ -81,8 +81,8 @@ void TcpServerTester ::test_with_loop(U32 iterations, bool recv_thread) { m_data_buffer.setSize(sizeof(m_data_storage)); size = Drv::Test::fill_random_buffer(m_data_buffer); invoke_to_send(0, m_data_buffer); - ASSERT_from_dataReturnOut_SIZE(i + 1); - Drv::ByteStreamStatus status = this->fromPortHistory_dataReturnOut->at(i).status; + ASSERT_from_sendReturnOut_SIZE(i + 1); + Drv::ByteStreamStatus status = this->fromPortHistory_sendReturnOut->at(i).status; EXPECT_EQ(status, ByteStreamStatus::OP_OK) << "On iteration: " << i << " and receive thread: " << recv_thread; Drv::Test::receive_all(client, client_fd, buffer, size); @@ -220,7 +220,7 @@ void TcpServerTester ::test_no_automatic_recv_connection() { void TcpServerTester ::test_buffer_deallocation() { U8 data[1]; Fw::Buffer buffer(data, sizeof(data)); - this->invoke_to_bufferReturnIn(0, buffer); + this->invoke_to_recvReturnIn(0, buffer); ASSERT_from_deallocate_SIZE(1); // incoming buffer should be deallocated ASSERT_EQ(this->fromPortHistory_deallocate->at(0).fwBuffer.getData(), data); ASSERT_EQ(this->fromPortHistory_deallocate->at(0).fwBuffer.getSize(), sizeof(data)); diff --git a/Drv/Udp/UdpComponentImpl.cpp b/Drv/Udp/UdpComponentImpl.cpp index a0576786032..d8c9b3c2a73 100644 --- a/Drv/Udp/UdpComponentImpl.cpp +++ b/Drv/Udp/UdpComponentImpl.cpp @@ -100,10 +100,10 @@ void UdpComponentImpl::send_handler(const FwIndexType portNum, Fw::Buffer& fwBuf break; } // Return the buffer and status to the caller - this->dataReturnOut_out(0, fwBuffer, returnStatus); + this->sendReturnOut_out(0, fwBuffer, returnStatus); } -void UdpComponentImpl::bufferReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) { +void UdpComponentImpl::recvReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) { this->deallocate_out(0, fwBuffer); } diff --git a/Drv/Udp/UdpComponentImpl.hpp b/Drv/Udp/UdpComponentImpl.hpp index f511b97d338..77e9d3f083e 100644 --- a/Drv/Udp/UdpComponentImpl.hpp +++ b/Drv/Udp/UdpComponentImpl.hpp @@ -149,10 +149,10 @@ class UdpComponentImpl : public UdpComponentBase, public SocketComponentHelper { void send_handler(const FwIndexType portNum, Fw::Buffer& fwBuffer) override; - //! Handler implementation for bufferReturnIn + //! Handler implementation for recvReturnIn //! //! Port receiving back ownership of data sent out on $recv port - void bufferReturnIn_handler(FwIndexType portNum, //!< The port number + void recvReturnIn_handler(FwIndexType portNum, //!< The port number Fw::Buffer& fwBuffer //!< The buffer ) override; diff --git a/Drv/Udp/test/ut/UdpTester.cpp b/Drv/Udp/test/ut/UdpTester.cpp index 3392e44d15d..9be52e9cb46 100644 --- a/Drv/Udp/test/ut/UdpTester.cpp +++ b/Drv/Udp/test/ut/UdpTester.cpp @@ -92,8 +92,8 @@ void UdpTester::test_with_loop(U32 iterations, bool recv_thread) { m_data_buffer.setSize(sizeof(m_data_storage)); size = Drv::Test::fill_random_buffer(m_data_buffer); invoke_to_send(0, m_data_buffer); - ASSERT_from_dataReturnOut_SIZE(i + 1); - Drv::ByteStreamStatus status = this->fromPortHistory_dataReturnOut->at(i).status; + ASSERT_from_sendReturnOut_SIZE(i + 1); + Drv::ByteStreamStatus status = this->fromPortHistory_sendReturnOut->at(i).status; EXPECT_EQ(status, ByteStreamStatus::OP_OK); Drv::Test::receive_all(udp2, udp2_fd, buffer, size); Drv::Test::validate_random_buffer(m_data_buffer, buffer); @@ -161,7 +161,7 @@ void UdpTester ::test_advanced_reconnect() { void UdpTester ::test_buffer_deallocation() { U8 data[1]; Fw::Buffer buffer(data, sizeof(data)); - this->invoke_to_bufferReturnIn(0, buffer); + this->invoke_to_recvReturnIn(0, buffer); ASSERT_from_deallocate_SIZE(1); // incoming buffer should be deallocated ASSERT_EQ(this->fromPortHistory_deallocate->at(0).fwBuffer.getData(), data); ASSERT_EQ(this->fromPortHistory_deallocate->at(0).fwBuffer.getSize(), sizeof(data)); diff --git a/RPI/Top/topology.fpp b/RPI/Top/topology.fpp index d19d5ff6df6..88fd5ef7558 100644 --- a/RPI/Top/topology.fpp +++ b/RPI/Top/topology.fpp @@ -66,20 +66,20 @@ module RPI { eventLogger.PktSend -> comQueue.comPacketQueueIn[0] chanTlm.PktSend -> comQueue.comPacketQueueIn[1] fileDownlink.bufferSendOut -> comQueue.bufferQueueIn[0] - - comQueue.queueSend -> framer.dataIn comQueue.bufferReturnOut[0] -> fileDownlink.bufferReturn - framer.dataReturnOut -> comQueue.bufferReturnIn[0] + + comQueue.dataOut -> framer.dataIn + framer.dataReturnOut -> comQueue.dataReturnIn framer.bufferAllocate -> commsBufferManager.bufferGetCallee framer.bufferDeallocate -> commsBufferManager.bufferSendIn - framer.dataOut -> comStub.comDataIn + framer.dataOut -> comStub.dataIn comStub.dataReturnOut -> framer.dataReturnIn - comDriver.dataReturnOut -> comStub.dataReturnIn - comDriver.ready -> comStub.drvConnected - comStub.drvDataOut -> comDriver.$send + comStub.drvSendOut -> comDriver.$send + comDriver.sendReturnOut -> comStub.drvSendReturnIn + comDriver.ready -> comStub.drvConnected comStub.comStatusOut -> framer.comStatusIn framer.comStatusOut -> comQueue.comStatusIn @@ -130,7 +130,7 @@ module RPI { rpiDemo.UartWrite -> uartDrv.$send uartDrv.$recv -> rpiDemo.UartRead uartDrv.allocate -> uartBufferManager.bufferGetCallee - uartDrv.dataReturnOut -> rpiDemo.UartWriteReturn + uartDrv.sendReturnOut -> rpiDemo.UartWriteReturn } connections Uplink { @@ -138,19 +138,19 @@ module RPI { comDriver.allocate -> commsBufferManager.bufferGetCallee comDriver.deallocate -> commsBufferManager.bufferSendIn # ComDriver <-> ComStub - comDriver.$recv -> comStub.drvDataIn - comStub.bufferReturnOut -> comDriver.bufferReturnIn + comDriver.$recv -> comStub.drvReceiveIn + comStub.drvReceiveReturnOut -> comDriver.recvReturnIn # ComStub <-> FrameAccumulator - comStub.comDataOut -> frameAccumulator.dataIn - frameAccumulator.bufferReturnOut -> comStub.bufferReturnIn + comStub.dataOut -> frameAccumulator.dataIn + frameAccumulator.dataReturnOut -> comStub.dataReturnIn # FrameAccumulator buffer allocations frameAccumulator.bufferDeallocate -> commsBufferManager.bufferSendIn frameAccumulator.bufferAllocate -> commsBufferManager.bufferGetCallee # FrameAccumulator <-> Deframer - frameAccumulator.frameOut -> deframer.framedIn + frameAccumulator.dataOut -> deframer.dataIn deframer.dataReturnOut -> frameAccumulator.dataReturnIn # Deframer <-> Router - deframer.deframedOut -> fprimeRouter.dataIn + deframer.dataOut -> fprimeRouter.dataIn fprimeRouter.dataReturnOut -> deframer.dataReturnIn # Router buffer allocations fprimeRouter.bufferAllocate -> commsBufferManager.bufferGetCallee diff --git a/Ref/Top/topology.fpp b/Ref/Top/topology.fpp index 9ef10fbd018..7d617cd2bec 100644 --- a/Ref/Top/topology.fpp +++ b/Ref/Top/topology.fpp @@ -15,6 +15,10 @@ module Ref { TELEMETRY } + enum Ports_ComBufferQueue { + FILE_DOWNLINK + } + topology Ref { # ---------------------------------------------------------------------- @@ -96,25 +100,55 @@ module Ref { dpCat.fileOut -> fileDownlink.SendFile fileDownlink.FileComplete -> dpCat.fileDone # Inputs to ComQueue (events, telemetry, file) - eventLogger.PktSend -> comQueue.comPacketQueueIn[0] - tlmSend.PktSend -> comQueue.comPacketQueueIn[1] - fileDownlink.bufferSendOut -> comQueue.bufferQueueIn[0] - comQueue.bufferReturnOut[0] -> fileDownlink.bufferReturn + eventLogger.PktSend -> comQueue.comPacketQueueIn[Ports_ComPacketQueue.EVENTS] + tlmSend.PktSend -> comQueue.comPacketQueueIn[Ports_ComPacketQueue.TELEMETRY] + fileDownlink.bufferSendOut -> comQueue.bufferQueueIn[Ports_ComBufferQueue.FILE_DOWNLINK] + comQueue.bufferReturnOut[Ports_ComBufferQueue.FILE_DOWNLINK] -> fileDownlink.bufferReturn # ComQueue <-> Framer - comQueue.queueSend -> fprimeFramer.dataIn - fprimeFramer.dataReturnOut -> comQueue.bufferReturnIn - fprimeFramer.comStatusOut -> comQueue.comStatusIn + comQueue.dataOut -> fprimeFramer.dataIn + fprimeFramer.dataReturnOut -> comQueue.dataReturnIn # Buffer Management for Framer fprimeFramer.bufferAllocate -> commsBufferManager.bufferGetCallee fprimeFramer.bufferDeallocate -> commsBufferManager.bufferSendIn # Framer <-> ComStub - fprimeFramer.dataOut -> comStub.comDataIn + fprimeFramer.dataOut -> comStub.dataIn comStub.dataReturnOut -> fprimeFramer.dataReturnIn - comStub.comStatusOut -> fprimeFramer.comStatusIn # ComStub <-> ComDriver - comStub.drvDataOut -> comDriver.$send - comDriver.dataReturnOut -> comStub.dataReturnIn + comStub.drvSendOut -> comDriver.$send + comDriver.sendReturnOut -> comStub.drvSendReturnIn comDriver.ready -> comStub.drvConnected + # ComStatus + comStub.comStatusOut -> fprimeFramer.comStatusIn + fprimeFramer.comStatusOut -> comQueue.comStatusIn + } + + connections Uplink { + # ComDriver buffer allocations + comDriver.allocate -> commsBufferManager.bufferGetCallee + comDriver.deallocate -> commsBufferManager.bufferSendIn + # ComDriver <-> ComStub + comDriver.$recv -> comStub.drvReceiveIn + comStub.drvReceiveReturnOut -> comDriver.recvReturnIn + # ComStub <-> FrameAccumulator + comStub.dataOut -> frameAccumulator.dataIn + frameAccumulator.dataReturnOut -> comStub.dataReturnIn + # FrameAccumulator buffer allocations + frameAccumulator.bufferDeallocate -> commsBufferManager.bufferSendIn + frameAccumulator.bufferAllocate -> commsBufferManager.bufferGetCallee + # FrameAccumulator <-> Deframer + frameAccumulator.dataOut -> deframer.dataIn + deframer.dataReturnOut -> frameAccumulator.dataReturnIn + # Deframer <-> Router + deframer.dataOut -> fprimeRouter.dataIn + fprimeRouter.dataReturnOut -> deframer.dataReturnIn + # Router buffer allocations + fprimeRouter.bufferAllocate -> commsBufferManager.bufferGetCallee + fprimeRouter.bufferDeallocate -> commsBufferManager.bufferSendIn + # Router <-> CmdDispatcher/FileUplink + fprimeRouter.commandOut -> cmdDisp.seqCmdBuff + cmdDisp.seqCmdStatus -> fprimeRouter.cmdResponseIn + fprimeRouter.fileOut -> fileUplink.bufferSendIn + fileUplink.bufferSendOut -> fprimeRouter.fileBufferReturnIn } connections FaultProtection { @@ -163,35 +197,6 @@ module Ref { cmdDisp.seqCmdStatus -> cmdSeq.cmdResponseIn } - connections Uplink { - # ComDriver buffer allocations - comDriver.allocate -> commsBufferManager.bufferGetCallee - comDriver.deallocate -> commsBufferManager.bufferSendIn - # ComDriver <-> ComStub - comDriver.$recv -> comStub.drvDataIn - comStub.bufferReturnOut -> comDriver.bufferReturnIn - # ComStub <-> FrameAccumulator - comStub.comDataOut -> frameAccumulator.dataIn - frameAccumulator.bufferReturnOut -> comStub.bufferReturnIn - # FrameAccumulator buffer allocations - frameAccumulator.bufferDeallocate -> commsBufferManager.bufferSendIn - frameAccumulator.bufferAllocate -> commsBufferManager.bufferGetCallee - # FrameAccumulator <-> Deframer - frameAccumulator.frameOut -> deframer.framedIn - deframer.dataReturnOut -> frameAccumulator.dataReturnIn - # Deframer <-> Router - deframer.deframedOut -> fprimeRouter.dataIn - fprimeRouter.dataReturnOut -> deframer.dataReturnIn - # Router buffer allocations - fprimeRouter.bufferAllocate -> commsBufferManager.bufferGetCallee - fprimeRouter.bufferDeallocate -> commsBufferManager.bufferSendIn - # Router <-> CmdDispatcher/FileUplink - fprimeRouter.commandOut -> cmdDisp.seqCmdBuff - cmdDisp.seqCmdStatus -> fprimeRouter.cmdResponseIn - fprimeRouter.fileOut -> fileUplink.bufferSendIn - fileUplink.bufferSendOut -> fprimeRouter.fileBufferReturnIn - } - connections DataProducts { # DpMgr and DpWriter connections. Have explicit port indexes for demo dpMgr.bufferGetOut[0] -> dpBufferManager.bufferGetCallee diff --git a/Svc/ComQueue/ComQueue.cpp b/Svc/ComQueue/ComQueue.cpp index 7a779c96876..8526abf64b4 100644 --- a/Svc/ComQueue/ComQueue.cpp +++ b/Svc/ComQueue/ComQueue.cpp @@ -193,7 +193,7 @@ void ComQueue::run_handler(const FwIndexType portNum, U32 context) { this->tlmWrite_buffQueueDepth(buffQueueDepth); } -void ComQueue ::bufferReturnIn_handler(FwIndexType portNum, +void ComQueue ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { static_assert(std::numeric_limits::is_signed, "FwIndexType must be signed"); @@ -205,7 +205,7 @@ void ComQueue ::bufferReturnIn_handler(FwIndexType portNum, // Failing this assert means that context.apid was modified since ComQueue set it, which should not happen FW_ASSERT(bufferReturnPortNum < BUFFER_PORT_COUNT, static_cast(bufferReturnPortNum)); if (bufferReturnPortNum >= 0) { - // It is a coding error not to connect the associated bufferReturnOut port for each bufferReturnIn port + // It is a coding error not to connect the associated bufferReturnOut port for each dataReturnIn port FW_ASSERT(this->isConnected_bufferReturnOut_OutputPort(bufferReturnPortNum), static_cast(bufferReturnPortNum)); // If this is a buffer port, return the buffer to the BufferDownlink this->bufferReturnOut_out(bufferReturnPortNum, data); @@ -263,7 +263,7 @@ void ComQueue::sendComBuffer(Fw::ComBuffer& comBuffer, FwIndexType queueIndex) { // Context APID is set to the queue index for now. A future implementation may want this to be configurable ComCfg::FrameContext context; context.setcomQueueIndex(queueIndex); - this->queueSend_out(0, outBuffer, context); + this->dataOut_out(0, outBuffer, context); // Set state to WAITING for the status to come back this->m_state = WAITING; } @@ -275,7 +275,7 @@ void ComQueue::sendBuffer(Fw::Buffer& buffer, FwIndexType queueIndex) { // Context APID is set to the queue index for now. A future implementation may want this to be configurable ComCfg::FrameContext context; context.setcomQueueIndex(queueIndex); - this->queueSend_out(0, buffer, context); + this->dataOut_out(0, buffer, context); // Set state to WAITING for the status to come back this->m_state = WAITING; diff --git a/Svc/ComQueue/ComQueue.fpp b/Svc/ComQueue/ComQueue.fpp index ad85de3f706..37b18403b91 100644 --- a/Svc/ComQueue/ComQueue.fpp +++ b/Svc/ComQueue/ComQueue.fpp @@ -17,7 +17,7 @@ module Svc { # ---------------------------------------------------------------------- @ Port for emitting data ready to be sent - output port queueSend: Svc.ComDataWithContext + output port dataOut: Svc.ComDataWithContext @ Port for receiving the status signal async input port comStatusIn: Fw.SuccessCondition @@ -31,9 +31,8 @@ module Svc { @ Port array for returning ownership of Fw::Buffer to its original sender output port bufferReturnOut: [ComQueueBufferPorts] Fw.BufferSend - # It is appropriate for this port to be sync since it is just a passthrough @ Port for receiving Fw::Buffer whose ownership needs to be handed back - sync input port bufferReturnIn: Svc.ComDataWithContext + sync input port dataReturnIn: Svc.ComDataWithContext @ Port for scheduling telemetry output async input port run: Svc.Sched drop diff --git a/Svc/ComQueue/ComQueue.hpp b/Svc/ComQueue/ComQueue.hpp index 92d35ffa4e5..86ae9251784 100644 --- a/Svc/ComQueue/ComQueue.hpp +++ b/Svc/ComQueue/ComQueue.hpp @@ -148,10 +148,10 @@ class ComQueue final : public ComQueueComponentBase { U32 context /*! [!NOTE] diff --git a/Svc/ComQueue/test/ut/ComQueueTestMain.cpp b/Svc/ComQueue/test/ut/ComQueueTestMain.cpp index 0506b577404..858a6d6d7b3 100644 --- a/Svc/ComQueue/test/ut/ComQueueTestMain.cpp +++ b/Svc/ComQueue/test/ut/ComQueueTestMain.cpp @@ -6,7 +6,7 @@ TEST(Nominal, Send) { Svc::ComQueueTester tester; - tester.testQueueSend(); + tester.testdataOut(); } TEST(Nominal, Pause) { diff --git a/Svc/ComQueue/test/ut/ComQueueTester.cpp b/Svc/ComQueue/test/ut/ComQueueTester.cpp index 540973879eb..c5cdb558dfb 100644 --- a/Svc/ComQueue/test/ut/ComQueueTester.cpp +++ b/Svc/ComQueue/test/ut/ComQueueTester.cpp @@ -68,7 +68,7 @@ void ComQueueTester ::emitOneAndCheck(FwIndexType expectedIndex, FwSizeType expectedSize) { emitOne(); // Check that the data buffers are identical (size + data) - Fw::Buffer emittedBuffer = this->fromPortHistory_queueSend->at(expectedIndex).data; + Fw::Buffer emittedBuffer = this->fromPortHistory_dataOut->at(expectedIndex).data; ASSERT_EQ(expectedSize, emittedBuffer.getSize()); for (FwSizeType i = 0; i < expectedSize; i++) { ASSERT_EQ(emittedBuffer.getData()[i], expectedData[i]); @@ -79,7 +79,7 @@ void ComQueueTester ::emitOneAndCheck(FwIndexType expectedIndex, // Tests // ---------------------------------------------------------------------- -void ComQueueTester ::testQueueSend() { +void ComQueueTester ::testdataOut() { U8 data[BUFFER_LENGTH] = {0xde, 0xad, 0xbe}; Fw::ComBuffer comBuffer(&data[0], sizeof(data)); Fw::Buffer buffer(&data[0], sizeof(data)); @@ -158,17 +158,17 @@ void ComQueueTester ::testPrioritySend() { } // Check that nothing has yet been sent - ASSERT_from_queueSend_SIZE(0); + ASSERT_from_dataOut_SIZE(0); for (FwIndexType index = 0; index < ComQueue::TOTAL_PORT_COUNT; index++) { U8 orderKey; - U32 previousSize = fromPortHistory_queueSend->size(); + U32 previousSize = fromPortHistory_dataOut->size(); emitOne(); - ASSERT_EQ(fromPortHistory_queueSend->size(), (index + 1)); + ASSERT_EQ(fromPortHistory_dataOut->size(), (index + 1)); // Check that the size changed by exactly one - ASSERT_EQ(fromPortHistory_queueSend->size(), (previousSize + 1)); + ASSERT_EQ(fromPortHistory_dataOut->size(), (previousSize + 1)); - orderKey = fromPortHistory_queueSend->at(index).data.getData()[0]; + orderKey = fromPortHistory_dataOut->at(index).data.getData()[0]; ASSERT_EQ(orderKey, index); } clearFromPortHistory(); @@ -295,7 +295,7 @@ void ComQueueTester ::testReadyFirst() { invoke_to_comPacketQueueIn(portNum, comBuffer, 0); dispatchAll(); - Fw::Buffer emittedBuffer = this->fromPortHistory_queueSend->at(portNum).data; + Fw::Buffer emittedBuffer = this->fromPortHistory_dataOut->at(portNum).data; ASSERT_EQ(emittedBuffer.getSize(), comBuffer.getBuffLength()); for (FwSizeType i = 0; i < emittedBuffer.getSize(); i++) { ASSERT_EQ(emittedBuffer.getData()[i], comBuffer.getBuffAddr()[i]); @@ -307,7 +307,7 @@ void ComQueueTester ::testReadyFirst() { emitOne(); invoke_to_bufferQueueIn(portNum, buffer); dispatchAll(); - Fw::Buffer emittedBuffer = this->fromPortHistory_queueSend->at(portNum).data; + Fw::Buffer emittedBuffer = this->fromPortHistory_dataOut->at(portNum).data; ASSERT_EQ(emittedBuffer.getSize(), buffer.getSize()); for (FwSizeType i = 0; i < buffer.getSize(); i++) { ASSERT_EQ(buffer.getData()[i], emittedBuffer.getData()[i]); @@ -328,7 +328,7 @@ void ComQueueTester ::testContextData() { emitOne(); // Currently, the APID is set to the queue index, which is the same as the port number for COM ports FwIndexType expectedApid = portNum; - auto emittedContext = this->fromPortHistory_queueSend->at(portNum).context; + auto emittedContext = this->fromPortHistory_dataOut->at(portNum).context; ASSERT_EQ(expectedApid, emittedContext.getcomQueueIndex()); } clearFromPortHistory(); @@ -338,7 +338,7 @@ void ComQueueTester ::testContextData() { emitOne(); // APID is queue index, which is COM_PORT_COUNT + portNum for BUFFER ports FwIndexType expectedApid = portNum + ComQueue::COM_PORT_COUNT; - auto emittedContext = this->fromPortHistory_queueSend->at(portNum).context; + auto emittedContext = this->fromPortHistory_dataOut->at(portNum).context; ASSERT_EQ(expectedApid, emittedContext.getcomQueueIndex()); } clearFromPortHistory(); @@ -354,7 +354,7 @@ void ComQueueTester ::testBufferQueueReturn() { for(FwIndexType portNum = 0; portNum < ComQueue::TOTAL_PORT_COUNT; portNum++){ clearFromPortHistory(); context.setcomQueueIndex(portNum); - invoke_to_bufferReturnIn(0, buffer, context); + invoke_to_dataReturnIn(0, buffer, context); // APIDs that correspond to an buffer originating from a Fw.Com port // do no get deallocated – APIDs that correspond to a Fw.Buffer do if (portNum < ComQueue::COM_PORT_COUNT) { diff --git a/Svc/ComQueue/test/ut/ComQueueTester.hpp b/Svc/ComQueue/test/ut/ComQueueTester.hpp index 78b2e42d520..1dd2f25b363 100644 --- a/Svc/ComQueue/test/ut/ComQueueTester.hpp +++ b/Svc/ComQueue/test/ut/ComQueueTester.hpp @@ -66,7 +66,7 @@ class ComQueueTester : public ComQueueGTestBase { // Tests // ---------------------------------------------------------------------- - void testQueueSend(); + void testdataOut(); void testQueuePause(); diff --git a/Svc/ComStub/ComStub.cpp b/Svc/ComStub/ComStub.cpp index 0b80361a09d..464a355ab3b 100644 --- a/Svc/ComStub/ComStub.cpp +++ b/Svc/ComStub/ComStub.cpp @@ -23,10 +23,10 @@ ComStub::~ComStub() {} // Handler implementations for user-defined typed input ports // ---------------------------------------------------------------------- -void ComStub::comDataIn_handler(const FwIndexType portNum, Fw::Buffer& sendBuffer, const ComCfg::FrameContext& context) { +void ComStub::dataIn_handler(const FwIndexType portNum, Fw::Buffer& sendBuffer, const ComCfg::FrameContext& context) { FW_ASSERT(!this->m_reinitialize || !this->isConnected_comStatusOut_OutputPort(0)); // A message should never get here if we need to reinitialize is needed this->m_storedContext = context; // Store the context of the current message - this->drvDataOut_out(0, sendBuffer); + this->drvSendOut_out(0, sendBuffer); } void ComStub::drvConnected_handler(const FwIndexType portNum) { @@ -37,16 +37,16 @@ void ComStub::drvConnected_handler(const FwIndexType portNum) { } } -void ComStub::drvDataIn_handler(const FwIndexType portNum, +void ComStub::drvReceiveIn_handler(const FwIndexType portNum, Fw::Buffer& recvBuffer, const Drv::ByteStreamStatus& recvStatus) { if (recvStatus.e == Drv::ByteStreamStatus::OP_OK) { ComCfg::FrameContext emptyContext; // ComStub knows nothing about the received bytes, so use an empty context - this->comDataOut_out(0, recvBuffer, emptyContext); + this->dataOut_out(0, recvBuffer, emptyContext); } } -void ComStub ::dataReturnIn_handler(FwIndexType portNum, //!< The port number +void ComStub ::drvSendReturnIn_handler(FwIndexType portNum, //!< The port number Fw::Buffer& fwBuffer, //!< The buffer const Drv::ByteStreamStatus& sendStatus) { if (sendStatus != Drv::ByteStreamStatus::SEND_RETRY) { @@ -61,7 +61,7 @@ void ComStub ::dataReturnIn_handler(FwIndexType portNum, //!< The port number if (this->m_retry_count < this->RETRY_LIMIT) { // If we have not yet retried more than the retry limit, attempt to retry this->m_retry_count++; - this->drvDataOut_out(0, fwBuffer); + this->drvSendOut_out(0, fwBuffer); } else { // If retried too many times, return buffer and log failure this->dataReturnOut_out(0, fwBuffer, this->m_storedContext); @@ -71,8 +71,8 @@ void ComStub ::dataReturnIn_handler(FwIndexType portNum, //!< The port number } } -void ComStub ::bufferReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) { - this->bufferReturnOut_out(0, fwBuffer); +void ComStub ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer, const ComCfg::FrameContext& context) { + this->drvReceiveReturnOut_out(0, fwBuffer); } } // end namespace Svc diff --git a/Svc/ComStub/ComStub.fpp b/Svc/ComStub/ComStub.fpp index 9fe20dbd544..a317f62b86c 100644 --- a/Svc/ComStub/ComStub.fpp +++ b/Svc/ComStub/ComStub.fpp @@ -10,17 +10,17 @@ module Svc { @ Ready signal when driver is connected sync input port drvConnected: Drv.ByteStreamReady - @ Receive (read) data from driver. This gets forwarded to comDataOut - sync input port drvDataIn: Drv.ByteStreamData + @ Receive (read) data from driver. This gets forwarded to dataOut + sync input port drvReceiveIn: Drv.ByteStreamData - @ Send (write) data to the driver. This gets invoked on comDataIn invocation - output port drvDataOut: Fw.BufferSend + @ Send (write) data to the driver. This gets invoked on dataIn invocation + output port drvSendOut: Fw.BufferSend - @ Callback from drvDataOut (retrieving status and ownership of sent buffer) - sync input port dataReturnIn: Drv.ByteStreamData + @ Callback from drvSendOut (retrieving status and ownership of sent buffer) + sync input port drvSendReturnIn: Drv.ByteStreamData - @ Returning ownership of buffer that came in on drvDataIn - output port bufferReturnOut: Fw.BufferSend + @ Returning ownership of buffer that came in on drvReceiveIn + output port drvReceiveReturnOut: Fw.BufferSend } } diff --git a/Svc/ComStub/ComStub.hpp b/Svc/ComStub/ComStub.hpp index 421f70f42d8..8afeff86124 100644 --- a/Svc/ComStub/ComStub.hpp +++ b/Svc/ComStub/ComStub.hpp @@ -35,11 +35,11 @@ class ComStub final : public ComStubComponentBase { // Handler implementations for user-defined typed input ports // ---------------------------------------------------------------------- - //! Handler implementation for comDataIn + //! Handler implementation for dataIn //! //! Comms data is coming in meaning there is a request for ComStub to send data on the wire //! For ComStub, this means we send the data to the underlying driver (e.g. TCP/UDP/UART) - void comDataIn_handler(const FwIndexType portNum, /*!< The port number*/ + void dataIn_handler(const FwIndexType portNum, /*!< The port number*/ Fw::Buffer& sendBuffer, const ComCfg::FrameContext& context) override; @@ -47,25 +47,25 @@ class ComStub final : public ComStubComponentBase { //! void drvConnected_handler(const FwIndexType portNum) override; - //! Handler implementation for drvDataIn + //! Handler implementation for drvReceiveIn //! //! Data is coming in from the driver (meaning it has been read from the wire). - //! ComStub forwards this to the comDataOut port - void drvDataIn_handler(const FwIndexType portNum, + //! ComStub forwards this to the dataOut port + void drvReceiveIn_handler(const FwIndexType portNum, /*!< The port number*/ Fw::Buffer& recvBuffer, const Drv::ByteStreamStatus& recvStatus) override; - //! Handler implementation for bufferReturnIn + //! Handler implementation for dataReturnIn //! - //! Port receiving back ownership of buffer sent out on comDataOut - void bufferReturnIn_handler(FwIndexType portNum, //!< The port number - Fw::Buffer& fwBuffer //!< The buffer - ) override; + //! Port receiving back ownership of buffer sent out on dataOut + void dataReturnIn_handler(FwIndexType portNum, //!< The port number + Fw::Buffer& fwBuffer, //!< The buffer + const ComCfg::FrameContext& context) override; - //! Handler implementation for dataReturnIn + //! Handler implementation for drvSendReturnIn //! //! Buffer ownership and status returning from a Driver "send" operation - void dataReturnIn_handler(FwIndexType portNum, //!< The port number + void drvSendReturnIn_handler(FwIndexType portNum, //!< The port number Fw::Buffer& fwBuffer, //!< The buffer const Drv::ByteStreamStatus& recvStatus) override; diff --git a/Svc/ComStub/docs/sdd.md b/Svc/ComStub/docs/sdd.md index fe1c157ef5c..25cc8c492bf 100644 --- a/Svc/ComStub/docs/sdd.md +++ b/Svc/ComStub/docs/sdd.md @@ -55,17 +55,17 @@ be useful | Kind | Name | Port Type | Usage | |--------------|----------------|-----------------------|-----------------------------------------------------------------------------------| -| `sync input` | `comDataIn` | `Svc.ComDataWithContext` | Port receiving `Fw::Buffer`s for transmission out `drvDataOut` | +| `sync input` | `dataIn` | `Svc.ComDataWithContext` | Port receiving `Fw::Buffer`s for transmission out `drvSendOut` | | `output` | `comStatusOut` | `Svc.ComStatus` | Port indicating success or failure to attached `Svc::ComQueue` | -| `output` | `comDataOut` | `Drv.ByteStreamRecv` | Port providing received `Fw::Buffers` to a potential `Svc::Deframer` | +| `output` | `dataOut` | `Drv.ByteStreamRecv` | Port providing received `Fw::Buffers` to a potential `Svc::Deframer` | **Byte Stream Driver Model Ports** | Kind | Name | Port Type | Usage | |--------------|----------------|-----------------------|-----------------------------------------------------------------------------------| | `sync input` | `drvConnected` | `Drv.ByteStreamReady` | Port called when the underlying driver has connected | -| `sync input` | `drvDataIn` | `Drv.ByteStreamRecv` | Port receiving `Fw::Buffers` from underlying communications bus driver | -| `output` | `drvDataOut` | `Drv.ByteStreamSend` | Port providing received `Fw::Buffers` to the underlying communications bus driver | +| `sync input` | `drvReceiveIn` | `Drv.ByteStreamRecv` | Port receiving `Fw::Buffers` from underlying communications bus driver | +| `output` | `drvSendOut` | `Drv.ByteStreamSend` | Port providing received `Fw::Buffers` to the underlying communications bus driver | ### 4.2. State, Configuration, and Runtime Setup @@ -76,11 +76,11 @@ response to a driver reconnection event. This is to implement the Communication ### 4.3. Port Handlers -#### 4.3.1 comDataIn +#### 4.3.1 dataIn -The `comDataIn` port handler receives an `Fw::Buffer` from the F´ system for transmission to the ground. Typically, it +The `dataIn` port handler receives an `Fw::Buffer` from the F´ system for transmission to the ground. Typically, it is connected to the output of the `Svc::Framer` component. In this `Svc::ComStub` implementation, it passes this -`Fw::Buffer` directly to the `drvDataOut` port. It will retry when that port responds with a `RETRY` request. Otherwise, +`Fw::Buffer` directly to the `drvSendOut` port. It will retry when that port responds with a `RETRY` request. Otherwise, the `comStatusOut` port will be invoked to indicate success or failure. Retries attempts are limited before the port asserts. @@ -89,7 +89,7 @@ asserts. This port receives the connected signal from the driver and responds with exactly one `READY` invocation to the `comStatusOut` port. This starts downlink. This occurs each time the driver reconnects. -#### 4.3.1 drvDataIn +#### 4.3.1 drvReceiveIn -The `drvDataIn` handler receives data read from the driver and supplies it out the `comDataOut` port. It is usually +The `drvReceiveIn` handler receives data read from the driver and supplies it out the `dataOut` port. It is usually connected to the `Svc::Deframer` component diff --git a/Svc/ComStub/test/ut/ComStubTester.cpp b/Svc/ComStub/test/ut/ComStubTester.cpp index 14adee34f12..e7d202ac4af 100644 --- a/Svc/ComStub/test/ut/ComStubTester.cpp +++ b/Svc/ComStub/test/ut/ComStubTester.cpp @@ -55,15 +55,15 @@ void ComStubTester ::test_basic() { this->fill(buffer); // Downlink - invoke_to_comDataIn(0, buffer, context); - ASSERT_from_drvDataOut_SIZE(1); - ASSERT_from_drvDataOut(0, buffer); + invoke_to_dataIn(0, buffer, context); + ASSERT_from_drvSendOut_SIZE(1); + ASSERT_from_drvSendOut(0, buffer); // Uplink ComCfg::FrameContext emptyContext; - invoke_to_drvDataIn(0, buffer, Drv::ByteStreamStatus::OP_OK); - ASSERT_from_comDataOut_SIZE(1); - ASSERT_from_comDataOut(0, buffer, emptyContext); + invoke_to_drvReceiveIn(0, buffer, Drv::ByteStreamStatus::OP_OK); + ASSERT_from_dataOut_SIZE(1); + ASSERT_from_dataOut(0, buffer, emptyContext); } void ComStubTester ::test_fail() { @@ -76,13 +76,13 @@ void ComStubTester ::test_fail() { ComCfg::FrameContext context; // Downlink - invoke_to_comDataIn(0, buffer, context); - ASSERT_from_drvDataOut_SIZE(1); - ASSERT_from_drvDataOut(0, buffer); + invoke_to_dataIn(0, buffer, context); + ASSERT_from_drvSendOut_SIZE(1); + ASSERT_from_drvSendOut(0, buffer); // Uplink - invoke_to_drvDataIn(0, buffer, Drv::ByteStreamStatus::OTHER_ERROR); - ASSERT_from_comDataOut_SIZE(0); // receiving failure should not send anything + invoke_to_drvReceiveIn(0, buffer, Drv::ByteStreamStatus::OTHER_ERROR); + ASSERT_from_dataOut_SIZE(0); // receiving failure should not send anything } void ComStubTester ::test_retry() { @@ -100,16 +100,16 @@ void ComStubTester ::test_retry() { } // Retrying for as many times as the RETRY_LIMIT should be ok for (FwIndexType i = 0; i < this->component.RETRY_LIMIT; i++) { - invoke_to_dataReturnIn(0, buffers[i], Drv::ByteStreamStatus::SEND_RETRY); - // Test we have indeed retried (data sent on drvDataOut) - ASSERT_from_drvDataOut_SIZE(static_cast(i + 1)); - ASSERT_from_drvDataOut(static_cast(i), buffers[i]); + invoke_to_drvSendReturnIn(0, buffers[i], Drv::ByteStreamStatus::SEND_RETRY); + // Test we have indeed retried (data sent on drvSendOut) + ASSERT_from_drvSendOut_SIZE(static_cast(i + 1)); + ASSERT_from_drvSendOut(static_cast(i), buffers[i]); } - ASSERT_from_drvDataOut_SIZE(static_cast(this->component.RETRY_LIMIT)); + ASSERT_from_drvSendOut_SIZE(static_cast(this->component.RETRY_LIMIT)); ASSERT_EQ(this->component.m_retry_count, this->component.RETRY_LIMIT); // Retry one more time should block from retrying and reset retry count - invoke_to_dataReturnIn(0, buffers[MAX_ITERS - 1], Drv::ByteStreamStatus::SEND_RETRY); - ASSERT_from_drvDataOut_SIZE(static_cast(this->component.RETRY_LIMIT)); // no drvDataOut sent when SEND_RETRY + invoke_to_drvSendReturnIn(0, buffers[MAX_ITERS - 1], Drv::ByteStreamStatus::SEND_RETRY); + ASSERT_from_drvSendOut_SIZE(static_cast(this->component.RETRY_LIMIT)); // no drvSendOut sent when SEND_RETRY ASSERT_from_dataReturnOut_SIZE(1); // buffer ownership was returned ASSERT_EQ(this->component.m_retry_count, 0); } @@ -117,7 +117,7 @@ void ComStubTester ::test_retry() { void ComStubTester ::test_retry_reset() { this->test_initial(); FwIndexType MAX_ITERS = this->component.RETRY_LIMIT + 1; - U32 expected_drvDataOut_count = 0; + U32 expected_drvSendOut_count = 0; // Make small individual buffers for testing U8 storage[MAX_ITERS][8]; @@ -131,50 +131,50 @@ void ComStubTester ::test_retry_reset() { // Retrying for as many times as the RETRY_LIMIT should be ok for (FwIndexType i = 0; i < this->component.RETRY_LIMIT; i++) { - invoke_to_dataReturnIn(0, buffers[i], Drv::ByteStreamStatus::SEND_RETRY); - ASSERT_from_drvDataOut(expected_drvDataOut_count, buffers[i]); - expected_drvDataOut_count++; // trick: increment now to use as index prior and size after - ASSERT_from_drvDataOut_SIZE(expected_drvDataOut_count); + invoke_to_drvSendReturnIn(0, buffers[i], Drv::ByteStreamStatus::SEND_RETRY); + ASSERT_from_drvSendOut(expected_drvSendOut_count, buffers[i]); + expected_drvSendOut_count++; // trick: increment now to use as index prior and size after + ASSERT_from_drvSendOut_SIZE(expected_drvSendOut_count); } - // Now, we receive a OP_OK, which should not retry (drvDataOut should not be called) and reset the retry count - ASSERT_from_drvDataOut_SIZE(expected_drvDataOut_count); // no drvDataOut sent when OP_OK - invoke_to_dataReturnIn(0, buffers[0], Drv::ByteStreamStatus::OP_OK); - ASSERT_from_drvDataOut_SIZE(expected_drvDataOut_count); // no drvDataOut sent when OP_OK + // Now, we receive a OP_OK, which should not retry (drvSendOut should not be called) and reset the retry count + ASSERT_from_drvSendOut_SIZE(expected_drvSendOut_count); // no drvSendOut sent when OP_OK + invoke_to_drvSendReturnIn(0, buffers[0], Drv::ByteStreamStatus::OP_OK); + ASSERT_from_drvSendOut_SIZE(expected_drvSendOut_count); // no drvSendOut sent when OP_OK // Now that retry count is reset, we can retry again without a problem for (FwIndexType i = 0; i < this->component.RETRY_LIMIT; i++) { - invoke_to_dataReturnIn(0, buffers[i], Drv::ByteStreamStatus::SEND_RETRY); - ASSERT_from_drvDataOut(expected_drvDataOut_count, buffers[i]); - expected_drvDataOut_count++; // trick: increment now to use as index prior and size after - ASSERT_from_drvDataOut_SIZE(expected_drvDataOut_count); + invoke_to_drvSendReturnIn(0, buffers[i], Drv::ByteStreamStatus::SEND_RETRY); + ASSERT_from_drvSendOut(expected_drvSendOut_count, buffers[i]); + expected_drvSendOut_count++; // trick: increment now to use as index prior and size after + ASSERT_from_drvSendOut_SIZE(expected_drvSendOut_count); } - ASSERT_from_drvDataOut_SIZE(expected_drvDataOut_count); // no drvDataOut sent when OP_OK + ASSERT_from_drvSendOut_SIZE(expected_drvSendOut_count); // no drvSendOut sent when OP_OK } void ComStubTester ::test_buffer_return() { U8 data[1]; Fw::Buffer buffer(data, sizeof(data)); - this->invoke_to_bufferReturnIn(0, buffer); - ASSERT_from_bufferReturnOut_SIZE(1); // incoming buffer should be returned - ASSERT_EQ(this->fromPortHistory_bufferReturnOut->at(0).fwBuffer.getData(), data); - ASSERT_EQ(this->fromPortHistory_bufferReturnOut->at(0).fwBuffer.getSize(), sizeof(data)); + this->invoke_to_dataReturnIn(0, buffer); + ASSERT_from_drvReceiveReturnOut_SIZE(1); // incoming buffer should be returned + ASSERT_EQ(this->fromPortHistory_drvReceiveReturnOut->at(0).fwBuffer.getData(), data); + ASSERT_EQ(this->fromPortHistory_drvReceiveReturnOut->at(0).fwBuffer.getSize(), sizeof(data)); } // ---------------------------------------------------------------------- // Handlers for typed from ports // ---------------------------------------------------------------------- -void ComStubTester ::from_comDataOut_handler(const FwIndexType portNum, +void ComStubTester ::from_dataOut_handler(const FwIndexType portNum, Fw::Buffer& recvBuffer, const ComCfg::FrameContext& context) { - this->pushFromPortEntry_comDataOut(recvBuffer, context); + this->pushFromPortEntry_dataOut(recvBuffer, context); } void ComStubTester ::from_comStatusOut_handler(const FwIndexType portNum, Fw::Success& condition) { this->pushFromPortEntry_comStatusOut(condition); } -void ComStubTester ::from_drvDataOut_handler(const FwIndexType portNum, Fw::Buffer& sendBuffer) { - this->pushFromPortEntry_drvDataOut(sendBuffer); +void ComStubTester ::from_drvSendOut_handler(const FwIndexType portNum, Fw::Buffer& sendBuffer) { + this->pushFromPortEntry_drvSendOut(sendBuffer); } diff --git a/Svc/ComStub/test/ut/ComStubTester.hpp b/Svc/ComStub/test/ut/ComStubTester.hpp index 508f334b38c..90b1af35f05 100644 --- a/Svc/ComStub/test/ut/ComStubTester.hpp +++ b/Svc/ComStub/test/ut/ComStubTester.hpp @@ -68,9 +68,9 @@ class ComStubTester : public ComStubGTestBase { // Handlers for typed from ports // ---------------------------------------------------------------------- - //! Handler for from_comDataOut + //! Handler for from_dataOut //! - void from_comDataOut_handler(const FwIndexType portNum, //!< The port number + void from_dataOut_handler(const FwIndexType portNum, //!< The port number Fw::Buffer& recvBuffer, const ComCfg::FrameContext& context //!< The context ); @@ -81,9 +81,9 @@ class ComStubTester : public ComStubGTestBase { Fw::Success& condition //!< Status of communication state ); - //! Handler for from_drvDataOut + //! Handler for from_drvSendOut //! - void from_drvDataOut_handler(const FwIndexType portNum, //!< The port number + void from_drvSendOut_handler(const FwIndexType portNum, //!< The port number Fw::Buffer& sendBuffer); private: diff --git a/Svc/FprimeDeframer/FprimeDeframer.cpp b/Svc/FprimeDeframer/FprimeDeframer.cpp index 0fa2227e54e..9f816fdf23f 100644 --- a/Svc/FprimeDeframer/FprimeDeframer.cpp +++ b/Svc/FprimeDeframer/FprimeDeframer.cpp @@ -25,7 +25,7 @@ FprimeDeframer ::~FprimeDeframer() {} // Handler implementations for user-defined typed input ports // ---------------------------------------------------------------------- -void FprimeDeframer ::framedIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { +void FprimeDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { if (data.getSize() < FprimeProtocol::FrameHeader::SERIALIZED_SIZE + FprimeProtocol::FrameTrailer::SERIALIZED_SIZE) { // Incoming buffer is not long enough to contain a valid frame (header+trailer) this->log_WARNING_HI_InvalidBufferReceived(); @@ -88,7 +88,7 @@ void FprimeDeframer ::framedIn_handler(FwIndexType portNum, Fw::Buffer& data, co data.setSize(data.getSize() - FprimeProtocol::FrameHeader::SERIALIZED_SIZE - FprimeProtocol::FrameTrailer::SERIALIZED_SIZE); // Emit the deframed data - this->deframedOut_out(0, data, context); + this->dataOut_out(0, data, context); } void FprimeDeframer ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer, const ComCfg::FrameContext& context) { diff --git a/Svc/FprimeDeframer/FprimeDeframer.hpp b/Svc/FprimeDeframer/FprimeDeframer.hpp index fb2b1394be4..6d74d7a3563 100644 --- a/Svc/FprimeDeframer/FprimeDeframer.hpp +++ b/Svc/FprimeDeframer/FprimeDeframer.hpp @@ -36,7 +36,7 @@ class FprimeDeframer final : public FprimeDeframerComponentBase { //! //! Port to receive framed data. The handler will strip the header and trailer from the frame //! and pass the deframed data to the deframed output port. - void framedIn_handler(FwIndexType portNum, //!< The port number + void dataIn_handler(FwIndexType portNum, //!< The port number Fw::Buffer& data, const ComCfg::FrameContext& context) override; diff --git a/Svc/FprimeDeframer/docs/sdd.md b/Svc/FprimeDeframer/docs/sdd.md index b8ed3ec52cf..dbfd25d78e7 100644 --- a/Svc/FprimeDeframer/docs/sdd.md +++ b/Svc/FprimeDeframer/docs/sdd.md @@ -2,13 +2,13 @@ The `Svc::FprimeDeframer` component receives F´ frames on its input port, takes off the header and trailer (sometimes referred to as "footer"), and passes the encapsulated payload to a downstream component (usually the [`Svc.FprimeRouter`](../../FprimeRouter/docs/sdd.md)). -Following the [F Prime Protocol frame specification](../../FprimeProtocol/docs/sdd.md), the `Svc::FprimeDeframer` validates the passed in `Fw.Buffer` to ensure it represents a valid frame (see [Frame validation](#frame-validation)), extract the payload from the frame, and outputs the payload on the `deframedOut` output port. +Following the [F Prime Protocol frame specification](../../FprimeProtocol/docs/sdd.md), the `Svc::FprimeDeframer` validates the passed in `Fw.Buffer` to ensure it represents a valid frame (see [Frame validation](#frame-validation)), extract the payload from the frame, and outputs the payload on the `dataOut` output port. ## Internals -The `Svc::FprimeDeframer` component is an implementation of the [DeframerInterface](../../Interfaces/DeframerInterface.fppi) for the F´ communications protocol. It receives an F´ frame (in a [Fw::Buffer](../../../Fw/Buffer/docs/sdd.md) object) on its `framedIn` input port, modifies the input buffer to remove the header and trailer, and sends it out through its `deframedOut` output port. +The `Svc::FprimeDeframer` component is an implementation of the [DeframerInterface](../../Interfaces/DeframerInterface.fppi) for the F´ communications protocol. It receives an F´ frame (in a [Fw::Buffer](../../../Fw/Buffer/docs/sdd.md) object) on its `dataIn` input port, modifies the input buffer to remove the header and trailer, and sends it out through its `dataOut` output port. -Ownership of the buffer is transferred to the component connected to the `deframedOut` output port. The input buffer is modified by subtracting the header and trailer size from the buffer's length, and offsetting the buffer's data pointer to point to the start of the packet data. +Ownership of the buffer is transferred to the component connected to the `dataOut` output port. The input buffer is modified by subtracting the header and trailer size from the buffer's length, and offsetting the buffer's data pointer to point to the start of the packet data. The `Svc::FprimeDeframer` component does not perform any validation of the frame. It is expected that the frame is valid and well-formed. The validation should be performed by an upstream component, such as [`Svc::FrameAccumulator`](../../FrameAccumulator/docs/sdd.md). @@ -41,7 +41,7 @@ The below diagram shows a typical configuration in which the `Svc::FprimeDeframe ```mermaid classDiagram class FprimeDeframer~PassiveComponent~ { - + void framedIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) + + void dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) } ``` @@ -57,6 +57,6 @@ SVC-DEFRAMER-002 | `Svc::FprimeDeframer` shall deallocate input buffers that are | Kind | Name | Type | Description | |---|---|---|---| -| `guarded input` | framedIn | `Svc.ComDataWithContext` | Receives a frame with optional context data | -| `output` | deframedOut | `Svc.ComDataWithContext` | Receives a frame with optional context data | +| `guarded input` | dataIn | `Svc.ComDataWithContext` | Receives a frame with optional context data | +| `output` | dataOut | `Svc.ComDataWithContext` | Receives a frame with optional context data | | `output` | bufferDeallocate | `Fw.BufferSend` | Port for deallocating dropped frames | diff --git a/Svc/FprimeDeframer/test/ut/FprimeDeframerTester.cpp b/Svc/FprimeDeframer/test/ut/FprimeDeframerTester.cpp index cf506b17e5a..a745bbb78c8 100644 --- a/Svc/FprimeDeframer/test/ut/FprimeDeframerTester.cpp +++ b/Svc/FprimeDeframer/test/ut/FprimeDeframerTester.cpp @@ -34,10 +34,10 @@ void FprimeDeframerTester ::testNominalFrame() { this->injectChecksum(data, sizeof(data)); this->mockReceiveData(data, sizeof(data)); - ASSERT_from_deframedOut_SIZE(1); // something emitted on deframedOut + ASSERT_from_dataOut_SIZE(1); // something emitted on dataOut ASSERT_from_dataReturnOut_SIZE(0); // nothing emitted on dataReturnOut - // Assert that the data that was emitted on deframedOut is equal to Data field above (randomByte) - ASSERT_EQ(this->fromPortHistory_deframedOut->at(0).data.getData()[0], randomByte); + // Assert that the data that was emitted on dataOut is equal to Data field above (randomByte) + ASSERT_EQ(this->fromPortHistory_dataOut->at(0).data.getData()[0], randomByte); ASSERT_EVENTS_SIZE(0); // no events emitted } @@ -48,7 +48,7 @@ void FprimeDeframerTester ::testIncorrectLengthToken() { this->injectChecksum(data, sizeof(data)); this->mockReceiveData(data, sizeof(data)); - ASSERT_from_deframedOut_SIZE(0); // nothing emitted on deframedOut + ASSERT_from_dataOut_SIZE(0); // nothing emitted on dataOut ASSERT_from_dataReturnOut_SIZE(1); // invalid buffer was deallocated // Check which event was emitted ASSERT_EVENTS_SIZE(1); // exactly 1 event emitted @@ -62,7 +62,7 @@ void FprimeDeframerTester ::testIncorrectStartWord() { this->injectChecksum(data, sizeof(data)); this->mockReceiveData(data, sizeof(data)); - ASSERT_from_deframedOut_SIZE(0); // nothing emitted on deframedOut + ASSERT_from_dataOut_SIZE(0); // nothing emitted on dataOut ASSERT_from_dataReturnOut_SIZE(1); // invalid buffer was deallocated // Check which event was emitted ASSERT_EVENTS_SIZE(1); // exactly 1 event emitted @@ -73,7 +73,7 @@ void FprimeDeframerTester ::testIncorrectCrc() { // Frame: | F´ start word | Length = 1 | Data | INCORRECT Checksum | U8 data[13] = {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; this->mockReceiveData(data, sizeof(data)); - ASSERT_from_deframedOut_SIZE(0); // nothing emitted on deframedOut + ASSERT_from_dataOut_SIZE(0); // nothing emitted on dataOut ASSERT_from_dataReturnOut_SIZE(1); // invalid buffer was deallocated // Check which event was emitted ASSERT_EVENTS_SIZE(1); // exactly 1 event emitted @@ -84,7 +84,7 @@ void FprimeDeframerTester::testTruncatedFrame() { // Send a truncated frame, too short to be valid U8 data[11] = {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; this->mockReceiveData(data, sizeof(data)); - ASSERT_from_deframedOut_SIZE(0); // nothing emitted on deframedOut + ASSERT_from_dataOut_SIZE(0); // nothing emitted on dataOut ASSERT_from_dataReturnOut_SIZE(1); // invalid buffer was deallocated // Check which event was emitted ASSERT_EVENTS_SIZE(1); // exactly 1 event emitted @@ -94,7 +94,7 @@ void FprimeDeframerTester::testTruncatedFrame() { void FprimeDeframerTester::testZeroSizeFrame() { // Send an empty frame, too short to be valid this->mockReceiveData(nullptr, 0); - ASSERT_from_deframedOut_SIZE(0); // nothing emitted on deframedOut + ASSERT_from_dataOut_SIZE(0); // nothing emitted on dataOut ASSERT_from_dataReturnOut_SIZE(1); // invalid buffer was deallocated // Check which event was emitted ASSERT_EVENTS_SIZE(1); // exactly 1 event emitted @@ -134,7 +134,7 @@ void FprimeDeframerTester::injectChecksum(U8* data, FwSizeType size) { void FprimeDeframerTester::mockReceiveData(U8* data, FwSizeType size) { ComCfg::FrameContext nullContext; Fw::Buffer buffer(data, static_cast(size)); - this->invoke_to_framedIn(0, buffer, nullContext); + this->invoke_to_dataIn(0, buffer, nullContext); } } // namespace Svc diff --git a/Svc/FrameAccumulator/FrameAccumulator.cpp b/Svc/FrameAccumulator/FrameAccumulator.cpp index 4937738ef93..79acf7d5637 100644 --- a/Svc/FrameAccumulator/FrameAccumulator.cpp +++ b/Svc/FrameAccumulator/FrameAccumulator.cpp @@ -56,8 +56,8 @@ void FrameAccumulator ::dataIn_handler(FwIndexType portNum, Fw::Buffer& buffer, // The buffer is not necessarily a full frame, so the attached context has no meaning and we ignore it this->processBuffer(buffer); } - // Return ownership of the incoming buffer (FrameAccumulator allocates its own buffers to hold frames) - this->bufferReturnOut_out(0, buffer); + // Return ownership of the incoming data + this->dataReturnOut_out(0, buffer, context); } void FrameAccumulator ::processBuffer(Fw::Buffer& buffer) { @@ -136,7 +136,7 @@ void FrameAccumulator ::processRing() { static_cast(m_inRing.get_allocated_size()), static_cast(remaining), static_cast(size_out)); ComCfg::FrameContext context; - this->frameOut_out(0, buffer, context); + this->dataOut_out(0, buffer, context); } else { // No buffer is available, we need to exit and try again later this->log_WARNING_HI_NoBufferAvailable(); diff --git a/Svc/FrameAccumulator/FrameAccumulator.hpp b/Svc/FrameAccumulator/FrameAccumulator.hpp index 0465aff69a2..a6bd4128a40 100644 --- a/Svc/FrameAccumulator/FrameAccumulator.hpp +++ b/Svc/FrameAccumulator/FrameAccumulator.hpp @@ -55,7 +55,7 @@ class FrameAccumulator final : public FrameAccumulatorComponentBase { //! Handler implementation for bufferReturnIn //! - //! Port receiving ownership back of buffers sent on frameOut + //! Port receiving ownership back of buffers sent on dataOut void dataReturnIn_handler(FwIndexType portNum, //!< The port number Fw::Buffer& fwBuffer, //!< The buffer const ComCfg::FrameContext& context //!< The context object diff --git a/Svc/FrameAccumulator/docs/sdd.md b/Svc/FrameAccumulator/docs/sdd.md index 34e24c1ae6c..c9494f40c45 100644 --- a/Svc/FrameAccumulator/docs/sdd.md +++ b/Svc/FrameAccumulator/docs/sdd.md @@ -2,7 +2,7 @@ The `Svc::FrameAccumulator` component accumulates a stream of data (sequence of [Fw::Buffer](../../../Fw/Buffer/docs/sdd.md) objects) to extract full frames from. -The `Svc::FrameAccumulator` accepts as input a sequence of byte buffers, which typically come from a ground data system via a [ByteStreamDriver](../../../Drv/ByteStreamDriverModel/docs/sdd.md). It extracts the frames from the sequence of buffers and emits them on the `frameOut` output port. +The `Svc::FrameAccumulator` accepts as input a sequence of byte buffers, which typically come from a ground data system via a [ByteStreamDriver](../../../Drv/ByteStreamDriverModel/docs/sdd.md). It extracts the frames from the sequence of buffers and emits them on the `dataOut` output port. ## Internals @@ -19,7 +19,7 @@ The uplink frames need not be aligned on the buffer boundaries, and each frame m The `Svc::FrameAccumulator` receives `Fw::Buffer` objects on its `dataIn` input port. These buffers are accumulated in a `Utils::CircularBuffer`. Every time a new buffer is accumulated into the circular buffer, the `Svc::FrameAccumulator` enters a loop to `detect()` a frame within the circular buffer, starting at the current head of the circular buffer. The `Svc::FrameDetector` returns one of three results: - `NO_FRAME_DETECTED`: indicates no valid frame is present at the head of the circular buffer (for example, start word does not match the current head of the circular buffer). The `Svc::FrameAccumulator` rotates the circular buffer one byte and loops over to `detect()` again, or break the loop if the circular buffer is exhausted. -- `FRAME_DETECTED`: indicates there is a frame at the current head of the circular buffer. The `Svc::FrameAccumulator` allocates a new `Fw::Buffer` object to hold the frame, copies the detected frame from the circular buffer into the new `Fw::Buffer` object, and emits the new `Fw::Buffer` object (containing the frame) on its `frameOut` output port. The `Svc::FrameAccumulator` then rotates the circular buffer to remove the data that was just extracted, and deallocates the original `Fw::Buffer` that was received on the `dataIn` input port. +- `FRAME_DETECTED`: indicates there is a frame at the current head of the circular buffer. The `Svc::FrameAccumulator` allocates a new `Fw::Buffer` object to hold the frame, copies the detected frame from the circular buffer into the new `Fw::Buffer` object, and emits the new `Fw::Buffer` object (containing the frame) on its `dataOut` output port. The `Svc::FrameAccumulator` then rotates the circular buffer to remove the data that was just extracted, and deallocates the original `Fw::Buffer` that was received on the `dataIn` input port. - `MORE_DATA_NEEDED`: indicates that more data is needed to determine whether there is a valid frame. The `Svc::FrameAccumulator` deallocates the original `Fw::Buffer` that was received on the `dataIn` input port and halts execution, effectively waiting for the next `Fw::Buffer` to be received on the `dataIn` input port. @@ -86,6 +86,6 @@ SVC-FRAME-ACCUMULATOR-004 | `Svc::FrameAccumulator` shall accept byte buffers co | Kind | Name | Type | Description | |---|---|---|---| | `guarded input` | dataIn | `Drv.ByteStreamRecv` | Receives raw data from a ByteStreamDriver, ComStub, or other buffer producing component | -| `output` | frameOut | `Svc.ComDataWithContext` | Port for sending an extracted frame out | +| `output` | dataOut | `Svc.ComDataWithContext` | Port for sending an extracted frame out | | `output` | bufferAllocate | `Fw.BufferGet` | Port for allocating buffer to hold extracted frame | | `output`| bufferDeallocate | `Fw.BufferSend` | Port for deallocating buffers received on dataIn. | diff --git a/Svc/FrameAccumulator/test/ut/FrameAccumulatorTester.cpp b/Svc/FrameAccumulator/test/ut/FrameAccumulatorTester.cpp index c079cf148df..3f705d489f6 100644 --- a/Svc/FrameAccumulator/test/ut/FrameAccumulatorTester.cpp +++ b/Svc/FrameAccumulator/test/ut/FrameAccumulatorTester.cpp @@ -43,10 +43,10 @@ void FrameAccumulatorTester ::testFrameDetected() { // Receive the buffer on dataIn this->invoke_to_dataIn(0, buffer, context); // Checks - ASSERT_from_bufferReturnOut_SIZE(1); // input buffer ownership was returned - ASSERT_from_frameOut_SIZE(1); // frame was sent + ASSERT_from_dataReturnOut_SIZE(1); // input buffer ownership was returned + ASSERT_from_dataOut_SIZE(1); // frame was sent ASSERT_EQ(this->component.m_inRing.get_allocated_size(), 0); // no data left in ring buffer - ASSERT_EQ(this->fromPortHistory_frameOut->at(0).data.getSize(), buffer_size); // all data was sent out + ASSERT_EQ(this->fromPortHistory_dataOut->at(0).data.getSize(), buffer_size); // all data was sent out } void FrameAccumulatorTester ::testMoreDataNeeded() { @@ -60,8 +60,8 @@ void FrameAccumulatorTester ::testMoreDataNeeded() { // Receive the buffer on dataIn this->invoke_to_dataIn(0, buffer, context); // Checks - ASSERT_from_bufferReturnOut_SIZE(1); // input buffer ownership was returned - ASSERT_from_frameOut_SIZE(0); // frame was not sent (waiting on more data) + ASSERT_from_dataReturnOut_SIZE(1); // input buffer ownership was returned + ASSERT_from_dataOut_SIZE(0); // frame was not sent (waiting on more data) ASSERT_EQ(this->component.m_inRing.get_allocated_size(), buffer_size); // data left in ring buffer } @@ -76,8 +76,8 @@ void FrameAccumulatorTester ::testNoFrameDetected() { // Receive the buffer on dataIn this->invoke_to_dataIn(0, buffer, context); // Checks - ASSERT_from_bufferReturnOut_SIZE(1); // input buffer ownership was returned - ASSERT_from_frameOut_SIZE(0); // No frame was sent out + ASSERT_from_dataReturnOut_SIZE(1); // input buffer ownership was returned + ASSERT_from_dataOut_SIZE(0); // No frame was sent out ASSERT_EQ(this->component.m_inRing.get_allocated_size(), 0); // all data was consumed and discarded } @@ -90,8 +90,8 @@ void FrameAccumulatorTester ::testReceiveZeroSizeBuffer() { // Receive the buffer on dataIn this->invoke_to_dataIn(0, buffer, context); // Checks - ASSERT_from_bufferReturnOut_SIZE(1); // input buffer ownership was returned - ASSERT_from_frameOut_SIZE(0); // No frame was sent out + ASSERT_from_dataReturnOut_SIZE(1); // input buffer ownership was returned + ASSERT_from_dataOut_SIZE(0); // No frame was sent out ASSERT_EQ(this->component.m_inRing.get_allocated_size(), 0); // No data in ring buffer ASSERT_EQ(this->component.m_inRing.m_head_idx, 0); } @@ -114,8 +114,8 @@ void FrameAccumulatorTester ::testAccumulateTwoBuffers() { this->invoke_to_dataIn(0, buffer2, context); // Checks - ASSERT_from_bufferReturnOut_SIZE(2); // both input buffers ownership were returned - ASSERT_from_frameOut_SIZE(1); // Exactly one frame was sent out + ASSERT_from_dataReturnOut_SIZE(2); // both input buffers ownership were returned + ASSERT_from_dataOut_SIZE(1); // Exactly one frame was sent out ASSERT_EQ(this->component.m_inRing.get_allocated_size(), 0); // No data in ring buffer } @@ -124,10 +124,10 @@ void FrameAccumulatorTester ::testAccumulateBuffersEmitFrame() { U32 buffer_count = 0; this->mockAccumulateFullFrame(frame_size, buffer_count); // Checks - ASSERT_from_bufferReturnOut_SIZE(buffer_count); // all input buffers ownership were returned - ASSERT_from_frameOut_SIZE(1); // Exactly one frame was sent out + ASSERT_from_dataReturnOut_SIZE(buffer_count); // all input buffers ownership were returned + ASSERT_from_dataOut_SIZE(1); // Exactly one frame was sent out ASSERT_EQ(this->component.m_inRing.get_allocated_size(), 0); // No data left in ring buffer - ASSERT_EQ(this->fromPortHistory_frameOut->at(0).data.getSize(), frame_size); // accumulated buffer size + ASSERT_EQ(this->fromPortHistory_dataOut->at(0).data.getSize(), frame_size); // accumulated buffer size } void FrameAccumulatorTester ::testAccumulateBuffersEmitManyFrames() { @@ -142,14 +142,14 @@ void FrameAccumulatorTester ::testAccumulateBuffersEmitManyFrames() { this->mockAccumulateFullFrame(frame_size, buffer_count); total_buffer_received += buffer_count; - ASSERT_from_bufferReturnOut_SIZE(total_buffer_received); // all input buffers returned - ASSERT_from_frameOut_SIZE(i+1); // Exactly one frame was sent out + ASSERT_from_dataReturnOut_SIZE(total_buffer_received); // all input buffers returned + ASSERT_from_dataOut_SIZE(i+1); // Exactly one frame was sent out ASSERT_EQ(this->component.m_inRing.get_allocated_size(), 0); // No data left in ring buffer - ASSERT_EQ(this->fromPortHistory_frameOut->at(i).data.getSize(), frame_size); // accumulated buffer size + ASSERT_EQ(this->fromPortHistory_dataOut->at(i).data.getSize(), frame_size); // accumulated buffer size } // Final checks - ASSERT_from_bufferReturnOut_SIZE(total_buffer_received); // all input buffers returned - ASSERT_from_frameOut_SIZE(max_iters); // Exactly max_iters frames were sent out + ASSERT_from_dataReturnOut_SIZE(total_buffer_received); // all input buffers returned + ASSERT_from_dataOut_SIZE(max_iters); // Exactly max_iters frames were sent out ASSERT_EQ(this->component.m_inRing.get_allocated_size(), 0); // No data left in ring buffer } diff --git a/Svc/Interfaces/ComInterface.fppi b/Svc/Interfaces/ComInterface.fppi index 137c6718381..629096011eb 100644 --- a/Svc/Interfaces/ComInterface.fppi +++ b/Svc/Interfaces/ComInterface.fppi @@ -3,10 +3,10 @@ # ---------------------------------------------------------------------- @ Data to be sent on the wire (coming in to the component) -sync input port comDataIn: Svc.ComDataWithContext +sync input port dataIn: Svc.ComDataWithContext -@ Data received from the wire (coming out of the component) -output port comDataOut: Svc.ComDataWithContext +@ Data received from the wire (going out of the component) +output port dataOut: Svc.ComDataWithContext @ Status of the last transmission output port comStatusOut: Fw.SuccessCondition @@ -15,8 +15,8 @@ output port comStatusOut: Fw.SuccessCondition # Memory management # ---------------------------------------------------------------------- -@ Port returning ownership of data that came in on comDataIn +@ Port returning ownership of data that came in on dataIn output port dataReturnOut: Svc.ComDataWithContext -@ Port receiving back ownership of buffer sent out on comDataOut -sync input port bufferReturnIn: Fw.BufferSend +@ Port receiving back ownership of buffer sent out on dataOut +sync input port dataReturnIn: Svc.ComDataWithContext diff --git a/Svc/Interfaces/DeframerInterface.fppi b/Svc/Interfaces/DeframerInterface.fppi index 139bf30c54c..5fd9f45fa31 100644 --- a/Svc/Interfaces/DeframerInterface.fppi +++ b/Svc/Interfaces/DeframerInterface.fppi @@ -1,5 +1,5 @@ @ Port to receive framed data, with optional context -guarded input port framedIn: Svc.ComDataWithContext +guarded input port dataIn: Svc.ComDataWithContext @ Port to output deframed data, with optional context -output port deframedOut: Svc.ComDataWithContext +output port dataOut: Svc.ComDataWithContext diff --git a/Svc/Interfaces/FrameAccumulatorInterface.fppi b/Svc/Interfaces/FrameAccumulatorInterface.fppi index 5222b47206c..76dabda8c18 100644 --- a/Svc/Interfaces/FrameAccumulatorInterface.fppi +++ b/Svc/Interfaces/FrameAccumulatorInterface.fppi @@ -2,10 +2,10 @@ guarded input port dataIn: Svc.ComDataWithContext @ Port for sending an extracted frame out -output port frameOut: Svc.ComDataWithContext +output port dataOut: Svc.ComDataWithContext @ Port for returning ownership of buffers received on dataIn -output port bufferReturnOut: Fw.BufferSend +output port dataReturnOut: Svc.ComDataWithContext @ Port receiving back ownership of buffers sent on frameOut sync input port dataReturnIn: Svc.ComDataWithContext From 2040518045a701f437c5c0e544d6e0f60e8a7a64 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Thu, 1 May 2025 13:05:34 -0700 Subject: [PATCH 16/95] Fix variable name --- Svc/ComStub/test/ut/ComStubTester.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Svc/ComStub/test/ut/ComStubTester.cpp b/Svc/ComStub/test/ut/ComStubTester.cpp index 44381336f1f..51f10053216 100644 --- a/Svc/ComStub/test/ut/ComStubTester.cpp +++ b/Svc/ComStub/test/ut/ComStubTester.cpp @@ -117,7 +117,7 @@ void ComStubTester ::test_retry() { void ComStubTester ::test_retry_reset() { this->test_initial(); FwIndexType MAX_ITERS = static_cast(this->component.RETRY_LIMIT + 1); - U32 expected_drvDataOut_count = 0; + U32 expected_drvSendOut_count = 0; // Make small individual buffers for testing U8 storage[MAX_ITERS][8]; From 1490693fd5b44e1ca861474766a504630b2a3a47 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Thu, 1 May 2025 13:35:40 -0700 Subject: [PATCH 17/95] Adapt UTs --- Svc/ComStub/test/ut/ComStubTester.cpp | 3 ++- Svc/FrameAccumulator/test/ut/FrameAccumulatorTester.cpp | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Svc/ComStub/test/ut/ComStubTester.cpp b/Svc/ComStub/test/ut/ComStubTester.cpp index 51f10053216..337a281e754 100644 --- a/Svc/ComStub/test/ut/ComStubTester.cpp +++ b/Svc/ComStub/test/ut/ComStubTester.cpp @@ -153,7 +153,8 @@ void ComStubTester ::test_retry_reset() { void ComStubTester ::test_buffer_return() { U8 data[1]; Fw::Buffer buffer(data, sizeof(data)); - this->invoke_to_dataReturnIn(0, buffer); + ComCfg::FrameContext context; + this->invoke_to_dataReturnIn(0, buffer, context); ASSERT_from_drvReceiveReturnOut_SIZE(1); // incoming buffer should be returned ASSERT_EQ(this->fromPortHistory_drvReceiveReturnOut->at(0).fwBuffer.getData(), data); ASSERT_EQ(this->fromPortHistory_drvReceiveReturnOut->at(0).fwBuffer.getSize(), sizeof(data)); diff --git a/Svc/FrameAccumulator/test/ut/FrameAccumulatorTester.cpp b/Svc/FrameAccumulator/test/ut/FrameAccumulatorTester.cpp index 3f705d489f6..c084ab08be9 100644 --- a/Svc/FrameAccumulator/test/ut/FrameAccumulatorTester.cpp +++ b/Svc/FrameAccumulator/test/ut/FrameAccumulatorTester.cpp @@ -156,8 +156,8 @@ void FrameAccumulatorTester ::testAccumulateBuffersEmitManyFrames() { void FrameAccumulatorTester ::testBufferReturnDeallocation() { U8 data[1]; Fw::Buffer buffer(data, sizeof(data)); - ComCfg::FrameContext ignoredContext; - this->invoke_to_dataReturnIn(0, buffer, ignoredContext); + ComCfg::FrameContext context; + this->invoke_to_dataReturnIn(0, buffer, context); ASSERT_from_bufferDeallocate_SIZE(1); // incoming buffer should be deallocated ASSERT_EQ(this->fromPortHistory_bufferDeallocate->at(0).fwBuffer.getData(), data); ASSERT_EQ(this->fromPortHistory_bufferDeallocate->at(0).fwBuffer.getSize(), sizeof(data)); From 99c2b755b3c39691f55123bfa71e4ebe16b39042 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Thu, 1 May 2025 14:40:53 -0700 Subject: [PATCH 18/95] Update Communication Adapter Interface docs --- .../communication-adapter-interface.md | 72 +++++++++---------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/docs/reference/communication-adapter-interface.md b/docs/reference/communication-adapter-interface.md index e28d040ea56..98705556c22 100644 --- a/docs/reference/communication-adapter-interface.md +++ b/docs/reference/communication-adapter-interface.md @@ -13,50 +13,51 @@ protocol to ensure that data messages do not overload a communication interface. ## Ports -The communication adapter interface is composed of three ports. These ports are used to transmit outgoing data through +The `Svc.ComDataWithContext` port type is used to transmit comms data between components of the F´ system. This port type is composed of a `Fw::Buffer` object and a `ComCfg::FrameContext` object. The `Fw::Buffer` object is used to transmit the data, while the `ComCfg::FrameContext` object is used to provide context for the data being transmitted, such as header information once the header has been consumed. + +The communication adapter interface is composed of five ports. These ports are used to transmit outgoing data through some communication hardware and receive incoming data from that same hardware. These ports share types with the byte stream driver model for backwards compatibility. -| Kind | Suggested Name | Port Type | Usage | -|----------|----------------|-----------------------|----------------------------------------------------------------| -| `input` | `comDataIn` | `Svc.ComDataWithContext` | Port receiving `Fw::Buffer` objects for outgoing transmission (to be sent on the wire) | -| `output` | `comDataOut` | `Fw.BufferSend` | Port producing incoming `Fw::Buffer` objects (received on the wire) | -| `output` | `dataReturnOut` | `Svc.ComDataWithContext` | Port returning ownership of the `Fw::Buffer` sent on the `comDataIn` port | -| `output` | `comStatusOut` | `Fw.SuccessCondition` | Port indicating status of outgoing transmission. See protocol. | +| Kind | Suggested Name | Port Type | Description | +|----------|----------------|--------------------------|----------------------------------------------------------------| +| `input` | `dataIn` | `Svc.ComDataWithContext` | Port receiving data for outgoing transmission (to be sent on the wire) | +| `output` | `dataOut` | `Svc.ComDataWithContext` | Port producing data from incoming transmissions (received on the wire) | +| `output` | `dataReturnOut`| `Svc.ComDataWithContext` | Port for sending back ownership of the `Fw::Buffer` received on the `dataIn` port | +| `input` | `dataReturnIn` | `Svc.ComDataWithContext` | Port for receiving back ownership of the `Fw::Buffer` sent on the `dataOut` port | +| `output` | `comStatusOut` | `Fw.SuccessCondition` | Port indicating status of outgoing transmission. See protocol. | > [!NOTE] -> About buffer management: after receiving a buffer on the `comDataIn` port, the communication component must return ownership of said buffer through the `dataReturnOut` port. The common scenario is to connect `comDataIn` and `dataReturnOut` to the same component, so that the sender can handle deallocation. -> This is done with a callback so that `comDataIn` can be an asynchronous port if needed. +> About buffer management: after receiving a buffer on the `dataIn` port, the communication component must return ownership of said buffer through the `dataReturnOut` port. The common scenario is to connect `dataIn` and `dataReturnOut` to the same component, so that the sender can handle deallocation. This is done with a callback so that `dataIn` can be an asynchronous port if needed. +> Similarly, the buffer sent out on `dataOut` is expected to be returned through the `dataReturnIn` port. -### comDataIn Description +### dataIn Description -This port receives data from an F´ application in the form of an argument of `Fw::Buffer` type. This data is intended to -be sent out the communications interface managed by this component (often referred to as _the wire_). From the perspective of the application this is -the outgoing data port. +This port receives data from an F´ application in the form of an argument of `Fw::Buffer` type and a `ComCfg::FrameContext` context. This data is intended to be sent out the communications interface managed by this component (often referred to as _the wire_). From the perspective of the application this is the _outgoing data_ port. -### comDataOut Description +### dataOut Description -This port receives data from the communication interface managed by this component and provides it to the F´ application -in the form of an argument of `Fw::Buffer` type. From the perspective of the application this is the incoming data port. +This port produces data to the F´ application once it is received on the wire. From the perspective of the application this is the _incoming data_ port. ### dataReturnOut Description -This port is used to receive a callback returning ownership of the `Fw::Buffer` object that was sent on the `comDataIn` port. Ownership is typically returned to the sender. A callback is used so that `comDataIn` may be an asynchronous port if needed. +This port is used to send a callback returning ownership of the `Fw::Buffer` object that was received on the `dataIn` port. Ownership is typically returned to the sender. A callback is used so that `dataIn` may be an asynchronous port if needed. + +### dataReturnIn Description + +This port is used to receive a callback returning ownership of the `Fw::Buffer` object that was sent on the `dataOut` port. Ownership is typically returned from the receiver of dataOut. A callback is used so that `dataOut` may be an asynchronous call if needed. ### comStatusOut Description -This port carries a status of `Fw::Success::SUCCESS` or `Fw::Success::FAILURE` typically in response to a call to the -`comDataIn` port described above. +This port carries a status of `Fw::Success::SUCCESS` or `Fw::Success::FAILURE` typically in response to a call to the `dataIn` port described above. > [!NOTE] > it is critical to obey the protocol as described in the protocol section below. ## Communication Queue Protocol -`Svc::ComQueue` queues messages until the communication adapter is ready to receive these messages. For each -Fw::Success::SUCCESS message received, `Svc::ComQueue` will emit one message. `Svc::ComQueue` will not emit messages -at any other time. This implies several things: +`Svc::ComQueue` queues messages until the communication adapter is ready to receive these messages. For each `Fw::Success::SUCCESS` message received, `Svc::ComQueue` will emit one message. `Svc::ComQueue` will not emit messages at any other time. This implies several things: 1. An initial `Fw::Success::SUCCESS` message must be sent to `Svc::ComQueue` to initiate data flow 2. A `Fw::Success::SUCCESS` must be eventually received in response to each message for data to continue to flow @@ -65,22 +66,19 @@ These implications are discussed in more depth in the appropriate protocol secti ## Framer Status Protocol -Framing typically happens between `Svc::ComQueue` and a communications adapter. The `Svc::Framer` component implements -this protocol in order to interoperate with these other components. The action taken by this protocol is dependent on -the number of framed messages (frames) sent to the communication adapter in response to each message received from -`Svc::ComQueue`. +Framing typically happens between `Svc::ComQueue` and a communications adapter. The action taken by this protocol is dependent on the number of framed messages (frames) sent to the communication adapter in response to each message received from `Svc::ComQueue`. + +The `Svc::FprimeFramer` implements the Framer status protocol by emitting a frame for each message received from `Svc::ComQueue`. Therefore, the `Svc::FprimeFramer` receives a status from the communication adapter on each sent frame and forwards it back to `Svc::ComQueue`. This allows the data flow to continue, or pause if the communication adapter is unable to receive more data. + +Framer implementations may choose to implement a different behavior. For example, a framer may choose to accept multiple messages from `Svc::ComQueue` and concatenate them in a single frame. In this case, the framer implementation must manage the flow of statuses accordingly. This is summarized in the table below. | Produced Frames | Action | Rationale | |-----------------|----------------------------------------|----------------------------------------------------------| | 0 | Send one `Fw::Success::SUCCESS` status | Data must continue to flow to produce a frame | -| 1 | Pass through received statuses | Frame produced and communication adapter produces status | - -When a frame is produced the communication adapter is responsible for determining the status of the message and its -statuses must be passed through. When no frame is produced, the communication adapter does not receive a frame and is -incapable of producing a status. `Svc::Framer` must act appropriately in this case. +| 1 | Pass through received status from ComQueue | Frame produced and communication adapter produces status | -> [!NOTE] -> `Svc::Framer` must also pass through the initiation message from the communication adapter to start data flow. +> [!IMPORTANT] +> All framer implementations must pass through the initiation message from the communication adapter to start data flow. ## Communication Adapter Protocol @@ -89,16 +87,16 @@ transmissions. This is done with the `comStatus` port. A communication status is | Status | Description | |----------------------|-----------------------------------------------------------------------------------| -| Fw::Success::SUCCESS | *Communication adapter* transmission succeeded and is ready for more data. | +| Fw::Success::SUCCESS | *Communication adapter* transmission succeeded and is ready for more data. | | Fw::Success::FAILURE | Last transmission failed; *communication adapter* is unable to receive more data. | * Fw::Success::SUCCESS may also indicate a connection/reconnection success when data flow must be initiated. -A *Communication Adapter* shall emit either Fw::Success::SUCCESS or Fw::Success::FAILURE via the `comStatus` port once -for each call received on `comDataIn`. Additionally, a *Communication Adapter* shall emit Fw::Success::SUCCESS once at +A *Communication Adapter* shall emit either Fw::Success::SUCCESS or Fw::Success::FAILURE via the `comStatusOut` port once +for each call received on `dataIn`. Additionally, a *Communication Adapter* shall emit Fw::Success::SUCCESS once at startup to indicate communication is initially ready and once after each Fw::Success::FAILURE event to indicate that communication has been restored. By emitting Fw::Success::SUCCESS after any failure, the communication adapter ensures that each received message eventually results in a Fw::Success::SUCCESS. > [!NOTE] -> It is imperative that *Communication Adapters* implement the `comStatus` protocol correctly. +> It is imperative that *Communication Adapters* implement the `comStatusOut` protocol correctly. From 58dab50cfccd3db5729b990e0645da166b60c685 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Thu, 1 May 2025 16:07:07 -0700 Subject: [PATCH 19/95] Full SDD updates --- Svc/ComStub/docs/sdd.md | 11 ++++++++--- Svc/FprimeDeframer/docs/sdd.md | 24 ++++++------------------ Svc/FprimeFramer/docs/sdd.md | 9 ++++++--- Svc/FprimeRouter/docs/sdd.md | 30 ++++++++++++------------------ Svc/FrameAccumulator/docs/sdd.md | 4 +++- Svc/Interfaces/docs/sdd.md | 2 +- 6 files changed, 36 insertions(+), 44 deletions(-) diff --git a/Svc/ComStub/docs/sdd.md b/Svc/ComStub/docs/sdd.md index 25cc8c492bf..ebd2e8ea970 100644 --- a/Svc/ComStub/docs/sdd.md +++ b/Svc/ComStub/docs/sdd.md @@ -57,7 +57,9 @@ be useful |--------------|----------------|-----------------------|-----------------------------------------------------------------------------------| | `sync input` | `dataIn` | `Svc.ComDataWithContext` | Port receiving `Fw::Buffer`s for transmission out `drvSendOut` | | `output` | `comStatusOut` | `Svc.ComStatus` | Port indicating success or failure to attached `Svc::ComQueue` | -| `output` | `dataOut` | `Drv.ByteStreamRecv` | Port providing received `Fw::Buffers` to a potential `Svc::Deframer` | +| `output` | `dataOut` | `Svc.ComDataWithContext` | Port providing received `Fw::Buffers` to the broader application (typically a Deframer) | +| `output` | `dataReturnOut` | `Svc.ComDataWithContext` | Port returning ownership of data that came in on `dataIn` | +| `sync input` | `dataReturnIn` | `Svc.ComDataWithContext` | Port receiving back ownership of buffer sent out on `dataOut` | **Byte Stream Driver Model Ports** @@ -66,13 +68,16 @@ be useful | `sync input` | `drvConnected` | `Drv.ByteStreamReady` | Port called when the underlying driver has connected | | `sync input` | `drvReceiveIn` | `Drv.ByteStreamRecv` | Port receiving `Fw::Buffers` from underlying communications bus driver | | `output` | `drvSendOut` | `Drv.ByteStreamSend` | Port providing received `Fw::Buffers` to the underlying communications bus driver | +| `sync input` | `drvSendReturnIn` | `Drv.ByteStreamData` | Port receiving status and ownership of buffer sent out on `drvSendOut` | +| `output` | `drvReceiveReturnOut` | `Fw.BufferSend` | Port returning ownership of buffer that came in on `drvReceiveIn` | ### 4.2. State, Configuration, and Runtime Setup -`Svc::ComStub` has only stores a boolean `m_reinitialize` indicating when it should send `Fw::Success::SUCCESS` in +`Svc::ComStub` stores a boolean `m_reinitialize` indicating when it should send `Fw::Success::SUCCESS` in response to a driver reconnection event. This is to implement the Communication Adapter Protocol of a -[communication adapter interface](../../../docs/reference/communication-adapter-interface.md). +[communication adapter interface](../../../docs/reference/communication-adapter-interface.md). It also keeps +track of a `m_retry_count` to limit the number of retries on an attempt to send data. ### 4.3. Port Handlers diff --git a/Svc/FprimeDeframer/docs/sdd.md b/Svc/FprimeDeframer/docs/sdd.md index dbfd25d78e7..9afee4513f0 100644 --- a/Svc/FprimeDeframer/docs/sdd.md +++ b/Svc/FprimeDeframer/docs/sdd.md @@ -10,8 +10,6 @@ The `Svc::FprimeDeframer` component is an implementation of the [DeframerInterfa Ownership of the buffer is transferred to the component connected to the `dataOut` output port. The input buffer is modified by subtracting the header and trailer size from the buffer's length, and offsetting the buffer's data pointer to point to the start of the packet data. -The `Svc::FprimeDeframer` component does not perform any validation of the frame. It is expected that the frame is valid and well-formed. The validation should be performed by an upstream component, such as [`Svc::FrameAccumulator`](../../FrameAccumulator/docs/sdd.md). - The `Svc::FprimeDeframer` does not support deframing multiple packets in a single frame (i.e. concatenated packets) as this is not supported by the F´ communications protocol. ### Frame validation @@ -28,35 +26,25 @@ If any of these conditions are not met, the frame is dropped meaning no payload The `Svc::FprimeDeframer` component is used in the uplink stack of many reference F´ application such as [the tutorials source code](https://github.com/fprime-community#tutorials). - ## Diagrams The below diagram shows a typical configuration in which the `Svc::FprimeDeframer` can be used. This is the configuration used in the [the tutorials source code](https://github.com/fprime-community#tutorials). It is receiving accumulated frames from a [Svc::FrameAccumulator](../../FrameAccumulator/docs/sdd.md) and passes packets to a [Svc::FprimeRouter](../../FprimeRouter/docs/sdd.md) for routing to other components. ![./img/deframer_uplink_stack.png](./img/deframer_uplink_stack.png) - -## Class Diagram - -```mermaid -classDiagram - class FprimeDeframer~PassiveComponent~ { - + void dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) - } -``` - - ## Requirements Requirement | Description | Rationale | Verification Method ----------- | ----------- | ----------| ------------------- SVC-DEFRAMER-001 | `Svc::FprimeDeframer` shall extract the payload field from input buffers that represent a valid F Prime frame as specified by the [F Prime Protocol](../../FprimeProtocol/docs/sdd.md) | Deframe valid frames and extract payload | Unit test | -SVC-DEFRAMER-002 | `Svc::FprimeDeframer` shall deallocate input buffers that are not a valid F Prime frame as specified by the [F Prime Protocol](../../FprimeProtocol/docs/sdd.md) | Drop invalid frames | Unit test | +SVC-DEFRAMER-002 | `Svc::FprimeDeframer` shall return ownership of input buffers that are not a valid F Prime frame as specified by the [F Prime Protocol](../../FprimeProtocol/docs/sdd.md) | Drop invalid frames | Unit test | ## Port Descriptions | Kind | Name | Type | Description | |---|---|---|---| -| `guarded input` | dataIn | `Svc.ComDataWithContext` | Receives a frame with optional context data | -| `output` | dataOut | `Svc.ComDataWithContext` | Receives a frame with optional context data | -| `output` | bufferDeallocate | `Fw.BufferSend` | Port for deallocating dropped frames | +| `guarded input` | `dataIn` | `Svc.ComDataWithContext` | Receives a frame for deframing | +| `output` | `dataOut` | `Svc.ComDataWithContext` | Emits deframed data (F´ packets) | +| `sync input` | `dataReturnIn` | `Svc.ComDataWithContext` | Receives ownership of the emitted data back | +| `output` | `dataReturnOut` | `Svc.ComDataWithContext` | Returns ownership of the input buffer back to the sender | + diff --git a/Svc/FprimeFramer/docs/sdd.md b/Svc/FprimeFramer/docs/sdd.md index a059be4523d..4aec38fdbcd 100644 --- a/Svc/FprimeFramer/docs/sdd.md +++ b/Svc/FprimeFramer/docs/sdd.md @@ -4,11 +4,11 @@ The `Svc::FprimeFramer` is an implementation of the [FramerInterface](../../Inte It receives data (an F´ packet) on input and produces an [F´ frame](../../FprimeProtocol/docs/sdd.md) on its output port as a result. Please refer to the [F Prime frame specification](../../FprimeProtocol/docs/sdd.md) for details on the frame format. -### Diagrams +It is designed to receive packets from a [`Svc::ComQueue`](../../ComQueue/docs/sdd.md) and passes frames to a [Communications Adapter](../../Interfaces/docs/sdd.md), such as a Radio manager component or [`Svc::ComStub`](../../ComStub/docs/sdd.md), for transmission on the wire. -Below is the common configuration in which the `Svc::FprimeFramer` can be used. It is receiving packets from a [`Svc::ComQueue`](../../ComQueue/docs/sdd.md) and passes frames to a [Communications Adapter](../../Interfaces/docs/sdd.md), such as a Radio manager component (or a [`Svc::ComStub`](../../ComStub/docs/sdd.md)), for transmission. +## Usage Examples -![./img/framer-topology.png](./img/framer-topology.png) +The `Svc::FprimeFramer` component is used in the uplink stack of many reference F´ application such as [the tutorials source code](https://github.com/fprime-community#tutorials). ## Internals @@ -29,6 +29,8 @@ On receiving a data packet, the `Svc::FprimeFramer` performs the following actio |---|---|---|---| | `guarded input` | `dataIn` | `Svc.ComDataWithContext` | Port to receive data to frame, in a Fw::Buffer with optional context| | `output` | `dataOut` | `Svc.ComDataWithContext` | Port to output framed data, with optional context, for follow-up framing| +| `sync input` | `dataReturnIn` | `Svc.ComDataWithContext` | Port to receive back ownership of buffer sent out of `dataOut` | +| `output` | `dataReturnOut` | `Svc.ComDataWithContext` | Port to return ownership of buffer received received on `dataIn` | | `sync input` | `comStatusIn` | `Fw.SuccessCondition` | Port receiving the general status from the downstream component| | `output` | `comStatusOut` | `Fw.SuccessCondition` | Port receiving indicating the status of framer for receiving more data| @@ -39,4 +41,5 @@ On receiving a data packet, the `Svc::FprimeFramer` performs the following actio | SVC-FPRIME_FRAMER-001 | `Svc::FprimeFramer` shall accept data buffers (packets) stored in `Fw::Buffer` through its `dataIn` input port | Unit Test | | SVC-FPRIME_FRAMER-002 | `Svc::FprimeFramer` shall emit one F Prime frame on its `framedOut` output port for each packet received on `dataIn` input port | Unit Test | | SVC-FPRIME_FRAMER-003 | `Svc::FprimeFramer` shall emit F Prime frames that conforms to the [F´ frame specification](../../FprimeProtocol/docs/sdd.md) | Unit Test | +| SVC-FPRIME_FRAMER-004 | `Svc::FprimeFramer` shall pass through all `Fw.SuccessCondition` received on `comStatusIn` to `comStatusOut` | Unit Test | diff --git a/Svc/FprimeRouter/docs/sdd.md b/Svc/FprimeRouter/docs/sdd.md index d4bfe760892..a4b9598d25d 100644 --- a/Svc/FprimeRouter/docs/sdd.md +++ b/Svc/FprimeRouter/docs/sdd.md @@ -16,26 +16,18 @@ In the canonical uplink communications stack, `Svc::FprimeRouter` is connected t ![uplink_stack](../../FprimeDeframer/docs/img/deframer_uplink_stack.png) -## Class Diagram - - -```mermaid -classDiagram - class FprimeRouter~PassiveComponent~ { - + void dataIn_handler(portNum, packetBuffer, contextBuffer) - + void cmdResponseIn_handler(portNum, opcode, cmdSeq, response) - } -``` - ## Port Descriptions -| Name | Description | Type | -|---|---|---| -| `dataIn: Svc.ComDataWithContext` | Receiving Fw::Buffer with context buffer from Deframer | `guarded input` | -| `commandOut: Fw.Com` | Port for sending command packets as Fw::ComBuffers | `output` | -| `fileOut: Fw.BufferSend` | Port for sending file packets as Fw::Buffer (ownership passed to receiver) | `output` | -| `unknownDataOut: Svc.ComDataWithContext` | Port forwarding unknown data (useful for adding custom routing rules with a project-defined router) | `output` | -| `output`| bufferDeallocate | `Fw.BufferSend` | Port for deallocating buffers once routed | +| Kind | Name | Type | Description | +|---|---|---|---| +| `guarded input` | `dataIn` | `Svc.ComDataWithContext` | Receiving Fw::Buffer with context buffer from Deframer +| `guarded input` | `dataReturnOut` | `Svc.ComDataWithContext` | Returning ownership of buffer received on `dataIn` +| `output` | `commandOut` | `Fw.Com` | Port for sending command packets as Fw::ComBuffers | +| `output` | `fileOut` | `Fw.BufferSend` | Port for sending file packets as Fw::Buffer (ownership passed to receiver) | +| `sync input` | `fileBufferReturnIn` | `Fw.BufferSend` | Receiving ownership of buffer sent on `fileOut` | +| `output` | `unknownDataOut` | `Svc.ComDataWithContext` | Port forwarding unknown data (useful for adding custom routing rules with a project-defined router) | +| `output`| `bufferAllocate` | `Fw.BufferGet` | Port for allocating buffers, allowing copy of received data | +| `output`| `bufferDeallocate` | `Fw.BufferSend` | Port for deallocating buffers | ## Requirements @@ -46,3 +38,5 @@ SVC-ROUTER-002 | `Svc::FprimeRouter` shall route packets of type `Fw::ComPacket: SVC-ROUTER-003 | `Svc::FprimeRouter` shall route packets of type `Fw::ComPacket::FW_PACKET_FILE` to the `fileOut` output port. | Routing file packets | Unit test | SVC-ROUTER-004 | `Svc::FprimeRouter` shall route data that is neither `Fw::ComPacket::FW_PACKET_COMMAND` nor `Fw::ComPacket::FW_PACKET_FILE` to the `unknownDataOut` output port. | Allows for projects to provide custom routing for additional (project-specific) uplink data types | Unit test | SVC-ROUTER-005 | `Svc::FprimeRouter` shall emit warning events if serialization errors occur during processing of incoming packets | Aid in diagnosing uplink issues | Unit test | +SVC-ROUTER-005 | `Svc::FprimeRouter` shall make a copy of buffers that represent a `FW_PACKET_FILE` | Aid in memory management of file buffers | Unit test | +SVC-ROUTER-005 | `Svc::FprimeRouter` shall return ownership of all buffers received on `dataIn` through `dataReturnOut` | Memory management | Unit test | diff --git a/Svc/FrameAccumulator/docs/sdd.md b/Svc/FrameAccumulator/docs/sdd.md index c9494f40c45..0b7fb0e45f3 100644 --- a/Svc/FrameAccumulator/docs/sdd.md +++ b/Svc/FrameAccumulator/docs/sdd.md @@ -85,7 +85,9 @@ SVC-FRAME-ACCUMULATOR-004 | `Svc::FrameAccumulator` shall accept byte buffers co | Kind | Name | Type | Description | |---|---|---|---| -| `guarded input` | dataIn | `Drv.ByteStreamRecv` | Receives raw data from a ByteStreamDriver, ComStub, or other buffer producing component | +| `guarded input` | dataIn | `Svc.ComDataWithContext` | Receives a stream of byte buffers from a [Communication Adapter](../../Interfaces/docs/sdd.md) | | `output` | dataOut | `Svc.ComDataWithContext` | Port for sending an extracted frame out | | `output` | bufferAllocate | `Fw.BufferGet` | Port for allocating buffer to hold extracted frame | | `output`| bufferDeallocate | `Fw.BufferSend` | Port for deallocating buffers received on dataIn. | +| `output` | dataReturnOut | `Svc.ComDataWithContext` | Port for returning ownership of buffers received on dataIn | +| `sync input` | dataReturnIn | `Svc.ComDataWithContext` | Receiving back ownership of buffers sent on dataOut | diff --git a/Svc/Interfaces/docs/sdd.md b/Svc/Interfaces/docs/sdd.md index 18549bd19a4..d51b650317c 100644 --- a/Svc/Interfaces/docs/sdd.md +++ b/Svc/Interfaces/docs/sdd.md @@ -4,7 +4,7 @@ The Svc interfaces are a set of `.fppi` files that define FPP interfaces for com ## Svc/ComInterface -The `Svc/ComInterface` is an interface for implementing the [Communications Adapter Interface](../../../docs/reference/communication-adapter-interface.md). +The `Svc/ComInterface` is an interface for implementing the [Communications Adapter Interface](../../../docs/reference/communication-adapter-interface.md). [`Svc::ComStub`](../../ComStub/docs/sdd.md) implements this interface and uses a ByteStream driver to send and receive data on a TCP/UDP/UART link, and is often used in development and early testing. ## Svc/DeframerInterface From d3d7857773a1079c88f47686bd293ded6d7f455e Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Thu, 1 May 2025 16:22:37 -0700 Subject: [PATCH 20/95] Spelling & nits and details --- Svc/ComQueue/docs/sdd.md | 13 +++++++------ Svc/ComQueue/test/ut/ComQueueTestMain.cpp | 2 +- Svc/ComQueue/test/ut/ComQueueTester.cpp | 2 +- Svc/ComQueue/test/ut/ComQueueTester.hpp | 2 +- Svc/FprimeFramer/docs/sdd.md | 16 ++++++++-------- 5 files changed, 18 insertions(+), 17 deletions(-) diff --git a/Svc/ComQueue/docs/sdd.md b/Svc/ComQueue/docs/sdd.md index 03c2060b42d..56b45952a28 100644 --- a/Svc/ComQueue/docs/sdd.md +++ b/Svc/ComQueue/docs/sdd.md @@ -24,7 +24,7 @@ Queued messages from the highest priority source port are serviced first and a r | Requirement | Description | Rationale | Verification Method | |------------------|-----------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------|---------------------| | SVC-COMQUEUE-001 | `Svc::ComQueue` shall queue `Fw::Buffer` and `Fw::ComBuffer` received on incoming ports. | The purpose of the queue is to store messages. | Unit Test | -| SVC-COMQUEUE-002 | `Svc::ComQueue` shall output exactly one `Fw::Buffer` (wrapping the queued data units) on a received `Fw::Success::SUCCESS` signal. | `Svc::ComQueue` obeys the communication adapter interface protocol. | Unit Test | +| SVC-COMQUEUE-002 | `Svc::ComQueue` shall output exactly one `Fw::Buffer` (wrapping the queued data units) on a received `Fw::Success::SUCCESS` signal. | `Svc::ComQueue` obeys the communication adapter interface protocol. | Unit Test | | SVC-COMQUEUE-003 | `Svc::ComQueue` shall pause sending on the `Fw::Success::FAILURE` and restart on the next `Fw::Success::SUCCESS` signal. | `Svc::ComQueue` should not sent to a failing communication adapter. | Unit Test | | SVC-COMQUEUE-004 | `Svc::ComQueue` shall have a configurable number of `Fw::Com` and `Fw::Buffer` input ports. | `Svc::ComQueue` should be adaptable for a number of projects. | Inspection | | SVC-COMQUEUE-005 | `Svc::ComQueue` shall select and send the next priority `Fw::Buffer` and `Fw::ComBuffer` message in response to `Fw::Success::SUCCESS`. | `Svc::ComQueue` obeys the communication adapter interface protocol. | Unit test | @@ -32,7 +32,8 @@ Queued messages from the highest priority source port are serviced first and a r | SVC-COMQUEUE-007 | `Svc::ComQueue` shall emit a queue overflow event for a given port when the configured depth is exceeded. Messages shall be discarded. | `Svc::ComQueue` needs to indicate off-nominal events. | Unit Test | | SVC-COMQUEUE-008 | `Svc::ComQueue` shall implement a round robin approach to balance between ports of the same priority. | Allows projects to balance between a set of queues of similar priority. | Unit Test | | SVC-COMQUEUE-009 | `Svc::ComQueue` shall keep track and throttle queue overflow events per port. | Prevents a flood of queue overflow events. | Unit test | -comPacketQueueIn +| SVC-COMQUEUE-010 | `Svc::ComQueue` shall return ownership of incoming buffers once they have been enqueued. | Memory management | Unit test | + ## 4. Design The diagram below shows the `Svc::ComQueue` component. @@ -43,12 +44,12 @@ The diagram below shows the `Svc::ComQueue` component. | Kind | Name | Port Type | Usage | |---------------|-------------------|---------------------------------------|----------------------------------------------------------| -| `output` | `dataOut` | `Svc.ComDataWithContext` | Port emitting queued messages | +| `output` | `dataOut` | `Svc.ComDataWithContext` | Port emitting queued messages | +| `sync input` | `dataReturnIn` | `Svc.ComDataWithContext` | Port retrieving back ownership buffers sent on dataOut | | `async input` | `comStatusIn` | `Fw.SuccessCondition` | Port for receiving the status signal | | `async input` | `comPacketQueueIn`| `[ComQueueComPorts] Fw.Com` | Port array for receiving Fw::ComBuffers | -| `async input` | `bufferQueueIn` | `[ComQueueBufferPorts] Fw.BufferSend`| Port array for receiving Fw::Buffers | -| `sync input` | `dataReturnIn` | `Svc.ComDataWithContext` | Port for deallocating Fw::Buffer on queue overflow | -| `output` | `bufferReturnOut` | `Svc.ComDataWithContext` | Port for deallocating Fw::Buffer on queue overflow | +| `async input` | `bufferQueueIn` | `[ComQueueBufferPorts] Fw.BufferSend` | Port array for receiving Fw::Buffers | +| `output` | `bufferReturnOut` | `[ComQueueBufferPorts] Fw.BufferSend` | Port array returning ownership of buffers received on bufferQueueIn | > [!NOTE] > ComQueue also has the port instances for autocoded functionality for events, telemetry and time. diff --git a/Svc/ComQueue/test/ut/ComQueueTestMain.cpp b/Svc/ComQueue/test/ut/ComQueueTestMain.cpp index 858a6d6d7b3..0506b577404 100644 --- a/Svc/ComQueue/test/ut/ComQueueTestMain.cpp +++ b/Svc/ComQueue/test/ut/ComQueueTestMain.cpp @@ -6,7 +6,7 @@ TEST(Nominal, Send) { Svc::ComQueueTester tester; - tester.testdataOut(); + tester.testQueueSend(); } TEST(Nominal, Pause) { diff --git a/Svc/ComQueue/test/ut/ComQueueTester.cpp b/Svc/ComQueue/test/ut/ComQueueTester.cpp index c5cdb558dfb..bbc67a2080c 100644 --- a/Svc/ComQueue/test/ut/ComQueueTester.cpp +++ b/Svc/ComQueue/test/ut/ComQueueTester.cpp @@ -79,7 +79,7 @@ void ComQueueTester ::emitOneAndCheck(FwIndexType expectedIndex, // Tests // ---------------------------------------------------------------------- -void ComQueueTester ::testdataOut() { +void ComQueueTester ::testQueueSend() { U8 data[BUFFER_LENGTH] = {0xde, 0xad, 0xbe}; Fw::ComBuffer comBuffer(&data[0], sizeof(data)); Fw::Buffer buffer(&data[0], sizeof(data)); diff --git a/Svc/ComQueue/test/ut/ComQueueTester.hpp b/Svc/ComQueue/test/ut/ComQueueTester.hpp index 1dd2f25b363..78b2e42d520 100644 --- a/Svc/ComQueue/test/ut/ComQueueTester.hpp +++ b/Svc/ComQueue/test/ut/ComQueueTester.hpp @@ -66,7 +66,7 @@ class ComQueueTester : public ComQueueGTestBase { // Tests // ---------------------------------------------------------------------- - void testdataOut(); + void testQueueSend(); void testQueuePause(); diff --git a/Svc/FprimeFramer/docs/sdd.md b/Svc/FprimeFramer/docs/sdd.md index 4aec38fdbcd..a91dc94027e 100644 --- a/Svc/FprimeFramer/docs/sdd.md +++ b/Svc/FprimeFramer/docs/sdd.md @@ -25,14 +25,14 @@ On receiving a data packet, the `Svc::FprimeFramer` performs the following actio ## Port Descriptions -| Kind | Name | Port Type | Usage | -|---|---|---|---| -| `guarded input` | `dataIn` | `Svc.ComDataWithContext` | Port to receive data to frame, in a Fw::Buffer with optional context| -| `output` | `dataOut` | `Svc.ComDataWithContext` | Port to output framed data, with optional context, for follow-up framing| -| `sync input` | `dataReturnIn` | `Svc.ComDataWithContext` | Port to receive back ownership of buffer sent out of `dataOut` | -| `output` | `dataReturnOut` | `Svc.ComDataWithContext` | Port to return ownership of buffer received received on `dataIn` | -| `sync input` | `comStatusIn` | `Fw.SuccessCondition` | Port receiving the general status from the downstream component| -| `output` | `comStatusOut` | `Fw.SuccessCondition` | Port receiving indicating the status of framer for receiving more data| +| Kind | Name | Port Type | Usage | +|-----------------|-----------------|--------------------------|--------------------------------------------------------------------------| +| `guarded input` | `dataIn` | `Svc.ComDataWithContext` | Port to receive data to frame, in a Fw::Buffer with optional context | +| `output` | `dataOut` | `Svc.ComDataWithContext` | Port to output framed data, with optional context, for follow-up framing | +| `sync input` | `dataReturnIn` | `Svc.ComDataWithContext` | Port to receive back ownership of buffer sent out of `dataOut` | +| `output` | `dataReturnOut` | `Svc.ComDataWithContext` | Port to return ownership of buffer received on `dataIn` | +| `sync input` | `comStatusIn` | `Fw.SuccessCondition` | Port receiving the general status from the downstream component | +| `output` | `comStatusOut` | `Fw.SuccessCondition` | Port receiving indicating the status of framer for receiving more data | ## Requirements From c205399c0d4713bd80a869a0ab73e1926b762cd9 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Thu, 1 May 2025 16:25:28 -0700 Subject: [PATCH 21/95] Put formatting back to original --- RPI/Top/topology.fpp | 16 ++++++------ Ref/Top/topology.fpp | 58 ++++++++++++++++++++++---------------------- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/RPI/Top/topology.fpp b/RPI/Top/topology.fpp index 88fd5ef7558..a8abd2cc987 100644 --- a/RPI/Top/topology.fpp +++ b/RPI/Top/topology.fpp @@ -63,9 +63,9 @@ module RPI { # ---------------------------------------------------------------------- connections Downlink { - eventLogger.PktSend -> comQueue.comPacketQueueIn[0] - chanTlm.PktSend -> comQueue.comPacketQueueIn[1] - fileDownlink.bufferSendOut -> comQueue.bufferQueueIn[0] + eventLogger.PktSend -> comQueue.comPacketQueueIn[0] + chanTlm.PktSend -> comQueue.comPacketQueueIn[1] + fileDownlink.bufferSendOut -> comQueue.bufferQueueIn[0] comQueue.bufferReturnOut[0] -> fileDownlink.bufferReturn comQueue.dataOut -> framer.dataIn @@ -138,20 +138,20 @@ module RPI { comDriver.allocate -> commsBufferManager.bufferGetCallee comDriver.deallocate -> commsBufferManager.bufferSendIn # ComDriver <-> ComStub - comDriver.$recv -> comStub.drvReceiveIn + comDriver.$recv -> comStub.drvReceiveIn comStub.drvReceiveReturnOut -> comDriver.recvReturnIn # ComStub <-> FrameAccumulator - comStub.dataOut -> frameAccumulator.dataIn + comStub.dataOut -> frameAccumulator.dataIn frameAccumulator.dataReturnOut -> comStub.dataReturnIn # FrameAccumulator buffer allocations frameAccumulator.bufferDeallocate -> commsBufferManager.bufferSendIn frameAccumulator.bufferAllocate -> commsBufferManager.bufferGetCallee # FrameAccumulator <-> Deframer - frameAccumulator.dataOut -> deframer.dataIn + frameAccumulator.dataOut -> deframer.dataIn deframer.dataReturnOut -> frameAccumulator.dataReturnIn # Deframer <-> Router - deframer.dataOut -> fprimeRouter.dataIn - fprimeRouter.dataReturnOut -> deframer.dataReturnIn + deframer.dataOut -> fprimeRouter.dataIn + fprimeRouter.dataReturnOut -> deframer.dataReturnIn # Router buffer allocations fprimeRouter.bufferAllocate -> commsBufferManager.bufferGetCallee fprimeRouter.bufferDeallocate -> commsBufferManager.bufferSendIn diff --git a/Ref/Top/topology.fpp b/Ref/Top/topology.fpp index 7d617cd2bec..3461626c17e 100644 --- a/Ref/Top/topology.fpp +++ b/Ref/Top/topology.fpp @@ -122,35 +122,6 @@ module Ref { fprimeFramer.comStatusOut -> comQueue.comStatusIn } - connections Uplink { - # ComDriver buffer allocations - comDriver.allocate -> commsBufferManager.bufferGetCallee - comDriver.deallocate -> commsBufferManager.bufferSendIn - # ComDriver <-> ComStub - comDriver.$recv -> comStub.drvReceiveIn - comStub.drvReceiveReturnOut -> comDriver.recvReturnIn - # ComStub <-> FrameAccumulator - comStub.dataOut -> frameAccumulator.dataIn - frameAccumulator.dataReturnOut -> comStub.dataReturnIn - # FrameAccumulator buffer allocations - frameAccumulator.bufferDeallocate -> commsBufferManager.bufferSendIn - frameAccumulator.bufferAllocate -> commsBufferManager.bufferGetCallee - # FrameAccumulator <-> Deframer - frameAccumulator.dataOut -> deframer.dataIn - deframer.dataReturnOut -> frameAccumulator.dataReturnIn - # Deframer <-> Router - deframer.dataOut -> fprimeRouter.dataIn - fprimeRouter.dataReturnOut -> deframer.dataReturnIn - # Router buffer allocations - fprimeRouter.bufferAllocate -> commsBufferManager.bufferGetCallee - fprimeRouter.bufferDeallocate -> commsBufferManager.bufferSendIn - # Router <-> CmdDispatcher/FileUplink - fprimeRouter.commandOut -> cmdDisp.seqCmdBuff - cmdDisp.seqCmdStatus -> fprimeRouter.cmdResponseIn - fprimeRouter.fileOut -> fileUplink.bufferSendIn - fileUplink.bufferSendOut -> fprimeRouter.fileBufferReturnIn - } - connections FaultProtection { eventLogger.FatalAnnounce -> fatalHandler.FatalReceive } @@ -197,6 +168,35 @@ module Ref { cmdDisp.seqCmdStatus -> cmdSeq.cmdResponseIn } + connections Uplink { + # ComDriver buffer allocations + comDriver.allocate -> commsBufferManager.bufferGetCallee + comDriver.deallocate -> commsBufferManager.bufferSendIn + # ComDriver <-> ComStub + comDriver.$recv -> comStub.drvReceiveIn + comStub.drvReceiveReturnOut -> comDriver.recvReturnIn + # ComStub <-> FrameAccumulator + comStub.dataOut -> frameAccumulator.dataIn + frameAccumulator.dataReturnOut -> comStub.dataReturnIn + # FrameAccumulator buffer allocations + frameAccumulator.bufferDeallocate -> commsBufferManager.bufferSendIn + frameAccumulator.bufferAllocate -> commsBufferManager.bufferGetCallee + # FrameAccumulator <-> Deframer + frameAccumulator.dataOut -> deframer.dataIn + deframer.dataReturnOut -> frameAccumulator.dataReturnIn + # Deframer <-> Router + deframer.dataOut -> fprimeRouter.dataIn + fprimeRouter.dataReturnOut -> deframer.dataReturnIn + # Router buffer allocations + fprimeRouter.bufferAllocate -> commsBufferManager.bufferGetCallee + fprimeRouter.bufferDeallocate -> commsBufferManager.bufferSendIn + # Router <-> CmdDispatcher/FileUplink + fprimeRouter.commandOut -> cmdDisp.seqCmdBuff + cmdDisp.seqCmdStatus -> fprimeRouter.cmdResponseIn + fprimeRouter.fileOut -> fileUplink.bufferSendIn + fileUplink.bufferSendOut -> fprimeRouter.fileBufferReturnIn + } + connections DataProducts { # DpMgr and DpWriter connections. Have explicit port indexes for demo dpMgr.bufferGetOut[0] -> dpBufferManager.bufferGetCallee From 4ca0304f29d62b47ac138b2b78647e4f86b882eb Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Mon, 5 May 2025 17:45:12 -0700 Subject: [PATCH 22/95] Added SpacePacket, TC and TM framers/deframers + Ref topology. Working with GDS wohooo --- Ref/Top/RefTopology.cpp | 4 +- Ref/Top/instances.fpp | 8 +- Ref/Top/topology.fpp | 37 ++++--- Svc/CCSDS/CMakeLists.txt | 4 + .../SpacePacketDeframer.cpp | 51 +++------ .../SpacePacketDeframer.fpp | 7 +- .../SpacePacketDeframer.hpp | 18 ++-- .../TCDeframer/CMakeLists.txt | 21 ++++ .../TCDeframer/TCDeframer.cpp | 64 +++++++++++ .../TCDeframer/TCDeframer.fpp | 37 +++++++ .../TCDeframer/TCDeframer.hpp | 53 +++++++++ .../TCDeframer/docs/sdd.md | 66 ++++++++++++ Svc/CCSDS/SpacePacketFramer/CMakeLists.txt | 44 ++++++++ .../SpacePacketFramer/SpacePacketFramer.cpp | 82 ++++++++++++++ .../SpacePacketFramer/SpacePacketFramer.fpp | 35 ++++++ .../SpacePacketFramer/SpacePacketFramer.hpp | 63 +++++++++++ Svc/CCSDS/SpacePacketFramer/docs/sdd.md | 66 ++++++++++++ Svc/CCSDS/TCDeframer/CMakeLists.txt | 21 ++++ Svc/CCSDS/TCDeframer/TCDeframer.cpp | 66 ++++++++++++ Svc/CCSDS/TCDeframer/TCDeframer.fpp | 37 +++++++ Svc/CCSDS/TCDeframer/TCDeframer.hpp | 53 +++++++++ Svc/CCSDS/TCDeframer/docs/sdd.md | 66 ++++++++++++ Svc/CCSDS/TMFramer/CMakeLists.txt | 21 ++++ Svc/CCSDS/TMFramer/TMFramer.cpp | 101 ++++++++++++++++++ Svc/CCSDS/TMFramer/TMFramer.fpp | 34 ++++++ Svc/CCSDS/TMFramer/TMFramer.hpp | 63 +++++++++++ Svc/CCSDS/TMFramer/docs/sdd.md | 66 ++++++++++++ Svc/CCSDS/Types/Types.fpp | 39 ++++++- Svc/CCSDS/Utils/CMakeLists.txt | 28 +++++ Svc/CCSDS/Utils/CRC16.hpp | 58 ++++++++++ Svc/CCSDS/Utils/Utils.fpp | 20 ++++ Svc/FrameAccumulator/CMakeLists.txt | 1 + .../FrameDetector/CcsdsTCFrameDetector.cpp | 51 +++++++++ .../FrameDetector/CcsdsTCFrameDetector.hpp | 52 +++++++++ config/ComCfg.fpp | 4 + 35 files changed, 1381 insertions(+), 60 deletions(-) create mode 100644 Svc/CCSDS/SpacePacketDeframer/TCDeframer/CMakeLists.txt create mode 100644 Svc/CCSDS/SpacePacketDeframer/TCDeframer/TCDeframer.cpp create mode 100644 Svc/CCSDS/SpacePacketDeframer/TCDeframer/TCDeframer.fpp create mode 100644 Svc/CCSDS/SpacePacketDeframer/TCDeframer/TCDeframer.hpp create mode 100644 Svc/CCSDS/SpacePacketDeframer/TCDeframer/docs/sdd.md create mode 100644 Svc/CCSDS/SpacePacketFramer/CMakeLists.txt create mode 100644 Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp create mode 100644 Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.fpp create mode 100644 Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp create mode 100644 Svc/CCSDS/SpacePacketFramer/docs/sdd.md create mode 100644 Svc/CCSDS/TCDeframer/CMakeLists.txt create mode 100644 Svc/CCSDS/TCDeframer/TCDeframer.cpp create mode 100644 Svc/CCSDS/TCDeframer/TCDeframer.fpp create mode 100644 Svc/CCSDS/TCDeframer/TCDeframer.hpp create mode 100644 Svc/CCSDS/TCDeframer/docs/sdd.md create mode 100644 Svc/CCSDS/TMFramer/CMakeLists.txt create mode 100644 Svc/CCSDS/TMFramer/TMFramer.cpp create mode 100644 Svc/CCSDS/TMFramer/TMFramer.fpp create mode 100644 Svc/CCSDS/TMFramer/TMFramer.hpp create mode 100644 Svc/CCSDS/TMFramer/docs/sdd.md create mode 100644 Svc/CCSDS/Utils/CMakeLists.txt create mode 100644 Svc/CCSDS/Utils/CRC16.hpp create mode 100644 Svc/CCSDS/Utils/Utils.fpp create mode 100644 Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp create mode 100644 Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.hpp diff --git a/Ref/Top/RefTopology.cpp b/Ref/Top/RefTopology.cpp index b65d442bd08..2c13fabada0 100644 --- a/Ref/Top/RefTopology.cpp +++ b/Ref/Top/RefTopology.cpp @@ -14,7 +14,7 @@ // Necessary project-specified types #include #include -#include +#include #include // Used for 1Hz synthetic cycling @@ -32,7 +32,7 @@ Fw::MallocAllocator mallocator; // The reference topology uses the F´ packet protocol when communicating with the ground and therefore uses the F´ // framing and deframing implementations. -Svc::FrameDetectors::FprimeFrameDetector frameDetector; +Svc::FrameDetectors::CcsdsTCFrameDetector frameDetector; // The reference topology divides the incoming clock signal (1Hz) into sub-signals: 1Hz, 1/2Hz, and 1/4Hz and diff --git a/Ref/Top/instances.fpp b/Ref/Top/instances.fpp index 78884e00c0d..48232db515b 100644 --- a/Ref/Top/instances.fpp +++ b/Ref/Top/instances.fpp @@ -167,7 +167,13 @@ module Ref { instance frameAccumulator: Svc.FrameAccumulator base id 0x4B00 - instance deframer: Svc.FprimeDeframer base id 0x4C00 + instance tcDeframer: Svc.CCSDS.TCDeframer base id 0x4C00 + + instance spacePacketDeframer: Svc.CCSDS.SpacePacketDeframer base id 0x5000 + + instance tmFramer: Svc.CCSDS.TMFramer base id 0x4C00 + + instance spacePacketFramer: Svc.CCSDS.SpacePacketFramer base id 0x5000 instance fprimeRouter: Svc.FprimeRouter base id 0x4D00 diff --git a/Ref/Top/topology.fpp b/Ref/Top/topology.fpp index 3461626c17e..3e7990235e5 100644 --- a/Ref/Top/topology.fpp +++ b/Ref/Top/topology.fpp @@ -38,7 +38,10 @@ module Ref { instance comDriver instance comStub instance comQueue - instance deframer + instance tcDeframer + instance spacePacketDeframer + instance tmFramer + instance spacePacketFramer instance eventLogger instance fatalAdapter instance fatalHandler @@ -105,21 +108,27 @@ module Ref { fileDownlink.bufferSendOut -> comQueue.bufferQueueIn[Ports_ComBufferQueue.FILE_DOWNLINK] comQueue.bufferReturnOut[Ports_ComBufferQueue.FILE_DOWNLINK] -> fileDownlink.bufferReturn # ComQueue <-> Framer - comQueue.dataOut -> fprimeFramer.dataIn - fprimeFramer.dataReturnOut -> comQueue.dataReturnIn + comQueue.dataOut -> spacePacketFramer.dataIn + spacePacketFramer.dataReturnOut -> comQueue.dataReturnIn # Buffer Management for Framer - fprimeFramer.bufferAllocate -> commsBufferManager.bufferGetCallee - fprimeFramer.bufferDeallocate -> commsBufferManager.bufferSendIn + spacePacketFramer.bufferAllocate -> commsBufferManager.bufferGetCallee + spacePacketFramer.bufferDeallocate -> commsBufferManager.bufferSendIn + tmFramer.bufferAllocate -> commsBufferManager.bufferGetCallee + tmFramer.bufferDeallocate -> commsBufferManager.bufferSendIn + # Framer chain + spacePacketFramer.dataOut -> tmFramer.dataIn + tmFramer.dataReturnOut -> spacePacketFramer.dataReturnIn # Framer <-> ComStub - fprimeFramer.dataOut -> comStub.dataIn - comStub.dataReturnOut -> fprimeFramer.dataReturnIn + tmFramer.dataOut -> comStub.dataIn + comStub.dataReturnOut -> tmFramer.dataReturnIn # ComStub <-> ComDriver comStub.drvSendOut -> comDriver.$send comDriver.sendReturnOut -> comStub.drvSendReturnIn comDriver.ready -> comStub.drvConnected # ComStatus - comStub.comStatusOut -> fprimeFramer.comStatusIn - fprimeFramer.comStatusOut -> comQueue.comStatusIn + comStub.comStatusOut -> tmFramer.comStatusIn + tmFramer.comStatusOut -> spacePacketFramer.comStatusIn + spacePacketFramer.comStatusOut -> comQueue.comStatusIn } connections FaultProtection { @@ -182,11 +191,13 @@ module Ref { frameAccumulator.bufferDeallocate -> commsBufferManager.bufferSendIn frameAccumulator.bufferAllocate -> commsBufferManager.bufferGetCallee # FrameAccumulator <-> Deframer - frameAccumulator.dataOut -> deframer.dataIn - deframer.dataReturnOut -> frameAccumulator.dataReturnIn + frameAccumulator.dataOut -> tcDeframer.dataIn + tcDeframer.dataReturnOut -> frameAccumulator.dataReturnIn + tcDeframer.dataOut -> spacePacketDeframer.dataIn + spacePacketDeframer.dataReturnOut -> tcDeframer.dataReturnIn # Deframer <-> Router - deframer.dataOut -> fprimeRouter.dataIn - fprimeRouter.dataReturnOut -> deframer.dataReturnIn + spacePacketDeframer.dataOut -> fprimeRouter.dataIn + fprimeRouter.dataReturnOut -> spacePacketDeframer.dataReturnIn # Router buffer allocations fprimeRouter.bufferAllocate -> commsBufferManager.bufferGetCallee fprimeRouter.bufferDeallocate -> commsBufferManager.bufferSendIn diff --git a/Svc/CCSDS/CMakeLists.txt b/Svc/CCSDS/CMakeLists.txt index 616c26b44b7..7982dd49cb2 100644 --- a/Svc/CCSDS/CMakeLists.txt +++ b/Svc/CCSDS/CMakeLists.txt @@ -1,2 +1,6 @@ add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Types/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/SpacePacketDeframer/") +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/SpacePacketFramer/") +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/TCDeframer/") +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/TMFramer/") +# add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Utils/") diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp index b7543d8f590..8c8ca0c233b 100644 --- a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp @@ -6,6 +6,7 @@ #include "Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp" #include "Svc/CCSDS/Types/SpacePacketHeaderSerializableAc.hpp" +#include "Svc/CCSDS/Types/FppConstantsAc.hpp" namespace Svc { @@ -23,7 +24,7 @@ SpacePacketDeframer ::~SpacePacketDeframer() {} // Handler implementations for typed input ports // ---------------------------------------------------------------------- -void SpacePacketDeframer ::framedIn_handler(FwIndexType portNum, Fw::Buffer& data, CommsCfg::FrameContext& context) { +void SpacePacketDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { // ################################ // CCSDS SpacePacket Format: // 6 octets - Primary Header @@ -39,52 +40,32 @@ void SpacePacketDeframer ::framedIn_handler(FwIndexType portNum, Fw::Buffer& dat // 16b - n/a - Packet Data Length // ################################ - FW_ASSERT(data.getSize() >= Svc::CCSDS::Types::SpacePacketHeader::SERIALIZED_SIZE, data.getSize()); + FW_ASSERT(data.getSize() >= Svc::CCSDS::Types::SpacePacketHeader::SERIALIZED_SIZE, static_cast(data.getSize())); CCSDS::Types::SpacePacketHeader header; Fw::SerializeStatus status = data.getDeserializer().deserialize(header); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); - U16 apid = header.getpacketIdentification() & 0x07FF; - - // // Read first byte from ring - // U8 byte = data.getData()[0]; - // // Unpack Packet Version Number (PVN) - // U8 pvn = (byte & 0xE0) >> 5; // 0xE0 = 0b11100000 - // // Unpack Packet Type (PT) - // U8 pt = (byte & 0x10) >> 4; // 0x10 = 0b00010000 - // // Unpack Secondary Header Flag (SHF) - // U8 shf = (byte & 0x08) >> 3; // 0x08 = 0b00001000 - - // // Unpack APID - // U16 apid = ((byte & 0x07) << 8); // 0x07 = 0b00000111 - // byte = data.getData()[1]; - // apid |= byte; - context.setapid(apid); - - // Sequence flag - byte = data.getData()[2]; - U8 seq_flag = (byte & 0xC0) >> 6; // 0xC0 = 0b11000000 - - // Sequence count - U16 seq_count = (byte & 0x3F) << 8; // 0x3F = 0b00111111 - byte = data.getData()[3]; - seq_count |= byte; - - // Packet length - byte = data.getData()[4]; - U16 pkt_length = byte << 8; - byte = data.getData()[5]; - pkt_length |= byte; + U16 apid = header.getpacketIdentification() & CCSDS::Types::SpacePacketMasks::ApidMask; + ComCfg::FrameContext contextCopy = context; + contextCopy.setapid(apid); + // TODO: Add checks and events in case of failure + U16 pkt_length = header.getpacketDataLength(); // Set data buffer to be of the encapsulated data: HEADER (6 bytes) | PACKET DATA data.setData(data.getData() + Svc::CCSDS::Types::SpacePacketHeader::SERIALIZED_SIZE); data.setSize(pkt_length); - this->deframedOut_out(0, data, context); + this->dataOut_out(0, data, contextCopy); } -} // namespace CCSDS +void SpacePacketDeframer ::dataReturnIn_handler(FwIndexType portNum, + Fw::Buffer& data, + const ComCfg::FrameContext& context) { + this->dataReturnOut_out(0, data, context); +} + +} // namespace CCSDS } // namespace Svc diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp index c12dce2c2b9..ff888acb747 100644 --- a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp @@ -5,8 +5,11 @@ module CCSDS { include "../../Interfaces/DeframerInterface.fppi" - @ Port for deallocating dropped frames - output port bufferDeallocate: Fw.BufferSend + @ Port for returning ownership of received frame buffers + output port dataReturnOut: Svc.ComDataWithContext + + @ Port receiving back ownership of sent frame buffers + sync input port dataReturnIn: Svc.ComDataWithContext ############################################################################### # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp index 0de8fa31fa2..99beb9b79e4 100644 --- a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp @@ -1,6 +1,6 @@ // ====================================================================== // \title SpacePacketDeframer.hpp -// \author thomas-bc +// \author chammard // \brief hpp file for SpacePacketDeframer component implementation class // ====================================================================== @@ -26,18 +26,24 @@ class SpacePacketDeframer final : public SpacePacketDeframerComponentBase { //! Destroy SpacePacketDeframer object ~SpacePacketDeframer(); - PRIVATE: + private: // ---------------------------------------------------------------------- // Handler implementations for typed input ports // ---------------------------------------------------------------------- - //! Handler implementation for framedIn + //! Handler implementation for dataIn //! //! Port to receive framed data, with optional context - void framedIn_handler(FwIndexType portNum, //!< The port number - Fw::Buffer& data, - CommsCfg::FrameContext& context) override; + void dataIn_handler(FwIndexType portNum, //!< The port number + Fw::Buffer& data, + const ComCfg::FrameContext& context) override; + //! Handler implementation for dataReturnIn + //! + //! Port receiving back ownership of sent frame buffers + void dataReturnIn_handler(FwIndexType portNum, //!< The port number + Fw::Buffer& data, + const ComCfg::FrameContext& context) override; }; } // namespace CCSDS diff --git a/Svc/CCSDS/SpacePacketDeframer/TCDeframer/CMakeLists.txt b/Svc/CCSDS/SpacePacketDeframer/TCDeframer/CMakeLists.txt new file mode 100644 index 00000000000..4d67d7aeae7 --- /dev/null +++ b/Svc/CCSDS/SpacePacketDeframer/TCDeframer/CMakeLists.txt @@ -0,0 +1,21 @@ +#### +# F prime CMakeLists.txt: +# +# SOURCE_FILES: combined list of source and autocoding files +# MOD_DEPS: (optional) module dependencies +# UT_SOURCE_FILES: list of source files for unit tests +# +#### +set(SOURCE_FILES + "${CMAKE_CURRENT_LIST_DIR}/TCDeframer.fpp" + "${CMAKE_CURRENT_LIST_DIR}/TCDeframer.cpp" +) + +# Uncomment and add any modules that this component depends on, else +# they might not be available when cmake tries to build this component. + +set(MOD_DEPS + Svc_CCSDS_Types +) + +register_fprime_module() diff --git a/Svc/CCSDS/SpacePacketDeframer/TCDeframer/TCDeframer.cpp b/Svc/CCSDS/SpacePacketDeframer/TCDeframer/TCDeframer.cpp new file mode 100644 index 00000000000..19b138923f7 --- /dev/null +++ b/Svc/CCSDS/SpacePacketDeframer/TCDeframer/TCDeframer.cpp @@ -0,0 +1,64 @@ +// ====================================================================== +// \title TCDeframer.cpp +// \author thomas-bc +// \brief cpp file for TCDeframer component implementation class +// ====================================================================== + +#include "Svc/CCSDS/TCDeframer/TCDeframer.hpp" +#include "Svc/CCSDS/Types/TCFrameHeaderSerializableAc.hpp" +#include "Svc/CCSDS/Types/FppConstantsAc.hpp" +#include "FpConfig.hpp" + +namespace Svc { +namespace CCSDS { +// ---------------------------------------------------------------------- +// Component construction and destruction +// ---------------------------------------------------------------------- + +TCDeframer ::TCDeframer(const char* const compName) + : TCDeframerComponentBase(compName) {} + +TCDeframer ::~TCDeframer() {} + +// ---------------------------------------------------------------------- +// Handler implementations for user-defined typed input ports +// ---------------------------------------------------------------------- + +void TCDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { + + // CCSDS TC Format: + // 5 octets - TC Primary Header + // Up to 1019 octets - Data Field (including optional 2 octets frame error control field) + + // CCSDS TC Primary Header: + // 2b - 00 - TF Version Number + // 1b - 0/1 - Bypass Flag (0 = FARM checks enabled, 1 = FARM checks bypassed) + // 1b - 0/1 - Control Command Flag (0 = Type-D data, 1 = Type-C data) + // 2b - 00 - Reserved Spare (set to 00) + // 10b- XX - Spacecraft ID + // 6b - XX - Virtual Channel ID + // 10b- XX - Frame Length + // 8b - XX - Frame Sequence Number + + FW_ASSERT(data.getSize() >= CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE, static_cast(data.getSize())); + + CCSDS::Types::TCFrameHeader header; + Fw::SerializeStatus status = data.getDeserializer().deserialize(header); + FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); + + U16 frame_length = header.getvcIdAndLength() & CCSDS::Types::TCFrameMasks::FrameLengthMask; + // U8 vc_id = (header.getvcIdAndLength() & CCSDS::Types::TCFrameMasks::VcIdMask) >> 2; + // TODO: check if frame_length is same as length of data minus header size + data.setData(data.getData() + Svc::CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE); + data.setSize(frame_length); + + this->dataOut_out(0, data, context); + +} + +void TCDeframer ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer, const ComCfg::FrameContext& context) { + this->dataReturnOut_out(0, fwBuffer, context); +} + +} // namespace CCSDS +} // namespace Svc diff --git a/Svc/CCSDS/SpacePacketDeframer/TCDeframer/TCDeframer.fpp b/Svc/CCSDS/SpacePacketDeframer/TCDeframer/TCDeframer.fpp new file mode 100644 index 00000000000..403862446f8 --- /dev/null +++ b/Svc/CCSDS/SpacePacketDeframer/TCDeframer/TCDeframer.fpp @@ -0,0 +1,37 @@ +module Svc { +module CCSDS { + @ Deframer for the TC Space Data Link Protocl (CCSDS Standard) + passive component TCDeframer { + + include "../../Interfaces/DeframerInterface.fppi" + + @ Port for returning ownership of received frame buffers + output port dataReturnOut: Svc.ComDataWithContext + + @ Port receiving back ownership of sent frame buffers + sync input port dataReturnIn: Svc.ComDataWithContext + + ############################################################################### + # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # + ############################################################################### + @ Port for requesting the current time + time get port timeCaller + + @ Port for sending textual representation of events + text event port logTextOut + + @ Port for sending events to downlink + event port logOut + + @ Port for sending telemetry channels to downlink + telemetry port tlmOut + + @ Port to return the value of a parameter + param get port prmGetOut + + @Port to set the value of a parameter + param set port prmSetOut + + } +} +} \ No newline at end of file diff --git a/Svc/CCSDS/SpacePacketDeframer/TCDeframer/TCDeframer.hpp b/Svc/CCSDS/SpacePacketDeframer/TCDeframer/TCDeframer.hpp new file mode 100644 index 00000000000..0e3b48c6f3d --- /dev/null +++ b/Svc/CCSDS/SpacePacketDeframer/TCDeframer/TCDeframer.hpp @@ -0,0 +1,53 @@ +// ====================================================================== +// \title TCDeframer.hpp +// \author thomas-bc +// \brief hpp file for TCDeframer component implementation class +// ====================================================================== + +#ifndef Svc_CCSDS_TCDeframer_HPP +#define Svc_CCSDS_TCDeframer_HPP + +#include "Svc/CCSDS/TCDeframer/TCDeframerComponentAc.hpp" + +namespace Svc { +namespace CCSDS { +class TCDeframer : public TCDeframerComponentBase { + + static const U8 SPACE_PACKET_HEADER_SIZE = 5; + static const U8 SPACE_PACKET_TRAILER_SIZE = 2; + public: + // ---------------------------------------------------------------------- + // Component construction and destruction + // ---------------------------------------------------------------------- + + //! Construct TCDeframer object + TCDeframer(const char* const compName //!< The component name + ); + + //! Destroy TCDeframer object + ~TCDeframer(); + + private: + // ---------------------------------------------------------------------- + // Handler implementations for user-defined typed input ports + // ---------------------------------------------------------------------- + + //! Handler implementation for dataIn + //! + //! Port to receive framed data + void dataIn_handler(FwIndexType portNum, //!< The port number + Fw::Buffer& data, + const ComCfg::FrameContext& context) override; + + //! Handler implementation for dataReturnIn + //! + //! Port receiving back ownership of sent frame buffers + void dataReturnIn_handler(FwIndexType portNum, //!< The port number + Fw::Buffer& data, //!< The buffer + const ComCfg::FrameContext& context) override; + +}; +} // namespace CCSDS +} // namespace Svc + +#endif diff --git a/Svc/CCSDS/SpacePacketDeframer/TCDeframer/docs/sdd.md b/Svc/CCSDS/SpacePacketDeframer/TCDeframer/docs/sdd.md new file mode 100644 index 00000000000..a8cb66d1945 --- /dev/null +++ b/Svc/CCSDS/SpacePacketDeframer/TCDeframer/docs/sdd.md @@ -0,0 +1,66 @@ +# Svc::TCDeframer + +Deframer for the TC Space Data Link Protocl (CCSDS Standard) + +## Usage Examples +Add usage examples here + +### Diagrams +Add diagrams here + +### Typical Usage +And the typical usage of the component here + +## Class Diagram +Add a class diagram here + +## Port Descriptions +| Name | Description | +|---|---| +|---|---| + +## Component States +Add component states in the chart below +| Name | Description | +|---|---| +|---|---| + +## Sequence Diagrams +Add sequence diagrams here + +## Parameters +| Name | Description | +|---|---| +|---|---| + +## Commands +| Name | Description | +|---|---| +|---|---| + +## Events +| Name | Description | +|---|---| +|---|---| + +## Telemetry +| Name | Description | +|---|---| +|---|---| + +## Unit Tests +Add unit test descriptions in the chart below +| Name | Description | Output | Coverage | +|---|---|---|---| +|---|---|---|---| + +## Requirements +Add requirements in the chart below +| Name | Description | Validation | +|---|---|---| +|---|---|---| + +## Change Log +| Date | Description | +|---|---| +|---| Initial Draft | \ No newline at end of file diff --git a/Svc/CCSDS/SpacePacketFramer/CMakeLists.txt b/Svc/CCSDS/SpacePacketFramer/CMakeLists.txt new file mode 100644 index 00000000000..245b3143da0 --- /dev/null +++ b/Svc/CCSDS/SpacePacketFramer/CMakeLists.txt @@ -0,0 +1,44 @@ +#### +# FPrime CMakeLists.txt: +# +# SOURCE_FILES: combined list of source and autocoding files +# MOD_DEPS: (optional) module dependencies +# UT_SOURCE_FILES: list of source files for unit tests +# +# More information in the F´ CMake API documentation: +# https://fprime.jpl.nasa.gov/latest/documentation/reference +# +#### + +set(SOURCE_FILES + "${CMAKE_CURRENT_LIST_DIR}/SpacePacketFramer.fpp" + "${CMAKE_CURRENT_LIST_DIR}/SpacePacketFramer.cpp" +) + +# Uncomment and add any modules that this component depends on, else +# they might not be available when cmake tries to build this component. +# +# Module names are derived from the path from the nearest project/library/framework +# root when not specifically overridden by the developer. i.e. The module defined by +# `Ref/SignalGen/CMakeLists.txt` will be named `Ref_SignalGen`. `Ref/SignalGen` +# is an acceptable alternative and will be internally converted to `Ref_SignalGen`. +# + +set(MOD_DEPS + Svc_CCSDS_Types +) + +register_fprime_module() + + +### Unit Tests ### +# set(UT_SOURCE_FILES +# "${CMAKE_CURRENT_LIST_DIR}/SpacePacketFramer.fpp" +# "${CMAKE_CURRENT_LIST_DIR}/test/ut/SpacePacketFramerTestMain.cpp" +# "${CMAKE_CURRENT_LIST_DIR}/test/ut/SpacePacketFramerTester.cpp" +# ) +# set(UT_MOD_DEPS +# STest +# ) +# set(UT_AUTO_HELPERS ON) +# register_fprime_ut() diff --git a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp new file mode 100644 index 00000000000..e7a1ef9402b --- /dev/null +++ b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp @@ -0,0 +1,82 @@ +// ====================================================================== +// \title SpacePacketFramer.cpp +// \author chammard +// \brief cpp file for SpacePacketFramer component implementation class +// ====================================================================== + +#include "Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp" +#include "Svc/CCSDS/Types/SpacePacketHeaderSerializableAc.hpp" +#include "Svc/CCSDS/Types/FppConstantsAc.hpp" + +namespace Svc { + +namespace CCSDS { + +// ---------------------------------------------------------------------- +// Component construction and destruction +// ---------------------------------------------------------------------- + +SpacePacketFramer ::SpacePacketFramer(const char* const compName) : SpacePacketFramerComponentBase(compName) {} + +SpacePacketFramer ::~SpacePacketFramer() {} + +// ---------------------------------------------------------------------- +// Handler implementations for typed input ports +// ---------------------------------------------------------------------- + +void SpacePacketFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { + CCSDS::Types::SpacePacketHeader header; + Fw::SerializeStatus status; + FwSizeType frameSize = CCSDS::Types::SpacePacketHeader::SERIALIZED_SIZE + data.getSize(); + FW_ASSERT(data.getSize() <= std::numeric_limits::max(), static_cast(frameSize)); + FW_ASSERT(frameSize <= std::numeric_limits::max(), static_cast(frameSize)); + + // Allocate frame buffer + Fw::Buffer frameBuffer = this->bufferAllocate_out(0, static_cast(frameSize)); + auto frameSerializer = frameBuffer.getSerializer(); + + // ----------------------------------------------- + // Header + // ----------------------------------------------- + // PVN is always 0 per Standard - Packet Type is 0 for Telemetry (downlink) - SecHdr flag is 0 for no secondary header + U16 packetIdentification = 0; + packetIdentification |= context.getcomQueueIndex(); // APID = comQueueIndex (for now; TBD how to configure APIDs) + + U16 packetSequenceControl = 0; + packetSequenceControl |= 0x3 << CCSDS::Types::SpacePacketMasks::SeqFlagsOffset; // Sequence Flags 0b11 = unsegmented User Data + packetSequenceControl |= this->m_packetSequenceCount; + this->m_packetSequenceCount += 1; + + // TODO: Assert / event that it fits in a U16 + U16 packetDataLength = static_cast(data.getSize() - 1); // Standard specifies length is number of bytes minus 1 + + header.setpacketIdentification(packetIdentification); + header.setpacketSequenceControl(packetSequenceControl); + header.setpacketDataLength(packetDataLength); + + // ----------------------------------------------- + // Serialize the packet + // ----------------------------------------------- + status = frameSerializer.serialize(header); + FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); + status = frameSerializer.serialize(data.getData(), data.getSize(), Fw::Serialization::OMIT_LENGTH); + FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); + + this->dataOut_out(0, frameBuffer, context); + this->dataReturnOut_out(0, data, context); // return ownership of the original data buffer +} + +void SpacePacketFramer ::comStatusIn_handler(FwIndexType portNum, Fw::Success& condition) { + if (this->isConnected_comStatusOut_OutputPort(portNum)) { + this->comStatusOut_out(portNum, condition); + } +} + +void SpacePacketFramer ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& frameBuffer, const ComCfg::FrameContext& context) { + // dataReturnIn is the allocated buffer coming back from the ComManager (e.g. ComStub) component + this->bufferDeallocate_out(0, frameBuffer); +} + +} // namespace CCSDS + +} // namespace Svc diff --git a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.fpp b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.fpp new file mode 100644 index 00000000000..3e0c1f38265 --- /dev/null +++ b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.fpp @@ -0,0 +1,35 @@ +module Svc { +module CCSDS { + @ Deframer for the CCSDS Space Packet protocol + passive component SpacePacketFramer { + + include "../../Interfaces/FramerInterface.fppi" + + output port bufferAllocate: Fw.BufferGet + output port bufferDeallocate: Fw.BufferSend + + ############################################################################### + # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # + ############################################################################### + @ Port for requesting the current time + time get port timeCaller + + @ Port for sending textual representation of events + text event port logTextOut + + @ Port for sending events to downlink + event port logOut + + @ Port for sending telemetry channels to downlink + telemetry port tlmOut + + @ Port to return the value of a parameter + param get port prmGetOut + + @ Port to set the value of a parameter + param set port prmSetOut + + } + +} # end CCSDS +} # end Svc diff --git a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp new file mode 100644 index 00000000000..53248495b75 --- /dev/null +++ b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp @@ -0,0 +1,63 @@ +// ====================================================================== +// \title SpacePacketFramer.hpp +// \author chammard +// \brief hpp file for SpacePacketFramer component implementation class +// ====================================================================== + +#ifndef Svc_CCSDS_SpacePacketFramer_HPP +#define Svc_CCSDS_SpacePacketFramer_HPP + +#include "Svc/CCSDS/SpacePacketFramer/SpacePacketFramerComponentAc.hpp" + +namespace Svc { + +namespace CCSDS { + +class SpacePacketFramer final : public SpacePacketFramerComponentBase { + public: + // ---------------------------------------------------------------------- + // Component construction and destruction + // ---------------------------------------------------------------------- + + //! Construct SpacePacketFramer object + SpacePacketFramer(const char* const compName //!< The component name + ); + + //! Destroy SpacePacketFramer object + ~SpacePacketFramer(); + + PRIVATE: + // ---------------------------------------------------------------------- + // Handler implementations for typed input ports + // ---------------------------------------------------------------------- + + //! Handler implementation for comStatusIn + //! + //! Port receiving the general status from the downstream component + //! indicating it is ready or not-ready for more input + void comStatusIn_handler(FwIndexType portNum, //!< The port number + Fw::Success& condition //!< Condition success/failure + ) override; + + //! Handler implementation for dataIn + //! + //! Port to receive data to frame, in a Fw::Buffer with optional context + void dataIn_handler(FwIndexType portNum, //!< The port number + Fw::Buffer& data, + const ComCfg::FrameContext& context) override; + + //! Handler implementation for dataReturnIn + //! + //! Buffer coming from a deallocate call in a ComDriver component + void dataReturnIn_handler(FwIndexType portNum, //!< The port number + Fw::Buffer& data, + const ComCfg::FrameContext& context) override; + + U16 m_packetSequenceCount = 0; //!< Packet sequence count (TODO: needs to be per-APID; and wrap around at 14 bits) +}; + +} // namespace CCSDS + +} // namespace Svc + +#endif diff --git a/Svc/CCSDS/SpacePacketFramer/docs/sdd.md b/Svc/CCSDS/SpacePacketFramer/docs/sdd.md new file mode 100644 index 00000000000..82a30b4883c --- /dev/null +++ b/Svc/CCSDS/SpacePacketFramer/docs/sdd.md @@ -0,0 +1,66 @@ +# CCSDS::SpacePacketFramer + +Deframer for the CCSDS Space Packet protocol + +## Usage Examples +Add usage examples here + +### Diagrams +Add diagrams here + +### Typical Usage +And the typical usage of the component here + +## Class Diagram +Add a class diagram here + +## Port Descriptions +| Name | Description | +|---|---| +|---|---| + +## Component States +Add component states in the chart below +| Name | Description | +|---|---| +|---|---| + +## Sequence Diagrams +Add sequence diagrams here + +## Parameters +| Name | Description | +|---|---| +|---|---| + +## Commands +| Name | Description | +|---|---| +|---|---| + +## Events +| Name | Description | +|---|---| +|---|---| + +## Telemetry +| Name | Description | +|---|---| +|---|---| + +## Unit Tests +Add unit test descriptions in the chart below +| Name | Description | Output | Coverage | +|---|---|---|---| +|---|---|---|---| + +## Requirements +Add requirements in the chart below +| Name | Description | Validation | +|---|---|---| +|---|---|---| + +## Change Log +| Date | Description | +|---|---| +|---| Initial Draft | \ No newline at end of file diff --git a/Svc/CCSDS/TCDeframer/CMakeLists.txt b/Svc/CCSDS/TCDeframer/CMakeLists.txt new file mode 100644 index 00000000000..4d67d7aeae7 --- /dev/null +++ b/Svc/CCSDS/TCDeframer/CMakeLists.txt @@ -0,0 +1,21 @@ +#### +# F prime CMakeLists.txt: +# +# SOURCE_FILES: combined list of source and autocoding files +# MOD_DEPS: (optional) module dependencies +# UT_SOURCE_FILES: list of source files for unit tests +# +#### +set(SOURCE_FILES + "${CMAKE_CURRENT_LIST_DIR}/TCDeframer.fpp" + "${CMAKE_CURRENT_LIST_DIR}/TCDeframer.cpp" +) + +# Uncomment and add any modules that this component depends on, else +# they might not be available when cmake tries to build this component. + +set(MOD_DEPS + Svc_CCSDS_Types +) + +register_fprime_module() diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.cpp b/Svc/CCSDS/TCDeframer/TCDeframer.cpp new file mode 100644 index 00000000000..6b6d3b44222 --- /dev/null +++ b/Svc/CCSDS/TCDeframer/TCDeframer.cpp @@ -0,0 +1,66 @@ +// ====================================================================== +// \title TCDeframer.cpp +// \author thomas-bc +// \brief cpp file for TCDeframer component implementation class +// ====================================================================== + +#include "Svc/CCSDS/TCDeframer/TCDeframer.hpp" +#include "Svc/CCSDS/Types/TCFrameHeaderSerializableAc.hpp" +#include "Svc/CCSDS/Types/FppConstantsAc.hpp" +#include "FpConfig.hpp" + +namespace Svc { +namespace CCSDS { +// ---------------------------------------------------------------------- +// Component construction and destruction +// ---------------------------------------------------------------------- + +TCDeframer ::TCDeframer(const char* const compName) + : TCDeframerComponentBase(compName) {} + +TCDeframer ::~TCDeframer() {} + +// ---------------------------------------------------------------------- +// Handler implementations for user-defined typed input ports +// ---------------------------------------------------------------------- + +void TCDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { + + // CCSDS TC Format: + // 5 octets - TC Primary Header + // Up to 1019 octets - Data Field (including optional 2 octets frame error control field) + + // CCSDS TC Primary Header: + // 2b - 00 - TF Version Number + // 1b - 0/1 - Bypass Flag (0 = FARM checks enabled, 1 = FARM checks bypassed) + // 1b - 0/1 - Control Command Flag (0 = Type-D data, 1 = Type-C data) + // 2b - 00 - Reserved Spare (set to 00) + // 10b- XX - Spacecraft ID + // 6b - XX - Virtual Channel ID + // 10b- XX - Frame Length + // 8b - XX - Frame Sequence Number + + FW_ASSERT(data.getSize() >= CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE, static_cast(data.getSize())); + + CCSDS::Types::TCFrameHeader header; + Fw::SerializeStatus status = data.getDeserializer().deserialize(header); + FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); + + U16 frame_length = header.getvcIdAndLength() & CCSDS::Types::TCFrameMasks::FrameLengthMask; + // U8 vc_id = (header.getvcIdAndLength() & CCSDS::Types::TCFrameMasks::VcIdMask) >> 2; + // TODO: check if frame_length is same as length of data minus header size + // TODO: Add checks and events in case of failure + + data.setData(data.getData() + Svc::CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE); + data.setSize(frame_length); + + this->dataOut_out(0, data, context); + +} + +void TCDeframer ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer, const ComCfg::FrameContext& context) { + this->dataReturnOut_out(0, fwBuffer, context); +} + +} // namespace CCSDS +} // namespace Svc diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.fpp b/Svc/CCSDS/TCDeframer/TCDeframer.fpp new file mode 100644 index 00000000000..403862446f8 --- /dev/null +++ b/Svc/CCSDS/TCDeframer/TCDeframer.fpp @@ -0,0 +1,37 @@ +module Svc { +module CCSDS { + @ Deframer for the TC Space Data Link Protocl (CCSDS Standard) + passive component TCDeframer { + + include "../../Interfaces/DeframerInterface.fppi" + + @ Port for returning ownership of received frame buffers + output port dataReturnOut: Svc.ComDataWithContext + + @ Port receiving back ownership of sent frame buffers + sync input port dataReturnIn: Svc.ComDataWithContext + + ############################################################################### + # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # + ############################################################################### + @ Port for requesting the current time + time get port timeCaller + + @ Port for sending textual representation of events + text event port logTextOut + + @ Port for sending events to downlink + event port logOut + + @ Port for sending telemetry channels to downlink + telemetry port tlmOut + + @ Port to return the value of a parameter + param get port prmGetOut + + @Port to set the value of a parameter + param set port prmSetOut + + } +} +} \ No newline at end of file diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.hpp b/Svc/CCSDS/TCDeframer/TCDeframer.hpp new file mode 100644 index 00000000000..0e3b48c6f3d --- /dev/null +++ b/Svc/CCSDS/TCDeframer/TCDeframer.hpp @@ -0,0 +1,53 @@ +// ====================================================================== +// \title TCDeframer.hpp +// \author thomas-bc +// \brief hpp file for TCDeframer component implementation class +// ====================================================================== + +#ifndef Svc_CCSDS_TCDeframer_HPP +#define Svc_CCSDS_TCDeframer_HPP + +#include "Svc/CCSDS/TCDeframer/TCDeframerComponentAc.hpp" + +namespace Svc { +namespace CCSDS { +class TCDeframer : public TCDeframerComponentBase { + + static const U8 SPACE_PACKET_HEADER_SIZE = 5; + static const U8 SPACE_PACKET_TRAILER_SIZE = 2; + public: + // ---------------------------------------------------------------------- + // Component construction and destruction + // ---------------------------------------------------------------------- + + //! Construct TCDeframer object + TCDeframer(const char* const compName //!< The component name + ); + + //! Destroy TCDeframer object + ~TCDeframer(); + + private: + // ---------------------------------------------------------------------- + // Handler implementations for user-defined typed input ports + // ---------------------------------------------------------------------- + + //! Handler implementation for dataIn + //! + //! Port to receive framed data + void dataIn_handler(FwIndexType portNum, //!< The port number + Fw::Buffer& data, + const ComCfg::FrameContext& context) override; + + //! Handler implementation for dataReturnIn + //! + //! Port receiving back ownership of sent frame buffers + void dataReturnIn_handler(FwIndexType portNum, //!< The port number + Fw::Buffer& data, //!< The buffer + const ComCfg::FrameContext& context) override; + +}; +} // namespace CCSDS +} // namespace Svc + +#endif diff --git a/Svc/CCSDS/TCDeframer/docs/sdd.md b/Svc/CCSDS/TCDeframer/docs/sdd.md new file mode 100644 index 00000000000..a8cb66d1945 --- /dev/null +++ b/Svc/CCSDS/TCDeframer/docs/sdd.md @@ -0,0 +1,66 @@ +# Svc::TCDeframer + +Deframer for the TC Space Data Link Protocl (CCSDS Standard) + +## Usage Examples +Add usage examples here + +### Diagrams +Add diagrams here + +### Typical Usage +And the typical usage of the component here + +## Class Diagram +Add a class diagram here + +## Port Descriptions +| Name | Description | +|---|---| +|---|---| + +## Component States +Add component states in the chart below +| Name | Description | +|---|---| +|---|---| + +## Sequence Diagrams +Add sequence diagrams here + +## Parameters +| Name | Description | +|---|---| +|---|---| + +## Commands +| Name | Description | +|---|---| +|---|---| + +## Events +| Name | Description | +|---|---| +|---|---| + +## Telemetry +| Name | Description | +|---|---| +|---|---| + +## Unit Tests +Add unit test descriptions in the chart below +| Name | Description | Output | Coverage | +|---|---|---|---| +|---|---|---|---| + +## Requirements +Add requirements in the chart below +| Name | Description | Validation | +|---|---|---| +|---|---|---| + +## Change Log +| Date | Description | +|---|---| +|---| Initial Draft | \ No newline at end of file diff --git a/Svc/CCSDS/TMFramer/CMakeLists.txt b/Svc/CCSDS/TMFramer/CMakeLists.txt new file mode 100644 index 00000000000..f79c0f729fe --- /dev/null +++ b/Svc/CCSDS/TMFramer/CMakeLists.txt @@ -0,0 +1,21 @@ +#### +# F prime CMakeLists.txt: +# +# SOURCE_FILES: combined list of source and autocoding files +# MOD_DEPS: (optional) module dependencies +# UT_SOURCE_FILES: list of source files for unit tests +# +#### +set(SOURCE_FILES + "${CMAKE_CURRENT_LIST_DIR}/TMFramer.fpp" + "${CMAKE_CURRENT_LIST_DIR}/TMFramer.cpp" +) + +# Uncomment and add any modules that this component depends on, else +# they might not be available when cmake tries to build this component. + +set(MOD_DEPS + Svc_CCSDS_Types +) + +register_fprime_module() diff --git a/Svc/CCSDS/TMFramer/TMFramer.cpp b/Svc/CCSDS/TMFramer/TMFramer.cpp new file mode 100644 index 00000000000..f2feb441546 --- /dev/null +++ b/Svc/CCSDS/TMFramer/TMFramer.cpp @@ -0,0 +1,101 @@ +// ====================================================================== +// \title TMFramer.cpp +// \author chammard +// \brief cpp file for TMFramer component implementation class +// ====================================================================== + +#include "Svc/CCSDS/TMFramer/TMFramer.hpp" +#include "Svc/CCSDS/Types/TMFrameHeaderSerializableAc.hpp" +#include "Svc/CCSDS/Types/TMFrameTrailerSerializableAc.hpp" +#include "Svc/CCSDS/Types/FppConstantsAc.hpp" +#include "Svc/CCSDS/Utils/CRC16.hpp" +#include "config/FppConstantsAc.hpp" + +namespace Svc { + +namespace CCSDS { + +// ---------------------------------------------------------------------- +// Component construction and destruction +// ---------------------------------------------------------------------- + +TMFramer ::TMFramer(const char* const compName) : TMFramerComponentBase(compName) {} + +TMFramer ::~TMFramer() {} + +// ---------------------------------------------------------------------- +// Handler implementations for typed input ports +// ---------------------------------------------------------------------- + +void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { + // ----------------------------------------------- + // Header + // ----------------------------------------------- + CCSDS::Types::TMFrameHeader header; + U16 channelIds = 0; + channelIds |= ComCfg::FppConstant_SpacecraftId::SpacecraftId << CCSDS::Types::TMFrameMasks::spacecraftIdOffset; + channelIds |= 0x00 << CCSDS::Types::TMFrameMasks::virtualChannelIdOffset; // VCID + channelIds |= 0x0; // No Operational Control Field: Flag set to 0 + + U8 masterFrameCount = 0; + U8 virtualFrameCount = 0; + + // Data Field Status: + // - all flags to 0 except segment length id 0b11 per standard + // - First Header Pointer is always 0 since we are always wrapping a single entire packet at offset 0 + U16 dataFieldStatus = 0; + dataFieldStatus |= 0x3 << CCSDS::Types::TMFrameMasks::segLengthOffset; // Seg Length 0b11 per Standard + + header.setchannelIds(channelIds); + header.setmasterFrameCount(masterFrameCount); + header.setvirtualFrameCount(virtualFrameCount); + header.setdataFieldStatus(dataFieldStatus); + + // ------------------------------------------------- + // Serialize the Frame + // ------------------------------------------------- + + Fw::SerializeStatus status; + FwSizeType frameSize = CCSDS::Types::TMFrameHeader::SERIALIZED_SIZE + data.getSize() + CCSDS::Types::TMFrameHeader::SERIALIZED_SIZE; + FW_ASSERT(data.getSize() <= std::numeric_limits::max(), static_cast(frameSize)); + FW_ASSERT(frameSize <= std::numeric_limits::max(), static_cast(frameSize)); + // Allocate frame buffer + Fw::Buffer frameBuffer = Fw::Buffer(this->m_frameBuffer, sizeof(this->m_frameBuffer)); + auto frameSerializer = frameBuffer.getSerializer(); + + status = frameSerializer.serialize(header); + FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); + status = frameSerializer.serialize(data.getData(), data.getSize(), Fw::Serialization::OMIT_LENGTH); + FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); + + // ------------------------------------------------- + // Trailer: Compute CRC + // ------------------------------------------------- + CCSDS::Types::TMFrameTrailer trailer; + U16 crc = CCSDS::Utils::CRC16::compute(frameBuffer.getData(), sizeof(this->m_frameBuffer) - CCSDS::Types::TMFrameTrailer::SERIALIZED_SIZE); + trailer.setfecf(crc); // Frame Error Control Field + + frameSerializer.moveSerToOffset(ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize - CCSDS::Types::TMFrameTrailer::SERIALIZED_SIZE); + status = frameSerializer.serialize(trailer); + FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); + + this->dataOut_out(0, frameBuffer, context); + this->dataReturnOut_out(0, data, context); // return ownership of the original data buffer +} + +void TMFramer ::comStatusIn_handler(FwIndexType portNum, Fw::Success& condition) { + if (this->isConnected_comStatusOut_OutputPort(portNum)) { + this->comStatusOut_out(portNum, condition); + } +} + +void TMFramer ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& frameBuffer, const ComCfg::FrameContext& context) { + // dataReturnIn is the member buffer coming back from the ComManager (e.g. ComStub) component + // this->bufferDeallocate_out(0, frameBuffer); + ::memset(this->m_frameBuffer, 0, sizeof(this->m_frameBuffer)); +} + + +} // namespace CCSDS + +} // namespace Svc diff --git a/Svc/CCSDS/TMFramer/TMFramer.fpp b/Svc/CCSDS/TMFramer/TMFramer.fpp new file mode 100644 index 00000000000..2648ceda1b9 --- /dev/null +++ b/Svc/CCSDS/TMFramer/TMFramer.fpp @@ -0,0 +1,34 @@ +module Svc { +module CCSDS { + @ Deframer for the TM Space Data Link Protocl (CCSDS Standard) + passive component TMFramer { + + include "../../Interfaces/FramerInterface.fppi" + + output port bufferAllocate: Fw.BufferGet + output port bufferDeallocate: Fw.BufferSend + + ############################################################################### + # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # + ############################################################################### + @ Port for requesting the current time + time get port timeCaller + + @ Port for sending textual representation of events + text event port logTextOut + + @ Port for sending events to downlink + event port logOut + + @ Port for sending telemetry channels to downlink + telemetry port tlmOut + + @ Port to return the value of a parameter + param get port prmGetOut + + @Port to set the value of a parameter + param set port prmSetOut + + } +} +} \ No newline at end of file diff --git a/Svc/CCSDS/TMFramer/TMFramer.hpp b/Svc/CCSDS/TMFramer/TMFramer.hpp new file mode 100644 index 00000000000..6735499eac9 --- /dev/null +++ b/Svc/CCSDS/TMFramer/TMFramer.hpp @@ -0,0 +1,63 @@ +// ====================================================================== +// \title TMFramer.hpp +// \author chammard +// \brief hpp file for TMFramer component implementation class +// ====================================================================== + +#ifndef Svc_CCSDS_TMFramer_HPP +#define Svc_CCSDS_TMFramer_HPP + +#include "Svc/CCSDS/TMFramer/TMFramerComponentAc.hpp" + +namespace Svc { + +namespace CCSDS { + +class TMFramer final : public TMFramerComponentBase { + public: + // ---------------------------------------------------------------------- + // Component construction and destruction + // ---------------------------------------------------------------------- + + //! Construct TMFramer object + TMFramer(const char* const compName //!< The component name + ); + + //! Destroy TMFramer object + ~TMFramer(); + + PRIVATE: + // ---------------------------------------------------------------------- + // Handler implementations for typed input ports + // ---------------------------------------------------------------------- + + //! Handler implementation for comStatusIn + //! + //! Port receiving the general status from the downstream component + //! indicating it is ready or not-ready for more input + void comStatusIn_handler(FwIndexType portNum, //!< The port number + Fw::Success& condition //!< Condition success/failure + ) override; + + //! Handler implementation for dataIn + //! + //! Port to receive data to frame, in a Fw::Buffer with optional context + void dataIn_handler(FwIndexType portNum, //!< The port number + Fw::Buffer& data, + const ComCfg::FrameContext& context) override; + + //! Handler implementation for dataReturnIn + //! + //! Buffer coming from a deallocate call in a ComDriver component + void dataReturnIn_handler(FwIndexType portNum, //!< The port number + Fw::Buffer& data, + const ComCfg::FrameContext& context) override; + + U8 m_frameBuffer[ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize]; //!< Buffer to hold the frame data +}; + +} // namespace CCSDS + +} // namespace Svc + +#endif diff --git a/Svc/CCSDS/TMFramer/docs/sdd.md b/Svc/CCSDS/TMFramer/docs/sdd.md new file mode 100644 index 00000000000..505785b0beb --- /dev/null +++ b/Svc/CCSDS/TMFramer/docs/sdd.md @@ -0,0 +1,66 @@ +# Svc::TMFramer + +Deframer for the TC Space Data Link Protocl (CCSDS Standard) + +## Usage Examples +Add usage examples here + +### Diagrams +Add diagrams here + +### Typical Usage +And the typical usage of the component here + +## Class Diagram +Add a class diagram here + +## Port Descriptions +| Name | Description | +|---|---| +|---|---| + +## Component States +Add component states in the chart below +| Name | Description | +|---|---| +|---|---| + +## Sequence Diagrams +Add sequence diagrams here + +## Parameters +| Name | Description | +|---|---| +|---|---| + +## Commands +| Name | Description | +|---|---| +|---|---| + +## Events +| Name | Description | +|---|---| +|---|---| + +## Telemetry +| Name | Description | +|---|---| +|---|---| + +## Unit Tests +Add unit test descriptions in the chart below +| Name | Description | Output | Coverage | +|---|---|---|---| +|---|---|---|---| + +## Requirements +Add requirements in the chart below +| Name | Description | Validation | +|---|---|---| +|---|---|---| + +## Change Log +| Date | Description | +|---|---| +|---| Initial Draft | \ No newline at end of file diff --git a/Svc/CCSDS/Types/Types.fpp b/Svc/CCSDS/Types/Types.fpp index 0ddbdce7300..bd576d4351e 100644 --- a/Svc/CCSDS/Types/Types.fpp +++ b/Svc/CCSDS/Types/Types.fpp @@ -14,6 +14,21 @@ module Types { constant PktTypeMask = 0x1000 @< 0b0001000000000000 constant SecHdrMask = 0x0800 @< 0b0000100000000000 constant ApidMask = 0x07FF @< 0b0000011111111111 + constant SecHdrOffset = 11 + constant PktTypeOffset = 12 + constant PvnOffset = 13 + constant SeqFlagsMask = 0xC000 @< 0b1100000000000000 + constant SeqFlagsOffset = 14 + } + + module TCFrameMasks { + constant FrameVersionMask = 0xC000 + constant BypassFlagMask = 0x2000 + constant ControlFlagMask = 0x1000 + constant ReservedMask = 0x0C00 + constant SpacecraftIdMask = 0x03FF + constant VcIdMask = 0xFC00 + constant FrameLengthMask = 0x03FF } @ Describes the frame header format for the SpacePacket communications protocol @@ -30,8 +45,30 @@ module Types { frameSequenceNbr: U8 @< 8 bits Frame Sequence Number } + struct TCFrameTrailer { + fecf: U16 @< 16 bit Frame Error Control Field (CRC16) + } + + module TMFrameMasks { + constant frameVersionOffset = 14 + constant spacecraftIdOffset = 4 + constant virtualChannelIdOffset = 1 + constant segLengthOffset = 11 + } + + struct TMFrameHeader { + # TODO: rename: channelIds is called GVCID Global Virtual Channel Identifier + channelIds: U16, @< 2 bit Frame Version | 10 bit spacecraft ID | 3 bit virtual channel ID | 1 bit OCF flag + masterFrameCount: U8, @< 8 bit Master Channel Frame Count + virtualFrameCount: U8, @< 8 bit Virtual Channel Frame Count + dataFieldStatus: U16 @< 1 bit 2nd Header | 1 bit sync | 1 bit pkt order | 2 bit seg len | 11 bit header ptr + } + struct TMFrameTrailer { + fecf: U16 @< 16 bit Frame Error Control Field (CRC16) + } + +} } } -} \ No newline at end of file diff --git a/Svc/CCSDS/Utils/CMakeLists.txt b/Svc/CCSDS/Utils/CMakeLists.txt new file mode 100644 index 00000000000..f45e61e3899 --- /dev/null +++ b/Svc/CCSDS/Utils/CMakeLists.txt @@ -0,0 +1,28 @@ +#### +# FPrime CMakeLists.txt: +# +# SOURCE_FILES: combined list of source and autocoding files +# MOD_DEPS: (optional) module dependencies +# UT_SOURCE_FILES: list of source files for unit tests +# +# More information in the F´ CMake API documentation: +# https://fprime.jpl.nasa.gov/latest/documentation/reference/ +#### + +set(SOURCE_FILES + "${CMAKE_CURRENT_LIST_DIR}/Utils.fpp" +) + +# Uncomment and add any modules that this module depends on, else +# they might not be available when cmake tries to build this module. +# +# Module names are derived from the path from the nearest project/library/framework +# root when not specifically overridden by the developer. i.e. The module defined by +# `Ref/SignalGen/CMakeLists.txt` will be named `Ref_SignalGen`. `Ref/SignalGen` +# is an acceptable alternative and will be internally converted to `Ref_SignalGen`. +# +#set(MOD_DEPS +# MyPackage_MyOtherModule +#) + +register_fprime_module() diff --git a/Svc/CCSDS/Utils/CRC16.hpp b/Svc/CCSDS/Utils/CRC16.hpp new file mode 100644 index 00000000000..00d9011871b --- /dev/null +++ b/Svc/CCSDS/Utils/CRC16.hpp @@ -0,0 +1,58 @@ +#ifndef SVC_CCSDS_UTILS_CRC16_HPP +#define SVC_CCSDS_UTILS_CRC16_HPP + +#include "Fw/Types/BasicTypes.hpp" +// Include the lic crc c library: +extern "C" { +#include +} + +namespace Svc { +namespace CCSDS { +namespace Utils { + +//! \brief CRC16 CCITT implementation +//! +//! CCSDS uses a CRC16 (CCITT) implementation with polynomial 0x1021, initial value of 0xFFFF, and XOR of 0x0000. +//! +class CRC16 { + public: + // Initial value is 0xFFFF + CRC16() : m_crc(std::numeric_limits::max()) {} + + //! \brief update CRC with one new byte + //! + //! Update function for CRC taking previous value from member variable and updating it. + //! + //! \param new_byte: new byte to add to calculation + void update(U8 new_byte) { this->m_crc = static_cast(update_crc_ccitt(m_crc, static_cast(new_byte))); }; + + //! \brief finalize and return CRC value + U16 finalize() { + // Specified XOR value is 0x0000 + return this->m_crc ^ static_cast(0); + }; + + //! \brief compute CRC16 for a buffer + //! + //! Compute the CRC16 for a given buffer and length. + //! + //! \param buffer: pointer to the data buffer + //! \param length: length of the data buffer + //! \return computed CRC16 value + static U16 compute(const U8* buffer, U32 length) { + U16 crc = std::numeric_limits::max(); // Initial value + for (U32 i = 0; i < length; ++i) { + crc = static_cast(update_crc_ccitt(crc, static_cast(buffer[i]))); + } + return crc ^ static_cast(0); // Finalize with XOR value + } + + U16 m_crc; +}; + +} // namespace Utils +} // namespace CCSDS +} // namespace Svc + +#endif // SVC_CCSDS_UTILS_CRC16_HPP \ No newline at end of file diff --git a/Svc/CCSDS/Utils/Utils.fpp b/Svc/CCSDS/Utils/Utils.fpp new file mode 100644 index 00000000000..e42b16a9177 --- /dev/null +++ b/Svc/CCSDS/Utils/Utils.fpp @@ -0,0 +1,20 @@ +module Utils { + + ########################################################################### + #### Uncomment the following examples to start customizing your module #### + ########################################################################### + + # enum ExampleEnum: U8 { A, B, C } + + # array ExampleArray = [3] F32 + + # struct ExampleStruct { x: U32, y: string } + + # @ ExamplePort returning an F32 + # port ExamplePort( + # arg1: ExampleEnum @< The first argument + # arg2: ExampleArray @< The second argument + # arg3: ExampleStruct @< The third argument + # ) -> F32 + +} diff --git a/Svc/FrameAccumulator/CMakeLists.txt b/Svc/FrameAccumulator/CMakeLists.txt index aa3f3915173..8966a20207a 100644 --- a/Svc/FrameAccumulator/CMakeLists.txt +++ b/Svc/FrameAccumulator/CMakeLists.txt @@ -11,6 +11,7 @@ set(SOURCE_FILES "${CMAKE_CURRENT_LIST_DIR}/FrameAccumulator.fpp" "${CMAKE_CURRENT_LIST_DIR}/FrameAccumulator.cpp" "${CMAKE_CURRENT_LIST_DIR}/FrameDetector/FprimeFrameDetector.cpp" + "${CMAKE_CURRENT_LIST_DIR}/FrameDetector/CcsdsTCFrameDetector.cpp" ) set(MOD_DEPS Utils/Types diff --git a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp new file mode 100644 index 00000000000..03f641d93a0 --- /dev/null +++ b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp @@ -0,0 +1,51 @@ +// ====================================================================== +// \title CcsdsTCFrameDetector.hpp +// \author thomas-bc +// \brief hpp file for fprime frame detector definitions +// ====================================================================== + +#include "Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.hpp" +#include "Svc/CCSDS/Types/FppConstantsAc.hpp" +#include "config/FppConstantsAc.hpp" + +namespace Svc { +namespace FrameDetectors { + +FrameDetector::Status CcsdsTCFrameDetector::detect(const Types::CircularBuffer& data, FwSizeType& size_out) const { + + if (data.get_allocated_size() < CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE) { + size_out = CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE; + return Status::MORE_DATA_NEEDED; + } + + // Copy CircularBuffer data into linear buffer, for serialization into FrameHeader object + U8 header_data[CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE]; + Fw::SerializeStatus status = data.peek(header_data, CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE, 0); + if (status != Fw::FW_SERIALIZE_OK) { + return Status::NO_FRAME_DETECTED; + } + CCSDS::Types::TCFrameHeader header; + Fw::ExternalSerializeBuffer header_ser_buffer(header_data, CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE); + status = header_ser_buffer.setBuffLen(CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE); + FW_ASSERT(status == Fw::FW_SERIALIZE_OK, static_cast(status)); + // Attempt to deserialize data into the FrameHeader object + status = header.deserialize(header_ser_buffer); + FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); + + U16 sc_id = header.getflagsAndScId() & CCSDS::Types::TCFrameMasks::SpacecraftIdMask; + U16 frame_length = header.getvcIdAndLength() & CCSDS::Types::TCFrameMasks::FrameLengthMask; + + FwSizeType expected_frame_size = CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE + frame_length + 2; // 2 bytes for CRC + if (sc_id == ComCfg::FppConstant_SpacecraftId::SpacecraftId) { + size_out = expected_frame_size; + if (frame_length > expected_frame_size) { + return Status::MORE_DATA_NEEDED; + } + return Status::FRAME_DETECTED; + } + + return Status::NO_FRAME_DETECTED; +} + +} // namespace FrameDetectors +} // namespace Svc diff --git a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.hpp b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.hpp new file mode 100644 index 00000000000..55436b7f6f8 --- /dev/null +++ b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.hpp @@ -0,0 +1,52 @@ +// ====================================================================== +// \title CcsdsTCFrameDetector.hpp +// \author thomas-bc +// \brief hpp file for fprime frame detector definitions +// ====================================================================== +#ifndef SVC_FRAME_ACCUMULATOR_FRAME_DETECTOR_CCSDS_TC_FRAME_DETECTOR +#define SVC_FRAME_ACCUMULATOR_FRAME_DETECTOR_CCSDS_TC_FRAME_DETECTOR + +#include "Svc/FrameAccumulator/FrameDetector.hpp" + +#include "Fw/Buffer/Buffer.hpp" +#include "Utils/Hash/Hash.hpp" +#include "Fw/FPrimeBasicTypes.hpp" + +#include "Svc/CCSDS/Types/TCFrameHeaderSerializableAc.hpp" + + +namespace Svc { +namespace FrameDetectors { + +//! \brief interface class used to codify what must be supported to allow frame detection +class CcsdsTCFrameDetector : public FrameDetector { + public: + //! \brief detect if a frame is available within the circular buffer + //! + //! Function implemented by sub classes used to determine if a frame is available at the current position of the + //! circular buffer. Implementors should detect if a frame is available, set size_out, and return a status while + //! following these expectations: + //! + //! 1. FRAME_DETECTED status implies a frame is available at the current offset of the circular buffer. + //! size_out must be set to the size of the frame from that location. + //! + //! 2. NO_FRAME_DETECTED status implies no frame is possible at the current offset of the circular buffer. + //! e.g. no start word is found at the current offset. size_out is ignored. + //! + //! 3. MORE_DATA_NEEDED status implies that a frame might be possible but more data is needed before a + //! determination is possible. size_out must be set to the total amount of data needed. + //! + //! For example, if a frame start word is 4 bytes, and 3 bytes are available in the circular buffer then the + //! return status would be NO_FRAME_DETECTED and size_out must be set to 4 to ensure that at least the start + //! word is available. + //! + //! \param data: circular buffer with read-only access + //! \param size_out: set as output to caller indicating size when appropriate + //! \return status of the detection to be paired with size_out + Status detect(const Types::CircularBuffer& data, FwSizeType& size_out) const override; + +}; // class CcsdsTCFrameDetector +} // namespace FrameDetectors +} // namespace Svc + +#endif // SVC_FRAME_ACCUMULATOR_FRAME_DETECTOR_CCSDS_TC_FRAME_DETECTOR diff --git a/config/ComCfg.fpp b/config/ComCfg.fpp index 4dfd70a8002..f146510c563 100644 --- a/config/ComCfg.fpp +++ b/config/ComCfg.fpp @@ -8,9 +8,13 @@ module ComCfg { + constant SpacecraftId = 0x0355 + constant TmFrameFixedSize = 1024 + @ Type used to pass context info between components during framing/deframing struct FrameContext { comQueueIndex: FwIndexType @< Queue Index used by the ComQueue, other components shall not modify + apid: U16 @< 11 bits APID in CCSDS } default { comQueueIndex = 0 } From 4c4c24adcf521f418e7b8efce8f18b5ee69c8ab8 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Tue, 6 May 2025 13:17:18 -0700 Subject: [PATCH 23/95] TODOs and code cleanup --- Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp | 5 +++-- Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp | 2 +- Svc/CCSDS/TMFramer/TMFramer.cpp | 8 +++----- Svc/CCSDS/TMFramer/TMFramer.hpp | 4 +++- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp index e7a1ef9402b..ee3d0874984 100644 --- a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp +++ b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp @@ -31,6 +31,7 @@ void SpacePacketFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, c FW_ASSERT(data.getSize() <= std::numeric_limits::max(), static_cast(frameSize)); FW_ASSERT(frameSize <= std::numeric_limits::max(), static_cast(frameSize)); + // TODO: Maybe can use a member as well, instead of allocating a new one each time // Allocate frame buffer Fw::Buffer frameBuffer = this->bufferAllocate_out(0, static_cast(frameSize)); auto frameSerializer = frameBuffer.getSerializer(); @@ -47,7 +48,7 @@ void SpacePacketFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, c packetSequenceControl |= this->m_packetSequenceCount; this->m_packetSequenceCount += 1; - // TODO: Assert / event that it fits in a U16 + FW_ASSERT(data.getSize() <= std::numeric_limits::max(), static_cast(this->m_packetSequenceCount)); U16 packetDataLength = static_cast(data.getSize() - 1); // Standard specifies length is number of bytes minus 1 header.setpacketIdentification(packetIdentification); @@ -73,7 +74,7 @@ void SpacePacketFramer ::comStatusIn_handler(FwIndexType portNum, Fw::Success& c } void SpacePacketFramer ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& frameBuffer, const ComCfg::FrameContext& context) { - // dataReturnIn is the allocated buffer coming back from the ComManager (e.g. ComStub) component + // dataReturnIn is the allocated buffer coming back from the dataOut port this->bufferDeallocate_out(0, frameBuffer); } diff --git a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp index 53248495b75..a1422c1a096 100644 --- a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp +++ b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp @@ -26,7 +26,7 @@ class SpacePacketFramer final : public SpacePacketFramerComponentBase { //! Destroy SpacePacketFramer object ~SpacePacketFramer(); - PRIVATE: + private: // ---------------------------------------------------------------------- // Handler implementations for typed input ports // ---------------------------------------------------------------------- diff --git a/Svc/CCSDS/TMFramer/TMFramer.cpp b/Svc/CCSDS/TMFramer/TMFramer.cpp index f2feb441546..ebf80ff8fd3 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.cpp +++ b/Svc/CCSDS/TMFramer/TMFramer.cpp @@ -56,10 +56,7 @@ void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComC // ------------------------------------------------- Fw::SerializeStatus status; - FwSizeType frameSize = CCSDS::Types::TMFrameHeader::SERIALIZED_SIZE + data.getSize() + CCSDS::Types::TMFrameHeader::SERIALIZED_SIZE; - FW_ASSERT(data.getSize() <= std::numeric_limits::max(), static_cast(frameSize)); - FW_ASSERT(frameSize <= std::numeric_limits::max(), static_cast(frameSize)); - // Allocate frame buffer + // Create frame Fw::Buffer using member data field Fw::Buffer frameBuffer = Fw::Buffer(this->m_frameBuffer, sizeof(this->m_frameBuffer)); auto frameSerializer = frameBuffer.getSerializer(); @@ -72,9 +69,10 @@ void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComC // Trailer: Compute CRC // ------------------------------------------------- CCSDS::Types::TMFrameTrailer trailer; + // Compute CRC over the entire frame buffer minus the FECF trailer U16 crc = CCSDS::Utils::CRC16::compute(frameBuffer.getData(), sizeof(this->m_frameBuffer) - CCSDS::Types::TMFrameTrailer::SERIALIZED_SIZE); trailer.setfecf(crc); // Frame Error Control Field - + // Move the serializer pointer to the end of the frame buffer since we are using a fixed size buffer frameSerializer.moveSerToOffset(ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize - CCSDS::Types::TMFrameTrailer::SERIALIZED_SIZE); status = frameSerializer.serialize(trailer); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); diff --git a/Svc/CCSDS/TMFramer/TMFramer.hpp b/Svc/CCSDS/TMFramer/TMFramer.hpp index 6735499eac9..62fa68fa746 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.hpp +++ b/Svc/CCSDS/TMFramer/TMFramer.hpp @@ -26,7 +26,7 @@ class TMFramer final : public TMFramerComponentBase { //! Destroy TMFramer object ~TMFramer(); - PRIVATE: + private: // ---------------------------------------------------------------------- // Handler implementations for typed input ports // ---------------------------------------------------------------------- @@ -53,6 +53,8 @@ class TMFramer final : public TMFramerComponentBase { Fw::Buffer& data, const ComCfg::FrameContext& context) override; + // Because the TM protocol use fixed width frames, and only one frame is in transit between ComQueue and ComInterface + // at a time, we can use a member fixed-size buffer to hold the frame data U8 m_frameBuffer[ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize]; //!< Buffer to hold the frame data }; From 1f1e456545f7b0b1b8a6f5bf500dcd075654f8f5 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 7 May 2025 17:52:47 -0700 Subject: [PATCH 24/95] Add APID enum to ComCfg.fpp and route based on received APID --- .../SpacePacketDeframer.cpp | 2 +- .../SpacePacketDeframer.hpp | 2 +- .../SpacePacketFramer/SpacePacketFramer.cpp | 19 +++- .../SpacePacketFramer/SpacePacketFramer.hpp | 2 +- Svc/CCSDS/TMFramer/TMFramer.cpp | 2 +- Svc/CCSDS/TMFramer/TMFramer.hpp | 2 +- Svc/CCSDS/Types/Types.fpp | 18 ++-- Svc/FprimeRouter/FprimeRouter.cpp | 86 ++++++++----------- .../FrameDetector/CcsdsTCFrameDetector.cpp | 7 +- .../FrameDetector/CcsdsTCFrameDetector.hpp | 6 +- config/ComCfg.fpp | 15 +++- 11 files changed, 88 insertions(+), 73 deletions(-) diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp index 8c8ca0c233b..3b2401cd8e3 100644 --- a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp @@ -48,7 +48,7 @@ void SpacePacketDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, U16 apid = header.getpacketIdentification() & CCSDS::Types::SpacePacketMasks::ApidMask; ComCfg::FrameContext contextCopy = context; - contextCopy.setapid(apid); + contextCopy.setapid(static_cast(apid)); // TODO: Add checks and events in case of failure U16 pkt_length = header.getpacketDataLength(); diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp index 99beb9b79e4..9d11be666e4 100644 --- a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp @@ -1,6 +1,6 @@ // ====================================================================== // \title SpacePacketDeframer.hpp -// \author chammard +// \author thomas-bc // \brief hpp file for SpacePacketDeframer component implementation class // ====================================================================== diff --git a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp index ee3d0874984..d7e32b865b2 100644 --- a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp +++ b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp @@ -1,6 +1,6 @@ // ====================================================================== // \title SpacePacketFramer.cpp -// \author chammard +// \author thomas-bc // \brief cpp file for SpacePacketFramer component implementation class // ====================================================================== @@ -41,7 +41,22 @@ void SpacePacketFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, c // ----------------------------------------------- // PVN is always 0 per Standard - Packet Type is 0 for Telemetry (downlink) - SecHdr flag is 0 for no secondary header U16 packetIdentification = 0; - packetIdentification |= context.getcomQueueIndex(); // APID = comQueueIndex (for now; TBD how to configure APIDs) + U16 apid; + // Figure out APID based on queue index - TODO: find a better way ?? + switch (context.getcomQueueIndex()) { + case 0: + apid = ComCfg::APID::FW_PACKET_LOG; // Only true if topology is wired this way. Need to fix this logic somehow + break; + case 1: + apid = ComCfg::APID::FW_PACKET_TELEM; + break; + case 2: + apid = ComCfg::APID::FW_PACKET_FILE; + break; + default: + apid = ComCfg::APID::FW_PACKET_UNKNOWN; + } + packetIdentification |= apid & CCSDS::Types::SpacePacketMasks::ApidMask; // 11 bit APID U16 packetSequenceControl = 0; packetSequenceControl |= 0x3 << CCSDS::Types::SpacePacketMasks::SeqFlagsOffset; // Sequence Flags 0b11 = unsegmented User Data diff --git a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp index a1422c1a096..d9535e74b10 100644 --- a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp +++ b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp @@ -1,6 +1,6 @@ // ====================================================================== // \title SpacePacketFramer.hpp -// \author chammard +// \author thomas-bc // \brief hpp file for SpacePacketFramer component implementation class // ====================================================================== diff --git a/Svc/CCSDS/TMFramer/TMFramer.cpp b/Svc/CCSDS/TMFramer/TMFramer.cpp index ebf80ff8fd3..a94c7487a36 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.cpp +++ b/Svc/CCSDS/TMFramer/TMFramer.cpp @@ -1,6 +1,6 @@ // ====================================================================== // \title TMFramer.cpp -// \author chammard +// \author thomas-bc // \brief cpp file for TMFramer component implementation class // ====================================================================== diff --git a/Svc/CCSDS/TMFramer/TMFramer.hpp b/Svc/CCSDS/TMFramer/TMFramer.hpp index 62fa68fa746..36087d24441 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.hpp +++ b/Svc/CCSDS/TMFramer/TMFramer.hpp @@ -1,6 +1,6 @@ // ====================================================================== // \title TMFramer.hpp -// \author chammard +// \author thomas-bc // \brief hpp file for TMFramer component implementation class // ====================================================================== diff --git a/Svc/CCSDS/Types/Types.fpp b/Svc/CCSDS/Types/Types.fpp index bd576d4351e..2510339aeb3 100644 --- a/Svc/CCSDS/Types/Types.fpp +++ b/Svc/CCSDS/Types/Types.fpp @@ -10,15 +10,15 @@ module Types { # with the approriate mask to module SpacePacketMasks { - constant PvnMask = 0xE000 @< 0b1110000000000000 - constant PktTypeMask = 0x1000 @< 0b0001000000000000 - constant SecHdrMask = 0x0800 @< 0b0000100000000000 - constant ApidMask = 0x07FF @< 0b0000011111111111 - constant SecHdrOffset = 11 - constant PktTypeOffset = 12 - constant PvnOffset = 13 - constant SeqFlagsMask = 0xC000 @< 0b1100000000000000 - constant SeqFlagsOffset = 14 + constant PvnMask = 0xE000; @< 0b1110000000000000 + constant PktTypeMask = 0x1000; @< 0b0001000000000000 + constant SecHdrMask = 0x0800; @< 0b0000100000000000 + constant ApidMask = 0x07FF; @< 0b0000011111111111 + constant SecHdrOffset = 11; + constant PktTypeOffset = 12; + constant PvnOffset = 13; + constant SeqFlagsMask = 0xC000; @< 0b1100000000000000 + constant SeqFlagsOffset = 14; } module TCFrameMasks { diff --git a/Svc/FprimeRouter/FprimeRouter.cpp b/Svc/FprimeRouter/FprimeRouter.cpp index 1c7e30dec55..7e8a88d5bd8 100644 --- a/Svc/FprimeRouter/FprimeRouter.cpp +++ b/Svc/FprimeRouter/FprimeRouter.cpp @@ -8,6 +8,7 @@ #include "Fw/FPrimeBasicTypes.hpp" #include "Fw/Com/ComPacket.hpp" #include "Fw/Logger/Logger.hpp" +#include "config/APIDEnumAc.hpp" namespace Svc { @@ -24,59 +25,46 @@ FprimeRouter ::~FprimeRouter() {} // ---------------------------------------------------------------------- void FprimeRouter ::dataIn_handler(FwIndexType portNum, Fw::Buffer& packetBuffer, const ComCfg::FrameContext& context) { - // Read the packet type from the packet buffer - FwPacketDescriptorType packetType = Fw::ComPacket::FW_PACKET_UNKNOWN; - Fw::SerializeStatus status = Fw::FW_SERIALIZE_OK; - { - auto esb = packetBuffer.getDeserializer(); - status = esb.deserialize(packetType); - } - - // Process the packet - if (status == Fw::FW_SERIALIZE_OK) { - U8* const packetData = packetBuffer.getData(); - const FwSizeType packetSize = packetBuffer.getSize(); - switch (packetType) { - // Handle a command packet - case Fw::ComPacket::FW_PACKET_COMMAND: { - // Allocate a com buffer on the stack - Fw::ComBuffer com; - // Copy the contents of the packet buffer into the com buffer - status = com.setBuff(packetData, packetSize); - if (status == Fw::FW_SERIALIZE_OK) { - // Send the com buffer - critical functionality so it is considered an error not to - // have the port connected. This is why we don't check isConnected() before sending. - this->commandOut_out(0, com, 0); - } else { - this->log_WARNING_HI_SerializationError(status); - } - break; + Fw::SerializeStatus status; + // Route based on received APID + switch (context.getapid()) { + // Handle a command packet + case ComCfg::APID::FW_PACKET_COMMAND: { + // Allocate a com buffer on the stack + Fw::ComBuffer com; + // Copy the contents of the packet buffer into the com buffer + status = com.setBuff(packetBuffer.getData(), packetBuffer.getSize()); + if (status == Fw::FW_SERIALIZE_OK) { + // Send the com buffer - critical functionality so it is considered an error not to + // have the port connected. This is why we don't check isConnected() before sending. + this->commandOut_out(0, com, 0); + } else { + this->log_WARNING_HI_SerializationError(status); } - // Handle a file packet - case Fw::ComPacket::FW_PACKET_FILE: { - // If the file uplink output port is connected, send the file packet. Otherwise take no action. - if (this->isConnected_fileOut_OutputPort(0)) { - // Copy buffer into a new allocated buffer. This lets us return the original buffer with dataReturnOut, - // and FprimeRouter can handle the deallocation of the file buffer when it returns on fileBufferReturnIn - Fw::Buffer packetBufferCopy = this->bufferAllocate_out(0, packetBuffer.getSize()); - auto copySerializer = packetBufferCopy.getSerializer(); - status = copySerializer.serialize(packetBuffer.getData(), packetBuffer.getSize(), Fw::Serialization::OMIT_LENGTH); - FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); - // Send the copied buffer out. It will come back on fileBufferReturnIn once the receiver is done with it - this->fileOut_out(0, packetBufferCopy); - } - break; + break; + } + // Handle a file packet + case ComCfg::APID::FW_PACKET_FILE: { + // If the file uplink output port is connected, send the file packet. Otherwise take no action. + if (this->isConnected_fileOut_OutputPort(0)) { + // Copy buffer into a new allocated buffer. This lets us return the original buffer with dataReturnOut, + // and FprimeRouter can handle the deallocation of the file buffer when it returns on fileBufferReturnIn + Fw::Buffer packetBufferCopy = this->bufferAllocate_out(0, packetBuffer.getSize()); + auto copySerializer = packetBufferCopy.getSerializer(); + status = copySerializer.serialize(packetBuffer.getData(), packetBuffer.getSize(), Fw::Serialization::OMIT_LENGTH); + FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); + // Send the copied buffer out. It will come back on fileBufferReturnIn once the receiver is done with it + this->fileOut_out(0, packetBufferCopy); } - default: { - // Packet type is not known to the F Prime protocol. If the unknownDataOut port is - // connected, forward packet and context for further processing - if (this->isConnected_unknownDataOut_OutputPort(0)) { - this->unknownDataOut_out(0, packetBuffer, context); - } + break; + } + default: { + // Packet type is not known to the F Prime protocol. If the unknownDataOut port is + // connected, forward packet and context for further processing + if (this->isConnected_unknownDataOut_OutputPort(0)) { + this->unknownDataOut_out(0, packetBuffer, context); } } - } else { - this->log_WARNING_HI_DeserializationError(status); } // Return ownership of the incoming packetBuffer diff --git a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp index 03f641d93a0..89cc4f74794 100644 --- a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp +++ b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp @@ -7,6 +7,9 @@ #include "Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.hpp" #include "Svc/CCSDS/Types/FppConstantsAc.hpp" #include "config/FppConstantsAc.hpp" +#include "Svc/CCSDS/Types/TCFrameHeaderSerializableAc.hpp" +#include "Svc/CCSDS/Types/TCFrameTrailerSerializableAc.hpp" +#include "Utils/Hash/Hash.hpp" namespace Svc { namespace FrameDetectors { @@ -35,10 +38,10 @@ FrameDetector::Status CcsdsTCFrameDetector::detect(const Types::CircularBuffer& U16 sc_id = header.getflagsAndScId() & CCSDS::Types::TCFrameMasks::SpacecraftIdMask; U16 frame_length = header.getvcIdAndLength() & CCSDS::Types::TCFrameMasks::FrameLengthMask; - FwSizeType expected_frame_size = CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE + frame_length + 2; // 2 bytes for CRC + FwSizeType expected_frame_size = CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE + frame_length + CCSDS::Types::TCFrameTrailer::SERIALIZED_SIZE; // 2 bytes for CRC if (sc_id == ComCfg::FppConstant_SpacecraftId::SpacecraftId) { size_out = expected_frame_size; - if (frame_length > expected_frame_size) { + if (data.get_allocated_size() < expected_frame_size) { return Status::MORE_DATA_NEEDED; } return Status::FRAME_DETECTED; diff --git a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.hpp b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.hpp index 55436b7f6f8..93d4bb79941 100644 --- a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.hpp +++ b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.hpp @@ -8,13 +8,9 @@ #include "Svc/FrameAccumulator/FrameDetector.hpp" -#include "Fw/Buffer/Buffer.hpp" -#include "Utils/Hash/Hash.hpp" +// #include "Fw/Buffer/Buffer.hpp" #include "Fw/FPrimeBasicTypes.hpp" -#include "Svc/CCSDS/Types/TCFrameHeaderSerializableAc.hpp" - - namespace Svc { namespace FrameDetectors { diff --git a/config/ComCfg.fpp b/config/ComCfg.fpp index f146510c563..cb18944953c 100644 --- a/config/ComCfg.fpp +++ b/config/ComCfg.fpp @@ -11,10 +11,23 @@ module ComCfg { constant SpacecraftId = 0x0355 constant TmFrameFixedSize = 1024 + @ APIDs are 11 bits in the Space Packet protocol, so we use U16. Max value 7FF + enum APID : U16 { + FW_PACKET_COMMAND = 0x0000 @< Command packet type - incoming + FW_PACKET_TELEM = 0x0001 @< Telemetry packet type - outgoing + FW_PACKET_LOG = 0x0002 @< Log type - outgoing + FW_PACKET_FILE = 0x0003 @< File type - incoming and outgoing + FW_PACKET_PACKETIZED_TLM = 0x0004 @< Packetized telemetry packet type + FW_PACKET_IDLE = 0x0005 @< F Prime idle + FW_PACKET_HAND = 0xFE @< F Prime handshake + FW_PACKET_UNKNOWN = 0xFF @< F Prime unknown packet + IDLE_PACKET = 0x7FF @< Per Space Packet Standard, all 1s (11bits) is reserved for Idle Packets + } + @ Type used to pass context info between components during framing/deframing struct FrameContext { comQueueIndex: FwIndexType @< Queue Index used by the ComQueue, other components shall not modify - apid: U16 @< 11 bits APID in CCSDS + apid: APID @< 11 bits APID in CCSDS } default { comQueueIndex = 0 } From d65e5915b7c436eb7076a1f12ff588d23bffbdbb Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Fri, 9 May 2025 09:26:43 -0700 Subject: [PATCH 25/95] Increment counts per frame/apid --- .../SpacePacketDeframer.fpp | 6 --- .../SpacePacketFramer/SpacePacketFramer.cpp | 48 +++++++++++-------- .../SpacePacketFramer/SpacePacketFramer.hpp | 12 ++++- Svc/CCSDS/TCDeframer/TCDeframer.fpp | 6 --- Svc/CCSDS/TCDeframer/TCDeframer.hpp | 2 - Svc/CCSDS/TMFramer/TMFramer.cpp | 44 ++++++++++------- Svc/CCSDS/TMFramer/TMFramer.hpp | 3 ++ Svc/CCSDS/Types/Types.fpp | 1 + .../FrameDetector/CcsdsTCFrameDetector.cpp | 2 +- config/ComCfg.fpp | 3 +- 10 files changed, 73 insertions(+), 54 deletions(-) diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp index ff888acb747..d725e6d079a 100644 --- a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp @@ -5,12 +5,6 @@ module CCSDS { include "../../Interfaces/DeframerInterface.fppi" - @ Port for returning ownership of received frame buffers - output port dataReturnOut: Svc.ComDataWithContext - - @ Port receiving back ownership of sent frame buffers - sync input port dataReturnIn: Svc.ComDataWithContext - ############################################################################### # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # ############################################################################### diff --git a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp index d7e32b865b2..ef4f53c3064 100644 --- a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp +++ b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp @@ -41,29 +41,15 @@ void SpacePacketFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, c // ----------------------------------------------- // PVN is always 0 per Standard - Packet Type is 0 for Telemetry (downlink) - SecHdr flag is 0 for no secondary header U16 packetIdentification = 0; - U16 apid; - // Figure out APID based on queue index - TODO: find a better way ?? - switch (context.getcomQueueIndex()) { - case 0: - apid = ComCfg::APID::FW_PACKET_LOG; // Only true if topology is wired this way. Need to fix this logic somehow - break; - case 1: - apid = ComCfg::APID::FW_PACKET_TELEM; - break; - case 2: - apid = ComCfg::APID::FW_PACKET_FILE; - break; - default: - apid = ComCfg::APID::FW_PACKET_UNKNOWN; - } - packetIdentification |= apid & CCSDS::Types::SpacePacketMasks::ApidMask; // 11 bit APID + ComCfg::APID::T apid = this->get_apid_from_index(context.getcomQueueIndex()); + U16 sequenceCount = this->increment_sequence_count_for_apid(context.getcomQueueIndex()); + packetIdentification |= static_cast(apid) & CCSDS::Types::SpacePacketMasks::ApidMask; // 11 bit APID U16 packetSequenceControl = 0; packetSequenceControl |= 0x3 << CCSDS::Types::SpacePacketMasks::SeqFlagsOffset; // Sequence Flags 0b11 = unsegmented User Data - packetSequenceControl |= this->m_packetSequenceCount; - this->m_packetSequenceCount += 1; + packetSequenceControl |= sequenceCount & CCSDS::Types::SpacePacketMasks::SeqCountMask; // 14 bit sequence count - FW_ASSERT(data.getSize() <= std::numeric_limits::max(), static_cast(this->m_packetSequenceCount)); + FW_ASSERT(data.getSize() <= std::numeric_limits::max(), static_cast(data.getSize())); U16 packetDataLength = static_cast(data.getSize() - 1); // Standard specifies length is number of bytes minus 1 header.setpacketIdentification(packetIdentification); @@ -93,6 +79,30 @@ void SpacePacketFramer ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& f this->bufferDeallocate_out(0, frameBuffer); } +U16 SpacePacketFramer ::increment_sequence_count_for_apid(FwIndexType index) { + // FwIndexType index = this->get_index_from_apid(apid); + U16 sequenceCount = this->m_packetSequenceCounts[index]; + this->m_packetSequenceCounts[index] = (this->m_packetSequenceCounts[index] + 1) % (1 << 14); // Wrap around at 14 bits (modulo 2^14) + printf("index: %d, Sequence Count: %d\n", index, this->m_packetSequenceCounts[index]); + return sequenceCount; +} + +ComCfg::APID::T SpacePacketFramer ::get_apid_from_index(FwIndexType index) { + // Need a manual mapping from comQueue index to APID for now to get an APID count + // per APID + switch (index) { + case 0: + return ComCfg::APID::FW_PACKET_LOG; + case 1: + return ComCfg::APID::FW_PACKET_TELEM; + case 2: + return ComCfg::APID::FW_PACKET_FILE; + default: + return ComCfg::APID::FW_PACKET_UNKNOWN; // TODO: Handle unknown index + } +} + + } // namespace CCSDS } // namespace Svc diff --git a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp index d9535e74b10..bf854ca35a6 100644 --- a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp +++ b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp @@ -8,6 +8,7 @@ #define Svc_CCSDS_SpacePacketFramer_HPP #include "Svc/CCSDS/SpacePacketFramer/SpacePacketFramerComponentAc.hpp" +#include "config/APIDEnumAc.hpp" namespace Svc { @@ -53,7 +54,16 @@ class SpacePacketFramer final : public SpacePacketFramerComponentBase { Fw::Buffer& data, const ComCfg::FrameContext& context) override; - U16 m_packetSequenceCount = 0; //!< Packet sequence count (TODO: needs to be per-APID; and wrap around at 14 bits) + // ---------------------------------------------------------------------- + // Helpers + // ---------------------------------------------------------------------- + + U16 increment_sequence_count_for_apid(FwIndexType index); + + // FwIndexType get_index_from_apid(ComCfg::APID::T apid); + ComCfg::APID::T get_apid_from_index(FwIndexType index); + + U16 m_packetSequenceCounts[ComCfg::APID::NUM_CONSTANTS] = {0}; //!< Packet sequence counts for each APID }; } // namespace CCSDS diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.fpp b/Svc/CCSDS/TCDeframer/TCDeframer.fpp index 403862446f8..ee85ab68b06 100644 --- a/Svc/CCSDS/TCDeframer/TCDeframer.fpp +++ b/Svc/CCSDS/TCDeframer/TCDeframer.fpp @@ -5,12 +5,6 @@ module CCSDS { include "../../Interfaces/DeframerInterface.fppi" - @ Port for returning ownership of received frame buffers - output port dataReturnOut: Svc.ComDataWithContext - - @ Port receiving back ownership of sent frame buffers - sync input port dataReturnIn: Svc.ComDataWithContext - ############################################################################### # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # ############################################################################### diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.hpp b/Svc/CCSDS/TCDeframer/TCDeframer.hpp index 0e3b48c6f3d..704937a646d 100644 --- a/Svc/CCSDS/TCDeframer/TCDeframer.hpp +++ b/Svc/CCSDS/TCDeframer/TCDeframer.hpp @@ -13,8 +13,6 @@ namespace Svc { namespace CCSDS { class TCDeframer : public TCDeframerComponentBase { - static const U8 SPACE_PACKET_HEADER_SIZE = 5; - static const U8 SPACE_PACKET_TRAILER_SIZE = 2; public: // ---------------------------------------------------------------------- // Component construction and destruction diff --git a/Svc/CCSDS/TMFramer/TMFramer.cpp b/Svc/CCSDS/TMFramer/TMFramer.cpp index a94c7487a36..2902dedb7ec 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.cpp +++ b/Svc/CCSDS/TMFramer/TMFramer.cpp @@ -5,9 +5,9 @@ // ====================================================================== #include "Svc/CCSDS/TMFramer/TMFramer.hpp" +#include "Svc/CCSDS/Types/FppConstantsAc.hpp" #include "Svc/CCSDS/Types/TMFrameHeaderSerializableAc.hpp" #include "Svc/CCSDS/Types/TMFrameTrailerSerializableAc.hpp" -#include "Svc/CCSDS/Types/FppConstantsAc.hpp" #include "Svc/CCSDS/Utils/CRC16.hpp" #include "config/FppConstantsAc.hpp" @@ -19,7 +19,8 @@ namespace CCSDS { // Component construction and destruction // ---------------------------------------------------------------------- -TMFramer ::TMFramer(const char* const compName) : TMFramerComponentBase(compName) {} +TMFramer ::TMFramer(const char* const compName) + : TMFramerComponentBase(compName), m_masterFrameCount(0), m_virtualFrameCount(0) {} TMFramer ::~TMFramer() {} @@ -28,29 +29,33 @@ TMFramer ::~TMFramer() {} // ---------------------------------------------------------------------- void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { + // TODO: make this an event probably + FW_ASSERT(data.getSize() <= ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize, + static_cast(data.getSize())); + // ----------------------------------------------- // Header // ----------------------------------------------- CCSDS::Types::TMFrameHeader header; U16 channelIds = 0; channelIds |= ComCfg::FppConstant_SpacecraftId::SpacecraftId << CCSDS::Types::TMFrameMasks::spacecraftIdOffset; - channelIds |= 0x00 << CCSDS::Types::TMFrameMasks::virtualChannelIdOffset; // VCID - channelIds |= 0x0; // No Operational Control Field: Flag set to 0 + channelIds |= ComCfg::FppConstant_VcId::VcId << CCSDS::Types::TMFrameMasks::virtualChannelIdOffset; + channelIds |= 0x0; // No Operational Control Field: Flag set to 0 - U8 masterFrameCount = 0; - U8 virtualFrameCount = 0; - - // Data Field Status: + // Data Field Status: // - all flags to 0 except segment length id 0b11 per standard // - First Header Pointer is always 0 since we are always wrapping a single entire packet at offset 0 U16 dataFieldStatus = 0; - dataFieldStatus |= 0x3 << CCSDS::Types::TMFrameMasks::segLengthOffset; // Seg Length 0b11 per Standard + dataFieldStatus |= 0x3 << CCSDS::Types::TMFrameMasks::segLengthOffset; // Seg Length 0b11 per Standard header.setchannelIds(channelIds); - header.setmasterFrameCount(masterFrameCount); - header.setvirtualFrameCount(virtualFrameCount); + header.setmasterFrameCount(this->m_masterFrameCount); + header.setvirtualFrameCount(this->m_virtualFrameCount); header.setdataFieldStatus(dataFieldStatus); + this->m_masterFrameCount++; // U8 intended to wrap around (modulo 256) + this->m_virtualFrameCount++; // U8 intended to wrap around (modulo 256) + // ------------------------------------------------- // Serialize the Frame // ------------------------------------------------- @@ -70,15 +75,17 @@ void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComC // ------------------------------------------------- CCSDS::Types::TMFrameTrailer trailer; // Compute CRC over the entire frame buffer minus the FECF trailer - U16 crc = CCSDS::Utils::CRC16::compute(frameBuffer.getData(), sizeof(this->m_frameBuffer) - CCSDS::Types::TMFrameTrailer::SERIALIZED_SIZE); - trailer.setfecf(crc); // Frame Error Control Field - // Move the serializer pointer to the end of the frame buffer since we are using a fixed size buffer - frameSerializer.moveSerToOffset(ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize - CCSDS::Types::TMFrameTrailer::SERIALIZED_SIZE); + U16 crc = CCSDS::Utils::CRC16::compute(frameBuffer.getData(), + sizeof(this->m_frameBuffer) - CCSDS::Types::TMFrameTrailer::SERIALIZED_SIZE); + trailer.setfecf(crc); // Frame Error Control Field + // Move the serializer pointer to the end of the location where the trailer will be serialized + frameSerializer.moveSerToOffset(ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize - + CCSDS::Types::TMFrameTrailer::SERIALIZED_SIZE); status = frameSerializer.serialize(trailer); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); this->dataOut_out(0, frameBuffer, context); - this->dataReturnOut_out(0, data, context); // return ownership of the original data buffer + this->dataReturnOut_out(0, data, context); // return ownership of the original data buffer } void TMFramer ::comStatusIn_handler(FwIndexType portNum, Fw::Success& condition) { @@ -87,13 +94,14 @@ void TMFramer ::comStatusIn_handler(FwIndexType portNum, Fw::Success& condition) } } -void TMFramer ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& frameBuffer, const ComCfg::FrameContext& context) { +void TMFramer ::dataReturnIn_handler(FwIndexType portNum, + Fw::Buffer& frameBuffer, + const ComCfg::FrameContext& context) { // dataReturnIn is the member buffer coming back from the ComManager (e.g. ComStub) component // this->bufferDeallocate_out(0, frameBuffer); ::memset(this->m_frameBuffer, 0, sizeof(this->m_frameBuffer)); } - } // namespace CCSDS } // namespace Svc diff --git a/Svc/CCSDS/TMFramer/TMFramer.hpp b/Svc/CCSDS/TMFramer/TMFramer.hpp index 36087d24441..efc842a1884 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.hpp +++ b/Svc/CCSDS/TMFramer/TMFramer.hpp @@ -56,6 +56,9 @@ class TMFramer final : public TMFramerComponentBase { // Because the TM protocol use fixed width frames, and only one frame is in transit between ComQueue and ComInterface // at a time, we can use a member fixed-size buffer to hold the frame data U8 m_frameBuffer[ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize]; //!< Buffer to hold the frame data + + U8 m_masterFrameCount; //!< Master Frame Count - 8 bits - wraps around at 255 + U8 m_virtualFrameCount; //!< Virtual Frame Count - 8 bits - wraps around at 255 }; } // namespace CCSDS diff --git a/Svc/CCSDS/Types/Types.fpp b/Svc/CCSDS/Types/Types.fpp index 2510339aeb3..872f6523bd0 100644 --- a/Svc/CCSDS/Types/Types.fpp +++ b/Svc/CCSDS/Types/Types.fpp @@ -19,6 +19,7 @@ module Types { constant PvnOffset = 13; constant SeqFlagsMask = 0xC000; @< 0b1100000000000000 constant SeqFlagsOffset = 14; + constant SeqCountMask = 0x3FFF } module TCFrameMasks { diff --git a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp index 89cc4f74794..230a1e8dce3 100644 --- a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp +++ b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp @@ -6,6 +6,7 @@ #include "Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.hpp" #include "Svc/CCSDS/Types/FppConstantsAc.hpp" +#include #include "config/FppConstantsAc.hpp" #include "Svc/CCSDS/Types/TCFrameHeaderSerializableAc.hpp" #include "Svc/CCSDS/Types/TCFrameTrailerSerializableAc.hpp" @@ -46,7 +47,6 @@ FrameDetector::Status CcsdsTCFrameDetector::detect(const Types::CircularBuffer& } return Status::FRAME_DETECTED; } - return Status::NO_FRAME_DETECTED; } diff --git a/config/ComCfg.fpp b/config/ComCfg.fpp index cb18944953c..5f4d325bad2 100644 --- a/config/ComCfg.fpp +++ b/config/ComCfg.fpp @@ -8,7 +8,8 @@ module ComCfg { - constant SpacecraftId = 0x0355 + constant SpacecraftId = 0x03FF # Spacecraft ID (10 bits) + constant VcId = 0x001 # Virtual Channel ID (3 bits) constant TmFrameFixedSize = 1024 @ APIDs are 11 bits in the Space Packet protocol, so we use U16. Max value 7FF From 92142216f67c99f9a086f2826e5a827bd57f7d57 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Mon, 12 May 2025 15:32:18 -0700 Subject: [PATCH 26/95] Remove duplicate files --- .../TCDeframer/CMakeLists.txt | 21 ------ .../TCDeframer/TCDeframer.cpp | 64 ------------------ .../TCDeframer/TCDeframer.fpp | 37 ----------- .../TCDeframer/TCDeframer.hpp | 53 --------------- .../TCDeframer/docs/sdd.md | 66 ------------------- 5 files changed, 241 deletions(-) delete mode 100644 Svc/CCSDS/SpacePacketDeframer/TCDeframer/CMakeLists.txt delete mode 100644 Svc/CCSDS/SpacePacketDeframer/TCDeframer/TCDeframer.cpp delete mode 100644 Svc/CCSDS/SpacePacketDeframer/TCDeframer/TCDeframer.fpp delete mode 100644 Svc/CCSDS/SpacePacketDeframer/TCDeframer/TCDeframer.hpp delete mode 100644 Svc/CCSDS/SpacePacketDeframer/TCDeframer/docs/sdd.md diff --git a/Svc/CCSDS/SpacePacketDeframer/TCDeframer/CMakeLists.txt b/Svc/CCSDS/SpacePacketDeframer/TCDeframer/CMakeLists.txt deleted file mode 100644 index 4d67d7aeae7..00000000000 --- a/Svc/CCSDS/SpacePacketDeframer/TCDeframer/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -#### -# F prime CMakeLists.txt: -# -# SOURCE_FILES: combined list of source and autocoding files -# MOD_DEPS: (optional) module dependencies -# UT_SOURCE_FILES: list of source files for unit tests -# -#### -set(SOURCE_FILES - "${CMAKE_CURRENT_LIST_DIR}/TCDeframer.fpp" - "${CMAKE_CURRENT_LIST_DIR}/TCDeframer.cpp" -) - -# Uncomment and add any modules that this component depends on, else -# they might not be available when cmake tries to build this component. - -set(MOD_DEPS - Svc_CCSDS_Types -) - -register_fprime_module() diff --git a/Svc/CCSDS/SpacePacketDeframer/TCDeframer/TCDeframer.cpp b/Svc/CCSDS/SpacePacketDeframer/TCDeframer/TCDeframer.cpp deleted file mode 100644 index 19b138923f7..00000000000 --- a/Svc/CCSDS/SpacePacketDeframer/TCDeframer/TCDeframer.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// ====================================================================== -// \title TCDeframer.cpp -// \author thomas-bc -// \brief cpp file for TCDeframer component implementation class -// ====================================================================== - -#include "Svc/CCSDS/TCDeframer/TCDeframer.hpp" -#include "Svc/CCSDS/Types/TCFrameHeaderSerializableAc.hpp" -#include "Svc/CCSDS/Types/FppConstantsAc.hpp" -#include "FpConfig.hpp" - -namespace Svc { -namespace CCSDS { -// ---------------------------------------------------------------------- -// Component construction and destruction -// ---------------------------------------------------------------------- - -TCDeframer ::TCDeframer(const char* const compName) - : TCDeframerComponentBase(compName) {} - -TCDeframer ::~TCDeframer() {} - -// ---------------------------------------------------------------------- -// Handler implementations for user-defined typed input ports -// ---------------------------------------------------------------------- - -void TCDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { - - // CCSDS TC Format: - // 5 octets - TC Primary Header - // Up to 1019 octets - Data Field (including optional 2 octets frame error control field) - - // CCSDS TC Primary Header: - // 2b - 00 - TF Version Number - // 1b - 0/1 - Bypass Flag (0 = FARM checks enabled, 1 = FARM checks bypassed) - // 1b - 0/1 - Control Command Flag (0 = Type-D data, 1 = Type-C data) - // 2b - 00 - Reserved Spare (set to 00) - // 10b- XX - Spacecraft ID - // 6b - XX - Virtual Channel ID - // 10b- XX - Frame Length - // 8b - XX - Frame Sequence Number - - FW_ASSERT(data.getSize() >= CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE, static_cast(data.getSize())); - - CCSDS::Types::TCFrameHeader header; - Fw::SerializeStatus status = data.getDeserializer().deserialize(header); - FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); - - U16 frame_length = header.getvcIdAndLength() & CCSDS::Types::TCFrameMasks::FrameLengthMask; - // U8 vc_id = (header.getvcIdAndLength() & CCSDS::Types::TCFrameMasks::VcIdMask) >> 2; - // TODO: check if frame_length is same as length of data minus header size - data.setData(data.getData() + Svc::CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE); - data.setSize(frame_length); - - this->dataOut_out(0, data, context); - -} - -void TCDeframer ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer, const ComCfg::FrameContext& context) { - this->dataReturnOut_out(0, fwBuffer, context); -} - -} // namespace CCSDS -} // namespace Svc diff --git a/Svc/CCSDS/SpacePacketDeframer/TCDeframer/TCDeframer.fpp b/Svc/CCSDS/SpacePacketDeframer/TCDeframer/TCDeframer.fpp deleted file mode 100644 index 403862446f8..00000000000 --- a/Svc/CCSDS/SpacePacketDeframer/TCDeframer/TCDeframer.fpp +++ /dev/null @@ -1,37 +0,0 @@ -module Svc { -module CCSDS { - @ Deframer for the TC Space Data Link Protocl (CCSDS Standard) - passive component TCDeframer { - - include "../../Interfaces/DeframerInterface.fppi" - - @ Port for returning ownership of received frame buffers - output port dataReturnOut: Svc.ComDataWithContext - - @ Port receiving back ownership of sent frame buffers - sync input port dataReturnIn: Svc.ComDataWithContext - - ############################################################################### - # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # - ############################################################################### - @ Port for requesting the current time - time get port timeCaller - - @ Port for sending textual representation of events - text event port logTextOut - - @ Port for sending events to downlink - event port logOut - - @ Port for sending telemetry channels to downlink - telemetry port tlmOut - - @ Port to return the value of a parameter - param get port prmGetOut - - @Port to set the value of a parameter - param set port prmSetOut - - } -} -} \ No newline at end of file diff --git a/Svc/CCSDS/SpacePacketDeframer/TCDeframer/TCDeframer.hpp b/Svc/CCSDS/SpacePacketDeframer/TCDeframer/TCDeframer.hpp deleted file mode 100644 index 0e3b48c6f3d..00000000000 --- a/Svc/CCSDS/SpacePacketDeframer/TCDeframer/TCDeframer.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// ====================================================================== -// \title TCDeframer.hpp -// \author thomas-bc -// \brief hpp file for TCDeframer component implementation class -// ====================================================================== - -#ifndef Svc_CCSDS_TCDeframer_HPP -#define Svc_CCSDS_TCDeframer_HPP - -#include "Svc/CCSDS/TCDeframer/TCDeframerComponentAc.hpp" - -namespace Svc { -namespace CCSDS { -class TCDeframer : public TCDeframerComponentBase { - - static const U8 SPACE_PACKET_HEADER_SIZE = 5; - static const U8 SPACE_PACKET_TRAILER_SIZE = 2; - public: - // ---------------------------------------------------------------------- - // Component construction and destruction - // ---------------------------------------------------------------------- - - //! Construct TCDeframer object - TCDeframer(const char* const compName //!< The component name - ); - - //! Destroy TCDeframer object - ~TCDeframer(); - - private: - // ---------------------------------------------------------------------- - // Handler implementations for user-defined typed input ports - // ---------------------------------------------------------------------- - - //! Handler implementation for dataIn - //! - //! Port to receive framed data - void dataIn_handler(FwIndexType portNum, //!< The port number - Fw::Buffer& data, - const ComCfg::FrameContext& context) override; - - //! Handler implementation for dataReturnIn - //! - //! Port receiving back ownership of sent frame buffers - void dataReturnIn_handler(FwIndexType portNum, //!< The port number - Fw::Buffer& data, //!< The buffer - const ComCfg::FrameContext& context) override; - -}; -} // namespace CCSDS -} // namespace Svc - -#endif diff --git a/Svc/CCSDS/SpacePacketDeframer/TCDeframer/docs/sdd.md b/Svc/CCSDS/SpacePacketDeframer/TCDeframer/docs/sdd.md deleted file mode 100644 index a8cb66d1945..00000000000 --- a/Svc/CCSDS/SpacePacketDeframer/TCDeframer/docs/sdd.md +++ /dev/null @@ -1,66 +0,0 @@ -# Svc::TCDeframer - -Deframer for the TC Space Data Link Protocl (CCSDS Standard) - -## Usage Examples -Add usage examples here - -### Diagrams -Add diagrams here - -### Typical Usage -And the typical usage of the component here - -## Class Diagram -Add a class diagram here - -## Port Descriptions -| Name | Description | -|---|---| -|---|---| - -## Component States -Add component states in the chart below -| Name | Description | -|---|---| -|---|---| - -## Sequence Diagrams -Add sequence diagrams here - -## Parameters -| Name | Description | -|---|---| -|---|---| - -## Commands -| Name | Description | -|---|---| -|---|---| - -## Events -| Name | Description | -|---|---| -|---|---| - -## Telemetry -| Name | Description | -|---|---| -|---|---| - -## Unit Tests -Add unit test descriptions in the chart below -| Name | Description | Output | Coverage | -|---|---|---|---| -|---|---|---|---| - -## Requirements -Add requirements in the chart below -| Name | Description | Validation | -|---|---|---| -|---|---|---| - -## Change Log -| Date | Description | -|---|---| -|---| Initial Draft | \ No newline at end of file From 628262502927ceb31db45058119c7a61aaf8c7bc Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Mon, 12 May 2025 17:30:19 -0700 Subject: [PATCH 27/95] Document and implement services/functions provided by the TCDeframer --- Svc/CCSDS/TCDeframer/TCDeframer.cpp | 55 +++++++++++++++++++++++------ Svc/CCSDS/TCDeframer/docs/sdd.md | 18 ++++++++++ Svc/CCSDS/Types/Types.fpp | 1 + 3 files changed, 63 insertions(+), 11 deletions(-) diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.cpp b/Svc/CCSDS/TCDeframer/TCDeframer.cpp index 6b6d3b44222..3c092227e62 100644 --- a/Svc/CCSDS/TCDeframer/TCDeframer.cpp +++ b/Svc/CCSDS/TCDeframer/TCDeframer.cpp @@ -5,9 +5,11 @@ // ====================================================================== #include "Svc/CCSDS/TCDeframer/TCDeframer.hpp" -#include "Svc/CCSDS/Types/TCFrameHeaderSerializableAc.hpp" -#include "Svc/CCSDS/Types/FppConstantsAc.hpp" #include "FpConfig.hpp" +#include "Svc/CCSDS/Types/FppConstantsAc.hpp" +#include "Svc/CCSDS/Types/TCFrameHeaderSerializableAc.hpp" +#include "Svc/CCSDS/Types/TCFrameTrailerSerializableAc.hpp" +#include "Svc/CCSDS/Utils/CRC16.hpp" namespace Svc { namespace CCSDS { @@ -15,8 +17,7 @@ namespace CCSDS { // Component construction and destruction // ---------------------------------------------------------------------- -TCDeframer ::TCDeframer(const char* const compName) - : TCDeframerComponentBase(compName) {} +TCDeframer ::TCDeframer(const char* const compName) : TCDeframerComponentBase(compName) {} TCDeframer ::~TCDeframer() {} @@ -25,7 +26,6 @@ TCDeframer ::~TCDeframer() {} // ---------------------------------------------------------------------- void TCDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { - // CCSDS TC Format: // 5 octets - TC Primary Header // Up to 1019 octets - Data Field (including optional 2 octets frame error control field) @@ -40,27 +40,60 @@ void TCDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const Co // 10b- XX - Frame Length // 8b - XX - Frame Sequence Number - FW_ASSERT(data.getSize() >= CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE, static_cast(data.getSize())); + // CCSDS TC Trailer: + // 16b - Frame Error Control Field (FECF): CRC16 + + FW_ASSERT(data.getSize() >= CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE, + static_cast(data.getSize())); CCSDS::Types::TCFrameHeader header; Fw::SerializeStatus status = data.getDeserializer().deserialize(header); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); U16 frame_length = header.getvcIdAndLength() & CCSDS::Types::TCFrameMasks::FrameLengthMask; - // U8 vc_id = (header.getvcIdAndLength() & CCSDS::Types::TCFrameMasks::VcIdMask) >> 2; - // TODO: check if frame_length is same as length of data minus header size - // TODO: Add checks and events in case of failure + U8 vc_id = + (header.getvcIdAndLength() & CCSDS::Types::TCFrameMasks::VcIdMask) >> CCSDS::Types::TCFrameMasks::VcIdOffset; + U16 spacecraft_id = header.getflagsAndScId() & CCSDS::Types::TCFrameMasks::SpacecraftIdMask; + if (spacecraft_id != ComCfg::FppConstant_SpacecraftId::SpacecraftId) { + printf("Spacecraft ID mismatch: %d != %d\n", spacecraft_id, + ComCfg::FppConstant_SpacecraftId::SpacecraftId); + } + if (data.getSize() < frame_length + CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE + CCSDS::Types::TCFrameTrailer::SERIALIZED_SIZE) { + printf("Frame length mismatch: %d != %d\n", frame_length, + data.getSize() - CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE - + CCSDS::Types::TCFrameTrailer::SERIALIZED_SIZE); + } + if (vc_id != ComCfg::FppConstant_VcId::VcId) { + printf("VC ID mismatch: %d != %d\n", vc_id, ComCfg::FppConstant_VcId::VcId); + } + + // ------------------------------------------------- + // CRC Check + // ------------------------------------------------- + // Compute CRC over the entire frame buffer minus the FECF trailer + U16 computed_crc = CCSDS::Utils::CRC16::compute(data.getData(), + CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE + frame_length); + CCSDS::Types::TCFrameTrailer trailer; + auto deserializer = data.getDeserializer(); + deserializer.moveDeserToOffset(CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE + frame_length); + status = deserializer.deserialize(trailer); + FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); + U16 transmitted_crc = trailer.getfecf(); + if (transmitted_crc != computed_crc) { + printf("FECF mismatch: %d != %d\n", transmitted_crc, computed_crc); + } + + // Point to the start of the data field and set appropriate size data.setData(data.getData() + Svc::CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE); data.setSize(frame_length); this->dataOut_out(0, data, context); - } void TCDeframer ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer, const ComCfg::FrameContext& context) { this->dataReturnOut_out(0, fwBuffer, context); } -} // namespace CCSDS +} // namespace CCSDS } // namespace Svc diff --git a/Svc/CCSDS/TCDeframer/docs/sdd.md b/Svc/CCSDS/TCDeframer/docs/sdd.md index a8cb66d1945..d052e388cb5 100644 --- a/Svc/CCSDS/TCDeframer/docs/sdd.md +++ b/Svc/CCSDS/TCDeframer/docs/sdd.md @@ -2,6 +2,24 @@ Deframer for the TC Space Data Link Protocl (CCSDS Standard) +- Service Types: Use "Expedited Service" Type-B Frames (meaning no sequence control) +- This means FARM flag is expected to be 0, and sequence control is set to all 0s + +Implements the following service: +- VIRTUAL CHANNEL PACKET SERVICE + +Implements the following functions: +- ALL FRAMES RECEPTION FUNCTION +- VC PACKET EXTRACTION FUNCTION (Router is the user to which frame data unit is delivered) ---- OR ------ use VCA_SDU with no Space Packet +- FRAME DELIVERY FUNCTION (Type-BD -> to Router) +- Frame Validation Check Procedure + + +Not implemented: +- Sequence Control (Type-A frames) and Control Commands +- + + ## Usage Examples Add usage examples here diff --git a/Svc/CCSDS/Types/Types.fpp b/Svc/CCSDS/Types/Types.fpp index 872f6523bd0..b913b38f8fd 100644 --- a/Svc/CCSDS/Types/Types.fpp +++ b/Svc/CCSDS/Types/Types.fpp @@ -29,6 +29,7 @@ module Types { constant ReservedMask = 0x0C00 constant SpacecraftIdMask = 0x03FF constant VcIdMask = 0xFC00 + constant VcIdOffset = 10 constant FrameLengthMask = 0x03FF } From efc26d138cabb93a9d5ab12d6022e636107af7e2 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Tue, 13 May 2025 15:33:09 -0700 Subject: [PATCH 28/95] Add events, todos and notes --- Ref/Top/instances.fpp | 4 ++-- Svc/CCSDS/TCDeframer/TCDeframer.cpp | 17 +++++++++-------- Svc/CCSDS/TCDeframer/TCDeframer.fpp | 12 ++++++++++++ Svc/CCSDS/TMFramer/TMFramer.cpp | 9 +++++++-- Svc/CCSDS/TMFramer/TMFramer.hpp | 6 +++++- Svc/CCSDS/space-packet.md | 5 +++++ 6 files changed, 40 insertions(+), 13 deletions(-) create mode 100644 Svc/CCSDS/space-packet.md diff --git a/Ref/Top/instances.fpp b/Ref/Top/instances.fpp index 48232db515b..1b1d96b61f1 100644 --- a/Ref/Top/instances.fpp +++ b/Ref/Top/instances.fpp @@ -171,9 +171,9 @@ module Ref { instance spacePacketDeframer: Svc.CCSDS.SpacePacketDeframer base id 0x5000 - instance tmFramer: Svc.CCSDS.TMFramer base id 0x4C00 + instance tmFramer: Svc.CCSDS.TMFramer base id 0x5100 - instance spacePacketFramer: Svc.CCSDS.SpacePacketFramer base id 0x5000 + instance spacePacketFramer: Svc.CCSDS.SpacePacketFramer base id 0x5200 instance fprimeRouter: Svc.FprimeRouter base id 0x4D00 diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.cpp b/Svc/CCSDS/TCDeframer/TCDeframer.cpp index 3c092227e62..c28a7e63d56 100644 --- a/Svc/CCSDS/TCDeframer/TCDeframer.cpp +++ b/Svc/CCSDS/TCDeframer/TCDeframer.cpp @@ -5,7 +5,7 @@ // ====================================================================== #include "Svc/CCSDS/TCDeframer/TCDeframer.hpp" -#include "FpConfig.hpp" +#include "config/FpConfig.hpp" #include "Svc/CCSDS/Types/FppConstantsAc.hpp" #include "Svc/CCSDS/Types/TCFrameHeaderSerializableAc.hpp" #include "Svc/CCSDS/Types/TCFrameTrailerSerializableAc.hpp" @@ -33,7 +33,7 @@ void TCDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const Co // CCSDS TC Primary Header: // 2b - 00 - TF Version Number // 1b - 0/1 - Bypass Flag (0 = FARM checks enabled, 1 = FARM checks bypassed) - // 1b - 0/1 - Control Command Flag (0 = Type-D data, 1 = Type-C data) + // 1b - 0/1 - Control Command Flag (0 = Type-D data, 1 = Type-C control command) // 2b - 00 - Reserved Spare (set to 00) // 10b- XX - Spacecraft ID // 6b - XX - Virtual Channel ID @@ -55,16 +55,17 @@ void TCDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const Co (header.getvcIdAndLength() & CCSDS::Types::TCFrameMasks::VcIdMask) >> CCSDS::Types::TCFrameMasks::VcIdOffset; U16 spacecraft_id = header.getflagsAndScId() & CCSDS::Types::TCFrameMasks::SpacecraftIdMask; if (spacecraft_id != ComCfg::FppConstant_SpacecraftId::SpacecraftId) { - printf("Spacecraft ID mismatch: %d != %d\n", spacecraft_id, - ComCfg::FppConstant_SpacecraftId::SpacecraftId); + this->log_WARNING_HI_InvalidHeaderField(TCDeframer_HeaderField::SpacecraftId, spacecraft_id, + ComCfg::FppConstant_SpacecraftId::SpacecraftId); } if (data.getSize() < frame_length + CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE + CCSDS::Types::TCFrameTrailer::SERIALIZED_SIZE) { - printf("Frame length mismatch: %d != %d\n", frame_length, - data.getSize() - CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE - - CCSDS::Types::TCFrameTrailer::SERIALIZED_SIZE); + this->log_WARNING_HI_InvalidHeaderField(TCDeframer_HeaderField::FrameLength, frame_length, + data.getSize() - CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE - + CCSDS::Types::TCFrameTrailer::SERIALIZED_SIZE); } if (vc_id != ComCfg::FppConstant_VcId::VcId) { - printf("VC ID mismatch: %d != %d\n", vc_id, ComCfg::FppConstant_VcId::VcId); + this->log_WARNING_HI_InvalidHeaderField(TCDeframer_HeaderField::VcId, vc_id, + ComCfg::FppConstant_VcId::VcId); } // ------------------------------------------------- diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.fpp b/Svc/CCSDS/TCDeframer/TCDeframer.fpp index ee85ab68b06..65ec39f8616 100644 --- a/Svc/CCSDS/TCDeframer/TCDeframer.fpp +++ b/Svc/CCSDS/TCDeframer/TCDeframer.fpp @@ -5,6 +5,18 @@ module CCSDS { include "../../Interfaces/DeframerInterface.fppi" + @ Used for event reporting + enum HeaderField { + SpacecraftId, + FrameLength, + VcId + } + + @ Invalid Data Field + event InvalidHeaderField(field: HeaderField, expected: U32, received: U32) \ + severity warning high \ + format "Invalid Header Field Received. Field {} | Expected: {} | Received: {}" + ############################################################################### # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # ############################################################################### diff --git a/Svc/CCSDS/TMFramer/TMFramer.cpp b/Svc/CCSDS/TMFramer/TMFramer.cpp index 2902dedb7ec..a17e73e84aa 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.cpp +++ b/Svc/CCSDS/TMFramer/TMFramer.cpp @@ -29,6 +29,9 @@ TMFramer ::~TMFramer() {} // ---------------------------------------------------------------------- void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { + // TODO: VcId should likely be passed in the context by the caller, rather than retrieved here + // This matches the VCP.request Service Primitive better + // TODO: make this an event probably FW_ASSERT(data.getSize() <= ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize, static_cast(data.getSize())); @@ -53,6 +56,7 @@ void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComC header.setvirtualFrameCount(this->m_virtualFrameCount); header.setdataFieldStatus(dataFieldStatus); + // We use only a single Virtual Channel for now, so master and virtual frame counts are the same this->m_masterFrameCount++; // U8 intended to wrap around (modulo 256) this->m_virtualFrameCount++; // U8 intended to wrap around (modulo 256) @@ -70,6 +74,8 @@ void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComC status = frameSerializer.serialize(data.getData(), data.getSize(), Fw::Serialization::OMIT_LENGTH); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); + // TODO: fill with Idle Packets + // ------------------------------------------------- // Trailer: Compute CRC // ------------------------------------------------- @@ -97,8 +103,7 @@ void TMFramer ::comStatusIn_handler(FwIndexType portNum, Fw::Success& condition) void TMFramer ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& frameBuffer, const ComCfg::FrameContext& context) { - // dataReturnIn is the member buffer coming back from the ComManager (e.g. ComStub) component - // this->bufferDeallocate_out(0, frameBuffer); + // dataReturnIn is our own member buffer coming back from the dataOut call - memset it to 0 ::memset(this->m_frameBuffer, 0, sizeof(this->m_frameBuffer)); } diff --git a/Svc/CCSDS/TMFramer/TMFramer.hpp b/Svc/CCSDS/TMFramer/TMFramer.hpp index efc842a1884..0abca7a99bb 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.hpp +++ b/Svc/CCSDS/TMFramer/TMFramer.hpp @@ -41,7 +41,10 @@ class TMFramer final : public TMFramerComponentBase { //! Handler implementation for dataIn //! - //! Port to receive data to frame, in a Fw::Buffer with optional context + //! Port to receive data to frame, in a Fw::Buffer with optional context. + //! This is essentially the CCSDS TM VCP.request Service Primitive, with + //! Packet=data and GVCID implicitly passed in context + //! void dataIn_handler(FwIndexType portNum, //!< The port number Fw::Buffer& data, const ComCfg::FrameContext& context) override; @@ -57,6 +60,7 @@ class TMFramer final : public TMFramerComponentBase { // at a time, we can use a member fixed-size buffer to hold the frame data U8 m_frameBuffer[ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize]; //!< Buffer to hold the frame data + // Current implementation uses a single virtual channel, so we can use a single virtual frame count U8 m_masterFrameCount; //!< Master Frame Count - 8 bits - wraps around at 255 U8 m_virtualFrameCount; //!< Virtual Frame Count - 8 bits - wraps around at 255 }; diff --git a/Svc/CCSDS/space-packet.md b/Svc/CCSDS/space-packet.md new file mode 100644 index 00000000000..5aa01b0d144 --- /dev/null +++ b/Svc/CCSDS/space-packet.md @@ -0,0 +1,5 @@ +# F´ Space Packet usage + +In the Space Packets used by core F´: + +- Secondary header is implicitly set to the APID, because the data is there on all F´ packets. \ No newline at end of file From 2cf0435e16b695ec437550636a90b0581194d0e7 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 14 May 2025 15:39:38 -0700 Subject: [PATCH 29/95] fill TM frame with idle packet --- .../SpacePacketFramer/SpacePacketFramer.hpp | 4 +++ Svc/CCSDS/TCDeframer/TCDeframer.cpp | 3 ++- Svc/CCSDS/TCDeframer/TCDeframer.fpp | 3 ++- Svc/CCSDS/TCDeframer/TCDeframer.hpp | 10 +++---- Svc/CCSDS/TMFramer/TMFramer.cpp | 27 ++++++++++++++++++- Svc/CCSDS/TMFramer/TMFramer.hpp | 20 +++++++++----- default/config/ComCfg.fpp | 2 +- 7 files changed, 53 insertions(+), 16 deletions(-) diff --git a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp index bf854ca35a6..1810a649dc8 100644 --- a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp +++ b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp @@ -63,6 +63,10 @@ class SpacePacketFramer final : public SpacePacketFramerComponentBase { // FwIndexType get_index_from_apid(ComCfg::APID::T apid); ComCfg::APID::T get_apid_from_index(FwIndexType index); + // ---------------------------------------------------------------------- + // Members + // ---------------------------------------------------------------------- + U16 m_packetSequenceCounts[ComCfg::APID::NUM_CONSTANTS] = {0}; //!< Packet sequence counts for each APID }; diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.cpp b/Svc/CCSDS/TCDeframer/TCDeframer.cpp index c28a7e63d56..fb83f01547c 100644 --- a/Svc/CCSDS/TCDeframer/TCDeframer.cpp +++ b/Svc/CCSDS/TCDeframer/TCDeframer.cpp @@ -82,7 +82,8 @@ void TCDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const Co U16 transmitted_crc = trailer.getfecf(); if (transmitted_crc != computed_crc) { - printf("FECF mismatch: %d != %d\n", transmitted_crc, computed_crc); + this->log_WARNING_HI_InvalidHeaderField(TCDeframer_HeaderField::FrameErrorControlField, + computed_crc, transmitted_crc); } // Point to the start of the data field and set appropriate size diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.fpp b/Svc/CCSDS/TCDeframer/TCDeframer.fpp index 65ec39f8616..a2bcc018dec 100644 --- a/Svc/CCSDS/TCDeframer/TCDeframer.fpp +++ b/Svc/CCSDS/TCDeframer/TCDeframer.fpp @@ -9,7 +9,8 @@ module CCSDS { enum HeaderField { SpacecraftId, FrameLength, - VcId + VcId, + FrameErrorControlField } @ Invalid Data Field diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.hpp b/Svc/CCSDS/TCDeframer/TCDeframer.hpp index 704937a646d..50bbac42fd7 100644 --- a/Svc/CCSDS/TCDeframer/TCDeframer.hpp +++ b/Svc/CCSDS/TCDeframer/TCDeframer.hpp @@ -12,7 +12,6 @@ namespace Svc { namespace CCSDS { class TCDeframer : public TCDeframerComponentBase { - public: // ---------------------------------------------------------------------- // Component construction and destruction @@ -34,16 +33,15 @@ class TCDeframer : public TCDeframerComponentBase { //! //! Port to receive framed data void dataIn_handler(FwIndexType portNum, //!< The port number - Fw::Buffer& data, - const ComCfg::FrameContext& context) override; + Fw::Buffer& data, + const ComCfg::FrameContext& context) override; //! Handler implementation for dataReturnIn //! //! Port receiving back ownership of sent frame buffers void dataReturnIn_handler(FwIndexType portNum, //!< The port number - Fw::Buffer& data, //!< The buffer - const ComCfg::FrameContext& context) override; - + Fw::Buffer& data, //!< The buffer + const ComCfg::FrameContext& context) override; }; } // namespace CCSDS } // namespace Svc diff --git a/Svc/CCSDS/TMFramer/TMFramer.cpp b/Svc/CCSDS/TMFramer/TMFramer.cpp index a17e73e84aa..b178788d71d 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.cpp +++ b/Svc/CCSDS/TMFramer/TMFramer.cpp @@ -75,6 +75,9 @@ void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComC FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); // TODO: fill with Idle Packets + FW_ASSERT(frameSerializer.getBuffLength() <= std::numeric_limits::max(), + static_cast(frameSerializer.getBuffLength())); + this->fill_with_idle_packet(static_cast(frameSerializer.getBuffLength())); // ------------------------------------------------- // Trailer: Compute CRC @@ -107,6 +110,28 @@ void TMFramer ::dataReturnIn_handler(FwIndexType portNum, ::memset(this->m_frameBuffer, 0, sizeof(this->m_frameBuffer)); } -} // namespace CCSDS +void TMFramer ::fill_with_idle_packet(U16 startIndex) { + // TODO: make this code cleaner + U16 endIndex = ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize - + CCSDS::Types::TMFrameTrailer::SERIALIZED_SIZE; + U16 idlePacketLength = endIndex - startIndex; + FW_ASSERT(idlePacketLength > 0, static_cast(idlePacketLength)); + FW_ASSERT(idlePacketLength >= 7, static_cast(idlePacketLength)); // 7 bytes minimum for idle packet + FW_ASSERT(idlePacketLength <= ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize, + static_cast(idlePacketLength)); + U16 idleApid = 0x7FF; // All 1s (11bit) per Space Packet protocol paragraph 4.1.3.3.4.4 + this->m_frameBuffer[startIndex + 0] = (idleApid >> 8) & 0xFF; + this->m_frameBuffer[startIndex + 1] = idleApid & 0xFF; + this->m_frameBuffer[startIndex + 2] = 0xC0; // Sequence Flags = 0b11 (unsegmented) & unused Seq count + this->m_frameBuffer[startIndex + 3] = 0x00; // unused Sequence Count + this->m_frameBuffer[startIndex + 4] = idlePacketLength >> 8; // Packet Data Length MSB + this->m_frameBuffer[startIndex + 5] = idlePacketLength & 0xFF; // Packet Data Length LSB + // Fill the rest of the buffer with arbitrary idle data + for (U16 i = startIndex + 6; i < endIndex; i++) { + this->m_frameBuffer[i] = 0x44; // Idle data + } +} + +} // namespace CCSDS } // namespace Svc diff --git a/Svc/CCSDS/TMFramer/TMFramer.hpp b/Svc/CCSDS/TMFramer/TMFramer.hpp index 0abca7a99bb..f7d755728cc 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.hpp +++ b/Svc/CCSDS/TMFramer/TMFramer.hpp @@ -42,8 +42,8 @@ class TMFramer final : public TMFramerComponentBase { //! Handler implementation for dataIn //! //! Port to receive data to frame, in a Fw::Buffer with optional context. - //! This is essentially the CCSDS TM VCP.request Service Primitive, with - //! Packet=data and GVCID implicitly passed in context + //! This is essentially the CCSDS TM VCP.request Service Primitive, with + //! Packet=data and GVCID implicitly passed in context (TM Protocol 3.3.3.2) //! void dataIn_handler(FwIndexType portNum, //!< The port number Fw::Buffer& data, @@ -56,13 +56,21 @@ class TMFramer final : public TMFramerComponentBase { Fw::Buffer& data, const ComCfg::FrameContext& context) override; - // Because the TM protocol use fixed width frames, and only one frame is in transit between ComQueue and ComInterface - // at a time, we can use a member fixed-size buffer to hold the frame data + // ---------------------------------------------------------------------- + // Helpers + // ---------------------------------------------------------------------- + //! Fill the frame buffer with an Idle Packet to complete the frame data field + //! as per CCSDS TM Protocol paragraph 4.2.2.5. Idle packet is inserted at the + //! start_index index of the frame buffer, and fills it up to the end minus CRC + void fill_with_idle_packet(U16 start_index); + + // Because the TM protocol use fixed width frames, and only one frame is in transit between ComQueue and + // ComInterface at a time, we can use a member fixed-size buffer to hold the frame data U8 m_frameBuffer[ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize]; //!< Buffer to hold the frame data // Current implementation uses a single virtual channel, so we can use a single virtual frame count - U8 m_masterFrameCount; //!< Master Frame Count - 8 bits - wraps around at 255 - U8 m_virtualFrameCount; //!< Virtual Frame Count - 8 bits - wraps around at 255 + U8 m_masterFrameCount; //!< Master Frame Count - 8 bits - wraps around at 255 + U8 m_virtualFrameCount; //!< Virtual Frame Count - 8 bits - wraps around at 255 }; } // namespace CCSDS diff --git a/default/config/ComCfg.fpp b/default/config/ComCfg.fpp index 5f4d325bad2..7df3310748c 100644 --- a/default/config/ComCfg.fpp +++ b/default/config/ComCfg.fpp @@ -10,7 +10,7 @@ module ComCfg { constant SpacecraftId = 0x03FF # Spacecraft ID (10 bits) constant VcId = 0x001 # Virtual Channel ID (3 bits) - constant TmFrameFixedSize = 1024 + constant TmFrameFixedSize = 1024 # Needs to be at least COM_BUFFER_MAX_SIZE + (2 * SpacePacketHeaderSize) + 1 @ APIDs are 11 bits in the Space Packet protocol, so we use U16. Max value 7FF enum APID : U16 { From c42a5f475629d8507571ec5de57f9a1195b8bee1 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Mon, 19 May 2025 15:45:08 -0700 Subject: [PATCH 30/95] Add ApidMapper component and map APID - FwPacketDescriptor --- Ref/Top/instances.fpp | 2 +- Ref/Top/topology.fpp | 11 ++- Svc/CCSDS/ApidMapper/ApidMapper.cpp | 76 +++++++++++++++++ Svc/CCSDS/ApidMapper/ApidMapper.fpp | 16 ++++ Svc/CCSDS/ApidMapper/ApidMapper.hpp | 81 +++++++++++++++++++ Svc/CCSDS/ApidMapper/CMakeLists.txt | 43 ++++++++++ Svc/CCSDS/ApidMapper/docs/sdd.md | 26 ++++++ Svc/CCSDS/CMakeLists.txt | 1 + .../SpacePacketFramer/SpacePacketFramer.cpp | 31 +------ .../SpacePacketFramer/SpacePacketFramer.hpp | 14 ---- Svc/CCSDS/TMFramer/TMFramer.cpp | 1 + default/config/ComCfg.fpp | 5 +- 12 files changed, 259 insertions(+), 48 deletions(-) create mode 100644 Svc/CCSDS/ApidMapper/ApidMapper.cpp create mode 100644 Svc/CCSDS/ApidMapper/ApidMapper.fpp create mode 100644 Svc/CCSDS/ApidMapper/ApidMapper.hpp create mode 100644 Svc/CCSDS/ApidMapper/CMakeLists.txt create mode 100644 Svc/CCSDS/ApidMapper/docs/sdd.md diff --git a/Ref/Top/instances.fpp b/Ref/Top/instances.fpp index 1b1d96b61f1..ca01d09974a 100644 --- a/Ref/Top/instances.fpp +++ b/Ref/Top/instances.fpp @@ -177,7 +177,7 @@ module Ref { instance fprimeRouter: Svc.FprimeRouter base id 0x4D00 - instance fprimeFramer: Svc.FprimeFramer base id 0x4E00 + instance apidMapper: Svc.CCSDS.ApidMapper base id 0x4E00 instance comStub: Svc.ComStub base id 0x4F00 diff --git a/Ref/Top/topology.fpp b/Ref/Top/topology.fpp index 3e7990235e5..de52dcc55f7 100644 --- a/Ref/Top/topology.fpp +++ b/Ref/Top/topology.fpp @@ -50,7 +50,7 @@ module Ref { instance fileUplink instance commsBufferManager instance frameAccumulator - instance fprimeFramer + instance apidMapper instance posixTime instance pingRcvr instance prmDb @@ -107,9 +107,12 @@ module Ref { tlmSend.PktSend -> comQueue.comPacketQueueIn[Ports_ComPacketQueue.TELEMETRY] fileDownlink.bufferSendOut -> comQueue.bufferQueueIn[Ports_ComBufferQueue.FILE_DOWNLINK] comQueue.bufferReturnOut[Ports_ComBufferQueue.FILE_DOWNLINK] -> fileDownlink.bufferReturn - # ComQueue <-> Framer - comQueue.dataOut -> spacePacketFramer.dataIn - spacePacketFramer.dataReturnOut -> comQueue.dataReturnIn + # ComQueue <-> ApidMapper + comQueue.dataOut -> apidMapper.dataIn + apidMapper.dataReturnOut -> comQueue.dataReturnIn + # ApidMapper <-> Framer + apidMapper.dataOut -> spacePacketFramer.dataIn + spacePacketFramer.dataReturnOut -> apidMapper.dataReturnIn # Buffer Management for Framer spacePacketFramer.bufferAllocate -> commsBufferManager.bufferGetCallee spacePacketFramer.bufferDeallocate -> commsBufferManager.bufferSendIn diff --git a/Svc/CCSDS/ApidMapper/ApidMapper.cpp b/Svc/CCSDS/ApidMapper/ApidMapper.cpp new file mode 100644 index 00000000000..4e8603fb3cf --- /dev/null +++ b/Svc/CCSDS/ApidMapper/ApidMapper.cpp @@ -0,0 +1,76 @@ +// ====================================================================== +// \title ApidMapper.cpp +// \author chammard +// \brief cpp file for ApidMapper component implementation class +// ====================================================================== + +#include "Svc/CCSDS/ApidMapper/ApidMapper.hpp" + +namespace Svc { + +namespace CCSDS { + +// ---------------------------------------------------------------------- +// Component construction and destruction +// ---------------------------------------------------------------------- + +ApidMapper ::ApidMapper(const char* const compName) : ApidMapperComponentBase(compName) { + // Initialize the APID sequence table with APID values that need to be counted (order does not matter) + this->m_apidSequences[0].apid = ComCfg::APID::FW_PACKET_LOG; + this->m_apidSequences[1].apid = ComCfg::APID::FW_PACKET_TELEM; + this->m_apidSequences[2].apid = ComCfg::APID::FW_PACKET_FILE; + this->m_apidSequences[3].apid = ComCfg::APID::FW_PACKET_PACKETIZED_TLM; + this->m_apidSequences[4].apid = ComCfg::APID::FW_PACKET_UNKNOWN; + +} + +ApidMapper ::~ApidMapper() {} + +// ---------------------------------------------------------------------- +// Handler implementations for typed input ports +// ---------------------------------------------------------------------- + +void ApidMapper ::comStatusIn_handler(FwIndexType portNum, Fw::Success& condition) { + if (this->isConnected_comStatusOut_OutputPort(portNum)) { + this->comStatusOut_out(portNum, condition); + } +} + +void ApidMapper ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { + ComCfg::FrameContext contextCopy = context; + + // Deserialize Packet Descriptor to map to an APID + auto deserializer = data.getDeserializer(); + FwPacketDescriptorType descriptorValue = 0; + Fw::SerializeStatus status = deserializer.deserialize(descriptorValue); + FW_ASSERT(status == Fw::FW_SERIALIZE_OK, static_cast(status)); + + // Mapping one-to-one: Descriptor value is APID value + ComCfg::APID::T apid = static_cast(descriptorValue); + contextCopy.setapid(static_cast(apid)); + contextCopy.setsequenceCount(this->getAndIncrementSeqCount(static_cast(apid))); + // printf("APID: %d, SeqCount: %d\n", apid, contextCopy.getsequenceCount()); + + // Forward the buffer and context to the output port + this->dataOut_out(0, data, contextCopy); +} + +void ApidMapper ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { + this->dataReturnOut_out(portNum, data, context); +} + + +U16 ApidMapper ::getAndIncrementSeqCount(ComCfg::APID::T apid) { + for (U8 i = 0; i < MAX_TRACKED_APIDS; ++i) { + if (m_apidSequences[i].apid == apid) { + U16 seq = m_apidSequences[i].sequenceCount; + m_apidSequences[i].sequenceCount = (seq + 1) % (1 << 14); // Wrap around at 14 bits + return seq; + } + } + return 0; // or some error value +} + +} // namespace CCSDS + +} // namespace Svc diff --git a/Svc/CCSDS/ApidMapper/ApidMapper.fpp b/Svc/CCSDS/ApidMapper/ApidMapper.fpp new file mode 100644 index 00000000000..f2702321929 --- /dev/null +++ b/Svc/CCSDS/ApidMapper/ApidMapper.fpp @@ -0,0 +1,16 @@ +module Svc { +module CCSDS { + @ Maps output of ComQueue to CCSDS APIDs + passive component ApidMapper { + + include "../../Interfaces/FramerInterface.fppi" + + ############################################################################### + # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # + ############################################################################### + @ Port for requesting the current time + time get port timeCaller + + } +} +} \ No newline at end of file diff --git a/Svc/CCSDS/ApidMapper/ApidMapper.hpp b/Svc/CCSDS/ApidMapper/ApidMapper.hpp new file mode 100644 index 00000000000..4b0d0d625c8 --- /dev/null +++ b/Svc/CCSDS/ApidMapper/ApidMapper.hpp @@ -0,0 +1,81 @@ +// ====================================================================== +// \title ApidMapper.hpp +// \author chammard +// \brief hpp file for ApidMapper component implementation class +// ====================================================================== + +#ifndef Svc_CCSDS_ApidMapper_HPP +#define Svc_CCSDS_ApidMapper_HPP + +#include "Svc/CCSDS/ApidMapper/ApidMapperComponentAc.hpp" + +namespace Svc { + +namespace CCSDS { + +class ApidMapper final : public ApidMapperComponentBase { + public: + // ---------------------------------------------------------------------- + // Component construction and destruction + // ---------------------------------------------------------------------- + + //! Construct ApidMapper object + ApidMapper(const char* const compName //!< The component name + ); + + //! Destroy ApidMapper object + ~ApidMapper(); + + private: + // ---------------------------------------------------------------------- + // Handler implementations for typed input ports + // ---------------------------------------------------------------------- + + //! Handler implementation for comStatusIn + //! + //! Port receiving the general status from the downstream component + //! indicating it is ready or not-ready for more input + void comStatusIn_handler(FwIndexType portNum, //!< The port number + Fw::Success& condition //!< Condition success/failure + ) override; + + //! Handler implementation for dataIn + //! + //! Port to receive data to frame, in a Fw::Buffer with optional context + void dataIn_handler(FwIndexType portNum, //!< The port number + Fw::Buffer& data, + const ComCfg::FrameContext& context) override; + + //! Handler implementation for dataReturnIn + //! + //! Buffer coming from a deallocate call in a ComDriver component + void dataReturnIn_handler(FwIndexType portNum, //!< The port number + Fw::Buffer& data, + const ComCfg::FrameContext& context) override; + + private: + // ---------------------------------------------------------------------- + // Helpers + // ---------------------------------------------------------------------- + //! Get the sequence count for a given APID and increment it for the next + //! Wraps around at 14 bits + U16 getAndIncrementSeqCount(ComCfg::APID::T apid); + + //! This struct helps to track sequence counts per APID + struct ApidSequenceEntry { + ComCfg::APID::T apid = ComCfg::APID::FW_PACKET_UNKNOWN; + U16 sequenceCount; + }; + + private: + // ---------------------------------------------------------------------- + // Member variables + // ---------------------------------------------------------------------- + static const U8 MAX_TRACKED_APIDS = 5; + ApidSequenceEntry m_apidSequences[MAX_TRACKED_APIDS]; +}; + +} // namespace CCSDS +} // namespace Svc + +#endif diff --git a/Svc/CCSDS/ApidMapper/CMakeLists.txt b/Svc/CCSDS/ApidMapper/CMakeLists.txt new file mode 100644 index 00000000000..d278426f0ed --- /dev/null +++ b/Svc/CCSDS/ApidMapper/CMakeLists.txt @@ -0,0 +1,43 @@ +#### +# FPrime CMakeLists.txt: +# +# SOURCE_FILES: combined list of source and autocoding files +# MOD_DEPS: (optional) module dependencies +# UT_SOURCE_FILES: list of source files for unit tests +# +# More information in the F´ CMake API documentation: +# https://fprime.jpl.nasa.gov/latest/documentation/reference +# +#### + +set(SOURCE_FILES + "${CMAKE_CURRENT_LIST_DIR}/ApidMapper.fpp" + "${CMAKE_CURRENT_LIST_DIR}/ApidMapper.cpp" +) + +# Uncomment and add any modules that this component depends on, else +# they might not be available when cmake tries to build this component. +# +# Module names are derived from the path from the nearest project/library/framework +# root when not specifically overridden by the developer. i.e. The module defined by +# `Ref/SignalGen/CMakeLists.txt` will be named `Ref_SignalGen`. `Ref/SignalGen` +# is an acceptable alternative and will be internally converted to `Ref_SignalGen`. +# +# set(MOD_DEPS +# MyPackage_MyOtherModule +# ) + +register_fprime_module() + + +### Unit Tests ### +# set(UT_SOURCE_FILES +# "${CMAKE_CURRENT_LIST_DIR}/ApidMapper.fpp" +# "${CMAKE_CURRENT_LIST_DIR}/test/ut/ApidMapperTestMain.cpp" +# "${CMAKE_CURRENT_LIST_DIR}/test/ut/ApidMapperTester.cpp" +# ) +# set(UT_MOD_DEPS +# STest +# ) +# set(UT_AUTO_HELPERS ON) +# register_fprime_ut() diff --git a/Svc/CCSDS/ApidMapper/docs/sdd.md b/Svc/CCSDS/ApidMapper/docs/sdd.md new file mode 100644 index 00000000000..0b7b31d2598 --- /dev/null +++ b/Svc/CCSDS/ApidMapper/docs/sdd.md @@ -0,0 +1,26 @@ +# Svc::CCSDS::ApidMapper + +## 1. Overview + +The `ApidMapper` component is a passive F´ component that maps the descriptor type (ComPacketType/APID) found in the first two bytes of a data buffer to a CCSDS Space Packet APID. It also tracks and manages a sequence count for each APID, as required by the CCSDS protocol. This enables downstream components to generate correct CCSDS Space Packets with the appropriate APID and sequence count. + +## 2. Requirements + +- Extract the APID (descriptor type) from the first two bytes of each incoming buffer. +- Set the APID in the outgoing `FrameContext`. +- Track a 14-bit sequence count for each APID, incrementing and wrapping as required by the CCSDS standard. +- Support a small, fixed set of non-contiguous APIDs. +- Operate without dynamic memory allocation or standard library containers. + +## 3. Interfaces + +### Ports + +| Port Name | Direction | Description | +|----------------|-----------|------------------------------------------------------------------| +| dataIn | input | Receives data buffers and context from upstream | +| dataOut | output | Forwards buffer with updated context (APID and sequence count) | +| dataReturnIn | input | Receives returned buffers from downstream | +| dataReturnOut | output | Returns buffers to upstream | +| comStatusIn | input | Receives status from downstream | +| comStatusOut | output | Forwards status upstream | diff --git a/Svc/CCSDS/CMakeLists.txt b/Svc/CCSDS/CMakeLists.txt index 7982dd49cb2..d48fe84074d 100644 --- a/Svc/CCSDS/CMakeLists.txt +++ b/Svc/CCSDS/CMakeLists.txt @@ -4,3 +4,4 @@ add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/SpacePacketFramer/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/TCDeframer/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/TMFramer/") # add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Utils/") +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/ApidMapper/") diff --git a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp index ef4f53c3064..d8f40f3bf81 100644 --- a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp +++ b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp @@ -41,12 +41,12 @@ void SpacePacketFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, c // ----------------------------------------------- // PVN is always 0 per Standard - Packet Type is 0 for Telemetry (downlink) - SecHdr flag is 0 for no secondary header U16 packetIdentification = 0; - ComCfg::APID::T apid = this->get_apid_from_index(context.getcomQueueIndex()); - U16 sequenceCount = this->increment_sequence_count_for_apid(context.getcomQueueIndex()); + ComCfg::APID::T apid = context.getapid(); packetIdentification |= static_cast(apid) & CCSDS::Types::SpacePacketMasks::ApidMask; // 11 bit APID - + U16 packetSequenceControl = 0; packetSequenceControl |= 0x3 << CCSDS::Types::SpacePacketMasks::SeqFlagsOffset; // Sequence Flags 0b11 = unsegmented User Data + U16 sequenceCount = context.getsequenceCount(); packetSequenceControl |= sequenceCount & CCSDS::Types::SpacePacketMasks::SeqCountMask; // 14 bit sequence count FW_ASSERT(data.getSize() <= std::numeric_limits::max(), static_cast(data.getSize())); @@ -79,30 +79,5 @@ void SpacePacketFramer ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& f this->bufferDeallocate_out(0, frameBuffer); } -U16 SpacePacketFramer ::increment_sequence_count_for_apid(FwIndexType index) { - // FwIndexType index = this->get_index_from_apid(apid); - U16 sequenceCount = this->m_packetSequenceCounts[index]; - this->m_packetSequenceCounts[index] = (this->m_packetSequenceCounts[index] + 1) % (1 << 14); // Wrap around at 14 bits (modulo 2^14) - printf("index: %d, Sequence Count: %d\n", index, this->m_packetSequenceCounts[index]); - return sequenceCount; -} - -ComCfg::APID::T SpacePacketFramer ::get_apid_from_index(FwIndexType index) { - // Need a manual mapping from comQueue index to APID for now to get an APID count - // per APID - switch (index) { - case 0: - return ComCfg::APID::FW_PACKET_LOG; - case 1: - return ComCfg::APID::FW_PACKET_TELEM; - case 2: - return ComCfg::APID::FW_PACKET_FILE; - default: - return ComCfg::APID::FW_PACKET_UNKNOWN; // TODO: Handle unknown index - } -} - - } // namespace CCSDS - } // namespace Svc diff --git a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp index 1810a649dc8..f4eba53d4e9 100644 --- a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp +++ b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp @@ -54,20 +54,6 @@ class SpacePacketFramer final : public SpacePacketFramerComponentBase { Fw::Buffer& data, const ComCfg::FrameContext& context) override; - // ---------------------------------------------------------------------- - // Helpers - // ---------------------------------------------------------------------- - - U16 increment_sequence_count_for_apid(FwIndexType index); - - // FwIndexType get_index_from_apid(ComCfg::APID::T apid); - ComCfg::APID::T get_apid_from_index(FwIndexType index); - - // ---------------------------------------------------------------------- - // Members - // ---------------------------------------------------------------------- - - U16 m_packetSequenceCounts[ComCfg::APID::NUM_CONSTANTS] = {0}; //!< Packet sequence counts for each APID }; } // namespace CCSDS diff --git a/Svc/CCSDS/TMFramer/TMFramer.cpp b/Svc/CCSDS/TMFramer/TMFramer.cpp index b178788d71d..42a834618c4 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.cpp +++ b/Svc/CCSDS/TMFramer/TMFramer.cpp @@ -51,6 +51,7 @@ void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComC U16 dataFieldStatus = 0; dataFieldStatus |= 0x3 << CCSDS::Types::TMFrameMasks::segLengthOffset; // Seg Length 0b11 per Standard + // TODO: could virtual channel be passed in context or use portNum and a mapping ?? header.setchannelIds(channelIds); header.setmasterFrameCount(this->m_masterFrameCount); header.setvirtualFrameCount(this->m_virtualFrameCount); diff --git a/default/config/ComCfg.fpp b/default/config/ComCfg.fpp index 7df3310748c..d8fe9433635 100644 --- a/default/config/ComCfg.fpp +++ b/default/config/ComCfg.fpp @@ -28,9 +28,12 @@ module ComCfg { @ Type used to pass context info between components during framing/deframing struct FrameContext { comQueueIndex: FwIndexType @< Queue Index used by the ComQueue, other components shall not modify - apid: APID @< 11 bits APID in CCSDS + apid: APID @< 11 bits APID in CCSDS + sequenceCount: U16 @< 14 bit Sequence count - sequence count is incremented per APID } default { comQueueIndex = 0 + apid = APID.FW_PACKET_UNKNOWN + sequenceCount = 0 } } From a916ca7b51a49577b9bd469a8b9e0ea6e3195cda Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Tue, 20 May 2025 09:29:54 -0700 Subject: [PATCH 31/95] Refactor to new CMake API --- Svc/CCSDS/ApidMapper/CMakeLists.txt | 27 +++++------------ Svc/CCSDS/SpacePacketDeframer/CMakeLists.txt | 31 +++++++------------- Svc/CCSDS/SpacePacketFramer/CMakeLists.txt | 31 +++++++------------- Svc/CCSDS/TCDeframer/CMakeLists.txt | 28 +++++++++--------- Svc/CCSDS/TMFramer/CMakeLists.txt | 29 +++++++++--------- Svc/CCSDS/Types/CMakeLists.txt | 28 +++++------------- Svc/CCSDS/Utils/CMakeLists.txt | 28 +++++------------- 7 files changed, 72 insertions(+), 130 deletions(-) diff --git a/Svc/CCSDS/ApidMapper/CMakeLists.txt b/Svc/CCSDS/ApidMapper/CMakeLists.txt index d278426f0ed..3e06472f34a 100644 --- a/Svc/CCSDS/ApidMapper/CMakeLists.txt +++ b/Svc/CCSDS/ApidMapper/CMakeLists.txt @@ -1,33 +1,22 @@ #### # FPrime CMakeLists.txt: # -# SOURCE_FILES: combined list of source and autocoding files -# MOD_DEPS: (optional) module dependencies -# UT_SOURCE_FILES: list of source files for unit tests +# SOURCES: list of source files (to be compiled) +# AUTOCODER_INPUTS: list of files to be passed to the autocoders +# DEPENDS: list of libraries that this module depends on # # More information in the F´ CMake API documentation: # https://fprime.jpl.nasa.gov/latest/documentation/reference # #### -set(SOURCE_FILES - "${CMAKE_CURRENT_LIST_DIR}/ApidMapper.fpp" - "${CMAKE_CURRENT_LIST_DIR}/ApidMapper.cpp" +register_fprime_library( + SOURCES + "${CMAKE_CURRENT_LIST_DIR}/ApidMapper.cpp" + AUTOCODER_INPUTS + "${CMAKE_CURRENT_LIST_DIR}/ApidMapper.fpp" ) -# Uncomment and add any modules that this component depends on, else -# they might not be available when cmake tries to build this component. -# -# Module names are derived from the path from the nearest project/library/framework -# root when not specifically overridden by the developer. i.e. The module defined by -# `Ref/SignalGen/CMakeLists.txt` will be named `Ref_SignalGen`. `Ref/SignalGen` -# is an acceptable alternative and will be internally converted to `Ref_SignalGen`. -# -# set(MOD_DEPS -# MyPackage_MyOtherModule -# ) - -register_fprime_module() ### Unit Tests ### diff --git a/Svc/CCSDS/SpacePacketDeframer/CMakeLists.txt b/Svc/CCSDS/SpacePacketDeframer/CMakeLists.txt index 745f38e7bcf..b35e23e6814 100644 --- a/Svc/CCSDS/SpacePacketDeframer/CMakeLists.txt +++ b/Svc/CCSDS/SpacePacketDeframer/CMakeLists.txt @@ -1,35 +1,24 @@ #### # FPrime CMakeLists.txt: # -# SOURCE_FILES: combined list of source and autocoding files -# MOD_DEPS: (optional) module dependencies -# UT_SOURCE_FILES: list of source files for unit tests +# SOURCES: list of source files (to be compiled) +# AUTOCODER_INPUTS: list of files to be passed to the autocoders +# DEPENDS: list of libraries that this module depends on # # More information in the F´ CMake API documentation: # https://fprime.jpl.nasa.gov/latest/documentation/reference # #### -set(SOURCE_FILES - "${CMAKE_CURRENT_LIST_DIR}/SpacePacketDeframer.fpp" - "${CMAKE_CURRENT_LIST_DIR}/SpacePacketDeframer.cpp" +register_fprime_library( + SOURCES + "${CMAKE_CURRENT_LIST_DIR}/SpacePacketDeframer.cpp" + AUTOCODER_INPUTS + "${CMAKE_CURRENT_LIST_DIR}/SpacePacketDeframer.fpp" + DEPENDS + Svc_CCSDS_Types ) -# Uncomment and add any modules that this component depends on, else -# they might not be available when cmake tries to build this component. -# -# Module names are derived from the path from the nearest project/library/framework -# root when not specifically overridden by the developer. i.e. The module defined by -# `Ref/SignalGen/CMakeLists.txt` will be named `Ref_SignalGen`. `Ref/SignalGen` -# is an acceptable alternative and will be internally converted to `Ref_SignalGen`. -# - -set(MOD_DEPS - Svc_CCSDS_Types -) - -register_fprime_module() - ### Unit Tests ### # set(UT_SOURCE_FILES diff --git a/Svc/CCSDS/SpacePacketFramer/CMakeLists.txt b/Svc/CCSDS/SpacePacketFramer/CMakeLists.txt index 245b3143da0..72db320a4d6 100644 --- a/Svc/CCSDS/SpacePacketFramer/CMakeLists.txt +++ b/Svc/CCSDS/SpacePacketFramer/CMakeLists.txt @@ -1,35 +1,24 @@ #### # FPrime CMakeLists.txt: # -# SOURCE_FILES: combined list of source and autocoding files -# MOD_DEPS: (optional) module dependencies -# UT_SOURCE_FILES: list of source files for unit tests +# SOURCES: list of source files (to be compiled) +# AUTOCODER_INPUTS: list of files to be passed to the autocoders +# DEPENDS: list of libraries that this module depends on # # More information in the F´ CMake API documentation: # https://fprime.jpl.nasa.gov/latest/documentation/reference # #### -set(SOURCE_FILES - "${CMAKE_CURRENT_LIST_DIR}/SpacePacketFramer.fpp" - "${CMAKE_CURRENT_LIST_DIR}/SpacePacketFramer.cpp" +register_fprime_library( + SOURCES + "${CMAKE_CURRENT_LIST_DIR}/SpacePacketFramer.cpp" + AUTOCODER_INPUTS + "${CMAKE_CURRENT_LIST_DIR}/SpacePacketFramer.fpp" + DEPENDS + Svc_CCSDS_Types ) -# Uncomment and add any modules that this component depends on, else -# they might not be available when cmake tries to build this component. -# -# Module names are derived from the path from the nearest project/library/framework -# root when not specifically overridden by the developer. i.e. The module defined by -# `Ref/SignalGen/CMakeLists.txt` will be named `Ref_SignalGen`. `Ref/SignalGen` -# is an acceptable alternative and will be internally converted to `Ref_SignalGen`. -# - -set(MOD_DEPS - Svc_CCSDS_Types -) - -register_fprime_module() - ### Unit Tests ### # set(UT_SOURCE_FILES diff --git a/Svc/CCSDS/TCDeframer/CMakeLists.txt b/Svc/CCSDS/TCDeframer/CMakeLists.txt index 4d67d7aeae7..43d8b35cc6f 100644 --- a/Svc/CCSDS/TCDeframer/CMakeLists.txt +++ b/Svc/CCSDS/TCDeframer/CMakeLists.txt @@ -1,21 +1,21 @@ #### -# F prime CMakeLists.txt: +# FPrime CMakeLists.txt: # -# SOURCE_FILES: combined list of source and autocoding files -# MOD_DEPS: (optional) module dependencies -# UT_SOURCE_FILES: list of source files for unit tests +# SOURCES: list of source files (to be compiled) +# AUTOCODER_INPUTS: list of files to be passed to the autocoders +# DEPENDS: list of libraries that this module depends on +# +# More information in the F´ CMake API documentation: +# https://fprime.jpl.nasa.gov/latest/documentation/reference # #### -set(SOURCE_FILES - "${CMAKE_CURRENT_LIST_DIR}/TCDeframer.fpp" - "${CMAKE_CURRENT_LIST_DIR}/TCDeframer.cpp" -) - -# Uncomment and add any modules that this component depends on, else -# they might not be available when cmake tries to build this component. -set(MOD_DEPS - Svc_CCSDS_Types +register_fprime_library( + SOURCES + "${CMAKE_CURRENT_LIST_DIR}/TCDeframer.cpp" + AUTOCODER_INPUTS + "${CMAKE_CURRENT_LIST_DIR}/TCDeframer.fpp" + DEPENDS + Svc_CCSDS_Types ) -register_fprime_module() diff --git a/Svc/CCSDS/TMFramer/CMakeLists.txt b/Svc/CCSDS/TMFramer/CMakeLists.txt index f79c0f729fe..bf91e7e6f26 100644 --- a/Svc/CCSDS/TMFramer/CMakeLists.txt +++ b/Svc/CCSDS/TMFramer/CMakeLists.txt @@ -1,21 +1,20 @@ #### -# F prime CMakeLists.txt: +# FPrime CMakeLists.txt: # -# SOURCE_FILES: combined list of source and autocoding files -# MOD_DEPS: (optional) module dependencies -# UT_SOURCE_FILES: list of source files for unit tests +# SOURCES: list of source files (to be compiled) +# AUTOCODER_INPUTS: list of files to be passed to the autocoders +# DEPENDS: list of libraries that this module depends on +# +# More information in the F´ CMake API documentation: +# https://fprime.jpl.nasa.gov/latest/documentation/reference # #### -set(SOURCE_FILES - "${CMAKE_CURRENT_LIST_DIR}/TMFramer.fpp" - "${CMAKE_CURRENT_LIST_DIR}/TMFramer.cpp" -) -# Uncomment and add any modules that this component depends on, else -# they might not be available when cmake tries to build this component. - -set(MOD_DEPS - Svc_CCSDS_Types +register_fprime_library( + SOURCES + "${CMAKE_CURRENT_LIST_DIR}/TMFramer.cpp" + AUTOCODER_INPUTS + "${CMAKE_CURRENT_LIST_DIR}/TMFramer.fpp" + DEPENDS + Svc_CCSDS_Types ) - -register_fprime_module() diff --git a/Svc/CCSDS/Types/CMakeLists.txt b/Svc/CCSDS/Types/CMakeLists.txt index cc029842e0b..d7001e1b994 100644 --- a/Svc/CCSDS/Types/CMakeLists.txt +++ b/Svc/CCSDS/Types/CMakeLists.txt @@ -1,28 +1,16 @@ #### # FPrime CMakeLists.txt: # -# SOURCE_FILES: combined list of source and autocoding files -# MOD_DEPS: (optional) module dependencies -# UT_SOURCE_FILES: list of source files for unit tests +# SOURCES: list of source files (to be compiled) +# AUTOCODER_INPUTS: list of files to be passed to the autocoders +# DEPENDS: list of libraries that this module depends on # # More information in the F´ CMake API documentation: -# https://fprime.jpl.nasa.gov/latest/documentation/reference/ +# https://fprime.jpl.nasa.gov/latest/documentation/reference +# #### -set(SOURCE_FILES - "${CMAKE_CURRENT_LIST_DIR}/Types.fpp" +register_fprime_library( + AUTOCODER_INPUTS + "${CMAKE_CURRENT_LIST_DIR}/Types.fpp" ) - -# Uncomment and add any modules that this module depends on, else -# they might not be available when cmake tries to build this module. -# -# Module names are derived from the path from the nearest project/library/framework -# root when not specifically overridden by the developer. i.e. The module defined by -# `Ref/SignalGen/CMakeLists.txt` will be named `Ref_SignalGen`. `Ref/SignalGen` -# is an acceptable alternative and will be internally converted to `Ref_SignalGen`. -# -#set(MOD_DEPS -# MyPackage_MyOtherModule -#) - -register_fprime_module() diff --git a/Svc/CCSDS/Utils/CMakeLists.txt b/Svc/CCSDS/Utils/CMakeLists.txt index f45e61e3899..3f40f0177db 100644 --- a/Svc/CCSDS/Utils/CMakeLists.txt +++ b/Svc/CCSDS/Utils/CMakeLists.txt @@ -1,28 +1,16 @@ #### # FPrime CMakeLists.txt: # -# SOURCE_FILES: combined list of source and autocoding files -# MOD_DEPS: (optional) module dependencies -# UT_SOURCE_FILES: list of source files for unit tests +# SOURCES: list of source files (to be compiled) +# AUTOCODER_INPUTS: list of files to be passed to the autocoders +# DEPENDS: list of libraries that this module depends on # # More information in the F´ CMake API documentation: -# https://fprime.jpl.nasa.gov/latest/documentation/reference/ +# https://fprime.jpl.nasa.gov/latest/documentation/reference +# #### -set(SOURCE_FILES - "${CMAKE_CURRENT_LIST_DIR}/Utils.fpp" +register_fprime_library( + AUTOCODER_INPUTS + "${CMAKE_CURRENT_LIST_DIR}/Utils.fpp" ) - -# Uncomment and add any modules that this module depends on, else -# they might not be available when cmake tries to build this module. -# -# Module names are derived from the path from the nearest project/library/framework -# root when not specifically overridden by the developer. i.e. The module defined by -# `Ref/SignalGen/CMakeLists.txt` will be named `Ref_SignalGen`. `Ref/SignalGen` -# is an acceptable alternative and will be internally converted to `Ref_SignalGen`. -# -#set(MOD_DEPS -# MyPackage_MyOtherModule -#) - -register_fprime_module() From cdb6c9baaa33d50509ca45cd1b0e2a5da633241d Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Tue, 20 May 2025 12:42:29 -0700 Subject: [PATCH 32/95] Update Types and Add TCDeframer tests --- Svc/CCSDS/TCDeframer/CMakeLists.txt | 12 ++ Svc/CCSDS/TCDeframer/TCDeframer.cpp | 65 ++++---- Svc/CCSDS/TCDeframer/TCDeframer.fpp | 34 +++-- Svc/CCSDS/TCDeframer/TCDeframer.hpp | 24 +++ .../TCDeframer/test/ut/TCDeframerTestMain.cpp | 33 +++++ .../TCDeframer/test/ut/TCDeframerTester.cpp | 140 ++++++++++++++++++ .../TCDeframer/test/ut/TCDeframerTester.hpp | 83 +++++++++++ Svc/CCSDS/Types/Types.fpp | 5 +- default/config/ComCfg.fpp | 1 - 9 files changed, 356 insertions(+), 41 deletions(-) create mode 100644 Svc/CCSDS/TCDeframer/test/ut/TCDeframerTestMain.cpp create mode 100644 Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp create mode 100644 Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.hpp diff --git a/Svc/CCSDS/TCDeframer/CMakeLists.txt b/Svc/CCSDS/TCDeframer/CMakeLists.txt index 43d8b35cc6f..a7ea1a7b48a 100644 --- a/Svc/CCSDS/TCDeframer/CMakeLists.txt +++ b/Svc/CCSDS/TCDeframer/CMakeLists.txt @@ -19,3 +19,15 @@ register_fprime_library( Svc_CCSDS_Types ) +set(UT_AUTO_HELPERS ON) + +register_fprime_ut( + SOURCES + "${CMAKE_CURRENT_LIST_DIR}/test/ut/TCDeframerTestMain.cpp" + "${CMAKE_CURRENT_LIST_DIR}/test/ut/TCDeframerTester.cpp" + AUTOCODER_INPUTS + "${CMAKE_CURRENT_LIST_DIR}/TCDeframer.fpp" + DEPENDS + Svc_CCSDS_Types + STest +) \ No newline at end of file diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.cpp b/Svc/CCSDS/TCDeframer/TCDeframer.cpp index fb83f01547c..e869229a7d9 100644 --- a/Svc/CCSDS/TCDeframer/TCDeframer.cpp +++ b/Svc/CCSDS/TCDeframer/TCDeframer.cpp @@ -5,19 +5,22 @@ // ====================================================================== #include "Svc/CCSDS/TCDeframer/TCDeframer.hpp" -#include "config/FpConfig.hpp" #include "Svc/CCSDS/Types/FppConstantsAc.hpp" #include "Svc/CCSDS/Types/TCFrameHeaderSerializableAc.hpp" #include "Svc/CCSDS/Types/TCFrameTrailerSerializableAc.hpp" #include "Svc/CCSDS/Utils/CRC16.hpp" +#include "config/FpConfig.hpp" namespace Svc { namespace CCSDS { + // ---------------------------------------------------------------------- // Component construction and destruction // ---------------------------------------------------------------------- -TCDeframer ::TCDeframer(const char* const compName) : TCDeframerComponentBase(compName) {} +TCDeframer ::TCDeframer(const char* const compName) + : TCDeframerComponentBase(compName), + m_spacecraftId(ComCfg::FppConstant_SpacecraftId::SpacecraftId) {} TCDeframer ::~TCDeframer() {} @@ -43,51 +46,61 @@ void TCDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const Co // CCSDS TC Trailer: // 16b - Frame Error Control Field (FECF): CRC16 - FW_ASSERT(data.getSize() >= CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE, - static_cast(data.getSize())); + FW_ASSERT(data.getSize() >= TCFrameHeader::SERIALIZED_SIZE, static_cast(data.getSize())); - CCSDS::Types::TCFrameHeader header; + TCFrameHeader header; Fw::SerializeStatus status = data.getDeserializer().deserialize(header); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); - U16 frame_length = header.getvcIdAndLength() & CCSDS::Types::TCFrameMasks::FrameLengthMask; - U8 vc_id = - (header.getvcIdAndLength() & CCSDS::Types::TCFrameMasks::VcIdMask) >> CCSDS::Types::TCFrameMasks::VcIdOffset; - U16 spacecraft_id = header.getflagsAndScId() & CCSDS::Types::TCFrameMasks::SpacecraftIdMask; - if (spacecraft_id != ComCfg::FppConstant_SpacecraftId::SpacecraftId) { - this->log_WARNING_HI_InvalidHeaderField(TCDeframer_HeaderField::SpacecraftId, spacecraft_id, - ComCfg::FppConstant_SpacecraftId::SpacecraftId); + U16 frame_length = header.getvcIdAndLength() & TCFrameMasks::FrameLengthMask; + U8 vc_id = (header.getvcIdAndLength() & TCFrameMasks::VcIdMask) >> TCFrameMasks::VcIdOffset; + U16 spacecraft_id = header.getflagsAndScId() & TCFrameMasks::SpacecraftIdMask; + U8 sequence_number = header.getframeSequenceNbr(); + + if (spacecraft_id != this->m_spacecraftId) { + this->log_ACTIVITY_LO_InvalidSpacecraftId(spacecraft_id, this->m_spacecraftId); + this->dataReturnOut_out(0, data, context); // drop the frame + return; + } + if (data.getSize() < frame_length + TCFrameHeader::SERIALIZED_SIZE + TCFrameTrailer::SERIALIZED_SIZE) { + U32 maxDataAvailable = data.getSize() - TCFrameHeader::SERIALIZED_SIZE - TCFrameTrailer::SERIALIZED_SIZE; + this->log_WARNING_HI_InvalidFrameLength(frame_length, maxDataAvailable); + this->dataReturnOut_out(0, data, context); // drop the frame + return; } - if (data.getSize() < frame_length + CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE + CCSDS::Types::TCFrameTrailer::SERIALIZED_SIZE) { - this->log_WARNING_HI_InvalidHeaderField(TCDeframer_HeaderField::FrameLength, frame_length, - data.getSize() - CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE - - CCSDS::Types::TCFrameTrailer::SERIALIZED_SIZE); + if (this->m_acceptAllVcid == false && vc_id != this->m_vcId) { + this->log_ACTIVITY_LO_InvalidVcId(vc_id, this->m_vcId); + this->dataReturnOut_out(0, data, context); // drop the frame + return; } - if (vc_id != ComCfg::FppConstant_VcId::VcId) { - this->log_WARNING_HI_InvalidHeaderField(TCDeframer_HeaderField::VcId, vc_id, - ComCfg::FppConstant_VcId::VcId); + if (sequence_number != this->m_sequenceCount) { + this->log_WARNING_HI_UnexpectedSequenceNumber(sequence_number, this->m_sequenceCount); + // Synchronize onboard count with received number so that count can keep going + this->m_sequenceCount = sequence_number; } + this->m_sequenceCount++; // increment count for next frame + // ------------------------------------------------- // CRC Check // ------------------------------------------------- // Compute CRC over the entire frame buffer minus the FECF trailer - U16 computed_crc = CCSDS::Utils::CRC16::compute(data.getData(), - CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE + frame_length); - CCSDS::Types::TCFrameTrailer trailer; + U16 computed_crc = CCSDS::Utils::CRC16::compute(data.getData(), TCFrameHeader::SERIALIZED_SIZE + frame_length); + TCFrameTrailer trailer; auto deserializer = data.getDeserializer(); - deserializer.moveDeserToOffset(CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE + frame_length); + deserializer.moveDeserToOffset(TCFrameHeader::SERIALIZED_SIZE + frame_length); status = deserializer.deserialize(trailer); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); U16 transmitted_crc = trailer.getfecf(); if (transmitted_crc != computed_crc) { - this->log_WARNING_HI_InvalidHeaderField(TCDeframer_HeaderField::FrameErrorControlField, - computed_crc, transmitted_crc); + this->log_WARNING_HI_InvalidCrc(computed_crc, transmitted_crc); + this->dataReturnOut_out(0, data, context); // drop the frame + return; } // Point to the start of the data field and set appropriate size - data.setData(data.getData() + Svc::CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE); + data.setData(data.getData() + TCFrameHeader::SERIALIZED_SIZE); data.setSize(frame_length); this->dataOut_out(0, data, context); diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.fpp b/Svc/CCSDS/TCDeframer/TCDeframer.fpp index a2bcc018dec..4b13a5acf9a 100644 --- a/Svc/CCSDS/TCDeframer/TCDeframer.fpp +++ b/Svc/CCSDS/TCDeframer/TCDeframer.fpp @@ -5,18 +5,30 @@ module CCSDS { include "../../Interfaces/DeframerInterface.fppi" - @ Used for event reporting - enum HeaderField { - SpacecraftId, - FrameLength, - VcId, - FrameErrorControlField - } - - @ Invalid Data Field - event InvalidHeaderField(field: HeaderField, expected: U32, received: U32) \ + @ Deframing received an invalid SCID + event InvalidSpacecraftId(transmitted: U16, configured: U16) \ + severity activity low \ + format "Invalid Spacecraft ID Received. Received: {} | Deframer configured with: {}" + + @ Deframing received an invalid frame length + event InvalidFrameLength(transmitted: U16, actual: U32) \ + severity warning high \ + format "Not enough data received. Header length specified: {} | Received data length: {}" + + @ Deframing received an invalid VCID + event InvalidVcId(transmitted: U16, configured: U16) \ + severity activity low \ + format "Invalid Virtual Channel ID Received. Header token specified: {} | Deframer configured with: {}" + + @ Deframing received an invalid checksum + event InvalidCrc(transmitted: U16, computed: U16) \ + severity warning high \ + format "Invalid checksum received. Trailer specified: {} | Computed on board: {}" + + @ Deframing received an unexpected sequence number + event UnexpectedSequenceNumber(transmitted: U16, expected: U16) \ severity warning high \ - format "Invalid Header Field Received. Field {} | Expected: {} | Received: {}" + format "Invalid sequence number received. Frames may have been lost. Transmitted: {} | Expected on board: {}" ############################################################################### # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.hpp b/Svc/CCSDS/TCDeframer/TCDeframer.hpp index 50bbac42fd7..5385ae79211 100644 --- a/Svc/CCSDS/TCDeframer/TCDeframer.hpp +++ b/Svc/CCSDS/TCDeframer/TCDeframer.hpp @@ -12,6 +12,8 @@ namespace Svc { namespace CCSDS { class TCDeframer : public TCDeframerComponentBase { + friend class TCDeframerTester; + public: // ---------------------------------------------------------------------- // Component construction and destruction @@ -24,6 +26,22 @@ class TCDeframer : public TCDeframerComponentBase { //! Destroy TCDeframer object ~TCDeframer(); + //! \brief Configure the TCDeframer to deframe only a specific VCID and spacecraft ID + //! + //! By default, the TCDeframer is configured with the spacecraft ID set in the config/ComCfg.fpp file, + //! and deframes all incoming frames regardless of their VCID. Should project instantiate a TCDeframer + //! with a different configuration, they can use this configure method to set the desired properties. + //! + //! \param vcId The virtual channel ID to accept (if acceptAllVcid is false) + //! \param spacecraftId The spacecraft ID to accept + //! \param acceptAllVcid If true, the deframer will accept all VCIDs. If false, it will only accept configured vcId + //! + void configure(U16 vcId, U16 spacecraftId, bool acceptAllVcid) { + this->m_vcId = vcId; + this->m_spacecraftId = spacecraftId; + this->m_acceptAllVcid = acceptAllVcid; + } + private: // ---------------------------------------------------------------------- // Handler implementations for user-defined typed input ports @@ -42,6 +60,12 @@ class TCDeframer : public TCDeframerComponentBase { void dataReturnIn_handler(FwIndexType portNum, //!< The port number Fw::Buffer& data, //!< The buffer const ComCfg::FrameContext& context) override; + + private: + U16 m_vcId; //!< The virtual channel ID this deframer is configured to handle + U16 m_spacecraftId; //!< The spacecraft ID this deframer is configured to handle + bool m_acceptAllVcid = true; //!< Flag to accept all VCIDs + U8 m_sequenceCount = 0; //! Counter tracking the next expected frame count }; } // namespace CCSDS } // namespace Svc diff --git a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTestMain.cpp b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTestMain.cpp new file mode 100644 index 00000000000..ef47a68061a --- /dev/null +++ b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTestMain.cpp @@ -0,0 +1,33 @@ +// ====================================================================== +// \title TCDeframerTestMain.cpp +// \author thomas-bc +// \brief cpp file for TCDeframer component test main function +// ====================================================================== + +#include "TCDeframerTester.hpp" + +TEST(TCDeframer, testDataReturn) { + Svc::CCSDS::TCDeframerTester tester; + tester.testDataReturn(); +} + +TEST(TCDeframer, testNominalDeframing) { + Svc::CCSDS::TCDeframerTester tester; + tester.testNominalDeframing(); +} + +TEST(TCDeframer, testInvalidScId) { + Svc::CCSDS::TCDeframerTester tester; + tester.testInvalidScId(); +} + +TEST(TCDeframer, testInvalidVcId) { + Svc::CCSDS::TCDeframerTester tester; + tester.testInvalidVcId(); +} + + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp new file mode 100644 index 00000000000..9ff6b7757aa --- /dev/null +++ b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp @@ -0,0 +1,140 @@ +// ====================================================================== +// \title TCDeframerTester.cpp +// \author chammard +// \brief cpp file for TCDeframer component test harness implementation class +// ====================================================================== + +#include "TCDeframerTester.hpp" +#include "STest/Random/Random.hpp" +#include "Svc/CCSDS/Utils/CRC16.hpp" +#include "Svc/CCSDS/Types/TCFrameHeaderSerializableAc.hpp" +#include "Svc/CCSDS/Types/TCFrameTrailerSerializableAc.hpp" + +namespace Svc { + +namespace CCSDS { + +// ---------------------------------------------------------------------- +// Construction and destruction +// ---------------------------------------------------------------------- + +TCDeframerTester ::TCDeframerTester() + : TCDeframerGTestBase("TCDeframerTester", TCDeframerTester::MAX_HISTORY_SIZE), component("TCDeframer") { + this->initComponents(); + this->connectPorts(); +} + +TCDeframerTester ::~TCDeframerTester() {} + +// ---------------------------------------------------------------------- +// Tests +// ---------------------------------------------------------------------- + +void TCDeframerTester::testDataReturn() { + U8 data[1]; + Fw::Buffer buffer(data, sizeof(data)); + ComCfg::FrameContext nullContext; + this->invoke_to_dataReturnIn(0, buffer, nullContext); + ASSERT_from_dataReturnOut_SIZE(1); // incoming buffer should be deallocated + ASSERT_EQ(this->fromPortHistory_dataReturnOut->at(0).data.getData(), data); + ASSERT_EQ(this->fromPortHistory_dataReturnOut->at(0).data.getSize(), sizeof(data)); + ASSERT_EQ(this->fromPortHistory_dataReturnOut->at(0).context, nullContext); +} + +void TCDeframerTester::testNominalDeframing() { + // Frame: 5 bytes (header) + 1 byte (data) + 2 bytes (trailer) + U16 scId = static_cast(STest::Random::lowerUpper(0, 0x3FF)); // random 10 bit Spacecraft ID + U8 vcId = static_cast(STest::Random::lowerUpper(0, 0x3F)); // random 6 bit virtual channel ID + U8 seqCount = static_cast(STest::Random::lowerUpper(0, 0xFF)); // random 8 bit sequence count + U8 dataLength = static_cast(STest::Random::lowerUpper(1, 200)); // bytes of data, random length + U8 data[dataLength]; + + Fw::Buffer buffer = this->assembleFrameBuffer(data, dataLength, scId, vcId, seqCount); + ComCfg::FrameContext nullContext; + + this->setComponentState(scId, vcId, seqCount); + this->invoke_to_dataIn(0, buffer, nullContext); + + ASSERT_from_dataOut_SIZE(1); + Fw::Buffer outBuffer = this->fromPortHistory_dataOut->at(0).data; + ASSERT_EQ(outBuffer.getSize(), dataLength); + for (FwIndexType i = 0; i < dataLength; i++) { + ASSERT_EQ(outBuffer.getData()[i], data[i]); + } +} + +void TCDeframerTester::testInvalidScId() { + // Frame: 5 bytes (header) + 1 byte (data) + 2 bytes (trailer) + U16 scId = static_cast(STest::Random::lowerUpper(1, 0x3FF)); // random 10 bit Spacecraft ID + U8 dataLength = static_cast(STest::Random::lowerUpper(1, 200)); // bytes of data, random length + U8 data[dataLength]; + + // Assemble frame with incorrect scId value + Fw::Buffer buffer = this->assembleFrameBuffer(data, dataLength, scId - 1); + ComCfg::FrameContext nullContext; + + this->setComponentState(scId); + this->invoke_to_dataIn(0, buffer, nullContext); + + ASSERT_from_dataOut_SIZE(0); + ASSERT_from_dataReturnOut_SIZE(1); // invalid buffer was deallocated + ASSERT_EQ(this->fromPortHistory_dataReturnOut->at(0).data.getData(), buffer.getData()); + ASSERT_EQ(this->fromPortHistory_dataReturnOut->at(0).data.getSize(), buffer.getSize()); + ASSERT_EVENTS_SIZE(1); // exactly 1 event emitted + ASSERT_EVENTS_InvalidSpacecraftId_SIZE(1); // event was emitted for invalid spacecraft ID + ASSERT_EVENTS_InvalidSpacecraftId(0, scId - 1, scId); // event was emitted for invalid spacecraft ID +} + + +void TCDeframerTester::testInvalidVcId() { + U8 vcId = static_cast(STest::Random::lowerUpper(1, 0x3F)); // random 6 bit VCID + U8 dataLength = static_cast(STest::Random::lowerUpper(1, 200)); // bytes of data, random length + U8 data[dataLength]; + + // Assemble frame with incorrect vcId value + Fw::Buffer buffer = this->assembleFrameBuffer(data, dataLength, 0, vcId - 1); + ComCfg::FrameContext nullContext; + + this->setComponentState(0, vcId, 0, false); // set the component in mode where only one VCID is accepted + this->invoke_to_dataIn(0, buffer, nullContext); + + ASSERT_from_dataOut_SIZE(0); + ASSERT_from_dataReturnOut_SIZE(1); // invalid buffer was deallocated + ASSERT_EQ(this->fromPortHistory_dataReturnOut->at(0).data.getData(), buffer.getData()); + ASSERT_EQ(this->fromPortHistory_dataReturnOut->at(0).data.getSize(), buffer.getSize()); + ASSERT_EVENTS_SIZE(1); // exactly 1 event emitted + ASSERT_EVENTS_InvalidVcId_SIZE(1); // event was emitted for invalid VCID + ASSERT_EVENTS_InvalidVcId(0, vcId - 1, vcId); // event was emitted for invalid VCID +} + +void TCDeframerTester::setComponentState(U16 scid, U8 vcid, U8 sequenceNumber, bool acceptAllVcid) { + this->component.m_spacecraftId = scid; + this->component.m_vcId = vcid; + this->component.m_sequenceCount = sequenceNumber; + this->component.m_acceptAllVcid = acceptAllVcid; +} + +Fw::Buffer TCDeframerTester::assembleFrameBuffer(U8* data, U8 dataLength, U16 scid, U8 vcid, U8 seqNumber){ + ::memset(this->m_frameData, 0, sizeof(this->m_frameData)); + U16 frameLength = TCFrameHeader::SERIALIZED_SIZE + dataLength + TCFrameTrailer::SERIALIZED_SIZE; + + // Header + this->m_frameData[0] = scid >> 8; + this->m_frameData[1] = scid & 0xFF; + this->m_frameData[2] = static_cast((vcid << 2) | static_cast((dataLength >> 8) & 0x03)); + this->m_frameData[3] = dataLength & 0xFF; + this->m_frameData[4] = seqNumber; + + // Data + memcpy(&this->m_frameData[TCFrameHeader::SERIALIZED_SIZE], data, dataLength); + + // CRC trailer + U16 crc = CCSDS::Utils::CRC16::compute(this->m_frameData, TCFrameHeader::SERIALIZED_SIZE + dataLength); + this->m_frameData[TCFrameHeader::SERIALIZED_SIZE + dataLength] = crc >> 8; + this->m_frameData[TCFrameHeader::SERIALIZED_SIZE + dataLength + 1] = crc & 0xFF; + + return Fw::Buffer(this->m_frameData, frameLength); +} + +} // namespace CCSDS +} // namespace Svc diff --git a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.hpp b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.hpp new file mode 100644 index 00000000000..3bc7b83ac86 --- /dev/null +++ b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.hpp @@ -0,0 +1,83 @@ +// ====================================================================== +// \title TCDeframerTester.hpp +// \author chammard +// \brief hpp file for TCDeframer component test harness implementation class +// ====================================================================== + +#ifndef Svc_CCSDS_TCDeframerTester_HPP +#define Svc_CCSDS_TCDeframerTester_HPP + +#include "Svc/CCSDS/TCDeframer/TCDeframer.hpp" +#include "Svc/CCSDS/TCDeframer/TCDeframerGTestBase.hpp" + +namespace Svc { + +namespace CCSDS { + +class TCDeframerTester final : public TCDeframerGTestBase { + public: + // ---------------------------------------------------------------------- + // Constants + // ---------------------------------------------------------------------- + + // Maximum size of histories storing events, telemetry, and port outputs + static const FwSizeType MAX_HISTORY_SIZE = 10; + + // Instance ID supplied to the component instance under test + static const FwEnumStoreType TEST_INSTANCE_ID = 0; + + public: + // ---------------------------------------------------------------------- + // Construction and destruction + // ---------------------------------------------------------------------- + + //! Construct object TCDeframerTester + TCDeframerTester(); + + //! Destroy object TCDeframerTester + ~TCDeframerTester(); + + public: + // ---------------------------------------------------------------------- + // Tests + // ---------------------------------------------------------------------- + + //! Test Data Return handler + void testDataReturn(); + void testNominalDeframing(); + void testInvalidScId(); + void testInvalidVcId(); + + + private: + // ---------------------------------------------------------------------- + // Helper functions + // ---------------------------------------------------------------------- + + //! Connect ports + void connectPorts(); + + //! Initialize components + void initComponents(); + + //! Sets the component state to specific values, helpful for testing + void setComponentState(U16 scid = 0, U8 vcid = 0, U8 seqNumber = 0, bool acceptAllVcid = true); + + Fw::Buffer assembleFrameBuffer(U8* data, U8 dataLength, U16 scid = 0, U8 vcid = 0, U8 seqNumber = 0); + + private: + // ---------------------------------------------------------------------- + // Member variables + // ---------------------------------------------------------------------- + + //! The component under test + TCDeframer component; + + U8 m_frameData[300]; // data buffer used to produce test frames +}; + +} // namespace CCSDS + +} // namespace Svc + +#endif diff --git a/Svc/CCSDS/Types/Types.fpp b/Svc/CCSDS/Types/Types.fpp index b913b38f8fd..005b586b257 100644 --- a/Svc/CCSDS/Types/Types.fpp +++ b/Svc/CCSDS/Types/Types.fpp @@ -1,9 +1,8 @@ module Svc { module CCSDS { -module Types { # ------------------------------------------------ - # Frame header types + # Frame header and trailer types # ------------------------------------------------ # Note: FPP does not currently support bit fields, so these structs may contain fields # that are compoed of multiple bitfields. One should mask the individual FPP types @@ -71,6 +70,6 @@ module Types { -} + } } diff --git a/default/config/ComCfg.fpp b/default/config/ComCfg.fpp index d8fe9433635..31d853e7b2b 100644 --- a/default/config/ComCfg.fpp +++ b/default/config/ComCfg.fpp @@ -9,7 +9,6 @@ module ComCfg { constant SpacecraftId = 0x03FF # Spacecraft ID (10 bits) - constant VcId = 0x001 # Virtual Channel ID (3 bits) constant TmFrameFixedSize = 1024 # Needs to be at least COM_BUFFER_MAX_SIZE + (2 * SpacePacketHeaderSize) + 1 @ APIDs are 11 bits in the Space Packet protocol, so we use U16. Max value 7FF From 58259034af80195e9bbe26526a46224e23776fbc Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Tue, 20 May 2025 12:50:43 -0700 Subject: [PATCH 33/95] Update type usage namespacing --- .../SpacePacketDeframer.cpp | 8 ++++---- .../SpacePacketFramer/SpacePacketFramer.cpp | 10 +++++----- Svc/CCSDS/TMFramer/TMFramer.cpp | 17 ++++++++-------- .../FrameDetector/CcsdsTCFrameDetector.cpp | 20 +++++++++---------- 4 files changed, 28 insertions(+), 27 deletions(-) diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp index 3b2401cd8e3..410c1890902 100644 --- a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp @@ -40,13 +40,13 @@ void SpacePacketDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, // 16b - n/a - Packet Data Length // ################################ - FW_ASSERT(data.getSize() >= Svc::CCSDS::Types::SpacePacketHeader::SERIALIZED_SIZE, static_cast(data.getSize())); + FW_ASSERT(data.getSize() >= SpacePacketHeader::SERIALIZED_SIZE, static_cast(data.getSize())); - CCSDS::Types::SpacePacketHeader header; + SpacePacketHeader header; Fw::SerializeStatus status = data.getDeserializer().deserialize(header); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); - U16 apid = header.getpacketIdentification() & CCSDS::Types::SpacePacketMasks::ApidMask; + U16 apid = header.getpacketIdentification() & SpacePacketMasks::ApidMask; ComCfg::FrameContext contextCopy = context; contextCopy.setapid(static_cast(apid)); @@ -54,7 +54,7 @@ void SpacePacketDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, U16 pkt_length = header.getpacketDataLength(); // Set data buffer to be of the encapsulated data: HEADER (6 bytes) | PACKET DATA - data.setData(data.getData() + Svc::CCSDS::Types::SpacePacketHeader::SERIALIZED_SIZE); + data.setData(data.getData() + SpacePacketHeader::SERIALIZED_SIZE); data.setSize(pkt_length); this->dataOut_out(0, data, contextCopy); diff --git a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp index d8f40f3bf81..44fd4fa92ce 100644 --- a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp +++ b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp @@ -25,9 +25,9 @@ SpacePacketFramer ::~SpacePacketFramer() {} // ---------------------------------------------------------------------- void SpacePacketFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { - CCSDS::Types::SpacePacketHeader header; + SpacePacketHeader header; Fw::SerializeStatus status; - FwSizeType frameSize = CCSDS::Types::SpacePacketHeader::SERIALIZED_SIZE + data.getSize(); + FwSizeType frameSize = SpacePacketHeader::SERIALIZED_SIZE + data.getSize(); FW_ASSERT(data.getSize() <= std::numeric_limits::max(), static_cast(frameSize)); FW_ASSERT(frameSize <= std::numeric_limits::max(), static_cast(frameSize)); @@ -42,12 +42,12 @@ void SpacePacketFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, c // PVN is always 0 per Standard - Packet Type is 0 for Telemetry (downlink) - SecHdr flag is 0 for no secondary header U16 packetIdentification = 0; ComCfg::APID::T apid = context.getapid(); - packetIdentification |= static_cast(apid) & CCSDS::Types::SpacePacketMasks::ApidMask; // 11 bit APID + packetIdentification |= static_cast(apid) & SpacePacketMasks::ApidMask; // 11 bit APID U16 packetSequenceControl = 0; - packetSequenceControl |= 0x3 << CCSDS::Types::SpacePacketMasks::SeqFlagsOffset; // Sequence Flags 0b11 = unsegmented User Data + packetSequenceControl |= 0x3 << SpacePacketMasks::SeqFlagsOffset; // Sequence Flags 0b11 = unsegmented User Data U16 sequenceCount = context.getsequenceCount(); - packetSequenceControl |= sequenceCount & CCSDS::Types::SpacePacketMasks::SeqCountMask; // 14 bit sequence count + packetSequenceControl |= sequenceCount & SpacePacketMasks::SeqCountMask; // 14 bit sequence count FW_ASSERT(data.getSize() <= std::numeric_limits::max(), static_cast(data.getSize())); U16 packetDataLength = static_cast(data.getSize() - 1); // Standard specifies length is number of bytes minus 1 diff --git a/Svc/CCSDS/TMFramer/TMFramer.cpp b/Svc/CCSDS/TMFramer/TMFramer.cpp index 42a834618c4..3074b957da5 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.cpp +++ b/Svc/CCSDS/TMFramer/TMFramer.cpp @@ -39,17 +39,18 @@ void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComC // ----------------------------------------------- // Header // ----------------------------------------------- - CCSDS::Types::TMFrameHeader header; + TMFrameHeader header; U16 channelIds = 0; - channelIds |= ComCfg::FppConstant_SpacecraftId::SpacecraftId << CCSDS::Types::TMFrameMasks::spacecraftIdOffset; - channelIds |= ComCfg::FppConstant_VcId::VcId << CCSDS::Types::TMFrameMasks::virtualChannelIdOffset; + channelIds |= ComCfg::FppConstant_SpacecraftId::SpacecraftId << TMFrameMasks::spacecraftIdOffset; + U8 vcId = 1; + channelIds |= vcId << TMFrameMasks::virtualChannelIdOffset; channelIds |= 0x0; // No Operational Control Field: Flag set to 0 // Data Field Status: // - all flags to 0 except segment length id 0b11 per standard // - First Header Pointer is always 0 since we are always wrapping a single entire packet at offset 0 U16 dataFieldStatus = 0; - dataFieldStatus |= 0x3 << CCSDS::Types::TMFrameMasks::segLengthOffset; // Seg Length 0b11 per Standard + dataFieldStatus |= 0x3 << TMFrameMasks::segLengthOffset; // Seg Length 0b11 per Standard // TODO: could virtual channel be passed in context or use portNum and a mapping ?? header.setchannelIds(channelIds); @@ -83,14 +84,14 @@ void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComC // ------------------------------------------------- // Trailer: Compute CRC // ------------------------------------------------- - CCSDS::Types::TMFrameTrailer trailer; + TMFrameTrailer trailer; // Compute CRC over the entire frame buffer minus the FECF trailer U16 crc = CCSDS::Utils::CRC16::compute(frameBuffer.getData(), - sizeof(this->m_frameBuffer) - CCSDS::Types::TMFrameTrailer::SERIALIZED_SIZE); + sizeof(this->m_frameBuffer) - TMFrameTrailer::SERIALIZED_SIZE); trailer.setfecf(crc); // Frame Error Control Field // Move the serializer pointer to the end of the location where the trailer will be serialized frameSerializer.moveSerToOffset(ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize - - CCSDS::Types::TMFrameTrailer::SERIALIZED_SIZE); + TMFrameTrailer::SERIALIZED_SIZE); status = frameSerializer.serialize(trailer); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); @@ -114,7 +115,7 @@ void TMFramer ::dataReturnIn_handler(FwIndexType portNum, void TMFramer ::fill_with_idle_packet(U16 startIndex) { // TODO: make this code cleaner U16 endIndex = ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize - - CCSDS::Types::TMFrameTrailer::SERIALIZED_SIZE; + TMFrameTrailer::SERIALIZED_SIZE; U16 idlePacketLength = endIndex - startIndex; FW_ASSERT(idlePacketLength > 0, static_cast(idlePacketLength)); FW_ASSERT(idlePacketLength >= 7, static_cast(idlePacketLength)); // 7 bytes minimum for idle packet diff --git a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp index 230a1e8dce3..9cf144311b6 100644 --- a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp +++ b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp @@ -17,29 +17,29 @@ namespace FrameDetectors { FrameDetector::Status CcsdsTCFrameDetector::detect(const Types::CircularBuffer& data, FwSizeType& size_out) const { - if (data.get_allocated_size() < CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE) { - size_out = CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE; + if (data.get_allocated_size() < CCSDS::TCFrameHeader::SERIALIZED_SIZE) { + size_out = CCSDS::TCFrameHeader::SERIALIZED_SIZE; return Status::MORE_DATA_NEEDED; } // Copy CircularBuffer data into linear buffer, for serialization into FrameHeader object - U8 header_data[CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE]; - Fw::SerializeStatus status = data.peek(header_data, CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE, 0); + U8 header_data[CCSDS::TCFrameHeader::SERIALIZED_SIZE]; + Fw::SerializeStatus status = data.peek(header_data, CCSDS::TCFrameHeader::SERIALIZED_SIZE, 0); if (status != Fw::FW_SERIALIZE_OK) { return Status::NO_FRAME_DETECTED; } - CCSDS::Types::TCFrameHeader header; - Fw::ExternalSerializeBuffer header_ser_buffer(header_data, CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE); - status = header_ser_buffer.setBuffLen(CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE); + CCSDS::TCFrameHeader header; + Fw::ExternalSerializeBuffer header_ser_buffer(header_data, CCSDS::TCFrameHeader::SERIALIZED_SIZE); + status = header_ser_buffer.setBuffLen(CCSDS::TCFrameHeader::SERIALIZED_SIZE); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, static_cast(status)); // Attempt to deserialize data into the FrameHeader object status = header.deserialize(header_ser_buffer); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); - U16 sc_id = header.getflagsAndScId() & CCSDS::Types::TCFrameMasks::SpacecraftIdMask; - U16 frame_length = header.getvcIdAndLength() & CCSDS::Types::TCFrameMasks::FrameLengthMask; + U16 sc_id = header.getflagsAndScId() & CCSDS::TCFrameMasks::SpacecraftIdMask; + U16 frame_length = header.getvcIdAndLength() & CCSDS::TCFrameMasks::FrameLengthMask; - FwSizeType expected_frame_size = CCSDS::Types::TCFrameHeader::SERIALIZED_SIZE + frame_length + CCSDS::Types::TCFrameTrailer::SERIALIZED_SIZE; // 2 bytes for CRC + FwSizeType expected_frame_size = CCSDS::TCFrameHeader::SERIALIZED_SIZE + frame_length + CCSDS::TCFrameTrailer::SERIALIZED_SIZE; // 2 bytes for CRC if (sc_id == ComCfg::FppConstant_SpacecraftId::SpacecraftId) { size_out = expected_frame_size; if (data.get_allocated_size() < expected_frame_size) { From 930081249b4c964db440eed6aec1e3a66d6f585f Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Tue, 20 May 2025 13:53:53 -0700 Subject: [PATCH 34/95] Finish TCDeframer UTs --- Svc/CCSDS/TCDeframer/TCDeframer.cpp | 1 - .../TCDeframer/test/ut/TCDeframerTestMain.cpp | 14 ++++ .../TCDeframer/test/ut/TCDeframerTester.cpp | 64 +++++++++++++++++++ .../TCDeframer/test/ut/TCDeframerTester.hpp | 4 +- 4 files changed, 81 insertions(+), 2 deletions(-) diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.cpp b/Svc/CCSDS/TCDeframer/TCDeframer.cpp index e869229a7d9..3851dcf617d 100644 --- a/Svc/CCSDS/TCDeframer/TCDeframer.cpp +++ b/Svc/CCSDS/TCDeframer/TCDeframer.cpp @@ -80,7 +80,6 @@ void TCDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const Co } this->m_sequenceCount++; // increment count for next frame - // ------------------------------------------------- // CRC Check // ------------------------------------------------- diff --git a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTestMain.cpp b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTestMain.cpp index ef47a68061a..52dc06f7612 100644 --- a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTestMain.cpp +++ b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTestMain.cpp @@ -26,6 +26,20 @@ TEST(TCDeframer, testInvalidVcId) { tester.testInvalidVcId(); } +TEST(TCDeframer, testInvalidLengthToken) { + Svc::CCSDS::TCDeframerTester tester; + tester.testInvalidLengthToken(); +} + +TEST(TCDeframer, testInvalidSequenceNumber) { + Svc::CCSDS::TCDeframerTester tester; + tester.testInvalidSequenceNumber(); +} + +TEST(TCDeframer, testInvalidCrc) { + Svc::CCSDS::TCDeframerTester tester; + tester.testInvalidCrc(); +} int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); diff --git a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp index 9ff6b7757aa..b4ae2253710 100644 --- a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp +++ b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp @@ -107,6 +107,70 @@ void TCDeframerTester::testInvalidVcId() { ASSERT_EVENTS_InvalidVcId(0, vcId - 1, vcId); // event was emitted for invalid VCID } +void TCDeframerTester::testInvalidLengthToken() { + U8 dataLength = static_cast(STest::Random::lowerUpper(1, 200)); // bytes of data, random length + U8 data[dataLength]; + U8 fakeLength = 255; // more than max dataLength value + + Fw::Buffer buffer = this->assembleFrameBuffer(data, dataLength); + buffer.getData()[3] = fakeLength; // Override length token to invalid value + ComCfg::FrameContext nullContext; + + this->setComponentState(); + this->invoke_to_dataIn(0, buffer, nullContext); + + ASSERT_from_dataOut_SIZE(0); + ASSERT_from_dataReturnOut_SIZE(1); // invalid buffer was deallocated + ASSERT_EQ(this->fromPortHistory_dataReturnOut->at(0).data.getData(), buffer.getData()); + ASSERT_EQ(this->fromPortHistory_dataReturnOut->at(0).data.getSize(), buffer.getSize()); + ASSERT_EVENTS_SIZE(1); // exactly 1 event emitted + ASSERT_EVENTS_InvalidFrameLength_SIZE(1); // event was emitted for invalid frame length + ASSERT_EVENTS_InvalidFrameLength(0, fakeLength, dataLength); +} + +void TCDeframerTester::testInvalidSequenceNumber() { + U8 dataLength = static_cast(STest::Random::lowerUpper(1, 200)); // bytes of data, random length + U8 data[dataLength]; + U8 expectedSeqCount = static_cast(STest::Random::lowerUpper(1, 0xFF)); // random 8 bit sequence count + U8 invalidSeqCount = expectedSeqCount - 1; // invalid sequence count + + Fw::Buffer buffer = this->assembleFrameBuffer(data, dataLength, 0, 0, invalidSeqCount); + ComCfg::FrameContext nullContext; + + this->setComponentState(0, 0, expectedSeqCount); + this->invoke_to_dataIn(0, buffer, nullContext); + + // Invalid sequence number should emit a warning but deframe data (not dropping the frame) + ASSERT_from_dataOut_SIZE(1); + ASSERT_from_dataReturnOut_SIZE(0); + ASSERT_EQ(this->fromPortHistory_dataOut->at(0).data.getData(), buffer.getData()); + ASSERT_EQ(this->fromPortHistory_dataOut->at(0).data.getSize(), dataLength); + ASSERT_EVENTS_SIZE(1); // exactly 1 event emitted + ASSERT_EVENTS_UnexpectedSequenceNumber_SIZE(1); + ASSERT_EVENTS_UnexpectedSequenceNumber(0, invalidSeqCount, expectedSeqCount); +} + +void TCDeframerTester::testInvalidCrc() { + U8 dataLength = static_cast(STest::Random::lowerUpper(1, 200)); // bytes of data, random length + U8 data[dataLength]; + + Fw::Buffer buffer = this->assembleFrameBuffer(data, dataLength); + // Override CRC to invalid value + buffer.getData()[TCFrameHeader::SERIALIZED_SIZE + dataLength + 1] = 0x00; + ComCfg::FrameContext nullContext; + + this->setComponentState(); + this->invoke_to_dataIn(0, buffer, nullContext); + + // Invalid CRC drops the frame + ASSERT_from_dataOut_SIZE(0); + ASSERT_from_dataReturnOut_SIZE(1); + ASSERT_EQ(this->fromPortHistory_dataReturnOut->at(0).data.getData(), buffer.getData()); + ASSERT_EQ(this->fromPortHistory_dataReturnOut->at(0).data.getSize(), buffer.getSize()); + ASSERT_EVENTS_SIZE(1); // exactly 1 event emitted + ASSERT_EVENTS_InvalidCrc_SIZE(1); +} + void TCDeframerTester::setComponentState(U16 scid, U8 vcid, U8 sequenceNumber, bool acceptAllVcid) { this->component.m_spacecraftId = scid; this->component.m_vcId = vcid; diff --git a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.hpp b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.hpp index 3bc7b83ac86..25320aea54f 100644 --- a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.hpp +++ b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.hpp @@ -42,11 +42,13 @@ class TCDeframerTester final : public TCDeframerGTestBase { // Tests // ---------------------------------------------------------------------- - //! Test Data Return handler void testDataReturn(); void testNominalDeframing(); void testInvalidScId(); void testInvalidVcId(); + void testInvalidLengthToken(); + void testInvalidSequenceNumber(); + void testInvalidCrc(); private: From 01880eaccc6b9e96629830487e8fca22c3a4f0fa Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Tue, 20 May 2025 18:39:41 -0700 Subject: [PATCH 35/95] Add TMFramer tests and refine VcId handling --- Svc/CCSDS/TMFramer/CMakeLists.txt | 13 ++ Svc/CCSDS/TMFramer/TMFramer.cpp | 31 ++--- Svc/CCSDS/TMFramer/TMFramer.hpp | 6 + .../TMFramer/test/ut/TMFramerTestMain.cpp | 27 ++++ Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp | 131 ++++++++++++++++++ Svc/CCSDS/TMFramer/test/ut/TMFramerTester.hpp | 78 +++++++++++ Svc/CCSDS/Types/Types.fpp | 3 +- default/config/ComCfg.fpp | 2 + 8 files changed, 271 insertions(+), 20 deletions(-) create mode 100644 Svc/CCSDS/TMFramer/test/ut/TMFramerTestMain.cpp create mode 100644 Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp create mode 100644 Svc/CCSDS/TMFramer/test/ut/TMFramerTester.hpp diff --git a/Svc/CCSDS/TMFramer/CMakeLists.txt b/Svc/CCSDS/TMFramer/CMakeLists.txt index bf91e7e6f26..ec98423a4ea 100644 --- a/Svc/CCSDS/TMFramer/CMakeLists.txt +++ b/Svc/CCSDS/TMFramer/CMakeLists.txt @@ -18,3 +18,16 @@ register_fprime_library( DEPENDS Svc_CCSDS_Types ) + +set(UT_AUTO_HELPERS ON) + +register_fprime_ut( + SOURCES + "${CMAKE_CURRENT_LIST_DIR}/test/ut/TMFramerTestMain.cpp" + "${CMAKE_CURRENT_LIST_DIR}/test/ut/TMFramerTester.cpp" + AUTOCODER_INPUTS + "${CMAKE_CURRENT_LIST_DIR}/TMFramer.fpp" + DEPENDS + Svc_CCSDS_Types + STest +) \ No newline at end of file diff --git a/Svc/CCSDS/TMFramer/TMFramer.cpp b/Svc/CCSDS/TMFramer/TMFramer.cpp index 3074b957da5..6bf5f04f407 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.cpp +++ b/Svc/CCSDS/TMFramer/TMFramer.cpp @@ -29,9 +29,6 @@ TMFramer ::~TMFramer() {} // ---------------------------------------------------------------------- void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { - // TODO: VcId should likely be passed in the context by the caller, rather than retrieved here - // This matches the VCP.request Service Primitive better - // TODO: make this an event probably FW_ASSERT(data.getSize() <= ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize, static_cast(data.getSize())); @@ -40,11 +37,11 @@ void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComC // Header // ----------------------------------------------- TMFrameHeader header; - U16 channelIds = 0; - channelIds |= ComCfg::FppConstant_SpacecraftId::SpacecraftId << TMFrameMasks::spacecraftIdOffset; - U8 vcId = 1; - channelIds |= vcId << TMFrameMasks::virtualChannelIdOffset; - channelIds |= 0x0; // No Operational Control Field: Flag set to 0 + + U16 globalVcId = 0; + globalVcId |= ComCfg::FppConstant_SpacecraftId::SpacecraftId << TMFrameMasks::spacecraftIdOffset; + globalVcId |= context.getvcId() << TMFrameMasks::virtualChannelIdOffset; + globalVcId |= 0x0; // Operational Control Field: Flag set to 0 // Data Field Status: // - all flags to 0 except segment length id 0b11 per standard @@ -52,8 +49,7 @@ void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComC U16 dataFieldStatus = 0; dataFieldStatus |= 0x3 << TMFrameMasks::segLengthOffset; // Seg Length 0b11 per Standard - // TODO: could virtual channel be passed in context or use portNum and a mapping ?? - header.setchannelIds(channelIds); + header.setglobalVcId(globalVcId); header.setmasterFrameCount(this->m_masterFrameCount); header.setvirtualFrameCount(this->m_virtualFrameCount); header.setdataFieldStatus(dataFieldStatus); @@ -63,7 +59,7 @@ void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComC this->m_virtualFrameCount++; // U8 intended to wrap around (modulo 256) // ------------------------------------------------- - // Serialize the Frame + // Data field // ------------------------------------------------- Fw::SerializeStatus status; @@ -76,19 +72,17 @@ void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComC status = frameSerializer.serialize(data.getData(), data.getSize(), Fw::Serialization::OMIT_LENGTH); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); - // TODO: fill with Idle Packets - FW_ASSERT(frameSerializer.getBuffLength() <= std::numeric_limits::max(), - static_cast(frameSerializer.getBuffLength())); this->fill_with_idle_packet(static_cast(frameSerializer.getBuffLength())); // ------------------------------------------------- - // Trailer: Compute CRC + // Trailer (CRC) // ------------------------------------------------- TMFrameTrailer trailer; // Compute CRC over the entire frame buffer minus the FECF trailer U16 crc = CCSDS::Utils::CRC16::compute(frameBuffer.getData(), sizeof(this->m_frameBuffer) - TMFrameTrailer::SERIALIZED_SIZE); - trailer.setfecf(crc); // Frame Error Control Field + // Set the Frame Error Control Field (FECF) + trailer.setfecf(crc); // Move the serializer pointer to the end of the location where the trailer will be serialized frameSerializer.moveSerToOffset(ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize - TMFrameTrailer::SERIALIZED_SIZE); @@ -110,10 +104,11 @@ void TMFramer ::dataReturnIn_handler(FwIndexType portNum, const ComCfg::FrameContext& context) { // dataReturnIn is our own member buffer coming back from the dataOut call - memset it to 0 ::memset(this->m_frameBuffer, 0, sizeof(this->m_frameBuffer)); + // NOTE: should I set a flag to track that it has been returned an ready for reuse? } void TMFramer ::fill_with_idle_packet(U16 startIndex) { - // TODO: make this code cleaner + // TODO: make this code cleaner - could request from SpacePacket ?? U16 endIndex = ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize - TMFrameTrailer::SERIALIZED_SIZE; U16 idlePacketLength = endIndex - startIndex; @@ -130,7 +125,7 @@ void TMFramer ::fill_with_idle_packet(U16 startIndex) { this->m_frameBuffer[startIndex + 5] = idlePacketLength & 0xFF; // Packet Data Length LSB // Fill the rest of the buffer with arbitrary idle data for (U16 i = startIndex + 6; i < endIndex; i++) { - this->m_frameBuffer[i] = 0x44; // Idle data + this->m_frameBuffer[i] = IDLE_DATA_PATTERN; // Idle data } } diff --git a/Svc/CCSDS/TMFramer/TMFramer.hpp b/Svc/CCSDS/TMFramer/TMFramer.hpp index f7d755728cc..2991b37560e 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.hpp +++ b/Svc/CCSDS/TMFramer/TMFramer.hpp @@ -14,6 +14,10 @@ namespace Svc { namespace CCSDS { class TMFramer final : public TMFramerComponentBase { + friend class TMFramerTester; + + static constexpr U8 IDLE_DATA_PATTERN = 0x44; + public: // ---------------------------------------------------------------------- // Component construction and destruction @@ -45,6 +49,8 @@ class TMFramer final : public TMFramerComponentBase { //! This is essentially the CCSDS TM VCP.request Service Primitive, with //! Packet=data and GVCID implicitly passed in context (TM Protocol 3.3.3.2) //! + //! TODO: mention context values that are being used + //! void dataIn_handler(FwIndexType portNum, //!< The port number Fw::Buffer& data, const ComCfg::FrameContext& context) override; diff --git a/Svc/CCSDS/TMFramer/test/ut/TMFramerTestMain.cpp b/Svc/CCSDS/TMFramer/test/ut/TMFramerTestMain.cpp new file mode 100644 index 00000000000..ee5c8dffe2d --- /dev/null +++ b/Svc/CCSDS/TMFramer/test/ut/TMFramerTestMain.cpp @@ -0,0 +1,27 @@ +// ====================================================================== +// \title TMFramerTestMain.cpp +// \author chammard +// \brief cpp file for TMFramer component test main function +// ====================================================================== + +#include "TMFramerTester.hpp" + +TEST(Nominal, testComStatusPassthrough) { + Svc::CCSDS::TMFramerTester tester; + tester.testComStatusPassthrough(); +} + +TEST(Nominal, testNominalFraming) { + Svc::CCSDS::TMFramerTester tester; + tester.testNominalFraming(); +} + +TEST(Nominal, testSeqCountWrapAround) { + Svc::CCSDS::TMFramerTester tester; + tester.testSeqCountWrapAround(); +} + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp new file mode 100644 index 00000000000..c836f2d8b95 --- /dev/null +++ b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp @@ -0,0 +1,131 @@ +// ====================================================================== +// \title TMFramerTester.cpp +// \author chammard +// \brief cpp file for TMFramer component test harness implementation class +// ====================================================================== + +#include "TMFramerTester.hpp" +#include "Svc/CCSDS/Types/TMFrameHeaderSerializableAc.hpp" +#include "Svc/CCSDS/Types/TMFrameTrailerSerializableAc.hpp" +#include "Svc/CCSDS/Types/SpacePacketHeaderSerializableAc.hpp" + +namespace Svc { + +namespace CCSDS { + +// ---------------------------------------------------------------------- +// Construction and destruction +// ---------------------------------------------------------------------- + +TMFramerTester ::TMFramerTester() + : TMFramerGTestBase("TMFramerTester", TMFramerTester::MAX_HISTORY_SIZE), component("TMFramer") { + this->initComponents(); + this->connectPorts(); +} + +TMFramerTester ::~TMFramerTester() {} + +// ---------------------------------------------------------------------- +// Tests +// ---------------------------------------------------------------------- + +void TMFramerTester ::testComStatusPassthrough() { + // Send a status message to the component + Fw::Success inputStatus = Fw::Success::SUCCESS; + this->invoke_to_comStatusIn(0, inputStatus); + ASSERT_from_comStatusOut_SIZE(1); + ASSERT_from_comStatusOut(0, inputStatus); // at index 0, received SUCCESS + inputStatus = Fw::Success::FAILURE; + this->invoke_to_comStatusIn(0, inputStatus); + ASSERT_from_comStatusOut_SIZE(2); + ASSERT_from_comStatusOut(1, inputStatus); // at index 1, received FAILURE +} + +void TMFramerTester ::testNominalFraming() { + U8 bufferData[100]; + Fw::Buffer buffer(bufferData, sizeof(bufferData)); + ComCfg::FrameContext defaultContext; + + // Fill the buffer with some data + for (U32 i = 0; i < sizeof(bufferData); ++i) { + bufferData[i] = static_cast(i); + } + + // Invoke the dataIn handler + this->invoke_to_dataIn(0, buffer, defaultContext); + + // Check that the dataOut handler was called with the correct data + ASSERT_from_dataOut_SIZE(1); + Fw::Buffer outBuffer = this->fromPortHistory_dataOut->at(0).data; + ComCfg::FrameContext outContext = this->fromPortHistory_dataOut->at(0).context; + ASSERT_EQ(outBuffer.getSize(), ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize); + ASSERT_EQ(this->fromPortHistory_dataOut->at(0).context.getvcId(), defaultContext.getvcId()); + + U16 outScId = this->getFrameScId(outBuffer.getData()); + U8 outVcId = this->getFrameVcId(outBuffer.getData()); + U8 outMcCount = this->getFrameMcCount(outBuffer.getData()); + U8 outVcCount = this->getFrameVcCount(outBuffer.getData()); + + ASSERT_EQ(outScId, ComCfg::FppConstant_SpacecraftId::SpacecraftId); + ASSERT_EQ(outVcId, defaultContext.getvcId()); + ASSERT_EQ(outMcCount, 0); + ASSERT_EQ(outVcCount, 0); + ASSERT_EQ(this->component.m_masterFrameCount, outMcCount + 1); + ASSERT_EQ(this->component.m_virtualFrameCount, outVcCount + 1); + + // Idle data should be filled at the offset of header + payload + the Space Packet Idle Packet header + FwSizeType expectedIdleDataOffset = TMFrameHeader::SERIALIZED_SIZE + sizeof(bufferData) + SpacePacketHeader::SERIALIZED_SIZE; + + // The frame is composed of the payload + a SpacePacket Idle Packet (Header + idle_pattern) + for (FwSizeType i = expectedIdleDataOffset; i < ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize - TMFrameTrailer::SERIALIZED_SIZE; ++i) { + ASSERT_EQ(outBuffer.getData()[i], 0x44); + } +} + +void TMFramerTester ::testSeqCountWrapAround() { + U8 bufferData[100]; + Fw::Buffer buffer(bufferData, sizeof(bufferData)); + ComCfg::FrameContext defaultContext; + + // Fill the buffer with some data + for (U32 i = 0; i < sizeof(bufferData); ++i) { + bufferData[i] = static_cast(i); + } + + // Intentionally set the sequence count to 250 and iterate 10 times + // to test the wrap around of the sequence counts + this->component.m_masterFrameCount = 250; + this->component.m_virtualFrameCount = 250; + U8 countWrapAround = 250; // will wrap around to 0 after 255 + for (U32 iter = 0; iter < 10; iter++) { + this->invoke_to_dataIn(0, buffer, defaultContext); + ASSERT_from_dataOut_SIZE(iter + 1); + Fw::Buffer outBuffer = this->fromPortHistory_dataOut->at(iter).data; + U8 outMcCount = this->getFrameMcCount(outBuffer.getData()); + U8 outVcCount = this->getFrameVcCount(outBuffer.getData()); + ASSERT_EQ(outMcCount, countWrapAround); + ASSERT_EQ(outVcCount, countWrapAround); + countWrapAround++; + } +} + +// ---------------------------------------------------------------------- +// Helper functions +// ---------------------------------------------------------------------- + +U16 TMFramerTester::getFrameScId(U8* frameData) { + return static_cast((frameData[0] & 0x3F) << 4 | (frameData[1] >> 4)); +} +U8 TMFramerTester::getFrameVcId(U8* frameData) { + return (frameData[1] & 0x0E) >> 1; +} +U8 TMFramerTester::getFrameMcCount(U8* frameData) { + return frameData[2]; +} +U8 TMFramerTester::getFrameVcCount(U8* frameData) { + return frameData[3]; +} + +} // namespace CCSDS + +} // namespace Svc diff --git a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.hpp b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.hpp new file mode 100644 index 00000000000..c8be66f287c --- /dev/null +++ b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.hpp @@ -0,0 +1,78 @@ +// ====================================================================== +// \title TMFramerTester.hpp +// \author chammard +// \brief hpp file for TMFramer component test harness implementation class +// ====================================================================== + +#ifndef Svc_CCSDS_TMFramerTester_HPP +#define Svc_CCSDS_TMFramerTester_HPP + +#include "Svc/CCSDS/TMFramer/TMFramer.hpp" +#include "Svc/CCSDS/TMFramer/TMFramerGTestBase.hpp" + +namespace Svc { + +namespace CCSDS { + +class TMFramerTester final : public TMFramerGTestBase { + public: + // ---------------------------------------------------------------------- + // Constants + // ---------------------------------------------------------------------- + + // Maximum size of histories storing events, telemetry, and port outputs + static const FwSizeType MAX_HISTORY_SIZE = 10; + + // Instance ID supplied to the component instance under test + static const FwEnumStoreType TEST_INSTANCE_ID = 0; + + public: + // ---------------------------------------------------------------------- + // Construction and destruction + // ---------------------------------------------------------------------- + + //! Construct object TMFramerTester + TMFramerTester(); + + //! Destroy object TMFramerTester + ~TMFramerTester(); + + public: + // ---------------------------------------------------------------------- + // Tests + // ---------------------------------------------------------------------- + + void testComStatusPassthrough(); + void testNominalFraming(); + void testSeqCountWrapAround(); + + private: + // ---------------------------------------------------------------------- + // Helper functions + // ---------------------------------------------------------------------- + + //! Connect ports + void connectPorts(); + + //! Initialize components + void initComponents(); + + U16 getFrameScId(U8* frameData); + U8 getFrameVcId(U8* frameData); + U8 getFrameMcCount(U8* frameData); + U8 getFrameVcCount(U8* frameData); + + private: + // ---------------------------------------------------------------------- + // Member variables + // ---------------------------------------------------------------------- + + //! The component under test + TMFramer component; +}; + +} // namespace CCSDS + +} // namespace Svc + +#endif diff --git a/Svc/CCSDS/Types/Types.fpp b/Svc/CCSDS/Types/Types.fpp index 005b586b257..82573f285f0 100644 --- a/Svc/CCSDS/Types/Types.fpp +++ b/Svc/CCSDS/Types/Types.fpp @@ -58,8 +58,7 @@ module CCSDS { } struct TMFrameHeader { - # TODO: rename: channelIds is called GVCID Global Virtual Channel Identifier - channelIds: U16, @< 2 bit Frame Version | 10 bit spacecraft ID | 3 bit virtual channel ID | 1 bit OCF flag + globalVcId: U16, @< 2 bit Frame Version | 10 bit spacecraft ID | 3 bit virtual channel ID | 1 bit OCF flag masterFrameCount: U8, @< 8 bit Master Channel Frame Count virtualFrameCount: U8, @< 8 bit Virtual Channel Frame Count dataFieldStatus: U16 @< 1 bit 2nd Header | 1 bit sync | 1 bit pkt order | 2 bit seg len | 11 bit header ptr diff --git a/default/config/ComCfg.fpp b/default/config/ComCfg.fpp index 31d853e7b2b..4817341f97f 100644 --- a/default/config/ComCfg.fpp +++ b/default/config/ComCfg.fpp @@ -29,10 +29,12 @@ module ComCfg { comQueueIndex: FwIndexType @< Queue Index used by the ComQueue, other components shall not modify apid: APID @< 11 bits APID in CCSDS sequenceCount: U16 @< 14 bit Sequence count - sequence count is incremented per APID + vcId: U8 @< 6 bit Virtual Channel ID - used for TC and TM } default { comQueueIndex = 0 apid = APID.FW_PACKET_UNKNOWN sequenceCount = 0 + vcId = 1 } } From cbf8d926611d0fed0105c07833ec43c1d870c638 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 21 May 2025 16:40:31 -0700 Subject: [PATCH 36/95] Tests and code cleanup --- Svc/CCSDS/ApidMapper/ApidMapper.cpp | 2 +- Svc/CCSDS/ApidMapper/ApidMapper.hpp | 4 +-- .../SpacePacketFramer/SpacePacketFramer.cpp | 1 + .../TCDeframer/test/ut/TCDeframerTester.cpp | 2 +- .../TCDeframer/test/ut/TCDeframerTester.hpp | 2 +- Svc/CCSDS/TMFramer/CMakeLists.txt | 2 +- Svc/CCSDS/TMFramer/TMFramer.cpp | 2 +- .../TMFramer/test/ut/TMFramerTestMain.cpp | 2 +- Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp | 2 +- Svc/CCSDS/TMFramer/test/ut/TMFramerTester.hpp | 10 +++--- Svc/CCSDS/Types/Types.fpp | 36 ++++++++++--------- .../FrameDetector/CcsdsTCFrameDetector.cpp | 4 ++- 12 files changed, 38 insertions(+), 31 deletions(-) diff --git a/Svc/CCSDS/ApidMapper/ApidMapper.cpp b/Svc/CCSDS/ApidMapper/ApidMapper.cpp index 4e8603fb3cf..714f49a3710 100644 --- a/Svc/CCSDS/ApidMapper/ApidMapper.cpp +++ b/Svc/CCSDS/ApidMapper/ApidMapper.cpp @@ -1,6 +1,6 @@ // ====================================================================== // \title ApidMapper.cpp -// \author chammard +// \author thomas-bc // \brief cpp file for ApidMapper component implementation class // ====================================================================== diff --git a/Svc/CCSDS/ApidMapper/ApidMapper.hpp b/Svc/CCSDS/ApidMapper/ApidMapper.hpp index 4b0d0d625c8..b8a51de2de5 100644 --- a/Svc/CCSDS/ApidMapper/ApidMapper.hpp +++ b/Svc/CCSDS/ApidMapper/ApidMapper.hpp @@ -1,6 +1,6 @@ // ====================================================================== // \title ApidMapper.hpp -// \author chammard +// \author thomas-bc // \brief hpp file for ApidMapper component implementation class // ====================================================================== @@ -61,7 +61,7 @@ class ApidMapper final : public ApidMapperComponentBase { //! Wraps around at 14 bits U16 getAndIncrementSeqCount(ComCfg::APID::T apid); - //! This struct helps to track sequence counts per APID + //! This struct helps track sequence counts per APID struct ApidSequenceEntry { ComCfg::APID::T apid = ComCfg::APID::FW_PACKET_UNKNOWN; U16 sequenceCount; diff --git a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp index 44fd4fa92ce..8faa9b7a015 100644 --- a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp +++ b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp @@ -47,6 +47,7 @@ void SpacePacketFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, c U16 packetSequenceControl = 0; packetSequenceControl |= 0x3 << SpacePacketMasks::SeqFlagsOffset; // Sequence Flags 0b11 = unsegmented User Data U16 sequenceCount = context.getsequenceCount(); + // TODO: Add assert that it indeed fits in 14 bits ?? packetSequenceControl |= sequenceCount & SpacePacketMasks::SeqCountMask; // 14 bit sequence count FW_ASSERT(data.getSize() <= std::numeric_limits::max(), static_cast(data.getSize())); diff --git a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp index b4ae2253710..40f99ddc11e 100644 --- a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp +++ b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp @@ -1,6 +1,6 @@ // ====================================================================== // \title TCDeframerTester.cpp -// \author chammard +// \author thomas-bc // \brief cpp file for TCDeframer component test harness implementation class // ====================================================================== diff --git a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.hpp b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.hpp index 25320aea54f..abcd565a148 100644 --- a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.hpp +++ b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.hpp @@ -1,6 +1,6 @@ // ====================================================================== // \title TCDeframerTester.hpp -// \author chammard +// \author thomas-bc // \brief hpp file for TCDeframer component test harness implementation class // ====================================================================== diff --git a/Svc/CCSDS/TMFramer/CMakeLists.txt b/Svc/CCSDS/TMFramer/CMakeLists.txt index ec98423a4ea..231b11416b8 100644 --- a/Svc/CCSDS/TMFramer/CMakeLists.txt +++ b/Svc/CCSDS/TMFramer/CMakeLists.txt @@ -30,4 +30,4 @@ register_fprime_ut( DEPENDS Svc_CCSDS_Types STest -) \ No newline at end of file +) diff --git a/Svc/CCSDS/TMFramer/TMFramer.cpp b/Svc/CCSDS/TMFramer/TMFramer.cpp index 6bf5f04f407..b17f8f45554 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.cpp +++ b/Svc/CCSDS/TMFramer/TMFramer.cpp @@ -116,7 +116,7 @@ void TMFramer ::fill_with_idle_packet(U16 startIndex) { FW_ASSERT(idlePacketLength >= 7, static_cast(idlePacketLength)); // 7 bytes minimum for idle packet FW_ASSERT(idlePacketLength <= ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize, static_cast(idlePacketLength)); - U16 idleApid = 0x7FF; // All 1s (11bit) per Space Packet protocol paragraph 4.1.3.3.4.4 + U16 idleApid = ComCfg::APID::SPP_IDLE_PACKET; // All 1s (11bit) per Space Packet protocol paragraph 4.1.3.3.4.4 this->m_frameBuffer[startIndex + 0] = (idleApid >> 8) & 0xFF; this->m_frameBuffer[startIndex + 1] = idleApid & 0xFF; this->m_frameBuffer[startIndex + 2] = 0xC0; // Sequence Flags = 0b11 (unsegmented) & unused Seq count diff --git a/Svc/CCSDS/TMFramer/test/ut/TMFramerTestMain.cpp b/Svc/CCSDS/TMFramer/test/ut/TMFramerTestMain.cpp index ee5c8dffe2d..0b0c7df7c09 100644 --- a/Svc/CCSDS/TMFramer/test/ut/TMFramerTestMain.cpp +++ b/Svc/CCSDS/TMFramer/test/ut/TMFramerTestMain.cpp @@ -1,6 +1,6 @@ // ====================================================================== // \title TMFramerTestMain.cpp -// \author chammard +// \author thomas-bc // \brief cpp file for TMFramer component test main function // ====================================================================== diff --git a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp index c836f2d8b95..4c896f90776 100644 --- a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp +++ b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp @@ -1,6 +1,6 @@ // ====================================================================== // \title TMFramerTester.cpp -// \author chammard +// \author thomas-bc // \brief cpp file for TMFramer component test harness implementation class // ====================================================================== diff --git a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.hpp b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.hpp index c8be66f287c..e1df80cd1bb 100644 --- a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.hpp +++ b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.hpp @@ -1,6 +1,6 @@ // ====================================================================== // \title TMFramerTester.hpp -// \author chammard +// \author thomas-bc // \brief hpp file for TMFramer component test harness implementation class // ====================================================================== @@ -57,10 +57,10 @@ class TMFramerTester final : public TMFramerGTestBase { //! Initialize components void initComponents(); - U16 getFrameScId(U8* frameData); - U8 getFrameVcId(U8* frameData); - U8 getFrameMcCount(U8* frameData); - U8 getFrameVcCount(U8* frameData); + U16 getFrameScId(U8* frameData); //!< Get the Spacecraft ID from the frame - no boundary check + U8 getFrameVcId(U8* frameData); //!< Get the Virtual Channel ID from the frame - no boundary check + U8 getFrameMcCount(U8* frameData); //!< Get the Master Frame Count from the frame - no boundary check + U8 getFrameVcCount(U8* frameData); //!< Get the Virtual Frame Count from the frame - no boundary check private: // ---------------------------------------------------------------------- diff --git a/Svc/CCSDS/Types/Types.fpp b/Svc/CCSDS/Types/Types.fpp index 82573f285f0..f2e43879c76 100644 --- a/Svc/CCSDS/Types/Types.fpp +++ b/Svc/CCSDS/Types/Types.fpp @@ -9,27 +9,31 @@ module CCSDS { # with the approriate mask to module SpacePacketMasks { - constant PvnMask = 0xE000; @< 0b1110000000000000 - constant PktTypeMask = 0x1000; @< 0b0001000000000000 - constant SecHdrMask = 0x0800; @< 0b0000100000000000 - constant ApidMask = 0x07FF; @< 0b0000011111111111 - constant SecHdrOffset = 11; - constant PktTypeOffset = 12; - constant PvnOffset = 13; - constant SeqFlagsMask = 0xC000; @< 0b1100000000000000 + # packetIdentification sub-fields |-- 16 bits ---| + constant PvnMask = 0xE000; @< 0b1110000000000000 + constant PktTypeMask = 0x1000; @< 0b0001000000000000 + constant SecHdrMask = 0x0800; @< 0b0000100000000000 + constant ApidMask = 0x07FF; @< 0b0000011111111111 + constant PvnOffset = 13; + constant PktTypeOffset = 12; + constant SecHdrOffset = 11; + # packetSequenceControl sub-fields + constant SeqFlagsMask = 0xC000; @< 0b1100000000000000 + constant SeqCountMask = 0x3FFF; @< 0b0011111111111111 constant SeqFlagsOffset = 14; - constant SeqCountMask = 0x3FFF } module TCFrameMasks { - constant FrameVersionMask = 0xC000 - constant BypassFlagMask = 0x2000 - constant ControlFlagMask = 0x1000 - constant ReservedMask = 0x0C00 - constant SpacecraftIdMask = 0x03FF - constant VcIdMask = 0xFC00 + # flagsAndScId sub-fields + constant FrameVersionMask = 0xC000; @< 0b1100000000000000 + constant BypassFlagMask = 0x2000; @< 0b0010000000000000 + constant ControlFlagMask = 0x1000; @< 0b0001000000000000 + constant ReservedMask = 0x0C00; @< 0b0000110000000000 + constant SpacecraftIdMask = 0x03FF; @< 0b0000001111111111 + # vcIdAndLength sub-fields + constant VcIdMask = 0xFC00; @< 0b1111110000000000 + constant FrameLengthMask = 0x03FF; @< 0b0000001111111111 constant VcIdOffset = 10 - constant FrameLengthMask = 0x03FF } @ Describes the frame header format for the SpacePacket communications protocol diff --git a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp index 9cf144311b6..9a224a31c3e 100644 --- a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp +++ b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp @@ -28,15 +28,17 @@ FrameDetector::Status CcsdsTCFrameDetector::detect(const Types::CircularBuffer& if (status != Fw::FW_SERIALIZE_OK) { return Status::NO_FRAME_DETECTED; } - CCSDS::TCFrameHeader header; Fw::ExternalSerializeBuffer header_ser_buffer(header_data, CCSDS::TCFrameHeader::SERIALIZED_SIZE); status = header_ser_buffer.setBuffLen(CCSDS::TCFrameHeader::SERIALIZED_SIZE); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, static_cast(status)); // Attempt to deserialize data into the FrameHeader object + CCSDS::TCFrameHeader header; status = header.deserialize(header_ser_buffer); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); U16 sc_id = header.getflagsAndScId() & CCSDS::TCFrameMasks::SpacecraftIdMask; + // TODO?? Use the full expected flagsAndScId value since the other fields should be static + // REVIEW NOTE: Not doing CRC here.... U16 frame_length = header.getvcIdAndLength() & CCSDS::TCFrameMasks::FrameLengthMask; FwSizeType expected_frame_size = CCSDS::TCFrameHeader::SERIALIZED_SIZE + frame_length + CCSDS::TCFrameTrailer::SERIALIZED_SIZE; // 2 bytes for CRC From 95667c4329741fe9ed903d8b16e7cb12b9a1c997 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 21 May 2025 17:36:55 -0700 Subject: [PATCH 37/95] Define ComPacketType in FPP --- Fw/Cmd/CmdPacket.cpp | 4 +- Fw/Com/ComPacket.cpp | 2 +- Fw/Com/ComPacket.hpp | 15 ++---- Fw/Dp/DpContainer.cpp | 4 +- Fw/Dp/test/ut/TestMain.cpp | 2 +- Fw/Dp/test/util/DpContainerHeader.hpp | 4 +- Fw/Log/LogPacket.cpp | 2 +- Fw/Tlm/TlmPacket.cpp | 6 +-- .../test/ut/ActiveLoggerImplTester.cpp | 8 +-- .../test/ut/CommandDispatcherImplTester.cpp | 22 ++++---- Svc/CmdSequencer/docs/AMPCSSequence.md | 2 +- Svc/CmdSequencer/formats/AMPCSSequence.cpp | 2 +- Svc/CmdSequencer/test/ut/CommandBuffers.cpp | 2 +- .../test/ut/SequenceFiles/FPrime/Records.cpp | 2 +- Svc/CmdSplitter/test/ut/CmdSplitterTester.cpp | 2 +- Svc/FileDownlink/FileDownlink.cpp | 4 +- Svc/FileUplink/FileUplink.cpp | 4 +- Svc/FileUplink/test/ut/FileUplinkTester.cpp | 2 +- Svc/FprimeRouter/docs/sdd.md | 8 +-- .../test/ut/FprimeRouterTester.cpp | 8 +-- Svc/FpySequencer/FpySequencerRunState.cpp | 4 +- .../test/ut/FpySequencerTestMain.cpp | 2 +- Svc/FramingProtocol/docs/sdd.md | 2 +- Svc/FramingProtocol/test/ut/main.cpp | 6 +-- Svc/TlmChan/test/ut/TlmChanTester.cpp | 2 +- Svc/TlmPacketizer/TlmPacketizer.cpp | 2 +- .../test/ut/TlmPacketizerTester.cpp | 50 +++++++++---------- default/config/ComCfg.fpp | 14 ++++-- 28 files changed, 92 insertions(+), 95 deletions(-) diff --git a/Fw/Cmd/CmdPacket.cpp b/Fw/Cmd/CmdPacket.cpp index 9ab6063a544..eef2690fef5 100644 --- a/Fw/Cmd/CmdPacket.cpp +++ b/Fw/Cmd/CmdPacket.cpp @@ -12,7 +12,7 @@ namespace Fw { CmdPacket::CmdPacket() : m_opcode(0) { - this->m_type = FW_PACKET_COMMAND; + this->m_type = ComPacketType::FW_PACKET_COMMAND; } CmdPacket::~CmdPacket() { @@ -34,7 +34,7 @@ namespace Fw { } // double check packet type - if (this->m_type != FW_PACKET_COMMAND) { + if (this->m_type != ComPacketType::FW_PACKET_COMMAND) { return FW_DESERIALIZE_TYPE_MISMATCH; } diff --git a/Fw/Com/ComPacket.cpp b/Fw/Com/ComPacket.cpp index e2af35cf92c..222c6887d28 100644 --- a/Fw/Com/ComPacket.cpp +++ b/Fw/Com/ComPacket.cpp @@ -9,7 +9,7 @@ namespace Fw { - ComPacket::ComPacket() : m_type(FW_PACKET_UNKNOWN) { + ComPacket::ComPacket() : m_type(ComPacketType::FW_PACKET_UNKNOWN) { } ComPacket::~ComPacket() { diff --git a/Fw/Com/ComPacket.hpp b/Fw/Com/ComPacket.hpp index 2179eb9da89..7163ec145cd 100644 --- a/Fw/Com/ComPacket.hpp +++ b/Fw/Com/ComPacket.hpp @@ -9,26 +9,19 @@ #define COMPACKET_HPP_ #include +#include "config/APIDEnumAc.hpp" // Packet format: // |32-bit packet type|packet type-specific data| namespace Fw { + // This type is defined in config/ComCfg.fpp + typedef ComCfg::APID::T ComPacketType; + class ComPacket: public Serializable { public: - typedef enum { - FW_PACKET_COMMAND, // !< Command packet type - incoming - FW_PACKET_TELEM, // !< Telemetry packet type - outgoing - FW_PACKET_LOG, // !< Log type - outgoing - FW_PACKET_FILE, // !< File type - incoming and outgoing - FW_PACKET_PACKETIZED_TLM, // !< Packetized telemetry packet type - FW_PACKET_DP, //!< Data product packet - FW_PACKET_IDLE, // !< Idle packet - FW_PACKET_UNKNOWN = 0xFF // !< Unknown packet - } ComPacketType; - ComPacket(); virtual ~ComPacket(); diff --git a/Fw/Dp/DpContainer.cpp b/Fw/Dp/DpContainer.cpp index 897ce7552cb..d84fe7a1d60 100644 --- a/Fw/Dp/DpContainer.cpp +++ b/Fw/Dp/DpContainer.cpp @@ -46,7 +46,7 @@ Fw::SerializeStatus DpContainer::deserializeHeader() { if (status == Fw::FW_SERIALIZE_OK) { FwPacketDescriptorType packetDescriptor; status = deserializer.deserialize(packetDescriptor); - if (packetDescriptor != Fw::ComPacket::FW_PACKET_DP) { + if (packetDescriptor != ComPacketType::FW_PACKET_DP) { status = Fw::FW_SERIALIZE_FORMAT_ERROR; } } @@ -91,7 +91,7 @@ void DpContainer::serializeHeader() { auto serializer = this->m_buffer.getSerializer(); // Serialize the packet type Fw::SerializeStatus status = - serializer.serialize(static_cast(Fw::ComPacket::FW_PACKET_DP)); + serializer.serialize(static_cast(Fw::ComPacketType::FW_PACKET_DP)); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, static_cast(status)); // Serialize the container id status = serializer.serialize(this->m_id); diff --git a/Fw/Dp/test/ut/TestMain.cpp b/Fw/Dp/test/ut/TestMain.cpp index e331f498ac8..b195f01affc 100644 --- a/Fw/Dp/test/ut/TestMain.cpp +++ b/Fw/Dp/test/ut/TestMain.cpp @@ -166,7 +166,7 @@ TEST(Header, BadPacketDescriptor) { Fw::Buffer buffer(bufferData, sizeof bufferData); // Set the packet descriptor to a bad value auto serializer = buffer.getSerializer(); - const FwPacketDescriptorType badPacketDescriptor = Fw::ComPacket::FW_PACKET_DP + 1; + const FwPacketDescriptorType badPacketDescriptor = Fw::ComPacketType::FW_PACKET_DP + 1; Fw::SerializeStatus status = serializer.serialize(badPacketDescriptor); ASSERT_EQ(status, Fw::FW_SERIALIZE_OK); // Use the buffer to create a container diff --git a/Fw/Dp/test/util/DpContainerHeader.hpp b/Fw/Dp/test/util/DpContainerHeader.hpp index e77ebb677d0..867a3a9235f 100644 --- a/Fw/Dp/test/util/DpContainerHeader.hpp +++ b/Fw/Dp/test/util/DpContainerHeader.hpp @@ -49,12 +49,12 @@ struct DpContainerHeader { ) { auto deserializer = buffer.getDeserializer(); // Deserialize the packet descriptor - FwPacketDescriptorType packetDescriptor = Fw::ComPacket::FW_PACKET_UNKNOWN; + FwPacketDescriptorType packetDescriptor = Fw::ComPacketType::FW_PACKET_UNKNOWN; // Deserialize the packet descriptor DpContainerHeader::moveDeserToOffset(file, line, deserializer, DpContainer::Header::PACKET_DESCRIPTOR_OFFSET); Fw::SerializeStatus status = deserializer.deserialize(packetDescriptor); DP_CONTAINER_HEADER_ASSERT_EQ(status, FW_SERIALIZE_OK); - DP_CONTAINER_HEADER_ASSERT_EQ(packetDescriptor, Fw::ComPacket::FW_PACKET_DP); + DP_CONTAINER_HEADER_ASSERT_EQ(packetDescriptor, Fw::ComPacketType::FW_PACKET_DP); // Deserialize the container id DpContainerHeader::moveDeserToOffset(file, line, deserializer, DpContainer::Header::ID_OFFSET); status = deserializer.deserialize(this->m_id); diff --git a/Fw/Log/LogPacket.cpp b/Fw/Log/LogPacket.cpp index ad8a214d690..ef504da29f7 100644 --- a/Fw/Log/LogPacket.cpp +++ b/Fw/Log/LogPacket.cpp @@ -11,7 +11,7 @@ namespace Fw { LogPacket::LogPacket() : m_id(0) { - this->m_type = FW_PACKET_LOG; + this->m_type = ComPacketType::FW_PACKET_LOG; } LogPacket::~LogPacket() { diff --git a/Fw/Tlm/TlmPacket.cpp b/Fw/Tlm/TlmPacket.cpp index 377153f1acd..9996b96fa6d 100644 --- a/Fw/Tlm/TlmPacket.cpp +++ b/Fw/Tlm/TlmPacket.cpp @@ -11,7 +11,7 @@ namespace Fw { TlmPacket::TlmPacket() : m_numEntries(0) { - this->m_type = FW_PACKET_TELEM; + this->m_type = ComPacketType::FW_PACKET_TELEM; this->m_tlmBuffer.resetSer(); } @@ -24,7 +24,7 @@ namespace Fw { this->m_numEntries = 0; // make sure packet type is correct before serializing. It should // never be anything but FW_PACKET_TELEM, so assert. - FW_ASSERT(FW_PACKET_TELEM == this->m_type, static_cast(this->m_type)); + FW_ASSERT(ComPacketType::FW_PACKET_TELEM == this->m_type, static_cast(this->m_type)); // serialize descriptor // The function serializeBase inherited from ComPacket converts this->m_type // to type FwPacketDescriptorType and serializes the result into this->m_tlmBuffer. @@ -42,7 +42,7 @@ namespace Fw { return stat; } // make sure that this->m_tlmBuffer stores a telemetry packet - if (this->m_type != FW_PACKET_TELEM) { + if (this->m_type != ComPacketType::FW_PACKET_TELEM) { return Fw::FW_DESERIALIZE_TYPE_MISMATCH; } diff --git a/Svc/ActiveLogger/test/ut/ActiveLoggerImplTester.cpp b/Svc/ActiveLogger/test/ut/ActiveLoggerImplTester.cpp index 513b88f4a3d..a685a97a8fb 100644 --- a/Svc/ActiveLogger/test/ut/ActiveLoggerImplTester.cpp +++ b/Svc/ActiveLogger/test/ut/ActiveLoggerImplTester.cpp @@ -118,7 +118,7 @@ namespace Svc { FwPacketDescriptorType desc; stat = this->m_sentPacket.deserialize(desc); ASSERT_EQ(Fw::FW_SERIALIZE_OK,stat); - ASSERT_EQ(desc,static_cast(Fw::ComPacket::FW_PACKET_LOG)); + ASSERT_EQ(desc,static_cast(Fw::ComPacketType::FW_PACKET_LOG)); // next piece should be event ID FwEventIdType sentId; stat = this->m_sentPacket.deserialize(sentId); @@ -451,7 +451,7 @@ namespace Svc { FwPacketDescriptorType desc; stat = this->m_sentPacket.deserialize(desc); ASSERT_EQ(Fw::FW_SERIALIZE_OK,stat); - ASSERT_EQ(desc,static_cast(Fw::ComPacket::FW_PACKET_LOG)); + ASSERT_EQ(desc,static_cast(Fw::ComPacketType::FW_PACKET_LOG)); // next piece should be event ID FwEventIdType sentId; stat = this->m_sentPacket.deserialize(sentId); @@ -503,7 +503,7 @@ namespace Svc { // first piece should be log packet descriptor stat = this->m_sentPacket.deserialize(desc); ASSERT_EQ(Fw::FW_SERIALIZE_OK,stat); - ASSERT_EQ(desc,static_cast(Fw::ComPacket::FW_PACKET_LOG)); + ASSERT_EQ(desc,static_cast(Fw::ComPacketType::FW_PACKET_LOG)); // next piece should be event ID stat = this->m_sentPacket.deserialize(sentId); ASSERT_EQ(Fw::FW_SERIALIZE_OK,stat); @@ -552,7 +552,7 @@ namespace Svc { FwPacketDescriptorType desc; stat = this->m_sentPacket.deserialize(desc); ASSERT_EQ(Fw::FW_SERIALIZE_OK,stat); - ASSERT_EQ(desc,static_cast(Fw::ComPacket::FW_PACKET_LOG)); + ASSERT_EQ(desc,static_cast(Fw::ComPacketType::FW_PACKET_LOG)); // next piece should be event ID FwEventIdType sentId; stat = this->m_sentPacket.deserialize(sentId); diff --git a/Svc/CmdDispatcher/test/ut/CommandDispatcherImplTester.cpp b/Svc/CmdDispatcher/test/ut/CommandDispatcherImplTester.cpp index 360e98fc64c..d8da9bf3a3f 100644 --- a/Svc/CmdDispatcher/test/ut/CommandDispatcherImplTester.cpp +++ b/Svc/CmdDispatcher/test/ut/CommandDispatcherImplTester.cpp @@ -105,7 +105,7 @@ namespace Svc { U32 testContext = 110; this->clearEvents(); Fw::ComBuffer buff; - ASSERT_EQ(buff.serialize(FwPacketDescriptorType(Fw::ComPacket::FW_PACKET_COMMAND)),Fw::FW_SERIALIZE_OK); + ASSERT_EQ(buff.serialize(FwPacketDescriptorType(Fw::ComPacketType::FW_PACKET_COMMAND)),Fw::FW_SERIALIZE_OK); ASSERT_EQ(buff.serialize(testOpCode),Fw::FW_SERIALIZE_OK); ASSERT_EQ(buff.serialize(testCmdArg),Fw::FW_SERIALIZE_OK); @@ -207,7 +207,7 @@ namespace Svc { // send NO_OP command this->m_seqStatusRcvd = false; Fw::ComBuffer buff; - ASSERT_EQ(buff.serialize(static_cast(Fw::ComPacket::FW_PACKET_COMMAND)),Fw::FW_SERIALIZE_OK); + ASSERT_EQ(buff.serialize(static_cast(Fw::ComPacketType::FW_PACKET_COMMAND)),Fw::FW_SERIALIZE_OK); ASSERT_EQ(buff.serialize(static_cast(CommandDispatcherImpl::OPCODE_CMD_NO_OP)),Fw::FW_SERIALIZE_OK); this->clearEvents(); @@ -234,7 +234,7 @@ namespace Svc { this->clearEvents(); this->m_seqStatusRcvd = false; buff.resetSer(); - ASSERT_EQ(buff.serialize(FwPacketDescriptorType(Fw::ComPacket::FW_PACKET_COMMAND)),Fw::FW_SERIALIZE_OK); + ASSERT_EQ(buff.serialize(FwPacketDescriptorType(Fw::ComPacketType::FW_PACKET_COMMAND)),Fw::FW_SERIALIZE_OK); ASSERT_EQ(buff.serialize(FwOpcodeType(CommandDispatcherImpl::OPCODE_CMD_NO_OP_STRING)),Fw::FW_SERIALIZE_OK); // serialize arg1 Fw::CmdStringArg argString("BOO!"); @@ -261,7 +261,7 @@ namespace Svc { // send TEST_CMD_1 command this->m_seqStatusRcvd = false; buff.resetSer(); - ASSERT_EQ(buff.serialize(static_cast(Fw::ComPacket::FW_PACKET_COMMAND)),Fw::FW_SERIALIZE_OK); + ASSERT_EQ(buff.serialize(static_cast(Fw::ComPacketType::FW_PACKET_COMMAND)),Fw::FW_SERIALIZE_OK); ASSERT_EQ(buff.serialize(static_cast(CommandDispatcherImpl::OPCODE_CMD_TEST_CMD_1)),Fw::FW_SERIALIZE_OK); // serialize arg1 ASSERT_EQ(buff.serialize(static_cast(1)),Fw::FW_SERIALIZE_OK); @@ -384,7 +384,7 @@ namespace Svc { this->clearEvents(); this->m_seqStatusRcvd = false; Fw::ComBuffer buff; - ASSERT_EQ(buff.serialize(FwPacketDescriptorType(Fw::ComPacket::FW_PACKET_COMMAND)),Fw::FW_SERIALIZE_OK); + ASSERT_EQ(buff.serialize(FwPacketDescriptorType(Fw::ComPacketType::FW_PACKET_COMMAND)),Fw::FW_SERIALIZE_OK); ASSERT_EQ(buff.serialize(FwOpcodeType(testOpCode + 1)),Fw::FW_SERIALIZE_OK); ASSERT_EQ(buff.serialize(testCmdArg),Fw::FW_SERIALIZE_OK); @@ -466,7 +466,7 @@ namespace Svc { U32 testContext = 13; this->clearEvents(); Fw::ComBuffer buff; - ASSERT_EQ(buff.serialize(FwPacketDescriptorType(Fw::ComPacket::FW_PACKET_COMMAND)),Fw::FW_SERIALIZE_OK); + ASSERT_EQ(buff.serialize(FwPacketDescriptorType(Fw::ComPacketType::FW_PACKET_COMMAND)),Fw::FW_SERIALIZE_OK); ASSERT_EQ(buff.serialize(testOpCode),Fw::FW_SERIALIZE_OK); ASSERT_EQ(buff.serialize(testCmdArg),Fw::FW_SERIALIZE_OK); @@ -520,7 +520,7 @@ namespace Svc { currSeq++; this->clearEvents(); buff.resetSer(); - ASSERT_EQ(buff.serialize(FwPacketDescriptorType(Fw::ComPacket::FW_PACKET_COMMAND)),Fw::FW_SERIALIZE_OK); + ASSERT_EQ(buff.serialize(FwPacketDescriptorType(Fw::ComPacketType::FW_PACKET_COMMAND)),Fw::FW_SERIALIZE_OK); ASSERT_EQ(buff.serialize(testOpCode),Fw::FW_SERIALIZE_OK); ASSERT_EQ(buff.serialize(testCmdArg),Fw::FW_SERIALIZE_OK); @@ -574,7 +574,7 @@ namespace Svc { // dispatch a test command this->clearEvents(); buff.resetSer(); - ASSERT_EQ(buff.serialize(FwPacketDescriptorType(Fw::ComPacket::FW_PACKET_COMMAND)),Fw::FW_SERIALIZE_OK); + ASSERT_EQ(buff.serialize(FwPacketDescriptorType(Fw::ComPacketType::FW_PACKET_COMMAND)),Fw::FW_SERIALIZE_OK); ASSERT_EQ(buff.serialize(testOpCode),Fw::FW_SERIALIZE_OK); ASSERT_EQ(buff.serialize(testCmdArg),Fw::FW_SERIALIZE_OK); @@ -720,7 +720,7 @@ namespace Svc { U32 testContext = 13; this->clearEvents(); Fw::ComBuffer buff; - ASSERT_EQ(buff.serialize(FwPacketDescriptorType(Fw::ComPacket::FW_PACKET_COMMAND)),Fw::FW_SERIALIZE_OK); + ASSERT_EQ(buff.serialize(FwPacketDescriptorType(Fw::ComPacketType::FW_PACKET_COMMAND)),Fw::FW_SERIALIZE_OK); ASSERT_EQ(buff.serialize(testOpCode),Fw::FW_SERIALIZE_OK); ASSERT_EQ(buff.serialize(testCmdArg),Fw::FW_SERIALIZE_OK); @@ -816,7 +816,7 @@ namespace Svc { U32 testCmdArg = 100; this->clearEvents(); Fw::ComBuffer buff; - ASSERT_EQ(buff.serialize(FwPacketDescriptorType(Fw::ComPacket::FW_PACKET_COMMAND)),Fw::FW_SERIALIZE_OK); + ASSERT_EQ(buff.serialize(FwPacketDescriptorType(Fw::ComPacketType::FW_PACKET_COMMAND)),Fw::FW_SERIALIZE_OK); ASSERT_EQ(buff.serialize(testOpCode),Fw::FW_SERIALIZE_OK); ASSERT_EQ(buff.serialize(testCmdArg),Fw::FW_SERIALIZE_OK); @@ -848,7 +848,7 @@ namespace Svc { // dispatch command to clear sequence tracker table buff.resetSer(); - ASSERT_EQ(buff.serialize(FwPacketDescriptorType(Fw::ComPacket::FW_PACKET_COMMAND)),Fw::FW_SERIALIZE_OK); + ASSERT_EQ(buff.serialize(FwPacketDescriptorType(Fw::ComPacketType::FW_PACKET_COMMAND)),Fw::FW_SERIALIZE_OK); ASSERT_EQ(buff.serialize(static_cast(CommandDispatcherImpl::OPCODE_CMD_CLEAR_TRACKING)),Fw::FW_SERIALIZE_OK); this->invoke_to_seqCmdBuff(0,buff,testContext); diff --git a/Svc/CmdSequencer/docs/AMPCSSequence.md b/Svc/CmdSequencer/docs/AMPCSSequence.md index f23ca5700c7..a2efd62fa05 100644 --- a/Svc/CmdSequencer/docs/AMPCSSequence.md +++ b/Svc/CmdSequencer/docs/AMPCSSequence.md @@ -63,7 +63,7 @@ argument field: Field | Size in Bytes | Value ----------------- | ------------- | ----------- -Packet Descriptor | 4 | `Fw::ComPacket::FW_PACKET_COMMAND` +Packet Descriptor | 4 | `Fw::ComPacketType::FW_PACKET_COMMAND` Opcode | 4 | The opcode stored in bytes 0-1 of the serial record, zero-extended to four bytes Arguments | Variable | Bytes 2-end of the serial record diff --git a/Svc/CmdSequencer/formats/AMPCSSequence.cpp b/Svc/CmdSequencer/formats/AMPCSSequence.cpp index 290648b1989..d0e7be8754c 100644 --- a/Svc/CmdSequencer/formats/AMPCSSequence.cpp +++ b/Svc/CmdSequencer/formats/AMPCSSequence.cpp @@ -423,7 +423,7 @@ namespace Svc { Fw::SerializeBufferBase& buffer = this->m_buffer; comBuffer.resetSer(); // Serialize the command packet descriptor - const FwPacketDescriptorType cmdDescriptor = Fw::ComPacket::FW_PACKET_COMMAND; + const FwPacketDescriptorType cmdDescriptor = Fw::ComPacketType::FW_PACKET_COMMAND; Fw::SerializeStatus status = comBuffer.serialize(cmdDescriptor); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); // Zero-extend the two-byte AMPCS opcode by two bytes diff --git a/Svc/CmdSequencer/test/ut/CommandBuffers.cpp b/Svc/CmdSequencer/test/ut/CommandBuffers.cpp index e420bb217a3..2e9823dd851 100644 --- a/Svc/CmdSequencer/test/ut/CommandBuffers.cpp +++ b/Svc/CmdSequencer/test/ut/CommandBuffers.cpp @@ -22,7 +22,7 @@ namespace Svc { const U32 argument ) { comBuff.resetSer(); - const FwPacketDescriptorType descriptor = Fw::ComPacket::FW_PACKET_COMMAND; + const FwPacketDescriptorType descriptor = Fw::ComPacketType::FW_PACKET_COMMAND; ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(descriptor)); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(opcode)); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(argument)); diff --git a/Svc/CmdSequencer/test/ut/SequenceFiles/FPrime/Records.cpp b/Svc/CmdSequencer/test/ut/SequenceFiles/FPrime/Records.cpp index 173d4f1cf1c..b57b523d3e4 100644 --- a/Svc/CmdSequencer/test/ut/SequenceFiles/FPrime/Records.cpp +++ b/Svc/CmdSequencer/test/ut/SequenceFiles/FPrime/Records.cpp @@ -31,7 +31,7 @@ namespace Svc { const U8 *const buffAddr = opcodeAndArgument.getBuffAddr(); const U32 size = opcodeAndArgument.getBuffLength(); const U32 recSize = sizeof(FwPacketDescriptorType) + size; - const FwPacketDescriptorType cmdDescriptor = Fw::ComPacket::FW_PACKET_COMMAND; + const FwPacketDescriptorType cmdDescriptor = Fw::ComPacketType::FW_PACKET_COMMAND; const U32 seconds = time.getSeconds(); const U32 uSeconds = time.getUSeconds(); ASSERT_EQ(Fw::FW_SERIALIZE_OK, destBuffer.serialize(seconds)); diff --git a/Svc/CmdSplitter/test/ut/CmdSplitterTester.cpp b/Svc/CmdSplitter/test/ut/CmdSplitterTester.cpp index e8184eba9f4..a41387a1464 100644 --- a/Svc/CmdSplitter/test/ut/CmdSplitterTester.cpp +++ b/Svc/CmdSplitter/test/ut/CmdSplitterTester.cpp @@ -29,7 +29,7 @@ CmdSplitterTester ::~CmdSplitterTester() {} Fw::ComBuffer CmdSplitterTester ::build_command_around_opcode(FwOpcodeType opcode) { Fw::ComBuffer comBuffer; - EXPECT_EQ(comBuffer.serialize(static_cast(Fw::ComPacket::FW_PACKET_COMMAND)), Fw::FW_SERIALIZE_OK); + EXPECT_EQ(comBuffer.serialize(static_cast(Fw::ComPacketType::FW_PACKET_COMMAND)), Fw::FW_SERIALIZE_OK); EXPECT_EQ(comBuffer.serialize(opcode), Fw::FW_SERIALIZE_OK); Fw::CmdArgBuffer args; diff --git a/Svc/FileDownlink/FileDownlink.cpp b/Svc/FileDownlink/FileDownlink.cpp index 18e9bad4462..324bfba4374 100644 --- a/Svc/FileDownlink/FileDownlink.cpp +++ b/Svc/FileDownlink/FileDownlink.cpp @@ -360,7 +360,7 @@ void FileDownlink ::sendCancelPacket() { static_cast(filePacket.bufferSize() + sizeof(FwPacketDescriptorType))); // Serialize the packet descriptor FW_PACKET_FILE to the buffer - Fw::SerializeStatus status = buffer.getSerializer().serialize(Fw::ComPacket::FW_PACKET_FILE); + Fw::SerializeStatus status = buffer.getSerializer().serialize(Fw::ComPacketType::FW_PACKET_FILE); FW_ASSERT(status == Fw::FW_SERIALIZE_OK); Fw::Buffer offsetBuffer(buffer.getData() + sizeof(FwPacketDescriptorType), buffer.getSize() - static_cast(sizeof(FwPacketDescriptorType))); @@ -398,7 +398,7 @@ void FileDownlink ::sendFilePacket(const Fw::FilePacket& filePacket) { FW_ASSERT(this->m_buffer.getSize() >= bufferSize, static_cast(bufferSize), static_cast(this->m_buffer.getSize())); // Serialize packet descriptor FW_PACKET_FILE to the buffer - Fw::SerializeStatus status = this->m_buffer.getSerializer().serialize(Fw::ComPacket::FW_PACKET_FILE); + Fw::SerializeStatus status = this->m_buffer.getSerializer().serialize(Fw::ComPacketType::FW_PACKET_FILE); FW_ASSERT(status == Fw::FW_SERIALIZE_OK); // Serialize the filePacket content into the buffer, offset by the size of the packet descriptor Fw::Buffer offsetBuffer( diff --git a/Svc/FileUplink/FileUplink.cpp b/Svc/FileUplink/FileUplink.cpp index 1e7f051d6ba..4ea45fc9743 100644 --- a/Svc/FileUplink/FileUplink.cpp +++ b/Svc/FileUplink/FileUplink.cpp @@ -39,7 +39,7 @@ FileUplink ::~FileUplink() {} void FileUplink ::bufferSendIn_handler(const FwIndexType portNum, Fw::Buffer& buffer) { // If packet is too small to contain a packet type, log + deallocate and return if (buffer.getSize() < sizeof(FwPacketDescriptorType)) { - this->log_WARNING_HI_InvalidPacketReceived(Fw::ComPacket::FW_PACKET_UNKNOWN); + this->log_WARNING_HI_InvalidPacketReceived(Fw::ComPacketType::FW_PACKET_UNKNOWN); this->bufferSendOut_out(0, buffer); return; } @@ -50,7 +50,7 @@ void FileUplink ::bufferSendIn_handler(const FwIndexType portNum, Fw::Buffer& bu FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); // If packet type is not a file packet, log + deallocate and return - if (packetType != Fw::ComPacket::FW_PACKET_FILE) { + if (packetType != Fw::ComPacketType::FW_PACKET_FILE) { this->log_WARNING_HI_InvalidPacketReceived(packetType); this->bufferSendOut_out(0, buffer); return; diff --git a/Svc/FileUplink/test/ut/FileUplinkTester.cpp b/Svc/FileUplink/test/ut/FileUplinkTester.cpp index 0cfd22766ec..b965bcdec23 100644 --- a/Svc/FileUplink/test/ut/FileUplinkTester.cpp +++ b/Svc/FileUplink/test/ut/FileUplinkTester.cpp @@ -617,7 +617,7 @@ namespace Svc { Fw::Buffer buffer(bufferData, bufferSize); // Serialize the packet descriptor FW_PACKET_FILE to the buffer - Fw::SerializeStatus status = buffer.getSerializer().serialize(Fw::ComPacket::FW_PACKET_FILE); + Fw::SerializeStatus status = buffer.getSerializer().serialize(Fw::ComPacketType::FW_PACKET_FILE); FW_ASSERT(status == Fw::FW_SERIALIZE_OK); // Serialize the filePacket content into the buffer after the packet descriptor token Fw::Buffer offsetBuffer(buffer.getData() + sizeof(FwPacketDescriptorType), diff --git a/Svc/FprimeRouter/docs/sdd.md b/Svc/FprimeRouter/docs/sdd.md index 374a4182fd1..87bc219395a 100644 --- a/Svc/FprimeRouter/docs/sdd.md +++ b/Svc/FprimeRouter/docs/sdd.md @@ -4,7 +4,7 @@ The `Svc::FprimeRouter` component routes F´ packets (such as command or file pa The `Svc::FprimeRouter` component receives F´ packets (as [Fw::Buffer](../../../Fw/Buffer/docs/sdd.md) objects) and routes them to other components through synchronous port calls. The input port of type `Svc.ComDataWithContext` passes this Fw.Buffer object along with optional context data which can help for routing. The current F Prime protocol does not use this context data, but is nevertheless present in the interface for compatibility with other protocols which may for example pass APIDs in the frame headers. -The `Svc::FprimeRouter` component supports `Fw::ComPacket::FW_PACKET_COMMAND` and `Fw::ComPacket::FW_PACKET_FILE` packet types. Unknown packet types are forwarded on the `unknownDataOut` port, which a project-specific component can connect to for custom routing. +The `Svc::FprimeRouter` component supports `Fw::ComPacketType::FW_PACKET_COMMAND` and `Fw::ComPacketType::FW_PACKET_FILE` packet types. Unknown packet types are forwarded on the `unknownDataOut` port, which a project-specific component can connect to for custom routing. About memory management, all buffers sent by `Svc::FprimeRouter` on the `fileOut` and `unknownDataOut` ports are expected to be returned to the router through the `fileBufferReturnIn` port for deallocation. @@ -40,9 +40,9 @@ In the canonical uplink communications stack, `Svc::FprimeRouter` is connected t | Name | Description | Rationale | Validation | |---|---|---|---| SVC-ROUTER-001 | `Svc::FprimeRouter` shall route packets based on their packet type as indicated by the packet header | Routing mechanism of the F´ comms protocol | Unit test | -SVC-ROUTER-002 | `Svc::FprimeRouter` shall route packets of type `Fw::ComPacket::FW_PACKET_COMMAND` to the `commandOut` output port. | Routing command packets | Unit test | -SVC-ROUTER-003 | `Svc::FprimeRouter` shall route packets of type `Fw::ComPacket::FW_PACKET_FILE` to the `fileOut` output port. | Routing file packets | Unit test | -SVC-ROUTER-004 | `Svc::FprimeRouter` shall route data that is neither `Fw::ComPacket::FW_PACKET_COMMAND` nor `Fw::ComPacket::FW_PACKET_FILE` to the `unknownDataOut` output port. | Allows for projects to provide custom routing for additional (project-specific) uplink data types | Unit test | +SVC-ROUTER-002 | `Svc::FprimeRouter` shall route packets of type `Fw::ComPacketType::FW_PACKET_COMMAND` to the `commandOut` output port. | Routing command packets | Unit test | +SVC-ROUTER-003 | `Svc::FprimeRouter` shall route packets of type `Fw::ComPacketType::FW_PACKET_FILE` to the `fileOut` output port. | Routing file packets | Unit test | +SVC-ROUTER-004 | `Svc::FprimeRouter` shall route data that is neither `Fw::ComPacketType::FW_PACKET_COMMAND` nor `Fw::ComPacketType::FW_PACKET_FILE` to the `unknownDataOut` output port. | Allows for projects to provide custom routing for additional (project-specific) uplink data types | Unit test | SVC-ROUTER-005 | `Svc::FprimeRouter` shall emit warning events if serialization errors occur during processing of incoming packets | Aid in diagnosing uplink issues | Unit test | SVC-ROUTER-005 | `Svc::FprimeRouter` shall make a copy of buffers that represent a `FW_PACKET_FILE` | Aid in memory management of file buffers | Unit test | SVC-ROUTER-005 | `Svc::FprimeRouter` shall return ownership of all buffers received on `dataIn` through `dataReturnOut` | Memory management | Unit test | diff --git a/Svc/FprimeRouter/test/ut/FprimeRouterTester.cpp b/Svc/FprimeRouter/test/ut/FprimeRouterTester.cpp index f2a38552c64..0e3638be801 100644 --- a/Svc/FprimeRouter/test/ut/FprimeRouterTester.cpp +++ b/Svc/FprimeRouter/test/ut/FprimeRouterTester.cpp @@ -29,7 +29,7 @@ FprimeRouterTester ::~FprimeRouterTester() {} // ---------------------------------------------------------------------- void FprimeRouterTester ::testRouteComInterface() { - this->mockReceivePacketType(Fw::ComPacket::FW_PACKET_COMMAND); + this->mockReceivePacketType(Fw::ComPacketType::FW_PACKET_COMMAND); ASSERT_from_commandOut_SIZE(1); // one command packet emitted ASSERT_from_fileOut_SIZE(0); // no file packet emitted ASSERT_from_unknownDataOut_SIZE(0); // no unknown data emitted @@ -38,7 +38,7 @@ void FprimeRouterTester ::testRouteComInterface() { } void FprimeRouterTester ::testRouteFileInterface() { - this->mockReceivePacketType(Fw::ComPacket::FW_PACKET_FILE); + this->mockReceivePacketType(Fw::ComPacketType::FW_PACKET_FILE); ASSERT_from_commandOut_SIZE(0); // no command packet emitted ASSERT_from_fileOut_SIZE(1); // one file packet emitted ASSERT_from_unknownDataOut_SIZE(0); // no unknown data emitted @@ -47,7 +47,7 @@ void FprimeRouterTester ::testRouteFileInterface() { } void FprimeRouterTester ::testRouteUnknownPacket() { - this->mockReceivePacketType(Fw::ComPacket::FW_PACKET_UNKNOWN); + this->mockReceivePacketType(Fw::ComPacketType::FW_PACKET_UNKNOWN); ASSERT_from_commandOut_SIZE(0); // no command packet emitted ASSERT_from_fileOut_SIZE(0); // no file packet emitted ASSERT_from_unknownDataOut_SIZE(1); // one unknown data emitted @@ -56,7 +56,7 @@ void FprimeRouterTester ::testRouteUnknownPacket() { } void FprimeRouterTester ::testRouteUnknownPacketUnconnected() { - this->mockReceivePacketType(Fw::ComPacket::FW_PACKET_UNKNOWN); + this->mockReceivePacketType(Fw::ComPacketType::FW_PACKET_UNKNOWN); ASSERT_from_commandOut_SIZE(0); // no command packet emitted ASSERT_from_fileOut_SIZE(0); // no file packet emitted ASSERT_from_unknownDataOut_SIZE(0); // zero unknown data emitted when port is unconnected diff --git a/Svc/FpySequencer/FpySequencerRunState.cpp b/Svc/FpySequencer/FpySequencerRunState.cpp index b500e101e3c..ec93457ba7c 100644 --- a/Svc/FpySequencer/FpySequencerRunState.cpp +++ b/Svc/FpySequencer/FpySequencerRunState.cpp @@ -50,12 +50,12 @@ Signal FpySequencer::dispatchStatement() { Fw::Success FpySequencer::dispatchCommand(const Fpy::Statement& stmt) { FW_ASSERT(stmt.gettype() == Fpy::StatementType::COMMAND); Fw::ComBuffer cmdBuf; - Fw::SerializeStatus stat = cmdBuf.serialize(Fw::ComPacket::FW_PACKET_COMMAND); + Fw::SerializeStatus stat = cmdBuf.serialize(Fw::ComPacketType::FW_PACKET_COMMAND); // TODO should I assert here? this really shouldn't fail, I should just add a static assert // on com buf size and then assert here if (stat != Fw::SerializeStatus::FW_SERIALIZE_OK) { this->log_WARNING_HI_CommandSerializeError(stmt.getopCode(), cmdBuf.getBuffCapacity(), cmdBuf.getBuffLength(), - sizeof(Fw::ComPacket::FW_PACKET_COMMAND), stat, + sizeof(Fw::ComPacketType::FW_PACKET_COMMAND), stat, this->m_runtime.nextStatementIndex - 1); return Fw::Success::FAILURE; } diff --git a/Svc/FpySequencer/test/ut/FpySequencerTestMain.cpp b/Svc/FpySequencer/test/ut/FpySequencerTestMain.cpp index b980c544495..4827880b466 100644 --- a/Svc/FpySequencer/test/ut/FpySequencerTestMain.cpp +++ b/Svc/FpySequencer/test/ut/FpySequencerTestMain.cpp @@ -765,7 +765,7 @@ TEST_F(FpySequencerTester, dispatchCommand) { ASSERT_EQ(result, Fw::Success::SUCCESS); Fw::ComBuffer expected; - ASSERT_EQ(expected.serialize(Fw::ComPacket::FW_PACKET_COMMAND), Fw::SerializeStatus::FW_SERIALIZE_OK); + ASSERT_EQ(expected.serialize(Fw::ComPacketType::FW_PACKET_COMMAND), Fw::SerializeStatus::FW_SERIALIZE_OK); ASSERT_EQ(expected.serialize(cmd.getopCode()), Fw::SerializeStatus::FW_SERIALIZE_OK); ASSERT_EQ(expected.serialize(buf.getBuffAddr(), buf.getBuffLength(), true), Fw::SerializeStatus::FW_SERIALIZE_OK); ASSERT_from_cmdOut_SIZE(1); diff --git a/Svc/FramingProtocol/docs/sdd.md b/Svc/FramingProtocol/docs/sdd.md index ccf01b4beb4..60cba914c73 100644 --- a/Svc/FramingProtocol/docs/sdd.md +++ b/Svc/FramingProtocol/docs/sdd.md @@ -255,7 +255,7 @@ The F Prime framing protocol operates as follows: 1. Compute the size of the data stored in the frame (the "frame data size") - 1. If `packet_type` is `Fw::ComPacket::FW_PACKET_UNKNOWN`, then the frame data + 1. If `packet_type` is `Fw::ComPacketType::FW_PACKET_UNKNOWN`, then the frame data size is the size of the provided data. 1. Otherwise the frame data size is the size of the provided data plus four diff --git a/Svc/FramingProtocol/test/ut/main.cpp b/Svc/FramingProtocol/test/ut/main.cpp index a8a9f548e32..b7838e934b4 100644 --- a/Svc/FramingProtocol/test/ut/main.cpp +++ b/Svc/FramingProtocol/test/ut/main.cpp @@ -144,7 +144,7 @@ TEST(Framing, CommandPacket) { COMMENT("Apply framing to a command packet"); REQUIREMENT("Svc-FramingProtocol-001"); REQUIREMENT("Svc-FramingProtocol-003"); - Svc::FramingTester tester(Fw::ComPacket::FW_PACKET_COMMAND); + Svc::FramingTester tester(Fw::ComPacketType::FW_PACKET_COMMAND); tester.check(); } @@ -152,7 +152,7 @@ TEST(Framing, FilePacket) { COMMENT("Apply framing to a file packet"); REQUIREMENT("Svc-FramingProtocol-001"); REQUIREMENT("Svc-FramingProtocol-003"); - Svc::FramingTester tester(Fw::ComPacket::FW_PACKET_FILE); + Svc::FramingTester tester(Fw::ComPacketType::FW_PACKET_FILE); tester.check(); } @@ -160,7 +160,7 @@ TEST(Framing, UnknownPacket) { COMMENT("Apply framing to a packet of unknown type"); REQUIREMENT("Svc-FramingProtocol-001"); REQUIREMENT("Svc-FramingProtocol-003"); - Svc::FramingTester tester(Fw::ComPacket::FW_PACKET_UNKNOWN); + Svc::FramingTester tester(Fw::ComPacketType::FW_PACKET_UNKNOWN); tester.check(); } diff --git a/Svc/TlmChan/test/ut/TlmChanTester.cpp b/Svc/TlmChan/test/ut/TlmChanTester.cpp index 201e0026394..9fc28089b2f 100644 --- a/Svc/TlmChan/test/ut/TlmChanTester.cpp +++ b/Svc/TlmChan/test/ut/TlmChanTester.cpp @@ -187,7 +187,7 @@ void TlmChanTester::checkBuff(FwChanIdType chanNum, FwChanIdType totalChan, FwCh FwPacketDescriptorType desc; stat = this->m_rcvdBuffer[packet].deserialize(desc); ASSERT_EQ(Fw::FW_SERIALIZE_OK, stat); - ASSERT_EQ(desc, static_cast(Fw::ComPacket::FW_PACKET_TELEM)); + ASSERT_EQ(desc, static_cast(Fw::ComPacketType::FW_PACKET_TELEM)); for (FwChanIdType chan = 0; chan < CHANS_PER_COMBUFFER; chan++) { // decode channel ID diff --git a/Svc/TlmPacketizer/TlmPacketizer.cpp b/Svc/TlmPacketizer/TlmPacketizer.cpp index fb195312e59..b5d90f59be9 100644 --- a/Svc/TlmPacketizer/TlmPacketizer.cpp +++ b/Svc/TlmPacketizer/TlmPacketizer.cpp @@ -90,7 +90,7 @@ void TlmPacketizer::setPacketList(const TlmPacketizerPacketList& packetList, memset(this->m_fillBuffers[pktEntry].buffer.getBuffAddr(), 0, static_cast(packetLen)); // serialize packet descriptor and packet ID now since it will always be the same Fw::SerializeStatus stat = this->m_fillBuffers[pktEntry].buffer.serialize( - static_cast(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM)); + static_cast(Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM)); FW_ASSERT(Fw::FW_SERIALIZE_OK == stat, stat); stat = this->m_fillBuffers[pktEntry].buffer.serialize(packetList.list[pktEntry]->id); FW_ASSERT(Fw::FW_SERIALIZE_OK == stat, stat); diff --git a/Svc/TlmPacketizer/test/ut/TlmPacketizerTester.cpp b/Svc/TlmPacketizer/test/ut/TlmPacketizerTester.cpp index 0863cb5366f..b41b8eb51af 100644 --- a/Svc/TlmPacketizer/test/ut/TlmPacketizerTester.cpp +++ b/Svc/TlmPacketizer/test/ut/TlmPacketizerTester.cpp @@ -133,7 +133,7 @@ void TlmPacketizerTester ::sendPacketsTest() { Fw::ComBuffer comBuff; ASSERT_EQ(Fw::FW_SERIALIZE_OK, - comBuff.serialize(static_cast(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM))); + comBuff.serialize(static_cast(Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(4))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(this->m_testTime)); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(20))); @@ -144,7 +144,7 @@ void TlmPacketizerTester ::sendPacketsTest() { comBuff.resetSer(); ASSERT_EQ(Fw::FW_SERIALIZE_OK, - comBuff.serialize(static_cast(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM))); + comBuff.serialize(static_cast(Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(8))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(this->m_testTime)); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(20))); @@ -201,7 +201,7 @@ void TlmPacketizerTester ::sendPacketLevelsTest() { Fw::ComBuffer comBuff; ASSERT_EQ(Fw::FW_SERIALIZE_OK, - comBuff.serialize(static_cast(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM))); + comBuff.serialize(static_cast(Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(4))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(this->m_testTime)); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(20))); @@ -212,7 +212,7 @@ void TlmPacketizerTester ::sendPacketLevelsTest() { comBuff.resetSer(); ASSERT_EQ(Fw::FW_SERIALIZE_OK, - comBuff.serialize(static_cast(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM))); + comBuff.serialize(static_cast(Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(8))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(this->m_testTime)); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(20))); @@ -251,7 +251,7 @@ void TlmPacketizerTester ::updatePacketsTest() { comBuff.resetSer(); ASSERT_EQ(Fw::FW_SERIALIZE_OK, - comBuff.serialize(static_cast(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM))); + comBuff.serialize(static_cast(Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(4))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(ts)); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(20))); @@ -262,7 +262,7 @@ void TlmPacketizerTester ::updatePacketsTest() { comBuff.resetSer(); ASSERT_EQ(Fw::FW_SERIALIZE_OK, - comBuff.serialize(static_cast(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM))); + comBuff.serialize(static_cast(Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(8))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(ts)); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(20))); @@ -290,7 +290,7 @@ void TlmPacketizerTester ::updatePacketsTest() { comBuff.resetSer(); ASSERT_EQ(Fw::FW_SERIALIZE_OK, - comBuff.serialize(static_cast(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM))); + comBuff.serialize(static_cast(Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(4))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(ts)); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(20))); @@ -312,7 +312,7 @@ void TlmPacketizerTester ::updatePacketsTest() { comBuff.resetSer(); ASSERT_EQ(Fw::FW_SERIALIZE_OK, - comBuff.serialize(static_cast(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM))); + comBuff.serialize(static_cast(Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(4))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(ts)); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(20))); @@ -333,7 +333,7 @@ void TlmPacketizerTester ::updatePacketsTest() { comBuff.resetSer(); ASSERT_EQ(Fw::FW_SERIALIZE_OK, - comBuff.serialize(static_cast(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM))); + comBuff.serialize(static_cast(Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(8))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(ts)); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(20))); @@ -357,7 +357,7 @@ void TlmPacketizerTester ::updatePacketsTest() { comBuff.resetSer(); ASSERT_EQ(Fw::FW_SERIALIZE_OK, - comBuff.serialize(static_cast(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM))); + comBuff.serialize(static_cast(Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(8))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(ts)); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(20))); @@ -379,7 +379,7 @@ void TlmPacketizerTester ::updatePacketsTest() { comBuff.resetSer(); ASSERT_EQ(Fw::FW_SERIALIZE_OK, - comBuff.serialize(static_cast(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM))); + comBuff.serialize(static_cast(Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(8))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(ts)); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(20))); @@ -404,7 +404,7 @@ void TlmPacketizerTester ::updatePacketsTest() { comBuff.resetSer(); ASSERT_EQ(Fw::FW_SERIALIZE_OK, - comBuff.serialize(static_cast(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM))); + comBuff.serialize(static_cast(Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(4))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(ts)); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(1000))); @@ -415,7 +415,7 @@ void TlmPacketizerTester ::updatePacketsTest() { comBuff.resetSer(); ASSERT_EQ(Fw::FW_SERIALIZE_OK, - comBuff.serialize(static_cast(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM))); + comBuff.serialize(static_cast(Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(8))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(ts)); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(1000))); @@ -439,7 +439,7 @@ void TlmPacketizerTester ::updatePacketsTest() { comBuff.resetSer(); ASSERT_EQ(Fw::FW_SERIALIZE_OK, - comBuff.serialize(static_cast(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM))); + comBuff.serialize(static_cast(Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(4))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(ts)); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(1000))); @@ -460,7 +460,7 @@ void TlmPacketizerTester ::updatePacketsTest() { comBuff.resetSer(); ASSERT_EQ(Fw::FW_SERIALIZE_OK, - comBuff.serialize(static_cast(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM))); + comBuff.serialize(static_cast(Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(4))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(ts)); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(1000))); @@ -481,7 +481,7 @@ void TlmPacketizerTester ::updatePacketsTest() { comBuff.resetSer(); ASSERT_EQ(Fw::FW_SERIALIZE_OK, - comBuff.serialize(static_cast(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM))); + comBuff.serialize(static_cast(Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(8))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(ts)); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(1000))); @@ -503,7 +503,7 @@ void TlmPacketizerTester ::updatePacketsTest() { comBuff.resetSer(); ASSERT_EQ(Fw::FW_SERIALIZE_OK, - comBuff.serialize(static_cast(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM))); + comBuff.serialize(static_cast(Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(8))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(ts)); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(1000))); @@ -525,7 +525,7 @@ void TlmPacketizerTester ::updatePacketsTest() { comBuff.resetSer(); ASSERT_EQ(Fw::FW_SERIALIZE_OK, - comBuff.serialize(static_cast(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM))); + comBuff.serialize(static_cast(Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(8))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(ts)); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(1000))); @@ -564,7 +564,7 @@ void TlmPacketizerTester ::ignoreTest() { comBuff.resetSer(); ASSERT_EQ(Fw::FW_SERIALIZE_OK, - comBuff.serialize(static_cast(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM))); + comBuff.serialize(static_cast(Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(4))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(ts)); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(20))); @@ -575,7 +575,7 @@ void TlmPacketizerTester ::ignoreTest() { comBuff.resetSer(); ASSERT_EQ(Fw::FW_SERIALIZE_OK, - comBuff.serialize(static_cast(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM))); + comBuff.serialize(static_cast(Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(8))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(ts)); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(20))); @@ -648,7 +648,7 @@ void TlmPacketizerTester ::sendManualPacketTest() { Fw::ComBuffer comBuff1; ASSERT_EQ(Fw::FW_SERIALIZE_OK, - comBuff1.serialize(static_cast(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM))); + comBuff1.serialize(static_cast(Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff1.serialize(static_cast(4))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff1.serialize(this->m_testTime)); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff1.serialize(static_cast(20))); @@ -659,7 +659,7 @@ void TlmPacketizerTester ::sendManualPacketTest() { Fw::ComBuffer comBuff2; ASSERT_EQ(Fw::FW_SERIALIZE_OK, - comBuff2.serialize(static_cast(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM))); + comBuff2.serialize(static_cast(Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff2.serialize(static_cast(8))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff2.serialize(this->m_testTime)); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff2.serialize(static_cast(20))); @@ -820,7 +820,7 @@ void TlmPacketizerTester ::setPacketLevelTest() { Fw::ComBuffer comBuff1; ASSERT_EQ(Fw::FW_SERIALIZE_OK, - comBuff1.serialize(static_cast(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM))); + comBuff1.serialize(static_cast(Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff1.serialize(static_cast(4))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff1.serialize(this->m_testTime)); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff1.serialize(static_cast(0x20))); @@ -838,7 +838,7 @@ void TlmPacketizerTester ::setPacketLevelTest() { Fw::ComBuffer comBuff; ASSERT_EQ(Fw::FW_SERIALIZE_OK, - comBuff.serialize(static_cast(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM))); + comBuff.serialize(static_cast(Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(4))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(this->m_testTime)); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(20))); @@ -849,7 +849,7 @@ void TlmPacketizerTester ::setPacketLevelTest() { comBuff.resetSer(); ASSERT_EQ(Fw::FW_SERIALIZE_OK, - comBuff.serialize(static_cast(Fw::ComPacket::FW_PACKET_PACKETIZED_TLM))); + comBuff.serialize(static_cast(Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(8))); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(this->m_testTime)); ASSERT_EQ(Fw::FW_SERIALIZE_OK, comBuff.serialize(static_cast(20))); diff --git a/default/config/ComCfg.fpp b/default/config/ComCfg.fpp index 4817341f97f..cddaf18533a 100644 --- a/default/config/ComCfg.fpp +++ b/default/config/ComCfg.fpp @@ -13,16 +13,20 @@ module ComCfg { @ APIDs are 11 bits in the Space Packet protocol, so we use U16. Max value 7FF enum APID : U16 { + # APIDs prefixed with FW are reserved for F Prime and should not be changed FW_PACKET_COMMAND = 0x0000 @< Command packet type - incoming FW_PACKET_TELEM = 0x0001 @< Telemetry packet type - outgoing FW_PACKET_LOG = 0x0002 @< Log type - outgoing FW_PACKET_FILE = 0x0003 @< File type - incoming and outgoing FW_PACKET_PACKETIZED_TLM = 0x0004 @< Packetized telemetry packet type - FW_PACKET_IDLE = 0x0005 @< F Prime idle - FW_PACKET_HAND = 0xFE @< F Prime handshake - FW_PACKET_UNKNOWN = 0xFF @< F Prime unknown packet - IDLE_PACKET = 0x7FF @< Per Space Packet Standard, all 1s (11bits) is reserved for Idle Packets - } + FW_PACKET_DP = 0x0005 @< Data Product packet type + FW_PACKET_IDLE = 0x0006 @< F Prime idle + FW_PACKET_HAND = 0x00FE @< F Prime handshake + FW_PACKET_UNKNOWN = 0x00FF @< F Prime unknown packet + # SPP_FILE_UPLINK = 0x0101 @< APID for File packets on uplink + SPP_FILE_DOWNLINK = 0x0103 @< Extra APID for File packets on downlink so APID isn't shared between uplink and downlink + SPP_IDLE_PACKET = 0x07FF @< Per Space Packet Standard, all 1s (11bits) is reserved for Idle Packets + } default FW_PACKET_UNKNOWN @ Type used to pass context info between components during framing/deframing struct FrameContext { From 8c3ddbaa0fe45dd4db6530bfdc00ab5500ca1a62 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 21 May 2025 17:37:09 -0700 Subject: [PATCH 38/95] Map FW_PACKET_FILE to downlink specific APID --- Svc/CCSDS/ApidMapper/ApidMapper.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Svc/CCSDS/ApidMapper/ApidMapper.cpp b/Svc/CCSDS/ApidMapper/ApidMapper.cpp index 714f49a3710..bb001a5a5ca 100644 --- a/Svc/CCSDS/ApidMapper/ApidMapper.cpp +++ b/Svc/CCSDS/ApidMapper/ApidMapper.cpp @@ -44,9 +44,17 @@ void ApidMapper ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const Co FwPacketDescriptorType descriptorValue = 0; Fw::SerializeStatus status = deserializer.deserialize(descriptorValue); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, static_cast(status)); + ComCfg::APID::T apid; + if (descriptorValue == ComCfg::APID::FW_PACKET_FILE) { + // If descriptor is a file packet, set APID to the file downlink APID + // This is because we don't want to use FW_PACKET_FILE as the APID so + // the APID isn't shared between uplink and downlink + apid = ComCfg::APID::SPP_FILE_DOWNLINK; + } else { + // Else, map one-to-one: Descriptor value is APID value + apid = static_cast(descriptorValue); + } - // Mapping one-to-one: Descriptor value is APID value - ComCfg::APID::T apid = static_cast(descriptorValue); contextCopy.setapid(static_cast(apid)); contextCopy.setsequenceCount(this->getAndIncrementSeqCount(static_cast(apid))); // printf("APID: %d, SeqCount: %d\n", apid, contextCopy.getsequenceCount()); From a4b9ccc5e59dd09cedcecbe2c78a8c9f398f3583 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 21 May 2025 17:37:50 -0700 Subject: [PATCH 39/95] Remove sequence number check --- Svc/CCSDS/TCDeframer/TCDeframer.cpp | 11 +++-------- Svc/CCSDS/TCDeframer/TCDeframer.fpp | 5 ----- Svc/CCSDS/TCDeframer/TCDeframer.hpp | 2 +- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.cpp b/Svc/CCSDS/TCDeframer/TCDeframer.cpp index 3851dcf617d..165cfe92031 100644 --- a/Svc/CCSDS/TCDeframer/TCDeframer.cpp +++ b/Svc/CCSDS/TCDeframer/TCDeframer.cpp @@ -33,9 +33,10 @@ void TCDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const Co // 5 octets - TC Primary Header // Up to 1019 octets - Data Field (including optional 2 octets frame error control field) + // Note: F Prime uses Type-BD // CCSDS TC Primary Header: // 2b - 00 - TF Version Number - // 1b - 0/1 - Bypass Flag (0 = FARM checks enabled, 1 = FARM checks bypassed) + // 1b - 0/1 - Bypass Flag (0 = Type-A FARM checks enabled, 1 = Type-B FARM checks bypassed) // 1b - 0/1 - Control Command Flag (0 = Type-D data, 1 = Type-C control command) // 2b - 00 - Reserved Spare (set to 00) // 10b- XX - Spacecraft ID @@ -55,7 +56,6 @@ void TCDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const Co U16 frame_length = header.getvcIdAndLength() & TCFrameMasks::FrameLengthMask; U8 vc_id = (header.getvcIdAndLength() & TCFrameMasks::VcIdMask) >> TCFrameMasks::VcIdOffset; U16 spacecraft_id = header.getflagsAndScId() & TCFrameMasks::SpacecraftIdMask; - U8 sequence_number = header.getframeSequenceNbr(); if (spacecraft_id != this->m_spacecraftId) { this->log_ACTIVITY_LO_InvalidSpacecraftId(spacecraft_id, this->m_spacecraftId); @@ -73,12 +73,7 @@ void TCDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const Co this->dataReturnOut_out(0, data, context); // drop the frame return; } - if (sequence_number != this->m_sequenceCount) { - this->log_WARNING_HI_UnexpectedSequenceNumber(sequence_number, this->m_sequenceCount); - // Synchronize onboard count with received number so that count can keep going - this->m_sequenceCount = sequence_number; - } - this->m_sequenceCount++; // increment count for next frame + // Note: F Prime uses TC Type-BD frames for now, so the FARM checks are not ran (meaning no sequence count checks) // ------------------------------------------------- // CRC Check diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.fpp b/Svc/CCSDS/TCDeframer/TCDeframer.fpp index 4b13a5acf9a..43adb63cf51 100644 --- a/Svc/CCSDS/TCDeframer/TCDeframer.fpp +++ b/Svc/CCSDS/TCDeframer/TCDeframer.fpp @@ -25,11 +25,6 @@ module CCSDS { severity warning high \ format "Invalid checksum received. Trailer specified: {} | Computed on board: {}" - @ Deframing received an unexpected sequence number - event UnexpectedSequenceNumber(transmitted: U16, expected: U16) \ - severity warning high \ - format "Invalid sequence number received. Frames may have been lost. Transmitted: {} | Expected on board: {}" - ############################################################################### # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # ############################################################################### diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.hpp b/Svc/CCSDS/TCDeframer/TCDeframer.hpp index 5385ae79211..b86792f6265 100644 --- a/Svc/CCSDS/TCDeframer/TCDeframer.hpp +++ b/Svc/CCSDS/TCDeframer/TCDeframer.hpp @@ -65,7 +65,7 @@ class TCDeframer : public TCDeframerComponentBase { U16 m_vcId; //!< The virtual channel ID this deframer is configured to handle U16 m_spacecraftId; //!< The spacecraft ID this deframer is configured to handle bool m_acceptAllVcid = true; //!< Flag to accept all VCIDs - U8 m_sequenceCount = 0; //! Counter tracking the next expected frame count + }; } // namespace CCSDS } // namespace Svc From 3a5321c246cceb13833ec7e3a42ed3a592268a05 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 21 May 2025 18:46:03 -0700 Subject: [PATCH 40/95] Add packet loss notification to space packet --- Svc/CCSDS/ApidMapper/ApidMapper.cpp | 5 ++ Svc/CCSDS/ApidMapper/ApidMapper.hpp | 4 +- .../SpacePacketDeframer.cpp | 53 +++++++++++++++++-- .../SpacePacketDeframer.fpp | 10 ++++ .../SpacePacketDeframer.hpp | 27 +++++++++- default/config/ComCfg.fpp | 2 +- 6 files changed, 93 insertions(+), 8 deletions(-) diff --git a/Svc/CCSDS/ApidMapper/ApidMapper.cpp b/Svc/CCSDS/ApidMapper/ApidMapper.cpp index bb001a5a5ca..ce11c98db6f 100644 --- a/Svc/CCSDS/ApidMapper/ApidMapper.cpp +++ b/Svc/CCSDS/ApidMapper/ApidMapper.cpp @@ -21,6 +21,8 @@ ApidMapper ::ApidMapper(const char* const compName) : ApidMapperComponentBase(co this->m_apidSequences[2].apid = ComCfg::APID::FW_PACKET_FILE; this->m_apidSequences[3].apid = ComCfg::APID::FW_PACKET_PACKETIZED_TLM; this->m_apidSequences[4].apid = ComCfg::APID::FW_PACKET_UNKNOWN; + // TODO: Why does it work without specifying the downlink file APID ? + // and add DP ?? } @@ -67,6 +69,9 @@ void ApidMapper ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& data, co this->dataReturnOut_out(portNum, data, context); } +// ---------------------------------------------------------------------- +// Helpers +// ---------------------------------------------------------------------- U16 ApidMapper ::getAndIncrementSeqCount(ComCfg::APID::T apid) { for (U8 i = 0; i < MAX_TRACKED_APIDS; ++i) { diff --git a/Svc/CCSDS/ApidMapper/ApidMapper.hpp b/Svc/CCSDS/ApidMapper/ApidMapper.hpp index b8a51de2de5..709565d77e1 100644 --- a/Svc/CCSDS/ApidMapper/ApidMapper.hpp +++ b/Svc/CCSDS/ApidMapper/ApidMapper.hpp @@ -14,6 +14,9 @@ namespace Svc { namespace CCSDS { class ApidMapper final : public ApidMapperComponentBase { + + static constexpr U8 MAX_TRACKED_APIDS = 5; + public: // ---------------------------------------------------------------------- // Component construction and destruction @@ -71,7 +74,6 @@ class ApidMapper final : public ApidMapperComponentBase { // ---------------------------------------------------------------------- // Member variables // ---------------------------------------------------------------------- - static const U8 MAX_TRACKED_APIDS = 5; ApidSequenceEntry m_apidSequences[MAX_TRACKED_APIDS]; }; diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp index 410c1890902..59187583079 100644 --- a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp @@ -5,8 +5,8 @@ // ====================================================================== #include "Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp" -#include "Svc/CCSDS/Types/SpacePacketHeaderSerializableAc.hpp" #include "Svc/CCSDS/Types/FppConstantsAc.hpp" +#include "Svc/CCSDS/Types/SpacePacketHeaderSerializableAc.hpp" namespace Svc { @@ -16,7 +16,13 @@ namespace CCSDS { // Component construction and destruction // ---------------------------------------------------------------------- -SpacePacketDeframer ::SpacePacketDeframer(const char* const compName) : SpacePacketDeframerComponentBase(compName) {} +SpacePacketDeframer ::SpacePacketDeframer(const char* const compName) : SpacePacketDeframerComponentBase(compName) { + // Initialize the APID sequence table with APID values that need to be counted (order does not matter) + this->m_apidSequences[0].apid = ComCfg::APID::FW_PACKET_COMMAND; + this->m_apidSequences[2].apid = ComCfg::APID::FW_PACKET_FILE; + this->m_apidSequences[3].apid = ComCfg::APID::FW_PACKET_PACKETIZED_TLM; + this->m_apidSequences[4].apid = ComCfg::APID::FW_PACKET_UNKNOWN; +} SpacePacketDeframer ::~SpacePacketDeframer() {} @@ -46,12 +52,25 @@ void SpacePacketDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, Fw::SerializeStatus status = data.getDeserializer().deserialize(header); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); - U16 apid = header.getpacketIdentification() & SpacePacketMasks::ApidMask; + U16 apidValue = header.getpacketIdentification() & SpacePacketMasks::ApidMask; + ComCfg::APID::T apid = static_cast(apidValue); ComCfg::FrameContext contextCopy = context; - contextCopy.setapid(static_cast(apid)); + contextCopy.setapid(apid); - // TODO: Add checks and events in case of failure U16 pkt_length = header.getpacketDataLength(); + if (pkt_length > data.getSize()) { + this->log_WARNING_HI_InvalidLength(pkt_length, data.getSize()); + this->dataReturnOut_out(0, data, context); // Drop the packet + return; + } + U16 receivedSequenceCount = header.getpacketSequenceControl() & SpacePacketMasks::SeqCountMask; + U16 expectedSequenceCount = this->getAndIncrementSeqCount(apid); + if (receivedSequenceCount != expectedSequenceCount) { + // Likely a packet was dropped or out of order + this->log_WARNING_HI_UnexpectedSequenceCount(receivedSequenceCount, expectedSequenceCount); + // Synchronize onboard count with received number so that count can keep going + this->setNextSeqCount(apid, receivedSequenceCount); + } // Set data buffer to be of the encapsulated data: HEADER (6 bytes) | PACKET DATA data.setData(data.getData() + SpacePacketHeader::SERIALIZED_SIZE); @@ -66,6 +85,30 @@ void SpacePacketDeframer ::dataReturnIn_handler(FwIndexType portNum, this->dataReturnOut_out(0, data, context); } +// ---------------------------------------------------------------------- +// Helpers +// ---------------------------------------------------------------------- + +U16 SpacePacketDeframer::getAndIncrementSeqCount(ComCfg::APID::T apid) { + for (U8 i = 0; i < MAX_TRACKED_APIDS; ++i) { + if (m_apidSequences[i].apid == apid) { + U16 seq = m_apidSequences[i].sequenceCount; + m_apidSequences[i].sequenceCount = (seq + 1) % (1 << 14); // Wrap around at 14 bits + printf("APID: %d, SeqCount: %d\n", apid, seq); + return seq; + } + } + return std::numeric_limits::max(); // error value +} + +void SpacePacketDeframer::setNextSeqCount(ComCfg::APID::T apid, U16 seqCount) { + for (U8 i = 0; i < MAX_TRACKED_APIDS; i++) { + if (m_apidSequences[i].apid == apid) { + m_apidSequences[i].sequenceCount = seqCount; + return; + } + } +} } // namespace CCSDS } // namespace Svc diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp index d725e6d079a..02956b89ac2 100644 --- a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp @@ -5,6 +5,16 @@ module CCSDS { include "../../Interfaces/DeframerInterface.fppi" + @ Deframing received an invalid frame length + event InvalidLength(transmitted: U16, actual: U32) \ + severity warning high \ + format "Invalid length received. Header specified packet length of {} | Actual received data length: {}" + + @ Deframing received an unexpected sequence count + event UnexpectedSequenceCount(transmitted: U16, expected: U16) \ + severity warning high \ + format "Unexpected sequence count received. Packets may have been lost. Transmitted: {} | Expected on board: {}" + ############################################################################### # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # ############################################################################### diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp index 9d11be666e4..b2c6e5b072e 100644 --- a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp @@ -14,7 +14,10 @@ namespace Svc { namespace CCSDS { class SpacePacketDeframer final : public SpacePacketDeframerComponentBase { - public: + + static constexpr U8 MAX_TRACKED_APIDS = 5; + + public: // ---------------------------------------------------------------------- // Component construction and destruction // ---------------------------------------------------------------------- @@ -44,6 +47,28 @@ class SpacePacketDeframer final : public SpacePacketDeframerComponentBase { void dataReturnIn_handler(FwIndexType portNum, //!< The port number Fw::Buffer& data, const ComCfg::FrameContext& context) override; + + private: + // ---------------------------------------------------------------------- + // Helpers + // ---------------------------------------------------------------------- + //! Get the sequence count for a given APID and increment it for the next + //! Wraps around at 14 bits + U16 getAndIncrementSeqCount(ComCfg::APID::T apid); + + void setNextSeqCount(ComCfg::APID::T apid, U16 seqCount); + + //! This struct helps track sequence counts per APID + struct ApidSequenceEntry { + ComCfg::APID::T apid = ComCfg::APID::FW_PACKET_UNKNOWN; + U16 sequenceCount; + }; + + private: + // ---------------------------------------------------------------------- + // Member variables + // ---------------------------------------------------------------------- + ApidSequenceEntry m_apidSequences[MAX_TRACKED_APIDS]; }; } // namespace CCSDS diff --git a/default/config/ComCfg.fpp b/default/config/ComCfg.fpp index cddaf18533a..06576b26bea 100644 --- a/default/config/ComCfg.fpp +++ b/default/config/ComCfg.fpp @@ -8,7 +8,7 @@ module ComCfg { - constant SpacecraftId = 0x03FF # Spacecraft ID (10 bits) + constant SpacecraftId = 0x0044 # Spacecraft ID (10 bits) constant TmFrameFixedSize = 1024 # Needs to be at least COM_BUFFER_MAX_SIZE + (2 * SpacePacketHeaderSize) + 1 @ APIDs are 11 bits in the Space Packet protocol, so we use U16. Max value 7FF From 1f1fe5e3cc902731535371bd5fb76027a261edee Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 21 May 2025 19:04:31 -0700 Subject: [PATCH 41/95] Tests WIP --- Svc/CCSDS/SpacePacketDeframer/CMakeLists.txt | 23 +++--- .../test/ut/SpacePacketDeframerTestMain.cpp | 22 ++++++ .../test/ut/SpacePacketDeframerTester.cpp | 63 ++++++++++++++++ .../test/ut/SpacePacketDeframerTester.hpp | 72 +++++++++++++++++++ 4 files changed, 170 insertions(+), 10 deletions(-) create mode 100644 Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTestMain.cpp create mode 100644 Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp create mode 100644 Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.hpp diff --git a/Svc/CCSDS/SpacePacketDeframer/CMakeLists.txt b/Svc/CCSDS/SpacePacketDeframer/CMakeLists.txt index b35e23e6814..872f25f02dc 100644 --- a/Svc/CCSDS/SpacePacketDeframer/CMakeLists.txt +++ b/Svc/CCSDS/SpacePacketDeframer/CMakeLists.txt @@ -21,13 +21,16 @@ register_fprime_library( ### Unit Tests ### -# set(UT_SOURCE_FILES -# "${CMAKE_CURRENT_LIST_DIR}/SpacePacketDeframer.fpp" -# "${CMAKE_CURRENT_LIST_DIR}/test/ut/SpacePacketDeframerTestMain.cpp" -# "${CMAKE_CURRENT_LIST_DIR}/test/ut/SpacePacketDeframerTester.cpp" -# ) -# set(UT_MOD_DEPS -# STest -# ) -# set(UT_AUTO_HELPERS ON) -# register_fprime_ut() +set(UT_AUTO_HELPERS ON) + +register_fprime_ut( + SOURCES + "${CMAKE_CURRENT_LIST_DIR}/test/ut/SpacePacketDeframerTestMain.cpp" + "${CMAKE_CURRENT_LIST_DIR}/test/ut/SpacePacketDeframerTester.cpp" + AUTOCODER_INPUTS + "${CMAKE_CURRENT_LIST_DIR}/SpacePacketDeframer.fpp" + DEPENDS + Svc_CCSDS_Types + STest +) + diff --git a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTestMain.cpp b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTestMain.cpp new file mode 100644 index 00000000000..cfc0e01c408 --- /dev/null +++ b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTestMain.cpp @@ -0,0 +1,22 @@ +// ====================================================================== +// \title SpacePacketDeframerTestMain.cpp +// \author chammard +// \brief cpp file for SpacePacketDeframer component test main function +// ====================================================================== + +#include "SpacePacketDeframerTester.hpp" + +TEST(Nominal, testDataReturnPassthrough) { + Svc::CCSDS::SpacePacketDeframerTester tester; + tester.testDataReturnPassthrough(); +} + +TEST(Nominal, testNominalDeframing) { + Svc::CCSDS::SpacePacketDeframerTester tester; + tester.testNominalDeframing(); +} + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp new file mode 100644 index 00000000000..5addbd0e8e8 --- /dev/null +++ b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp @@ -0,0 +1,63 @@ +// ====================================================================== +// \title SpacePacketDeframerTester.cpp +// \author chammard +// \brief cpp file for SpacePacketDeframer component test harness implementation class +// ====================================================================== + +#include "SpacePacketDeframerTester.hpp" +#include "STest/Random/Random.hpp" + +namespace Svc { + +namespace CCSDS { + +// ---------------------------------------------------------------------- +// Construction and destruction +// ---------------------------------------------------------------------- + +SpacePacketDeframerTester ::SpacePacketDeframerTester() + : SpacePacketDeframerGTestBase("SpacePacketDeframerTester", SpacePacketDeframerTester::MAX_HISTORY_SIZE), + component("SpacePacketDeframer") { + this->initComponents(); + this->connectPorts(); +} + +SpacePacketDeframerTester ::~SpacePacketDeframerTester() {} + +// ---------------------------------------------------------------------- +// Tests +// ---------------------------------------------------------------------- + +void SpacePacketDeframerTester ::testDataReturnPassthrough() { + U8 data[1]; + Fw::Buffer buffer(data, sizeof(data)); + ComCfg::FrameContext nullContext; + this->invoke_to_dataReturnIn(0, buffer, nullContext); + ASSERT_from_dataReturnOut_SIZE(1); // incoming buffer should be deallocated + ASSERT_EQ(this->fromPortHistory_dataReturnOut->at(0).data.getData(), data); + ASSERT_EQ(this->fromPortHistory_dataReturnOut->at(0).data.getSize(), sizeof(data)); + ASSERT_EQ(this->fromPortHistory_dataReturnOut->at(0).context, nullContext); +} + +void SpacePacketDeframerTester ::testNominalDeframing() { + // // Frame: 5 bytes (header) + 1 byte (data) + 2 bytes (trailer) + // U16 scId = static_cast(STest::Random::lowerUpper(0, 0x3FF)); // random 10 bit Spacecraft ID + // U8 vcId = static_cast(STest::Random::lowerUpper(0, 0x3F)); // random 6 bit virtual channel ID + // U8 seqCount = static_cast(STest::Random::lowerUpper(0, 0xFF)); // random 8 bit sequence count + // U8 dataLength = static_cast(STest::Random::lowerUpper(1, 200)); // bytes of data, random length + // U8 data[dataLength]; + + // Fw::Buffer buffer = this->assembleFrameBuffer(data, dataLength, scId, vcId, seqCount); + // ComCfg::FrameContext nullContext; + + // this->setComponentState(scId, vcId, seqCount); + // this->invoke_to_dataIn(0, buffer, nullContext); + + // ASSERT_from_dataOut_SIZE(1); + // Fw::Buffer outBuffer = this->fromPortHistory_dataOut->at(0).data; + // ASSERT_EQ(outBuffer.getSize(), dataLength); +} + + +} // namespace CCSDS +} // namespace Svc diff --git a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.hpp b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.hpp new file mode 100644 index 00000000000..05cc43f9fcd --- /dev/null +++ b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.hpp @@ -0,0 +1,72 @@ +// ====================================================================== +// \title SpacePacketDeframerTester.hpp +// \author chammard +// \brief hpp file for SpacePacketDeframer component test harness implementation class +// ====================================================================== + +#ifndef Svc_CCSDS_SpacePacketDeframerTester_HPP +#define Svc_CCSDS_SpacePacketDeframerTester_HPP + +#include "Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp" +#include "Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframerGTestBase.hpp" + +namespace Svc { + +namespace CCSDS { + +class SpacePacketDeframerTester final : public SpacePacketDeframerGTestBase { + public: + // ---------------------------------------------------------------------- + // Constants + // ---------------------------------------------------------------------- + + // Maximum size of histories storing events, telemetry, and port outputs + static const FwSizeType MAX_HISTORY_SIZE = 10; + + // Instance ID supplied to the component instance under test + static const FwEnumStoreType TEST_INSTANCE_ID = 0; + + public: + // ---------------------------------------------------------------------- + // Construction and destruction + // ---------------------------------------------------------------------- + + //! Construct object SpacePacketDeframerTester + SpacePacketDeframerTester(); + + //! Destroy object SpacePacketDeframerTester + ~SpacePacketDeframerTester(); + + public: + // ---------------------------------------------------------------------- + // Tests + // ---------------------------------------------------------------------- + + void testDataReturnPassthrough(); + void testNominalDeframing(); + + private: + // ---------------------------------------------------------------------- + // Helper functions + // ---------------------------------------------------------------------- + + //! Connect ports + void connectPorts(); + + //! Initialize components + void initComponents(); + + private: + // ---------------------------------------------------------------------- + // Member variables + // ---------------------------------------------------------------------- + + //! The component under test + SpacePacketDeframer component; +}; + +} // namespace CCSDS + +} // namespace Svc + +#endif From 027afb88e06439ca87db5875fb66ea7fd5300a51 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 21 May 2025 19:04:48 -0700 Subject: [PATCH 42/95] WIP --- .../SpacePacketFramer/SpacePacketFramer.cpp | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp index 8faa9b7a015..5cdd524c6e1 100644 --- a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp +++ b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp @@ -80,5 +80,38 @@ void SpacePacketFramer ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& f this->bufferDeallocate_out(0, frameBuffer); } +// TODO: use below +// Aspirational: use this structure for everything, and put it into Utils package!! so other users can use it... ??? +// void SpacePacketFramer ::assemblePacketIntoBuffer(Fw::Buffer targetBuffer, ComCfg::APID::T apid, U16 sequenceCount, Fw::Buffer packetData) { +// SpacePacketHeader header; +// Fw::SerializeStatus status; +// auto frameSerializer = targetBuffer.getSerializer(); + +// // ----------------------------------------------- +// // Header +// // ----------------------------------------------- +// // PVN is always 0 per Standard - Packet Type is 0 for Telemetry (downlink) - SecHdr flag is 0 for no secondary header +// U16 packetIdentification = 0; +// packetIdentification |= static_cast(apid) & SpacePacketMasks::ApidMask; // 11 bit APID + +// U16 packetSequenceControl = 0; +// packetSequenceControl |= 0x3 << SpacePacketMasks::SeqFlagsOffset; // Sequence Flags 0b11 = unsegmented User Data +// // TODO: Add assert that it indeed fits in 14 bits ?? +// packetSequenceControl |= sequenceCount & SpacePacketMasks::SeqCountMask; // 14 bit sequence count +// header.setpacketIdentification(packetIdentification); +// header.setpacketSequenceControl(packetSequenceControl); +// U16 packetDataLength = static_cast(packetData.getSize() - 1); // Standard specifies length is number of bytes minus 1 +// header.setpacketDataLength(packetDataLength); + +// // ----------------------------------------------- +// // Serialize the packet +// // ----------------------------------------------- +// status = frameSerializer.serialize(header); +// FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); +// status = frameSerializer.serialize(packetData.getData(), packetData.getSize(), Fw::Serialization::OMIT_LENGTH); +// FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); +// } + + } // namespace CCSDS } // namespace Svc From 1ac783debd076e2e9cde6674d2f4cdc2a89f8a4e Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Fri, 23 May 2025 11:29:36 -0700 Subject: [PATCH 43/95] Use SpacePacket header type in TMFramer idle packet --- Ref/Top/topology.fpp | 1 + Svc/CCSDS/ApidMapper/CMakeLists.txt | 2 +- Svc/CCSDS/SpacePacketDeframer/CMakeLists.txt | 5 +-- Svc/CCSDS/TCDeframer/CMakeLists.txt | 7 ++-- Svc/CCSDS/TMFramer/CMakeLists.txt | 9 ++--- Svc/CCSDS/TMFramer/TMFramer.cpp | 40 +++++++++++--------- Svc/CCSDS/TMFramer/TMFramer.hpp | 3 +- Svc/CCSDS/Types/CMakeLists.txt | 2 +- Svc/CCSDS/Utils/CMakeLists.txt | 2 +- Svc/FrameAccumulator/CMakeLists.txt | 1 + 10 files changed, 38 insertions(+), 34 deletions(-) diff --git a/Ref/Top/topology.fpp b/Ref/Top/topology.fpp index de52dcc55f7..e90e959e5eb 100644 --- a/Ref/Top/topology.fpp +++ b/Ref/Top/topology.fpp @@ -132,6 +132,7 @@ module Ref { comStub.comStatusOut -> tmFramer.comStatusIn tmFramer.comStatusOut -> spacePacketFramer.comStatusIn spacePacketFramer.comStatusOut -> comQueue.comStatusIn + # TODO: probably need comStatus to APIDMapper ?? } connections FaultProtection { diff --git a/Svc/CCSDS/ApidMapper/CMakeLists.txt b/Svc/CCSDS/ApidMapper/CMakeLists.txt index 3e06472f34a..fb778ee1cfd 100644 --- a/Svc/CCSDS/ApidMapper/CMakeLists.txt +++ b/Svc/CCSDS/ApidMapper/CMakeLists.txt @@ -6,7 +6,7 @@ # DEPENDS: list of libraries that this module depends on # # More information in the F´ CMake API documentation: -# https://fprime.jpl.nasa.gov/latest/documentation/reference +# https://fprime.jpl.nasa.gov/devel/docs/reference/api/cmake/API/ # #### diff --git a/Svc/CCSDS/SpacePacketDeframer/CMakeLists.txt b/Svc/CCSDS/SpacePacketDeframer/CMakeLists.txt index 872f25f02dc..7512009983b 100644 --- a/Svc/CCSDS/SpacePacketDeframer/CMakeLists.txt +++ b/Svc/CCSDS/SpacePacketDeframer/CMakeLists.txt @@ -6,7 +6,7 @@ # DEPENDS: list of libraries that this module depends on # # More information in the F´ CMake API documentation: -# https://fprime.jpl.nasa.gov/latest/documentation/reference +# https://fprime.jpl.nasa.gov/devel/docs/reference/api/cmake/API/ # #### @@ -21,8 +21,6 @@ register_fprime_library( ### Unit Tests ### -set(UT_AUTO_HELPERS ON) - register_fprime_ut( SOURCES "${CMAKE_CURRENT_LIST_DIR}/test/ut/SpacePacketDeframerTestMain.cpp" @@ -32,5 +30,6 @@ register_fprime_ut( DEPENDS Svc_CCSDS_Types STest + UT_AUTO_HELPERS ) diff --git a/Svc/CCSDS/TCDeframer/CMakeLists.txt b/Svc/CCSDS/TCDeframer/CMakeLists.txt index a7ea1a7b48a..22daab7cf44 100644 --- a/Svc/CCSDS/TCDeframer/CMakeLists.txt +++ b/Svc/CCSDS/TCDeframer/CMakeLists.txt @@ -6,7 +6,7 @@ # DEPENDS: list of libraries that this module depends on # # More information in the F´ CMake API documentation: -# https://fprime.jpl.nasa.gov/latest/documentation/reference +# https://fprime.jpl.nasa.gov/devel/docs/reference/api/cmake/API/ # #### @@ -19,8 +19,6 @@ register_fprime_library( Svc_CCSDS_Types ) -set(UT_AUTO_HELPERS ON) - register_fprime_ut( SOURCES "${CMAKE_CURRENT_LIST_DIR}/test/ut/TCDeframerTestMain.cpp" @@ -30,4 +28,5 @@ register_fprime_ut( DEPENDS Svc_CCSDS_Types STest -) \ No newline at end of file + UT_AUTO_HELPERS +) diff --git a/Svc/CCSDS/TMFramer/CMakeLists.txt b/Svc/CCSDS/TMFramer/CMakeLists.txt index 231b11416b8..b716cb123f9 100644 --- a/Svc/CCSDS/TMFramer/CMakeLists.txt +++ b/Svc/CCSDS/TMFramer/CMakeLists.txt @@ -1,26 +1,24 @@ #### -# FPrime CMakeLists.txt: +# F Prime CMakeLists.txt: # # SOURCES: list of source files (to be compiled) # AUTOCODER_INPUTS: list of files to be passed to the autocoders # DEPENDS: list of libraries that this module depends on # # More information in the F´ CMake API documentation: -# https://fprime.jpl.nasa.gov/latest/documentation/reference +# https://fprime.jpl.nasa.gov/devel/docs/reference/api/cmake/API/ # #### register_fprime_library( SOURCES "${CMAKE_CURRENT_LIST_DIR}/TMFramer.cpp" - AUTOCODER_INPUTS + AUTOCODER_INPUTS "${CMAKE_CURRENT_LIST_DIR}/TMFramer.fpp" DEPENDS Svc_CCSDS_Types ) -set(UT_AUTO_HELPERS ON) - register_fprime_ut( SOURCES "${CMAKE_CURRENT_LIST_DIR}/test/ut/TMFramerTestMain.cpp" @@ -30,4 +28,5 @@ register_fprime_ut( DEPENDS Svc_CCSDS_Types STest + UT_AUTO_HELPERS ) diff --git a/Svc/CCSDS/TMFramer/TMFramer.cpp b/Svc/CCSDS/TMFramer/TMFramer.cpp index b17f8f45554..f81a8a6fb92 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.cpp +++ b/Svc/CCSDS/TMFramer/TMFramer.cpp @@ -10,6 +10,7 @@ #include "Svc/CCSDS/Types/TMFrameTrailerSerializableAc.hpp" #include "Svc/CCSDS/Utils/CRC16.hpp" #include "config/FppConstantsAc.hpp" +#include "Svc/CCSDS/Types/SpacePacketHeaderSerializableAc.hpp" namespace Svc { @@ -61,18 +62,18 @@ void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComC // ------------------------------------------------- // Data field // ------------------------------------------------- - + // Payload packet Fw::SerializeStatus status; // Create frame Fw::Buffer using member data field Fw::Buffer frameBuffer = Fw::Buffer(this->m_frameBuffer, sizeof(this->m_frameBuffer)); auto frameSerializer = frameBuffer.getSerializer(); - status = frameSerializer.serialize(header); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); status = frameSerializer.serialize(data.getData(), data.getSize(), Fw::Serialization::OMIT_LENGTH); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); - this->fill_with_idle_packet(static_cast(frameSerializer.getBuffLength())); + // As per TM Standard 4.2.2.5, fill the rest of the data field with an Idle Packet + this->fill_with_idle_packet(frameSerializer); // ------------------------------------------------- // Trailer (CRC) @@ -103,29 +104,32 @@ void TMFramer ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& frameBuffer, const ComCfg::FrameContext& context) { // dataReturnIn is our own member buffer coming back from the dataOut call - memset it to 0 + FW_ASSERT(frameBuffer.getData() == static_cast(this->m_frameBuffer)); ::memset(this->m_frameBuffer, 0, sizeof(this->m_frameBuffer)); - // NOTE: should I set a flag to track that it has been returned an ready for reuse? + // NOTE: should we set a flag to track that it has been returned and ready for reuse? + // NOTE: a nice trick for efficiency would be to memset to IDLE_DATA_PATTERN instead... but eh } -void TMFramer ::fill_with_idle_packet(U16 startIndex) { - // TODO: make this code cleaner - could request from SpacePacket ?? - U16 endIndex = ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize - +void TMFramer ::fill_with_idle_packet(Fw::SerializeBufferBase& serializer) { + constexpr U16 endIndex = ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize - TMFrameTrailer::SERIALIZED_SIZE; - U16 idlePacketLength = endIndex - startIndex; + constexpr U16 idleApid = static_cast(ComCfg::APID::SPP_IDLE_PACKET); + const U16 startIndex = static_cast(serializer.getBuffLength()); + const U16 idlePacketLength = endIndex - startIndex; + FW_ASSERT(idlePacketLength > 0, static_cast(idlePacketLength)); FW_ASSERT(idlePacketLength >= 7, static_cast(idlePacketLength)); // 7 bytes minimum for idle packet FW_ASSERT(idlePacketLength <= ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize, static_cast(idlePacketLength)); - U16 idleApid = ComCfg::APID::SPP_IDLE_PACKET; // All 1s (11bit) per Space Packet protocol paragraph 4.1.3.3.4.4 - this->m_frameBuffer[startIndex + 0] = (idleApid >> 8) & 0xFF; - this->m_frameBuffer[startIndex + 1] = idleApid & 0xFF; - this->m_frameBuffer[startIndex + 2] = 0xC0; // Sequence Flags = 0b11 (unsegmented) & unused Seq count - this->m_frameBuffer[startIndex + 3] = 0x00; // unused Sequence Count - this->m_frameBuffer[startIndex + 4] = idlePacketLength >> 8; // Packet Data Length MSB - this->m_frameBuffer[startIndex + 5] = idlePacketLength & 0xFF; // Packet Data Length LSB - // Fill the rest of the buffer with arbitrary idle data - for (U16 i = startIndex + 6; i < endIndex; i++) { - this->m_frameBuffer[i] = IDLE_DATA_PATTERN; // Idle data + + SpacePacketHeader header; + header.setpacketIdentification(idleApid); + header.setpacketSequenceControl(0x3 << SpacePacketMasks::SeqFlagsOffset); // Sequence Flags = 0b11 (unsegmented) & unused Seq count + header.setpacketDataLength(idlePacketLength); + // Serialize header and idle data into the frame + serializer.serialize(header); + for (U16 i = startIndex + SpacePacketHeader::SERIALIZED_SIZE; i < endIndex; i++) { + serializer.serialize(IDLE_DATA_PATTERN); // Idle data } } diff --git a/Svc/CCSDS/TMFramer/TMFramer.hpp b/Svc/CCSDS/TMFramer/TMFramer.hpp index 2991b37560e..abc0304fd62 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.hpp +++ b/Svc/CCSDS/TMFramer/TMFramer.hpp @@ -68,7 +68,8 @@ class TMFramer final : public TMFramerComponentBase { //! Fill the frame buffer with an Idle Packet to complete the frame data field //! as per CCSDS TM Protocol paragraph 4.2.2.5. Idle packet is inserted at the //! start_index index of the frame buffer, and fills it up to the end minus CRC - void fill_with_idle_packet(U16 start_index); + // void fill_with_idle_packet(U16 start_index); + void fill_with_idle_packet(Fw::SerializeBufferBase& serializer); // Because the TM protocol use fixed width frames, and only one frame is in transit between ComQueue and // ComInterface at a time, we can use a member fixed-size buffer to hold the frame data diff --git a/Svc/CCSDS/Types/CMakeLists.txt b/Svc/CCSDS/Types/CMakeLists.txt index d7001e1b994..3299b0b31ec 100644 --- a/Svc/CCSDS/Types/CMakeLists.txt +++ b/Svc/CCSDS/Types/CMakeLists.txt @@ -6,7 +6,7 @@ # DEPENDS: list of libraries that this module depends on # # More information in the F´ CMake API documentation: -# https://fprime.jpl.nasa.gov/latest/documentation/reference +# https://fprime.jpl.nasa.gov/devel/docs/reference/api/cmake/API/ # #### diff --git a/Svc/CCSDS/Utils/CMakeLists.txt b/Svc/CCSDS/Utils/CMakeLists.txt index 3f40f0177db..f75175a5072 100644 --- a/Svc/CCSDS/Utils/CMakeLists.txt +++ b/Svc/CCSDS/Utils/CMakeLists.txt @@ -6,7 +6,7 @@ # DEPENDS: list of libraries that this module depends on # # More information in the F´ CMake API documentation: -# https://fprime.jpl.nasa.gov/latest/documentation/reference +# https://fprime.jpl.nasa.gov/devel/docs/reference/api/cmake/API/ # #### diff --git a/Svc/FrameAccumulator/CMakeLists.txt b/Svc/FrameAccumulator/CMakeLists.txt index 8966a20207a..c97305b38a3 100644 --- a/Svc/FrameAccumulator/CMakeLists.txt +++ b/Svc/FrameAccumulator/CMakeLists.txt @@ -16,6 +16,7 @@ set(SOURCE_FILES set(MOD_DEPS Utils/Types Svc/FprimeProtocol + Svc/CCSDS/Types ) register_fprime_module() From 5dfd6493c2d4019abbbd162afc9339c47a5dd4c2 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Fri, 23 May 2025 14:38:01 -0700 Subject: [PATCH 44/95] SpacePacketDeframer tests and untracked APID detection --- .../SpacePacketDeframer.cpp | 10 +- .../SpacePacketDeframer.fpp | 5 + .../SpacePacketDeframer.hpp | 2 + .../test/ut/SpacePacketDeframerTestMain.cpp | 10 ++ .../test/ut/SpacePacketDeframerTester.cpp | 121 +++++++++++++++--- .../test/ut/SpacePacketDeframerTester.hpp | 10 ++ .../SpacePacketFramer/SpacePacketFramer.cpp | 2 +- Svc/CCSDS/TMFramer/TMFramer.hpp | 1 - 8 files changed, 140 insertions(+), 21 deletions(-) diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp index 59187583079..ba83efc0f81 100644 --- a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp @@ -65,12 +65,16 @@ void SpacePacketDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, } U16 receivedSequenceCount = header.getpacketSequenceControl() & SpacePacketMasks::SeqCountMask; U16 expectedSequenceCount = this->getAndIncrementSeqCount(apid); - if (receivedSequenceCount != expectedSequenceCount) { + if (expectedSequenceCount == SEQUENCE_COUNT_ERROR) { + // This APID is not being tracked + this->log_ACTIVITY_LO_UntrackedApid(apidValue); + } else if (receivedSequenceCount != expectedSequenceCount) { // Likely a packet was dropped or out of order this->log_WARNING_HI_UnexpectedSequenceCount(receivedSequenceCount, expectedSequenceCount); // Synchronize onboard count with received number so that count can keep going - this->setNextSeqCount(apid, receivedSequenceCount); + this->setNextSeqCount(apid, receivedSequenceCount + 1); } + contextCopy.setsequenceCount(receivedSequenceCount); // Set data buffer to be of the encapsulated data: HEADER (6 bytes) | PACKET DATA data.setData(data.getData() + SpacePacketHeader::SERIALIZED_SIZE); @@ -98,7 +102,7 @@ U16 SpacePacketDeframer::getAndIncrementSeqCount(ComCfg::APID::T apid) { return seq; } } - return std::numeric_limits::max(); // error value + return SEQUENCE_COUNT_ERROR; // error value - this value is never returned with wraparound } void SpacePacketDeframer::setNextSeqCount(ComCfg::APID::T apid, U16 seqCount) { diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp index 02956b89ac2..83aefdc2ae9 100644 --- a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp @@ -15,6 +15,11 @@ module CCSDS { severity warning high \ format "Unexpected sequence count received. Packets may have been lost. Transmitted: {} | Expected on board: {}" + @ Deframing received an unexpected sequence count + event UntrackedApid(apid: U16) \ + severity activity low \ + format "Received APID not registered with the deframer. Not checking sequence count. APID={}" + ############################################################################### # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # ############################################################################### diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp index b2c6e5b072e..8602114bdb4 100644 --- a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp @@ -14,8 +14,10 @@ namespace Svc { namespace CCSDS { class SpacePacketDeframer final : public SpacePacketDeframerComponentBase { + friend class SpacePacketDeframerTester; static constexpr U8 MAX_TRACKED_APIDS = 5; + static constexpr U16 SEQUENCE_COUNT_ERROR = std::numeric_limits::max(); public: // ---------------------------------------------------------------------- diff --git a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTestMain.cpp b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTestMain.cpp index cfc0e01c408..d66a16f8b2d 100644 --- a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTestMain.cpp +++ b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTestMain.cpp @@ -16,6 +16,16 @@ TEST(Nominal, testNominalDeframing) { tester.testNominalDeframing(); } +TEST(Nominal, testDeframingUntrackedApid) { + Svc::CCSDS::SpacePacketDeframerTester tester; + tester.testDeframingUntrackedApid(); +} + +TEST(Nominal, testDeframingIncorrectSeqCount) { + Svc::CCSDS::SpacePacketDeframerTester tester; + tester.testDeframingIncorrectSeqCount(); +} + int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp index 5addbd0e8e8..12431af6b0e 100644 --- a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp +++ b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp @@ -6,6 +6,7 @@ #include "SpacePacketDeframerTester.hpp" #include "STest/Random/Random.hpp" +#include "Svc/CCSDS/Types/SpacePacketHeaderSerializableAc.hpp" namespace Svc { @@ -40,24 +41,112 @@ void SpacePacketDeframerTester ::testDataReturnPassthrough() { } void SpacePacketDeframerTester ::testNominalDeframing() { - // // Frame: 5 bytes (header) + 1 byte (data) + 2 bytes (trailer) - // U16 scId = static_cast(STest::Random::lowerUpper(0, 0x3FF)); // random 10 bit Spacecraft ID - // U8 vcId = static_cast(STest::Random::lowerUpper(0, 0x3F)); // random 6 bit virtual channel ID - // U8 seqCount = static_cast(STest::Random::lowerUpper(0, 0xFF)); // random 8 bit sequence count - // U8 dataLength = static_cast(STest::Random::lowerUpper(1, 200)); // bytes of data, random length - // U8 data[dataLength]; - - // Fw::Buffer buffer = this->assembleFrameBuffer(data, dataLength, scId, vcId, seqCount); - // ComCfg::FrameContext nullContext; - - // this->setComponentState(scId, vcId, seqCount); - // this->invoke_to_dataIn(0, buffer, nullContext); - - // ASSERT_from_dataOut_SIZE(1); - // Fw::Buffer outBuffer = this->fromPortHistory_dataOut->at(0).data; - // ASSERT_EQ(outBuffer.getSize(), dataLength); + ComCfg::APID::T apid = static_cast(STest::Random::lowerUpper(0, 0x7FF)); // random 11 bit APID + U16 seqCount = static_cast(STest::Random::lowerUpper(0, 0x3FFF)); // random 14 bit sequence count + U16 dataLength = static_cast(STest::Random::lowerUpper(1, MAX_TEST_PACKET_DATA_SIZE)); // bytes of data, random length + U8 data[dataLength]; + + Fw::Buffer buffer = this->assemblePacket(apid, seqCount, dataLength, data); + ComCfg::FrameContext nullContext; + + // Add the APID to the tracked APID list for nominal deframing + this->component.m_apidSequences[0].apid = apid; + this->component.m_apidSequences[0].sequenceCount = seqCount; + + this->invoke_to_dataIn(0, buffer, nullContext); + + // Check output packet payload + ASSERT_from_dataOut_SIZE(1); + Fw::Buffer outBuffer = this->fromPortHistory_dataOut->at(0).data; + ASSERT_EQ(outBuffer.getSize(), dataLength); + for (U32 i = 0; i < dataLength; ++i) { + ASSERT_EQ(outBuffer.getData()[i], data[i]); + } + // Check output context (header info) + ComCfg::FrameContext context = this->fromPortHistory_dataOut->at(0).context; + ASSERT_EQ(context.getapid(), apid); + ASSERT_EQ(context.getsequenceCount(), seqCount); + + ASSERT_EVENTS_SIZE(0); // No events should be generated in the nominal case +} + +void SpacePacketDeframerTester ::testDeframingUntrackedApid() { + U16 apid = 0x7FF - 2; // Unspecified APID + U16 seqCount = static_cast(STest::Random::lowerUpper(0, 0x3FFF)); // random 14 bit sequence count + U16 dataLength = static_cast(STest::Random::lowerUpper(1, MAX_TEST_PACKET_DATA_SIZE)); // bytes of data, random length + U8 data[dataLength]; + + Fw::Buffer buffer = this->assemblePacket(apid, seqCount, dataLength, data); + ComCfg::FrameContext nullContext; + + this->invoke_to_dataIn(0, buffer, nullContext); + + // Check output packet payload + ASSERT_from_dataOut_SIZE(1); + Fw::Buffer outBuffer = this->fromPortHistory_dataOut->at(0).data; + ASSERT_EQ(outBuffer.getSize(), dataLength); + for (U32 i = 0; i < dataLength; ++i) { + ASSERT_EQ(outBuffer.getData()[i], data[i]); + } + // Check output context (header info) + ComCfg::FrameContext outContext = this->fromPortHistory_dataOut->at(0).context; + ASSERT_EQ(outContext.getapid(), apid); + ASSERT_EQ(outContext.getsequenceCount(), seqCount); + // Check event logging that untracked APID was received + ASSERT_EVENTS_SIZE(1); + ASSERT_EVENTS_UntrackedApid_SIZE(1); } +void SpacePacketDeframerTester ::testDeframingIncorrectSeqCount() { + U16 apid = ComCfg::APID::FW_PACKET_COMMAND; + U16 dataLength = static_cast(STest::Random::lowerUpper(1, MAX_TEST_PACKET_DATA_SIZE)); // bytes of data, random length + U8 data[dataLength]; + U16 receivedSeqCount = static_cast(STest::Random::lowerUpper(1, 0x3FFF)); // random 14 bit sequence count + U16 expectedSeqCount = receivedSeqCount - 1; // effectively mocks a packet drop + + Fw::Buffer buffer = this->assemblePacket(apid, receivedSeqCount, dataLength, data); + ComCfg::FrameContext nullContext; + + // Add the APID to the tracked APID list for nominal deframing + this->component.m_apidSequences[0].apid = ComCfg::APID::FW_PACKET_COMMAND; + this->component.m_apidSequences[0].sequenceCount = expectedSeqCount; + + this->invoke_to_dataIn(0, buffer, nullContext); + + // Check output packet payload + ASSERT_from_dataOut_SIZE(1); + Fw::Buffer outBuffer = this->fromPortHistory_dataOut->at(0).data; + ASSERT_EQ(outBuffer.getSize(), dataLength); + for (U32 i = 0; i < dataLength; ++i) { + ASSERT_EQ(outBuffer.getData()[i], data[i]); + } + // Check output context (header info) + ComCfg::FrameContext outContext = this->fromPortHistory_dataOut->at(0).context; + ASSERT_EQ(outContext.getapid(), apid); + ASSERT_EQ(outContext.getsequenceCount(), receivedSeqCount); + // Check event logging that untracked APID was received + ASSERT_EVENTS_SIZE(1); + ASSERT_EVENTS_UnexpectedSequenceCount_SIZE(1); + ASSERT_EVENTS_UnexpectedSequenceCount(0, receivedSeqCount, expectedSeqCount); + // Check that the sequence count was updated to the next after the received one + ASSERT_EQ(this->component.m_apidSequences[0].sequenceCount, receivedSeqCount + 1); +} + +// ---------------------------------------------------------------------- +// Helper functions +// ---------------------------------------------------------------------- + +Fw::Buffer SpacePacketDeframerTester ::assemblePacket(U16 apid, U16 seqCount, U16 packetLength, U8* packetData) { + SpacePacketHeader header; + header.setpacketIdentification(apid); + header.setpacketSequenceControl(seqCount); // Sequence Flags = 0b11 (unsegmented) & unused Seq count + header.setpacketDataLength(packetLength); + + Fw::ExternalSerializeBuffer serializer(static_cast(this->m_packetBuffer), sizeof(this->m_packetBuffer)); + serializer.serialize(header); + serializer.serialize(packetData, packetLength, Fw::Serialization::OMIT_LENGTH); + return Fw::Buffer(this->m_packetBuffer, static_cast(sizeof(this->m_packetBuffer))); +} } // namespace CCSDS } // namespace Svc diff --git a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.hpp b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.hpp index 05cc43f9fcd..86a6a436ddc 100644 --- a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.hpp +++ b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.hpp @@ -8,6 +8,7 @@ #define Svc_CCSDS_SpacePacketDeframerTester_HPP #include "Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp" +#include "Svc/CCSDS/Types/SpacePacketHeaderSerializableAc.hpp" #include "Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframerGTestBase.hpp" namespace Svc { @@ -44,6 +45,8 @@ class SpacePacketDeframerTester final : public SpacePacketDeframerGTestBase { void testDataReturnPassthrough(); void testNominalDeframing(); + void testDeframingUntrackedApid(); + void testDeframingIncorrectSeqCount(); private: // ---------------------------------------------------------------------- @@ -56,6 +59,9 @@ class SpacePacketDeframerTester final : public SpacePacketDeframerGTestBase { //! Initialize components void initComponents(); + //! Assemble a packet with the given parameters + Fw::Buffer assemblePacket(U16 apid, U16 seqCount, U16 packetLength, U8* packetData); + private: // ---------------------------------------------------------------------- // Member variables @@ -63,6 +69,10 @@ class SpacePacketDeframerTester final : public SpacePacketDeframerGTestBase { //! The component under test SpacePacketDeframer component; + + //! Test buffer + static const FwSizeType MAX_TEST_PACKET_DATA_SIZE = 200; + U8 m_packetBuffer[SpacePacketHeader::SERIALIZED_SIZE + MAX_TEST_PACKET_DATA_SIZE]; }; } // namespace CCSDS diff --git a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp index 5cdd524c6e1..163ff8a761c 100644 --- a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp +++ b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp @@ -43,7 +43,7 @@ void SpacePacketFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, c U16 packetIdentification = 0; ComCfg::APID::T apid = context.getapid(); packetIdentification |= static_cast(apid) & SpacePacketMasks::ApidMask; // 11 bit APID - + U16 packetSequenceControl = 0; packetSequenceControl |= 0x3 << SpacePacketMasks::SeqFlagsOffset; // Sequence Flags 0b11 = unsegmented User Data U16 sequenceCount = context.getsequenceCount(); diff --git a/Svc/CCSDS/TMFramer/TMFramer.hpp b/Svc/CCSDS/TMFramer/TMFramer.hpp index abc0304fd62..a6520ee0163 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.hpp +++ b/Svc/CCSDS/TMFramer/TMFramer.hpp @@ -68,7 +68,6 @@ class TMFramer final : public TMFramerComponentBase { //! Fill the frame buffer with an Idle Packet to complete the frame data field //! as per CCSDS TM Protocol paragraph 4.2.2.5. Idle packet is inserted at the //! start_index index of the frame buffer, and fills it up to the end minus CRC - // void fill_with_idle_packet(U16 start_index); void fill_with_idle_packet(Fw::SerializeBufferBase& serializer); // Because the TM protocol use fixed width frames, and only one frame is in transit between ComQueue and From 1f5997942947657ae0a0635d4cbb5032a913ce46 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Fri, 23 May 2025 16:22:26 -0700 Subject: [PATCH 45/95] Add APID (=PacketDescriptor) extraction to FprimeDeframer --- Svc/ComQueue/ComQueue.cpp | 4 ++-- Svc/FprimeDeframer/FprimeDeframer.cpp | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Svc/ComQueue/ComQueue.cpp b/Svc/ComQueue/ComQueue.cpp index 8526abf64b4..aa7936723bf 100644 --- a/Svc/ComQueue/ComQueue.cpp +++ b/Svc/ComQueue/ComQueue.cpp @@ -260,7 +260,7 @@ void ComQueue::sendComBuffer(Fw::ComBuffer& comBuffer, FwIndexType queueIndex) { Fw::Buffer outBuffer(comBuffer.getBuffAddr(), static_cast(comBuffer.getBuffLength())); - // Context APID is set to the queue index for now. A future implementation may want this to be configurable + // Context value is used to determine what to do when the buffer returns on the dataReturnIn port ComCfg::FrameContext context; context.setcomQueueIndex(queueIndex); this->dataOut_out(0, outBuffer, context); @@ -272,7 +272,7 @@ void ComQueue::sendBuffer(Fw::Buffer& buffer, FwIndexType queueIndex) { // Retry buffer expected to be cleared as we are either transferring ownership or have already deallocated it. FW_ASSERT(this->m_state == READY); - // Context APID is set to the queue index for now. A future implementation may want this to be configurable + // Context value is used to determine what to do when the buffer returns on the dataReturnIn port ComCfg::FrameContext context; context.setcomQueueIndex(queueIndex); this->dataOut_out(0, buffer, context); diff --git a/Svc/FprimeDeframer/FprimeDeframer.cpp b/Svc/FprimeDeframer/FprimeDeframer.cpp index 9f816fdf23f..d0e99ded5fc 100644 --- a/Svc/FprimeDeframer/FprimeDeframer.cpp +++ b/Svc/FprimeDeframer/FprimeDeframer.cpp @@ -57,6 +57,12 @@ void FprimeDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, cons this->dataReturnOut_out(0, data, context); // drop the frame return; } + // Extract packet descriptor from the packet data to set the APID for the Router + FwPacketDescriptorType packetDescriptor; + status = deserializer.deserialize(packetDescriptor); + FW_ASSERT(status == Fw::SerializeStatus::FW_SERIALIZE_OK, status); + ComCfg::FrameContext contextCopy = context; + contextCopy.setapid(static_cast(packetDescriptor)); // ---------------- Validate Frame Trailer ---------------- // Deserialize transmitted trailer: trailer is at offset = len(header) + len(body) @@ -88,7 +94,7 @@ void FprimeDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, cons data.setSize(data.getSize() - FprimeProtocol::FrameHeader::SERIALIZED_SIZE - FprimeProtocol::FrameTrailer::SERIALIZED_SIZE); // Emit the deframed data - this->dataOut_out(0, data, context); + this->dataOut_out(0, data, contextCopy); } void FprimeDeframer ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer, const ComCfg::FrameContext& context) { From b8debb108c29fd358477873f4c8c2bded245cf46 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Fri, 23 May 2025 16:38:03 -0700 Subject: [PATCH 46/95] Use ApidManager on uplink to validate seq count (is central authority for APID - SeqCount) --- Ref/Top/instances.fpp | 2 +- Ref/Top/topology.fpp | 16 ++--- .../ApidManager.cpp} | 52 ++++++++++++---- Svc/CCSDS/ApidManager/ApidManager.fpp | 34 +++++++++++ .../ApidManager.hpp} | 29 +++++---- .../CMakeLists.txt | 10 ++-- .../{ApidMapper => ApidManager}/docs/sdd.md | 4 +- Svc/CCSDS/ApidMapper/ApidMapper.fpp | 16 ----- Svc/CCSDS/CMakeLists.txt | 4 +- Svc/CCSDS/Ports/CMakeLists.txt | 16 +++++ Svc/CCSDS/Ports/Ports.fpp | 11 ++++ .../SpacePacketDeframer.cpp | 60 ++++++++----------- .../SpacePacketDeframer.fpp | 2 + .../SpacePacketDeframer.hpp | 28 ++++----- 14 files changed, 181 insertions(+), 103 deletions(-) rename Svc/CCSDS/{ApidMapper/ApidMapper.cpp => ApidManager/ApidManager.cpp} (57%) create mode 100644 Svc/CCSDS/ApidManager/ApidManager.fpp rename Svc/CCSDS/{ApidMapper/ApidMapper.hpp => ApidManager/ApidManager.hpp} (73%) rename Svc/CCSDS/{ApidMapper => ApidManager}/CMakeLists.txt (65%) rename Svc/CCSDS/{ApidMapper => ApidManager}/docs/sdd.md (74%) delete mode 100644 Svc/CCSDS/ApidMapper/ApidMapper.fpp create mode 100644 Svc/CCSDS/Ports/CMakeLists.txt create mode 100644 Svc/CCSDS/Ports/Ports.fpp diff --git a/Ref/Top/instances.fpp b/Ref/Top/instances.fpp index ca01d09974a..a5d50ea99fa 100644 --- a/Ref/Top/instances.fpp +++ b/Ref/Top/instances.fpp @@ -177,7 +177,7 @@ module Ref { instance fprimeRouter: Svc.FprimeRouter base id 0x4D00 - instance apidMapper: Svc.CCSDS.ApidMapper base id 0x4E00 + instance apidManager: Svc.CCSDS.ApidManager base id 0x4E00 instance comStub: Svc.ComStub base id 0x4F00 diff --git a/Ref/Top/topology.fpp b/Ref/Top/topology.fpp index e90e959e5eb..f3dfe152991 100644 --- a/Ref/Top/topology.fpp +++ b/Ref/Top/topology.fpp @@ -50,7 +50,7 @@ module Ref { instance fileUplink instance commsBufferManager instance frameAccumulator - instance apidMapper + instance apidManager instance posixTime instance pingRcvr instance prmDb @@ -107,12 +107,12 @@ module Ref { tlmSend.PktSend -> comQueue.comPacketQueueIn[Ports_ComPacketQueue.TELEMETRY] fileDownlink.bufferSendOut -> comQueue.bufferQueueIn[Ports_ComBufferQueue.FILE_DOWNLINK] comQueue.bufferReturnOut[Ports_ComBufferQueue.FILE_DOWNLINK] -> fileDownlink.bufferReturn - # ComQueue <-> ApidMapper - comQueue.dataOut -> apidMapper.dataIn - apidMapper.dataReturnOut -> comQueue.dataReturnIn - # ApidMapper <-> Framer - apidMapper.dataOut -> spacePacketFramer.dataIn - spacePacketFramer.dataReturnOut -> apidMapper.dataReturnIn + # ComQueue <-> ApidManager + comQueue.dataOut -> apidManager.dataIn + apidManager.dataReturnOut -> comQueue.dataReturnIn + # ApidManager <-> Framer + apidManager.dataOut -> spacePacketFramer.dataIn + spacePacketFramer.dataReturnOut -> apidManager.dataReturnIn # Buffer Management for Framer spacePacketFramer.bufferAllocate -> commsBufferManager.bufferGetCallee spacePacketFramer.bufferDeallocate -> commsBufferManager.bufferSendIn @@ -210,6 +210,8 @@ module Ref { cmdDisp.seqCmdStatus -> fprimeRouter.cmdResponseIn fprimeRouter.fileOut -> fileUplink.bufferSendIn fileUplink.bufferSendOut -> fprimeRouter.fileBufferReturnIn + + spacePacketDeframer.validateApidSeqCount -> apidManager.validateApidSeqCountIn } connections DataProducts { diff --git a/Svc/CCSDS/ApidMapper/ApidMapper.cpp b/Svc/CCSDS/ApidManager/ApidManager.cpp similarity index 57% rename from Svc/CCSDS/ApidMapper/ApidMapper.cpp rename to Svc/CCSDS/ApidManager/ApidManager.cpp index ce11c98db6f..8577bf96ff5 100644 --- a/Svc/CCSDS/ApidMapper/ApidMapper.cpp +++ b/Svc/CCSDS/ApidManager/ApidManager.cpp @@ -1,10 +1,10 @@ // ====================================================================== -// \title ApidMapper.cpp +// \title ApidManager.cpp // \author thomas-bc -// \brief cpp file for ApidMapper component implementation class +// \brief cpp file for ApidManager component implementation class // ====================================================================== -#include "Svc/CCSDS/ApidMapper/ApidMapper.hpp" +#include "Svc/CCSDS/ApidManager/ApidManager.hpp" namespace Svc { @@ -14,31 +14,51 @@ namespace CCSDS { // Component construction and destruction // ---------------------------------------------------------------------- -ApidMapper ::ApidMapper(const char* const compName) : ApidMapperComponentBase(compName) { +ApidManager ::ApidManager(const char* const compName) : ApidManagerComponentBase(compName) { // Initialize the APID sequence table with APID values that need to be counted (order does not matter) - this->m_apidSequences[0].apid = ComCfg::APID::FW_PACKET_LOG; + // this->m_apidSequences[0].apid = ComCfg::APID::FW_PACKET_LOG; this->m_apidSequences[1].apid = ComCfg::APID::FW_PACKET_TELEM; this->m_apidSequences[2].apid = ComCfg::APID::FW_PACKET_FILE; this->m_apidSequences[3].apid = ComCfg::APID::FW_PACKET_PACKETIZED_TLM; this->m_apidSequences[4].apid = ComCfg::APID::FW_PACKET_UNKNOWN; + this->m_apidSequences[5].apid = ComCfg::APID::FW_PACKET_COMMAND; + this->m_apidSequences[6].apid = ComCfg::APID::SPP_FILE_DOWNLINK; // TODO: Why does it work without specifying the downlink file APID ? // and add DP ?? } -ApidMapper ::~ApidMapper() {} +ApidManager ::~ApidManager() {} // ---------------------------------------------------------------------- // Handler implementations for typed input ports // ---------------------------------------------------------------------- -void ApidMapper ::comStatusIn_handler(FwIndexType portNum, Fw::Success& condition) { +void ApidManager ::comStatusIn_handler(FwIndexType portNum, Fw::Success& condition) { if (this->isConnected_comStatusOut_OutputPort(portNum)) { this->comStatusOut_out(portNum, condition); } } -void ApidMapper ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { +Fw::Success ApidManager ::validateApidSeqCountIn_handler(FwIndexType portNum, const ComCfg::APID& apid, U16 receivedSeqCount) { + // ComCfg::APID::T apidValue = static_cast(apid); + Fw::Success status = Fw::Success::SUCCESS; + U16 expectedSequenceCount = this->getAndIncrementSeqCount(apid); + if (expectedSequenceCount == SEQUENCE_COUNT_ERROR) { + // This APID is not being tracked + this->log_ACTIVITY_LO_UntrackedApid(apid); + status = Fw::Success::FAILURE; + } else if (receivedSeqCount != expectedSequenceCount) { + // Likely a packet was dropped or out of order + this->log_WARNING_HI_UnexpectedSequenceCount(receivedSeqCount, expectedSequenceCount); + // Synchronize onboard count with received number so that count can keep going + this->setNextSeqCount(apid, receivedSeqCount + 1); + status = Fw::Success::FAILURE; + } + return status; +} + +void ApidManager ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { ComCfg::FrameContext contextCopy = context; // Deserialize Packet Descriptor to map to an APID @@ -65,7 +85,7 @@ void ApidMapper ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const Co this->dataOut_out(0, data, contextCopy); } -void ApidMapper ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { +void ApidManager ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { this->dataReturnOut_out(portNum, data, context); } @@ -73,7 +93,7 @@ void ApidMapper ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& data, co // Helpers // ---------------------------------------------------------------------- -U16 ApidMapper ::getAndIncrementSeqCount(ComCfg::APID::T apid) { +U16 ApidManager ::getAndIncrementSeqCount(ComCfg::APID::T apid) { for (U8 i = 0; i < MAX_TRACKED_APIDS; ++i) { if (m_apidSequences[i].apid == apid) { U16 seq = m_apidSequences[i].sequenceCount; @@ -81,7 +101,17 @@ U16 ApidMapper ::getAndIncrementSeqCount(ComCfg::APID::T apid) { return seq; } } - return 0; // or some error value + // NOTE: log untracked APID on downlink as well? that's kind of a coding error? + return SEQUENCE_COUNT_ERROR; +} + +void ApidManager::setNextSeqCount(ComCfg::APID::T apid, U16 seqCount) { + for (U8 i = 0; i < MAX_TRACKED_APIDS; i++) { + if (m_apidSequences[i].apid == apid) { + m_apidSequences[i].sequenceCount = seqCount; + return; + } + } } } // namespace CCSDS diff --git a/Svc/CCSDS/ApidManager/ApidManager.fpp b/Svc/CCSDS/ApidManager/ApidManager.fpp new file mode 100644 index 00000000000..05a23537d60 --- /dev/null +++ b/Svc/CCSDS/ApidManager/ApidManager.fpp @@ -0,0 +1,34 @@ +module Svc { +module CCSDS { + @ Maps output of ComQueue to CCSDS APIDs + passive component ApidManager { + + include "../../Interfaces/FramerInterface.fppi" + + guarded input port validateApidSeqCountIn: CCSDS.ApidSequenceCount + + @ Deframing received an unexpected sequence count + event UnexpectedSequenceCount(transmitted: U16, expected: U16) \ + severity warning high \ + format "Unexpected sequence count received. Packets may have been lost. Transmitted: {} | Expected on board: {}" + + @ Received an unregistered APID + event UntrackedApid(invalidApidValue: U16) \ + severity activity low \ + format "Received APID not registered with the deframer. Not checking sequence count. APID={}" + + + ############################################################################### + # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # + ############################################################################### + @ Port for requesting the current time + time get port timeCaller + + @ Port for sending textual representation of events + text event port logTextOut + + @ Port for sending events to downlink + event port logOut + } +} +} diff --git a/Svc/CCSDS/ApidMapper/ApidMapper.hpp b/Svc/CCSDS/ApidManager/ApidManager.hpp similarity index 73% rename from Svc/CCSDS/ApidMapper/ApidMapper.hpp rename to Svc/CCSDS/ApidManager/ApidManager.hpp index 709565d77e1..306e6a80864 100644 --- a/Svc/CCSDS/ApidMapper/ApidMapper.hpp +++ b/Svc/CCSDS/ApidManager/ApidManager.hpp @@ -1,33 +1,34 @@ // ====================================================================== -// \title ApidMapper.hpp +// \title ApidManager.hpp // \author thomas-bc -// \brief hpp file for ApidMapper component implementation class +// \brief hpp file for ApidManager component implementation class // ====================================================================== -#ifndef Svc_CCSDS_ApidMapper_HPP -#define Svc_CCSDS_ApidMapper_HPP +#ifndef Svc_CCSDS_ApidManager_HPP +#define Svc_CCSDS_ApidManager_HPP -#include "Svc/CCSDS/ApidMapper/ApidMapperComponentAc.hpp" +#include "Svc/CCSDS/ApidManager/ApidManagerComponentAc.hpp" namespace Svc { namespace CCSDS { -class ApidMapper final : public ApidMapperComponentBase { +class ApidManager final : public ApidManagerComponentBase { - static constexpr U8 MAX_TRACKED_APIDS = 5; + static constexpr U8 MAX_TRACKED_APIDS = 10; + static constexpr U16 SEQUENCE_COUNT_ERROR = std::numeric_limits::max(); public: // ---------------------------------------------------------------------- // Component construction and destruction // ---------------------------------------------------------------------- - //! Construct ApidMapper object - ApidMapper(const char* const compName //!< The component name + //! Construct ApidManager object + ApidManager(const char* const compName //!< The component name ); - //! Destroy ApidMapper object - ~ApidMapper(); + //! Destroy ApidManager object + ~ApidManager(); private: // ---------------------------------------------------------------------- @@ -56,6 +57,10 @@ class ApidMapper final : public ApidMapperComponentBase { Fw::Buffer& data, const ComCfg::FrameContext& context) override; + //! Handler implementation for validateApidSeqCountIn + Fw::Success validateApidSeqCountIn_handler(FwIndexType portNum, //!< The port number + const ComCfg::APID& apid, + U16 seqCount) override; private: // ---------------------------------------------------------------------- // Helpers @@ -64,6 +69,8 @@ class ApidMapper final : public ApidMapperComponentBase { //! Wraps around at 14 bits U16 getAndIncrementSeqCount(ComCfg::APID::T apid); + void setNextSeqCount(ComCfg::APID::T apid, U16 seqCount); + //! This struct helps track sequence counts per APID struct ApidSequenceEntry { ComCfg::APID::T apid = ComCfg::APID::FW_PACKET_UNKNOWN; diff --git a/Svc/CCSDS/ApidMapper/CMakeLists.txt b/Svc/CCSDS/ApidManager/CMakeLists.txt similarity index 65% rename from Svc/CCSDS/ApidMapper/CMakeLists.txt rename to Svc/CCSDS/ApidManager/CMakeLists.txt index fb778ee1cfd..dbb2bec41cd 100644 --- a/Svc/CCSDS/ApidMapper/CMakeLists.txt +++ b/Svc/CCSDS/ApidManager/CMakeLists.txt @@ -12,18 +12,18 @@ register_fprime_library( SOURCES - "${CMAKE_CURRENT_LIST_DIR}/ApidMapper.cpp" + "${CMAKE_CURRENT_LIST_DIR}/ApidManager.cpp" AUTOCODER_INPUTS - "${CMAKE_CURRENT_LIST_DIR}/ApidMapper.fpp" + "${CMAKE_CURRENT_LIST_DIR}/ApidManager.fpp" ) ### Unit Tests ### # set(UT_SOURCE_FILES -# "${CMAKE_CURRENT_LIST_DIR}/ApidMapper.fpp" -# "${CMAKE_CURRENT_LIST_DIR}/test/ut/ApidMapperTestMain.cpp" -# "${CMAKE_CURRENT_LIST_DIR}/test/ut/ApidMapperTester.cpp" +# "${CMAKE_CURRENT_LIST_DIR}/ApidManager.fpp" +# "${CMAKE_CURRENT_LIST_DIR}/test/ut/ApidManagerTestMain.cpp" +# "${CMAKE_CURRENT_LIST_DIR}/test/ut/ApidManagerTester.cpp" # ) # set(UT_MOD_DEPS # STest diff --git a/Svc/CCSDS/ApidMapper/docs/sdd.md b/Svc/CCSDS/ApidManager/docs/sdd.md similarity index 74% rename from Svc/CCSDS/ApidMapper/docs/sdd.md rename to Svc/CCSDS/ApidManager/docs/sdd.md index 0b7b31d2598..34314c026fa 100644 --- a/Svc/CCSDS/ApidMapper/docs/sdd.md +++ b/Svc/CCSDS/ApidManager/docs/sdd.md @@ -1,8 +1,8 @@ -# Svc::CCSDS::ApidMapper +# Svc::CCSDS::ApidManager ## 1. Overview -The `ApidMapper` component is a passive F´ component that maps the descriptor type (ComPacketType/APID) found in the first two bytes of a data buffer to a CCSDS Space Packet APID. It also tracks and manages a sequence count for each APID, as required by the CCSDS protocol. This enables downstream components to generate correct CCSDS Space Packets with the appropriate APID and sequence count. +The `ApidManager` component is a passive F´ component that maps the descriptor type (ComPacketType/APID) found in the first two bytes of a data buffer to a CCSDS Space Packet APID. It also tracks and manages a sequence count for each APID, as required by the CCSDS protocol. This enables downstream components to generate correct CCSDS Space Packets with the appropriate APID and sequence count. ## 2. Requirements diff --git a/Svc/CCSDS/ApidMapper/ApidMapper.fpp b/Svc/CCSDS/ApidMapper/ApidMapper.fpp deleted file mode 100644 index f2702321929..00000000000 --- a/Svc/CCSDS/ApidMapper/ApidMapper.fpp +++ /dev/null @@ -1,16 +0,0 @@ -module Svc { -module CCSDS { - @ Maps output of ComQueue to CCSDS APIDs - passive component ApidMapper { - - include "../../Interfaces/FramerInterface.fppi" - - ############################################################################### - # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # - ############################################################################### - @ Port for requesting the current time - time get port timeCaller - - } -} -} \ No newline at end of file diff --git a/Svc/CCSDS/CMakeLists.txt b/Svc/CCSDS/CMakeLists.txt index d48fe84074d..bb80ac4ce41 100644 --- a/Svc/CCSDS/CMakeLists.txt +++ b/Svc/CCSDS/CMakeLists.txt @@ -1,7 +1,7 @@ add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Types/") +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Ports/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/SpacePacketDeframer/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/SpacePacketFramer/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/TCDeframer/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/TMFramer/") -# add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Utils/") -add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/ApidMapper/") +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/ApidManager/") diff --git a/Svc/CCSDS/Ports/CMakeLists.txt b/Svc/CCSDS/Ports/CMakeLists.txt new file mode 100644 index 00000000000..baa73af3c30 --- /dev/null +++ b/Svc/CCSDS/Ports/CMakeLists.txt @@ -0,0 +1,16 @@ +#### +# FPrime CMakeLists.txt: +# +# SOURCES: list of source files (to be compiled) +# AUTOCODER_INPUTS: list of files to be passed to the autocoders +# DEPENDS: list of libraries that this module depends on +# +# More information in the F´ CMake API documentation: +# https://fprime.jpl.nasa.gov/latest/docs/reference/api/cmake/API/ +# +#### + +register_fprime_library( + AUTOCODER_INPUTS + "${CMAKE_CURRENT_LIST_DIR}/Ports.fpp" +) diff --git a/Svc/CCSDS/Ports/Ports.fpp b/Svc/CCSDS/Ports/Ports.fpp new file mode 100644 index 00000000000..cf4eb29ddba --- /dev/null +++ b/Svc/CCSDS/Ports/Ports.fpp @@ -0,0 +1,11 @@ +module Svc { +module CCSDS { + + @ Port for requesting a sequence count for a given APID + port ApidSequenceCount (apid: ComCfg.APID, sequenceCount: U16) -> Fw.Success + + # port ApidSequenceCount (rawApidValue: U16, ref apid: ComCfg.APID, ref sequenceCount: U16) -> Fw.Success + + +} +} diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp index ba83efc0f81..c4420d3f76f 100644 --- a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp @@ -18,10 +18,10 @@ namespace CCSDS { SpacePacketDeframer ::SpacePacketDeframer(const char* const compName) : SpacePacketDeframerComponentBase(compName) { // Initialize the APID sequence table with APID values that need to be counted (order does not matter) - this->m_apidSequences[0].apid = ComCfg::APID::FW_PACKET_COMMAND; - this->m_apidSequences[2].apid = ComCfg::APID::FW_PACKET_FILE; - this->m_apidSequences[3].apid = ComCfg::APID::FW_PACKET_PACKETIZED_TLM; - this->m_apidSequences[4].apid = ComCfg::APID::FW_PACKET_UNKNOWN; + // this->m_apidSequences[0].apid = ComCfg::APID::FW_PACKET_COMMAND; + // this->m_apidSequences[2].apid = ComCfg::APID::FW_PACKET_FILE; + // this->m_apidSequences[3].apid = ComCfg::APID::FW_PACKET_PACKETIZED_TLM; + // this->m_apidSequences[4].apid = ComCfg::APID::FW_PACKET_UNKNOWN; } SpacePacketDeframer ::~SpacePacketDeframer() {} @@ -64,16 +64,8 @@ void SpacePacketDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, return; } U16 receivedSequenceCount = header.getpacketSequenceControl() & SpacePacketMasks::SeqCountMask; - U16 expectedSequenceCount = this->getAndIncrementSeqCount(apid); - if (expectedSequenceCount == SEQUENCE_COUNT_ERROR) { - // This APID is not being tracked - this->log_ACTIVITY_LO_UntrackedApid(apidValue); - } else if (receivedSequenceCount != expectedSequenceCount) { - // Likely a packet was dropped or out of order - this->log_WARNING_HI_UnexpectedSequenceCount(receivedSequenceCount, expectedSequenceCount); - // Synchronize onboard count with received number so that count can keep going - this->setNextSeqCount(apid, receivedSequenceCount + 1); - } + // Validate with the ApidManager that the sequence count is correct + (void) this->validateApidSeqCount_out(0, apid, receivedSequenceCount); contextCopy.setsequenceCount(receivedSequenceCount); // Set data buffer to be of the encapsulated data: HEADER (6 bytes) | PACKET DATA @@ -93,26 +85,26 @@ void SpacePacketDeframer ::dataReturnIn_handler(FwIndexType portNum, // Helpers // ---------------------------------------------------------------------- -U16 SpacePacketDeframer::getAndIncrementSeqCount(ComCfg::APID::T apid) { - for (U8 i = 0; i < MAX_TRACKED_APIDS; ++i) { - if (m_apidSequences[i].apid == apid) { - U16 seq = m_apidSequences[i].sequenceCount; - m_apidSequences[i].sequenceCount = (seq + 1) % (1 << 14); // Wrap around at 14 bits - printf("APID: %d, SeqCount: %d\n", apid, seq); - return seq; - } - } - return SEQUENCE_COUNT_ERROR; // error value - this value is never returned with wraparound -} - -void SpacePacketDeframer::setNextSeqCount(ComCfg::APID::T apid, U16 seqCount) { - for (U8 i = 0; i < MAX_TRACKED_APIDS; i++) { - if (m_apidSequences[i].apid == apid) { - m_apidSequences[i].sequenceCount = seqCount; - return; - } - } -} +// U16 SpacePacketDeframer::getAndIncrementSeqCount(ComCfg::APID::T apid) { +// for (U8 i = 0; i < MAX_TRACKED_APIDS; ++i) { +// if (m_apidSequences[i].apid == apid) { +// U16 seq = m_apidSequences[i].sequenceCount; +// m_apidSequences[i].sequenceCount = (seq + 1) % (1 << 14); // Wrap around at 14 bits +// printf("APID: %d, SeqCount: %d\n", apid, seq); +// return seq; +// } +// } +// return SEQUENCE_COUNT_ERROR; // error value - this value is never returned with wraparound +// } + +// void SpacePacketDeframer::setNextSeqCount(ComCfg::APID::T apid, U16 seqCount) { +// for (U8 i = 0; i < MAX_TRACKED_APIDS; i++) { +// if (m_apidSequences[i].apid == apid) { +// m_apidSequences[i].sequenceCount = seqCount; +// return; +// } +// } +// } } // namespace CCSDS } // namespace Svc diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp index 83aefdc2ae9..d978a40ed4f 100644 --- a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp @@ -5,6 +5,8 @@ module CCSDS { include "../../Interfaces/DeframerInterface.fppi" + output port validateApidSeqCount: CCSDS.ApidSequenceCount + @ Deframing received an invalid frame length event InvalidLength(transmitted: U16, actual: U32) \ severity warning high \ diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp index 8602114bdb4..e49a25e87b7 100644 --- a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp @@ -16,8 +16,8 @@ namespace CCSDS { class SpacePacketDeframer final : public SpacePacketDeframerComponentBase { friend class SpacePacketDeframerTester; - static constexpr U8 MAX_TRACKED_APIDS = 5; - static constexpr U16 SEQUENCE_COUNT_ERROR = std::numeric_limits::max(); + // static constexpr U8 MAX_TRACKED_APIDS = 5; + // static constexpr U16 SEQUENCE_COUNT_ERROR = std::numeric_limits::max(); public: // ---------------------------------------------------------------------- @@ -56,21 +56,21 @@ class SpacePacketDeframer final : public SpacePacketDeframerComponentBase { // ---------------------------------------------------------------------- //! Get the sequence count for a given APID and increment it for the next //! Wraps around at 14 bits - U16 getAndIncrementSeqCount(ComCfg::APID::T apid); +// U16 getAndIncrementSeqCount(ComCfg::APID::T apid); - void setNextSeqCount(ComCfg::APID::T apid, U16 seqCount); +// void setNextSeqCount(ComCfg::APID::T apid, U16 seqCount); - //! This struct helps track sequence counts per APID - struct ApidSequenceEntry { - ComCfg::APID::T apid = ComCfg::APID::FW_PACKET_UNKNOWN; - U16 sequenceCount; - }; +// //! This struct helps track sequence counts per APID +// struct ApidSequenceEntry { +// ComCfg::APID::T apid = ComCfg::APID::FW_PACKET_UNKNOWN; +// U16 sequenceCount; +// }; - private: - // ---------------------------------------------------------------------- - // Member variables - // ---------------------------------------------------------------------- - ApidSequenceEntry m_apidSequences[MAX_TRACKED_APIDS]; +// private: +// // ---------------------------------------------------------------------- +// // Member variables +// // ---------------------------------------------------------------------- +// ApidSequenceEntry m_apidSequences[MAX_TRACKED_APIDS]; }; } // namespace CCSDS From ad5d07d1c810a621bcfe1dcaa92e5f5f4b7548a6 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Fri, 23 May 2025 18:17:30 -0700 Subject: [PATCH 47/95] Code cleanup --- Svc/CCSDS/ApidManager/ApidManager.cpp | 9 +++--- Svc/CCSDS/ApidManager/ApidManager.hpp | 2 +- Svc/CCSDS/Ports/Ports.fpp | 3 -- .../SpacePacketDeframer.cpp | 25 --------------- .../SpacePacketDeframer.hpp | 24 -------------- .../SpacePacketFramer/SpacePacketFramer.cpp | 32 ------------------- default/config/ComCfg.fpp | 2 +- 7 files changed, 6 insertions(+), 91 deletions(-) diff --git a/Svc/CCSDS/ApidManager/ApidManager.cpp b/Svc/CCSDS/ApidManager/ApidManager.cpp index 8577bf96ff5..f5d97aaccb4 100644 --- a/Svc/CCSDS/ApidManager/ApidManager.cpp +++ b/Svc/CCSDS/ApidManager/ApidManager.cpp @@ -16,16 +16,15 @@ namespace CCSDS { ApidManager ::ApidManager(const char* const compName) : ApidManagerComponentBase(compName) { // Initialize the APID sequence table with APID values that need to be counted (order does not matter) - // this->m_apidSequences[0].apid = ComCfg::APID::FW_PACKET_LOG; + this->m_apidSequences[0].apid = ComCfg::APID::FW_PACKET_LOG; this->m_apidSequences[1].apid = ComCfg::APID::FW_PACKET_TELEM; this->m_apidSequences[2].apid = ComCfg::APID::FW_PACKET_FILE; this->m_apidSequences[3].apid = ComCfg::APID::FW_PACKET_PACKETIZED_TLM; this->m_apidSequences[4].apid = ComCfg::APID::FW_PACKET_UNKNOWN; this->m_apidSequences[5].apid = ComCfg::APID::FW_PACKET_COMMAND; this->m_apidSequences[6].apid = ComCfg::APID::SPP_FILE_DOWNLINK; - // TODO: Why does it work without specifying the downlink file APID ? - // and add DP ?? - + this->m_apidSequences[7].apid = ComCfg::APID::FW_PACKET_DP; + this->m_apidSequences[8].apid = ComCfg::APID::MY_USER_APID_EXAMPLE; } ApidManager ::~ApidManager() {} @@ -79,7 +78,7 @@ void ApidManager ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const C contextCopy.setapid(static_cast(apid)); contextCopy.setsequenceCount(this->getAndIncrementSeqCount(static_cast(apid))); - // printf("APID: %d, SeqCount: %d\n", apid, contextCopy.getsequenceCount()); + // TODO: assert if sequence count is error since that means it is a coding error: APID was not registered ?? // Forward the buffer and context to the output port this->dataOut_out(0, data, contextCopy); diff --git a/Svc/CCSDS/ApidManager/ApidManager.hpp b/Svc/CCSDS/ApidManager/ApidManager.hpp index 306e6a80864..d016e94205a 100644 --- a/Svc/CCSDS/ApidManager/ApidManager.hpp +++ b/Svc/CCSDS/ApidManager/ApidManager.hpp @@ -15,7 +15,7 @@ namespace CCSDS { class ApidManager final : public ApidManagerComponentBase { - static constexpr U8 MAX_TRACKED_APIDS = 10; + static constexpr U8 MAX_TRACKED_APIDS = ComCfg::APID::NUM_CONSTANTS; static constexpr U16 SEQUENCE_COUNT_ERROR = std::numeric_limits::max(); public: diff --git a/Svc/CCSDS/Ports/Ports.fpp b/Svc/CCSDS/Ports/Ports.fpp index cf4eb29ddba..f096199800d 100644 --- a/Svc/CCSDS/Ports/Ports.fpp +++ b/Svc/CCSDS/Ports/Ports.fpp @@ -4,8 +4,5 @@ module CCSDS { @ Port for requesting a sequence count for a given APID port ApidSequenceCount (apid: ComCfg.APID, sequenceCount: U16) -> Fw.Success - # port ApidSequenceCount (rawApidValue: U16, ref apid: ComCfg.APID, ref sequenceCount: U16) -> Fw.Success - - } } diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp index c4420d3f76f..ceac41d7db8 100644 --- a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp @@ -81,30 +81,5 @@ void SpacePacketDeframer ::dataReturnIn_handler(FwIndexType portNum, this->dataReturnOut_out(0, data, context); } -// ---------------------------------------------------------------------- -// Helpers -// ---------------------------------------------------------------------- - -// U16 SpacePacketDeframer::getAndIncrementSeqCount(ComCfg::APID::T apid) { -// for (U8 i = 0; i < MAX_TRACKED_APIDS; ++i) { -// if (m_apidSequences[i].apid == apid) { -// U16 seq = m_apidSequences[i].sequenceCount; -// m_apidSequences[i].sequenceCount = (seq + 1) % (1 << 14); // Wrap around at 14 bits -// printf("APID: %d, SeqCount: %d\n", apid, seq); -// return seq; -// } -// } -// return SEQUENCE_COUNT_ERROR; // error value - this value is never returned with wraparound -// } - -// void SpacePacketDeframer::setNextSeqCount(ComCfg::APID::T apid, U16 seqCount) { -// for (U8 i = 0; i < MAX_TRACKED_APIDS; i++) { -// if (m_apidSequences[i].apid == apid) { -// m_apidSequences[i].sequenceCount = seqCount; -// return; -// } -// } -// } - } // namespace CCSDS } // namespace Svc diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp index e49a25e87b7..c5bc03887cd 100644 --- a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.hpp @@ -16,9 +16,6 @@ namespace CCSDS { class SpacePacketDeframer final : public SpacePacketDeframerComponentBase { friend class SpacePacketDeframerTester; - // static constexpr U8 MAX_TRACKED_APIDS = 5; - // static constexpr U16 SEQUENCE_COUNT_ERROR = std::numeric_limits::max(); - public: // ---------------------------------------------------------------------- // Component construction and destruction @@ -50,27 +47,6 @@ class SpacePacketDeframer final : public SpacePacketDeframerComponentBase { Fw::Buffer& data, const ComCfg::FrameContext& context) override; - private: - // ---------------------------------------------------------------------- - // Helpers - // ---------------------------------------------------------------------- - //! Get the sequence count for a given APID and increment it for the next - //! Wraps around at 14 bits -// U16 getAndIncrementSeqCount(ComCfg::APID::T apid); - -// void setNextSeqCount(ComCfg::APID::T apid, U16 seqCount); - -// //! This struct helps track sequence counts per APID -// struct ApidSequenceEntry { -// ComCfg::APID::T apid = ComCfg::APID::FW_PACKET_UNKNOWN; -// U16 sequenceCount; -// }; - -// private: -// // ---------------------------------------------------------------------- -// // Member variables -// // ---------------------------------------------------------------------- -// ApidSequenceEntry m_apidSequences[MAX_TRACKED_APIDS]; }; } // namespace CCSDS diff --git a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp index 163ff8a761c..e1aed538a09 100644 --- a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp +++ b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp @@ -80,38 +80,6 @@ void SpacePacketFramer ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& f this->bufferDeallocate_out(0, frameBuffer); } -// TODO: use below -// Aspirational: use this structure for everything, and put it into Utils package!! so other users can use it... ??? -// void SpacePacketFramer ::assemblePacketIntoBuffer(Fw::Buffer targetBuffer, ComCfg::APID::T apid, U16 sequenceCount, Fw::Buffer packetData) { -// SpacePacketHeader header; -// Fw::SerializeStatus status; -// auto frameSerializer = targetBuffer.getSerializer(); - -// // ----------------------------------------------- -// // Header -// // ----------------------------------------------- -// // PVN is always 0 per Standard - Packet Type is 0 for Telemetry (downlink) - SecHdr flag is 0 for no secondary header -// U16 packetIdentification = 0; -// packetIdentification |= static_cast(apid) & SpacePacketMasks::ApidMask; // 11 bit APID - -// U16 packetSequenceControl = 0; -// packetSequenceControl |= 0x3 << SpacePacketMasks::SeqFlagsOffset; // Sequence Flags 0b11 = unsegmented User Data -// // TODO: Add assert that it indeed fits in 14 bits ?? -// packetSequenceControl |= sequenceCount & SpacePacketMasks::SeqCountMask; // 14 bit sequence count -// header.setpacketIdentification(packetIdentification); -// header.setpacketSequenceControl(packetSequenceControl); -// U16 packetDataLength = static_cast(packetData.getSize() - 1); // Standard specifies length is number of bytes minus 1 -// header.setpacketDataLength(packetDataLength); - -// // ----------------------------------------------- -// // Serialize the packet -// // ----------------------------------------------- -// status = frameSerializer.serialize(header); -// FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); -// status = frameSerializer.serialize(packetData.getData(), packetData.getSize(), Fw::Serialization::OMIT_LENGTH); -// FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); -// } - } // namespace CCSDS } // namespace Svc diff --git a/default/config/ComCfg.fpp b/default/config/ComCfg.fpp index 06576b26bea..a1c6edf026b 100644 --- a/default/config/ComCfg.fpp +++ b/default/config/ComCfg.fpp @@ -23,8 +23,8 @@ module ComCfg { FW_PACKET_IDLE = 0x0006 @< F Prime idle FW_PACKET_HAND = 0x00FE @< F Prime handshake FW_PACKET_UNKNOWN = 0x00FF @< F Prime unknown packet - # SPP_FILE_UPLINK = 0x0101 @< APID for File packets on uplink SPP_FILE_DOWNLINK = 0x0103 @< Extra APID for File packets on downlink so APID isn't shared between uplink and downlink + MY_USER_APID_EXAMPLE = 0x0777 @< Example APID for user defined packets SPP_IDLE_PACKET = 0x07FF @< Per Space Packet Standard, all 1s (11bits) is reserved for Idle Packets } default FW_PACKET_UNKNOWN From c757edb9e075c486acc4d79de89cac0595caac65 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Fri, 23 May 2025 23:58:58 -0700 Subject: [PATCH 48/95] Much cleaner ApidManager as a service, not in the middle of framing --- Svc/CCSDS/ApidManager/ApidManager.cpp | 48 ++++--------------- Svc/CCSDS/ApidManager/ApidManager.fpp | 5 +- Svc/CCSDS/ApidManager/ApidManager.hpp | 27 ++--------- Svc/CCSDS/Ports/Ports.fpp | 2 +- .../SpacePacketFramer/SpacePacketFramer.cpp | 6 ++- .../SpacePacketFramer/SpacePacketFramer.fpp | 2 + Svc/CCSDS/TMFramer/TMFramer.fpp | 3 -- Svc/ComQueue/ComQueue.cpp | 12 ++++- Svc/FprimeDeframer/FprimeDeframer.cpp | 12 ++--- Svc/FprimeRouter/FprimeRouter.cpp | 16 +++++-- 10 files changed, 50 insertions(+), 83 deletions(-) diff --git a/Svc/CCSDS/ApidManager/ApidManager.cpp b/Svc/CCSDS/ApidManager/ApidManager.cpp index f5d97aaccb4..ba238074023 100644 --- a/Svc/CCSDS/ApidManager/ApidManager.cpp +++ b/Svc/CCSDS/ApidManager/ApidManager.cpp @@ -33,59 +33,27 @@ ApidManager ::~ApidManager() {} // Handler implementations for typed input ports // ---------------------------------------------------------------------- -void ApidManager ::comStatusIn_handler(FwIndexType portNum, Fw::Success& condition) { - if (this->isConnected_comStatusOut_OutputPort(portNum)) { - this->comStatusOut_out(portNum, condition); - } -} - -Fw::Success ApidManager ::validateApidSeqCountIn_handler(FwIndexType portNum, const ComCfg::APID& apid, U16 receivedSeqCount) { - // ComCfg::APID::T apidValue = static_cast(apid); - Fw::Success status = Fw::Success::SUCCESS; +U16 ApidManager ::validateApidSeqCountIn_handler(FwIndexType portNum, const ComCfg::APID& apid, U16 receivedSeqCount) { U16 expectedSequenceCount = this->getAndIncrementSeqCount(apid); if (expectedSequenceCount == SEQUENCE_COUNT_ERROR) { // This APID is not being tracked this->log_ACTIVITY_LO_UntrackedApid(apid); - status = Fw::Success::FAILURE; } else if (receivedSeqCount != expectedSequenceCount) { // Likely a packet was dropped or out of order this->log_WARNING_HI_UnexpectedSequenceCount(receivedSeqCount, expectedSequenceCount); // Synchronize onboard count with received number so that count can keep going this->setNextSeqCount(apid, receivedSeqCount + 1); - status = Fw::Success::FAILURE; } - return status; + return receivedSeqCount; } -void ApidManager ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { - ComCfg::FrameContext contextCopy = context; - - // Deserialize Packet Descriptor to map to an APID - auto deserializer = data.getDeserializer(); - FwPacketDescriptorType descriptorValue = 0; - Fw::SerializeStatus status = deserializer.deserialize(descriptorValue); - FW_ASSERT(status == Fw::FW_SERIALIZE_OK, static_cast(status)); - ComCfg::APID::T apid; - if (descriptorValue == ComCfg::APID::FW_PACKET_FILE) { - // If descriptor is a file packet, set APID to the file downlink APID - // This is because we don't want to use FW_PACKET_FILE as the APID so - // the APID isn't shared between uplink and downlink - apid = ComCfg::APID::SPP_FILE_DOWNLINK; - } else { - // Else, map one-to-one: Descriptor value is APID value - apid = static_cast(descriptorValue); +U16 ApidManager ::getApidSeqCountIn_handler(FwIndexType portNum, const ComCfg::APID& apid, U16 unused) { + U16 expectedSequenceCount = this->getAndIncrementSeqCount(apid); + if (expectedSequenceCount == SEQUENCE_COUNT_ERROR) { + // This APID is not being tracked + this->log_ACTIVITY_LO_UntrackedApid(apid); } - - contextCopy.setapid(static_cast(apid)); - contextCopy.setsequenceCount(this->getAndIncrementSeqCount(static_cast(apid))); - // TODO: assert if sequence count is error since that means it is a coding error: APID was not registered ?? - - // Forward the buffer and context to the output port - this->dataOut_out(0, data, contextCopy); -} - -void ApidManager ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { - this->dataReturnOut_out(portNum, data, context); + return expectedSequenceCount; } // ---------------------------------------------------------------------- diff --git a/Svc/CCSDS/ApidManager/ApidManager.fpp b/Svc/CCSDS/ApidManager/ApidManager.fpp index 05a23537d60..688c8ce640e 100644 --- a/Svc/CCSDS/ApidManager/ApidManager.fpp +++ b/Svc/CCSDS/ApidManager/ApidManager.fpp @@ -2,11 +2,10 @@ module Svc { module CCSDS { @ Maps output of ComQueue to CCSDS APIDs passive component ApidManager { - - include "../../Interfaces/FramerInterface.fppi" - guarded input port validateApidSeqCountIn: CCSDS.ApidSequenceCount + guarded input port getApidSeqCountIn: CCSDS.ApidSequenceCount + @ Deframing received an unexpected sequence count event UnexpectedSequenceCount(transmitted: U16, expected: U16) \ severity warning high \ diff --git a/Svc/CCSDS/ApidManager/ApidManager.hpp b/Svc/CCSDS/ApidManager/ApidManager.hpp index d016e94205a..dbee34885ea 100644 --- a/Svc/CCSDS/ApidManager/ApidManager.hpp +++ b/Svc/CCSDS/ApidManager/ApidManager.hpp @@ -35,30 +35,13 @@ class ApidManager final : public ApidManagerComponentBase { // Handler implementations for typed input ports // ---------------------------------------------------------------------- - //! Handler implementation for comStatusIn - //! - //! Port receiving the general status from the downstream component - //! indicating it is ready or not-ready for more input - void comStatusIn_handler(FwIndexType portNum, //!< The port number - Fw::Success& condition //!< Condition success/failure - ) override; - - //! Handler implementation for dataIn - //! - //! Port to receive data to frame, in a Fw::Buffer with optional context - void dataIn_handler(FwIndexType portNum, //!< The port number - Fw::Buffer& data, - const ComCfg::FrameContext& context) override; - - //! Handler implementation for dataReturnIn - //! - //! Buffer coming from a deallocate call in a ComDriver component - void dataReturnIn_handler(FwIndexType portNum, //!< The port number - Fw::Buffer& data, - const ComCfg::FrameContext& context) override; + //! Handler implementation for validateApidSeqCountIn + U16 validateApidSeqCountIn_handler(FwIndexType portNum, //!< The port number + const ComCfg::APID& apid, + U16 seqCount) override; //! Handler implementation for validateApidSeqCountIn - Fw::Success validateApidSeqCountIn_handler(FwIndexType portNum, //!< The port number + U16 getApidSeqCountIn_handler(FwIndexType portNum, //!< The port number const ComCfg::APID& apid, U16 seqCount) override; private: diff --git a/Svc/CCSDS/Ports/Ports.fpp b/Svc/CCSDS/Ports/Ports.fpp index f096199800d..7da021553ed 100644 --- a/Svc/CCSDS/Ports/Ports.fpp +++ b/Svc/CCSDS/Ports/Ports.fpp @@ -2,7 +2,7 @@ module Svc { module CCSDS { @ Port for requesting a sequence count for a given APID - port ApidSequenceCount (apid: ComCfg.APID, sequenceCount: U16) -> Fw.Success + port ApidSequenceCount (apid: ComCfg.APID, sequenceCount: U16) -> U16 } } diff --git a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp index e1aed538a09..fa78982147b 100644 --- a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp +++ b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp @@ -42,12 +42,14 @@ void SpacePacketFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, c // PVN is always 0 per Standard - Packet Type is 0 for Telemetry (downlink) - SecHdr flag is 0 for no secondary header U16 packetIdentification = 0; ComCfg::APID::T apid = context.getapid(); + FW_ASSERT((apid >> 11) == 0, static_cast(apid)); // apid must fit in 11 bits packetIdentification |= static_cast(apid) & SpacePacketMasks::ApidMask; // 11 bit APID U16 packetSequenceControl = 0; packetSequenceControl |= 0x3 << SpacePacketMasks::SeqFlagsOffset; // Sequence Flags 0b11 = unsegmented User Data - U16 sequenceCount = context.getsequenceCount(); - // TODO: Add assert that it indeed fits in 14 bits ?? + + U16 sequenceCount = this->getApidSeqCount_out(0, apid, 0); // retrieve the sequence count for this APID + FW_ASSERT((sequenceCount >> 14) == 0, static_cast(sequenceCount)); // sequence count must fit in 14 bits packetSequenceControl |= sequenceCount & SpacePacketMasks::SeqCountMask; // 14 bit sequence count FW_ASSERT(data.getSize() <= std::numeric_limits::max(), static_cast(data.getSize())); diff --git a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.fpp b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.fpp index 3e0c1f38265..03aa9bfda5c 100644 --- a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.fpp +++ b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.fpp @@ -8,6 +8,8 @@ module CCSDS { output port bufferAllocate: Fw.BufferGet output port bufferDeallocate: Fw.BufferSend + output port getApidSeqCount: CCSDS.ApidSequenceCount + ############################################################################### # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # ############################################################################### diff --git a/Svc/CCSDS/TMFramer/TMFramer.fpp b/Svc/CCSDS/TMFramer/TMFramer.fpp index 2648ceda1b9..705a6610aa3 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.fpp +++ b/Svc/CCSDS/TMFramer/TMFramer.fpp @@ -5,9 +5,6 @@ module CCSDS { include "../../Interfaces/FramerInterface.fppi" - output port bufferAllocate: Fw.BufferGet - output port bufferDeallocate: Fw.BufferSend - ############################################################################### # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # ############################################################################### diff --git a/Svc/ComQueue/ComQueue.cpp b/Svc/ComQueue/ComQueue.cpp index aa7936723bf..9243a6fa00f 100644 --- a/Svc/ComQueue/ComQueue.cpp +++ b/Svc/ComQueue/ComQueue.cpp @@ -257,12 +257,16 @@ bool ComQueue::enqueue(const FwIndexType queueNum, QueueType queueType, const U8 void ComQueue::sendComBuffer(Fw::ComBuffer& comBuffer, FwIndexType queueIndex) { FW_ASSERT(this->m_state == READY); - Fw::Buffer outBuffer(comBuffer.getBuffAddr(), static_cast(comBuffer.getBuffLength())); // Context value is used to determine what to do when the buffer returns on the dataReturnIn port ComCfg::FrameContext context; + FwPacketDescriptorType descriptor; + Fw::SerializeStatus status = comBuffer.deserialize(descriptor); + FW_ASSERT(status == Fw::FW_SERIALIZE_OK, static_cast(status)); + context.setapid(static_cast(descriptor)); context.setcomQueueIndex(queueIndex); + this->dataOut_out(0, outBuffer, context); // Set state to WAITING for the status to come back this->m_state = WAITING; @@ -274,9 +278,13 @@ void ComQueue::sendBuffer(Fw::Buffer& buffer, FwIndexType queueIndex) { // Context value is used to determine what to do when the buffer returns on the dataReturnIn port ComCfg::FrameContext context; + FwPacketDescriptorType descriptor; + Fw::SerializeStatus status = buffer.getDeserializer().deserialize(descriptor); + FW_ASSERT(status == Fw::FW_SERIALIZE_OK, static_cast(status)); + context.setapid(static_cast(descriptor)); context.setcomQueueIndex(queueIndex); + this->dataOut_out(0, buffer, context); - // Set state to WAITING for the status to come back this->m_state = WAITING; } diff --git a/Svc/FprimeDeframer/FprimeDeframer.cpp b/Svc/FprimeDeframer/FprimeDeframer.cpp index d0e99ded5fc..b8b7556e38c 100644 --- a/Svc/FprimeDeframer/FprimeDeframer.cpp +++ b/Svc/FprimeDeframer/FprimeDeframer.cpp @@ -58,11 +58,11 @@ void FprimeDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, cons return; } // Extract packet descriptor from the packet data to set the APID for the Router - FwPacketDescriptorType packetDescriptor; - status = deserializer.deserialize(packetDescriptor); - FW_ASSERT(status == Fw::SerializeStatus::FW_SERIALIZE_OK, status); - ComCfg::FrameContext contextCopy = context; - contextCopy.setapid(static_cast(packetDescriptor)); + // FwPacketDescriptorType packetDescriptor; + // status = deserializer.deserialize(packetDescriptor); + // FW_ASSERT(status == Fw::SerializeStatus::FW_SERIALIZE_OK, status); + // ComCfg::FrameContext contextCopy = context; + // contextCopy.setapid(static_cast(packetDescriptor)); // ---------------- Validate Frame Trailer ---------------- // Deserialize transmitted trailer: trailer is at offset = len(header) + len(body) @@ -94,7 +94,7 @@ void FprimeDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, cons data.setSize(data.getSize() - FprimeProtocol::FrameHeader::SERIALIZED_SIZE - FprimeProtocol::FrameTrailer::SERIALIZED_SIZE); // Emit the deframed data - this->dataOut_out(0, data, contextCopy); + this->dataOut_out(0, data, context); } void FprimeDeframer ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer, const ComCfg::FrameContext& context) { diff --git a/Svc/FprimeRouter/FprimeRouter.cpp b/Svc/FprimeRouter/FprimeRouter.cpp index 6617d11646b..a0c4c457368 100644 --- a/Svc/FprimeRouter/FprimeRouter.cpp +++ b/Svc/FprimeRouter/FprimeRouter.cpp @@ -26,10 +26,18 @@ FprimeRouter ::~FprimeRouter() {} void FprimeRouter ::dataIn_handler(FwIndexType portNum, Fw::Buffer& packetBuffer, const ComCfg::FrameContext& context) { Fw::SerializeStatus status; - // Route based on received APID - switch (context.getapid()) { + Fw::ComPacketType packetType = context.getapid(); + // If APID is unknown (i.e. not provided), attempt to introspect the packet to determine the packet type + if (packetType == Fw::ComPacketType::FW_PACKET_UNKNOWN) { + FwPacketDescriptorType packetDescriptor; + auto esb = packetBuffer.getDeserializer(); + status = esb.deserialize(packetDescriptor); + packetType = static_cast(packetDescriptor); + } + // Route based on received APID (packet type) + switch (packetType) { // Handle a command packet - case ComCfg::APID::FW_PACKET_COMMAND: { + case Fw::ComPacketType::FW_PACKET_COMMAND: { // Allocate a com buffer on the stack Fw::ComBuffer com; // Copy the contents of the packet buffer into the com buffer @@ -44,7 +52,7 @@ void FprimeRouter ::dataIn_handler(FwIndexType portNum, Fw::Buffer& packetBuffer break; } // Handle a file packet - case ComCfg::APID::FW_PACKET_FILE: { + case Fw::ComPacketType::FW_PACKET_FILE: { // If the file uplink output port is connected, send the file packet. Otherwise take no action. if (this->isConnected_fileOut_OutputPort(0)) { // Copy buffer into a new allocated buffer. This lets us return the original buffer with dataReturnOut, From 3781aa13460f841964dbc20ae24ff6dd30d6731f Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Sat, 24 May 2025 12:59:41 -0700 Subject: [PATCH 49/95] Even better ApidManager --- Svc/CCSDS/ApidManager/ApidManager.cpp | 53 ++++++------ Svc/CCSDS/ApidManager/ApidManager.fpp | 7 +- Svc/CCSDS/ApidManager/ApidManager.hpp | 28 ++++-- .../SpacePacketDeframer.cpp | 26 +++--- .../test/ut/SpacePacketDeframerTestMain.cpp | 9 +- .../test/ut/SpacePacketDeframerTester.cpp | 86 +++++-------------- .../test/ut/SpacePacketDeframerTester.hpp | 6 +- .../SpacePacketFramer/SpacePacketFramer.cpp | 1 + default/config/ComCfg.fpp | 3 +- 9 files changed, 94 insertions(+), 125 deletions(-) diff --git a/Svc/CCSDS/ApidManager/ApidManager.cpp b/Svc/CCSDS/ApidManager/ApidManager.cpp index ba238074023..77f33477b5d 100644 --- a/Svc/CCSDS/ApidManager/ApidManager.cpp +++ b/Svc/CCSDS/ApidManager/ApidManager.cpp @@ -15,16 +15,13 @@ namespace CCSDS { // ---------------------------------------------------------------------- ApidManager ::ApidManager(const char* const compName) : ApidManagerComponentBase(compName) { - // Initialize the APID sequence table with APID values that need to be counted (order does not matter) - this->m_apidSequences[0].apid = ComCfg::APID::FW_PACKET_LOG; + // Initialize APID sequence table with common APID values + // This step is not strictly necessary, but it ensures that the most common APIDs are tracked + this->m_apidSequences[0].apid = ComCfg::APID::FW_PACKET_COMMAND; this->m_apidSequences[1].apid = ComCfg::APID::FW_PACKET_TELEM; - this->m_apidSequences[2].apid = ComCfg::APID::FW_PACKET_FILE; - this->m_apidSequences[3].apid = ComCfg::APID::FW_PACKET_PACKETIZED_TLM; - this->m_apidSequences[4].apid = ComCfg::APID::FW_PACKET_UNKNOWN; - this->m_apidSequences[5].apid = ComCfg::APID::FW_PACKET_COMMAND; - this->m_apidSequences[6].apid = ComCfg::APID::SPP_FILE_DOWNLINK; - this->m_apidSequences[7].apid = ComCfg::APID::FW_PACKET_DP; - this->m_apidSequences[8].apid = ComCfg::APID::MY_USER_APID_EXAMPLE; + this->m_apidSequences[2].apid = ComCfg::APID::FW_PACKET_LOG; + this->m_apidSequences[3].apid = ComCfg::APID::FW_PACKET_FILE; + this->m_apidSequences[4].apid = ComCfg::APID::FW_PACKET_PACKETIZED_TLM; } ApidManager ::~ApidManager() {} @@ -35,10 +32,7 @@ ApidManager ::~ApidManager() {} U16 ApidManager ::validateApidSeqCountIn_handler(FwIndexType portNum, const ComCfg::APID& apid, U16 receivedSeqCount) { U16 expectedSequenceCount = this->getAndIncrementSeqCount(apid); - if (expectedSequenceCount == SEQUENCE_COUNT_ERROR) { - // This APID is not being tracked - this->log_ACTIVITY_LO_UntrackedApid(apid); - } else if (receivedSeqCount != expectedSequenceCount) { + if (receivedSeqCount != expectedSequenceCount) { // Likely a packet was dropped or out of order this->log_WARNING_HI_UnexpectedSequenceCount(receivedSeqCount, expectedSequenceCount); // Synchronize onboard count with received number so that count can keep going @@ -48,12 +42,7 @@ U16 ApidManager ::validateApidSeqCountIn_handler(FwIndexType portNum, const ComC } U16 ApidManager ::getApidSeqCountIn_handler(FwIndexType portNum, const ComCfg::APID& apid, U16 unused) { - U16 expectedSequenceCount = this->getAndIncrementSeqCount(apid); - if (expectedSequenceCount == SEQUENCE_COUNT_ERROR) { - // This APID is not being tracked - this->log_ACTIVITY_LO_UntrackedApid(apid); - } - return expectedSequenceCount; + return this->getAndIncrementSeqCount(apid); } // ---------------------------------------------------------------------- @@ -61,26 +50,36 @@ U16 ApidManager ::getApidSeqCountIn_handler(FwIndexType portNum, const ComCfg::A // ---------------------------------------------------------------------- U16 ApidManager ::getAndIncrementSeqCount(ComCfg::APID::T apid) { + U16 seqCount = SEQUENCE_COUNT_ERROR; // Default to error value + // Search the APID in the sequence table + for (U8 i = 0; i < MAX_TRACKED_APIDS; ++i) { + if (this->m_apidSequences[i].apid == apid) { + seqCount = this->m_apidSequences[i].sequenceCount; + this->m_apidSequences[i].sequenceCount = (seqCount + 1) % (1 << 14); // Increment for next call + return seqCount; // Return the current sequence count + } + } + // If not found, search for an uninitialized entry to track this APID for (U8 i = 0; i < MAX_TRACKED_APIDS; ++i) { - if (m_apidSequences[i].apid == apid) { - U16 seq = m_apidSequences[i].sequenceCount; - m_apidSequences[i].sequenceCount = (seq + 1) % (1 << 14); // Wrap around at 14 bits - return seq; + if (this->m_apidSequences[i].apid == ComCfg::APID::INVALID_UNINITIALIZED) { + this->m_apidSequences[i].apid = apid; // Initialize this entry with the new APID + seqCount = this->m_apidSequences[i].sequenceCount; // Entries default to 0 unless otherwise specified + this->m_apidSequences[i].sequenceCount = (seqCount + 1) % (1 << 14); // Increment for next call + return seqCount; // Return the initialized sequence count } } - // NOTE: log untracked APID on downlink as well? that's kind of a coding error? + this->log_WARNING_HI_ApidTableFull(apid); return SEQUENCE_COUNT_ERROR; } void ApidManager::setNextSeqCount(ComCfg::APID::T apid, U16 seqCount) { for (U8 i = 0; i < MAX_TRACKED_APIDS; i++) { - if (m_apidSequences[i].apid == apid) { - m_apidSequences[i].sequenceCount = seqCount; + if (this->m_apidSequences[i].apid == apid) { + this->m_apidSequences[i].sequenceCount = seqCount; return; } } } } // namespace CCSDS - } // namespace Svc diff --git a/Svc/CCSDS/ApidManager/ApidManager.fpp b/Svc/CCSDS/ApidManager/ApidManager.fpp index 688c8ce640e..de8d0369f99 100644 --- a/Svc/CCSDS/ApidManager/ApidManager.fpp +++ b/Svc/CCSDS/ApidManager/ApidManager.fpp @@ -12,10 +12,9 @@ module CCSDS { format "Unexpected sequence count received. Packets may have been lost. Transmitted: {} | Expected on board: {}" @ Received an unregistered APID - event UntrackedApid(invalidApidValue: U16) \ - severity activity low \ - format "Received APID not registered with the deframer. Not checking sequence count. APID={}" - + event ApidTableFull(invalidApidValue: U16) \ + severity warning high \ + format "APID Table is full, cannot generate or check sequence counts for APID: {}" ############################################################################### # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # diff --git a/Svc/CCSDS/ApidManager/ApidManager.hpp b/Svc/CCSDS/ApidManager/ApidManager.hpp index dbee34885ea..b0f8edb6fe4 100644 --- a/Svc/CCSDS/ApidManager/ApidManager.hpp +++ b/Svc/CCSDS/ApidManager/ApidManager.hpp @@ -13,8 +13,24 @@ namespace Svc { namespace CCSDS { -class ApidManager final : public ApidManagerComponentBase { +static_assert(ComCfg::APID::SPP_IDLE_PACKET == 0x07FF, + "SPP_IDLE_PACKET must exist and equal 0x07FF (as specified by standard)"); +static_assert(ComCfg::APID::INVALID_UNINITIALIZED == 0x0800, + "Invalid APID must be 0x0800 (11 bits values allow 0-2047)"); +static_assert(ComCfg::APID::FW_PACKET_COMMAND == Fw::ComPacketType::FW_PACKET_COMMAND, + "APID FW_PACKET_COMMAND must exist, used by the Framework"); +static_assert(ComCfg::APID::FW_PACKET_TELEM == Fw::ComPacketType::FW_PACKET_TELEM, + "APID FW_PACKET_TELEM must exist, used by the Framework"); +static_assert(ComCfg::APID::FW_PACKET_LOG == Fw::ComPacketType::FW_PACKET_LOG, + "APID FW_PACKET_LOG must exist, used by the Framework"); +static_assert(ComCfg::APID::FW_PACKET_FILE == Fw::ComPacketType::FW_PACKET_FILE, + "APID FW_PACKET_FILE must exist, used by the Framework"); +static_assert(ComCfg::APID::FW_PACKET_PACKETIZED_TLM == Fw::ComPacketType::FW_PACKET_PACKETIZED_TLM, + "APID FW_PACKET_PACKETIZED_TLM must exist, used by the Framework"); +static_assert(ComCfg::APID::FW_PACKET_UNKNOWN == Fw::ComPacketType::FW_PACKET_UNKNOWN, + "APID FW_PACKET_UNKNOWN must exist, used by the Framework"); +class ApidManager final : public ApidManagerComponentBase { static constexpr U8 MAX_TRACKED_APIDS = ComCfg::APID::NUM_CONSTANTS; static constexpr U16 SEQUENCE_COUNT_ERROR = std::numeric_limits::max(); @@ -37,13 +53,14 @@ class ApidManager final : public ApidManagerComponentBase { //! Handler implementation for validateApidSeqCountIn U16 validateApidSeqCountIn_handler(FwIndexType portNum, //!< The port number - const ComCfg::APID& apid, - U16 seqCount) override; + const ComCfg::APID& apid, + U16 seqCount) override; //! Handler implementation for validateApidSeqCountIn U16 getApidSeqCountIn_handler(FwIndexType portNum, //!< The port number const ComCfg::APID& apid, U16 seqCount) override; + private: // ---------------------------------------------------------------------- // Helpers @@ -52,12 +69,13 @@ class ApidManager final : public ApidManagerComponentBase { //! Wraps around at 14 bits U16 getAndIncrementSeqCount(ComCfg::APID::T apid); + //! Set the next expected sequence count for a given APID void setNextSeqCount(ComCfg::APID::T apid, U16 seqCount); //! This struct helps track sequence counts per APID struct ApidSequenceEntry { - ComCfg::APID::T apid = ComCfg::APID::FW_PACKET_UNKNOWN; - U16 sequenceCount; + ComCfg::APID::T apid = ComCfg::APID::INVALID_UNINITIALIZED; + U16 sequenceCount = 0; }; private: diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp index ceac41d7db8..9399b19238a 100644 --- a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp @@ -16,13 +16,7 @@ namespace CCSDS { // Component construction and destruction // ---------------------------------------------------------------------- -SpacePacketDeframer ::SpacePacketDeframer(const char* const compName) : SpacePacketDeframerComponentBase(compName) { - // Initialize the APID sequence table with APID values that need to be counted (order does not matter) - // this->m_apidSequences[0].apid = ComCfg::APID::FW_PACKET_COMMAND; - // this->m_apidSequences[2].apid = ComCfg::APID::FW_PACKET_FILE; - // this->m_apidSequences[3].apid = ComCfg::APID::FW_PACKET_PACKETIZED_TLM; - // this->m_apidSequences[4].apid = ComCfg::APID::FW_PACKET_UNKNOWN; -} +SpacePacketDeframer ::SpacePacketDeframer(const char* const compName) : SpacePacketDeframerComponentBase(compName) {} SpacePacketDeframer ::~SpacePacketDeframer() {} @@ -52,20 +46,22 @@ void SpacePacketDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, Fw::SerializeStatus status = data.getDeserializer().deserialize(header); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); + U16 pkt_length = header.getpacketDataLength(); + if (pkt_length > data.getSize() - SpacePacketHeader::SERIALIZED_SIZE) { + U32 maxDataAvailable = data.getSize() - SpacePacketHeader::SERIALIZED_SIZE; + this->log_WARNING_HI_InvalidLength(pkt_length, maxDataAvailable); + this->dataReturnOut_out(0, data, context); // Drop the packet + return; + } + U16 apidValue = header.getpacketIdentification() & SpacePacketMasks::ApidMask; ComCfg::APID::T apid = static_cast(apidValue); ComCfg::FrameContext contextCopy = context; contextCopy.setapid(apid); - U16 pkt_length = header.getpacketDataLength(); - if (pkt_length > data.getSize()) { - this->log_WARNING_HI_InvalidLength(pkt_length, data.getSize()); - this->dataReturnOut_out(0, data, context); // Drop the packet - return; - } - U16 receivedSequenceCount = header.getpacketSequenceControl() & SpacePacketMasks::SeqCountMask; // Validate with the ApidManager that the sequence count is correct - (void) this->validateApidSeqCount_out(0, apid, receivedSequenceCount); + U16 receivedSequenceCount = header.getpacketSequenceControl() & SpacePacketMasks::SeqCountMask; + (void)this->validateApidSeqCount_out(0, apid, receivedSequenceCount); contextCopy.setsequenceCount(receivedSequenceCount); // Set data buffer to be of the encapsulated data: HEADER (6 bytes) | PACKET DATA diff --git a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTestMain.cpp b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTestMain.cpp index d66a16f8b2d..fba4a5418b1 100644 --- a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTestMain.cpp +++ b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTestMain.cpp @@ -16,14 +16,9 @@ TEST(Nominal, testNominalDeframing) { tester.testNominalDeframing(); } -TEST(Nominal, testDeframingUntrackedApid) { +TEST(Nominal, testDeframingIncorrectLength) { Svc::CCSDS::SpacePacketDeframerTester tester; - tester.testDeframingUntrackedApid(); -} - -TEST(Nominal, testDeframingIncorrectSeqCount) { - Svc::CCSDS::SpacePacketDeframerTester tester; - tester.testDeframingIncorrectSeqCount(); + tester.testDeframingIncorrectLength(); } int main(int argc, char** argv) { diff --git a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp index 12431af6b0e..1eb32e8544b 100644 --- a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp +++ b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp @@ -46,13 +46,9 @@ void SpacePacketDeframerTester ::testNominalDeframing() { U16 dataLength = static_cast(STest::Random::lowerUpper(1, MAX_TEST_PACKET_DATA_SIZE)); // bytes of data, random length U8 data[dataLength]; - Fw::Buffer buffer = this->assemblePacket(apid, seqCount, dataLength, data); + Fw::Buffer buffer = this->assemblePacket(apid, seqCount, dataLength, data, dataLength); ComCfg::FrameContext nullContext; - // Add the APID to the tracked APID list for nominal deframing - this->component.m_apidSequences[0].apid = apid; - this->component.m_apidSequences[0].sequenceCount = seqCount; - this->invoke_to_dataIn(0, buffer, nullContext); // Check output packet payload @@ -70,82 +66,46 @@ void SpacePacketDeframerTester ::testNominalDeframing() { ASSERT_EVENTS_SIZE(0); // No events should be generated in the nominal case } -void SpacePacketDeframerTester ::testDeframingUntrackedApid() { - U16 apid = 0x7FF - 2; // Unspecified APID +void SpacePacketDeframerTester ::testDeframingIncorrectLength() { + ComCfg::APID::T apid = static_cast(STest::Random::lowerUpper(0, 0x7FF)); // random 11 bit APID U16 seqCount = static_cast(STest::Random::lowerUpper(0, 0x3FFF)); // random 14 bit sequence count - U16 dataLength = static_cast(STest::Random::lowerUpper(1, MAX_TEST_PACKET_DATA_SIZE)); // bytes of data, random length - U8 data[dataLength]; + U16 realDataLength = static_cast(STest::Random::lowerUpper(1, MAX_TEST_PACKET_DATA_SIZE)); // bytes of data, random length + U16 invalidLengthToken = realDataLength + 1; // Length token is greater than actual data available + U8 data[realDataLength]; - Fw::Buffer buffer = this->assemblePacket(apid, seqCount, dataLength, data); + Fw::Buffer buffer = this->assemblePacket(apid, seqCount, invalidLengthToken, data, realDataLength); ComCfg::FrameContext nullContext; this->invoke_to_dataIn(0, buffer, nullContext); - // Check output packet payload - ASSERT_from_dataOut_SIZE(1); - Fw::Buffer outBuffer = this->fromPortHistory_dataOut->at(0).data; - ASSERT_EQ(outBuffer.getSize(), dataLength); - for (U32 i = 0; i < dataLength; ++i) { - ASSERT_EQ(outBuffer.getData()[i], data[i]); - } - // Check output context (header info) - ComCfg::FrameContext outContext = this->fromPortHistory_dataOut->at(0).context; - ASSERT_EQ(outContext.getapid(), apid); - ASSERT_EQ(outContext.getsequenceCount(), seqCount); - // Check event logging that untracked APID was received - ASSERT_EVENTS_SIZE(1); - ASSERT_EVENTS_UntrackedApid_SIZE(1); -} - -void SpacePacketDeframerTester ::testDeframingIncorrectSeqCount() { - U16 apid = ComCfg::APID::FW_PACKET_COMMAND; - U16 dataLength = static_cast(STest::Random::lowerUpper(1, MAX_TEST_PACKET_DATA_SIZE)); // bytes of data, random length - U8 data[dataLength]; - U16 receivedSeqCount = static_cast(STest::Random::lowerUpper(1, 0x3FFF)); // random 14 bit sequence count - U16 expectedSeqCount = receivedSeqCount - 1; // effectively mocks a packet drop - - Fw::Buffer buffer = this->assemblePacket(apid, receivedSeqCount, dataLength, data); - ComCfg::FrameContext nullContext; - - // Add the APID to the tracked APID list for nominal deframing - this->component.m_apidSequences[0].apid = ComCfg::APID::FW_PACKET_COMMAND; - this->component.m_apidSequences[0].sequenceCount = expectedSeqCount; - - this->invoke_to_dataIn(0, buffer, nullContext); - - // Check output packet payload - ASSERT_from_dataOut_SIZE(1); - Fw::Buffer outBuffer = this->fromPortHistory_dataOut->at(0).data; - ASSERT_EQ(outBuffer.getSize(), dataLength); - for (U32 i = 0; i < dataLength; ++i) { - ASSERT_EQ(outBuffer.getData()[i], data[i]); - } - // Check output context (header info) - ComCfg::FrameContext outContext = this->fromPortHistory_dataOut->at(0).context; - ASSERT_EQ(outContext.getapid(), apid); - ASSERT_EQ(outContext.getsequenceCount(), receivedSeqCount); - // Check event logging that untracked APID was received - ASSERT_EVENTS_SIZE(1); - ASSERT_EVENTS_UnexpectedSequenceCount_SIZE(1); - ASSERT_EVENTS_UnexpectedSequenceCount(0, receivedSeqCount, expectedSeqCount); - // Check that the sequence count was updated to the next after the received one - ASSERT_EQ(this->component.m_apidSequences[0].sequenceCount, receivedSeqCount + 1); + // No data emitted + ASSERT_from_dataOut_SIZE(0); + // Data returned (frame dropped) + ASSERT_from_dataReturnOut_SIZE(1); + Fw::Buffer returnedBuffer = this->fromPortHistory_dataReturnOut->at(0).data; + ASSERT_EQ(returnedBuffer.getSize(), buffer.getSize()); + ASSERT_EQ(this->fromPortHistory_dataReturnOut->at(0).context, nullContext); // Data should be the same as input + + // Event logging failure + ASSERT_EVENTS_SIZE(1); // No events should be generated in the nominal case + ASSERT_EVENTS_InvalidLength_SIZE(1); // No events should be generated in the nominal case + ASSERT_EVENTS_InvalidLength(0, invalidLengthToken, realDataLength); } // ---------------------------------------------------------------------- // Helper functions // ---------------------------------------------------------------------- -Fw::Buffer SpacePacketDeframerTester ::assemblePacket(U16 apid, U16 seqCount, U16 packetLength, U8* packetData) { +Fw::Buffer SpacePacketDeframerTester ::assemblePacket(U16 apid, U16 seqCount, U16 lengthToken, U8* packetData, U16 packetDataLen) { SpacePacketHeader header; header.setpacketIdentification(apid); header.setpacketSequenceControl(seqCount); // Sequence Flags = 0b11 (unsegmented) & unused Seq count - header.setpacketDataLength(packetLength); + header.setpacketDataLength(lengthToken); Fw::ExternalSerializeBuffer serializer(static_cast(this->m_packetBuffer), sizeof(this->m_packetBuffer)); serializer.serialize(header); - serializer.serialize(packetData, packetLength, Fw::Serialization::OMIT_LENGTH); - return Fw::Buffer(this->m_packetBuffer, static_cast(sizeof(this->m_packetBuffer))); + serializer.serialize(packetData, packetDataLen, Fw::Serialization::OMIT_LENGTH); + return Fw::Buffer(this->m_packetBuffer, static_cast(packetDataLen + SpacePacketHeader::SERIALIZED_SIZE)); } } // namespace CCSDS diff --git a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.hpp b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.hpp index 86a6a436ddc..82dc81b5bd1 100644 --- a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.hpp +++ b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.hpp @@ -45,8 +45,8 @@ class SpacePacketDeframerTester final : public SpacePacketDeframerGTestBase { void testDataReturnPassthrough(); void testNominalDeframing(); - void testDeframingUntrackedApid(); - void testDeframingIncorrectSeqCount(); + void testDeframingIncorrectLength(); + // void testDeframingIncorrectSeqCount(); private: // ---------------------------------------------------------------------- @@ -60,7 +60,7 @@ class SpacePacketDeframerTester final : public SpacePacketDeframerGTestBase { void initComponents(); //! Assemble a packet with the given parameters - Fw::Buffer assemblePacket(U16 apid, U16 seqCount, U16 packetLength, U8* packetData); + Fw::Buffer assemblePacket(U16 apid, U16 seqCount, U16 lengthToken, U8* packetData, U16 packetDataLen); private: // ---------------------------------------------------------------------- diff --git a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp index fa78982147b..22dff8173e1 100644 --- a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp +++ b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp @@ -49,6 +49,7 @@ void SpacePacketFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, c packetSequenceControl |= 0x3 << SpacePacketMasks::SeqFlagsOffset; // Sequence Flags 0b11 = unsegmented User Data U16 sequenceCount = this->getApidSeqCount_out(0, apid, 0); // retrieve the sequence count for this APID + // NOTE: this will assert if ApidManager's table is full - should it?? FW_ASSERT((sequenceCount >> 14) == 0, static_cast(sequenceCount)); // sequence count must fit in 14 bits packetSequenceControl |= sequenceCount & SpacePacketMasks::SeqCountMask; // 14 bit sequence count diff --git a/default/config/ComCfg.fpp b/default/config/ComCfg.fpp index a1c6edf026b..d4ba87a5aa2 100644 --- a/default/config/ComCfg.fpp +++ b/default/config/ComCfg.fpp @@ -26,7 +26,8 @@ module ComCfg { SPP_FILE_DOWNLINK = 0x0103 @< Extra APID for File packets on downlink so APID isn't shared between uplink and downlink MY_USER_APID_EXAMPLE = 0x0777 @< Example APID for user defined packets SPP_IDLE_PACKET = 0x07FF @< Per Space Packet Standard, all 1s (11bits) is reserved for Idle Packets - } default FW_PACKET_UNKNOWN + INVALID_UNINITIALIZED = 0x0800 @< Anything equal or higher value is invalid and should not be used + } default INVALID_UNINITIALIZED @ Type used to pass context info between components during framing/deframing struct FrameContext { From b82ba4b1b8fe9bf48b55731cc1321a773f4e8028 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Sat, 24 May 2025 13:30:24 -0700 Subject: [PATCH 50/95] Add SpacePacketFramer UTs --- Svc/CCSDS/SpacePacketFramer/CMakeLists.txt | 20 ++-- .../test/ut/SpacePacketFramerTestMain.cpp | 27 +++++ .../test/ut/SpacePacketFramerTester.cpp | 101 ++++++++++++++++++ .../test/ut/SpacePacketFramerTester.hpp | 89 +++++++++++++++ 4 files changed, 227 insertions(+), 10 deletions(-) create mode 100644 Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTestMain.cpp create mode 100644 Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTester.cpp create mode 100644 Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTester.hpp diff --git a/Svc/CCSDS/SpacePacketFramer/CMakeLists.txt b/Svc/CCSDS/SpacePacketFramer/CMakeLists.txt index 72db320a4d6..0e09408bb35 100644 --- a/Svc/CCSDS/SpacePacketFramer/CMakeLists.txt +++ b/Svc/CCSDS/SpacePacketFramer/CMakeLists.txt @@ -21,13 +21,13 @@ register_fprime_library( ### Unit Tests ### -# set(UT_SOURCE_FILES -# "${CMAKE_CURRENT_LIST_DIR}/SpacePacketFramer.fpp" -# "${CMAKE_CURRENT_LIST_DIR}/test/ut/SpacePacketFramerTestMain.cpp" -# "${CMAKE_CURRENT_LIST_DIR}/test/ut/SpacePacketFramerTester.cpp" -# ) -# set(UT_MOD_DEPS -# STest -# ) -# set(UT_AUTO_HELPERS ON) -# register_fprime_ut() +register_fprime_ut( + SOURCES + "${CMAKE_CURRENT_LIST_DIR}/test/ut/SpacePacketFramerTestMain.cpp" + "${CMAKE_CURRENT_LIST_DIR}/test/ut/SpacePacketFramerTester.cpp" + AUTOCODER_INPUTS + "${CMAKE_CURRENT_LIST_DIR}/SpacePacketFramer.fpp" + DEPENDS + STest + UT_AUTO_HELPERS +) \ No newline at end of file diff --git a/Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTestMain.cpp b/Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTestMain.cpp new file mode 100644 index 00000000000..86a5df36261 --- /dev/null +++ b/Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTestMain.cpp @@ -0,0 +1,27 @@ +// ====================================================================== +// \title SpacePacketFramerTestMain.cpp +// \author chammard +// \brief cpp file for SpacePacketFramer component test main function +// ====================================================================== + +#include "SpacePacketFramerTester.hpp" + +TEST(Nominal, testComStatusPassthrough) { + Svc::CCSDS::SpacePacketFramerTester tester; + tester.testComStatusPassthrough(); +} + +TEST(Nominal, testDataReturnPassthrough) { + Svc::CCSDS::SpacePacketFramerTester tester; + tester.testDataReturnPassthrough(); +} + +TEST(Nominal, testNominalFraming) { + Svc::CCSDS::SpacePacketFramerTester tester; + tester.testNominalFraming(); +} + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTester.cpp b/Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTester.cpp new file mode 100644 index 00000000000..00a9194486f --- /dev/null +++ b/Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTester.cpp @@ -0,0 +1,101 @@ +// ====================================================================== +// \title SpacePacketFramerTester.cpp +// \author chammard +// \brief cpp file for SpacePacketFramer component test harness implementation class +// ====================================================================== + +#include "SpacePacketFramerTester.hpp" +#include "STest/Random/Random.hpp" + +namespace Svc { + +namespace CCSDS { + +// ---------------------------------------------------------------------- +// Construction and destruction +// ---------------------------------------------------------------------- + +SpacePacketFramerTester ::SpacePacketFramerTester() + : SpacePacketFramerGTestBase("SpacePacketFramerTester", SpacePacketFramerTester::MAX_HISTORY_SIZE), + component("SpacePacketFramer") { + this->initComponents(); + this->connectPorts(); +} + +SpacePacketFramerTester ::~SpacePacketFramerTester() {} + +// ---------------------------------------------------------------------- +// Tests +// ---------------------------------------------------------------------- + +void SpacePacketFramerTester::testComStatusPassthrough() { + // Simulate a comStatusIn event and check comStatusOut + Fw::Success status = Fw::Success::SUCCESS; + this->invoke_to_comStatusIn(0, status); + ASSERT_from_comStatusOut_SIZE(1); + ASSERT_EQ(this->fromPortHistory_comStatusOut->at(0).condition, status); + this->clearHistory(); + status = Fw::Success::FAILURE; + this->invoke_to_comStatusIn(0, status); + ASSERT_from_comStatusOut_SIZE(1); + ASSERT_EQ(this->fromPortHistory_comStatusOut->at(0).condition, status); +} + +void SpacePacketFramerTester::testDataReturnPassthrough() { + // Simulate a dataReturnIn event and check bufferDeallocate_out + U8 data[8] = {0}; + Fw::Buffer buffer(data, sizeof(data)); + ComCfg::FrameContext context; + this->invoke_to_dataReturnIn(0, buffer, context); + ASSERT_from_bufferDeallocate_SIZE(1); + ASSERT_EQ(this->fromPortHistory_bufferDeallocate->at(0).fwBuffer.getData(), data); + ASSERT_EQ(this->fromPortHistory_bufferDeallocate->at(0).fwBuffer.getSize(), sizeof(data)); +} + +void SpacePacketFramerTester::testNominalFraming() { + // Simulate framing a buffer and check output + U8 payload[16]; + for (U32 i = 0; i < sizeof(payload); ++i) { + payload[i] = static_cast(STest::Random::lowerUpper(0, 0xFF)); + } + Fw::Buffer data(payload, sizeof(payload)); + ComCfg::APID::T apid = static_cast(STest::Random::lowerUpper(0, 0x7FF)); // random 11 bit APID + U16 seqCount = static_cast(STest::Random::lowerUpper(0, 0x3FFF)); // random 14 bit sequence count + ComCfg::FrameContext context; + context.setapid(apid); + this->m_nextSeqCount = seqCount; // seqCount to be returned by getApidSeqCount output port + + this->invoke_to_dataIn(0, data, context); + + // Check dataOut + ASSERT_from_dataOut_SIZE(1); + Fw::Buffer outBuffer = this->fromPortHistory_dataOut->at(0).data; + ASSERT_EQ(outBuffer.getSize(), sizeof(payload) + SpacePacketHeader::SERIALIZED_SIZE); + // Check that the payload is present at the correct offset + for (U32 i = 0; i < sizeof(payload); ++i) { + ASSERT_EQ(outBuffer.getData()[SpacePacketHeader::SERIALIZED_SIZE + i], payload[i]); + } + // Check that dataReturnOut is called for the original buffer + ASSERT_from_dataReturnOut_SIZE(1); + ASSERT_EQ(this->fromPortHistory_dataReturnOut->at(0).data.getData(), payload); + ASSERT_EQ(this->fromPortHistory_dataReturnOut->at(0).data.getSize(), sizeof(payload)); +} + +// ---------------------------------------------------------------------- +// Output port handler overrides +// ---------------------------------------------------------------------- + +U16 SpacePacketFramerTester ::from_getApidSeqCount_handler(FwIndexType portNum, + const ComCfg::APID& apid, + U16 sequenceCount) { + return this->m_nextSeqCount; +} + +Fw::Buffer SpacePacketFramerTester ::from_bufferAllocate_handler(FwIndexType portNum, + U32 size) { + return Fw::Buffer(this->m_internalDataBuffer, size); +} + +} // namespace CCSDS + +} // namespace Svc diff --git a/Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTester.hpp b/Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTester.hpp new file mode 100644 index 00000000000..b0539f36996 --- /dev/null +++ b/Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTester.hpp @@ -0,0 +1,89 @@ +// ====================================================================== +// \title SpacePacketFramerTester.hpp +// \author chammard +// \brief hpp file for SpacePacketFramer component test harness implementation class +// ====================================================================== + +#ifndef Svc_CCSDS_SpacePacketFramerTester_HPP +#define Svc_CCSDS_SpacePacketFramerTester_HPP + +#include "Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp" +#include "Svc/CCSDS/SpacePacketFramer/SpacePacketFramerGTestBase.hpp" +#include "Svc/CCSDS/Types/SpacePacketHeaderSerializableAc.hpp" + +namespace Svc { + +namespace CCSDS { + +class SpacePacketFramerTester final : public SpacePacketFramerGTestBase { + public: + // ---------------------------------------------------------------------- + // Constants + // ---------------------------------------------------------------------- + + // Maximum size of histories storing events, telemetry, and port outputs + static const FwSizeType MAX_HISTORY_SIZE = 10; + + // Instance ID supplied to the component instance under test + static const FwEnumStoreType TEST_INSTANCE_ID = 0; + + public: + // ---------------------------------------------------------------------- + // Construction and destruction + // ---------------------------------------------------------------------- + + //! Construct object SpacePacketFramerTester + SpacePacketFramerTester(); + + //! Destroy object SpacePacketFramerTester + ~SpacePacketFramerTester(); + + public: + // ---------------------------------------------------------------------- + // Tests + // ---------------------------------------------------------------------- + + void testComStatusPassthrough(); + void testDataReturnPassthrough(); + void testNominalFraming(); + + private: + // ---------------------------------------------------------------------- + // Helper functions + // ---------------------------------------------------------------------- + + //! Connect ports + void connectPorts(); + + //! Initialize components + void initComponents(); + + // ---------------------------------------------------------------------- + // Test Harness: output port overrides + // ---------------------------------------------------------------------- + U16 from_getApidSeqCount_handler(FwIndexType portNum, //!< The port number + const ComCfg::APID& apid, + U16 sequenceCount) override; + + Fw::Buffer from_bufferAllocate_handler(FwIndexType portNum, U32 size) override; + + private: + // ---------------------------------------------------------------------- + // Member variables + // ---------------------------------------------------------------------- + + //! The component under test + SpacePacketFramer component; + + //! Test buffer + static const FwSizeType MAX_TEST_PACKET_DATA_SIZE = 200; + U8 m_internalDataBuffer[SpacePacketHeader::SERIALIZED_SIZE + MAX_TEST_PACKET_DATA_SIZE]; + + U16 m_nextSeqCount; // Sequence count to be returned by getApidSeqCount output port +}; + +} // namespace CCSDS + +} // namespace Svc + +#endif From 58cac6d70fd3149cad181decf8115cb5a0393f73 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Sat, 24 May 2025 13:57:33 -0700 Subject: [PATCH 51/95] Set up rule based testing for ApidManager --- Svc/CCSDS/ApidManager/ApidManager.hpp | 3 + Svc/CCSDS/ApidManager/CMakeLists.txt | 21 ++-- .../test/ut/ApidManagerTestMain.cpp | 18 ++++ .../ApidManager/test/ut/ApidManagerTester.cpp | 43 ++++++++ .../ApidManager/test/ut/ApidManagerTester.hpp | 100 ++++++++++++++++++ .../test/ut/SpacePacketDeframerTestMain.cpp | 6 +- .../test/ut/SpacePacketFramerTestMain.cpp | 6 +- .../TMFramer/test/ut/TMFramerTestMain.cpp | 6 +- 8 files changed, 184 insertions(+), 19 deletions(-) create mode 100644 Svc/CCSDS/ApidManager/test/ut/ApidManagerTestMain.cpp create mode 100644 Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp create mode 100644 Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.hpp diff --git a/Svc/CCSDS/ApidManager/ApidManager.hpp b/Svc/CCSDS/ApidManager/ApidManager.hpp index b0f8edb6fe4..1b386ad38cb 100644 --- a/Svc/CCSDS/ApidManager/ApidManager.hpp +++ b/Svc/CCSDS/ApidManager/ApidManager.hpp @@ -8,6 +8,7 @@ #define Svc_CCSDS_ApidManager_HPP #include "Svc/CCSDS/ApidManager/ApidManagerComponentAc.hpp" +#include "Fw/Com/ComPacket.hpp" namespace Svc { @@ -31,6 +32,8 @@ static_assert(ComCfg::APID::FW_PACKET_UNKNOWN == Fw::ComPacketType::FW_PACKET_UN "APID FW_PACKET_UNKNOWN must exist, used by the Framework"); class ApidManager final : public ApidManagerComponentBase { + friend class ApidManagerTester; //!< Friend class for testing + static constexpr U8 MAX_TRACKED_APIDS = ComCfg::APID::NUM_CONSTANTS; static constexpr U16 SEQUENCE_COUNT_ERROR = std::numeric_limits::max(); diff --git a/Svc/CCSDS/ApidManager/CMakeLists.txt b/Svc/CCSDS/ApidManager/CMakeLists.txt index dbb2bec41cd..ca7e1a2aa4c 100644 --- a/Svc/CCSDS/ApidManager/CMakeLists.txt +++ b/Svc/CCSDS/ApidManager/CMakeLists.txt @@ -20,13 +20,14 @@ register_fprime_library( ### Unit Tests ### -# set(UT_SOURCE_FILES -# "${CMAKE_CURRENT_LIST_DIR}/ApidManager.fpp" -# "${CMAKE_CURRENT_LIST_DIR}/test/ut/ApidManagerTestMain.cpp" -# "${CMAKE_CURRENT_LIST_DIR}/test/ut/ApidManagerTester.cpp" -# ) -# set(UT_MOD_DEPS -# STest -# ) -# set(UT_AUTO_HELPERS ON) -# register_fprime_ut() +register_fprime_ut( + SOURCES + "${CMAKE_CURRENT_LIST_DIR}/test/ut/ApidManagerTestMain.cpp" + "${CMAKE_CURRENT_LIST_DIR}/test/ut/ApidManagerTester.cpp" + AUTOCODER_INPUTS + "${CMAKE_CURRENT_LIST_DIR}/ApidManager.fpp" + DEPENDS + Svc_CCSDS_Types + STest + UT_AUTO_HELPERS +) diff --git a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTestMain.cpp b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTestMain.cpp new file mode 100644 index 00000000000..bd29ea31582 --- /dev/null +++ b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTestMain.cpp @@ -0,0 +1,18 @@ +// ====================================================================== +// \title ApidManagerTestMain.cpp +// \author chammard +// \brief cpp file for ApidManager component test main function +// ====================================================================== + +#include "ApidManagerTester.hpp" + +TEST(ApidManager, getExistingSeqCount) { + Svc::CCSDS::ApidManagerTester tester; + Svc::CCSDS::ApidManagerTester::GetExistingSeqCount rule1; + rule1.apply(tester); +} + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp new file mode 100644 index 00000000000..31311ec21b3 --- /dev/null +++ b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp @@ -0,0 +1,43 @@ +// ====================================================================== +// \title ApidManagerTester.cpp +// \author chammard +// \brief cpp file for ApidManager component test harness implementation class +// ====================================================================== + +#include "ApidManagerTester.hpp" + +namespace Svc { + +namespace CCSDS { + +// ---------------------------------------------------------------------- +// Construction and destruction +// ---------------------------------------------------------------------- + +ApidManagerTester ::ApidManagerTester() + : ApidManagerGTestBase("ApidManagerTester", ApidManagerTester::MAX_HISTORY_SIZE), component("ApidManager") { + this->initComponents(); + this->connectPorts(); +} + +ApidManagerTester ::~ApidManagerTester() {} + +// ---------------------------------------------------------------------- +// Tests +// ---------------------------------------------------------------------- + +void ApidManagerTester ::toDo() { + // TODO +} + +bool ApidManagerTester::GetExistingSeqCount::precondition(const ApidManagerTester& state) { + return true; +} + +void ApidManagerTester::GetExistingSeqCount::action(ApidManagerTester& state) { + ASSERT_TRUE(true); +} + +} // namespace CCSDS + +} // namespace Svc diff --git a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.hpp b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.hpp new file mode 100644 index 00000000000..275428c8fd5 --- /dev/null +++ b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.hpp @@ -0,0 +1,100 @@ +// ====================================================================== +// \title ApidManagerTester.hpp +// \author chammard +// \brief hpp file for ApidManager component test harness implementation class +// ====================================================================== + +#ifndef Svc_CCSDS_ApidManagerTester_HPP +#define Svc_CCSDS_ApidManagerTester_HPP + +#include "Svc/CCSDS/ApidManager/ApidManager.hpp" +#include "Svc/CCSDS/ApidManager/ApidManagerGTestBase.hpp" +#include "STest/Rule/Rule.hpp" + +namespace Svc { + +namespace CCSDS { + +class ApidManagerTester final : public ApidManagerGTestBase { + friend class ApidManagerTester; + + public: + // ---------------------------------------------------------------------- + // Constants + // ---------------------------------------------------------------------- + + // Maximum size of histories storing events, telemetry, and port outputs + static const FwSizeType MAX_HISTORY_SIZE = 10; + + // Instance ID supplied to the component instance under test + static const FwEnumStoreType TEST_INSTANCE_ID = 0; + + public: + // ---------------------------------------------------------------------- + // Construction and destruction + // ---------------------------------------------------------------------- + + //! Construct object ApidManagerTester + ApidManagerTester(); + + //! Destroy object ApidManagerTester + ~ApidManagerTester(); + + public: + // ---------------------------------------------------------------------- + // Tests + // ---------------------------------------------------------------------- + + //! To do + void toDo(); + + private: + // ---------------------------------------------------------------------- + // Helper functions + // ---------------------------------------------------------------------- + + //! Connect ports + void connectPorts(); + + //! Initialize components + void initComponents(); + + private: + // ---------------------------------------------------------------------- + // Member variables + // ---------------------------------------------------------------------- + + //! The component under test + ApidManager component; + + std::map existingSeqCounts; //!< Map to hold existing sequence counts for APIDs + + U16 shadow_getAndIncrementSeqCount(ComCfg::APID::T apid) { + // This is a shadow function to simulate the getAndIncrementSeqCount behavior + // without modifying the actual component state. + auto found = this->existingSeqCounts.find(apid); + if (found != this->existingSeqCounts.end()) { + U16 seqCount = found->second; + found->second = (seqCount + 1) % (1 << 14); // Increment for next call + return seqCount; // Return the current sequence count + } + return ApidManager::SEQUENCE_COUNT_ERROR; // Return error if APID not found + } + + // ---------------------------------------------------------------------- + // Rules (Rule-based testing) + // ---------------------------------------------------------------------- + public: + struct GetExistingSeqCount : public STest::Rule { + GetExistingSeqCount(): STest::Rule("GetExistingSeqCount") {}; + bool precondition(const ApidManagerTester &state); + void action(ApidManagerTester &state); + }; + +}; + +} // namespace CCSDS + +} // namespace Svc + +#endif diff --git a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTestMain.cpp b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTestMain.cpp index fba4a5418b1..230d8a288a5 100644 --- a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTestMain.cpp +++ b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTestMain.cpp @@ -6,17 +6,17 @@ #include "SpacePacketDeframerTester.hpp" -TEST(Nominal, testDataReturnPassthrough) { +TEST(SpacePacketDeframer, testDataReturnPassthrough) { Svc::CCSDS::SpacePacketDeframerTester tester; tester.testDataReturnPassthrough(); } -TEST(Nominal, testNominalDeframing) { +TEST(SpacePacketDeframer, testNominalDeframing) { Svc::CCSDS::SpacePacketDeframerTester tester; tester.testNominalDeframing(); } -TEST(Nominal, testDeframingIncorrectLength) { +TEST(SpacePacketDeframer, testDeframingIncorrectLength) { Svc::CCSDS::SpacePacketDeframerTester tester; tester.testDeframingIncorrectLength(); } diff --git a/Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTestMain.cpp b/Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTestMain.cpp index 86a5df36261..e85c3b2ec42 100644 --- a/Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTestMain.cpp +++ b/Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTestMain.cpp @@ -6,17 +6,17 @@ #include "SpacePacketFramerTester.hpp" -TEST(Nominal, testComStatusPassthrough) { +TEST(SpacePacketFramer, testComStatusPassthrough) { Svc::CCSDS::SpacePacketFramerTester tester; tester.testComStatusPassthrough(); } -TEST(Nominal, testDataReturnPassthrough) { +TEST(SpacePacketFramer, testDataReturnPassthrough) { Svc::CCSDS::SpacePacketFramerTester tester; tester.testDataReturnPassthrough(); } -TEST(Nominal, testNominalFraming) { +TEST(SpacePacketFramer, testNominalFraming) { Svc::CCSDS::SpacePacketFramerTester tester; tester.testNominalFraming(); } diff --git a/Svc/CCSDS/TMFramer/test/ut/TMFramerTestMain.cpp b/Svc/CCSDS/TMFramer/test/ut/TMFramerTestMain.cpp index 0b0c7df7c09..d6973502675 100644 --- a/Svc/CCSDS/TMFramer/test/ut/TMFramerTestMain.cpp +++ b/Svc/CCSDS/TMFramer/test/ut/TMFramerTestMain.cpp @@ -6,17 +6,17 @@ #include "TMFramerTester.hpp" -TEST(Nominal, testComStatusPassthrough) { +TEST(TMFramer, testComStatusPassthrough) { Svc::CCSDS::TMFramerTester tester; tester.testComStatusPassthrough(); } -TEST(Nominal, testNominalFraming) { +TEST(TMFramer, testNominalFraming) { Svc::CCSDS::TMFramerTester tester; tester.testNominalFraming(); } -TEST(Nominal, testSeqCountWrapAround) { +TEST(TMFramer, testSeqCountWrapAround) { Svc::CCSDS::TMFramerTester tester; tester.testSeqCountWrapAround(); } From 59f211cc1ffca49aa13369942e32797113464d49 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Tue, 27 May 2025 12:40:27 -0700 Subject: [PATCH 52/95] Code cleanup and fix TMFramer UT --- .../SpacePacketFramer/SpacePacketFramer.cpp | 2 +- Svc/CCSDS/TCDeframer/TCDeframer.cpp | 4 +- .../TCDeframer/test/ut/TCDeframerTestMain.cpp | 8 ++-- .../TCDeframer/test/ut/TCDeframerTester.cpp | 44 +++++++++---------- .../TCDeframer/test/ut/TCDeframerTester.hpp | 2 +- Svc/CCSDS/TMFramer/TMFramer.cpp | 10 ++--- Svc/CCSDS/TMFramer/TMFramer.hpp | 2 +- Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp | 6 +-- Svc/CCSDS/Types/Types.fpp | 37 ++++++++-------- 9 files changed, 58 insertions(+), 57 deletions(-) diff --git a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp index 22dff8173e1..dc707aa5aa2 100644 --- a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp +++ b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp @@ -49,7 +49,7 @@ void SpacePacketFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, c packetSequenceControl |= 0x3 << SpacePacketMasks::SeqFlagsOffset; // Sequence Flags 0b11 = unsegmented User Data U16 sequenceCount = this->getApidSeqCount_out(0, apid, 0); // retrieve the sequence count for this APID - // NOTE: this will assert if ApidManager's table is full - should it?? + // NOTE: this will assert if ApidManager's table is full (because error value is max(U16)) - should it?? FW_ASSERT((sequenceCount >> 14) == 0, static_cast(sequenceCount)); // sequence count must fit in 14 bits packetSequenceControl |= sequenceCount & SpacePacketMasks::SeqCountMask; // 14 bit sequence count diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.cpp b/Svc/CCSDS/TCDeframer/TCDeframer.cpp index 165cfe92031..87049058d79 100644 --- a/Svc/CCSDS/TCDeframer/TCDeframer.cpp +++ b/Svc/CCSDS/TCDeframer/TCDeframer.cpp @@ -20,7 +20,7 @@ namespace CCSDS { TCDeframer ::TCDeframer(const char* const compName) : TCDeframerComponentBase(compName), - m_spacecraftId(ComCfg::FppConstant_SpacecraftId::SpacecraftId) {} + m_spacecraftId(ComCfg::SpacecraftId) {} TCDeframer ::~TCDeframer() {} @@ -42,7 +42,7 @@ void TCDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const Co // 10b- XX - Spacecraft ID // 6b - XX - Virtual Channel ID // 10b- XX - Frame Length - // 8b - XX - Frame Sequence Number + // 8b - XX - Frame Sequence Number (unused for Type-B frames) // CCSDS TC Trailer: // 16b - Frame Error Control Field (FECF): CRC16 diff --git a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTestMain.cpp b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTestMain.cpp index 52dc06f7612..84cabd71ae1 100644 --- a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTestMain.cpp +++ b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTestMain.cpp @@ -31,10 +31,10 @@ TEST(TCDeframer, testInvalidLengthToken) { tester.testInvalidLengthToken(); } -TEST(TCDeframer, testInvalidSequenceNumber) { - Svc::CCSDS::TCDeframerTester tester; - tester.testInvalidSequenceNumber(); -} +// TEST(TCDeframer, testInvalidSequenceNumber) { +// Svc::CCSDS::TCDeframerTester tester; +// tester.testInvalidSequenceNumber(); +// } TEST(TCDeframer, testInvalidCrc) { Svc::CCSDS::TCDeframerTester tester; diff --git a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp index 40f99ddc11e..afb636ace64 100644 --- a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp +++ b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp @@ -128,27 +128,27 @@ void TCDeframerTester::testInvalidLengthToken() { ASSERT_EVENTS_InvalidFrameLength(0, fakeLength, dataLength); } -void TCDeframerTester::testInvalidSequenceNumber() { - U8 dataLength = static_cast(STest::Random::lowerUpper(1, 200)); // bytes of data, random length - U8 data[dataLength]; - U8 expectedSeqCount = static_cast(STest::Random::lowerUpper(1, 0xFF)); // random 8 bit sequence count - U8 invalidSeqCount = expectedSeqCount - 1; // invalid sequence count - - Fw::Buffer buffer = this->assembleFrameBuffer(data, dataLength, 0, 0, invalidSeqCount); - ComCfg::FrameContext nullContext; - - this->setComponentState(0, 0, expectedSeqCount); - this->invoke_to_dataIn(0, buffer, nullContext); - - // Invalid sequence number should emit a warning but deframe data (not dropping the frame) - ASSERT_from_dataOut_SIZE(1); - ASSERT_from_dataReturnOut_SIZE(0); - ASSERT_EQ(this->fromPortHistory_dataOut->at(0).data.getData(), buffer.getData()); - ASSERT_EQ(this->fromPortHistory_dataOut->at(0).data.getSize(), dataLength); - ASSERT_EVENTS_SIZE(1); // exactly 1 event emitted - ASSERT_EVENTS_UnexpectedSequenceNumber_SIZE(1); - ASSERT_EVENTS_UnexpectedSequenceNumber(0, invalidSeqCount, expectedSeqCount); -} +// void TCDeframerTester::testInvalidSequenceNumber() { +// U8 dataLength = static_cast(STest::Random::lowerUpper(1, 200)); // bytes of data, random length +// U8 data[dataLength]; +// U8 expectedSeqCount = static_cast(STest::Random::lowerUpper(1, 0xFF)); // random 8 bit sequence count +// U8 invalidSeqCount = expectedSeqCount - 1; // invalid sequence count + +// Fw::Buffer buffer = this->assembleFrameBuffer(data, dataLength, 0, 0, invalidSeqCount); +// ComCfg::FrameContext nullContext; + +// this->setComponentState(0, 0, expectedSeqCount); +// this->invoke_to_dataIn(0, buffer, nullContext); + +// // Invalid sequence number should emit a warning but deframe data (not dropping the frame) +// ASSERT_from_dataOut_SIZE(1); +// ASSERT_from_dataReturnOut_SIZE(0); +// ASSERT_EQ(this->fromPortHistory_dataOut->at(0).data.getData(), buffer.getData()); +// ASSERT_EQ(this->fromPortHistory_dataOut->at(0).data.getSize(), dataLength); +// ASSERT_EVENTS_SIZE(1); // exactly 1 event emitted +// ASSERT_EVENTS_UnexpectedSequenceNumber_SIZE(1); +// ASSERT_EVENTS_UnexpectedSequenceNumber(0, invalidSeqCount, expectedSeqCount); +// } void TCDeframerTester::testInvalidCrc() { U8 dataLength = static_cast(STest::Random::lowerUpper(1, 200)); // bytes of data, random length @@ -174,7 +174,7 @@ void TCDeframerTester::testInvalidCrc() { void TCDeframerTester::setComponentState(U16 scid, U8 vcid, U8 sequenceNumber, bool acceptAllVcid) { this->component.m_spacecraftId = scid; this->component.m_vcId = vcid; - this->component.m_sequenceCount = sequenceNumber; + // this->component.m_sequenceCount = sequenceNumber; this->component.m_acceptAllVcid = acceptAllVcid; } diff --git a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.hpp b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.hpp index abcd565a148..bb54d34ebdc 100644 --- a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.hpp +++ b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.hpp @@ -47,7 +47,7 @@ class TCDeframerTester final : public TCDeframerGTestBase { void testInvalidScId(); void testInvalidVcId(); void testInvalidLengthToken(); - void testInvalidSequenceNumber(); + // void testInvalidSequenceNumber(); void testInvalidCrc(); diff --git a/Svc/CCSDS/TMFramer/TMFramer.cpp b/Svc/CCSDS/TMFramer/TMFramer.cpp index f81a8a6fb92..92cdcf0c016 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.cpp +++ b/Svc/CCSDS/TMFramer/TMFramer.cpp @@ -31,7 +31,7 @@ TMFramer ::~TMFramer() {} void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { // TODO: make this an event probably - FW_ASSERT(data.getSize() <= ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize, + FW_ASSERT(data.getSize() <= ComCfg::TmFrameFixedSize, static_cast(data.getSize())); // ----------------------------------------------- @@ -40,7 +40,7 @@ void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComC TMFrameHeader header; U16 globalVcId = 0; - globalVcId |= ComCfg::FppConstant_SpacecraftId::SpacecraftId << TMFrameMasks::spacecraftIdOffset; + globalVcId |= ComCfg::SpacecraftId << TMFrameMasks::spacecraftIdOffset; globalVcId |= context.getvcId() << TMFrameMasks::virtualChannelIdOffset; globalVcId |= 0x0; // Operational Control Field: Flag set to 0 @@ -85,7 +85,7 @@ void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComC // Set the Frame Error Control Field (FECF) trailer.setfecf(crc); // Move the serializer pointer to the end of the location where the trailer will be serialized - frameSerializer.moveSerToOffset(ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize - + frameSerializer.moveSerToOffset(ComCfg::TmFrameFixedSize - TMFrameTrailer::SERIALIZED_SIZE); status = frameSerializer.serialize(trailer); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); @@ -111,7 +111,7 @@ void TMFramer ::dataReturnIn_handler(FwIndexType portNum, } void TMFramer ::fill_with_idle_packet(Fw::SerializeBufferBase& serializer) { - constexpr U16 endIndex = ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize - + constexpr U16 endIndex = ComCfg::TmFrameFixedSize - TMFrameTrailer::SERIALIZED_SIZE; constexpr U16 idleApid = static_cast(ComCfg::APID::SPP_IDLE_PACKET); const U16 startIndex = static_cast(serializer.getBuffLength()); @@ -119,7 +119,7 @@ void TMFramer ::fill_with_idle_packet(Fw::SerializeBufferBase& serializer) { FW_ASSERT(idlePacketLength > 0, static_cast(idlePacketLength)); FW_ASSERT(idlePacketLength >= 7, static_cast(idlePacketLength)); // 7 bytes minimum for idle packet - FW_ASSERT(idlePacketLength <= ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize, + FW_ASSERT(idlePacketLength <= ComCfg::TmFrameFixedSize, static_cast(idlePacketLength)); SpacePacketHeader header; diff --git a/Svc/CCSDS/TMFramer/TMFramer.hpp b/Svc/CCSDS/TMFramer/TMFramer.hpp index a6520ee0163..52bb3585f67 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.hpp +++ b/Svc/CCSDS/TMFramer/TMFramer.hpp @@ -72,7 +72,7 @@ class TMFramer final : public TMFramerComponentBase { // Because the TM protocol use fixed width frames, and only one frame is in transit between ComQueue and // ComInterface at a time, we can use a member fixed-size buffer to hold the frame data - U8 m_frameBuffer[ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize]; //!< Buffer to hold the frame data + U8 m_frameBuffer[ComCfg::TmFrameFixedSize]; //!< Buffer to hold the frame data // Current implementation uses a single virtual channel, so we can use a single virtual frame count U8 m_masterFrameCount; //!< Master Frame Count - 8 bits - wraps around at 255 diff --git a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp index 4c896f90776..f9e0d52f573 100644 --- a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp +++ b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp @@ -58,7 +58,7 @@ void TMFramerTester ::testNominalFraming() { ASSERT_from_dataOut_SIZE(1); Fw::Buffer outBuffer = this->fromPortHistory_dataOut->at(0).data; ComCfg::FrameContext outContext = this->fromPortHistory_dataOut->at(0).context; - ASSERT_EQ(outBuffer.getSize(), ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize); + ASSERT_EQ(outBuffer.getSize(), ComCfg::TmFrameFixedSize); ASSERT_EQ(this->fromPortHistory_dataOut->at(0).context.getvcId(), defaultContext.getvcId()); U16 outScId = this->getFrameScId(outBuffer.getData()); @@ -66,7 +66,7 @@ void TMFramerTester ::testNominalFraming() { U8 outMcCount = this->getFrameMcCount(outBuffer.getData()); U8 outVcCount = this->getFrameVcCount(outBuffer.getData()); - ASSERT_EQ(outScId, ComCfg::FppConstant_SpacecraftId::SpacecraftId); + ASSERT_EQ(outScId, ComCfg::SpacecraftId); ASSERT_EQ(outVcId, defaultContext.getvcId()); ASSERT_EQ(outMcCount, 0); ASSERT_EQ(outVcCount, 0); @@ -77,7 +77,7 @@ void TMFramerTester ::testNominalFraming() { FwSizeType expectedIdleDataOffset = TMFrameHeader::SERIALIZED_SIZE + sizeof(bufferData) + SpacePacketHeader::SERIALIZED_SIZE; // The frame is composed of the payload + a SpacePacket Idle Packet (Header + idle_pattern) - for (FwSizeType i = expectedIdleDataOffset; i < ComCfg::FppConstant_TmFrameFixedSize::TmFrameFixedSize - TMFrameTrailer::SERIALIZED_SIZE; ++i) { + for (FwSizeType i = expectedIdleDataOffset; i < ComCfg::TmFrameFixedSize - TMFrameTrailer::SERIALIZED_SIZE; ++i) { ASSERT_EQ(outBuffer.getData()[i], 0x44); } } diff --git a/Svc/CCSDS/Types/Types.fpp b/Svc/CCSDS/Types/Types.fpp index f2e43879c76..6f013908d3f 100644 --- a/Svc/CCSDS/Types/Types.fpp +++ b/Svc/CCSDS/Types/Types.fpp @@ -9,30 +9,31 @@ module CCSDS { # with the approriate mask to module SpacePacketMasks { - # packetIdentification sub-fields |-- 16 bits ---| - constant PvnMask = 0xE000; @< 0b1110000000000000 - constant PktTypeMask = 0x1000; @< 0b0001000000000000 - constant SecHdrMask = 0x0800; @< 0b0000100000000000 - constant ApidMask = 0x07FF; @< 0b0000011111111111 - constant PvnOffset = 13; - constant PktTypeOffset = 12; - constant SecHdrOffset = 11; + # packetIdentification sub-fields |--- 16 bits ---| + constant PvnMask = 0xE000 @< 0b1110000000000000 + constant PktTypeMask = 0x1000 @< 0b0001000000000000 + constant SecHdrMask = 0x0800 @< 0b0000100000000000 + constant ApidMask = 0x07FF @< 0b0000011111111111 + constant PvnOffset = 13 + constant PktTypeOffset = 12 + constant SecHdrOffset = 11 # packetSequenceControl sub-fields - constant SeqFlagsMask = 0xC000; @< 0b1100000000000000 - constant SeqCountMask = 0x3FFF; @< 0b0011111111111111 - constant SeqFlagsOffset = 14; + constant SeqFlagsMask = 0xC000 @< 0b1100000000000000 + constant SeqCountMask = 0x3FFF @< 0b0011111111111111 + constant SeqFlagsOffset = 14 } module TCFrameMasks { # flagsAndScId sub-fields - constant FrameVersionMask = 0xC000; @< 0b1100000000000000 - constant BypassFlagMask = 0x2000; @< 0b0010000000000000 - constant ControlFlagMask = 0x1000; @< 0b0001000000000000 - constant ReservedMask = 0x0C00; @< 0b0000110000000000 - constant SpacecraftIdMask = 0x03FF; @< 0b0000001111111111 + constant FrameVersionMask = 0xC000 @< 0b1100000000000000 + constant BypassFlagMask = 0x2000 @< 0b0010000000000000 + constant ControlFlagMask = 0x1000 @< 0b0001000000000000 + constant ReservedMask = 0x0C00 @< 0b0000110000000000 + constant SpacecraftIdMask = 0x03FF @< 0b0000001111111111 + constant BypassFlagOffset = 13 # vcIdAndLength sub-fields - constant VcIdMask = 0xFC00; @< 0b1111110000000000 - constant FrameLengthMask = 0x03FF; @< 0b0000001111111111 + constant VcIdMask = 0xFC00 @< 0b1111110000000000 + constant FrameLengthMask = 0x03FF @< 0b0000001111111111 constant VcIdOffset = 10 } From 6c70bbcfeb099b5f84b197ed3dc79db36de72057 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 28 May 2025 17:37:44 -0700 Subject: [PATCH 53/95] First pass at SDDs and stuff --- Fw/Com/ComPacket.hpp | 2 +- Svc/CCSDS/ApidManager/ApidManager.hpp | 3 +- .../test/ut/ApidManagerTestMain.cpp | 38 +++++++ .../ApidManager/test/ut/ApidManagerTester.cpp | 61 +++++++++++- .../ApidManager/test/ut/ApidManagerTester.hpp | 47 ++++++++- .../SpacePacketDeframer.fpp | 18 ++-- Svc/CCSDS/SpacePacketDeframer/docs/sdd.md | 77 +++++---------- Svc/CCSDS/SpacePacketFramer/docs/sdd.md | 75 +++++--------- Svc/CCSDS/TCDeframer/docs/sdd.md | 99 +++++++------------ Svc/CCSDS/TMFramer/docs/sdd.md | 79 +++++---------- default/config/ComCfg.fpp | 9 +- 11 files changed, 263 insertions(+), 245 deletions(-) diff --git a/Fw/Com/ComPacket.hpp b/Fw/Com/ComPacket.hpp index 7163ec145cd..8e328b13d4a 100644 --- a/Fw/Com/ComPacket.hpp +++ b/Fw/Com/ComPacket.hpp @@ -17,7 +17,7 @@ namespace Fw { // This type is defined in config/ComCfg.fpp - typedef ComCfg::APID::T ComPacketType; + using ComPacketType = ComCfg::APID::T; class ComPacket: public Serializable { public: diff --git a/Svc/CCSDS/ApidManager/ApidManager.hpp b/Svc/CCSDS/ApidManager/ApidManager.hpp index 1b386ad38cb..aec7aeed04f 100644 --- a/Svc/CCSDS/ApidManager/ApidManager.hpp +++ b/Svc/CCSDS/ApidManager/ApidManager.hpp @@ -34,10 +34,9 @@ static_assert(ComCfg::APID::FW_PACKET_UNKNOWN == Fw::ComPacketType::FW_PACKET_UN class ApidManager final : public ApidManagerComponentBase { friend class ApidManagerTester; //!< Friend class for testing + public: static constexpr U8 MAX_TRACKED_APIDS = ComCfg::APID::NUM_CONSTANTS; static constexpr U16 SEQUENCE_COUNT_ERROR = std::numeric_limits::max(); - - public: // ---------------------------------------------------------------------- // Component construction and destruction // ---------------------------------------------------------------------- diff --git a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTestMain.cpp b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTestMain.cpp index bd29ea31582..42cef27751b 100644 --- a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTestMain.cpp +++ b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTestMain.cpp @@ -5,6 +5,8 @@ // ====================================================================== #include "ApidManagerTester.hpp" +#include "STest/Scenario/BoundedScenario.hpp" +#include "STest/Scenario/RandomScenario.hpp" TEST(ApidManager, getExistingSeqCount) { Svc::CCSDS::ApidManagerTester tester; @@ -12,6 +14,42 @@ TEST(ApidManager, getExistingSeqCount) { rule1.apply(tester); } +// Randomized sequence of conditioned take/release/lock/unlock +TEST(ApidManager, RandomizedInterfaceTesting) { + + Svc::CCSDS::ApidManagerTester tester; + + Svc::CCSDS::ApidManagerTester::GetExistingSeqCount rule1; + Svc::CCSDS::ApidManagerTester::GetNewSeqCountOk rule2; + Svc::CCSDS::ApidManagerTester::GetNewSeqCountTableFull rule3; + // rule1.apply(tester); + + // Place these rules into a list of rules + STest::Rule* rules[] = { + &rule1, + &rule2, + &rule3 + }; + + // Take the rules and place them into a random scenario + STest::RandomScenario random( + "Random Rules", + rules, + FW_NUM_ARRAY_ELEMENTS(rules) + ); + + // Create a bounded scenario wrapping the random scenario + STest::BoundedScenario bounded( + "Bounded Random Rules Scenario", + random, + 1000 + ); + // Run! + const U32 numSteps = bounded.run(tester); + printf("Ran %u steps.\n", numSteps); + // add one run of unlock for safe destruction +} + int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp index 31311ec21b3..1a8f76e770d 100644 --- a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp +++ b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp @@ -5,11 +5,18 @@ // ====================================================================== #include "ApidManagerTester.hpp" +#include "STest/Random/Random.hpp" namespace Svc { namespace CCSDS { +static constexpr ComCfg::APID::T TEST_REGISTERED_APIDS[] = { + ComCfg::APID::FW_PACKET_COMMAND, + ComCfg::APID::FW_PACKET_TELEM, + ComCfg::APID::FW_PACKET_LOG, + ComCfg::APID::FW_PACKET_FILE +}; // ---------------------------------------------------------------------- // Construction and destruction // ---------------------------------------------------------------------- @@ -18,6 +25,12 @@ ApidManagerTester ::ApidManagerTester() : ApidManagerGTestBase("ApidManagerTester", ApidManagerTester::MAX_HISTORY_SIZE), component("ApidManager") { this->initComponents(); this->connectPorts(); + // Initialize existing sequence counts for common APIDs + for (FwIndexType i = 0; i < static_cast(FW_NUM_ARRAY_ELEMENTS(TEST_REGISTERED_APIDS)); i++) { + this->component.m_apidSequences[i].apid = TEST_REGISTERED_APIDS[i]; + this->shadow_seqCounts[TEST_REGISTERED_APIDS[i]] = 0; // Initialize shadow sequence counts to 0 + + } } ApidManagerTester ::~ApidManagerTester() {} @@ -30,14 +43,52 @@ void ApidManagerTester ::toDo() { // TODO } -bool ApidManagerTester::GetExistingSeqCount::precondition(const ApidManagerTester& state) { - return true; +bool ApidManagerTester::GetExistingSeqCount::precondition(const ApidManagerTester& testerState) { + return true; // Can always get existing sequence count } -void ApidManagerTester::GetExistingSeqCount::action(ApidManagerTester& state) { - ASSERT_TRUE(true); +void ApidManagerTester::GetExistingSeqCount::action(ApidManagerTester& testerState) { + ComCfg::APID::T apid = testerState.getRandomTrackedApid(); + U16 seqCount = testerState.invoke_to_getApidSeqCountIn(0, apid, 0); + U16 shadownSeqCount = testerState.shadow_getAndIncrementSeqCount(apid); + ASSERT_EQ(seqCount, shadownSeqCount) + << "Sequence count for APID " << static_cast(apid) << " does not match shadow value." + << " Shadow: " << shadownSeqCount << ", Actual: " << seqCount; } -} // namespace CCSDS +bool ApidManagerTester::GetNewSeqCountOk::precondition(const ApidManagerTester& testerState) { + return testerState.shadow_isTableFull == false; +} + +void ApidManagerTester::GetNewSeqCountOk::action(ApidManagerTester& testerState) { + bool isTableFull = testerState.shadow_seqCounts.size() >= testerState.component.MAX_TRACKED_APIDS; + if (isTableFull) { + testerState.shadow_isTableFull = true; + return; // Cannot get new sequence count if table is full - skip action + } + + ComCfg::APID::T apid = testerState.getRandomUntrackedApid(); + U16 seqCount = testerState.invoke_to_getApidSeqCountIn(0, apid, 0); + U16 shadownSeqCount = testerState.shadow_getAndIncrementSeqCount(apid); + ASSERT_EQ(seqCount, shadownSeqCount) + << "Sequence count for APID " << static_cast(apid) << " does not match shadow value." + << " Shadow: " << shadownSeqCount << ", Actual: " << seqCount; +} + +bool ApidManagerTester::GetNewSeqCountTableFull::precondition(const ApidManagerTester& testerState) { + return testerState.shadow_isTableFull == true; +} + +void ApidManagerTester::GetNewSeqCountTableFull::action(ApidManagerTester& testerState) { + ComCfg::APID::T apid = testerState.getRandomUntrackedApid(); + U16 seqCount = testerState.invoke_to_getApidSeqCountIn(0, apid, 0); + ASSERT_EQ(seqCount, testerState.component.SEQUENCE_COUNT_ERROR) + << "Expected SEQUENCE_COUNT_ERROR for untracked APID " << static_cast(apid) + << ", but got " << seqCount; + testerState.assertEvents_ApidTableFull_size(__FILE__, __LINE__, 1); + testerState.assertEvents_ApidTableFull(__FILE__, __LINE__, 0, static_cast(apid)); +} + +} // namespace CCSDS } // namespace Svc diff --git a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.hpp b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.hpp index 275428c8fd5..10af42ebc2e 100644 --- a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.hpp +++ b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.hpp @@ -10,15 +10,16 @@ #include "Svc/CCSDS/ApidManager/ApidManager.hpp" #include "Svc/CCSDS/ApidManager/ApidManagerGTestBase.hpp" #include "STest/Rule/Rule.hpp" +#include "STest/Random/Random.hpp" namespace Svc { namespace CCSDS { class ApidManagerTester final : public ApidManagerGTestBase { - friend class ApidManagerTester; public: + // ---------------------------------------------------------------------- // Constants // ---------------------------------------------------------------------- @@ -67,20 +68,44 @@ class ApidManagerTester final : public ApidManagerGTestBase { //! The component under test ApidManager component; - std::map existingSeqCounts; //!< Map to hold existing sequence counts for APIDs + std::map shadow_seqCounts; //!< Map to hold existing sequence counts for APIDs + bool shadow_isTableFull = false; U16 shadow_getAndIncrementSeqCount(ComCfg::APID::T apid) { // This is a shadow function to simulate the getAndIncrementSeqCount behavior // without modifying the actual component state. - auto found = this->existingSeqCounts.find(apid); - if (found != this->existingSeqCounts.end()) { + auto found = this->shadow_seqCounts.find(apid); + if (found != this->shadow_seqCounts.end()) { U16 seqCount = found->second; found->second = (seqCount + 1) % (1 << 14); // Increment for next call return seqCount; // Return the current sequence count } - return ApidManager::SEQUENCE_COUNT_ERROR; // Return error if APID not found + // If APID not found, initialize a new entry + if (this->shadow_seqCounts.size() < this->component.MAX_TRACKED_APIDS) { + U16 seqCount = 0; + this->shadow_seqCounts[apid] = seqCount + 1; // increment for next call + return seqCount; // Return the initialized sequence count + } + return this->component.SEQUENCE_COUNT_ERROR; // Return error if APID not found + } + + ComCfg::APID::T getRandomTrackedApid() { + // Select a random APID from the sequence counts map + U32 mapSize = static_cast(this->shadow_seqCounts.size()); + U32 randomIndex = STest::Random::lowerUpper(0, mapSize - 1); + ComCfg::APID apid = std::next(this->shadow_seqCounts.begin(), randomIndex)->first; + return apid; } + ComCfg::APID::T getRandomUntrackedApid() { + // Select a random APID that is not currently tracked + ComCfg::APID::T apid; + do { + apid = static_cast(STest::Random::lowerUpper(10, ComCfg::APID::SPP_IDLE_PACKET)); + } while (this->shadow_seqCounts.find(apid) != this->shadow_seqCounts.end()); + return apid; + } + // ---------------------------------------------------------------------- // Rules (Rule-based testing) // ---------------------------------------------------------------------- @@ -91,6 +116,18 @@ class ApidManagerTester final : public ApidManagerGTestBase { void action(ApidManagerTester &state); }; + struct GetNewSeqCountOk : public STest::Rule { + GetNewSeqCountOk(): STest::Rule("GetNewSeqCountOk") {}; + bool precondition(const ApidManagerTester &state); + void action(ApidManagerTester &state); + }; + + struct GetNewSeqCountTableFull : public STest::Rule { + GetNewSeqCountTableFull(): STest::Rule("GetNewSeqCountTableFull") {}; + bool precondition(const ApidManagerTester &state); + void action(ApidManagerTester &state); + }; + }; } // namespace CCSDS diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp index d978a40ed4f..a2a494844ea 100644 --- a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp @@ -12,15 +12,15 @@ module CCSDS { severity warning high \ format "Invalid length received. Header specified packet length of {} | Actual received data length: {}" - @ Deframing received an unexpected sequence count - event UnexpectedSequenceCount(transmitted: U16, expected: U16) \ - severity warning high \ - format "Unexpected sequence count received. Packets may have been lost. Transmitted: {} | Expected on board: {}" - - @ Deframing received an unexpected sequence count - event UntrackedApid(apid: U16) \ - severity activity low \ - format "Received APID not registered with the deframer. Not checking sequence count. APID={}" + # @ Deframing received an unexpected sequence count + # event UnexpectedSequenceCount(transmitted: U16, expected: U16) \ + # severity warning high \ + # format "Unexpected sequence count received. Packets may have been lost. Transmitted: {} | Expected on board: {}" + + # @ Deframing received an unexpected sequence count + # event UntrackedApid(apid: U16) \ + # severity activity low \ + # format "Received APID not registered with the deframer. Not checking sequence count. APID={}" ############################################################################### # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # diff --git a/Svc/CCSDS/SpacePacketDeframer/docs/sdd.md b/Svc/CCSDS/SpacePacketDeframer/docs/sdd.md index 210f713e75b..b293efb3b92 100644 --- a/Svc/CCSDS/SpacePacketDeframer/docs/sdd.md +++ b/Svc/CCSDS/SpacePacketDeframer/docs/sdd.md @@ -1,66 +1,35 @@ -# CCSDS::SpacePacketDeframer +# Svc::CCSDS::SpacePacketDeframer -Deframer for the CCSDS Space Packet protocol +The `Svc::CCSDS::SpacePacketDeframer` is an implementation of the [DeframerInterface](../../Interfaces/docs/sdd.md) for the CCSDS [Space Packet Protocol](https://ccsds.org/Pubs/133x0b2e2.pdf). -## Usage Examples -Add usage examples here +It receives data containing a Space Packet on its input port and extracts the Space Packet. Please refer to the CCSDS [Space Packet Protocol specification (CCSDS 133.0-B-2)](https://ccsds.org/Pubs/133x0b2e2.pdf) for details on the packet format. -### Diagrams -Add diagrams here - -### Typical Usage -And the typical usage of the component here - -## Class Diagram -Add a class diagram here +The `Svc::CCSDS::SpacePacketDeframer` is typically used downstream of a component that removes transfer frame headers, such as the `Svc::CCSDS::TCDeframer`. It validates the Space Packet header and extracts the payload. ## Port Descriptions -| Name | Description | -|---|---| -|---|---| - -## Component States -Add component states in the chart below -| Name | Description | -|---|---| -|---|---| - -## Sequence Diagrams -Add sequence diagrams here - -## Parameters -| Name | Description | -|---|---| -|---|---| - -## Commands -| Name | Description | -|---|---| -|---|---| +| Kind | Name | Port Type | Description | +|---|---|---|---| +| Input (guarded) | dataIn | Svc.ComDataWithContext | Port to receive data containing a Space Packet | +| Output | dataOut | Svc.ComDataWithContext | Port to output the extracted Space Packet payload | +| Output | dataReturnOut | Svc.ComDataWithContext | Port for returning ownership of received buffers | +| Input (sync) | dataReturnIn | Svc.ComDataWithContext | Port receiving back ownership of sent buffers | +| Output | validateApidSeqCount | CCSDS.ApidSequenceCount | Port to request validation of a sequence count for a given APID | ## Events -| Name | Description | -|---|---| -|---|---| - -## Telemetry -| Name | Description | -|---|---| -|---|---| - -## Unit Tests -Add unit test descriptions in the chart below -| Name | Description | Output | Coverage | -|---|---|---|---| -|---|---|---|---| +| Name | Severity | Description | +|---|---|---| +| InvalidLength | `warning high` | Deframing received an invalid packet length | ## Requirements Add requirements in the chart below | Name | Description | Validation | |---|---|---| -|---|---|---| - -## Change Log -| Date | Description | -|---|---| -|---| Initial Draft | \ No newline at end of file +| SPD-001 | The SpacePacketDeframer shall deframe CCSDS Space Packets according to the CCSDS 133.0-B-2 standard. | Unit Test, Inspection | +| SPD-002 | The SpacePacketDeframer shall extract the user data field from valid Space Packets. | Unit Test | +| SPD-003 | The SpacePacketDeframer shall validate the packet length of a Space Packet Primary Header. | Unit Test | +| SPD-009 | The SpacePacketDeframer shall emit an `InvalidLength` event if the packet length token in the header is cannot fit in the received data, and drop the received packet. | Unit Test | +| SPD-004 | The SpacePacketDeframer shall receive incoming data containing Space Packets via the `dataIn` port. | Unit Test | +| SPD-005 | The SpacePacketDeframer shall output the extracted Space Packet user data via the `dataOut` port. | Unit Test | +| SPD-006 | The SpacePacketDeframer shall manage buffer ownership using the `dataReturnIn` and `dataReturnOut` ports. | Unit Test, Inspection | +| SPD-007 | The SpacePacketDeframer shall delegate sequence count validation to another component through the `validateApidSeqCount` port. | Unit Test | +| SPD-008 | The SpacePacketDeframer shall perform sequence count validation for APIDs registered via `validateApidSeqCount`. | Unit Test | diff --git a/Svc/CCSDS/SpacePacketFramer/docs/sdd.md b/Svc/CCSDS/SpacePacketFramer/docs/sdd.md index 82a30b4883c..96126f522ae 100644 --- a/Svc/CCSDS/SpacePacketFramer/docs/sdd.md +++ b/Svc/CCSDS/SpacePacketFramer/docs/sdd.md @@ -1,66 +1,43 @@ -# CCSDS::SpacePacketFramer + +# Svc::CCSDS::SpacePacketFramer -Deframer for the CCSDS Space Packet protocol +The `Svc::CCSDS::SpacePacketFramer` is an implementation of the [FramerInterface](../../Interfaces/docs/sdd.md) for the CCSDS [Space Packet Protocol](https://public.ccsds.org/Pubs/133x0b2e1.pdf). -## Usage Examples -Add usage examples here +It receives user data on its input port and constructs a CCSDS Space Packet. Please refer to the CCSDS [Space Packet Protocol specification (CCSDS 133.0-B-2)](https://public.ccsds.org/Pubs/133x0b2e1.pdf) for details on the packet format. -### Diagrams -Add diagrams here +The `Svc::CCSDS::SpacePacketFramer` is typically used upstream of a component that adds transfer frame headers, such as the `Svc::CCSDS::TMFramer`. It encapsulates user data into a Space Packet, adding the necessary header fields. -### Typical Usage -And the typical usage of the component here - -## Class Diagram -Add a class diagram here +## Configuration +The `Svc::CCSDS::SpacePacketFramer` requires an Application Process Identifier (APID) for the Space Packets it generates. This APID is typically provided during instantiation or configuration. It also uses a sequence count, which is managed per APID via the `getApidSeqCount` port. ## Port Descriptions -| Name | Description | -|---|---| -|---|---| - -## Component States -Add component states in the chart below -| Name | Description | -|---|---| -|---|---| - -## Sequence Diagrams -Add sequence diagrams here - -## Parameters -| Name | Description | -|---|---| -|---|---| - -## Commands -| Name | Description | -|---|---| -|---|---| +| Kind | Name | Port Type | Description | +|---|---|---|---| +| Input (sync) | dataIn | Svc.ComDataWithContext | Port to receive user data to be framed into a Space Packet | +| Output | dataOut | Svc.ComDataWithContext | Port to output the constructed Space Packet | +| Output | bufferAllocate | Fw.BufferGet | Port to allocate buffers for the outgoing Space Packet | +| Output | bufferDeallocate | Fw.BufferSend | Port to deallocate buffers after the Space Packet is sent | +| Output | getApidSeqCount | CCSDS.ApidSequenceCount | Port to retrieve the current sequence count for a given APID | ## Events -| Name | Description | -|---|---| -|---|---| - -## Telemetry -| Name | Description | -|---|---| -|---|---| - -## Unit Tests -Add unit test descriptions in the chart below -| Name | Description | Output | Coverage | -|---|---|---|---| -|---|---|---|---| +*No component-specific events are defined in the FPP for SpacePacketFramer.* ## Requirements Add requirements in the chart below | Name | Description | Validation | |---|---|---| -|---|---|---| +| SPF-001 | The SpacePacketFramer shall implement the `Svc.FramerInterface`. | Inspection, Unit Test | +| SPF-002 | The SpacePacketFramer shall construct CCSDS Space Packets compliant with the CCSDS 133.0-B-2 standard. | Unit Test, Inspection | +| SPF-003 | The SpacePacketFramer shall accept user data to be framed via its `dataIn` port. | Unit Test | +| SPF-004 | The SpacePacketFramer shall output the constructed Space Packet via its `dataOut` port. | Unit Test | +| SPF-005 | The SpacePacketFramer shall use the `bufferAllocate` port to request memory buffers for outgoing Space Packets. | Unit Test | +| SPF-006 | The SpacePacketFramer shall use the `bufferDeallocate` port to return ownership of buffers after transmission. | Unit Test | +| SPF-007 | The SpacePacketFramer shall utilize the `getApidSeqCount` port to obtain the correct sequence count for the configured APID before framing a packet. | Unit Test | +| SPF-008 | The SpacePacketFramer shall correctly populate all mandatory fields of the Space Packet Primary Header, including Version Number, Packet Type, Secondary Header Flag, APID, Sequence Flags, Packet Sequence Count, and Packet Data Length. | Unit Test | +| SPF-009 | The SpacePacketFramer shall be configurable with an Application Process Identifier (APID) to be used in the Space Packet Header. | Inspection, Unit Test | +| SPF-010 | The SpacePacketFramer shall accurately calculate and set the Packet Data Length field in the Space Packet header based on the length of the user data. | Unit Test | ## Change Log | Date | Description | |---|---| -|---| Initial Draft | \ No newline at end of file +| May 28, 2025 | Initial Draft | \ No newline at end of file diff --git a/Svc/CCSDS/TCDeframer/docs/sdd.md b/Svc/CCSDS/TCDeframer/docs/sdd.md index d052e388cb5..202cef3e1d6 100644 --- a/Svc/CCSDS/TCDeframer/docs/sdd.md +++ b/Svc/CCSDS/TCDeframer/docs/sdd.md @@ -1,84 +1,51 @@ # Svc::TCDeframer -Deframer for the TC Space Data Link Protocl (CCSDS Standard) +The `Svc::CCSDS::TCDeframer` is an implementation of the [DeframerInterface](../../Interfaces/docs/sdd.md) for the CCSDS [TC Space Data Link Protocol](https://ccsds.org/Pubs/232x0b4e1c1.pdf). -- Service Types: Use "Expedited Service" Type-B Frames (meaning no sequence control) -- This means FARM flag is expected to be 0, and sequence control is set to all 0s +It receives payload data (such as a Space Packet or a VCA_SDU) on input and produces a TC frame on its output port as a result. Please refer to the CCSDS [TC specification (CCSDS 232.0-B-4)](https://ccsds.org/Pubs/232x0b4e1c1.pdf) for details on the frame format and protocol. -Implements the following service: -- VIRTUAL CHANNEL PACKET SERVICE +The `Svc::CCSDS::TCDeframer` is designed to work in the common F Prime telemetry stack, receiving data from an upstream [`Svc::ComQueue`](../../../ComQueue/docs/sdd.md) and passing frames to a [Communications Adapter](../../Interfaces/docs/sdd.md), such as a Radio manager component or [`Svc::ComStub`](../../ComStub/docs/sdd.md), for transmission on the wire. It is commonly coupled with the [`Svc::CCSDS::SpacePacketFramer`](../../SpacePacketFramer/docs/sdd.md) to wrap CCSDS Space Packets into TM frames. -Implements the following functions: -- ALL FRAMES RECEPTION FUNCTION -- VC PACKET EXTRACTION FUNCTION (Router is the user to which frame data unit is delivered) ---- OR ------ use VCA_SDU with no Space Packet -- FRAME DELIVERY FUNCTION (Type-BD -> to Router) -- Frame Validation Check Procedure +The TCDeframer currently functions only in the "Expedited Service" mode, for Type-B Frames. This means that should Type-A frames be received, no FARM checks would be performed on board. +## Configuration -Not implemented: -- Sequence Control (Type-A frames) and Control Commands -- +The `TCDeframer` component can be configured with a specific Virtual Channel ID (VCID) and Spacecraft ID. By default, it uses the spacecraft ID from `config/ComCfg.fpp` and accepts all VCIDs. +```cpp +void configure(U16 vcId, U16 spacecraftId, bool acceptAllVcid); +``` -## Usage Examples -Add usage examples here - -### Diagrams -Add diagrams here - -### Typical Usage -And the typical usage of the component here - -## Class Diagram -Add a class diagram here +- `vcId`: The virtual channel ID to accept. This is only used if `acceptAllVcid` is `false`. +- `spacecraftId`: The spacecraft ID to accept. +- `acceptAllVcid`: If `true`, the deframer accepts all VCIDs. If `false`, it only accepts the `vcId` specified. ## Port Descriptions -| Name | Description | -|---|---| -|---|---| - -## Component States -Add component states in the chart below -| Name | Description | -|---|---| -|---|---| - -## Sequence Diagrams -Add sequence diagrams here - -## Parameters -| Name | Description | -|---|---| -|---|---| - -## Commands -| Name | Description | -|---|---| -|---|---| +| Kind | Name | Port Type | Description | +|---|---|---|---| +| Input (guarded) | dataIn | Svc.ComDataWithContext | Port to receive framed data | +| Output | dataOut | Svc.ComDataWithContext | Port to output deframed data | +| Output | dataReturnOut | Svc.ComDataWithContext | Port for returning ownership of received buffers to deframe | +| Input (sync) | dataReturnIn | Svc.ComDataWithContext | Port receiving back ownership of sent buffers | ## Events -| Name | Description | -|---|---| -|---|---| - -## Telemetry -| Name | Description | -|---|---| -|---|---| - -## Unit Tests -Add unit test descriptions in the chart below -| Name | Description | Output | Coverage | -|---|---|---|---| -|---|---|---|---| +| Name | Severity | Description | +|---|---|---| +| InvalidSpacecraftId | `activity low` | Deframing received an invalid SCID | +| InvalidFrameLength | `warning high` | Deframing received an invalid frame length | +| InvalidVcId | `activity low` | Deframing received an invalid VCID | +| InvalidCrc | `warning high` | Deframing received an invalid checksum | ## Requirements Add requirements in the chart below | Name | Description | Validation | |---|---|---| -|---|---|---| - -## Change Log -| Date | Description | -|---|---| -|---| Initial Draft | \ No newline at end of file +| SVC-CCSDS-TCDEFRAMER-001 | The TCDeframer shall deframe Telecommand (TC) Transfer Frames according to the CCSDS Space Data Link Protocol standard for Type-BD frames. | Unit Test, Inspection | +| SVC-CCSDS-TCDEFRAMER-002 | The TCDeframer shall perform Frame Validation Check Procedures, including Spacecraft ID, Virtual Channel ID, Frame Length, and CRC. | Unit Test | +| SVC-CCSDS-TCDEFRAMER-003 | The TCDeframer shall be configurable for a specific Spacecraft ID. | Unit Test, Inspection | +| SVC-CCSDS-TCDEFRAMER-004 | The TCDeframer shall be configurable with a specific Virtual Channel ID (VCID) OR to accept all VCIDs. | Unit Test, Inspection | +| SVC-CCSDS-TCDEFRAMER-005 | The TCDeframer shall log an `InvalidSpacecraftId` event if a frame with an unexpected Spacecraft ID is received. | Unit Test | +| SVC-CCSDS-TCDEFRAMER-006 | The TCDeframer shall log an `InvalidFrameLength` event if a frame with an invalid length is received. | Unit Test | +| SVC-CCSDS-TCDEFRAMER-007 | The TCDeframer shall log an `InvalidVcId` event if a frame with an unexpected VCID is received (when not configured to accept all VCIDs). | Unit Test | +| SVC-CCSDS-TCDEFRAMER-008 | The TCDeframer shall log an `InvalidCrc` event if a frame fails the CRC check. | Unit Test | +| SVC-CCSDS-TCDEFRAMER-009 | The TCDeframer shall provide an input port (`dataIn`) to receive framed data, and emit deframed data packets on its `dataOut` output port. | Unit Test | diff --git a/Svc/CCSDS/TMFramer/docs/sdd.md b/Svc/CCSDS/TMFramer/docs/sdd.md index 505785b0beb..d2ebb210769 100644 --- a/Svc/CCSDS/TMFramer/docs/sdd.md +++ b/Svc/CCSDS/TMFramer/docs/sdd.md @@ -1,66 +1,39 @@ -# Svc::TMFramer +# Svc::CCSDS::TMFramer -Deframer for the TC Space Data Link Protocl (CCSDS Standard) +The `Svc::CCSDS::TMFramer` is an implementation of the [FramerInterface](../../Interfaces/docs/sdd.md) for the CCSDS [TM Space Data Link Protocol](https://ccsds.org/Pubs/132x0b3.pdf). -## Usage Examples -Add usage examples here +It receives payload data (such as a Space Packet or a VCA_SDU) on input and produces a TM frame on its output port as a result. Please refer to the CCSDS [TM specification (CCSDS 132.0-B-3)](https://ccsds.org/Pubs/132x0b3.pdf) for details on the frame format and protocol. -### Diagrams -Add diagrams here +The `Svc::CCSDS::TMFramer` is designed to work in the common F Prime telemetry stack, receiving data from an upstream [`Svc::ComQueue`](../../../ComQueue/docs/sdd.md) and passing frames to a [Communications Adapter](../../Interfaces/docs/sdd.md), such as a Radio manager component or [`Svc::ComStub`](../../ComStub/docs/sdd.md), for transmission on the wire. It is commonly coupled with the [`Svc::CCSDS::SpacePacketFramer`](../../SpacePacketFramer/docs/sdd.md) to wrap CCSDS Space Packets into TM frames. -### Typical Usage -And the typical usage of the component here +## Usage Examples -## Class Diagram -Add a class diagram here +The `Svc::CCSDS::TMFramer` component, as well as the rest of the CCSDS communications stack, is used in the [`Ref/`](https://github.com/nasa/fprime/tree/devel/Ref) example application. It is also generated by the `fprime-util new --deployment` command. ## Port Descriptions -| Name | Description | -|---|---| -|---|---| - -## Component States -Add component states in the chart below -| Name | Description | -|---|---| -|---|---| - -## Sequence Diagrams -Add sequence diagrams here - -## Parameters -| Name | Description | -|---|---| -|---|---| - -## Commands -| Name | Description | -|---|---| -|---|---| - -## Events -| Name | Description | -|---|---| -|---|---| - -## Telemetry -| Name | Description | -|---|---| -|---|---| - -## Unit Tests -Add unit test descriptions in the chart below -| Name | Description | Output | Coverage | -|---|---|---|---| +| Kind | Name | Port Type | Description | |---|---|---|---| +| sync input | dataIn | Svc.ComDataWithContext | Receives data to frame, in a Fw::Buffer with optional context | +| output | dataOut | Svc.ComDataWithContext | Outputs framed data with optional context | +| output | dataReturnOut | Svc.ComDataWithContext | Returns ownership of the incoming Fw::Buffer to its sender once framing is handled | +| sync input | dataReturnIn | Svc.ComDataWithContext | Receives buffer from a deallocate call in a ComDriver component | +| sync input | comStatusIn | Fw.SuccessCondition | Receives general status from downstream component indicating readiness for more input | +| output | comStatusOut | Fw.SuccessCondition | Indicates the status of framer for receiving more data | ## Requirements Add requirements in the chart below | Name | Description | Validation | |---|---|---| -|---|---|---| - -## Change Log -| Date | Description | -|---|---| -|---| Initial Draft | \ No newline at end of file +| SVC-CCSDS-TMFRAMER-001 | The TMFramer shall implement the `Svc.FramerInterface`. | Inspection, Unit Test | +| SVC-CCSDS-TMFRAMER-002 | The TMFramer shall construct CCSDS Telemetry (TM) Transfer Frames compliant with the CCSDS 132.0-B-3 standard. | Unit Test, Inspection | +| SVC-CCSDS-TMFRAMER-003 | The TMFramer shall accept payload data (Space Packets or VCA_SDU) to be framed via its `dataIn` port. | Unit Test | +| SVC-CCSDS-TMFRAMER-004 | The TMFramer shall output the constructed TM Transfer Frame via its `dataOut` port. | Unit Test | +| SVC-CCSDS-TMFRAMER-005 | The TMFramer shall return ownership of the input buffer via the `dataReturnOut` port after the framing process is complete. | Unit Test | +| SVC-CCSDS-TMFRAMER-006 | The TMFramer shall accept returned buffers (previously sent via `dataOut`) through the `dataReturnIn` port for deallocation or reuse. | Unit Test | +| SVC-CCSDS-TMFRAMER-007 | The TMFramer shall receive communication status from downstream components via the `comStatusIn` port, and pass it through to `comStatusOut` | Unit Test, Integration Test | +| SVC-CCSDS-TMFRAMER-008 | The TMFramer shall use exactly one Virtual Channel. | Unit Test, Integration Test | +| SVC-CCSDS-TMFRAMER-009 | The TMFramer shall correctly populate all mandatory fields of the TM Transfer Frame Primary Header, including Transfer Frame Version Number, Spacecraft Identifier, Virtual Channel Identifier, Operational Control Field Flag, Master Channel Frame Count, Virtual Channel Frame Count, Transfer Frame Secondary Header Flag, Synchronization Flag, Packet Order Flag, Segment Length Identifier, and First Header Pointer. | Unit Test, Inspection | +| SVC-CCSDS-TMFRAMER-010 | The TMFramer shall be configurable with a Spacecraft Identifier. | Inspection, Unit Test | +| SVC-CCSDS-TMFRAMER-011 | The TMFramer shall use the Virtual Channel Identifier passed in the `context` object on `dataIn`. | Unit Test | +| SVC-CCSDS-TMFRAMER-012 | The TMFramer shall manage Master Channel Frame Count and Virtual Channel Frame Count. | Unit Test | +| SVC-CCSDS-TMFRAMER-013 | The TMFramer shall fill the data field of the TM Transfer Frame with the payload data received on `dataIn`, and fill up the rest of the fixed-size frame with a single Idle Packet as defined by the protocol. | Unit Test | \ No newline at end of file diff --git a/default/config/ComCfg.fpp b/default/config/ComCfg.fpp index d4ba87a5aa2..7ffbbe18526 100644 --- a/default/config/ComCfg.fpp +++ b/default/config/ComCfg.fpp @@ -8,12 +8,17 @@ module ComCfg { + # Needed in dictionary: + # - spacecraftId + # - TmFrameFixedSize + # - potentially APID enum ? constant SpacecraftId = 0x0044 # Spacecraft ID (10 bits) constant TmFrameFixedSize = 1024 # Needs to be at least COM_BUFFER_MAX_SIZE + (2 * SpacePacketHeaderSize) + 1 @ APIDs are 11 bits in the Space Packet protocol, so we use U16. Max value 7FF enum APID : U16 { - # APIDs prefixed with FW are reserved for F Prime and should not be changed + # APIDs prefixed with FW are reserved for F Prime and need to be present + # in the enumeration. Their values can be changed FW_PACKET_COMMAND = 0x0000 @< Command packet type - incoming FW_PACKET_TELEM = 0x0001 @< Telemetry packet type - outgoing FW_PACKET_LOG = 0x0002 @< Log type - outgoing @@ -29,6 +34,8 @@ module ComCfg { INVALID_UNINITIALIZED = 0x0800 @< Anything equal or higher value is invalid and should not be used } default INVALID_UNINITIALIZED +# TODO ???: add alias with name ComPacketDscriptor for the ComPacket.hpp + @ Type used to pass context info between components during framing/deframing struct FrameContext { comQueueIndex: FwIndexType @< Queue Index used by the ComQueue, other components shall not modify From 0792b0e72df9157ba60b164140586c8ad31b119c Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 28 May 2025 17:39:11 -0700 Subject: [PATCH 54/95] SDD fixes --- Svc/CCSDS/SpacePacketDeframer/docs/sdd.md | 3 +++ Svc/CCSDS/SpacePacketFramer/docs/sdd.md | 6 ++---- Svc/CCSDS/TCDeframer/docs/sdd.md | 4 +++- Svc/CCSDS/TMFramer/docs/sdd.md | 3 ++- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Svc/CCSDS/SpacePacketDeframer/docs/sdd.md b/Svc/CCSDS/SpacePacketDeframer/docs/sdd.md index b293efb3b92..a27a36cfd24 100644 --- a/Svc/CCSDS/SpacePacketDeframer/docs/sdd.md +++ b/Svc/CCSDS/SpacePacketDeframer/docs/sdd.md @@ -7,6 +7,7 @@ It receives data containing a Space Packet on its input port and extracts the Sp The `Svc::CCSDS::SpacePacketDeframer` is typically used downstream of a component that removes transfer frame headers, such as the `Svc::CCSDS::TCDeframer`. It validates the Space Packet header and extracts the payload. ## Port Descriptions + | Kind | Name | Port Type | Description | |---|---|---|---| | Input (guarded) | dataIn | Svc.ComDataWithContext | Port to receive data containing a Space Packet | @@ -16,11 +17,13 @@ The `Svc::CCSDS::SpacePacketDeframer` is typically used downstream of a componen | Output | validateApidSeqCount | CCSDS.ApidSequenceCount | Port to request validation of a sequence count for a given APID | ## Events + | Name | Severity | Description | |---|---|---| | InvalidLength | `warning high` | Deframing received an invalid packet length | ## Requirements + Add requirements in the chart below | Name | Description | Validation | |---|---|---| diff --git a/Svc/CCSDS/SpacePacketFramer/docs/sdd.md b/Svc/CCSDS/SpacePacketFramer/docs/sdd.md index 96126f522ae..6ded902b84a 100644 --- a/Svc/CCSDS/SpacePacketFramer/docs/sdd.md +++ b/Svc/CCSDS/SpacePacketFramer/docs/sdd.md @@ -11,6 +11,7 @@ The `Svc::CCSDS::SpacePacketFramer` is typically used upstream of a component th The `Svc::CCSDS::SpacePacketFramer` requires an Application Process Identifier (APID) for the Space Packets it generates. This APID is typically provided during instantiation or configuration. It also uses a sequence count, which is managed per APID via the `getApidSeqCount` port. ## Port Descriptions + | Kind | Name | Port Type | Description | |---|---|---|---| | Input (sync) | dataIn | Svc.ComDataWithContext | Port to receive user data to be framed into a Space Packet | @@ -19,11 +20,8 @@ The `Svc::CCSDS::SpacePacketFramer` requires an Application Process Identifier ( | Output | bufferDeallocate | Fw.BufferSend | Port to deallocate buffers after the Space Packet is sent | | Output | getApidSeqCount | CCSDS.ApidSequenceCount | Port to retrieve the current sequence count for a given APID | -## Events -*No component-specific events are defined in the FPP for SpacePacketFramer.* - ## Requirements -Add requirements in the chart below + | Name | Description | Validation | |---|---|---| | SPF-001 | The SpacePacketFramer shall implement the `Svc.FramerInterface`. | Inspection, Unit Test | diff --git a/Svc/CCSDS/TCDeframer/docs/sdd.md b/Svc/CCSDS/TCDeframer/docs/sdd.md index 202cef3e1d6..04dff30056c 100644 --- a/Svc/CCSDS/TCDeframer/docs/sdd.md +++ b/Svc/CCSDS/TCDeframer/docs/sdd.md @@ -21,6 +21,7 @@ void configure(U16 vcId, U16 spacecraftId, bool acceptAllVcid); - `acceptAllVcid`: If `true`, the deframer accepts all VCIDs. If `false`, it only accepts the `vcId` specified. ## Port Descriptions + | Kind | Name | Port Type | Description | |---|---|---|---| | Input (guarded) | dataIn | Svc.ComDataWithContext | Port to receive framed data | @@ -29,6 +30,7 @@ void configure(U16 vcId, U16 spacecraftId, bool acceptAllVcid); | Input (sync) | dataReturnIn | Svc.ComDataWithContext | Port receiving back ownership of sent buffers | ## Events + | Name | Severity | Description | |---|---|---| | InvalidSpacecraftId | `activity low` | Deframing received an invalid SCID | @@ -37,7 +39,7 @@ void configure(U16 vcId, U16 spacecraftId, bool acceptAllVcid); | InvalidCrc | `warning high` | Deframing received an invalid checksum | ## Requirements -Add requirements in the chart below + | Name | Description | Validation | |---|---|---| | SVC-CCSDS-TCDEFRAMER-001 | The TCDeframer shall deframe Telecommand (TC) Transfer Frames according to the CCSDS Space Data Link Protocol standard for Type-BD frames. | Unit Test, Inspection | diff --git a/Svc/CCSDS/TMFramer/docs/sdd.md b/Svc/CCSDS/TMFramer/docs/sdd.md index d2ebb210769..b8b7343e261 100644 --- a/Svc/CCSDS/TMFramer/docs/sdd.md +++ b/Svc/CCSDS/TMFramer/docs/sdd.md @@ -11,6 +11,7 @@ The `Svc::CCSDS::TMFramer` is designed to work in the common F Prime telemetry s The `Svc::CCSDS::TMFramer` component, as well as the rest of the CCSDS communications stack, is used in the [`Ref/`](https://github.com/nasa/fprime/tree/devel/Ref) example application. It is also generated by the `fprime-util new --deployment` command. ## Port Descriptions + | Kind | Name | Port Type | Description | |---|---|---|---| | sync input | dataIn | Svc.ComDataWithContext | Receives data to frame, in a Fw::Buffer with optional context | @@ -21,7 +22,7 @@ The `Svc::CCSDS::TMFramer` component, as well as the rest of the CCSDS communica | output | comStatusOut | Fw.SuccessCondition | Indicates the status of framer for receiving more data | ## Requirements -Add requirements in the chart below + | Name | Description | Validation | |---|---|---| | SVC-CCSDS-TMFRAMER-001 | The TMFramer shall implement the `Svc.FramerInterface`. | Inspection, Unit Test | From 7b40f98911284926f5cebe57285e4a6ccf3c0675 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 28 May 2025 19:46:36 -0700 Subject: [PATCH 55/95] ApidManager Rule-based testing --- Svc/CCSDS/ApidManager/ApidManager.cpp | 2 +- .../test/ut/ApidManagerTestMain.cpp | 16 +++++- .../ApidManager/test/ut/ApidManagerTester.cpp | 55 ++++++++++++++++--- .../ApidManager/test/ut/ApidManagerTester.hpp | 34 +++++++++--- 4 files changed, 87 insertions(+), 20 deletions(-) diff --git a/Svc/CCSDS/ApidManager/ApidManager.cpp b/Svc/CCSDS/ApidManager/ApidManager.cpp index 77f33477b5d..1f80de00086 100644 --- a/Svc/CCSDS/ApidManager/ApidManager.cpp +++ b/Svc/CCSDS/ApidManager/ApidManager.cpp @@ -21,7 +21,7 @@ ApidManager ::ApidManager(const char* const compName) : ApidManagerComponentBase this->m_apidSequences[1].apid = ComCfg::APID::FW_PACKET_TELEM; this->m_apidSequences[2].apid = ComCfg::APID::FW_PACKET_LOG; this->m_apidSequences[3].apid = ComCfg::APID::FW_PACKET_FILE; - this->m_apidSequences[4].apid = ComCfg::APID::FW_PACKET_PACKETIZED_TLM; + // this->m_apidSequences[4].apid = ComCfg::APID::FW_PACKET_PACKETIZED_TLM; } ApidManager ::~ApidManager() {} diff --git a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTestMain.cpp b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTestMain.cpp index 42cef27751b..e14c1849fe6 100644 --- a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTestMain.cpp +++ b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTestMain.cpp @@ -11,9 +11,16 @@ TEST(ApidManager, getExistingSeqCount) { Svc::CCSDS::ApidManagerTester tester; Svc::CCSDS::ApidManagerTester::GetExistingSeqCount rule1; + Svc::CCSDS::ApidManagerTester::GetNewSeqCountOk rule2; + Svc::CCSDS::ApidManagerTester::GetNewSeqCountTableFull rule3; + + rule1.apply(tester); + rule2.apply(tester); + // rule3.apply(tester); } + // Randomized sequence of conditioned take/release/lock/unlock TEST(ApidManager, RandomizedInterfaceTesting) { @@ -22,13 +29,16 @@ TEST(ApidManager, RandomizedInterfaceTesting) { Svc::CCSDS::ApidManagerTester::GetExistingSeqCount rule1; Svc::CCSDS::ApidManagerTester::GetNewSeqCountOk rule2; Svc::CCSDS::ApidManagerTester::GetNewSeqCountTableFull rule3; - // rule1.apply(tester); + Svc::CCSDS::ApidManagerTester::ValidateSeqCountOk rule4; + Svc::CCSDS::ApidManagerTester::ValidateSeqCountFailure rule5; // Place these rules into a list of rules STest::Rule* rules[] = { &rule1, &rule2, - &rule3 + &rule3, + &rule4, + &rule5 }; // Take the rules and place them into a random scenario @@ -47,10 +57,10 @@ TEST(ApidManager, RandomizedInterfaceTesting) { // Run! const U32 numSteps = bounded.run(tester); printf("Ran %u steps.\n", numSteps); - // add one run of unlock for safe destruction } int main(int argc, char** argv) { + STest::Random::seed(); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp index 1a8f76e770d..f98fa6e6ad2 100644 --- a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp +++ b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp @@ -39,15 +39,16 @@ ApidManagerTester ::~ApidManagerTester() {} // Tests // ---------------------------------------------------------------------- -void ApidManagerTester ::toDo() { - // TODO -} +// void ApidManagerTester ::toDo() { +// // TODO +// } bool ApidManagerTester::GetExistingSeqCount::precondition(const ApidManagerTester& testerState) { return true; // Can always get existing sequence count } void ApidManagerTester::GetExistingSeqCount::action(ApidManagerTester& testerState) { + testerState.clearHistory(); ComCfg::APID::T apid = testerState.getRandomTrackedApid(); U16 seqCount = testerState.invoke_to_getApidSeqCountIn(0, apid, 0); U16 shadownSeqCount = testerState.shadow_getAndIncrementSeqCount(apid); @@ -62,7 +63,10 @@ bool ApidManagerTester::GetNewSeqCountOk::precondition(const ApidManagerTester& } void ApidManagerTester::GetNewSeqCountOk::action(ApidManagerTester& testerState) { - bool isTableFull = testerState.shadow_seqCounts.size() >= testerState.component.MAX_TRACKED_APIDS; + testerState.clearHistory(); + // Use local constexpr to potentially avoid ODR-use of ApidManager::MAX_TRACKED_APIDS + constexpr U8 maxTrackedApidsVal = ApidManager::MAX_TRACKED_APIDS; + bool isTableFull = !(testerState.shadow_seqCounts.size() < maxTrackedApidsVal); if (isTableFull) { testerState.shadow_isTableFull = true; return; // Cannot get new sequence count if table is full - skip action @@ -81,14 +85,51 @@ bool ApidManagerTester::GetNewSeqCountTableFull::precondition(const ApidManagerT } void ApidManagerTester::GetNewSeqCountTableFull::action(ApidManagerTester& testerState) { + testerState.clearHistory(); ComCfg::APID::T apid = testerState.getRandomUntrackedApid(); U16 seqCount = testerState.invoke_to_getApidSeqCountIn(0, apid, 0); - ASSERT_EQ(seqCount, testerState.component.SEQUENCE_COUNT_ERROR) + // Use local constexpr to potentially avoid ODR-use of ApidManager::SEQUENCE_COUNT_ERROR + constexpr U16 sequenceCountErrorVal = ApidManager::SEQUENCE_COUNT_ERROR; + ASSERT_EQ(seqCount, sequenceCountErrorVal) << "Expected SEQUENCE_COUNT_ERROR for untracked APID " << static_cast(apid) << ", but got " << seqCount; testerState.assertEvents_ApidTableFull_size(__FILE__, __LINE__, 1); testerState.assertEvents_ApidTableFull(__FILE__, __LINE__, 0, static_cast(apid)); } -} // namespace CCSDS -} // namespace Svc +bool ApidManagerTester::ValidateSeqCountOk::precondition(const ApidManagerTester& testerState) { + return true; +} + +void ApidManagerTester::ValidateSeqCountOk::action(ApidManagerTester& testerState) { + testerState.clearHistory(); + ComCfg::APID::T apid = testerState.getRandomTrackedApid(); + U16 shadow_expectedSeqCount = testerState.shadow_seqCounts[apid]; + testerState.invoke_to_validateApidSeqCountIn(0, apid, shadow_expectedSeqCount); + testerState.shadow_validateApidSeqCount(apid, shadow_expectedSeqCount); // keep shadow state in sync + + testerState.assertEvents_UnexpectedSequenceCount_size(__FILE__, __LINE__, 0); +} + +bool ApidManagerTester::ValidateSeqCountFailure::precondition(const ApidManagerTester& testerState) { + return true; +} + +void ApidManagerTester::ValidateSeqCountFailure::action(ApidManagerTester& testerState) { + testerState.clearHistory(); + ComCfg::APID::T apid = testerState.getRandomTrackedApid(); + U16 shadow_expectedSeqCount = testerState.shadow_seqCounts.at(apid); + U16 invalidSeqCount = (shadow_expectedSeqCount + 1) % (1 << 14); // Or any other value that's different, ensure wrap around + + // Invoke the port with the deliberately incorrect sequence count + testerState.invoke_to_validateApidSeqCountIn(0, apid, invalidSeqCount); + testerState.shadow_validateApidSeqCount(apid, invalidSeqCount); // keep shadow state in sync + + // Now, the event should be logged + testerState.assertEvents_UnexpectedSequenceCount_size(__FILE__, __LINE__, 1); + testerState.assertEvents_UnexpectedSequenceCount(__FILE__, __LINE__, 0, invalidSeqCount, shadow_expectedSeqCount); + +} + +}; // namespace CCSDS +}; // namespace Svc diff --git a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.hpp b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.hpp index 10af42ebc2e..d8f4c4e073d 100644 --- a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.hpp +++ b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.hpp @@ -16,7 +16,7 @@ namespace Svc { namespace CCSDS { -class ApidManagerTester final : public ApidManagerGTestBase { +class ApidManagerTester : public ApidManagerGTestBase { public: @@ -60,7 +60,7 @@ class ApidManagerTester final : public ApidManagerGTestBase { //! Initialize components void initComponents(); - private: + public: // ---------------------------------------------------------------------- // Member variables // ---------------------------------------------------------------------- @@ -89,6 +89,14 @@ class ApidManagerTester final : public ApidManagerGTestBase { return this->component.SEQUENCE_COUNT_ERROR; // Return error if APID not found } + void shadow_validateApidSeqCount(ComCfg::APID::T apid, U16 expectedSeqCount) { + // This simply updates the shadow state to the next expected sequence count + auto found = this->shadow_seqCounts.find(apid); + if (found != this->shadow_seqCounts.end()) { + found->second = (expectedSeqCount + 1) % (1 << 14); + } + } + ComCfg::APID::T getRandomTrackedApid() { // Select a random APID from the sequence counts map U32 mapSize = static_cast(this->shadow_seqCounts.size()); @@ -105,30 +113,38 @@ class ApidManagerTester final : public ApidManagerGTestBase { } while (this->shadow_seqCounts.find(apid) != this->shadow_seqCounts.end()); return apid; } - - // ---------------------------------------------------------------------- - // Rules (Rule-based testing) - // ---------------------------------------------------------------------- + public: struct GetExistingSeqCount : public STest::Rule { GetExistingSeqCount(): STest::Rule("GetExistingSeqCount") {}; bool precondition(const ApidManagerTester &state); void action(ApidManagerTester &state); }; - + struct GetNewSeqCountOk : public STest::Rule { GetNewSeqCountOk(): STest::Rule("GetNewSeqCountOk") {}; bool precondition(const ApidManagerTester &state); void action(ApidManagerTester &state); }; - + struct GetNewSeqCountTableFull : public STest::Rule { GetNewSeqCountTableFull(): STest::Rule("GetNewSeqCountTableFull") {}; bool precondition(const ApidManagerTester &state); void action(ApidManagerTester &state); }; -}; + struct ValidateSeqCountOk : public STest::Rule { + ValidateSeqCountOk(): STest::Rule("ValidateSeqCountOk") {}; + bool precondition(const ApidManagerTester &state); + void action(ApidManagerTester &state); + }; + + struct ValidateSeqCountFailure : public STest::Rule { + ValidateSeqCountFailure(): STest::Rule("ValidateSeqCountFailure") {}; + bool precondition(const ApidManagerTester &state); + void action(ApidManagerTester &state); + }; + }; } // namespace CCSDS From 89847f6b2574a3ff3f0bb84107a204cfd96f6365 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Thu, 29 May 2025 10:05:23 -0700 Subject: [PATCH 56/95] Improve TMFramer code coverage, docs and comments --- Svc/CCSDS/TMFramer/TMFramer.cpp | 12 +++++----- Svc/CCSDS/TMFramer/docs/sdd.md | 3 ++- .../TMFramer/test/ut/TMFramerTestMain.cpp | 10 ++++++++ Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp | 23 +++++++++++++++++++ Svc/CCSDS/TMFramer/test/ut/TMFramerTester.hpp | 2 ++ 5 files changed, 43 insertions(+), 7 deletions(-) diff --git a/Svc/CCSDS/TMFramer/TMFramer.cpp b/Svc/CCSDS/TMFramer/TMFramer.cpp index 92cdcf0c016..fb0bd7fc7ed 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.cpp +++ b/Svc/CCSDS/TMFramer/TMFramer.cpp @@ -31,7 +31,7 @@ TMFramer ::~TMFramer() {} void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { // TODO: make this an event probably - FW_ASSERT(data.getSize() <= ComCfg::TmFrameFixedSize, + FW_ASSERT(data.getSize() <= ComCfg::TmFrameFixedSize - TMFrameHeader::SERIALIZED_SIZE - TMFrameTrailer::SERIALIZED_SIZE, static_cast(data.getSize())); // ----------------------------------------------- @@ -42,13 +42,13 @@ void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComC U16 globalVcId = 0; globalVcId |= ComCfg::SpacecraftId << TMFrameMasks::spacecraftIdOffset; globalVcId |= context.getvcId() << TMFrameMasks::virtualChannelIdOffset; - globalVcId |= 0x0; // Operational Control Field: Flag set to 0 + globalVcId |= 0x0; // Operational Control Field: Flag set to 0 (Standard 4.1.2.4) - // Data Field Status: - // - all flags to 0 except segment length id 0b11 per standard + // Data Field Status (Standard 4.1.2.7): + // - all flags to 0 except segment length id 0b11 per standard (4.1.2.7) // - First Header Pointer is always 0 since we are always wrapping a single entire packet at offset 0 U16 dataFieldStatus = 0; - dataFieldStatus |= 0x3 << TMFrameMasks::segLengthOffset; // Seg Length 0b11 per Standard + dataFieldStatus |= 0x3 << TMFrameMasks::segLengthOffset; // Seg Length Id 0b11 per Standard (4.1.2.7.5) header.setglobalVcId(globalVcId); header.setmasterFrameCount(this->m_masterFrameCount); @@ -79,7 +79,7 @@ void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComC // Trailer (CRC) // ------------------------------------------------- TMFrameTrailer trailer; - // Compute CRC over the entire frame buffer minus the FECF trailer + // Compute CRC over the entire frame buffer minus the FECF trailer (Standard 4.1.6) U16 crc = CCSDS::Utils::CRC16::compute(frameBuffer.getData(), sizeof(this->m_frameBuffer) - TMFrameTrailer::SERIALIZED_SIZE); // Set the Frame Error Control Field (FECF) diff --git a/Svc/CCSDS/TMFramer/docs/sdd.md b/Svc/CCSDS/TMFramer/docs/sdd.md index b8b7343e261..cf1ae8dfadc 100644 --- a/Svc/CCSDS/TMFramer/docs/sdd.md +++ b/Svc/CCSDS/TMFramer/docs/sdd.md @@ -27,6 +27,7 @@ The `Svc::CCSDS::TMFramer` component, as well as the rest of the CCSDS communica |---|---|---| | SVC-CCSDS-TMFRAMER-001 | The TMFramer shall implement the `Svc.FramerInterface`. | Inspection, Unit Test | | SVC-CCSDS-TMFRAMER-002 | The TMFramer shall construct CCSDS Telemetry (TM) Transfer Frames compliant with the CCSDS 132.0-B-3 standard. | Unit Test, Inspection | +| SVC-CCSDS-TMFRAMER-002 | The TMFramer shall use a fixed frame size that is configurable by the project. | Unit Test, Inspection | | SVC-CCSDS-TMFRAMER-003 | The TMFramer shall accept payload data (Space Packets or VCA_SDU) to be framed via its `dataIn` port. | Unit Test | | SVC-CCSDS-TMFRAMER-004 | The TMFramer shall output the constructed TM Transfer Frame via its `dataOut` port. | Unit Test | | SVC-CCSDS-TMFRAMER-005 | The TMFramer shall return ownership of the input buffer via the `dataReturnOut` port after the framing process is complete. | Unit Test | @@ -37,4 +38,4 @@ The `Svc::CCSDS::TMFramer` component, as well as the rest of the CCSDS communica | SVC-CCSDS-TMFRAMER-010 | The TMFramer shall be configurable with a Spacecraft Identifier. | Inspection, Unit Test | | SVC-CCSDS-TMFRAMER-011 | The TMFramer shall use the Virtual Channel Identifier passed in the `context` object on `dataIn`. | Unit Test | | SVC-CCSDS-TMFRAMER-012 | The TMFramer shall manage Master Channel Frame Count and Virtual Channel Frame Count. | Unit Test | -| SVC-CCSDS-TMFRAMER-013 | The TMFramer shall fill the data field of the TM Transfer Frame with the payload data received on `dataIn`, and fill up the rest of the fixed-size frame with a single Idle Packet as defined by the protocol. | Unit Test | \ No newline at end of file +| SVC-CCSDS-TMFRAMER-013 | The TMFramer shall fill the data field of the TM Transfer Frame with the payload data received on `dataIn`, and fill up the rest of the fixed-size frame with a single Idle Packet as defined by the protocol. | Unit Test | diff --git a/Svc/CCSDS/TMFramer/test/ut/TMFramerTestMain.cpp b/Svc/CCSDS/TMFramer/test/ut/TMFramerTestMain.cpp index d6973502675..32c934f49b8 100644 --- a/Svc/CCSDS/TMFramer/test/ut/TMFramerTestMain.cpp +++ b/Svc/CCSDS/TMFramer/test/ut/TMFramerTestMain.cpp @@ -11,6 +11,11 @@ TEST(TMFramer, testComStatusPassthrough) { tester.testComStatusPassthrough(); } +TEST(TMFramer, testDataReturn) { + Svc::CCSDS::TMFramerTester tester; + tester.testDataReturn(); +} + TEST(TMFramer, testNominalFraming) { Svc::CCSDS::TMFramerTester tester; tester.testNominalFraming(); @@ -21,6 +26,11 @@ TEST(TMFramer, testSeqCountWrapAround) { tester.testSeqCountWrapAround(); } +TEST(TMFramer, testInputBufferTooLarge) { + Svc::CCSDS::TMFramerTester tester; + tester.testInputBufferTooLarge(); +} + int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp index f9e0d52f573..b5ab5c46d18 100644 --- a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp +++ b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp @@ -109,6 +109,29 @@ void TMFramerTester ::testSeqCountWrapAround() { } } +void TMFramerTester ::testInputBufferTooLarge() { + FwSizeType tooLargeSize = ComCfg::TmFrameFixedSize; // This is too large since we need room for header+trailer as well + U8 bufferData[tooLargeSize]; + Fw::Buffer buffer(bufferData, static_cast(tooLargeSize)); + ComCfg::FrameContext defaultContext; + // Send a buffer larger than the + ASSERT_DEATH_IF_SUPPORTED(this->invoke_to_dataIn(0, buffer, defaultContext), "TMFramer.cpp"); +} + +void TMFramerTester ::testDataReturn() { + U8 bufferData[10]; + Fw::Buffer buffer(bufferData, sizeof(bufferData)); + ComCfg::FrameContext defaultContext; + // Send a buffer that is not the internal buffer of the component, and expect an assertion + ASSERT_DEATH_IF_SUPPORTED(this->invoke_to_dataReturnIn(0, buffer, defaultContext), "TMFramer.cpp"); + + // Now send the expected buffer and expect it to be cleared + this->component.m_frameBuffer[0] = 0xFF; // Set some data in the internal buffer + Fw::Buffer internalBuffer(this->component.m_frameBuffer, sizeof(this->component.m_frameBuffer)); + this->invoke_to_dataReturnIn(0, internalBuffer, defaultContext); + ASSERT_EQ(this->component.m_frameBuffer[0], 0x00); // data should have been cleared +} + // ---------------------------------------------------------------------- // Helper functions // ---------------------------------------------------------------------- diff --git a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.hpp b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.hpp index e1df80cd1bb..1d145deaba5 100644 --- a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.hpp +++ b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.hpp @@ -45,6 +45,8 @@ class TMFramerTester final : public TMFramerGTestBase { void testComStatusPassthrough(); void testNominalFraming(); void testSeqCountWrapAround(); + void testInputBufferTooLarge(); + void testDataReturn(); private: // ---------------------------------------------------------------------- From 35d7b46c4954c579211b6d08f137820fdf5cff18 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Thu, 29 May 2025 10:43:15 -0700 Subject: [PATCH 57/95] Types cleanup --- .../SpacePacketDeframer.cpp | 4 +- .../SpacePacketFramer/SpacePacketFramer.cpp | 6 +- Svc/CCSDS/TCDeframer/TCDeframer.cpp | 29 +++---- .../TCDeframer/test/ut/TCDeframerTester.cpp | 16 ++-- Svc/CCSDS/TMFramer/TMFramer.cpp | 24 +++--- Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp | 8 +- Svc/CCSDS/Types/Types.fpp | 81 ++++++++++--------- Svc/CCSDS/Utils/CMakeLists.txt | 16 ---- Svc/CCSDS/Utils/Utils.fpp | 20 ----- Svc/CCSDS/space-packet.md | 5 -- .../FrameDetector/CcsdsTCFrameDetector.cpp | 24 +++--- 11 files changed, 101 insertions(+), 132 deletions(-) delete mode 100644 Svc/CCSDS/Utils/CMakeLists.txt delete mode 100644 Svc/CCSDS/Utils/Utils.fpp delete mode 100644 Svc/CCSDS/space-packet.md diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp index 9399b19238a..1e787fe314d 100644 --- a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp @@ -54,13 +54,13 @@ void SpacePacketDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, return; } - U16 apidValue = header.getpacketIdentification() & SpacePacketMasks::ApidMask; + U16 apidValue = header.getpacketIdentification() & SpacePacketSubfields::ApidMask; ComCfg::APID::T apid = static_cast(apidValue); ComCfg::FrameContext contextCopy = context; contextCopy.setapid(apid); // Validate with the ApidManager that the sequence count is correct - U16 receivedSequenceCount = header.getpacketSequenceControl() & SpacePacketMasks::SeqCountMask; + U16 receivedSequenceCount = header.getpacketSequenceControl() & SpacePacketSubfields::SeqCountMask; (void)this->validateApidSeqCount_out(0, apid, receivedSequenceCount); contextCopy.setsequenceCount(receivedSequenceCount); diff --git a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp index dc707aa5aa2..76e2953e789 100644 --- a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp +++ b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp @@ -43,15 +43,15 @@ void SpacePacketFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, c U16 packetIdentification = 0; ComCfg::APID::T apid = context.getapid(); FW_ASSERT((apid >> 11) == 0, static_cast(apid)); // apid must fit in 11 bits - packetIdentification |= static_cast(apid) & SpacePacketMasks::ApidMask; // 11 bit APID + packetIdentification |= static_cast(apid) & SpacePacketSubfields::ApidMask; // 11 bit APID U16 packetSequenceControl = 0; - packetSequenceControl |= 0x3 << SpacePacketMasks::SeqFlagsOffset; // Sequence Flags 0b11 = unsegmented User Data + packetSequenceControl |= 0x3 << SpacePacketSubfields::SeqFlagsOffset; // Sequence Flags 0b11 = unsegmented User Data U16 sequenceCount = this->getApidSeqCount_out(0, apid, 0); // retrieve the sequence count for this APID // NOTE: this will assert if ApidManager's table is full (because error value is max(U16)) - should it?? FW_ASSERT((sequenceCount >> 14) == 0, static_cast(sequenceCount)); // sequence count must fit in 14 bits - packetSequenceControl |= sequenceCount & SpacePacketMasks::SeqCountMask; // 14 bit sequence count + packetSequenceControl |= sequenceCount & SpacePacketSubfields::SeqCountMask; // 14 bit sequence count FW_ASSERT(data.getSize() <= std::numeric_limits::max(), static_cast(data.getSize())); U16 packetDataLength = static_cast(data.getSize() - 1); // Standard specifies length is number of bytes minus 1 diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.cpp b/Svc/CCSDS/TCDeframer/TCDeframer.cpp index 87049058d79..1e208a501da 100644 --- a/Svc/CCSDS/TCDeframer/TCDeframer.cpp +++ b/Svc/CCSDS/TCDeframer/TCDeframer.cpp @@ -6,8 +6,8 @@ #include "Svc/CCSDS/TCDeframer/TCDeframer.hpp" #include "Svc/CCSDS/Types/FppConstantsAc.hpp" -#include "Svc/CCSDS/Types/TCFrameHeaderSerializableAc.hpp" -#include "Svc/CCSDS/Types/TCFrameTrailerSerializableAc.hpp" +#include "Svc/CCSDS/Types/TCHeaderSerializableAc.hpp" +#include "Svc/CCSDS/Types/TCTrailerSerializableAc.hpp" #include "Svc/CCSDS/Utils/CRC16.hpp" #include "config/FpConfig.hpp" @@ -47,23 +47,23 @@ void TCDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const Co // CCSDS TC Trailer: // 16b - Frame Error Control Field (FECF): CRC16 - FW_ASSERT(data.getSize() >= TCFrameHeader::SERIALIZED_SIZE, static_cast(data.getSize())); + FW_ASSERT(data.getSize() >= TCHeader::SERIALIZED_SIZE, static_cast(data.getSize())); - TCFrameHeader header; + TCHeader header; Fw::SerializeStatus status = data.getDeserializer().deserialize(header); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); - U16 frame_length = header.getvcIdAndLength() & TCFrameMasks::FrameLengthMask; - U8 vc_id = (header.getvcIdAndLength() & TCFrameMasks::VcIdMask) >> TCFrameMasks::VcIdOffset; - U16 spacecraft_id = header.getflagsAndScId() & TCFrameMasks::SpacecraftIdMask; + U16 frame_length = header.getvcIdAndLength() & TCSubfields::FrameLengthMask; + U8 vc_id = (header.getvcIdAndLength() & TCSubfields::VcIdMask) >> TCSubfields::VcIdOffset; + U16 spacecraft_id = header.getflagsAndScId() & TCSubfields::SpacecraftIdMask; if (spacecraft_id != this->m_spacecraftId) { this->log_ACTIVITY_LO_InvalidSpacecraftId(spacecraft_id, this->m_spacecraftId); this->dataReturnOut_out(0, data, context); // drop the frame return; } - if (data.getSize() < frame_length + TCFrameHeader::SERIALIZED_SIZE + TCFrameTrailer::SERIALIZED_SIZE) { - U32 maxDataAvailable = data.getSize() - TCFrameHeader::SERIALIZED_SIZE - TCFrameTrailer::SERIALIZED_SIZE; + if (data.getSize() < frame_length + TCHeader::SERIALIZED_SIZE + TCTrailer::SERIALIZED_SIZE) { + U32 maxDataAvailable = data.getSize() - TCHeader::SERIALIZED_SIZE - TCTrailer::SERIALIZED_SIZE; this->log_WARNING_HI_InvalidFrameLength(frame_length, maxDataAvailable); this->dataReturnOut_out(0, data, context); // drop the frame return; @@ -73,16 +73,17 @@ void TCDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const Co this->dataReturnOut_out(0, data, context); // drop the frame return; } - // Note: F Prime uses TC Type-BD frames for now, so the FARM checks are not ran (meaning no sequence count checks) + // Note: F Prime uses TC Type-BD frames for now, so the FARM checks are not ran + // This means there is no sequence count checks at the TC level (there are at the Space Packet level) // ------------------------------------------------- // CRC Check // ------------------------------------------------- // Compute CRC over the entire frame buffer minus the FECF trailer - U16 computed_crc = CCSDS::Utils::CRC16::compute(data.getData(), TCFrameHeader::SERIALIZED_SIZE + frame_length); - TCFrameTrailer trailer; + U16 computed_crc = CCSDS::Utils::CRC16::compute(data.getData(), TCHeader::SERIALIZED_SIZE + frame_length); + TCTrailer trailer; auto deserializer = data.getDeserializer(); - deserializer.moveDeserToOffset(TCFrameHeader::SERIALIZED_SIZE + frame_length); + deserializer.moveDeserToOffset(TCHeader::SERIALIZED_SIZE + frame_length); status = deserializer.deserialize(trailer); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); @@ -94,7 +95,7 @@ void TCDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const Co } // Point to the start of the data field and set appropriate size - data.setData(data.getData() + TCFrameHeader::SERIALIZED_SIZE); + data.setData(data.getData() + TCHeader::SERIALIZED_SIZE); data.setSize(frame_length); this->dataOut_out(0, data, context); diff --git a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp index afb636ace64..0515fd498a0 100644 --- a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp +++ b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp @@ -7,8 +7,8 @@ #include "TCDeframerTester.hpp" #include "STest/Random/Random.hpp" #include "Svc/CCSDS/Utils/CRC16.hpp" -#include "Svc/CCSDS/Types/TCFrameHeaderSerializableAc.hpp" -#include "Svc/CCSDS/Types/TCFrameTrailerSerializableAc.hpp" +#include "Svc/CCSDS/Types/TCHeaderSerializableAc.hpp" +#include "Svc/CCSDS/Types/TCTrailerSerializableAc.hpp" namespace Svc { @@ -156,7 +156,7 @@ void TCDeframerTester::testInvalidCrc() { Fw::Buffer buffer = this->assembleFrameBuffer(data, dataLength); // Override CRC to invalid value - buffer.getData()[TCFrameHeader::SERIALIZED_SIZE + dataLength + 1] = 0x00; + buffer.getData()[TCHeader::SERIALIZED_SIZE + dataLength + 1] = 0x00; ComCfg::FrameContext nullContext; this->setComponentState(); @@ -180,7 +180,7 @@ void TCDeframerTester::setComponentState(U16 scid, U8 vcid, U8 sequenceNumber, b Fw::Buffer TCDeframerTester::assembleFrameBuffer(U8* data, U8 dataLength, U16 scid, U8 vcid, U8 seqNumber){ ::memset(this->m_frameData, 0, sizeof(this->m_frameData)); - U16 frameLength = TCFrameHeader::SERIALIZED_SIZE + dataLength + TCFrameTrailer::SERIALIZED_SIZE; + U16 frameLength = TCHeader::SERIALIZED_SIZE + dataLength + TCTrailer::SERIALIZED_SIZE; // Header this->m_frameData[0] = scid >> 8; @@ -190,12 +190,12 @@ Fw::Buffer TCDeframerTester::assembleFrameBuffer(U8* data, U8 dataLength, U16 sc this->m_frameData[4] = seqNumber; // Data - memcpy(&this->m_frameData[TCFrameHeader::SERIALIZED_SIZE], data, dataLength); + memcpy(&this->m_frameData[TCHeader::SERIALIZED_SIZE], data, dataLength); // CRC trailer - U16 crc = CCSDS::Utils::CRC16::compute(this->m_frameData, TCFrameHeader::SERIALIZED_SIZE + dataLength); - this->m_frameData[TCFrameHeader::SERIALIZED_SIZE + dataLength] = crc >> 8; - this->m_frameData[TCFrameHeader::SERIALIZED_SIZE + dataLength + 1] = crc & 0xFF; + U16 crc = CCSDS::Utils::CRC16::compute(this->m_frameData, TCHeader::SERIALIZED_SIZE + dataLength); + this->m_frameData[TCHeader::SERIALIZED_SIZE + dataLength] = crc >> 8; + this->m_frameData[TCHeader::SERIALIZED_SIZE + dataLength + 1] = crc & 0xFF; return Fw::Buffer(this->m_frameData, frameLength); } diff --git a/Svc/CCSDS/TMFramer/TMFramer.cpp b/Svc/CCSDS/TMFramer/TMFramer.cpp index fb0bd7fc7ed..a46cd62366f 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.cpp +++ b/Svc/CCSDS/TMFramer/TMFramer.cpp @@ -6,8 +6,8 @@ #include "Svc/CCSDS/TMFramer/TMFramer.hpp" #include "Svc/CCSDS/Types/FppConstantsAc.hpp" -#include "Svc/CCSDS/Types/TMFrameHeaderSerializableAc.hpp" -#include "Svc/CCSDS/Types/TMFrameTrailerSerializableAc.hpp" +#include "Svc/CCSDS/Types/TMHeaderSerializableAc.hpp" +#include "Svc/CCSDS/Types/TMTrailerSerializableAc.hpp" #include "Svc/CCSDS/Utils/CRC16.hpp" #include "config/FppConstantsAc.hpp" #include "Svc/CCSDS/Types/SpacePacketHeaderSerializableAc.hpp" @@ -31,24 +31,24 @@ TMFramer ::~TMFramer() {} void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { // TODO: make this an event probably - FW_ASSERT(data.getSize() <= ComCfg::TmFrameFixedSize - TMFrameHeader::SERIALIZED_SIZE - TMFrameTrailer::SERIALIZED_SIZE, + FW_ASSERT(data.getSize() <= ComCfg::TmFrameFixedSize - TMHeader::SERIALIZED_SIZE - TMTrailer::SERIALIZED_SIZE, static_cast(data.getSize())); // ----------------------------------------------- // Header // ----------------------------------------------- - TMFrameHeader header; + TMHeader header; U16 globalVcId = 0; - globalVcId |= ComCfg::SpacecraftId << TMFrameMasks::spacecraftIdOffset; - globalVcId |= context.getvcId() << TMFrameMasks::virtualChannelIdOffset; + globalVcId |= ComCfg::SpacecraftId << TMSubfields::spacecraftIdOffset; + globalVcId |= context.getvcId() << TMSubfields::virtualChannelIdOffset; globalVcId |= 0x0; // Operational Control Field: Flag set to 0 (Standard 4.1.2.4) // Data Field Status (Standard 4.1.2.7): // - all flags to 0 except segment length id 0b11 per standard (4.1.2.7) // - First Header Pointer is always 0 since we are always wrapping a single entire packet at offset 0 U16 dataFieldStatus = 0; - dataFieldStatus |= 0x3 << TMFrameMasks::segLengthOffset; // Seg Length Id 0b11 per Standard (4.1.2.7.5) + dataFieldStatus |= 0x3 << TMSubfields::segLengthOffset; // Seg Length Id 0b11 per Standard (4.1.2.7.5) header.setglobalVcId(globalVcId); header.setmasterFrameCount(this->m_masterFrameCount); @@ -78,15 +78,15 @@ void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComC // ------------------------------------------------- // Trailer (CRC) // ------------------------------------------------- - TMFrameTrailer trailer; + TMTrailer trailer; // Compute CRC over the entire frame buffer minus the FECF trailer (Standard 4.1.6) U16 crc = CCSDS::Utils::CRC16::compute(frameBuffer.getData(), - sizeof(this->m_frameBuffer) - TMFrameTrailer::SERIALIZED_SIZE); + sizeof(this->m_frameBuffer) - TMTrailer::SERIALIZED_SIZE); // Set the Frame Error Control Field (FECF) trailer.setfecf(crc); // Move the serializer pointer to the end of the location where the trailer will be serialized frameSerializer.moveSerToOffset(ComCfg::TmFrameFixedSize - - TMFrameTrailer::SERIALIZED_SIZE); + TMTrailer::SERIALIZED_SIZE); status = frameSerializer.serialize(trailer); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); @@ -112,7 +112,7 @@ void TMFramer ::dataReturnIn_handler(FwIndexType portNum, void TMFramer ::fill_with_idle_packet(Fw::SerializeBufferBase& serializer) { constexpr U16 endIndex = ComCfg::TmFrameFixedSize - - TMFrameTrailer::SERIALIZED_SIZE; + TMTrailer::SERIALIZED_SIZE; constexpr U16 idleApid = static_cast(ComCfg::APID::SPP_IDLE_PACKET); const U16 startIndex = static_cast(serializer.getBuffLength()); const U16 idlePacketLength = endIndex - startIndex; @@ -124,7 +124,7 @@ void TMFramer ::fill_with_idle_packet(Fw::SerializeBufferBase& serializer) { SpacePacketHeader header; header.setpacketIdentification(idleApid); - header.setpacketSequenceControl(0x3 << SpacePacketMasks::SeqFlagsOffset); // Sequence Flags = 0b11 (unsegmented) & unused Seq count + header.setpacketSequenceControl(0x3 << SpacePacketSubfields::SeqFlagsOffset); // Sequence Flags = 0b11 (unsegmented) & unused Seq count header.setpacketDataLength(idlePacketLength); // Serialize header and idle data into the frame serializer.serialize(header); diff --git a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp index b5ab5c46d18..1585a94b1a3 100644 --- a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp +++ b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp @@ -5,8 +5,8 @@ // ====================================================================== #include "TMFramerTester.hpp" -#include "Svc/CCSDS/Types/TMFrameHeaderSerializableAc.hpp" -#include "Svc/CCSDS/Types/TMFrameTrailerSerializableAc.hpp" +#include "Svc/CCSDS/Types/TMHeaderSerializableAc.hpp" +#include "Svc/CCSDS/Types/TMTrailerSerializableAc.hpp" #include "Svc/CCSDS/Types/SpacePacketHeaderSerializableAc.hpp" namespace Svc { @@ -74,10 +74,10 @@ void TMFramerTester ::testNominalFraming() { ASSERT_EQ(this->component.m_virtualFrameCount, outVcCount + 1); // Idle data should be filled at the offset of header + payload + the Space Packet Idle Packet header - FwSizeType expectedIdleDataOffset = TMFrameHeader::SERIALIZED_SIZE + sizeof(bufferData) + SpacePacketHeader::SERIALIZED_SIZE; + FwSizeType expectedIdleDataOffset = TMHeader::SERIALIZED_SIZE + sizeof(bufferData) + SpacePacketHeader::SERIALIZED_SIZE; // The frame is composed of the payload + a SpacePacket Idle Packet (Header + idle_pattern) - for (FwSizeType i = expectedIdleDataOffset; i < ComCfg::TmFrameFixedSize - TMFrameTrailer::SERIALIZED_SIZE; ++i) { + for (FwSizeType i = expectedIdleDataOffset; i < ComCfg::TmFrameFixedSize - TMTrailer::SERIALIZED_SIZE; ++i) { ASSERT_EQ(outBuffer.getData()[i], 0x44); } } diff --git a/Svc/CCSDS/Types/Types.fpp b/Svc/CCSDS/Types/Types.fpp index 6f013908d3f..05ec98cdba0 100644 --- a/Svc/CCSDS/Types/Types.fpp +++ b/Svc/CCSDS/Types/Types.fpp @@ -1,14 +1,25 @@ +# ------------------------------------------------ +# CCSDS protocols header and trailer types +# +# Note: FPP does not currently support bit fields, so these structs may contain fields +# that are compoed of multiple bitfields. One should mask the individual FPP types +# with the approriate mask to +# ------------------------------------------------ + module Svc { module CCSDS { # ------------------------------------------------ - # Frame header and trailer types + # SpacePacket # ------------------------------------------------ - # Note: FPP does not currently support bit fields, so these structs may contain fields - # that are compoed of multiple bitfields. One should mask the individual FPP types - # with the approriate mask to - - module SpacePacketMasks { + @ Describes the frame header format for the SpacePacket communications protocol + struct SpacePacketHeader { + packetIdentification: U16, @< 3 bits PVN | 1 bit Pkt type | 1 bit Sec Hdr | 11 bit APID + packetSequenceControl: U16, @< 2 bits Sequence flags | 14 bits packet seq count (or name) + packetDataLength: U16 @< 16 bits length + } + @ Masks and Offsets for deserializing individual sub-fields in SpacePacket headers + module SpacePacketSubfields { # packetIdentification sub-fields |--- 16 bits ---| constant PvnMask = 0xE000 @< 0b1110000000000000 constant PktTypeMask = 0x1000 @< 0b0001000000000000 @@ -23,7 +34,21 @@ module CCSDS { constant SeqFlagsOffset = 14 } - module TCFrameMasks { + # ------------------------------------------------ + # TC (TeleCommand) + # ------------------------------------------------ + @ Describes the frame header format for a Telecommand (TC) Transfer Frame header + struct TCHeader { + flagsAndScId: U16, @< 2 bits Frame V. | 1 bit bypass | 1 bit ctrl | 2 bit rsvd | 10 bits spacecraft ID + vcIdAndLength: U16, @< 6 bits Virtual Channel ID | 10 bits Frame Length + frameSequenceNbr: U8 @< 8 bits Frame Sequence Number + } + @ Describes the frame trailer format for a Telecommand (TC) Transfer Frame + struct TCTrailer { + fecf: U16 @< 16 bit Frame Error Control Field (CRC16) + } + @ Masks and Offsets for deserializing individual sub-fields in TC headers + module TCSubfields { # flagsAndScId sub-fields constant FrameVersionMask = 0xC000 @< 0b1100000000000000 constant BypassFlagMask = 0x2000 @< 0b0010000000000000 @@ -37,43 +62,27 @@ module CCSDS { constant VcIdOffset = 10 } - @ Describes the frame header format for the SpacePacket communications protocol - struct SpacePacketHeader { - packetIdentification: U16, @< 3 bits PVN | 1 bit Pkt type | 1 bit Sec Hdr | 11 bit APID - packetSequenceControl: U16, @< 2 bits Sequence flags | 14 bits packet seq count (or name) - packetDataLength: U16 @< 16 bits length - } - - @ Describes the frame header format for a Telecommand (TC) Transfer Frame header - struct TCFrameHeader { - flagsAndScId: U16, @< 2 bits Frame V. | 1 bit bypass | 1 bit ctrl | 2 bit rsvd | 10 bits spacecraft ID - vcIdAndLength: U16, @< 6 bits Virtual Channel ID | 10 bits Frame Length - frameSequenceNbr: U8 @< 8 bits Frame Sequence Number + # ------------------------------------------------ + # TM (TeleMetry) + # ------------------------------------------------ + @ Describes the frame header format for a Telemetry (TM) Transfer Frame header + struct TMHeader { + globalVcId: U16, @< 2 bit Frame Version | 10 bit spacecraft ID | 3 bit virtual channel ID | 1 bit OCF flag + masterFrameCount: U8, @< 8 bit Master Channel Frame Count + virtualFrameCount: U8, @< 8 bit Virtual Channel Frame Count + dataFieldStatus: U16 @< 1 bit 2nd Header | 1 bit sync | 1 bit pkt order | 2 bit seg len | 11 bit header ptr } - - struct TCFrameTrailer { + @ Describes the frame trailer format for a Telemetry (TM) Transfer Frame + struct TMTrailer { fecf: U16 @< 16 bit Frame Error Control Field (CRC16) } - - module TMFrameMasks { + @ Offsets for serializing individual sub-fields in TM headers + module TMSubfields { constant frameVersionOffset = 14 constant spacecraftIdOffset = 4 constant virtualChannelIdOffset = 1 constant segLengthOffset = 11 } - struct TMFrameHeader { - globalVcId: U16, @< 2 bit Frame Version | 10 bit spacecraft ID | 3 bit virtual channel ID | 1 bit OCF flag - masterFrameCount: U8, @< 8 bit Master Channel Frame Count - virtualFrameCount: U8, @< 8 bit Virtual Channel Frame Count - dataFieldStatus: U16 @< 1 bit 2nd Header | 1 bit sync | 1 bit pkt order | 2 bit seg len | 11 bit header ptr - } - struct TMFrameTrailer { - fecf: U16 @< 16 bit Frame Error Control Field (CRC16) - } - - - - } } diff --git a/Svc/CCSDS/Utils/CMakeLists.txt b/Svc/CCSDS/Utils/CMakeLists.txt deleted file mode 100644 index f75175a5072..00000000000 --- a/Svc/CCSDS/Utils/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -#### -# FPrime CMakeLists.txt: -# -# SOURCES: list of source files (to be compiled) -# AUTOCODER_INPUTS: list of files to be passed to the autocoders -# DEPENDS: list of libraries that this module depends on -# -# More information in the F´ CMake API documentation: -# https://fprime.jpl.nasa.gov/devel/docs/reference/api/cmake/API/ -# -#### - -register_fprime_library( - AUTOCODER_INPUTS - "${CMAKE_CURRENT_LIST_DIR}/Utils.fpp" -) diff --git a/Svc/CCSDS/Utils/Utils.fpp b/Svc/CCSDS/Utils/Utils.fpp deleted file mode 100644 index e42b16a9177..00000000000 --- a/Svc/CCSDS/Utils/Utils.fpp +++ /dev/null @@ -1,20 +0,0 @@ -module Utils { - - ########################################################################### - #### Uncomment the following examples to start customizing your module #### - ########################################################################### - - # enum ExampleEnum: U8 { A, B, C } - - # array ExampleArray = [3] F32 - - # struct ExampleStruct { x: U32, y: string } - - # @ ExamplePort returning an F32 - # port ExamplePort( - # arg1: ExampleEnum @< The first argument - # arg2: ExampleArray @< The second argument - # arg3: ExampleStruct @< The third argument - # ) -> F32 - -} diff --git a/Svc/CCSDS/space-packet.md b/Svc/CCSDS/space-packet.md deleted file mode 100644 index 5aa01b0d144..00000000000 --- a/Svc/CCSDS/space-packet.md +++ /dev/null @@ -1,5 +0,0 @@ -# F´ Space Packet usage - -In the Space Packets used by core F´: - -- Secondary header is implicitly set to the APID, because the data is there on all F´ packets. \ No newline at end of file diff --git a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp index 9a224a31c3e..a23f475833e 100644 --- a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp +++ b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp @@ -8,8 +8,8 @@ #include "Svc/CCSDS/Types/FppConstantsAc.hpp" #include #include "config/FppConstantsAc.hpp" -#include "Svc/CCSDS/Types/TCFrameHeaderSerializableAc.hpp" -#include "Svc/CCSDS/Types/TCFrameTrailerSerializableAc.hpp" +#include "Svc/CCSDS/Types/TCHeaderSerializableAc.hpp" +#include "Svc/CCSDS/Types/TCTrailerSerializableAc.hpp" #include "Utils/Hash/Hash.hpp" namespace Svc { @@ -17,31 +17,31 @@ namespace FrameDetectors { FrameDetector::Status CcsdsTCFrameDetector::detect(const Types::CircularBuffer& data, FwSizeType& size_out) const { - if (data.get_allocated_size() < CCSDS::TCFrameHeader::SERIALIZED_SIZE) { - size_out = CCSDS::TCFrameHeader::SERIALIZED_SIZE; + if (data.get_allocated_size() < CCSDS::TCHeader::SERIALIZED_SIZE) { + size_out = CCSDS::TCHeader::SERIALIZED_SIZE; return Status::MORE_DATA_NEEDED; } // Copy CircularBuffer data into linear buffer, for serialization into FrameHeader object - U8 header_data[CCSDS::TCFrameHeader::SERIALIZED_SIZE]; - Fw::SerializeStatus status = data.peek(header_data, CCSDS::TCFrameHeader::SERIALIZED_SIZE, 0); + U8 header_data[CCSDS::TCHeader::SERIALIZED_SIZE]; + Fw::SerializeStatus status = data.peek(header_data, CCSDS::TCHeader::SERIALIZED_SIZE, 0); if (status != Fw::FW_SERIALIZE_OK) { return Status::NO_FRAME_DETECTED; } - Fw::ExternalSerializeBuffer header_ser_buffer(header_data, CCSDS::TCFrameHeader::SERIALIZED_SIZE); - status = header_ser_buffer.setBuffLen(CCSDS::TCFrameHeader::SERIALIZED_SIZE); + Fw::ExternalSerializeBuffer header_ser_buffer(header_data, CCSDS::TCHeader::SERIALIZED_SIZE); + status = header_ser_buffer.setBuffLen(CCSDS::TCHeader::SERIALIZED_SIZE); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, static_cast(status)); // Attempt to deserialize data into the FrameHeader object - CCSDS::TCFrameHeader header; + CCSDS::TCHeader header; status = header.deserialize(header_ser_buffer); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); - U16 sc_id = header.getflagsAndScId() & CCSDS::TCFrameMasks::SpacecraftIdMask; + U16 sc_id = header.getflagsAndScId() & CCSDS::TCSubfields::SpacecraftIdMask; // TODO?? Use the full expected flagsAndScId value since the other fields should be static // REVIEW NOTE: Not doing CRC here.... - U16 frame_length = header.getvcIdAndLength() & CCSDS::TCFrameMasks::FrameLengthMask; + U16 frame_length = header.getvcIdAndLength() & CCSDS::TCSubfields::FrameLengthMask; - FwSizeType expected_frame_size = CCSDS::TCFrameHeader::SERIALIZED_SIZE + frame_length + CCSDS::TCFrameTrailer::SERIALIZED_SIZE; // 2 bytes for CRC + FwSizeType expected_frame_size = CCSDS::TCHeader::SERIALIZED_SIZE + frame_length + CCSDS::TCTrailer::SERIALIZED_SIZE; // 2 bytes for CRC if (sc_id == ComCfg::FppConstant_SpacecraftId::SpacecraftId) { size_out = expected_frame_size; if (data.get_allocated_size() < expected_frame_size) { From 53ce27444b620b7a6a8ca1506fd159d29aea3e64 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Mon, 2 Jun 2025 09:43:56 -0700 Subject: [PATCH 58/95] Add CRC check to CcsdsTCFrameDetector --- .../test/ut/ApidManagerTestMain.cpp | 2 +- .../ApidManager/test/ut/ApidManagerTester.cpp | 2 +- .../ApidManager/test/ut/ApidManagerTester.hpp | 2 +- .../test/ut/SpacePacketDeframerTestMain.cpp | 2 +- .../test/ut/SpacePacketDeframerTester.cpp | 2 +- .../test/ut/SpacePacketDeframerTester.hpp | 2 +- Svc/CCSDS/SpacePacketFramer/docs/sdd.md | 1 - .../test/ut/SpacePacketFramerTestMain.cpp | 2 +- .../test/ut/SpacePacketFramerTester.cpp | 2 +- .../test/ut/SpacePacketFramerTester.hpp | 2 +- .../FrameDetector/CcsdsTCFrameDetector.cpp | 60 +++++++++++++++---- .../FrameDetector/CcsdsTCFrameDetector.hpp | 9 ++- 12 files changed, 63 insertions(+), 25 deletions(-) diff --git a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTestMain.cpp b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTestMain.cpp index e14c1849fe6..41ee7e3cbba 100644 --- a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTestMain.cpp +++ b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTestMain.cpp @@ -1,6 +1,6 @@ // ====================================================================== // \title ApidManagerTestMain.cpp -// \author chammard +// \author thomas-bc // \brief cpp file for ApidManager component test main function // ====================================================================== diff --git a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp index f98fa6e6ad2..67ed15dbf74 100644 --- a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp +++ b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp @@ -1,6 +1,6 @@ // ====================================================================== // \title ApidManagerTester.cpp -// \author chammard +// \author thomas-bc // \brief cpp file for ApidManager component test harness implementation class // ====================================================================== diff --git a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.hpp b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.hpp index d8f4c4e073d..3002c152fad 100644 --- a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.hpp +++ b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.hpp @@ -1,6 +1,6 @@ // ====================================================================== // \title ApidManagerTester.hpp -// \author chammard +// \author thomas-bc // \brief hpp file for ApidManager component test harness implementation class // ====================================================================== diff --git a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTestMain.cpp b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTestMain.cpp index 230d8a288a5..7a94ea6b293 100644 --- a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTestMain.cpp +++ b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTestMain.cpp @@ -1,6 +1,6 @@ // ====================================================================== // \title SpacePacketDeframerTestMain.cpp -// \author chammard +// \author thomas-bc // \brief cpp file for SpacePacketDeframer component test main function // ====================================================================== diff --git a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp index 1eb32e8544b..c717fb9782d 100644 --- a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp +++ b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp @@ -1,6 +1,6 @@ // ====================================================================== // \title SpacePacketDeframerTester.cpp -// \author chammard +// \author thomas-bc // \brief cpp file for SpacePacketDeframer component test harness implementation class // ====================================================================== diff --git a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.hpp b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.hpp index 82dc81b5bd1..e0b7295f53d 100644 --- a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.hpp +++ b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.hpp @@ -1,6 +1,6 @@ // ====================================================================== // \title SpacePacketDeframerTester.hpp -// \author chammard +// \author thomas-bc // \brief hpp file for SpacePacketDeframer component test harness implementation class // ====================================================================== diff --git a/Svc/CCSDS/SpacePacketFramer/docs/sdd.md b/Svc/CCSDS/SpacePacketFramer/docs/sdd.md index 6ded902b84a..1005ed8ad3f 100644 --- a/Svc/CCSDS/SpacePacketFramer/docs/sdd.md +++ b/Svc/CCSDS/SpacePacketFramer/docs/sdd.md @@ -1,4 +1,3 @@ - # Svc::CCSDS::SpacePacketFramer The `Svc::CCSDS::SpacePacketFramer` is an implementation of the [FramerInterface](../../Interfaces/docs/sdd.md) for the CCSDS [Space Packet Protocol](https://public.ccsds.org/Pubs/133x0b2e1.pdf). diff --git a/Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTestMain.cpp b/Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTestMain.cpp index e85c3b2ec42..80ed31f92d7 100644 --- a/Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTestMain.cpp +++ b/Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTestMain.cpp @@ -1,6 +1,6 @@ // ====================================================================== // \title SpacePacketFramerTestMain.cpp -// \author chammard +// \author thomas-bc // \brief cpp file for SpacePacketFramer component test main function // ====================================================================== diff --git a/Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTester.cpp b/Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTester.cpp index 00a9194486f..4b86ce1059e 100644 --- a/Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTester.cpp +++ b/Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTester.cpp @@ -1,6 +1,6 @@ // ====================================================================== // \title SpacePacketFramerTester.cpp -// \author chammard +// \author thomas-bc // \brief cpp file for SpacePacketFramer component test harness implementation class // ====================================================================== diff --git a/Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTester.hpp b/Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTester.hpp index b0539f36996..9f003ebf31d 100644 --- a/Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTester.hpp +++ b/Svc/CCSDS/SpacePacketFramer/test/ut/SpacePacketFramerTester.hpp @@ -1,6 +1,6 @@ // ====================================================================== // \title SpacePacketFramerTester.hpp -// \author chammard +// \author thomas-bc // \brief hpp file for SpacePacketFramer component test harness implementation class // ====================================================================== diff --git a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp index a23f475833e..0fdd22924e1 100644 --- a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp +++ b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp @@ -10,6 +10,7 @@ #include "config/FppConstantsAc.hpp" #include "Svc/CCSDS/Types/TCHeaderSerializableAc.hpp" #include "Svc/CCSDS/Types/TCTrailerSerializableAc.hpp" +#include "Svc/CCSDS/Utils/CRC16.hpp" #include "Utils/Hash/Hash.hpp" namespace Svc { @@ -22,6 +23,7 @@ FrameDetector::Status CcsdsTCFrameDetector::detect(const Types::CircularBuffer& return Status::MORE_DATA_NEEDED; } + // ---------------- Frame Header ---------------- // Copy CircularBuffer data into linear buffer, for serialization into FrameHeader object U8 header_data[CCSDS::TCHeader::SERIALIZED_SIZE]; Fw::SerializeStatus status = data.peek(header_data, CCSDS::TCHeader::SERIALIZED_SIZE, 0); @@ -36,21 +38,53 @@ FrameDetector::Status CcsdsTCFrameDetector::detect(const Types::CircularBuffer& status = header.deserialize(header_ser_buffer); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); - U16 sc_id = header.getflagsAndScId() & CCSDS::TCSubfields::SpacecraftIdMask; - // TODO?? Use the full expected flagsAndScId value since the other fields should be static - // REVIEW NOTE: Not doing CRC here.... - U16 frame_length = header.getvcIdAndLength() & CCSDS::TCSubfields::FrameLengthMask; - - FwSizeType expected_frame_size = CCSDS::TCHeader::SERIALIZED_SIZE + frame_length + CCSDS::TCTrailer::SERIALIZED_SIZE; // 2 bytes for CRC - if (sc_id == ComCfg::FppConstant_SpacecraftId::SpacecraftId) { - size_out = expected_frame_size; - if (data.get_allocated_size() < expected_frame_size) { - return Status::MORE_DATA_NEEDED; - } - return Status::FRAME_DETECTED; + if (header.getflagsAndScId() != this->m_expectedFlagsAndScIdToken) { + // If the flags and SC ID do not match the expected token, we don't have a valid frame + return Status::NO_FRAME_DETECTED; + } + + const U16 frame_data_length = header.getvcIdAndLength() & CCSDS::TCSubfields::FrameLengthMask; + const FwSizeType expected_frame_length = frame_data_length + CCSDS::TCHeader::SERIALIZED_SIZE + CCSDS::TCTrailer::SERIALIZED_SIZE; + const U16 data_to_crc_length = frame_data_length + CCSDS::TCHeader::SERIALIZED_SIZE; + + if (data.get_allocated_size() < expected_frame_length) { + size_out = expected_frame_length; + return Status::MORE_DATA_NEEDED; + } + + // ---------------- Frame Trailer ---------------- + // Compute CRC on the received data + CCSDS::Utils::CRC16 crc; + for (FwSizeType i = 0; i < data_to_crc_length; ++i) { + U8 byte = 0; + status = data.peek(byte, i); + FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); + crc.update(byte); } - return Status::NO_FRAME_DETECTED; + U16 computed_fecf = crc.finalize(); + // Retrieve CRC field from the trailer + U8 trailer_data[CCSDS::TCTrailer::SERIALIZED_SIZE]; + status = data.peek(trailer_data, CCSDS::TCTrailer::SERIALIZED_SIZE, data_to_crc_length); + if (status != Fw::FW_SERIALIZE_OK) { + return Status::NO_FRAME_DETECTED; + } + Fw::ExternalSerializeBuffer trailer_ser_buffer(trailer_data, CCSDS::TCTrailer::SERIALIZED_SIZE); + status = trailer_ser_buffer.setBuffLen(CCSDS::TCTrailer::SERIALIZED_SIZE); + FW_ASSERT(status == Fw::FW_SERIALIZE_OK, static_cast(status)); + // Attempt to deserialize data into the Frametrailer object + CCSDS::TCTrailer trailer; + status = trailer.deserialize(trailer_ser_buffer); + FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); + U16 transmitted_fecf = trailer.getfecf(); + if (transmitted_fecf != computed_fecf) { + // If the computed CRC does not match the transmitted CRC, we don't have a valid frame + return Status::NO_FRAME_DETECTED; + } + // At this point, we have validated the header and CRC - we report a valid frame detected + size_out = expected_frame_length; + return Status::FRAME_DETECTED; } + } // namespace FrameDetectors } // namespace Svc diff --git a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.hpp b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.hpp index 93d4bb79941..5962cc497e5 100644 --- a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.hpp +++ b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.hpp @@ -7,9 +7,8 @@ #define SVC_FRAME_ACCUMULATOR_FRAME_DETECTOR_CCSDS_TC_FRAME_DETECTOR #include "Svc/FrameAccumulator/FrameDetector.hpp" - -// #include "Fw/Buffer/Buffer.hpp" #include "Fw/FPrimeBasicTypes.hpp" +#include "Svc/CCSDS/Types/FppConstantsAc.hpp" namespace Svc { namespace FrameDetectors { @@ -40,6 +39,12 @@ class CcsdsTCFrameDetector : public FrameDetector { //! \param size_out: set as output to caller indicating size when appropriate //! \return status of the detection to be paired with size_out Status detect(const Types::CircularBuffer& data, FwSizeType& size_out) const override; + + protected: + + //! \brief expected flags and spacecraft ID token for a valid CCSDS TC frame + const U16 m_expectedFlagsAndScIdToken = + 0x1 << CCSDS::TCSubfields::BypassFlagOffset | (ComCfg::FppConstant_SpacecraftId::SpacecraftId); }; // class CcsdsTCFrameDetector } // namespace FrameDetectors From d72a28817c4d7b57f21b9d7fbef7026f65b6d7ae Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Mon, 2 Jun 2025 09:44:15 -0700 Subject: [PATCH 59/95] Add unit tests for CcsdsTCFrameDetector --- Svc/FrameAccumulator/CMakeLists.txt | 68 ++++---- .../FrameDetector/CcsdsTCFrameDetector.cpp | 4 +- .../CcsdsTCFrameDetectorTestMain.cpp | 156 ++++++++++++++++++ 3 files changed, 197 insertions(+), 31 deletions(-) create mode 100644 Svc/FrameAccumulator/test/ut/detectors/CcsdsTCFrameDetectorTestMain.cpp diff --git a/Svc/FrameAccumulator/CMakeLists.txt b/Svc/FrameAccumulator/CMakeLists.txt index c97305b38a3..e6a096c73b1 100644 --- a/Svc/FrameAccumulator/CMakeLists.txt +++ b/Svc/FrameAccumulator/CMakeLists.txt @@ -7,41 +7,51 @@ # #### -set(SOURCE_FILES - "${CMAKE_CURRENT_LIST_DIR}/FrameAccumulator.fpp" - "${CMAKE_CURRENT_LIST_DIR}/FrameAccumulator.cpp" - "${CMAKE_CURRENT_LIST_DIR}/FrameDetector/FprimeFrameDetector.cpp" - "${CMAKE_CURRENT_LIST_DIR}/FrameDetector/CcsdsTCFrameDetector.cpp" +register_fprime_library( + SOURCES + "${CMAKE_CURRENT_LIST_DIR}/FrameAccumulator.cpp" + "${CMAKE_CURRENT_LIST_DIR}/FrameDetector/FprimeFrameDetector.cpp" + "${CMAKE_CURRENT_LIST_DIR}/FrameDetector/CcsdsTCFrameDetector.cpp" + AUTOCODER_INPUTS + "${CMAKE_CURRENT_LIST_DIR}/FrameAccumulator.fpp" + DEPENDS + Utils_Types + Svc_FprimeProtocol + Svc_CCSDS_Types ) -set(MOD_DEPS - Utils/Types - Svc/FprimeProtocol - Svc/CCSDS/Types -) - -register_fprime_module() #### UTs #### -set(UT_SOURCE_FILES - "${CMAKE_CURRENT_LIST_DIR}/FrameAccumulator.fpp" - "${CMAKE_CURRENT_LIST_DIR}/test/ut/FrameAccumulatorTester.cpp" - "${CMAKE_CURRENT_LIST_DIR}/test/ut/FrameAccumulatorTestMain.cpp" -) -set(UT_MOD_DEPS - Utils/Types +register_fprime_ut( + SOURCES + "${CMAKE_CURRENT_LIST_DIR}/test/ut/FrameAccumulatorTester.cpp" + "${CMAKE_CURRENT_LIST_DIR}/test/ut/FrameAccumulatorTestMain.cpp" + AUTOCODER_INPUTS + "${CMAKE_CURRENT_LIST_DIR}/FrameAccumulator.fpp" + DEPENDS STest + UT_AUTO_HELPERS ) -set(UT_AUTO_HELPERS ON) - -register_fprime_ut() -#### FprimeFrameDetector tests #### +#### FrameDetector tests #### -set(UT_HEADER_FILES - "${CMAKE_CURRENT_LIST_DIR}/FrameDetector/FprimeFrameDetector.hpp" -) -set(UT_SOURCE_FILES - "${CMAKE_CURRENT_LIST_DIR}/test/ut/detectors/FprimeFrameDetectorTestMain.cpp" +register_fprime_ut( + "Svc_FrameAccumulator_FprimeFrameDetector_test" + SOURCES + "${CMAKE_CURRENT_LIST_DIR}/test/ut/detectors/FprimeFrameDetectorTestMain.cpp" + HEADERS + "${CMAKE_CURRENT_LIST_DIR}/FrameDetector/FprimeFrameDetector.hpp" + DEPENDS + STest + UT_AUTO_HELPERS ) -register_fprime_ut("Svc_FrameAccumulator_FprimeFrameDetector_test") +register_fprime_ut( + "Svc_FrameAccumulator_CcsdsTCFrameDetector_test" + SOURCES + "${CMAKE_CURRENT_LIST_DIR}/test/ut/detectors/CcsdsTCFrameDetectorTestMain.cpp" + HEADERS + "${CMAKE_CURRENT_LIST_DIR}/FrameDetector/CcsdsTCFrameDetector.hpp" + DEPENDS + STest + UT_AUTO_HELPERS +) diff --git a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp index 0fdd22924e1..ce9896fb3f7 100644 --- a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp +++ b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp @@ -18,8 +18,8 @@ namespace FrameDetectors { FrameDetector::Status CcsdsTCFrameDetector::detect(const Types::CircularBuffer& data, FwSizeType& size_out) const { - if (data.get_allocated_size() < CCSDS::TCHeader::SERIALIZED_SIZE) { - size_out = CCSDS::TCHeader::SERIALIZED_SIZE; + if (data.get_allocated_size() < CCSDS::TCHeader::SERIALIZED_SIZE + CCSDS::TCTrailer::SERIALIZED_SIZE) { + size_out = CCSDS::TCHeader::SERIALIZED_SIZE + CCSDS::TCTrailer::SERIALIZED_SIZE; return Status::MORE_DATA_NEEDED; } diff --git a/Svc/FrameAccumulator/test/ut/detectors/CcsdsTCFrameDetectorTestMain.cpp b/Svc/FrameAccumulator/test/ut/detectors/CcsdsTCFrameDetectorTestMain.cpp new file mode 100644 index 00000000000..a9255599b7e --- /dev/null +++ b/Svc/FrameAccumulator/test/ut/detectors/CcsdsTCFrameDetectorTestMain.cpp @@ -0,0 +1,156 @@ +// ====================================================================== +// \title CcsdsTCFrameDetectorTestMain.cpp +// \author thomas-bc +// \brief cpp file for FrameAccumulator component test main function +// ====================================================================== + +#include "STest/Random/Random.hpp" +#include "Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.hpp" +#include "Svc/CCSDS/Utils/CRC16.hpp" +#include "Svc/CCSDS/Types/TCHeaderSerializableAc.hpp" +#include "Svc/CCSDS/Types/TCTrailerSerializableAc.hpp" +#include "Svc/CCSDS/Utils/CRC16.hpp" +#include "gtest/gtest.h" + +using namespace Svc::CCSDS; + +constexpr U32 CIRCULAR_BUFFER_TEST_SIZE = 2048; +constexpr U16 EXPECTED_START_TOKEN = 0x1 << TCSubfields::BypassFlagOffset | (ComCfg::FppConstant_SpacecraftId::SpacecraftId); + + +// Test fixture to set up the detector under test and circular buffer +class CcsdsFrameDetectorTest : public ::testing::Test { + protected: + + void SetUp() override { + ::memset(this->m_buffer, 0, CIRCULAR_BUFFER_TEST_SIZE); + this->circular_buffer = Types::CircularBuffer(this->m_buffer, CIRCULAR_BUFFER_TEST_SIZE); + } + + U8 m_buffer[CIRCULAR_BUFFER_TEST_SIZE]; + Svc::FrameDetectors::CcsdsTCFrameDetector detector; + Types::CircularBuffer circular_buffer; + +}; + +//! \brief Create an F´ frame and serialize it into the supplied circular buffer +//! \param circular_buffer The circular buffer to serialize the frame into +//! \note The frame is generated with random data of random size +//! \return The size of the generated frame +FwSizeType generate_random_tc_frame(Types::CircularBuffer& circular_buffer) { + // Generate random packet size (1-1024 bytes; because 0 would trigger undefined behavior warnings) + // U16 packet_size = static_cast(STest::Random::lowerUpper(1, 1024)); + U16 packet_size = 10; + + FwSizeType total_frame_size = packet_size + TCHeader::SERIALIZED_SIZE + TCTrailer::SERIALIZED_SIZE; + + U8 packet_data[packet_size]; + // Generate random packet_data of random size + for (FwSizeType i = 0; i < packet_size; i++) { + packet_data[i] = static_cast(STest::Random::lowerUpper(0, 255)); + } + TCHeader tcHeader( + EXPECTED_START_TOKEN, // Use a predefined token for flags and SC ID + static_cast(packet_size), // Length (and unused VcId) + static_cast(STest::Random::lowerUpper(0, 255)) // Random frame sequence number + ); + + U8 frame_header[TCHeader::SERIALIZED_SIZE]; + Fw::ExternalSerializeBuffer header_ser_buffer(frame_header, TCHeader::SERIALIZED_SIZE); + tcHeader.serialize(header_ser_buffer); + + // Serialize header and packet data into the circular buffer + circular_buffer.serialize(frame_header, TCHeader::SERIALIZED_SIZE); + circular_buffer.serialize(packet_data, packet_size); + + U8 frame_trailer[TCTrailer::SERIALIZED_SIZE]; + Fw::ExternalSerializeBuffer trailer_ser_buffer(frame_trailer, TCTrailer::SERIALIZED_SIZE); + TCTrailer tcTrailer; + + // Calculate CRC on header + packet_data + Svc::CCSDS::Utils::CRC16 crc; + for (FwSizeType i = 0; i < packet_size + TCHeader::SERIALIZED_SIZE; ++i) { + U8 byte = 0; + circular_buffer.peek(byte, i); + crc.update(byte); + } + tcTrailer.setfecf(crc.finalize()); + tcTrailer.serialize(trailer_ser_buffer); + // Serialize trailer into the circular buffer + circular_buffer.serialize(frame_trailer, TCTrailer::SERIALIZED_SIZE); + return total_frame_size; +} + +TEST_F(CcsdsFrameDetectorTest, TestBufferTooSmall) { + + // Anything smaller than the size of header + trailer is invalid + U32 minimum_valid_size = TCHeader::SERIALIZED_SIZE + TCTrailer::SERIALIZED_SIZE; + U32 invalid_size = STest::Random::lowerUpper(1, minimum_valid_size - 1); + this->circular_buffer.serialize(this->m_buffer, invalid_size); + + Svc::FrameDetector::Status status; + FwSizeType size_out = 0; + status = this->detector.detect(circular_buffer, size_out); + + // Expect that the detector reports that more data is needed + EXPECT_EQ(status, Svc::FrameDetector::Status::MORE_DATA_NEEDED); + EXPECT_EQ(size_out, minimum_valid_size); +} + +TEST_F(CcsdsFrameDetectorTest, TestFrameDetected) { + FwSizeType frame_size = generate_random_tc_frame(this->circular_buffer); + + Svc::FrameDetector::Status status; + FwSizeType size_out = 0; + status = this->detector.detect(circular_buffer, size_out); + + EXPECT_EQ(status, Svc::FrameDetector::Status::FRAME_DETECTED); + EXPECT_EQ(size_out, frame_size); +} + +TEST_F(CcsdsFrameDetectorTest, TestManyFrameDetected) { + U32 MAX_ITERS = 1000; + for (U32 i = 0; i < MAX_ITERS; i++) { + FwSizeType frame_size = generate_random_tc_frame(this->circular_buffer); + Svc::FrameDetector::Status status; + FwSizeType size_out = 0; + status = this->detector.detect(this->circular_buffer, size_out); + EXPECT_EQ(status, Svc::FrameDetector::Status::FRAME_DETECTED); + EXPECT_EQ(size_out, frame_size); + this->circular_buffer.rotate(size_out); // clear up used data + } +} + +TEST_F(CcsdsFrameDetectorTest, TestNoFrameDetected) { + (void) generate_random_tc_frame(this->circular_buffer); + // Remove 1 byte from the beginning of the frame, making it invalid + this->circular_buffer.rotate(1); + Svc::FrameDetector::Status status; + FwSizeType unused = 0; + status = this->detector.detect(this->circular_buffer, unused); + EXPECT_EQ(status, Svc::FrameDetector::Status::NO_FRAME_DETECTED); +} + +TEST_F(CcsdsFrameDetectorTest, TestMoreDataNeeded) { + (void)generate_random_tc_frame(this->circular_buffer); + this->circular_buffer.m_allocated_size--; // Remove 1 byte from the end of the frame to trigger "more data needed" + Svc::FrameDetector::Status status; + FwSizeType unused = 0; + status = this->detector.detect(this->circular_buffer, unused); + EXPECT_EQ(status, Svc::FrameDetector::Status::MORE_DATA_NEEDED); +} + +TEST_F(CcsdsFrameDetectorTest, TestCorruptedCrc) { + (void)generate_random_tc_frame(this->circular_buffer); + + Svc::FrameDetector::Status status; + FwSizeType unused = 0; + status = this->detector.detect(this->circular_buffer, unused); + EXPECT_EQ(status, Svc::FrameDetector::Status::MORE_DATA_NEEDED); +} + +int main(int argc, char** argv) { + STest::Random::seed(); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} From b9d746fd6e2a9c2bfd28511ae183bd89da29220f Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Mon, 2 Jun 2025 15:24:59 -0700 Subject: [PATCH 60/95] Fix Ref topology --- Ref/Top/topology.fpp | 44 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/Ref/Top/topology.fpp b/Ref/Top/topology.fpp index f3dfe152991..ebd4a7842a9 100644 --- a/Ref/Top/topology.fpp +++ b/Ref/Top/topology.fpp @@ -99,6 +99,8 @@ module Ref { # ---------------------------------------------------------------------- connections Downlink { + apidDemo.sendPacketDown -> comQueue.bufferQueueIn[1] + comQueue.bufferReturnOut[1] -> apidDemo.bufferReturnIn # Data Products dpCat.fileOut -> fileDownlink.SendFile fileDownlink.FileComplete -> dpCat.fileDone @@ -107,32 +109,27 @@ module Ref { tlmSend.PktSend -> comQueue.comPacketQueueIn[Ports_ComPacketQueue.TELEMETRY] fileDownlink.bufferSendOut -> comQueue.bufferQueueIn[Ports_ComBufferQueue.FILE_DOWNLINK] comQueue.bufferReturnOut[Ports_ComBufferQueue.FILE_DOWNLINK] -> fileDownlink.bufferReturn - # ComQueue <-> ApidManager - comQueue.dataOut -> apidManager.dataIn - apidManager.dataReturnOut -> comQueue.dataReturnIn - # ApidManager <-> Framer - apidManager.dataOut -> spacePacketFramer.dataIn - spacePacketFramer.dataReturnOut -> apidManager.dataReturnIn - # Buffer Management for Framer + # ComQueue <-> SpacePacketFramer + comQueue.dataOut -> spacePacketFramer.dataIn + spacePacketFramer.dataReturnOut -> comQueue.dataReturnIn + # SpacePacketFramer buffer and APID management spacePacketFramer.bufferAllocate -> commsBufferManager.bufferGetCallee spacePacketFramer.bufferDeallocate -> commsBufferManager.bufferSendIn - tmFramer.bufferAllocate -> commsBufferManager.bufferGetCallee - tmFramer.bufferDeallocate -> commsBufferManager.bufferSendIn - # Framer chain + spacePacketFramer.getApidSeqCount -> apidManager.getApidSeqCountIn + # SpacePacketFramer <-> TMFramer spacePacketFramer.dataOut -> tmFramer.dataIn - tmFramer.dataReturnOut -> spacePacketFramer.dataReturnIn + tmFramer.dataReturnOut -> spacePacketFramer.dataReturnIn # Framer <-> ComStub - tmFramer.dataOut -> comStub.dataIn + tmFramer.dataOut -> comStub.dataIn comStub.dataReturnOut -> tmFramer.dataReturnIn # ComStub <-> ComDriver comStub.drvSendOut -> comDriver.$send comDriver.sendReturnOut -> comStub.drvSendReturnIn comDriver.ready -> comStub.drvConnected # ComStatus - comStub.comStatusOut -> tmFramer.comStatusIn - tmFramer.comStatusOut -> spacePacketFramer.comStatusIn + comStub.comStatusOut -> tmFramer.comStatusIn + tmFramer.comStatusOut -> spacePacketFramer.comStatusIn spacePacketFramer.comStatusOut -> comQueue.comStatusIn - # TODO: probably need comStatus to APIDMapper ?? } connections FaultProtection { @@ -195,13 +192,16 @@ module Ref { frameAccumulator.bufferDeallocate -> commsBufferManager.bufferSendIn frameAccumulator.bufferAllocate -> commsBufferManager.bufferGetCallee # FrameAccumulator <-> Deframer - frameAccumulator.dataOut -> tcDeframer.dataIn - tcDeframer.dataReturnOut -> frameAccumulator.dataReturnIn - tcDeframer.dataOut -> spacePacketDeframer.dataIn + frameAccumulator.dataOut -> tcDeframer.dataIn + tcDeframer.dataReturnOut -> frameAccumulator.dataReturnIn + # TCDeframer <-> SpacePacketDeframer + tcDeframer.dataOut -> spacePacketDeframer.dataIn spacePacketDeframer.dataReturnOut -> tcDeframer.dataReturnIn - # Deframer <-> Router - spacePacketDeframer.dataOut -> fprimeRouter.dataIn - fprimeRouter.dataReturnOut -> spacePacketDeframer.dataReturnIn + # SpacePacketDeframer APID validation + spacePacketDeframer.validateApidSeqCount -> apidManager.validateApidSeqCountIn + # SpacePacketDeframer <-> Router + spacePacketDeframer.dataOut -> fprimeRouter.dataIn + fprimeRouter.dataReturnOut -> spacePacketDeframer.dataReturnIn # Router buffer allocations fprimeRouter.bufferAllocate -> commsBufferManager.bufferGetCallee fprimeRouter.bufferDeallocate -> commsBufferManager.bufferSendIn @@ -210,8 +210,6 @@ module Ref { cmdDisp.seqCmdStatus -> fprimeRouter.cmdResponseIn fprimeRouter.fileOut -> fileUplink.bufferSendIn fileUplink.bufferSendOut -> fprimeRouter.fileBufferReturnIn - - spacePacketDeframer.validateApidSeqCount -> apidManager.validateApidSeqCountIn } connections DataProducts { From f7bcdd51efdad23a1fc85c5590f08c345d1f7e8f Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Mon, 2 Jun 2025 15:25:40 -0700 Subject: [PATCH 61/95] Fix old PacketType usage --- Svc/FprimeRouter/test/ut/FprimeRouterTester.cpp | 2 +- Svc/FprimeRouter/test/ut/FprimeRouterTester.hpp | 2 +- Svc/FramingProtocol/FprimeProtocol.cpp | 2 +- Svc/FramingProtocol/FprimeProtocol.hpp | 2 +- Svc/FramingProtocol/FramingProtocol.hpp | 2 +- Svc/FramingProtocol/docs/sdd.md | 2 +- Svc/FramingProtocol/test/ut/FramingTester.cpp | 4 ++-- Svc/FramingProtocol/test/ut/FramingTester.hpp | 4 ++-- docs/user-manual/framework/ground-interface.md | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Svc/FprimeRouter/test/ut/FprimeRouterTester.cpp b/Svc/FprimeRouter/test/ut/FprimeRouterTester.cpp index 0e3638be801..857bdcf6c54 100644 --- a/Svc/FprimeRouter/test/ut/FprimeRouterTester.cpp +++ b/Svc/FprimeRouter/test/ut/FprimeRouterTester.cpp @@ -85,7 +85,7 @@ void FprimeRouterTester ::testCommandResponse() { // Test Helper // ---------------------------------------------------------------------- -void FprimeRouterTester::mockReceivePacketType(Fw::ComPacket::ComPacketType packetType) { +void FprimeRouterTester::mockReceivePacketType(Fw::ComPacketType packetType) { const FwPacketDescriptorType descriptorType = packetType; U8 data[sizeof descriptorType]; Fw::Buffer buffer(data, sizeof(data)); diff --git a/Svc/FprimeRouter/test/ut/FprimeRouterTester.hpp b/Svc/FprimeRouter/test/ut/FprimeRouterTester.hpp index bc32e6a4a77..8146d3a2003 100644 --- a/Svc/FprimeRouter/test/ut/FprimeRouterTester.hpp +++ b/Svc/FprimeRouter/test/ut/FprimeRouterTester.hpp @@ -77,7 +77,7 @@ class FprimeRouterTester : public FprimeRouterGTestBase { void initComponents(); //! Mock the reception of a packet of a specific type - void mockReceivePacketType(Fw::ComPacket::ComPacketType packetType); + void mockReceivePacketType(Fw::ComPacketType packetType); // ---------------------------------------------------------------------- // Port handler overrides diff --git a/Svc/FramingProtocol/FprimeProtocol.cpp b/Svc/FramingProtocol/FprimeProtocol.cpp index 7bedb8a4f8c..9b0669808d2 100644 --- a/Svc/FramingProtocol/FprimeProtocol.cpp +++ b/Svc/FramingProtocol/FprimeProtocol.cpp @@ -19,7 +19,7 @@ FprimeFraming::FprimeFraming(): FramingProtocol() {} FprimeDeframing::FprimeDeframing(): DeframingProtocol() {} -void FprimeFraming::frame(const U8* const data, const U32 size, Fw::ComPacket::ComPacketType packet_type) { +void FprimeFraming::frame(const U8* const data, const U32 size, Fw::ComPacketType packet_type) { // NOTE: packet_type is not used in this implementation FW_ASSERT(data != nullptr); diff --git a/Svc/FramingProtocol/FprimeProtocol.hpp b/Svc/FramingProtocol/FprimeProtocol.hpp index f6feac3d441..55f4e508639 100644 --- a/Svc/FramingProtocol/FprimeProtocol.hpp +++ b/Svc/FramingProtocol/FprimeProtocol.hpp @@ -45,7 +45,7 @@ namespace Svc { void frame( const U8* const data, //!< The data const U32 size, //!< The data size in bytes - Fw::ComPacket::ComPacketType packet_type //!< The packet type + Fw::ComPacketType packet_type //!< The packet type ) override; }; diff --git a/Svc/FramingProtocol/FramingProtocol.hpp b/Svc/FramingProtocol/FramingProtocol.hpp index c2deb12c403..fe73397449c 100644 --- a/Svc/FramingProtocol/FramingProtocol.hpp +++ b/Svc/FramingProtocol/FramingProtocol.hpp @@ -43,7 +43,7 @@ class FramingProtocol { //! \param data: pointer to a set of bytes to be framed //! \param size: size of data pointed to by `data` //! \param packet_type: type of data supplied for File downlink packets - virtual void frame(const U8* const data, const U32 size, Fw::ComPacket::ComPacketType packet_type) = 0; + virtual void frame(const U8* const data, const U32 size, Fw::ComPacketType packet_type) = 0; PROTECTED: FramingProtocolInterface* m_interface; diff --git a/Svc/FramingProtocol/docs/sdd.md b/Svc/FramingProtocol/docs/sdd.md index 60cba914c73..90ba9fbe03c 100644 --- a/Svc/FramingProtocol/docs/sdd.md +++ b/Svc/FramingProtocol/docs/sdd.md @@ -144,7 +144,7 @@ To implement `FramingProtocol`, you must implement the following pure virtual method: ```c++ -virtual void frame(const U8* const data, const U32 size, Fw::ComPacket::ComPacketType packet_type) = 0; +virtual void frame(const U8* const data, const U32 size, Fw::ComPacketType packet_type) = 0; ``` This method is called with the following arguments: diff --git a/Svc/FramingProtocol/test/ut/FramingTester.cpp b/Svc/FramingProtocol/test/ut/FramingTester.cpp index b86af5c4b43..ea43370427f 100644 --- a/Svc/FramingProtocol/test/ut/FramingTester.cpp +++ b/Svc/FramingProtocol/test/ut/FramingTester.cpp @@ -15,7 +15,7 @@ namespace Svc { // ---------------------------------------------------------------------- FramingTester :: - FramingTester(Fw::ComPacket::ComPacketType a_packetType) : + FramingTester(Fw::ComPacketType a_packetType) : // Pick a random data size dataSize(STest::Pick::lowerUpper(1, MAX_DATA_SIZE)), packetType(a_packetType), @@ -94,7 +94,7 @@ namespace Svc { sb.fill(); const Fw::SerializeStatus status = sb.deserialize(serialPacketType); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); - typedef Fw::ComPacket::ComPacketType PacketType; + typedef Fw::ComPacketType PacketType; const PacketType pt = static_cast(serialPacketType); ASSERT_EQ(pt, this->packetType); } diff --git a/Svc/FramingProtocol/test/ut/FramingTester.hpp b/Svc/FramingProtocol/test/ut/FramingTester.hpp index 6606a2e9fa6..1ada9c2c752 100644 --- a/Svc/FramingProtocol/test/ut/FramingTester.hpp +++ b/Svc/FramingProtocol/test/ut/FramingTester.hpp @@ -73,7 +73,7 @@ class FramingTester { // ---------------------------------------------------------------------- //! Construct a FramingTester - FramingTester(Fw::ComPacket::ComPacketType a_packetType //!< The packet type + FramingTester(Fw::ComPacketType a_packetType //!< The packet type ); public: @@ -121,7 +121,7 @@ class FramingTester { const U32 dataSize; //! The packet type - Fw::ComPacket::ComPacketType packetType; + Fw::ComPacketType packetType; //! Storage for the buffer U8 bufferStorage[MAX_BUFFER_SIZE]; diff --git a/docs/user-manual/framework/ground-interface.md b/docs/user-manual/framework/ground-interface.md index ebda43cbe8a..99dbe3dbdb9 100644 --- a/docs/user-manual/framework/ground-interface.md +++ b/docs/user-manual/framework/ground-interface.md @@ -121,7 +121,7 @@ class MyFrameProtocol : public Svc::FramingProtocol { public: MyFrameProtocol() {} - void frame(const U8 *const data, const U32 size, Fw::ComPacket::ComPacketType packet_type) { + void frame(const U8 *const data, const U32 size, Fw::ComPacketType packet_type) { Fw::Buffer my_framed_data = m_interface.allocate(size); auto serializer = my_framed_data.getSerializer(); serializer.serialize(0xdeadbeef); // Some start word From dbc6b72cbafc1f31587d84c8fd4c6253ea0f7ace Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Mon, 2 Jun 2025 16:30:00 -0700 Subject: [PATCH 62/95] Fix ComQueue UTs --- Svc/ComQueue/test/ut/ComQueueTester.cpp | 25 +++++++++++++------------ Svc/ComQueue/test/ut/ComQueueTester.hpp | 6 +++++- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/Svc/ComQueue/test/ut/ComQueueTester.cpp b/Svc/ComQueue/test/ut/ComQueueTester.cpp index bbc67a2080c..e9eafc9b2b4 100644 --- a/Svc/ComQueue/test/ut/ComQueueTester.cpp +++ b/Svc/ComQueue/test/ut/ComQueueTester.cpp @@ -80,7 +80,7 @@ void ComQueueTester ::emitOneAndCheck(FwIndexType expectedIndex, // ---------------------------------------------------------------------- void ComQueueTester ::testQueueSend() { - U8 data[BUFFER_LENGTH] = {0xde, 0xad, 0xbe}; + U8 data[BUFFER_LENGTH] = BUFFER_DATA; Fw::ComBuffer comBuffer(&data[0], sizeof(data)); Fw::Buffer buffer(&data[0], sizeof(data)); configure(); @@ -100,7 +100,7 @@ void ComQueueTester ::testQueueSend() { } void ComQueueTester ::testQueuePause() { - U8 data[BUFFER_LENGTH] = {0xde, 0xad, 0xbe}; + U8 data[BUFFER_LENGTH] = BUFFER_DATA; Fw::ComBuffer comBuffer(&data[0], sizeof(data)); Fw::Buffer buffer(&data[0], sizeof(data)); configure(); @@ -130,20 +130,21 @@ void ComQueueTester ::testQueuePause() { } void ComQueueTester ::testPrioritySend() { - U8 data[ComQueue::TOTAL_PORT_COUNT][BUFFER_LENGTH]; + U8 data[ComQueue::TOTAL_PORT_COUNT][BUFFER_LENGTH] = {}; ComQueue::QueueConfigurationTable configurationTable; for (FwIndexType i = 0; i < ComQueue::TOTAL_PORT_COUNT; i++) { configurationTable.entries[i].priority = ComQueue::TOTAL_PORT_COUNT - i - 1; configurationTable.entries[i].depth = 3; - data[i][0] = ComQueue::TOTAL_PORT_COUNT - i - 1; + // Set a unique data value in the buffer (at offset, accounting for mandatory packet type) + data[i][BUFFER_DATA_OFFSET] = ComQueue::TOTAL_PORT_COUNT - i - 1; } // Make the last message have the same priority as the second message configurationTable.entries[ComQueue::TOTAL_PORT_COUNT - 1].priority = 1; - data[ComQueue::TOTAL_PORT_COUNT - 2][0] = 0; - data[ComQueue::TOTAL_PORT_COUNT - 1][0] = 1; + data[ComQueue::TOTAL_PORT_COUNT - 2][BUFFER_DATA_OFFSET] = 0; + data[ComQueue::TOTAL_PORT_COUNT - 1][BUFFER_DATA_OFFSET] = 1; component.configure(configurationTable, 0, mallocAllocator); @@ -168,7 +169,7 @@ void ComQueueTester ::testPrioritySend() { // Check that the size changed by exactly one ASSERT_EQ(fromPortHistory_dataOut->size(), (previousSize + 1)); - orderKey = fromPortHistory_dataOut->at(index).data.getData()[0]; + orderKey = fromPortHistory_dataOut->at(index).data.getData()[BUFFER_DATA_OFFSET]; ASSERT_EQ(orderKey, index); } clearFromPortHistory(); @@ -196,7 +197,7 @@ void ComQueueTester::testExternalQueueOverflow() { component.configure(configurationTable, 0, mallocAllocator); - U8 data[BUFFER_LENGTH] = {0xde, 0xad, 0xbe}; + U8 data[BUFFER_LENGTH] = BUFFER_DATA; Fw::Buffer buffer(&data[0], sizeof(data)); for (FwIndexType queueNum = 0; queueNum < ComQueue::TOTAL_PORT_COUNT; queueNum++) { @@ -254,7 +255,7 @@ void ComQueueTester::testExternalQueueOverflow() { void ComQueueTester::testInternalQueueOverflow() { // Internal queue is the message queue for async input ports - U8 data[BUFFER_LENGTH] = {0xde, 0xad, 0xbe}; + U8 data[BUFFER_LENGTH] = BUFFER_DATA; Fw::Buffer buffer(data, sizeof(data)); const FwIndexType queueNum = ComQueue::COM_PORT_COUNT; @@ -285,7 +286,7 @@ void ComQueueTester::testInternalQueueOverflow() { } void ComQueueTester ::testReadyFirst() { - U8 data[BUFFER_LENGTH] = {0xde, 0xad, 0xbe}; + U8 data[BUFFER_LENGTH] = BUFFER_DATA; Fw::ComBuffer comBuffer(&data[0], sizeof(data)); Fw::Buffer buffer(&data[0], sizeof(data)); configure(); @@ -318,7 +319,7 @@ void ComQueueTester ::testReadyFirst() { } void ComQueueTester ::testContextData() { - U8 data[BUFFER_LENGTH] = {0xde, 0xad, 0xbe}; + U8 data[BUFFER_LENGTH] = BUFFER_DATA; Fw::ComBuffer comBuffer(&data[0], sizeof(data)); Fw::Buffer buffer(&data[0], sizeof(data)); configure(); @@ -346,7 +347,7 @@ void ComQueueTester ::testContextData() { } void ComQueueTester ::testBufferQueueReturn() { - U8 data[BUFFER_LENGTH] = {0xde, 0xad, 0xbe}; + U8 data[BUFFER_LENGTH] = BUFFER_DATA; Fw::Buffer buffer(&data[0], sizeof(data)); ComCfg::FrameContext context; configure(); diff --git a/Svc/ComQueue/test/ut/ComQueueTester.hpp b/Svc/ComQueue/test/ut/ComQueueTester.hpp index 78b2e42d520..b2d5d137176 100644 --- a/Svc/ComQueue/test/ut/ComQueueTester.hpp +++ b/Svc/ComQueue/test/ut/ComQueueTester.hpp @@ -9,7 +9,11 @@ #include "ComQueueGTestBase.hpp" #include "Svc/ComQueue/ComQueue.hpp" -#define BUFFER_LENGTH 3u +#include "Fw/Com/ComPacket.hpp" + +#define BUFFER_LENGTH 7u +#define BUFFER_DATA {0x00, 0x00, 0x00, 0x01, 0xad, 0xbe, 0xde} // First 4 bytes are the ComPacketType +#define BUFFER_DATA_OFFSET sizeof(Fw::ComPacketType) namespace Svc { From ad35401eaa05dbe2bb41cbd69d6b79e6585051a5 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Mon, 2 Jun 2025 16:30:21 -0700 Subject: [PATCH 63/95] Fix CI warnings --- Svc/CCSDS/ApidManager/ApidManager.cpp | 4 ++-- Svc/CCSDS/TCDeframer/TCDeframer.cpp | 2 +- Svc/CCSDS/TMFramer/TMFramer.cpp | 2 +- Svc/CCSDS/Utils/CRC16.hpp | 2 +- Svc/FprimeRouter/FprimeRouter.cpp | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Svc/CCSDS/ApidManager/ApidManager.cpp b/Svc/CCSDS/ApidManager/ApidManager.cpp index 1f80de00086..874a9342b88 100644 --- a/Svc/CCSDS/ApidManager/ApidManager.cpp +++ b/Svc/CCSDS/ApidManager/ApidManager.cpp @@ -55,7 +55,7 @@ U16 ApidManager ::getAndIncrementSeqCount(ComCfg::APID::T apid) { for (U8 i = 0; i < MAX_TRACKED_APIDS; ++i) { if (this->m_apidSequences[i].apid == apid) { seqCount = this->m_apidSequences[i].sequenceCount; - this->m_apidSequences[i].sequenceCount = (seqCount + 1) % (1 << 14); // Increment for next call + this->m_apidSequences[i].sequenceCount = static_cast((seqCount + 1) % (1 << 14)); // Increment for next call return seqCount; // Return the current sequence count } } @@ -64,7 +64,7 @@ U16 ApidManager ::getAndIncrementSeqCount(ComCfg::APID::T apid) { if (this->m_apidSequences[i].apid == ComCfg::APID::INVALID_UNINITIALIZED) { this->m_apidSequences[i].apid = apid; // Initialize this entry with the new APID seqCount = this->m_apidSequences[i].sequenceCount; // Entries default to 0 unless otherwise specified - this->m_apidSequences[i].sequenceCount = (seqCount + 1) % (1 << 14); // Increment for next call + this->m_apidSequences[i].sequenceCount = static_cast((seqCount + 1) % (1 << 14)); // Increment for next call return seqCount; // Return the initialized sequence count } } diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.cpp b/Svc/CCSDS/TCDeframer/TCDeframer.cpp index 1e208a501da..178cacd5264 100644 --- a/Svc/CCSDS/TCDeframer/TCDeframer.cpp +++ b/Svc/CCSDS/TCDeframer/TCDeframer.cpp @@ -62,7 +62,7 @@ void TCDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const Co this->dataReturnOut_out(0, data, context); // drop the frame return; } - if (data.getSize() < frame_length + TCHeader::SERIALIZED_SIZE + TCTrailer::SERIALIZED_SIZE) { + if (data.getSize() < static_cast(frame_length + TCHeader::SERIALIZED_SIZE + TCTrailer::SERIALIZED_SIZE)) { U32 maxDataAvailable = data.getSize() - TCHeader::SERIALIZED_SIZE - TCTrailer::SERIALIZED_SIZE; this->log_WARNING_HI_InvalidFrameLength(frame_length, maxDataAvailable); this->dataReturnOut_out(0, data, context); // drop the frame diff --git a/Svc/CCSDS/TMFramer/TMFramer.cpp b/Svc/CCSDS/TMFramer/TMFramer.cpp index a46cd62366f..e50b365a5b9 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.cpp +++ b/Svc/CCSDS/TMFramer/TMFramer.cpp @@ -41,7 +41,7 @@ void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComC U16 globalVcId = 0; globalVcId |= ComCfg::SpacecraftId << TMSubfields::spacecraftIdOffset; - globalVcId |= context.getvcId() << TMSubfields::virtualChannelIdOffset; + globalVcId |= static_cast(context.getvcId() << TMSubfields::virtualChannelIdOffset); globalVcId |= 0x0; // Operational Control Field: Flag set to 0 (Standard 4.1.2.4) // Data Field Status (Standard 4.1.2.7): diff --git a/Svc/CCSDS/Utils/CRC16.hpp b/Svc/CCSDS/Utils/CRC16.hpp index 00d9011871b..8d12ecfb9cb 100644 --- a/Svc/CCSDS/Utils/CRC16.hpp +++ b/Svc/CCSDS/Utils/CRC16.hpp @@ -55,4 +55,4 @@ class CRC16 { } // namespace CCSDS } // namespace Svc -#endif // SVC_CCSDS_UTILS_CRC16_HPP \ No newline at end of file +#endif // SVC_CCSDS_UTILS_CRC16_HPP diff --git a/Svc/FprimeRouter/FprimeRouter.cpp b/Svc/FprimeRouter/FprimeRouter.cpp index a0c4c457368..db5e8b14b3f 100644 --- a/Svc/FprimeRouter/FprimeRouter.cpp +++ b/Svc/FprimeRouter/FprimeRouter.cpp @@ -31,7 +31,7 @@ void FprimeRouter ::dataIn_handler(FwIndexType portNum, Fw::Buffer& packetBuffer if (packetType == Fw::ComPacketType::FW_PACKET_UNKNOWN) { FwPacketDescriptorType packetDescriptor; auto esb = packetBuffer.getDeserializer(); - status = esb.deserialize(packetDescriptor); + (void) esb.deserialize(packetDescriptor); packetType = static_cast(packetDescriptor); } // Route based on received APID (packet type) From 429e2e452aff905ac5db373e36babb1fb34470fd Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Mon, 2 Jun 2025 16:39:11 -0700 Subject: [PATCH 64/95] Add test for CRC corruption in frame detector --- .../test/ut/detectors/CcsdsTCFrameDetectorTestMain.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Svc/FrameAccumulator/test/ut/detectors/CcsdsTCFrameDetectorTestMain.cpp b/Svc/FrameAccumulator/test/ut/detectors/CcsdsTCFrameDetectorTestMain.cpp index a9255599b7e..06ab80be6f9 100644 --- a/Svc/FrameAccumulator/test/ut/detectors/CcsdsTCFrameDetectorTestMain.cpp +++ b/Svc/FrameAccumulator/test/ut/detectors/CcsdsTCFrameDetectorTestMain.cpp @@ -141,12 +141,14 @@ TEST_F(CcsdsFrameDetectorTest, TestMoreDataNeeded) { } TEST_F(CcsdsFrameDetectorTest, TestCorruptedCrc) { - (void)generate_random_tc_frame(this->circular_buffer); + FwSizeType frame_size = generate_random_tc_frame(this->circular_buffer); + this->m_buffer[frame_size - 2] = 0xFF; // Corrupt the last 2 bytes to fail CRC check + this->m_buffer[frame_size - 1] = 0xFF; // Corrupt the last 2 bytes to fail CRC check Svc::FrameDetector::Status status; FwSizeType unused = 0; status = this->detector.detect(this->circular_buffer, unused); - EXPECT_EQ(status, Svc::FrameDetector::Status::MORE_DATA_NEEDED); + EXPECT_EQ(status, Svc::FrameDetector::Status::NO_FRAME_DETECTED); } int main(int argc, char** argv) { From 20513b1b08a86ab8edde9a68d2aaa5cf957b9423 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Mon, 2 Jun 2025 17:15:14 -0700 Subject: [PATCH 65/95] Spelling --- .github/actions/spelling/expect.txt | 14 ++++++++-- .../ApidManager/test/ut/ApidManagerTester.cpp | 12 ++++---- Svc/CCSDS/TCDeframer/TCDeframer.fpp | 2 +- Svc/CCSDS/TCDeframer/docs/sdd.md | 18 ++++++------ Svc/CCSDS/TMFramer/TMFramer.fpp | 2 +- Svc/CCSDS/TMFramer/docs/sdd.md | 28 +++++++++---------- Svc/CCSDS/Types/Types.fpp | 12 +++----- .../FrameDetector/CcsdsTCFrameDetector.cpp | 2 +- default/config/ComCfg.fpp | 2 +- 9 files changed, 49 insertions(+), 43 deletions(-) diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt index fe80963da51..b850a2d7e52 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt @@ -70,7 +70,7 @@ bibtex Bies bindir binrel -Bitfields +bitfields bitmaps blogs bocchino @@ -109,7 +109,7 @@ CBF CBLOCK CCB CComponent -CCSDS +ccsds ccsparc cdefs CDH @@ -323,6 +323,7 @@ Fabcdef FAKELOGGER fbuild fdp +fecf FEEDNAME fetchcontent ffff @@ -423,6 +424,7 @@ gtags gtest gtimeout Guire +GVCID HACKSM handcoded handleflags @@ -659,7 +661,9 @@ objcopy objdoc objdump objmodule +OCF oclc +ODR oflag okidocki oldeol @@ -785,6 +789,7 @@ ptrt puml punc pushd +pvn PYS PYTHONPATH qch @@ -859,6 +864,7 @@ sbom Scatterometer scc schematron +scid sclk scm scons @@ -985,6 +991,7 @@ TCSANOW tcsh tdir tdirection +telecommand telem TELEMCHANIMPL testcmd @@ -1088,6 +1095,9 @@ ustr utdir valgrind vbai +vca +vcid +vcp vfd VFILE VID diff --git a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp index 67ed15dbf74..fe326e543c3 100644 --- a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp +++ b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp @@ -51,10 +51,10 @@ void ApidManagerTester::GetExistingSeqCount::action(ApidManagerTester& testerSta testerState.clearHistory(); ComCfg::APID::T apid = testerState.getRandomTrackedApid(); U16 seqCount = testerState.invoke_to_getApidSeqCountIn(0, apid, 0); - U16 shadownSeqCount = testerState.shadow_getAndIncrementSeqCount(apid); - ASSERT_EQ(seqCount, shadownSeqCount) + U16 shadowSeqCount = testerState.shadow_getAndIncrementSeqCount(apid); + ASSERT_EQ(seqCount, shadowSeqCount) << "Sequence count for APID " << static_cast(apid) << " does not match shadow value." - << " Shadow: " << shadownSeqCount << ", Actual: " << seqCount; + << " Shadow: " << shadowSeqCount << ", Actual: " << seqCount; } @@ -74,10 +74,10 @@ void ApidManagerTester::GetNewSeqCountOk::action(ApidManagerTester& testerState) ComCfg::APID::T apid = testerState.getRandomUntrackedApid(); U16 seqCount = testerState.invoke_to_getApidSeqCountIn(0, apid, 0); - U16 shadownSeqCount = testerState.shadow_getAndIncrementSeqCount(apid); - ASSERT_EQ(seqCount, shadownSeqCount) + U16 shadowSeqCount = testerState.shadow_getAndIncrementSeqCount(apid); + ASSERT_EQ(seqCount, shadowSeqCount) << "Sequence count for APID " << static_cast(apid) << " does not match shadow value." - << " Shadow: " << shadownSeqCount << ", Actual: " << seqCount; + << " Shadow: " << shadowSeqCount << ", Actual: " << seqCount; } bool ApidManagerTester::GetNewSeqCountTableFull::precondition(const ApidManagerTester& testerState) { diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.fpp b/Svc/CCSDS/TCDeframer/TCDeframer.fpp index 43adb63cf51..5294e618e7b 100644 --- a/Svc/CCSDS/TCDeframer/TCDeframer.fpp +++ b/Svc/CCSDS/TCDeframer/TCDeframer.fpp @@ -1,6 +1,6 @@ module Svc { module CCSDS { - @ Deframer for the TC Space Data Link Protocl (CCSDS Standard) + @ Deframer for the TC Space Data Link Protocol (CCSDS Standard) passive component TCDeframer { include "../../Interfaces/DeframerInterface.fppi" diff --git a/Svc/CCSDS/TCDeframer/docs/sdd.md b/Svc/CCSDS/TCDeframer/docs/sdd.md index 04dff30056c..c4050063ce6 100644 --- a/Svc/CCSDS/TCDeframer/docs/sdd.md +++ b/Svc/CCSDS/TCDeframer/docs/sdd.md @@ -42,12 +42,12 @@ void configure(U16 vcId, U16 spacecraftId, bool acceptAllVcid); | Name | Description | Validation | |---|---|---| -| SVC-CCSDS-TCDEFRAMER-001 | The TCDeframer shall deframe Telecommand (TC) Transfer Frames according to the CCSDS Space Data Link Protocol standard for Type-BD frames. | Unit Test, Inspection | -| SVC-CCSDS-TCDEFRAMER-002 | The TCDeframer shall perform Frame Validation Check Procedures, including Spacecraft ID, Virtual Channel ID, Frame Length, and CRC. | Unit Test | -| SVC-CCSDS-TCDEFRAMER-003 | The TCDeframer shall be configurable for a specific Spacecraft ID. | Unit Test, Inspection | -| SVC-CCSDS-TCDEFRAMER-004 | The TCDeframer shall be configurable with a specific Virtual Channel ID (VCID) OR to accept all VCIDs. | Unit Test, Inspection | -| SVC-CCSDS-TCDEFRAMER-005 | The TCDeframer shall log an `InvalidSpacecraftId` event if a frame with an unexpected Spacecraft ID is received. | Unit Test | -| SVC-CCSDS-TCDEFRAMER-006 | The TCDeframer shall log an `InvalidFrameLength` event if a frame with an invalid length is received. | Unit Test | -| SVC-CCSDS-TCDEFRAMER-007 | The TCDeframer shall log an `InvalidVcId` event if a frame with an unexpected VCID is received (when not configured to accept all VCIDs). | Unit Test | -| SVC-CCSDS-TCDEFRAMER-008 | The TCDeframer shall log an `InvalidCrc` event if a frame fails the CRC check. | Unit Test | -| SVC-CCSDS-TCDEFRAMER-009 | The TCDeframer shall provide an input port (`dataIn`) to receive framed data, and emit deframed data packets on its `dataOut` output port. | Unit Test | +| SVC-CCSDS-TC-DEFRAMER-001 | The TCDeframer shall deframe Telecommand (TC) Transfer Frames according to the CCSDS Space Data Link Protocol standard for Type-BD frames. | Unit Test, Inspection | +| SVC-CCSDS-TC-DEFRAMER-002 | The TCDeframer shall perform Frame Validation Check Procedures, including Spacecraft ID, Virtual Channel ID, Frame Length, and CRC. | Unit Test | +| SVC-CCSDS-TC-DEFRAMER-003 | The TCDeframer shall be configurable for a specific Spacecraft ID. | Unit Test, Inspection | +| SVC-CCSDS-TC-DEFRAMER-004 | The TCDeframer shall be configurable with a specific Virtual Channel ID (VCID) OR to accept all VCIDs. | Unit Test, Inspection | +| SVC-CCSDS-TC-DEFRAMER-005 | The TCDeframer shall log an `InvalidSpacecraftId` event if a frame with an unexpected Spacecraft ID is received. | Unit Test | +| SVC-CCSDS-TC-DEFRAMER-006 | The TCDeframer shall log an `InvalidFrameLength` event if a frame with an invalid length is received. | Unit Test | +| SVC-CCSDS-TC-DEFRAMER-007 | The TCDeframer shall log an `InvalidVcId` event if a frame with an unexpected VCID is received (when not configured to accept all VCIDs). | Unit Test | +| SVC-CCSDS-TC-DEFRAMER-008 | The TCDeframer shall log an `InvalidCrc` event if a frame fails the CRC check. | Unit Test | +| SVC-CCSDS-TC-DEFRAMER-009 | The TCDeframer shall provide an input port (`dataIn`) to receive framed data, and emit deframed data packets on its `dataOut` output port. | Unit Test | diff --git a/Svc/CCSDS/TMFramer/TMFramer.fpp b/Svc/CCSDS/TMFramer/TMFramer.fpp index 705a6610aa3..34bd5ed1dc0 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.fpp +++ b/Svc/CCSDS/TMFramer/TMFramer.fpp @@ -1,6 +1,6 @@ module Svc { module CCSDS { - @ Deframer for the TM Space Data Link Protocl (CCSDS Standard) + @ Deframer for the TM Space Data Link Protocol (CCSDS Standard) passive component TMFramer { include "../../Interfaces/FramerInterface.fppi" diff --git a/Svc/CCSDS/TMFramer/docs/sdd.md b/Svc/CCSDS/TMFramer/docs/sdd.md index cf1ae8dfadc..dd081daf887 100644 --- a/Svc/CCSDS/TMFramer/docs/sdd.md +++ b/Svc/CCSDS/TMFramer/docs/sdd.md @@ -25,17 +25,17 @@ The `Svc::CCSDS::TMFramer` component, as well as the rest of the CCSDS communica | Name | Description | Validation | |---|---|---| -| SVC-CCSDS-TMFRAMER-001 | The TMFramer shall implement the `Svc.FramerInterface`. | Inspection, Unit Test | -| SVC-CCSDS-TMFRAMER-002 | The TMFramer shall construct CCSDS Telemetry (TM) Transfer Frames compliant with the CCSDS 132.0-B-3 standard. | Unit Test, Inspection | -| SVC-CCSDS-TMFRAMER-002 | The TMFramer shall use a fixed frame size that is configurable by the project. | Unit Test, Inspection | -| SVC-CCSDS-TMFRAMER-003 | The TMFramer shall accept payload data (Space Packets or VCA_SDU) to be framed via its `dataIn` port. | Unit Test | -| SVC-CCSDS-TMFRAMER-004 | The TMFramer shall output the constructed TM Transfer Frame via its `dataOut` port. | Unit Test | -| SVC-CCSDS-TMFRAMER-005 | The TMFramer shall return ownership of the input buffer via the `dataReturnOut` port after the framing process is complete. | Unit Test | -| SVC-CCSDS-TMFRAMER-006 | The TMFramer shall accept returned buffers (previously sent via `dataOut`) through the `dataReturnIn` port for deallocation or reuse. | Unit Test | -| SVC-CCSDS-TMFRAMER-007 | The TMFramer shall receive communication status from downstream components via the `comStatusIn` port, and pass it through to `comStatusOut` | Unit Test, Integration Test | -| SVC-CCSDS-TMFRAMER-008 | The TMFramer shall use exactly one Virtual Channel. | Unit Test, Integration Test | -| SVC-CCSDS-TMFRAMER-009 | The TMFramer shall correctly populate all mandatory fields of the TM Transfer Frame Primary Header, including Transfer Frame Version Number, Spacecraft Identifier, Virtual Channel Identifier, Operational Control Field Flag, Master Channel Frame Count, Virtual Channel Frame Count, Transfer Frame Secondary Header Flag, Synchronization Flag, Packet Order Flag, Segment Length Identifier, and First Header Pointer. | Unit Test, Inspection | -| SVC-CCSDS-TMFRAMER-010 | The TMFramer shall be configurable with a Spacecraft Identifier. | Inspection, Unit Test | -| SVC-CCSDS-TMFRAMER-011 | The TMFramer shall use the Virtual Channel Identifier passed in the `context` object on `dataIn`. | Unit Test | -| SVC-CCSDS-TMFRAMER-012 | The TMFramer shall manage Master Channel Frame Count and Virtual Channel Frame Count. | Unit Test | -| SVC-CCSDS-TMFRAMER-013 | The TMFramer shall fill the data field of the TM Transfer Frame with the payload data received on `dataIn`, and fill up the rest of the fixed-size frame with a single Idle Packet as defined by the protocol. | Unit Test | +| SVC-CCSDS-TM-FRAMER-001 | The TMFramer shall implement the `Svc.FramerInterface`. | Inspection, Unit Test | +| SVC-CCSDS-TM-FRAMER-002 | The TMFramer shall construct CCSDS Telemetry (TM) Transfer Frames compliant with the CCSDS 132.0-B-3 standard. | Unit Test, Inspection | +| SVC-CCSDS-TM-FRAMER-002 | The TMFramer shall use a fixed frame size that is configurable by the project. | Unit Test, Inspection | +| SVC-CCSDS-TM-FRAMER-003 | The TMFramer shall accept payload data (Space Packets or VCA_SDU) to be framed via its `dataIn` port. | Unit Test | +| SVC-CCSDS-TM-FRAMER-004 | The TMFramer shall output the constructed TM Transfer Frame via its `dataOut` port. | Unit Test | +| SVC-CCSDS-TM-FRAMER-005 | The TMFramer shall return ownership of the input buffer via the `dataReturnOut` port after the framing process is complete. | Unit Test | +| SVC-CCSDS-TM-FRAMER-006 | The TMFramer shall accept returned buffers (previously sent via `dataOut`) through the `dataReturnIn` port for deallocation or reuse. | Unit Test | +| SVC-CCSDS-TM-FRAMER-007 | The TMFramer shall receive communication status from downstream components via the `comStatusIn` port, and pass it through to `comStatusOut` | Unit Test, Integration Test | +| SVC-CCSDS-TM-FRAMER-008 | The TMFramer shall use exactly one Virtual Channel. | Unit Test, Integration Test | +| SVC-CCSDS-TM-FRAMER-009 | The TMFramer shall correctly populate all mandatory fields of the TM Transfer Frame Primary Header, including Transfer Frame Version Number, Spacecraft Identifier, Virtual Channel Identifier, Operational Control Field Flag, Master Channel Frame Count, Virtual Channel Frame Count, Transfer Frame Secondary Header Flag, Synchronization Flag, Packet Order Flag, Segment Length Identifier, and First Header Pointer. | Unit Test, Inspection | +| SVC-CCSDS-TM-FRAMER-010 | The TMFramer shall be configurable with a Spacecraft Identifier. | Inspection, Unit Test | +| SVC-CCSDS-TM-FRAMER-011 | The TMFramer shall use the Virtual Channel Identifier passed in the `context` object on `dataIn`. | Unit Test | +| SVC-CCSDS-TM-FRAMER-012 | The TMFramer shall manage Master Channel Frame Count and Virtual Channel Frame Count. | Unit Test | +| SVC-CCSDS-TM-FRAMER-013 | The TMFramer shall fill the data field of the TM Transfer Frame with the payload data received on `dataIn`, and fill up the rest of the fixed-size frame with a single Idle Packet as defined by the protocol. | Unit Test | diff --git a/Svc/CCSDS/Types/Types.fpp b/Svc/CCSDS/Types/Types.fpp index 05ec98cdba0..f0b4e94b6bc 100644 --- a/Svc/CCSDS/Types/Types.fpp +++ b/Svc/CCSDS/Types/Types.fpp @@ -1,9 +1,5 @@ # ------------------------------------------------ # CCSDS protocols header and trailer types -# -# Note: FPP does not currently support bit fields, so these structs may contain fields -# that are compoed of multiple bitfields. One should mask the individual FPP types -# with the approriate mask to # ------------------------------------------------ module Svc { @@ -35,13 +31,13 @@ module CCSDS { } # ------------------------------------------------ - # TC (TeleCommand) + # TC # ------------------------------------------------ @ Describes the frame header format for a Telecommand (TC) Transfer Frame header struct TCHeader { - flagsAndScId: U16, @< 2 bits Frame V. | 1 bit bypass | 1 bit ctrl | 2 bit rsvd | 10 bits spacecraft ID + flagsAndScId: U16, @< 2 bits Frame V. | 1 bit bypass | 1 bit ctrl | 2 bit reserved | 10 bits spacecraft ID vcIdAndLength: U16, @< 6 bits Virtual Channel ID | 10 bits Frame Length - frameSequenceNbr: U8 @< 8 bits Frame Sequence Number + frameSequenceNum: U8 @< 8 bits Frame Sequence Number } @ Describes the frame trailer format for a Telecommand (TC) Transfer Frame struct TCTrailer { @@ -63,7 +59,7 @@ module CCSDS { } # ------------------------------------------------ - # TM (TeleMetry) + # TM # ------------------------------------------------ @ Describes the frame header format for a Telemetry (TM) Transfer Frame header struct TMHeader { diff --git a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp index ce9896fb3f7..7c5614d6620 100644 --- a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp +++ b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp @@ -71,7 +71,7 @@ FrameDetector::Status CcsdsTCFrameDetector::detect(const Types::CircularBuffer& Fw::ExternalSerializeBuffer trailer_ser_buffer(trailer_data, CCSDS::TCTrailer::SERIALIZED_SIZE); status = trailer_ser_buffer.setBuffLen(CCSDS::TCTrailer::SERIALIZED_SIZE); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, static_cast(status)); - // Attempt to deserialize data into the Frametrailer object + // Attempt to deserialize data into the FrameTrailer object CCSDS::TCTrailer trailer; status = trailer.deserialize(trailer_ser_buffer); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); diff --git a/default/config/ComCfg.fpp b/default/config/ComCfg.fpp index 7ffbbe18526..a7fc46cb123 100644 --- a/default/config/ComCfg.fpp +++ b/default/config/ComCfg.fpp @@ -34,7 +34,7 @@ module ComCfg { INVALID_UNINITIALIZED = 0x0800 @< Anything equal or higher value is invalid and should not be used } default INVALID_UNINITIALIZED -# TODO ???: add alias with name ComPacketDscriptor for the ComPacket.hpp +# TODO ???: add alias with name ComPacketDescriptor for the ComPacket.hpp @ Type used to pass context info between components during framing/deframing struct FrameContext { From 3820bd28645961caaa954680bb427f1f0404e3e3 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Mon, 2 Jun 2025 17:16:34 -0700 Subject: [PATCH 66/95] Remove ApidDemo component from topology --- Ref/Top/topology.fpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Ref/Top/topology.fpp b/Ref/Top/topology.fpp index ebd4a7842a9..1f96b9f194b 100644 --- a/Ref/Top/topology.fpp +++ b/Ref/Top/topology.fpp @@ -99,8 +99,6 @@ module Ref { # ---------------------------------------------------------------------- connections Downlink { - apidDemo.sendPacketDown -> comQueue.bufferQueueIn[1] - comQueue.bufferReturnOut[1] -> apidDemo.bufferReturnIn # Data Products dpCat.fileOut -> fileDownlink.SendFile fileDownlink.FileComplete -> dpCat.fileDone From 68b8e7a04c359b6d87fb25dd1d7b1ecd5d2abed4 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Mon, 2 Jun 2025 17:20:53 -0700 Subject: [PATCH 67/95] Fix more static analysis --- Svc/CCSDS/TCDeframer/TCDeframer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.cpp b/Svc/CCSDS/TCDeframer/TCDeframer.cpp index 178cacd5264..d13c12f3638 100644 --- a/Svc/CCSDS/TCDeframer/TCDeframer.cpp +++ b/Svc/CCSDS/TCDeframer/TCDeframer.cpp @@ -54,7 +54,7 @@ void TCDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const Co FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); U16 frame_length = header.getvcIdAndLength() & TCSubfields::FrameLengthMask; - U8 vc_id = (header.getvcIdAndLength() & TCSubfields::VcIdMask) >> TCSubfields::VcIdOffset; + U8 vc_id = static_cast((header.getvcIdAndLength() & TCSubfields::VcIdMask) >> TCSubfields::VcIdOffset); U16 spacecraft_id = header.getflagsAndScId() & TCSubfields::SpacecraftIdMask; if (spacecraft_id != this->m_spacecraftId) { From e42775a271d1040b2ae04f017e7a0662231500c7 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Mon, 2 Jun 2025 17:47:04 -0700 Subject: [PATCH 68/95] Clean up ApidManager tests and fix static analysis warnings --- Svc/CCSDS/ApidManager/ApidManager.cpp | 2 +- .../test/ut/ApidManagerTestMain.cpp | 45 +++---- .../ApidManager/test/ut/ApidManagerTester.cpp | 67 +++++++++-- .../ApidManager/test/ut/ApidManagerTester.hpp | 110 ++++++------------ .../FrameDetector/CcsdsTCFrameDetector.cpp | 2 +- .../CcsdsTCFrameDetectorTestMain.cpp | 2 +- 6 files changed, 119 insertions(+), 109 deletions(-) diff --git a/Svc/CCSDS/ApidManager/ApidManager.cpp b/Svc/CCSDS/ApidManager/ApidManager.cpp index 874a9342b88..8249d199685 100644 --- a/Svc/CCSDS/ApidManager/ApidManager.cpp +++ b/Svc/CCSDS/ApidManager/ApidManager.cpp @@ -36,7 +36,7 @@ U16 ApidManager ::validateApidSeqCountIn_handler(FwIndexType portNum, const ComC // Likely a packet was dropped or out of order this->log_WARNING_HI_UnexpectedSequenceCount(receivedSeqCount, expectedSequenceCount); // Synchronize onboard count with received number so that count can keep going - this->setNextSeqCount(apid, receivedSeqCount + 1); + this->setNextSeqCount(apid, static_cast(receivedSeqCount + 1)); } return receivedSeqCount; } diff --git a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTestMain.cpp b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTestMain.cpp index 41ee7e3cbba..11745853d4f 100644 --- a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTestMain.cpp +++ b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTestMain.cpp @@ -8,37 +8,40 @@ #include "STest/Scenario/BoundedScenario.hpp" #include "STest/Scenario/RandomScenario.hpp" -TEST(ApidManager, getExistingSeqCount) { +TEST(ApidManager, GetSequenceCounts) { Svc::CCSDS::ApidManagerTester tester; - Svc::CCSDS::ApidManagerTester::GetExistingSeqCount rule1; - Svc::CCSDS::ApidManagerTester::GetNewSeqCountOk rule2; - Svc::CCSDS::ApidManagerTester::GetNewSeqCountTableFull rule3; - - - rule1.apply(tester); - rule2.apply(tester); - // rule3.apply(tester); + Svc::CCSDS::ApidManagerTester::GetExistingSeqCount getExistingSeqCount; + Svc::CCSDS::ApidManagerTester::GetNewSeqCountOk getNewSeqCountOk; + getExistingSeqCount.apply(tester); + getNewSeqCountOk.apply(tester); } +TEST(ApidManager, ValidateSequenceCounts) { + Svc::CCSDS::ApidManagerTester tester; + Svc::CCSDS::ApidManagerTester::ValidateSeqCountOk validateSeqCountOkRule; + Svc::CCSDS::ApidManagerTester::ValidateSeqCountFailure validateSeqCountFailureRule; + validateSeqCountOkRule.apply(tester); + validateSeqCountFailureRule.apply(tester); +} -// Randomized sequence of conditioned take/release/lock/unlock -TEST(ApidManager, RandomizedInterfaceTesting) { +// Randomized testing +TEST(ApidManager, RandomizedTesting) { Svc::CCSDS::ApidManagerTester tester; - Svc::CCSDS::ApidManagerTester::GetExistingSeqCount rule1; - Svc::CCSDS::ApidManagerTester::GetNewSeqCountOk rule2; - Svc::CCSDS::ApidManagerTester::GetNewSeqCountTableFull rule3; - Svc::CCSDS::ApidManagerTester::ValidateSeqCountOk rule4; - Svc::CCSDS::ApidManagerTester::ValidateSeqCountFailure rule5; + Svc::CCSDS::ApidManagerTester::GetExistingSeqCount getExistingSeqCountRule; + Svc::CCSDS::ApidManagerTester::GetNewSeqCountOk getNewSeqCountOkRule; + Svc::CCSDS::ApidManagerTester::GetNewSeqCountTableFull getNewSeqCountTableFullRule; + Svc::CCSDS::ApidManagerTester::ValidateSeqCountOk validateSeqCountOkRule; + Svc::CCSDS::ApidManagerTester::ValidateSeqCountFailure validateSeqCountFailureRule; // Place these rules into a list of rules STest::Rule* rules[] = { - &rule1, - &rule2, - &rule3, - &rule4, - &rule5 + &getExistingSeqCountRule, + &getNewSeqCountOkRule, + &getNewSeqCountTableFullRule, + &validateSeqCountOkRule, + &validateSeqCountFailureRule }; // Take the rules and place them into a random scenario diff --git a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp index fe326e543c3..e4f76d4b406 100644 --- a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp +++ b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp @@ -39,17 +39,13 @@ ApidManagerTester ::~ApidManagerTester() {} // Tests // ---------------------------------------------------------------------- -// void ApidManagerTester ::toDo() { -// // TODO -// } - bool ApidManagerTester::GetExistingSeqCount::precondition(const ApidManagerTester& testerState) { return true; // Can always get existing sequence count } void ApidManagerTester::GetExistingSeqCount::action(ApidManagerTester& testerState) { testerState.clearHistory(); - ComCfg::APID::T apid = testerState.getRandomTrackedApid(); + ComCfg::APID::T apid = testerState.shadow_getRandomTrackedApid(); U16 seqCount = testerState.invoke_to_getApidSeqCountIn(0, apid, 0); U16 shadowSeqCount = testerState.shadow_getAndIncrementSeqCount(apid); ASSERT_EQ(seqCount, shadowSeqCount) @@ -72,7 +68,7 @@ void ApidManagerTester::GetNewSeqCountOk::action(ApidManagerTester& testerState) return; // Cannot get new sequence count if table is full - skip action } - ComCfg::APID::T apid = testerState.getRandomUntrackedApid(); + ComCfg::APID::T apid = testerState.shadow_getRandomUntrackedApid(); U16 seqCount = testerState.invoke_to_getApidSeqCountIn(0, apid, 0); U16 shadowSeqCount = testerState.shadow_getAndIncrementSeqCount(apid); ASSERT_EQ(seqCount, shadowSeqCount) @@ -86,7 +82,7 @@ bool ApidManagerTester::GetNewSeqCountTableFull::precondition(const ApidManagerT void ApidManagerTester::GetNewSeqCountTableFull::action(ApidManagerTester& testerState) { testerState.clearHistory(); - ComCfg::APID::T apid = testerState.getRandomUntrackedApid(); + ComCfg::APID::T apid = testerState.shadow_getRandomUntrackedApid(); U16 seqCount = testerState.invoke_to_getApidSeqCountIn(0, apid, 0); // Use local constexpr to potentially avoid ODR-use of ApidManager::SEQUENCE_COUNT_ERROR constexpr U16 sequenceCountErrorVal = ApidManager::SEQUENCE_COUNT_ERROR; @@ -103,7 +99,7 @@ bool ApidManagerTester::ValidateSeqCountOk::precondition(const ApidManagerTester void ApidManagerTester::ValidateSeqCountOk::action(ApidManagerTester& testerState) { testerState.clearHistory(); - ComCfg::APID::T apid = testerState.getRandomTrackedApid(); + ComCfg::APID::T apid = testerState.shadow_getRandomTrackedApid(); U16 shadow_expectedSeqCount = testerState.shadow_seqCounts[apid]; testerState.invoke_to_validateApidSeqCountIn(0, apid, shadow_expectedSeqCount); testerState.shadow_validateApidSeqCount(apid, shadow_expectedSeqCount); // keep shadow state in sync @@ -117,9 +113,9 @@ bool ApidManagerTester::ValidateSeqCountFailure::precondition(const ApidManagerT void ApidManagerTester::ValidateSeqCountFailure::action(ApidManagerTester& testerState) { testerState.clearHistory(); - ComCfg::APID::T apid = testerState.getRandomTrackedApid(); + ComCfg::APID::T apid = testerState.shadow_getRandomTrackedApid(); U16 shadow_expectedSeqCount = testerState.shadow_seqCounts.at(apid); - U16 invalidSeqCount = (shadow_expectedSeqCount + 1) % (1 << 14); // Or any other value that's different, ensure wrap around + U16 invalidSeqCount = static_cast((shadow_expectedSeqCount + 1) % (1 << 14)); // Or any other value that's different, ensure wrap around // Invoke the port with the deliberately incorrect sequence count testerState.invoke_to_validateApidSeqCountIn(0, apid, invalidSeqCount); @@ -131,5 +127,52 @@ void ApidManagerTester::ValidateSeqCountFailure::action(ApidManagerTester& teste } -}; // namespace CCSDS -}; // namespace Svc +// ---------------------------------------------------------------------- +// Helpers +// ---------------------------------------------------------------------- + +U16 ApidManagerTester::shadow_getAndIncrementSeqCount(ComCfg::APID::T apid) { + // This is a shadow function to simulate the getAndIncrementSeqCount behavior + // without modifying the actual component state. + auto found = this->shadow_seqCounts.find(apid); + if (found != this->shadow_seqCounts.end()) { + U16 seqCount = found->second; + found->second = static_cast((seqCount + 1) % (1 << 14)); // Increment for next call + return seqCount; // Return the current sequence count + } + // If APID not found, initialize a new entry + if (this->shadow_seqCounts.size() < this->component.MAX_TRACKED_APIDS) { + U16 seqCount = 0; + this->shadow_seqCounts[apid] = static_cast(seqCount + 1); // increment for next call + return seqCount; // Return the initialized sequence count + } + return this->component.SEQUENCE_COUNT_ERROR; // Return error if APID not found +} + +void ApidManagerTester::shadow_validateApidSeqCount(ComCfg::APID::T apid, U16 expectedSeqCount) { + // This simply updates the shadow state to the next expected sequence count + auto found = this->shadow_seqCounts.find(apid); + if (found != this->shadow_seqCounts.end()) { + found->second = static_cast((expectedSeqCount + 1) % (1 << 14)); + } +} + +ComCfg::APID::T ApidManagerTester::shadow_getRandomTrackedApid() { + // Select a random APID from the sequence counts map + U32 mapSize = static_cast(this->shadow_seqCounts.size()); + U32 randomIndex = STest::Random::lowerUpper(0, mapSize - 1); + ComCfg::APID apid = std::next(this->shadow_seqCounts.begin(), randomIndex)->first; + return apid; +} + +ComCfg::APID::T ApidManagerTester::shadow_getRandomUntrackedApid() { + // Select a random APID that is not currently tracked + ComCfg::APID::T apid; + do { + apid = static_cast(STest::Random::lowerUpper(10, ComCfg::APID::SPP_IDLE_PACKET)); + } while (this->shadow_seqCounts.find(apid) != this->shadow_seqCounts.end()); + return apid; +} + +} // namespace CCSDS +} // namespace Svc diff --git a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.hpp b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.hpp index 3002c152fad..127b00173d5 100644 --- a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.hpp +++ b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.hpp @@ -7,19 +7,17 @@ #ifndef Svc_CCSDS_ApidManagerTester_HPP #define Svc_CCSDS_ApidManagerTester_HPP +#include "STest/Random/Random.hpp" +#include "STest/Rule/Rule.hpp" #include "Svc/CCSDS/ApidManager/ApidManager.hpp" #include "Svc/CCSDS/ApidManager/ApidManagerGTestBase.hpp" -#include "STest/Rule/Rule.hpp" -#include "STest/Random/Random.hpp" namespace Svc { namespace CCSDS { class ApidManagerTester : public ApidManagerGTestBase { - public: - // ---------------------------------------------------------------------- // Constants // ---------------------------------------------------------------------- @@ -41,14 +39,6 @@ class ApidManagerTester : public ApidManagerGTestBase { //! Destroy object ApidManagerTester ~ApidManagerTester(); - public: - // ---------------------------------------------------------------------- - // Tests - // ---------------------------------------------------------------------- - - //! To do - void toDo(); - private: // ---------------------------------------------------------------------- // Helper functions @@ -68,83 +58,57 @@ class ApidManagerTester : public ApidManagerGTestBase { //! The component under test ApidManager component; - std::map shadow_seqCounts; //!< Map to hold existing sequence counts for APIDs + // Shadow test state + std::map shadow_seqCounts; //!< Map to hold expected sequence counts for APIDs bool shadow_isTableFull = false; - U16 shadow_getAndIncrementSeqCount(ComCfg::APID::T apid) { - // This is a shadow function to simulate the getAndIncrementSeqCount behavior - // without modifying the actual component state. - auto found = this->shadow_seqCounts.find(apid); - if (found != this->shadow_seqCounts.end()) { - U16 seqCount = found->second; - found->second = (seqCount + 1) % (1 << 14); // Increment for next call - return seqCount; // Return the current sequence count - } - // If APID not found, initialize a new entry - if (this->shadow_seqCounts.size() < this->component.MAX_TRACKED_APIDS) { - U16 seqCount = 0; - this->shadow_seqCounts[apid] = seqCount + 1; // increment for next call - return seqCount; // Return the initialized sequence count - } - return this->component.SEQUENCE_COUNT_ERROR; // Return error if APID not found - } - - void shadow_validateApidSeqCount(ComCfg::APID::T apid, U16 expectedSeqCount) { - // This simply updates the shadow state to the next expected sequence count - auto found = this->shadow_seqCounts.find(apid); - if (found != this->shadow_seqCounts.end()) { - found->second = (expectedSeqCount + 1) % (1 << 14); - } - } - - ComCfg::APID::T getRandomTrackedApid() { - // Select a random APID from the sequence counts map - U32 mapSize = static_cast(this->shadow_seqCounts.size()); - U32 randomIndex = STest::Random::lowerUpper(0, mapSize - 1); - ComCfg::APID apid = std::next(this->shadow_seqCounts.begin(), randomIndex)->first; - return apid; - } - - ComCfg::APID::T getRandomUntrackedApid() { - // Select a random APID that is not currently tracked - ComCfg::APID::T apid; - do { - apid = static_cast(STest::Random::lowerUpper(10, ComCfg::APID::SPP_IDLE_PACKET)); - } while (this->shadow_seqCounts.find(apid) != this->shadow_seqCounts.end()); - return apid; - } + // ---------------------------------------------------------------------- + // Helpers for tracking the shadow test state + // ---------------------------------------------------------------------- + + U16 shadow_getAndIncrementSeqCount(ComCfg::APID::T apid); + + void shadow_validateApidSeqCount(ComCfg::APID::T apid, U16 expectedSeqCount); + + ComCfg::APID::T shadow_getRandomTrackedApid(); + + ComCfg::APID::T shadow_getRandomUntrackedApid(); + + // ---------------------------------------------------------------------- + // Tests: Rule Based Testing + // ---------------------------------------------------------------------- public: struct GetExistingSeqCount : public STest::Rule { - GetExistingSeqCount(): STest::Rule("GetExistingSeqCount") {}; - bool precondition(const ApidManagerTester &state); - void action(ApidManagerTester &state); + GetExistingSeqCount() : STest::Rule("GetExistingSeqCount") {}; + bool precondition(const ApidManagerTester& state); + void action(ApidManagerTester& state); }; - + struct GetNewSeqCountOk : public STest::Rule { - GetNewSeqCountOk(): STest::Rule("GetNewSeqCountOk") {}; - bool precondition(const ApidManagerTester &state); - void action(ApidManagerTester &state); + GetNewSeqCountOk() : STest::Rule("GetNewSeqCountOk") {}; + bool precondition(const ApidManagerTester& state); + void action(ApidManagerTester& state); }; - + struct GetNewSeqCountTableFull : public STest::Rule { - GetNewSeqCountTableFull(): STest::Rule("GetNewSeqCountTableFull") {}; - bool precondition(const ApidManagerTester &state); - void action(ApidManagerTester &state); + GetNewSeqCountTableFull() : STest::Rule("GetNewSeqCountTableFull") {}; + bool precondition(const ApidManagerTester& state); + void action(ApidManagerTester& state); }; struct ValidateSeqCountOk : public STest::Rule { - ValidateSeqCountOk(): STest::Rule("ValidateSeqCountOk") {}; - bool precondition(const ApidManagerTester &state); - void action(ApidManagerTester &state); + ValidateSeqCountOk() : STest::Rule("ValidateSeqCountOk") {}; + bool precondition(const ApidManagerTester& state); + void action(ApidManagerTester& state); }; struct ValidateSeqCountFailure : public STest::Rule { - ValidateSeqCountFailure(): STest::Rule("ValidateSeqCountFailure") {}; - bool precondition(const ApidManagerTester &state); - void action(ApidManagerTester &state); + ValidateSeqCountFailure() : STest::Rule("ValidateSeqCountFailure") {}; + bool precondition(const ApidManagerTester& state); + void action(ApidManagerTester& state); }; - }; +}; } // namespace CCSDS diff --git a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp index 7c5614d6620..a320f2823a0 100644 --- a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp +++ b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp @@ -45,7 +45,7 @@ FrameDetector::Status CcsdsTCFrameDetector::detect(const Types::CircularBuffer& const U16 frame_data_length = header.getvcIdAndLength() & CCSDS::TCSubfields::FrameLengthMask; const FwSizeType expected_frame_length = frame_data_length + CCSDS::TCHeader::SERIALIZED_SIZE + CCSDS::TCTrailer::SERIALIZED_SIZE; - const U16 data_to_crc_length = frame_data_length + CCSDS::TCHeader::SERIALIZED_SIZE; + const U16 data_to_crc_length = static_cast(frame_data_length + CCSDS::TCHeader::SERIALIZED_SIZE); if (data.get_allocated_size() < expected_frame_length) { size_out = expected_frame_length; diff --git a/Svc/FrameAccumulator/test/ut/detectors/CcsdsTCFrameDetectorTestMain.cpp b/Svc/FrameAccumulator/test/ut/detectors/CcsdsTCFrameDetectorTestMain.cpp index 06ab80be6f9..71022304984 100644 --- a/Svc/FrameAccumulator/test/ut/detectors/CcsdsTCFrameDetectorTestMain.cpp +++ b/Svc/FrameAccumulator/test/ut/detectors/CcsdsTCFrameDetectorTestMain.cpp @@ -69,7 +69,7 @@ FwSizeType generate_random_tc_frame(Types::CircularBuffer& circular_buffer) { // Calculate CRC on header + packet_data Svc::CCSDS::Utils::CRC16 crc; - for (FwSizeType i = 0; i < packet_size + TCHeader::SERIALIZED_SIZE; ++i) { + for (FwSizeType i = 0; i < static_cast(packet_size + TCHeader::SERIALIZED_SIZE); ++i) { U8 byte = 0; circular_buffer.peek(byte, i); crc.update(byte); From a2c9325f0d59a9ede385d9f4331b5d0bb912eacd Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Mon, 2 Jun 2025 18:24:26 -0700 Subject: [PATCH 69/95] Fix UTs on RHEL8 --- .../test/ut/SpacePacketDeframerTester.cpp | 2 +- .../TCDeframer/test/ut/TCDeframerTestMain.cpp | 5 --- .../TCDeframer/test/ut/TCDeframerTester.cpp | 40 +++++-------------- .../TCDeframer/test/ut/TCDeframerTester.hpp | 1 - Svc/CCSDS/TMFramer/TMFramer.cpp | 31 +++++++------- Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp | 2 +- 6 files changed, 25 insertions(+), 56 deletions(-) diff --git a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp index c717fb9782d..9a15a63e850 100644 --- a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp +++ b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp @@ -70,7 +70,7 @@ void SpacePacketDeframerTester ::testDeframingIncorrectLength() { ComCfg::APID::T apid = static_cast(STest::Random::lowerUpper(0, 0x7FF)); // random 11 bit APID U16 seqCount = static_cast(STest::Random::lowerUpper(0, 0x3FFF)); // random 14 bit sequence count U16 realDataLength = static_cast(STest::Random::lowerUpper(1, MAX_TEST_PACKET_DATA_SIZE)); // bytes of data, random length - U16 invalidLengthToken = realDataLength + 1; // Length token is greater than actual data available + U16 invalidLengthToken = static_cast(realDataLength + 1); // Length token is greater than actual data available U8 data[realDataLength]; Fw::Buffer buffer = this->assemblePacket(apid, seqCount, invalidLengthToken, data, realDataLength); diff --git a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTestMain.cpp b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTestMain.cpp index 84cabd71ae1..6d5bbb2b5ab 100644 --- a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTestMain.cpp +++ b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTestMain.cpp @@ -31,11 +31,6 @@ TEST(TCDeframer, testInvalidLengthToken) { tester.testInvalidLengthToken(); } -// TEST(TCDeframer, testInvalidSequenceNumber) { -// Svc::CCSDS::TCDeframerTester tester; -// tester.testInvalidSequenceNumber(); -// } - TEST(TCDeframer, testInvalidCrc) { Svc::CCSDS::TCDeframerTester tester; tester.testInvalidCrc(); diff --git a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp index 0515fd498a0..5e6459818ae 100644 --- a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp +++ b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp @@ -70,7 +70,7 @@ void TCDeframerTester::testInvalidScId() { U8 data[dataLength]; // Assemble frame with incorrect scId value - Fw::Buffer buffer = this->assembleFrameBuffer(data, dataLength, scId - 1); + Fw::Buffer buffer = this->assembleFrameBuffer(data, dataLength, static_cast(scId - 1)); ComCfg::FrameContext nullContext; this->setComponentState(scId); @@ -82,7 +82,7 @@ void TCDeframerTester::testInvalidScId() { ASSERT_EQ(this->fromPortHistory_dataReturnOut->at(0).data.getSize(), buffer.getSize()); ASSERT_EVENTS_SIZE(1); // exactly 1 event emitted ASSERT_EVENTS_InvalidSpacecraftId_SIZE(1); // event was emitted for invalid spacecraft ID - ASSERT_EVENTS_InvalidSpacecraftId(0, scId - 1, scId); // event was emitted for invalid spacecraft ID + ASSERT_EVENTS_InvalidSpacecraftId(0, static_cast(scId - 1), scId); // event was emitted for invalid spacecraft ID } @@ -92,7 +92,7 @@ void TCDeframerTester::testInvalidVcId() { U8 data[dataLength]; // Assemble frame with incorrect vcId value - Fw::Buffer buffer = this->assembleFrameBuffer(data, dataLength, 0, vcId - 1); + Fw::Buffer buffer = this->assembleFrameBuffer(data, dataLength, 0, static_cast(vcId - 1)); ComCfg::FrameContext nullContext; this->setComponentState(0, vcId, 0, false); // set the component in mode where only one VCID is accepted @@ -104,7 +104,7 @@ void TCDeframerTester::testInvalidVcId() { ASSERT_EQ(this->fromPortHistory_dataReturnOut->at(0).data.getSize(), buffer.getSize()); ASSERT_EVENTS_SIZE(1); // exactly 1 event emitted ASSERT_EVENTS_InvalidVcId_SIZE(1); // event was emitted for invalid VCID - ASSERT_EVENTS_InvalidVcId(0, vcId - 1, vcId); // event was emitted for invalid VCID + ASSERT_EVENTS_InvalidVcId(0, static_cast(vcId - 1), vcId); // event was emitted for invalid VCID } void TCDeframerTester::testInvalidLengthToken() { @@ -128,28 +128,6 @@ void TCDeframerTester::testInvalidLengthToken() { ASSERT_EVENTS_InvalidFrameLength(0, fakeLength, dataLength); } -// void TCDeframerTester::testInvalidSequenceNumber() { -// U8 dataLength = static_cast(STest::Random::lowerUpper(1, 200)); // bytes of data, random length -// U8 data[dataLength]; -// U8 expectedSeqCount = static_cast(STest::Random::lowerUpper(1, 0xFF)); // random 8 bit sequence count -// U8 invalidSeqCount = expectedSeqCount - 1; // invalid sequence count - -// Fw::Buffer buffer = this->assembleFrameBuffer(data, dataLength, 0, 0, invalidSeqCount); -// ComCfg::FrameContext nullContext; - -// this->setComponentState(0, 0, expectedSeqCount); -// this->invoke_to_dataIn(0, buffer, nullContext); - -// // Invalid sequence number should emit a warning but deframe data (not dropping the frame) -// ASSERT_from_dataOut_SIZE(1); -// ASSERT_from_dataReturnOut_SIZE(0); -// ASSERT_EQ(this->fromPortHistory_dataOut->at(0).data.getData(), buffer.getData()); -// ASSERT_EQ(this->fromPortHistory_dataOut->at(0).data.getSize(), dataLength); -// ASSERT_EVENTS_SIZE(1); // exactly 1 event emitted -// ASSERT_EVENTS_UnexpectedSequenceNumber_SIZE(1); -// ASSERT_EVENTS_UnexpectedSequenceNumber(0, invalidSeqCount, expectedSeqCount); -// } - void TCDeframerTester::testInvalidCrc() { U8 dataLength = static_cast(STest::Random::lowerUpper(1, 200)); // bytes of data, random length U8 data[dataLength]; @@ -180,11 +158,11 @@ void TCDeframerTester::setComponentState(U16 scid, U8 vcid, U8 sequenceNumber, b Fw::Buffer TCDeframerTester::assembleFrameBuffer(U8* data, U8 dataLength, U16 scid, U8 vcid, U8 seqNumber){ ::memset(this->m_frameData, 0, sizeof(this->m_frameData)); - U16 frameLength = TCHeader::SERIALIZED_SIZE + dataLength + TCTrailer::SERIALIZED_SIZE; + U16 frameLength = static_cast(TCHeader::SERIALIZED_SIZE + dataLength + TCTrailer::SERIALIZED_SIZE); // Header - this->m_frameData[0] = scid >> 8; - this->m_frameData[1] = scid & 0xFF; + this->m_frameData[0] = static_cast(scid >> 8); + this->m_frameData[1] = static_cast(scid & 0xFF); this->m_frameData[2] = static_cast((vcid << 2) | static_cast((dataLength >> 8) & 0x03)); this->m_frameData[3] = dataLength & 0xFF; this->m_frameData[4] = seqNumber; @@ -194,8 +172,8 @@ Fw::Buffer TCDeframerTester::assembleFrameBuffer(U8* data, U8 dataLength, U16 sc // CRC trailer U16 crc = CCSDS::Utils::CRC16::compute(this->m_frameData, TCHeader::SERIALIZED_SIZE + dataLength); - this->m_frameData[TCHeader::SERIALIZED_SIZE + dataLength] = crc >> 8; - this->m_frameData[TCHeader::SERIALIZED_SIZE + dataLength + 1] = crc & 0xFF; + this->m_frameData[TCHeader::SERIALIZED_SIZE + dataLength] = static_cast(crc >> 8); + this->m_frameData[TCHeader::SERIALIZED_SIZE + dataLength + 1] = static_cast(crc & 0xFF); return Fw::Buffer(this->m_frameData, frameLength); } diff --git a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.hpp b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.hpp index bb54d34ebdc..1358e15adba 100644 --- a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.hpp +++ b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.hpp @@ -47,7 +47,6 @@ class TCDeframerTester final : public TCDeframerGTestBase { void testInvalidScId(); void testInvalidVcId(); void testInvalidLengthToken(); - // void testInvalidSequenceNumber(); void testInvalidCrc(); diff --git a/Svc/CCSDS/TMFramer/TMFramer.cpp b/Svc/CCSDS/TMFramer/TMFramer.cpp index e50b365a5b9..aec85625955 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.cpp +++ b/Svc/CCSDS/TMFramer/TMFramer.cpp @@ -6,11 +6,11 @@ #include "Svc/CCSDS/TMFramer/TMFramer.hpp" #include "Svc/CCSDS/Types/FppConstantsAc.hpp" +#include "Svc/CCSDS/Types/SpacePacketHeaderSerializableAc.hpp" #include "Svc/CCSDS/Types/TMHeaderSerializableAc.hpp" #include "Svc/CCSDS/Types/TMTrailerSerializableAc.hpp" #include "Svc/CCSDS/Utils/CRC16.hpp" #include "config/FppConstantsAc.hpp" -#include "Svc/CCSDS/Types/SpacePacketHeaderSerializableAc.hpp" namespace Svc { @@ -39,9 +39,9 @@ void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComC // ----------------------------------------------- TMHeader header; - U16 globalVcId = 0; - globalVcId |= ComCfg::SpacecraftId << TMSubfields::spacecraftIdOffset; - globalVcId |= static_cast(context.getvcId() << TMSubfields::virtualChannelIdOffset); + // GVCID (Global Virtual Channel ID) (Standard 4.1.2.2 and 4.1.2.3) + U16 globalVcId = static_cast(context.getvcId() << TMSubfields::virtualChannelIdOffset); + globalVcId |= static_cast(ComCfg::SpacecraftId << TMSubfields::spacecraftIdOffset); globalVcId |= 0x0; // Operational Control Field: Flag set to 0 (Standard 4.1.2.4) // Data Field Status (Standard 4.1.2.7): @@ -80,13 +80,12 @@ void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComC // ------------------------------------------------- TMTrailer trailer; // Compute CRC over the entire frame buffer minus the FECF trailer (Standard 4.1.6) - U16 crc = CCSDS::Utils::CRC16::compute(frameBuffer.getData(), - sizeof(this->m_frameBuffer) - TMTrailer::SERIALIZED_SIZE); + U16 crc = + CCSDS::Utils::CRC16::compute(frameBuffer.getData(), sizeof(this->m_frameBuffer) - TMTrailer::SERIALIZED_SIZE); // Set the Frame Error Control Field (FECF) trailer.setfecf(crc); // Move the serializer pointer to the end of the location where the trailer will be serialized - frameSerializer.moveSerToOffset(ComCfg::TmFrameFixedSize - - TMTrailer::SERIALIZED_SIZE); + frameSerializer.moveSerToOffset(ComCfg::TmFrameFixedSize - TMTrailer::SERIALIZED_SIZE); status = frameSerializer.serialize(trailer); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); @@ -111,28 +110,26 @@ void TMFramer ::dataReturnIn_handler(FwIndexType portNum, } void TMFramer ::fill_with_idle_packet(Fw::SerializeBufferBase& serializer) { - constexpr U16 endIndex = ComCfg::TmFrameFixedSize - - TMTrailer::SERIALIZED_SIZE; + constexpr U16 endIndex = ComCfg::TmFrameFixedSize - TMTrailer::SERIALIZED_SIZE; constexpr U16 idleApid = static_cast(ComCfg::APID::SPP_IDLE_PACKET); const U16 startIndex = static_cast(serializer.getBuffLength()); - const U16 idlePacketLength = endIndex - startIndex; + const U16 idlePacketLength = static_cast(endIndex - startIndex); FW_ASSERT(idlePacketLength > 0, static_cast(idlePacketLength)); - FW_ASSERT(idlePacketLength >= 7, static_cast(idlePacketLength)); // 7 bytes minimum for idle packet - FW_ASSERT(idlePacketLength <= ComCfg::TmFrameFixedSize, - static_cast(idlePacketLength)); + FW_ASSERT(idlePacketLength >= 7, static_cast(idlePacketLength)); // 7 bytes minimum for idle packet + FW_ASSERT(idlePacketLength <= ComCfg::TmFrameFixedSize, static_cast(idlePacketLength)); SpacePacketHeader header; header.setpacketIdentification(idleApid); - header.setpacketSequenceControl(0x3 << SpacePacketSubfields::SeqFlagsOffset); // Sequence Flags = 0b11 (unsegmented) & unused Seq count + header.setpacketSequenceControl( + 0x3 << SpacePacketSubfields::SeqFlagsOffset); // Sequence Flags = 0b11 (unsegmented) & unused Seq count header.setpacketDataLength(idlePacketLength); // Serialize header and idle data into the frame serializer.serialize(header); - for (U16 i = startIndex + SpacePacketHeader::SERIALIZED_SIZE; i < endIndex; i++) { + for (U16 i = static_cast(startIndex + SpacePacketHeader::SERIALIZED_SIZE); i < endIndex; i++) { serializer.serialize(IDLE_DATA_PATTERN); // Idle data } } - } // namespace CCSDS } // namespace Svc diff --git a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp index 1585a94b1a3..c076bd229f8 100644 --- a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp +++ b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp @@ -140,7 +140,7 @@ U16 TMFramerTester::getFrameScId(U8* frameData) { return static_cast((frameData[0] & 0x3F) << 4 | (frameData[1] >> 4)); } U8 TMFramerTester::getFrameVcId(U8* frameData) { - return (frameData[1] & 0x0E) >> 1; + return static_cast((frameData[1] & 0x0E) >> 1); } U8 TMFramerTester::getFrameMcCount(U8* frameData) { return frameData[2]; From 285676ef9d2543d6dcb5fad2d7b661a89a242f91 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Tue, 3 Jun 2025 10:28:52 -0700 Subject: [PATCH 70/95] Fix SDD links --- Svc/CCSDS/SpacePacketDeframer/docs/sdd.md | 2 +- Svc/CCSDS/SpacePacketFramer/docs/sdd.md | 2 +- Svc/CCSDS/TCDeframer/docs/sdd.md | 4 ++-- Svc/CCSDS/TMFramer/docs/sdd.md | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Svc/CCSDS/SpacePacketDeframer/docs/sdd.md b/Svc/CCSDS/SpacePacketDeframer/docs/sdd.md index a27a36cfd24..ff4df93b23b 100644 --- a/Svc/CCSDS/SpacePacketDeframer/docs/sdd.md +++ b/Svc/CCSDS/SpacePacketDeframer/docs/sdd.md @@ -1,6 +1,6 @@ # Svc::CCSDS::SpacePacketDeframer -The `Svc::CCSDS::SpacePacketDeframer` is an implementation of the [DeframerInterface](../../Interfaces/docs/sdd.md) for the CCSDS [Space Packet Protocol](https://ccsds.org/Pubs/133x0b2e2.pdf). +The `Svc::CCSDS::SpacePacketDeframer` is an implementation of the [DeframerInterface](../../../Interfaces/docs/sdd.md) for the CCSDS [Space Packet Protocol](https://ccsds.org/Pubs/133x0b2e2.pdf). It receives data containing a Space Packet on its input port and extracts the Space Packet. Please refer to the CCSDS [Space Packet Protocol specification (CCSDS 133.0-B-2)](https://ccsds.org/Pubs/133x0b2e2.pdf) for details on the packet format. diff --git a/Svc/CCSDS/SpacePacketFramer/docs/sdd.md b/Svc/CCSDS/SpacePacketFramer/docs/sdd.md index 1005ed8ad3f..d817c3b8020 100644 --- a/Svc/CCSDS/SpacePacketFramer/docs/sdd.md +++ b/Svc/CCSDS/SpacePacketFramer/docs/sdd.md @@ -1,6 +1,6 @@ # Svc::CCSDS::SpacePacketFramer -The `Svc::CCSDS::SpacePacketFramer` is an implementation of the [FramerInterface](../../Interfaces/docs/sdd.md) for the CCSDS [Space Packet Protocol](https://public.ccsds.org/Pubs/133x0b2e1.pdf). +The `Svc::CCSDS::SpacePacketFramer` is an implementation of the [FramerInterface](../../../Interfaces/docs/sdd.md) for the CCSDS [Space Packet Protocol](https://public.ccsds.org/Pubs/133x0b2e1.pdf). It receives user data on its input port and constructs a CCSDS Space Packet. Please refer to the CCSDS [Space Packet Protocol specification (CCSDS 133.0-B-2)](https://public.ccsds.org/Pubs/133x0b2e1.pdf) for details on the packet format. diff --git a/Svc/CCSDS/TCDeframer/docs/sdd.md b/Svc/CCSDS/TCDeframer/docs/sdd.md index c4050063ce6..62633ef77e1 100644 --- a/Svc/CCSDS/TCDeframer/docs/sdd.md +++ b/Svc/CCSDS/TCDeframer/docs/sdd.md @@ -1,10 +1,10 @@ # Svc::TCDeframer -The `Svc::CCSDS::TCDeframer` is an implementation of the [DeframerInterface](../../Interfaces/docs/sdd.md) for the CCSDS [TC Space Data Link Protocol](https://ccsds.org/Pubs/232x0b4e1c1.pdf). +The `Svc::CCSDS::TCDeframer` is an implementation of the [DeframerInterface](../../../Interfaces/docs/sdd.md) for the CCSDS [TC Space Data Link Protocol](https://ccsds.org/Pubs/232x0b4e1c1.pdf). It receives payload data (such as a Space Packet or a VCA_SDU) on input and produces a TC frame on its output port as a result. Please refer to the CCSDS [TC specification (CCSDS 232.0-B-4)](https://ccsds.org/Pubs/232x0b4e1c1.pdf) for details on the frame format and protocol. -The `Svc::CCSDS::TCDeframer` is designed to work in the common F Prime telemetry stack, receiving data from an upstream [`Svc::ComQueue`](../../../ComQueue/docs/sdd.md) and passing frames to a [Communications Adapter](../../Interfaces/docs/sdd.md), such as a Radio manager component or [`Svc::ComStub`](../../ComStub/docs/sdd.md), for transmission on the wire. It is commonly coupled with the [`Svc::CCSDS::SpacePacketFramer`](../../SpacePacketFramer/docs/sdd.md) to wrap CCSDS Space Packets into TM frames. +The `Svc::CCSDS::TCDeframer` is designed to work in the common F Prime telemetry stack, receiving data from an upstream [`Svc::ComQueue`](../../../ComQueue/docs/sdd.md) and passing frames to a [Communications Adapter](../../../Interfaces/docs/sdd.md), such as a Radio manager component or [`Svc::ComStub`](../../../ComStub/docs/sdd.md), for transmission on the wire. It is commonly coupled with the [`Svc::CCSDS::SpacePacketFramer`](../../SpacePacketFramer/docs/sdd.md) to wrap CCSDS Space Packets into TM frames. The TCDeframer currently functions only in the "Expedited Service" mode, for Type-B Frames. This means that should Type-A frames be received, no FARM checks would be performed on board. diff --git a/Svc/CCSDS/TMFramer/docs/sdd.md b/Svc/CCSDS/TMFramer/docs/sdd.md index dd081daf887..0ab2b825936 100644 --- a/Svc/CCSDS/TMFramer/docs/sdd.md +++ b/Svc/CCSDS/TMFramer/docs/sdd.md @@ -1,10 +1,10 @@ # Svc::CCSDS::TMFramer -The `Svc::CCSDS::TMFramer` is an implementation of the [FramerInterface](../../Interfaces/docs/sdd.md) for the CCSDS [TM Space Data Link Protocol](https://ccsds.org/Pubs/132x0b3.pdf). +The `Svc::CCSDS::TMFramer` is an implementation of the [FramerInterface](../../../Interfaces/docs/sdd.md) for the CCSDS [TM Space Data Link Protocol](https://ccsds.org/Pubs/132x0b3.pdf). It receives payload data (such as a Space Packet or a VCA_SDU) on input and produces a TM frame on its output port as a result. Please refer to the CCSDS [TM specification (CCSDS 132.0-B-3)](https://ccsds.org/Pubs/132x0b3.pdf) for details on the frame format and protocol. -The `Svc::CCSDS::TMFramer` is designed to work in the common F Prime telemetry stack, receiving data from an upstream [`Svc::ComQueue`](../../../ComQueue/docs/sdd.md) and passing frames to a [Communications Adapter](../../Interfaces/docs/sdd.md), such as a Radio manager component or [`Svc::ComStub`](../../ComStub/docs/sdd.md), for transmission on the wire. It is commonly coupled with the [`Svc::CCSDS::SpacePacketFramer`](../../SpacePacketFramer/docs/sdd.md) to wrap CCSDS Space Packets into TM frames. +The `Svc::CCSDS::TMFramer` is designed to work in the common F Prime telemetry stack, receiving data from an upstream [`Svc::ComQueue`](../../../ComQueue/docs/sdd.md) and passing frames to a [Communications Adapter](../../../Interfaces/docs/sdd.md), such as a Radio manager component or [`Svc::ComStub`](../../../ComStub/docs/sdd.md), for transmission on the wire. It is commonly coupled with the [`Svc::CCSDS::SpacePacketFramer`](../../SpacePacketFramer/docs/sdd.md) to wrap CCSDS Space Packets into TM frames. ## Usage Examples From 30da194adae68f44b85375db208458da0d99b6c9 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Tue, 3 Jun 2025 11:18:56 -0700 Subject: [PATCH 71/95] Fix more static analysis on UTs --- .../test/ut/SpacePacketDeframerTester.cpp | 5 ++++- .../test/ut/SpacePacketDeframerTester.hpp | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp index 9a15a63e850..71abf42a994 100644 --- a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp +++ b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp @@ -45,6 +45,9 @@ void SpacePacketDeframerTester ::testNominalDeframing() { U16 seqCount = static_cast(STest::Random::lowerUpper(0, 0x3FFF)); // random 14 bit sequence count U16 dataLength = static_cast(STest::Random::lowerUpper(1, MAX_TEST_PACKET_DATA_SIZE)); // bytes of data, random length U8 data[dataLength]; + for (FwIndexType i = 0; i < static_cast(dataLength); ++i) { + data[i] = static_cast(i); + } Fw::Buffer buffer = this->assemblePacket(apid, seqCount, dataLength, data, dataLength); ComCfg::FrameContext nullContext; @@ -54,7 +57,7 @@ void SpacePacketDeframerTester ::testNominalDeframing() { // Check output packet payload ASSERT_from_dataOut_SIZE(1); Fw::Buffer outBuffer = this->fromPortHistory_dataOut->at(0).data; - ASSERT_EQ(outBuffer.getSize(), dataLength); + ASSERT_EQ(outBuffer.getSize(), static_cast(dataLength)); for (U32 i = 0; i < dataLength; ++i) { ASSERT_EQ(outBuffer.getData()[i], data[i]); } diff --git a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.hpp b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.hpp index e0b7295f53d..9bf1a53872c 100644 --- a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.hpp +++ b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.hpp @@ -71,7 +71,7 @@ class SpacePacketDeframerTester final : public SpacePacketDeframerGTestBase { SpacePacketDeframer component; //! Test buffer - static const FwSizeType MAX_TEST_PACKET_DATA_SIZE = 200; + static const FwSizeType MAX_TEST_PACKET_DATA_SIZE = 200; // this value needs to fit in a U8 for testing U8 m_packetBuffer[SpacePacketHeader::SERIALIZED_SIZE + MAX_TEST_PACKET_DATA_SIZE]; }; From f293aab67449d039770b87d450458b67b3e05ad3 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Tue, 3 Jun 2025 13:52:55 -0700 Subject: [PATCH 72/95] More spelling fixes --- .github/actions/spelling/excludes.txt | 1 + .github/actions/spelling/expect.txt | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/actions/spelling/excludes.txt b/.github/actions/spelling/excludes.txt index 47f4651ed4e..6c6d66f9e9b 100644 --- a/.github/actions/spelling/excludes.txt +++ b/.github/actions/spelling/excludes.txt @@ -101,3 +101,4 @@ ^\QSvc/FileUplink/test/ut/dest.bin\E$ ignore$ mlc-config.json +Autocoders/ diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt index b850a2d7e52..aed8044cacb 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt @@ -790,6 +790,7 @@ puml punc pushd pvn +Pvn PYS PYTHONPATH qch @@ -991,7 +992,7 @@ TCSANOW tcsh tdir tdirection -telecommand +Telecommand telem TELEMCHANIMPL testcmd @@ -1095,9 +1096,9 @@ ustr utdir valgrind vbai -vca +VCA vcid -vcp +VCP vfd VFILE VID From 0f379a5e5c04bdda22cca443152e692db52eb1e7 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Tue, 3 Jun 2025 14:21:13 -0700 Subject: [PATCH 73/95] Improve SDDs and comments --- .../SpacePacketFramer/SpacePacketFramer.hpp | 3 +++ Svc/CCSDS/SpacePacketFramer/docs/sdd.md | 19 ++++++++++++++----- Svc/CCSDS/TMFramer/TMFramer.hpp | 2 -- Svc/CCSDS/TMFramer/docs/sdd.md | 18 ++++++++++++++++++ Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp | 4 +++- 5 files changed, 38 insertions(+), 8 deletions(-) diff --git a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp index f4eba53d4e9..145c3437084 100644 --- a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp +++ b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.hpp @@ -43,6 +43,9 @@ class SpacePacketFramer final : public SpacePacketFramerComponentBase { //! Handler implementation for dataIn //! //! Port to receive data to frame, in a Fw::Buffer with optional context + //! + //! Header fields are set according to the CCSDS Space Packet standard, and + //! is described in the component SDD. void dataIn_handler(FwIndexType portNum, //!< The port number Fw::Buffer& data, const ComCfg::FrameContext& context) override; diff --git a/Svc/CCSDS/SpacePacketFramer/docs/sdd.md b/Svc/CCSDS/SpacePacketFramer/docs/sdd.md index d817c3b8020..cb0a82e7f79 100644 --- a/Svc/CCSDS/SpacePacketFramer/docs/sdd.md +++ b/Svc/CCSDS/SpacePacketFramer/docs/sdd.md @@ -9,6 +9,20 @@ The `Svc::CCSDS::SpacePacketFramer` is typically used upstream of a component th ## Configuration The `Svc::CCSDS::SpacePacketFramer` requires an Application Process Identifier (APID) for the Space Packets it generates. This APID is typically provided during instantiation or configuration. It also uses a sequence count, which is managed per APID via the `getApidSeqCount` port. +## CCSDS Header Fields + +For each Space Packet generated, the `Svc::CCSDS::SpacePacketFramer` will populate the CCSDS Space Packet Primary Header fields as follows: + +| Field | Value | Notes | +|---|---|---| +| Version Number | 000 | As per protocol 4.1.3.2 | +| Packet Type | 0 (Telemetry) | SpacePacketFramer emits reporting packets only (no commanding), as per 4.1.3.3.2 | +| Secondary Header Flag | 0 | F Prime does not use secondary headers formally | +| Application Process Identifier (APID) | Uses value passed in the `context` argument | Project APIDs are defined in `config/ComCfg.fpp` | +| Sequence Flags | `0b11` (Unsegmented) | Unsegmented user data, F´ data fits in a single packet | +| Packet Sequence Count | Incremented for each packet, unique count per APID | Managed externally by a [`Svc::CCSDS::ApidManager`](../../ApidManager/docs/sdd.md) | +| Packet Data Length | Set to the length of the passed in data | Calculated based on the length of the data received on `dataIn` | + ## Port Descriptions | Kind | Name | Port Type | Description | @@ -33,8 +47,3 @@ The `Svc::CCSDS::SpacePacketFramer` requires an Application Process Identifier ( | SPF-008 | The SpacePacketFramer shall correctly populate all mandatory fields of the Space Packet Primary Header, including Version Number, Packet Type, Secondary Header Flag, APID, Sequence Flags, Packet Sequence Count, and Packet Data Length. | Unit Test | | SPF-009 | The SpacePacketFramer shall be configurable with an Application Process Identifier (APID) to be used in the Space Packet Header. | Inspection, Unit Test | | SPF-010 | The SpacePacketFramer shall accurately calculate and set the Packet Data Length field in the Space Packet header based on the length of the user data. | Unit Test | - -## Change Log -| Date | Description | -|---|---| -| May 28, 2025 | Initial Draft | \ No newline at end of file diff --git a/Svc/CCSDS/TMFramer/TMFramer.hpp b/Svc/CCSDS/TMFramer/TMFramer.hpp index 52bb3585f67..ab00ae5d1e6 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.hpp +++ b/Svc/CCSDS/TMFramer/TMFramer.hpp @@ -49,8 +49,6 @@ class TMFramer final : public TMFramerComponentBase { //! This is essentially the CCSDS TM VCP.request Service Primitive, with //! Packet=data and GVCID implicitly passed in context (TM Protocol 3.3.3.2) //! - //! TODO: mention context values that are being used - //! void dataIn_handler(FwIndexType portNum, //!< The port number Fw::Buffer& data, const ComCfg::FrameContext& context) override; diff --git a/Svc/CCSDS/TMFramer/docs/sdd.md b/Svc/CCSDS/TMFramer/docs/sdd.md index 0ab2b825936..3c31e3b2372 100644 --- a/Svc/CCSDS/TMFramer/docs/sdd.md +++ b/Svc/CCSDS/TMFramer/docs/sdd.md @@ -10,6 +10,24 @@ The `Svc::CCSDS::TMFramer` is designed to work in the common F Prime telemetry s The `Svc::CCSDS::TMFramer` component, as well as the rest of the CCSDS communications stack, is used in the [`Ref/`](https://github.com/nasa/fprime/tree/devel/Ref) example application. It is also generated by the `fprime-util new --deployment` command. +## CCSDS Header Fields + +For each frame generated, the `Svc::CCSDS::TMFramer` will populate the CCSDS TM Primary Header fields as follows: + +| Field | Value | Notes | +|---|---|---| +| Transfer Frame Version Number | 0 | As per protocol 4.1.2.2 | +| Spacecraft ID | Configured in `config/ComCfg.fpp` | Set in the project configuration | +| Virtual Channel ID | Uses value passed in the `context` argument (defaults to 0) | Set by an upstream component | +| Operational Control Field Flag | 0 | Unsupported | +| Master Channel Frame Count | Incremented for each frame | Managed internally by TMFramer | +| Virtual Channel Frame Count | Incremented for each frame | Managed internally by TMFramer. One TMFramer instance can only keep count of a single VCID. | +| Transfer Frame Secondary Header Flag | 0 | F Prime does not formally use secondary headers | +| Synchronization Flag | 0 | 0 as Packets are inserted | +| Packet Order Flag | 0 | As per protocol 4.1.2.7.4 | +| Segment Length Identifier | 0b11 | As per protocol 4.1.2.7.5 | +| First Header Pointer | 0 | F Prime packets are limited in length and always sent in a single frame, aligned to the start of the frame. | + ## Port Descriptions | Kind | Name | Port Type | Description | diff --git a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp index c076bd229f8..4d6ce7fe149 100644 --- a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp +++ b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp @@ -77,8 +77,10 @@ void TMFramerTester ::testNominalFraming() { FwSizeType expectedIdleDataOffset = TMHeader::SERIALIZED_SIZE + sizeof(bufferData) + SpacePacketHeader::SERIALIZED_SIZE; // The frame is composed of the payload + a SpacePacket Idle Packet (Header + idle_pattern) + const U8 idlePattern = this->component.IDLE_DATA_PATTERN; for (FwSizeType i = expectedIdleDataOffset; i < ComCfg::TmFrameFixedSize - TMTrailer::SERIALIZED_SIZE; ++i) { - ASSERT_EQ(outBuffer.getData()[i], 0x44); + ASSERT_EQ(outBuffer.getData()[i], idlePattern) + << "Idle data at index " << i << " does not match expected idle pattern"; } } From c3a8d265b61c757471c3b1875f15951526675251 Mon Sep 17 00:00:00 2001 From: Thomas Boyer-Chammard Date: Tue, 3 Jun 2025 21:22:37 +0000 Subject: [PATCH 74/95] Update metadata check-spelling run (pull_request_target) for ccsds-protocols Signed-off-by: check-spelling-bot on-behalf-of: @check-spelling --- .github/actions/spelling/expect.txt | 461 +--------------------------- 1 file changed, 10 insertions(+), 451 deletions(-) diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt index aed8044cacb..a34e1d22a25 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt @@ -1,7 +1,4 @@ Aadil -aarch -abcd -accurev AClass ACTIVELOGGER ACTIVELOGGERIMPL @@ -11,77 +8,40 @@ ACTIVERATEGROUP ACTIVERATEGROUPCFG ACTIVERATEGROUPIMPLTESTER ACTIVETEXTLOGGERIMPL -actools -addoffset adminlist -aeiouy -afterstatinfo ALLEXTERNALS alphanums ampcs -aname ANamespace -anotherchan -anotherparam -apad apid APIDOCS -aports -apos APPENDFILE aps -apxs -AQuat -AQueued -Arcsecond arduino ARef argcomplete -argcount ARGN -argname -argtype -arinc +ARINC arpa ASize -ASTRING -ATester ATL -ATMs -ATSAM -atypes AUTOBRIEF autocode autocoded autocoders autocoding -autodocs -Autodocumentation -autogen -automodule AYYYY -backslashreplace baremetal -bashcompinit batchmode BDV bfree bibtex Bies -bindir -binrel -bitfields +BINDIR bitmaps -blogs bocchino -bodychars -bodytext -bools boolt -brc -bre bsd -bslash BUFFERALLOCATE BUFFERALLOCATIONFAILED BUFFERGETOUT @@ -90,50 +50,35 @@ BUFFERMGR BUFFERQUEUEIN BUFFERTOOSMALLFORDATA BUFFERTOOSMALLFORPACKET -buffsize BUGLIST bugprone -builddir -buildroot buildstep -bysource BYTEDRV calcu callergraph callgraph -caltech Campuzano carg -caselessmatch CBF CBLOCK CCB CComponent ccsds ccsparc -cdefs CDH -cdn cerrno -cface CFDP cff cflag cfsetispeed cfsetospeed -changeme -CHANNELID CHANS -cheetahtemplate Chieu CHIPINFO CHK CHNG CIRCULARSTATE classdiagram -classdoc -classtype -CLion CLOSEFILE cloudbees CMDDISP @@ -141,48 +86,33 @@ CMDDISPATCHER CMDPACKET CMDREG cmdresponse -cmds cmdseq cmdsequencer cntx -cobj CODEFILE -codeql -codestyle -coldarm COLORSTYLE colorwheel COMBUFFER comlogger COMMANDDISPATCHERIMPL COMMANDDISPATCHERIMPLCFG -commandline -commasepitem COMPACKET COMPACKETQUEUEIN -componentipcbuf -COMPONENTTESTERIMPL COMQUEUE -COMQUEUEIN COMSPLITTER COMSTUB constexpr cookiecutter cooldown -coor coravy coreutils -cosmosgen Coverity CPHA -Cpkt cplusplus CPOL -cpos cppcheck cppcheckxml cpplint -cprogramming CRCAMPCS crcccitt crcdnp @@ -195,63 +125,37 @@ crsmith crt CRTSCTS cryptsoft -csh -cshrc -cstat csum ctest ctu culates -currentxml cuz CYCLEOUT -daringfireball DATAROOTDIR -dawbarton DDDTHH -ddmm -dealloc Debian deconstructor -defaultgen -defname deframe deframed deframer deframing -delchars deployables DEPRECATEDLIST deser Deserial DEVICESM -dhesikan DHTML diafile -dictgen -dictvalue -diffs -digitalcommons diles dinkel -dlog dnp -docblocks docbook docset -docstyle -doctag -doinit -dontcare dontinclude doodie -dotfile DOTFONTPATH downcall -downfiles -dox doxyfile -doxygen doxygenversion doxyindexer doxyrules @@ -268,58 +172,34 @@ DPWRITER DRAINBUFFERS drv drvtcpserversocket -dsdl dspal Dstate -duey -dumparch -dumpobj DVI DWN eabi eabihf eay ECLIPSEHELP -edu -EGB EHAs eip -elist Elts -emoji -endcode endcond endfunction -endloc endmacro endraw enduml -ENQUEUEX -enumchan -enumname -enumparam -eobj -errfile ERRORCHECK errornum ert esb -ethanchee etl EVENTARRAY EVENTBOOL eventflags -EVENTID -eventname EVENTPRIMITIVE evr evt -EXAMPLECOMPONENTIMPL -excinfo -Exoplanets -exprtokens externalproject -Fabcdef FAKELOGGER fbuild fdp @@ -331,21 +211,15 @@ Ffs FILEDOWNLINK FILEDOWNLINKCFG FILEID -fileopen FILEOPENERROR FILEWRITEERROR fio -Firefox FLDP -flist FNDELAY -fns FONTPATH foodoodie foodoodiehoo -formatline FPCONFIG -fpi FPL fpp fppi @@ -353,80 +227,43 @@ fpptest fprime fptr fputil -fpv fpy FPYSEQUENCER freeram Fregoso -frox frsize fsblkcnt fsw FWCASSERT -gaurav -gbl gcda gcgandhi gcov gdiplus -gencode -genfile GENHUB -genshi -getarg -getargument -getblocks -getbody -getchildren -getcontext -getcrc -getdata -getdefaultencoding -getduration -getextern -getf -getfooter -geti -getinput -getlength -getm -getop -getquaternion -getschema -getstart -getstatement -gett gettime getty -getu -getwakeup ghprb gitmodules gmock -Gnc Gnd gnueabihf -google googletest Gorang -GPGGA -gpio gpiochip gpioevent gpiohandle gpioline Graphviz grayscales -grnd GROUNDINTERFACERULES -gse +GSE gtags gtest gtimeout Guire GVCID HACKSM -handcoded +Handcoded handleflags hardtoaccess hashvalue @@ -434,10 +271,6 @@ hdr HEADERSIZE headlessly heapifying -hexid -hexnums -hexopcode -HFiles hhc hhk hhp @@ -449,39 +282,20 @@ HLTH HPSC htags HTH -htmlfile HTMLHELP -huey -HVisitor -hyperlinks ibd ieeetr -ifcomment iflag -ifname ifstr -ignorables -iif -ime imple -implgen importables -INADDR inbool INCLUDEDIR -inin -initfiles initstate inkscape -Inputline installable -instantiator -instring -instrlen -integertypename -interoperate intlimits -inttype +inttypes INVALIDBUFFER INVALIDHEADER INVALIDHEADERHASH @@ -491,36 +305,23 @@ ioctl ipas IPCFG IPHELPER -ipriority -isequal isf -ishii -isoschematron isr -iss itimerspec itr itval -itype janamian Jax jdk jdperez jenkins jenkinsci -jishii Joaquim jobrestrictions -joshuaa jpl jplffs jre -jsdelivr -JSO -jsonable kermit -kevin -kislyuk kubiak Lammert lammertbies @@ -528,9 +329,7 @@ LASTLOG LBLOCK LCHILD leisher -lemstarch lestarch -levelname lflag lhash LIBCRYPTO @@ -538,31 +337,20 @@ LIBDIR LIBEXECDIR LIBLOC lic -lindent LINEEVENT LINEHANDLE linelength lineoffset -lineroo -listdir -Listst -LJR lld llu LOCALSTATEDIR LOGGERRULES -loglvl LOGPACKET -logpath -Lps lseek -ltab -LTLT lvar LVL lxml MACROFILE -maincpp makefiles MAKEFLAGS makeindex @@ -570,24 +358,15 @@ MAKEVAR MALLOCALLOCATOR mallocator mathjax -maxdepth -maxloc -maxspew -mcomment MCT -mday MDFILE MEMALLOCATOR -memb -membername +MEMB memcheck -memname MEMTEST mentations mereweth Merewether -methoddoc -methodstub microcontrollers mkdocs mlc @@ -597,111 +376,61 @@ MML modbus MOSI MOVEFILE -mozilla -Mrf -Msap msc mscfile mseconds -msgs -msgtypeenum mstarch mstat MState -mstring -mtype multiarch -multioptionals -multirequired multitool -munmap mutexattr Mutexed -mval -MVC mycompany NACI nasafprime nbits ncsl -ndiffs -neascout -newloc newroot -newself -newstring newtio -ninjaaron -NMEA nmsgs -noargport NOBLOCK -nogen -noncomma -NONINFRINGEMENT noparent norecords -normalwidths -NOSIZE NOSPEC nostdlib nosubgrouping notask -notchars -nproc NPROCESSORS NSHUFF NSPACES ntohs -nukenewlines -numargs -nxt -objclass objcopy -objdoc -objdump -objmodule OCF -oclc ODR oflag okidocki -oldeol OLDINCLUDEDIR OMG ONLN -OPCODEBASE openmct openpyxl openssldir -oper optarg optind -oran orgslist -ORhex -origfile -origstatinfo ortega OSAL -osaves -osets -ossw ostate OSTIME -otherdictitems -otheritems otherside outbool outdir -outout ovr packetization packetize packetized packetizer -Packetizing -Paetz PARAMARRAY PARAMARRAYEXTERNAL PARAMBOOL @@ -715,43 +444,26 @@ PARAMSTRINGEXTERNAL PARAMSTRUCT PARAMSTRUCTEXTERNAL PARAMU -parseable PASSIVERATEGROUP PASSIVERATEGROUPIMPLTESTER -pathmaker patsubst -pbuild -pcmake -pcomp pdflatex PEB -Peet penv PERLMOD PINGSEND -pinit pkill -pkts +PKTS plainnat plantuml -pname PNGs pollfd POLLIN POLYDB -popd -portlist PORTOUT PORTSELECTOR -PORTSOUT ppandian -pport -PREDEF -preds pregen -preloc -preparse -printables prioritization PRIORITYQUEUE prm @@ -761,8 +473,6 @@ PRMDBIMPLTESTER PRMDBIMPLTESTERCFG PRMDBLIMPLCFG PRMLEDINITSTATE -prmname -probs PROCBUFFERSENDOUT PRODUCTGETIN PRODUCTREQUESTIN @@ -777,36 +487,18 @@ projectnumber propget propput protothreading -prototypetext -pstr -psyco ptbool -ptestrun ptf pthread -ptmcg ptrt -puml -punc -pushd -pvn Pvn -PYS -PYTHONPATH qch qhelpgenerator QHG qhp -QNX qsf -qthelpproject -Qualcomm -quatchan -RAbrack RAII -rancherdesktop randtbl -rapidscat raspberrypi raspi RATEGROUPDRIVER @@ -821,80 +513,47 @@ rcvd rdwr Readback Recvd -reder refspec REFTOPOLOGY REFTOPOLOGYDEFS regexs -relaxng REMOVEDIRECTORY REMOVEFILE -reparse reprioritize -reserializing -resname -resultlist -retobj RGD RHH -riverbankcomputing Rizvi -rootdir -ror -rowspan -rpaetz +ROOTDIR rpi RPIDEMO RPIDEMOCOMPONENTIMPLCFG rptr RSend -rtd -RTEMS -runperiod RXD -saddr SAlias sanitizers sats -savelist -saveop -sbb SBF SBINDIR sbom -Scatterometer -scc -schematron scid -sclk scm -scons sdd -SDFLIGHT searchdata SENDPARTIAL seqgen serializables setaffinity -setblocks -setdata -setid setinheritsched setlocalvar SETLOGGING -setm -setop setprotocol -setquaternion setschedparam setschedpolicy setstacksize settime -setversion sev -sface sfregoso -sgl SGN SHAREDSTATEDIR SHELLCOMMAND @@ -903,62 +562,38 @@ sideeffect sighandler Signedness Silveira -sinc sloc -smallsat -smcit socio SOCKETHELPER SOCKETIPDRIVER socklen -somechan -someenumchan -SOMEEVENT -Someother -someparam sometask somevalue sourced -SOURCEDIR -sourceforge -Sourcetrail sourcing -spacetech spdx -SPHINXBUILD -SPHINXOPTS spi spidev srandom -srange SRCS sreddy sss STAMEM -startloc startuml stdbool -STDC stddef stdint stest -stmtidx Stl +stmtidx STREQ STREQUAL -strg -stri -stringbuffer -stringchan -Stringpacket -stringparam STRINGUTILS STRNE strnlen subgrouping subhist subhistory -subpage subseconds subtargets subtopology @@ -968,12 +603,9 @@ SVCLOGFILE SVCLOGFILEL swcaegitadmin syft -synchronicity synopsys sysconf SYSCONFDIR -sysroot -tabbedwidths tabccitt tabdnp tabkermit @@ -982,44 +614,17 @@ tbase tcanham tcflush tcgetattr -tclist -tcomp -tcort TCPCLIENT TCPHELPER tcpserver TCSANOW -tcsh -tdir -tdirection Telecommand telem TELEMCHANIMPL -testcmd -TESTCOMMAND -TESTCOMMANDSOURCEIMPL -testcomp -TESTCOMPONENTIMPL testerbase -testgen TESTLIST -TESTLOGRECVIMPL testmark -TESTPARAMIMPL -TESTPARAMRECVIMPL -TESTPTSOURCEIMPL -teststring -TESTTELEMRECVIMPL -TESTTEXTLOGIMPL -TESTTIMEIMPL -testutdir TESTUTILS -tfile -tflat -tfn -thepihut -Thhmmss -thiscol thisdirdoesnotexist thisfiledoesnotexist Thu @@ -1032,106 +637,60 @@ tions tjh TKC tlc -tlist tlm TLMCHAN TLMCHANIMPLCFG TLMCHANIMPLTESTER -tlmname TLMPACKET TLMPACKETIZER TLMPACKETIZERCOMPONENTIMPLCFG TLMPACKETIZERTYPES -tlmval -TML tmpl -tmptokens tmptree -tname -toctree TODOLIST -tokdict TOKENBUCKETTESTER -tokenlist -toklist topologyapp topologydefs -TOTALFF -TOTALISFLOGEVENTMSG -TOTALISFTELMMSG -TOTALQUEUEFULL totalram tparam TPP -trimwhitespace trinomials -truncstring tts TXD -typedef typedef'ed -typelist -typeslist -typetoken +typedef uart -UBSAN -UDPRECEIVER -UDPRECEIVERCOMPONENTIMPLCFG -UDPSENDER -UDPSENDERCOMPONENTIMPLCFG UDPSOCKET UML UNEXP -UNINSTANTIATED unistd UNITTESTASSERT unittests -unprintables -upfiles -upl -usb useconds usecs -ustr -utdir valgrind vbai VCA vcid VCP -vfd VFILE VID -viewcontent -viewforum vla -vlist VOXL -vtype -vuejs vwong vxworks -waitrel watney Wdog whitebox WLE -Wno WORKDIR -worklist wrs -wsl wxgui wxy -Xabcdefx Xapian xdf xdffe -Xelect -xmlfile xsltproc xxxx XXYY -yacgen zimri -zmq From fa8271bc45c8fc230c027b82da45ce3dcf930179 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Tue, 3 Jun 2025 14:41:05 -0700 Subject: [PATCH 75/95] More SDD updates --- Svc/CCSDS/ApidManager/docs/sdd.md | 59 +++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/Svc/CCSDS/ApidManager/docs/sdd.md b/Svc/CCSDS/ApidManager/docs/sdd.md index 34314c026fa..5f5bd86cf4f 100644 --- a/Svc/CCSDS/ApidManager/docs/sdd.md +++ b/Svc/CCSDS/ApidManager/docs/sdd.md @@ -1,26 +1,49 @@ # Svc::CCSDS::ApidManager -## 1. Overview +The `Svc::CCSDS::ApidManager` component manages CCSDS Application Process Identifier (APID) sequence counts for the F Prime communications stack. It provides per-APID sequence count tracking and validation, supporting the construction and checking of CCSDS Space Packet headers by other components (such as `SpacePacketFramer` and `SpacePacketDeframer`). -The `ApidManager` component is a passive F´ component that maps the descriptor type (ComPacketType/APID) found in the first two bytes of a data buffer to a CCSDS Space Packet APID. It also tracks and manages a sequence count for each APID, as required by the CCSDS protocol. This enables downstream components to generate correct CCSDS Space Packets with the appropriate APID and sequence count. +The `ApidManager` is typically used in conjunction with the `SpacePacketFramer` (to provide incrementing sequence counts for each APID) and the `SpacePacketDeframer` (to validate received sequence counts and detect dropped or out-of-order packets). -## 2. Requirements +## Functionality -- Extract the APID (descriptor type) from the first two bytes of each incoming buffer. -- Set the APID in the outgoing `FrameContext`. -- Track a 14-bit sequence count for each APID, incrementing and wrapping as required by the CCSDS standard. -- Support a small, fixed set of non-contiguous APIDs. -- Operate without dynamic memory allocation or standard library containers. +- Maintains a table of APIDs and their associated 14-bit sequence counts. +- Handles a fixed maximum number of tracked APIDs (as configured in the project). +- Provides a way to retrieve the current sequence count for a given APID through a port call. +- Provides a way to validate a received sequence counts for a given APID through a port call. -## 3. Interfaces +## Port Descriptions -### Ports +| Kind | Name | Port Type | Description | +|-----------------|-----------------------|--------------------------|-----------------------------------------------------------------------------| +| guarded input | validateApidSeqCountIn| CCSDS.ApidSequenceCount | Validates a received sequence count for a given APID. | +| guarded input | getApidSeqCountIn | CCSDS.ApidSequenceCount | Returns and increments the sequence count for a given APID. | -| Port Name | Direction | Description | -|----------------|-----------|------------------------------------------------------------------| -| dataIn | input | Receives data buffers and context from upstream | -| dataOut | output | Forwards buffer with updated context (APID and sequence count) | -| dataReturnIn | input | Receives returned buffers from downstream | -| dataReturnOut | output | Returns buffers to upstream | -| comStatusIn | input | Receives status from downstream | -| comStatusOut | output | Forwards status upstream | +## Events + +| Name | Severity | Description | +|------------------------|---------------|-----------------------------------------------------------------------------| +| UnexpectedSequenceCount| warning high | Received an unexpected sequence count for an APID. | +| ApidTableFull | warning high | APID table is full; cannot track additional APIDs. | + +## Usage + +- The `getApidSeqCountIn` port is called by a component (e.g., `SpacePacketFramer`) to obtain and increment the sequence count for a given APID when constructing a new Space Packet. +- The `validateApidSeqCountIn` port is called by a component (e.g., `SpacePacketDeframer`) to check the sequence count of a received Space Packet. If the count does not match the expected value, an event is logged and the onboard count is synchronized. + +## Requirements + +| Name | Description | Validation | +|-----------------------------------|-----------------------------------------------------------------------------|----------------------| +| SVC-CCSDS-APID-MANAGER-001 | The ApidManager shall track a 14-bit sequence count for each APID. | Unit Test | +| SVC-CCSDS-APID-MANAGER-002 | The ApidManager shall provide the current sequence count for a given APID. | Unit Test | +| SVC-CCSDS-APID-MANAGER-003 | The ApidManager shall increment the sequence count for each APID on request.| Unit Test | +| SVC-CCSDS-APID-MANAGER-004 | The ApidManager shall provide validation of a received sequence counts for each APID. | Unit Test | +| SVC-CCSDS-APID-MANAGER-005 | The ApidManager shall emit an event if an unexpected sequence count is received.| Unit Test | +| SVC-CCSDS-APID-MANAGER-006 | The ApidManager shall emit an event if the APID table is full and an APID is not able to be added to the tracking. | Unit Test | +| SVC-CCSDS-APID-MANAGER-007 | The ApidManager shall synchronize the onboard sequence count if a mismatch is detected.| Unit Test | + +## See Also + +- [`Svc::CCSDS::SpacePacketFramer`](../../SpacePacketFramer/docs/sdd.md) +- [`Svc::CCSDS::SpacePacketDeframer`](../../SpacePacketDeframer/docs/sdd.md) +- [CCSDS Space Packet Protocol (CCSDS 133.0-B-2)](https://public.ccsds.org/Pubs/133x0b2e1.pdf) From 7341f2c8bbb4927a0875d5cd7e857f0ae4153bc2 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 4 Jun 2025 14:50:32 -0700 Subject: [PATCH 76/95] Attempt UT fixes --- Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp index 4d6ce7fe149..3eb19698c39 100644 --- a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp +++ b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp @@ -58,7 +58,8 @@ void TMFramerTester ::testNominalFraming() { ASSERT_from_dataOut_SIZE(1); Fw::Buffer outBuffer = this->fromPortHistory_dataOut->at(0).data; ComCfg::FrameContext outContext = this->fromPortHistory_dataOut->at(0).context; - ASSERT_EQ(outBuffer.getSize(), ComCfg::TmFrameFixedSize); + const FwSizeType expectedFrameSize = ComCfg::TmFrameFixedSize; + ASSERT_EQ(outBuffer.getSize(), expectedFrameSize); ASSERT_EQ(this->fromPortHistory_dataOut->at(0).context.getvcId(), defaultContext.getvcId()); U16 outScId = this->getFrameScId(outBuffer.getData()); @@ -66,7 +67,8 @@ void TMFramerTester ::testNominalFraming() { U8 outMcCount = this->getFrameMcCount(outBuffer.getData()); U8 outVcCount = this->getFrameVcCount(outBuffer.getData()); - ASSERT_EQ(outScId, ComCfg::SpacecraftId); + const U16 expectedScId = ComCfg::SpacecraftId; + ASSERT_EQ(outScId, expectedScId); ASSERT_EQ(outVcId, defaultContext.getvcId()); ASSERT_EQ(outMcCount, 0); ASSERT_EQ(outVcCount, 0); @@ -78,7 +80,8 @@ void TMFramerTester ::testNominalFraming() { // The frame is composed of the payload + a SpacePacket Idle Packet (Header + idle_pattern) const U8 idlePattern = this->component.IDLE_DATA_PATTERN; - for (FwSizeType i = expectedIdleDataOffset; i < ComCfg::TmFrameFixedSize - TMTrailer::SERIALIZED_SIZE; ++i) { + const FwSizeType ideDataEndOffset = ComCfg::TmFrameFixedSize - TMTrailer::SERIALIZED_SIZE; + for (FwSizeType i = expectedIdleDataOffset; i < ideDataEndOffset; ++i) { ASSERT_EQ(outBuffer.getData()[i], idlePattern) << "Idle data at index " << i << " does not match expected idle pattern"; } @@ -112,7 +115,7 @@ void TMFramerTester ::testSeqCountWrapAround() { } void TMFramerTester ::testInputBufferTooLarge() { - FwSizeType tooLargeSize = ComCfg::TmFrameFixedSize; // This is too large since we need room for header+trailer as well + const FwSizeType tooLargeSize = ComCfg::TmFrameFixedSize; // This is too large since we need room for header+trailer as well U8 bufferData[tooLargeSize]; Fw::Buffer buffer(bufferData, static_cast(tooLargeSize)); ComCfg::FrameContext defaultContext; From 493702bd2c8b9cf18ec10baee8694db1dc729848 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 4 Jun 2025 16:37:02 -0700 Subject: [PATCH 77/95] First pass of review comments --- Svc/CCSDS/ApidManager/ApidManager.cpp | 22 ++++++------------- Svc/CCSDS/ApidManager/ApidManager.fpp | 4 ++-- Svc/CCSDS/ApidManager/ApidManager.hpp | 5 +++-- .../SpacePacketDeframer.fpp | 10 --------- Svc/CCSDS/TCDeframer/TCDeframer.fpp | 4 ++-- Svc/ComStub/docs/sdd.md | 6 ++++- Svc/FprimeDeframer/FprimeDeframer.cpp | 10 ++++----- Svc/FprimeRouter/FprimeRouter.cpp | 7 ------ 8 files changed, 24 insertions(+), 44 deletions(-) diff --git a/Svc/CCSDS/ApidManager/ApidManager.cpp b/Svc/CCSDS/ApidManager/ApidManager.cpp index 8249d199685..c6850c594aa 100644 --- a/Svc/CCSDS/ApidManager/ApidManager.cpp +++ b/Svc/CCSDS/ApidManager/ApidManager.cpp @@ -14,17 +14,7 @@ namespace CCSDS { // Component construction and destruction // ---------------------------------------------------------------------- -ApidManager ::ApidManager(const char* const compName) : ApidManagerComponentBase(compName) { - // Initialize APID sequence table with common APID values - // This step is not strictly necessary, but it ensures that the most common APIDs are tracked - this->m_apidSequences[0].apid = ComCfg::APID::FW_PACKET_COMMAND; - this->m_apidSequences[1].apid = ComCfg::APID::FW_PACKET_TELEM; - this->m_apidSequences[2].apid = ComCfg::APID::FW_PACKET_LOG; - this->m_apidSequences[3].apid = ComCfg::APID::FW_PACKET_FILE; - // this->m_apidSequences[4].apid = ComCfg::APID::FW_PACKET_PACKETIZED_TLM; -} - -ApidManager ::~ApidManager() {} +ApidManager ::ApidManager(const char* const compName) : ApidManagerComponentBase(compName) {} // ---------------------------------------------------------------------- // Handler implementations for typed input ports @@ -32,7 +22,7 @@ ApidManager ::~ApidManager() {} U16 ApidManager ::validateApidSeqCountIn_handler(FwIndexType portNum, const ComCfg::APID& apid, U16 receivedSeqCount) { U16 expectedSequenceCount = this->getAndIncrementSeqCount(apid); - if (receivedSeqCount != expectedSequenceCount) { + if (receivedSeqCount != expectedSequenceCount && receivedSeqCount != SEQUENCE_COUNT_ERROR) { // Likely a packet was dropped or out of order this->log_WARNING_HI_UnexpectedSequenceCount(receivedSeqCount, expectedSequenceCount); // Synchronize onboard count with received number so that count can keep going @@ -52,7 +42,7 @@ U16 ApidManager ::getApidSeqCountIn_handler(FwIndexType portNum, const ComCfg::A U16 ApidManager ::getAndIncrementSeqCount(ComCfg::APID::T apid) { U16 seqCount = SEQUENCE_COUNT_ERROR; // Default to error value // Search the APID in the sequence table - for (U8 i = 0; i < MAX_TRACKED_APIDS; ++i) { + for (U16 i = 0; i < MAX_TRACKED_APIDS; i++) { if (this->m_apidSequences[i].apid == apid) { seqCount = this->m_apidSequences[i].sequenceCount; this->m_apidSequences[i].sequenceCount = static_cast((seqCount + 1) % (1 << 14)); // Increment for next call @@ -60,7 +50,7 @@ U16 ApidManager ::getAndIncrementSeqCount(ComCfg::APID::T apid) { } } // If not found, search for an uninitialized entry to track this APID - for (U8 i = 0; i < MAX_TRACKED_APIDS; ++i) { + for (U16 i = 0; i < MAX_TRACKED_APIDS; i++) { if (this->m_apidSequences[i].apid == ComCfg::APID::INVALID_UNINITIALIZED) { this->m_apidSequences[i].apid = apid; // Initialize this entry with the new APID seqCount = this->m_apidSequences[i].sequenceCount; // Entries default to 0 unless otherwise specified @@ -73,12 +63,14 @@ U16 ApidManager ::getAndIncrementSeqCount(ComCfg::APID::T apid) { } void ApidManager::setNextSeqCount(ComCfg::APID::T apid, U16 seqCount) { - for (U8 i = 0; i < MAX_TRACKED_APIDS; i++) { + for (U16 i = 0; i < MAX_TRACKED_APIDS; i++) { if (this->m_apidSequences[i].apid == apid) { this->m_apidSequences[i].sequenceCount = seqCount; return; } } + // This code should not be reahcable with the if statement in validateApidSeqCountIn_handler + FW_ASSERT(false, static_cast(apid)); } } // namespace CCSDS diff --git a/Svc/CCSDS/ApidManager/ApidManager.fpp b/Svc/CCSDS/ApidManager/ApidManager.fpp index de8d0369f99..1631012ecda 100644 --- a/Svc/CCSDS/ApidManager/ApidManager.fpp +++ b/Svc/CCSDS/ApidManager/ApidManager.fpp @@ -8,8 +8,8 @@ module CCSDS { @ Deframing received an unexpected sequence count event UnexpectedSequenceCount(transmitted: U16, expected: U16) \ - severity warning high \ - format "Unexpected sequence count received. Packets may have been lost. Transmitted: {} | Expected on board: {}" + severity warning low \ + format "Unexpected sequence count received. Packets may have been dropped. Transmitted: {} | Expected on board: {}" @ Received an unregistered APID event ApidTableFull(invalidApidValue: U16) \ diff --git a/Svc/CCSDS/ApidManager/ApidManager.hpp b/Svc/CCSDS/ApidManager/ApidManager.hpp index aec7aeed04f..47ed67b0377 100644 --- a/Svc/CCSDS/ApidManager/ApidManager.hpp +++ b/Svc/CCSDS/ApidManager/ApidManager.hpp @@ -35,7 +35,7 @@ class ApidManager final : public ApidManagerComponentBase { friend class ApidManagerTester; //!< Friend class for testing public: - static constexpr U8 MAX_TRACKED_APIDS = ComCfg::APID::NUM_CONSTANTS; + static constexpr U16 MAX_TRACKED_APIDS = ComCfg::APID::NUM_CONSTANTS; static constexpr U16 SEQUENCE_COUNT_ERROR = std::numeric_limits::max(); // ---------------------------------------------------------------------- // Component construction and destruction @@ -46,7 +46,7 @@ class ApidManager final : public ApidManagerComponentBase { ); //! Destroy ApidManager object - ~ApidManager(); + ~ApidManager() = default; private: // ---------------------------------------------------------------------- @@ -75,6 +75,7 @@ class ApidManager final : public ApidManagerComponentBase { void setNextSeqCount(ComCfg::APID::T apid, U16 seqCount); //! This struct helps track sequence counts per APID + //! Future work: update to using a map from Fw/DataStructures when available struct ApidSequenceEntry { ComCfg::APID::T apid = ComCfg::APID::INVALID_UNINITIALIZED; U16 sequenceCount = 0; diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp index a2a494844ea..5b922cc2c62 100644 --- a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp @@ -12,16 +12,6 @@ module CCSDS { severity warning high \ format "Invalid length received. Header specified packet length of {} | Actual received data length: {}" - # @ Deframing received an unexpected sequence count - # event UnexpectedSequenceCount(transmitted: U16, expected: U16) \ - # severity warning high \ - # format "Unexpected sequence count received. Packets may have been lost. Transmitted: {} | Expected on board: {}" - - # @ Deframing received an unexpected sequence count - # event UntrackedApid(apid: U16) \ - # severity activity low \ - # format "Received APID not registered with the deframer. Not checking sequence count. APID={}" - ############################################################################### # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # ############################################################################### diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.fpp b/Svc/CCSDS/TCDeframer/TCDeframer.fpp index 5294e618e7b..7500f092fe8 100644 --- a/Svc/CCSDS/TCDeframer/TCDeframer.fpp +++ b/Svc/CCSDS/TCDeframer/TCDeframer.fpp @@ -7,11 +7,11 @@ module CCSDS { @ Deframing received an invalid SCID event InvalidSpacecraftId(transmitted: U16, configured: U16) \ - severity activity low \ + severity warning low \ format "Invalid Spacecraft ID Received. Received: {} | Deframer configured with: {}" @ Deframing received an invalid frame length - event InvalidFrameLength(transmitted: U16, actual: U32) \ + event InvalidFrameLength(transmitted: U16, actual: FwSizeType) \ severity warning high \ format "Not enough data received. Header length specified: {} | Received data length: {}" diff --git a/Svc/ComStub/docs/sdd.md b/Svc/ComStub/docs/sdd.md index ebd2e8ea970..d3efda6c5ed 100644 --- a/Svc/ComStub/docs/sdd.md +++ b/Svc/ComStub/docs/sdd.md @@ -4,7 +4,11 @@ `Svc::ComStub` is an example F´ component implementing the [communication adapter interface](../../../docs/reference/communication-adapter-interface.md) required -to work with F´ communication components. Projects and users may choose to replace this with a complete communication +to work with F´ communication components. Projects would typically switch this component out for a +radio manager component. The purpose of ComStub is to implement the communication adapter interface by delegating +to a [`Drv.ByteStreamDriver`](../../../Drv/Interfaces/docs/sdd.md) (e.g. `Drv.TcpClient` or `Drv.LinuxUartDriver`) to send and receive data. + +Projects and users may choose to replace this with a complete communication implementation (i.e. a component managing a specific radio) once ready. As long as any communication implementation implements the communication adapter interface it can drop in and work with the standard F´ uplink and downlink setup. diff --git a/Svc/FprimeDeframer/FprimeDeframer.cpp b/Svc/FprimeDeframer/FprimeDeframer.cpp index b8b7556e38c..20a5dd0e0cc 100644 --- a/Svc/FprimeDeframer/FprimeDeframer.cpp +++ b/Svc/FprimeDeframer/FprimeDeframer.cpp @@ -58,11 +58,11 @@ void FprimeDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, cons return; } // Extract packet descriptor from the packet data to set the APID for the Router - // FwPacketDescriptorType packetDescriptor; - // status = deserializer.deserialize(packetDescriptor); - // FW_ASSERT(status == Fw::SerializeStatus::FW_SERIALIZE_OK, status); - // ComCfg::FrameContext contextCopy = context; - // contextCopy.setapid(static_cast(packetDescriptor)); + FwPacketDescriptorType packetDescriptor; + status = deserializer.deserialize(packetDescriptor); + FW_ASSERT(status == Fw::SerializeStatus::FW_SERIALIZE_OK, status); + ComCfg::FrameContext contextCopy = context; + contextCopy.setapid(static_cast(packetDescriptor)); // ---------------- Validate Frame Trailer ---------------- // Deserialize transmitted trailer: trailer is at offset = len(header) + len(body) diff --git a/Svc/FprimeRouter/FprimeRouter.cpp b/Svc/FprimeRouter/FprimeRouter.cpp index db5e8b14b3f..d6bfe2cc85d 100644 --- a/Svc/FprimeRouter/FprimeRouter.cpp +++ b/Svc/FprimeRouter/FprimeRouter.cpp @@ -27,13 +27,6 @@ FprimeRouter ::~FprimeRouter() {} void FprimeRouter ::dataIn_handler(FwIndexType portNum, Fw::Buffer& packetBuffer, const ComCfg::FrameContext& context) { Fw::SerializeStatus status; Fw::ComPacketType packetType = context.getapid(); - // If APID is unknown (i.e. not provided), attempt to introspect the packet to determine the packet type - if (packetType == Fw::ComPacketType::FW_PACKET_UNKNOWN) { - FwPacketDescriptorType packetDescriptor; - auto esb = packetBuffer.getDeserializer(); - (void) esb.deserialize(packetDescriptor); - packetType = static_cast(packetDescriptor); - } // Route based on received APID (packet type) switch (packetType) { // Handle a command packet From 9684c6c79f968424afb2302dde1e004f840afb5a Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 4 Jun 2025 20:31:16 -0700 Subject: [PATCH 78/95] Fix length token is minus 1 inconsistency --- Svc/CCSDS/ApidManager/ApidManager.cpp | 2 +- .../SpacePacketDeframer.cpp | 8 ++-- .../SpacePacketFramer/SpacePacketFramer.cpp | 9 +--- Svc/CCSDS/TCDeframer/TCDeframer.cpp | 42 +++++++++++-------- Svc/CCSDS/TCDeframer/TCDeframer.hpp | 6 +-- Svc/CCSDS/TMFramer/TMFramer.cpp | 17 ++++---- .../FrameDetector/CcsdsTCFrameDetector.cpp | 7 ++-- 7 files changed, 44 insertions(+), 47 deletions(-) diff --git a/Svc/CCSDS/ApidManager/ApidManager.cpp b/Svc/CCSDS/ApidManager/ApidManager.cpp index c6850c594aa..df049f7e683 100644 --- a/Svc/CCSDS/ApidManager/ApidManager.cpp +++ b/Svc/CCSDS/ApidManager/ApidManager.cpp @@ -24,7 +24,7 @@ U16 ApidManager ::validateApidSeqCountIn_handler(FwIndexType portNum, const ComC U16 expectedSequenceCount = this->getAndIncrementSeqCount(apid); if (receivedSeqCount != expectedSequenceCount && receivedSeqCount != SEQUENCE_COUNT_ERROR) { // Likely a packet was dropped or out of order - this->log_WARNING_HI_UnexpectedSequenceCount(receivedSeqCount, expectedSequenceCount); + this->log_WARNING_LO_UnexpectedSequenceCount(receivedSeqCount, expectedSequenceCount); // Synchronize onboard count with received number so that count can keep going this->setNextSeqCount(apid, static_cast(receivedSeqCount + 1)); } diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp index 1e787fe314d..0cde8c0c556 100644 --- a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp @@ -40,13 +40,15 @@ void SpacePacketDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, // 16b - n/a - Packet Data Length // ################################ - FW_ASSERT(data.getSize() >= SpacePacketHeader::SERIALIZED_SIZE, static_cast(data.getSize())); + FW_ASSERT(data.getSize() > SpacePacketHeader::SERIALIZED_SIZE, static_cast(data.getSize())); SpacePacketHeader header; Fw::SerializeStatus status = data.getDeserializer().deserialize(header); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); - U16 pkt_length = header.getpacketDataLength(); + // Space Packet protocol defines the Data Length as number of bytes minus 1 + // so we need to add 1 to the length to get the actual data size + U16 pkt_length = header.getpacketDataLength() + 1; if (pkt_length > data.getSize() - SpacePacketHeader::SERIALIZED_SIZE) { U32 maxDataAvailable = data.getSize() - SpacePacketHeader::SERIALIZED_SIZE; this->log_WARNING_HI_InvalidLength(pkt_length, maxDataAvailable); @@ -66,7 +68,7 @@ void SpacePacketDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, // Set data buffer to be of the encapsulated data: HEADER (6 bytes) | PACKET DATA data.setData(data.getData() + SpacePacketHeader::SERIALIZED_SIZE); - data.setSize(pkt_length); + data.setSize(pkt_length); this->dataOut_out(0, data, contextCopy); } diff --git a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp index 76e2953e789..c03054ba12a 100644 --- a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp +++ b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp @@ -28,10 +28,8 @@ void SpacePacketFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, c SpacePacketHeader header; Fw::SerializeStatus status; FwSizeType frameSize = SpacePacketHeader::SERIALIZED_SIZE + data.getSize(); - FW_ASSERT(data.getSize() <= std::numeric_limits::max(), static_cast(frameSize)); - FW_ASSERT(frameSize <= std::numeric_limits::max(), static_cast(frameSize)); + FW_ASSERT(data.getSize() <= std::numeric_limits::max() - SpacePacketHeader::SERIALIZED_SIZE, static_cast(data.getSize())); - // TODO: Maybe can use a member as well, instead of allocating a new one each time // Allocate frame buffer Fw::Buffer frameBuffer = this->bufferAllocate_out(0, static_cast(frameSize)); auto frameSerializer = frameBuffer.getSerializer(); @@ -45,12 +43,9 @@ void SpacePacketFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, c FW_ASSERT((apid >> 11) == 0, static_cast(apid)); // apid must fit in 11 bits packetIdentification |= static_cast(apid) & SpacePacketSubfields::ApidMask; // 11 bit APID + U16 sequenceCount = this->getApidSeqCount_out(0, apid, 0); // retrieve the sequence count for this APID U16 packetSequenceControl = 0; packetSequenceControl |= 0x3 << SpacePacketSubfields::SeqFlagsOffset; // Sequence Flags 0b11 = unsegmented User Data - - U16 sequenceCount = this->getApidSeqCount_out(0, apid, 0); // retrieve the sequence count for this APID - // NOTE: this will assert if ApidManager's table is full (because error value is max(U16)) - should it?? - FW_ASSERT((sequenceCount >> 14) == 0, static_cast(sequenceCount)); // sequence count must fit in 14 bits packetSequenceControl |= sequenceCount & SpacePacketSubfields::SeqCountMask; // 14 bit sequence count FW_ASSERT(data.getSize() <= std::numeric_limits::max(), static_cast(data.getSize())); diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.cpp b/Svc/CCSDS/TCDeframer/TCDeframer.cpp index d13c12f3638..91eb0959d52 100644 --- a/Svc/CCSDS/TCDeframer/TCDeframer.cpp +++ b/Svc/CCSDS/TCDeframer/TCDeframer.cpp @@ -19,11 +19,15 @@ namespace CCSDS { // ---------------------------------------------------------------------- TCDeframer ::TCDeframer(const char* const compName) - : TCDeframerComponentBase(compName), - m_spacecraftId(ComCfg::SpacecraftId) {} + : TCDeframerComponentBase(compName), m_spacecraftId(ComCfg::SpacecraftId) {} TCDeframer ::~TCDeframer() {} +void TCDeframer::configure(U16 vcId, U16 spacecraftId, bool acceptAllVcid) { + this->m_vcId = vcId; + this->m_spacecraftId = spacecraftId; + this->m_acceptAllVcid = acceptAllVcid; +} // ---------------------------------------------------------------------- // Handler implementations for user-defined typed input ports // ---------------------------------------------------------------------- @@ -33,7 +37,7 @@ void TCDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const Co // 5 octets - TC Primary Header // Up to 1019 octets - Data Field (including optional 2 octets frame error control field) - // Note: F Prime uses Type-BD + // Note: F Prime uses Type-BD // CCSDS TC Primary Header: // 2b - 00 - TF Version Number // 1b - 0/1 - Bypass Flag (0 = Type-A FARM checks enabled, 1 = Type-B FARM checks bypassed) @@ -47,30 +51,31 @@ void TCDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const Co // CCSDS TC Trailer: // 16b - Frame Error Control Field (FECF): CRC16 - FW_ASSERT(data.getSize() >= TCHeader::SERIALIZED_SIZE, static_cast(data.getSize())); + FW_ASSERT(data.getSize() > TCHeader::SERIALIZED_SIZE + TCTrailer::SERIALIZED_SIZE, + static_cast(data.getSize())); TCHeader header; Fw::SerializeStatus status = data.getDeserializer().deserialize(header); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); - - U16 frame_length = header.getvcIdAndLength() & TCSubfields::FrameLengthMask; + // TC protocol defines the Frame Length as number of bytes minus 1, so we add 1 back to get length in bytes + U16 total_frame_length = static_cast((header.getvcIdAndLength() & TCSubfields::FrameLengthMask) + 1); U8 vc_id = static_cast((header.getvcIdAndLength() & TCSubfields::VcIdMask) >> TCSubfields::VcIdOffset); U16 spacecraft_id = header.getflagsAndScId() & TCSubfields::SpacecraftIdMask; if (spacecraft_id != this->m_spacecraftId) { - this->log_ACTIVITY_LO_InvalidSpacecraftId(spacecraft_id, this->m_spacecraftId); - this->dataReturnOut_out(0, data, context); // drop the frame + this->log_WARNING_LO_InvalidSpacecraftId(spacecraft_id, this->m_spacecraftId); + this->dataReturnOut_out(0, data, context); // drop the frame return; } - if (data.getSize() < static_cast(frame_length + TCHeader::SERIALIZED_SIZE + TCTrailer::SERIALIZED_SIZE)) { - U32 maxDataAvailable = data.getSize() - TCHeader::SERIALIZED_SIZE - TCTrailer::SERIALIZED_SIZE; - this->log_WARNING_HI_InvalidFrameLength(frame_length, maxDataAvailable); - this->dataReturnOut_out(0, data, context); // drop the frame + if (data.getSize() < static_cast(total_frame_length)) { + FwSizeType maxDataAvailable = static_cast(data.getSize()); + this->log_WARNING_HI_InvalidFrameLength(total_frame_length, maxDataAvailable); + this->dataReturnOut_out(0, data, context); // drop the frame return; } - if (this->m_acceptAllVcid == false && vc_id != this->m_vcId) { + if (not this->m_acceptAllVcid && vc_id != this->m_vcId) { this->log_ACTIVITY_LO_InvalidVcId(vc_id, this->m_vcId); - this->dataReturnOut_out(0, data, context); // drop the frame + this->dataReturnOut_out(0, data, context); // drop the frame return; } // Note: F Prime uses TC Type-BD frames for now, so the FARM checks are not ran @@ -80,23 +85,24 @@ void TCDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const Co // CRC Check // ------------------------------------------------- // Compute CRC over the entire frame buffer minus the FECF trailer - U16 computed_crc = CCSDS::Utils::CRC16::compute(data.getData(), TCHeader::SERIALIZED_SIZE + frame_length); + U16 computed_crc = CCSDS::Utils::CRC16::compute(data.getData(), total_frame_length - TCTrailer::SERIALIZED_SIZE); TCTrailer trailer; auto deserializer = data.getDeserializer(); - deserializer.moveDeserToOffset(TCHeader::SERIALIZED_SIZE + frame_length); + deserializer.moveDeserToOffset(total_frame_length - TCTrailer::SERIALIZED_SIZE); status = deserializer.deserialize(trailer); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); U16 transmitted_crc = trailer.getfecf(); if (transmitted_crc != computed_crc) { this->log_WARNING_HI_InvalidCrc(computed_crc, transmitted_crc); - this->dataReturnOut_out(0, data, context); // drop the frame + this->dataReturnOut_out(0, data, context); // drop the frame return; } // Point to the start of the data field and set appropriate size data.setData(data.getData() + TCHeader::SERIALIZED_SIZE); - data.setSize(frame_length); + // Shrink size to that of the encapsulated data field ( header | data | trailer ) + data.setSize(total_frame_length - TCHeader::SERIALIZED_SIZE - TCTrailer::SERIALIZED_SIZE); this->dataOut_out(0, data, context); } diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.hpp b/Svc/CCSDS/TCDeframer/TCDeframer.hpp index b86792f6265..8776b680d67 100644 --- a/Svc/CCSDS/TCDeframer/TCDeframer.hpp +++ b/Svc/CCSDS/TCDeframer/TCDeframer.hpp @@ -36,11 +36,7 @@ class TCDeframer : public TCDeframerComponentBase { //! \param spacecraftId The spacecraft ID to accept //! \param acceptAllVcid If true, the deframer will accept all VCIDs. If false, it will only accept configured vcId //! - void configure(U16 vcId, U16 spacecraftId, bool acceptAllVcid) { - this->m_vcId = vcId; - this->m_spacecraftId = spacecraftId; - this->m_acceptAllVcid = acceptAllVcid; - } + void configure(U16 vcId, U16 spacecraftId, bool acceptAllVcid); private: // ---------------------------------------------------------------------- diff --git a/Svc/CCSDS/TMFramer/TMFramer.cpp b/Svc/CCSDS/TMFramer/TMFramer.cpp index aec85625955..c292cd664c0 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.cpp +++ b/Svc/CCSDS/TMFramer/TMFramer.cpp @@ -30,7 +30,6 @@ TMFramer ::~TMFramer() {} // ---------------------------------------------------------------------- void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { - // TODO: make this an event probably FW_ASSERT(data.getSize() <= ComCfg::TmFrameFixedSize - TMHeader::SERIALIZED_SIZE - TMTrailer::SERIALIZED_SIZE, static_cast(data.getSize())); @@ -104,32 +103,32 @@ void TMFramer ::dataReturnIn_handler(FwIndexType portNum, const ComCfg::FrameContext& context) { // dataReturnIn is our own member buffer coming back from the dataOut call - memset it to 0 FW_ASSERT(frameBuffer.getData() == static_cast(this->m_frameBuffer)); - ::memset(this->m_frameBuffer, 0, sizeof(this->m_frameBuffer)); + // Maybe check that pointer is within the bounds of m_frameBuffer? // NOTE: should we set a flag to track that it has been returned and ready for reuse? - // NOTE: a nice trick for efficiency would be to memset to IDLE_DATA_PATTERN instead... but eh + // --> yes that would be nice, and assert if not } void TMFramer ::fill_with_idle_packet(Fw::SerializeBufferBase& serializer) { constexpr U16 endIndex = ComCfg::TmFrameFixedSize - TMTrailer::SERIALIZED_SIZE; constexpr U16 idleApid = static_cast(ComCfg::APID::SPP_IDLE_PACKET); const U16 startIndex = static_cast(serializer.getBuffLength()); - const U16 idlePacketLength = static_cast(endIndex - startIndex); + const U16 idlePacketSize = static_cast(endIndex - startIndex); + // Length token is defined as the number of bytes of payload data minus 1 + const U16 lengthToken = static_cast(idlePacketSize - SpacePacketHeader::SERIALIZED_SIZE - 1); - FW_ASSERT(idlePacketLength > 0, static_cast(idlePacketLength)); - FW_ASSERT(idlePacketLength >= 7, static_cast(idlePacketLength)); // 7 bytes minimum for idle packet - FW_ASSERT(idlePacketLength <= ComCfg::TmFrameFixedSize, static_cast(idlePacketLength)); + FW_ASSERT(idlePacketSize >= 7, static_cast(idlePacketSize)); // 7 bytes minimum for idle packet + FW_ASSERT(idlePacketSize <= ComCfg::TmFrameFixedSize, static_cast(idlePacketSize)); SpacePacketHeader header; header.setpacketIdentification(idleApid); header.setpacketSequenceControl( 0x3 << SpacePacketSubfields::SeqFlagsOffset); // Sequence Flags = 0b11 (unsegmented) & unused Seq count - header.setpacketDataLength(idlePacketLength); + header.setpacketDataLength(lengthToken); // this should be payload length - 1 ??? // Serialize header and idle data into the frame serializer.serialize(header); for (U16 i = static_cast(startIndex + SpacePacketHeader::SERIALIZED_SIZE); i < endIndex; i++) { serializer.serialize(IDLE_DATA_PATTERN); // Idle data } } - } // namespace CCSDS } // namespace Svc diff --git a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp index a320f2823a0..90a3c646cd5 100644 --- a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp +++ b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp @@ -42,10 +42,9 @@ FrameDetector::Status CcsdsTCFrameDetector::detect(const Types::CircularBuffer& // If the flags and SC ID do not match the expected token, we don't have a valid frame return Status::NO_FRAME_DETECTED; } - - const U16 frame_data_length = header.getvcIdAndLength() & CCSDS::TCSubfields::FrameLengthMask; - const FwSizeType expected_frame_length = frame_data_length + CCSDS::TCHeader::SERIALIZED_SIZE + CCSDS::TCTrailer::SERIALIZED_SIZE; - const U16 data_to_crc_length = static_cast(frame_data_length + CCSDS::TCHeader::SERIALIZED_SIZE); + // TC protocol defines the Frame Length as number of bytes minus 1, so we add 1 back to get length in bytes + const FwSizeType expected_frame_length = static_cast((header.getvcIdAndLength() & CCSDS::TCSubfields::FrameLengthMask) + 1); + const U16 data_to_crc_length = static_cast(expected_frame_length - CCSDS::TCTrailer::SERIALIZED_SIZE); if (data.get_allocated_size() < expected_frame_length) { size_out = expected_frame_length; From d5ab202bca7893ea2d36e7112b7494396b42383b Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Fri, 6 Jun 2025 10:58:36 -0700 Subject: [PATCH 79/95] Review recs: static assert frame size, docs, TM buffer asserts --- Svc/CCSDS/TMFramer/TMFramer.cpp | 14 +++++---- Svc/CCSDS/TMFramer/TMFramer.hpp | 30 ++++++++++++++++--- Svc/CCSDS/TMFramer/docs/sdd.md | 6 ++++ default/config/ComCfg.fpp | 3 -- default/config/FileDownlinkCfg.hpp | 2 +- default/config/FpConfig.h | 4 +-- .../framework/configuring-fprime.md | 2 +- 7 files changed, 45 insertions(+), 16 deletions(-) diff --git a/Svc/CCSDS/TMFramer/TMFramer.cpp b/Svc/CCSDS/TMFramer/TMFramer.cpp index c292cd664c0..c3d69875242 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.cpp +++ b/Svc/CCSDS/TMFramer/TMFramer.cpp @@ -32,6 +32,10 @@ TMFramer ::~TMFramer() {} void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { FW_ASSERT(data.getSize() <= ComCfg::TmFrameFixedSize - TMHeader::SERIALIZED_SIZE - TMTrailer::SERIALIZED_SIZE, static_cast(data.getSize())); + // Ensure the buffer is owned by the TMFramer + // TODO: add UTs + FW_ASSERT(this->m_bufferState == BufferOwnershipState::OWNED, + static_cast(this->m_bufferState)); // ----------------------------------------------- // Header @@ -88,6 +92,7 @@ void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComC status = frameSerializer.serialize(trailer); FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); + this->m_bufferState = BufferOwnershipState::NOT_OWNED; this->dataOut_out(0, frameBuffer, context); this->dataReturnOut_out(0, data, context); // return ownership of the original data buffer } @@ -101,11 +106,10 @@ void TMFramer ::comStatusIn_handler(FwIndexType portNum, Fw::Success& condition) void TMFramer ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& frameBuffer, const ComCfg::FrameContext& context) { - // dataReturnIn is our own member buffer coming back from the dataOut call - memset it to 0 - FW_ASSERT(frameBuffer.getData() == static_cast(this->m_frameBuffer)); - // Maybe check that pointer is within the bounds of m_frameBuffer? - // NOTE: should we set a flag to track that it has been returned and ready for reuse? - // --> yes that would be nice, and assert if not + // Assert that the returned buffer is the member, and set ownership state + FW_ASSERT(frameBuffer.getData() >= &this->m_frameBuffer[0]); + FW_ASSERT(frameBuffer.getData() < &this->m_frameBuffer[0] + sizeof(this->m_frameBuffer)); + this->m_bufferState = BufferOwnershipState::OWNED; } void TMFramer ::fill_with_idle_packet(Fw::SerializeBufferBase& serializer) { diff --git a/Svc/CCSDS/TMFramer/TMFramer.hpp b/Svc/CCSDS/TMFramer/TMFramer.hpp index ab00ae5d1e6..b4c87adadc1 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.hpp +++ b/Svc/CCSDS/TMFramer/TMFramer.hpp @@ -14,9 +14,25 @@ namespace Svc { namespace CCSDS { class TMFramer final : public TMFramerComponentBase { - friend class TMFramerTester; - - static constexpr U8 IDLE_DATA_PATTERN = 0x44; + friend class TMFramerTester; + + static_assert(ComCfg::TmFrameFixedSize > TMHeader::SERIALIZED_SIZE + TMTrailer::SERIALIZED_SIZE, + "TM Frame Fixed Size must be at least large enough to hold header, trailer and data"); + // These are to ensure the frame can hold the the packet buffer, its SP header and an idle packet of 1 byte + // This is because TM specifies a frame to be padded with an idle packet of at least 1 byte of idle data + static_assert( + ComCfg::TmFrameFixedSize >= FW_COM_BUFFER_MAX_SIZE + (2 * SpacePacketHeader::SERIALIZED_SIZE) + 1, + "TM Frame Fixed Size must be at least large enough to hold a full com buffer, 2 SP headers and 1 byte"); + static_assert( + ComCfg::TmFrameFixedSize >= FW_FILE_BUFFER_MAX_SIZE + (2 * SpacePacketHeader::SERIALIZED_SIZE) + 1, + "TM Frame Fixed Size must be at least large enough to hold a full com buffer, 2 SP headers and 1 byte"); + + static constexpr U8 IDLE_DATA_PATTERN = 0x44; + + enum class BufferOwnershipState { + NOT_OWNED, //!< The buffer is currently not owned by the TMFramer + OWNED, //!< The buffer is currently owned by the TMFramer + }; public: // ---------------------------------------------------------------------- @@ -63,14 +79,21 @@ class TMFramer final : public TMFramerComponentBase { // ---------------------------------------------------------------------- // Helpers // ---------------------------------------------------------------------- + private: //! Fill the frame buffer with an Idle Packet to complete the frame data field //! as per CCSDS TM Protocol paragraph 4.2.2.5. Idle packet is inserted at the //! start_index index of the frame buffer, and fills it up to the end minus CRC void fill_with_idle_packet(Fw::SerializeBufferBase& serializer); + // ---------------------------------------------------------------------- + // Members + // ---------------------------------------------------------------------- + private: // Because the TM protocol use fixed width frames, and only one frame is in transit between ComQueue and // ComInterface at a time, we can use a member fixed-size buffer to hold the frame data U8 m_frameBuffer[ComCfg::TmFrameFixedSize]; //!< Buffer to hold the frame data + BufferOwnershipState m_bufferState = + BufferOwnershipState::OWNED; //!< Whether m_frameBuffer is owned by the TMFramer or not // Current implementation uses a single virtual channel, so we can use a single virtual frame count U8 m_masterFrameCount; //!< Master Frame Count - 8 bits - wraps around at 255 @@ -78,7 +101,6 @@ class TMFramer final : public TMFramerComponentBase { }; } // namespace CCSDS - } // namespace Svc #endif diff --git a/Svc/CCSDS/TMFramer/docs/sdd.md b/Svc/CCSDS/TMFramer/docs/sdd.md index 3c31e3b2372..e4cdc859092 100644 --- a/Svc/CCSDS/TMFramer/docs/sdd.md +++ b/Svc/CCSDS/TMFramer/docs/sdd.md @@ -6,6 +6,12 @@ It receives payload data (such as a Space Packet or a VCA_SDU) on input and prod The `Svc::CCSDS::TMFramer` is designed to work in the common F Prime telemetry stack, receiving data from an upstream [`Svc::ComQueue`](../../../ComQueue/docs/sdd.md) and passing frames to a [Communications Adapter](../../../Interfaces/docs/sdd.md), such as a Radio manager component or [`Svc::ComStub`](../../../ComStub/docs/sdd.md), for transmission on the wire. It is commonly coupled with the [`Svc::CCSDS::SpacePacketFramer`](../../SpacePacketFramer/docs/sdd.md) to wrap CCSDS Space Packets into TM frames. +## Internals + +The TM protocol specifies a fixed frame size. This can be configured in the `config/ComCfg.fpp` file. + +The `Svc::CCSDS::TMFramer` uses an internal (member) buffer to hold the fixed size frame. The buffer **must** be returned to the TMFramer via the `dataReturnIn` port once it has been used or consumed. When the buffer returns to the TMFramer it will reuse the buffer for the next frame. Should a component want to use the frame data past the time it is returned to the TMFramer, data should be copied before the original buffer is returned to the TMFramer via the `dataReturnIn` port. + ## Usage Examples The `Svc::CCSDS::TMFramer` component, as well as the rest of the CCSDS communications stack, is used in the [`Ref/`](https://github.com/nasa/fprime/tree/devel/Ref) example application. It is also generated by the `fprime-util new --deployment` command. diff --git a/default/config/ComCfg.fpp b/default/config/ComCfg.fpp index a7fc46cb123..4172cb1f74e 100644 --- a/default/config/ComCfg.fpp +++ b/default/config/ComCfg.fpp @@ -28,14 +28,11 @@ module ComCfg { FW_PACKET_IDLE = 0x0006 @< F Prime idle FW_PACKET_HAND = 0x00FE @< F Prime handshake FW_PACKET_UNKNOWN = 0x00FF @< F Prime unknown packet - SPP_FILE_DOWNLINK = 0x0103 @< Extra APID for File packets on downlink so APID isn't shared between uplink and downlink MY_USER_APID_EXAMPLE = 0x0777 @< Example APID for user defined packets SPP_IDLE_PACKET = 0x07FF @< Per Space Packet Standard, all 1s (11bits) is reserved for Idle Packets INVALID_UNINITIALIZED = 0x0800 @< Anything equal or higher value is invalid and should not be used } default INVALID_UNINITIALIZED -# TODO ???: add alias with name ComPacketDescriptor for the ComPacket.hpp - @ Type used to pass context info between components during framing/deframing struct FrameContext { comQueueIndex: FwIndexType @< Queue Index used by the ComQueue, other components shall not modify diff --git a/default/config/FileDownlinkCfg.hpp b/default/config/FileDownlinkCfg.hpp index 01042f42aea..a6a5fe308d7 100644 --- a/default/config/FileDownlinkCfg.hpp +++ b/default/config/FileDownlinkCfg.hpp @@ -20,7 +20,7 @@ namespace Svc { static const bool FILEDOWNLINK_COMMAND_FAILURES_DISABLED = true; // Size of the internal file downlink buffer. This must now be static as // file down maintains its own internal buffer. - static const U32 FILEDOWNLINK_INTERNAL_BUFFER_SIZE = FW_COM_BUFFER_MAX_SIZE; + static const U32 FILEDOWNLINK_INTERNAL_BUFFER_SIZE = FW_FILE_BUFFER_MAX_SIZE; } #endif /* SVC_FILEDOWNLINK_FILEDOWNLINKCFG_HPP_ */ diff --git a/default/config/FpConfig.h b/default/config/FpConfig.h index fa21d8294dc..c22d9df3198 100644 --- a/default/config/FpConfig.h +++ b/default/config/FpConfig.h @@ -244,9 +244,9 @@ typedef enum { #define FW_PARAM_STRING_MAX_SIZE 40 //!< Max size of parameter string type #endif -// Specifies the maximum size of a file upload chunk +// Specifies the maximum size of a file downlink chunk #ifndef FW_FILE_BUFFER_MAX_SIZE -#define FW_FILE_BUFFER_MAX_SIZE 255 //!< Max size of file buffer (i.e. chunk of file) +#define FW_FILE_BUFFER_MAX_SIZE FW_COM_BUFFER_MAX_SIZE //!< Max size of file buffer (i.e. chunk of file) #endif // Specifies the maximum size of a string in an interface call diff --git a/docs/user-manual/framework/configuring-fprime.md b/docs/user-manual/framework/configuring-fprime.md index 239b3d7faf0..98fd816a165 100644 --- a/docs/user-manual/framework/configuring-fprime.md +++ b/docs/user-manual/framework/configuring-fprime.md @@ -331,7 +331,7 @@ are less restrictive in size. | Macro | Definition | Default | Valid Values | | -------------------------- | -----------------------------------------------------------|---------|------------------| -| FW_FILE_BUFFER_MAX_SIZE | Defines buffer and chunk size for file uplink and downlink | 255 | Positive integer | +| FW_FILE_BUFFER_MAX_SIZE | Defines buffer and chunk size for file uplink and downlink | `FW_COM_BUFFER_MAX_SIZE` | Positive integer | | FW_INTERNAL_INTERFACE_STRING_MAX_SIZE | Maximum size for interface string | 40 | Positive integer | ### Text Logging From a7222af0d2d6893fb5e91ebedf6d79857ea536cf Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Fri, 6 Jun 2025 13:34:08 -0700 Subject: [PATCH 80/95] Add fprime-gds.yml to Ref for GDS with framing selection --- Ref/fprime-gds.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Ref/fprime-gds.yml diff --git a/Ref/fprime-gds.yml b/Ref/fprime-gds.yml new file mode 100644 index 00000000000..8733a329b3b --- /dev/null +++ b/Ref/fprime-gds.yml @@ -0,0 +1,3 @@ +command-line-options: + scid: 0x0044 + framing-selection: space-packet-space-data-link From d8547c893f2c653927e8c31ee6d213133e668f23 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Fri, 6 Jun 2025 13:34:44 -0700 Subject: [PATCH 81/95] Update requirements.txt for GDS 4.0.0a3 (CCSDS protocols) --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index db38b7e25a7..8ea4f4e4f10 100644 --- a/requirements.txt +++ b/requirements.txt @@ -35,7 +35,7 @@ fprime-fpp-to-dict==3.0.0a11 fprime-fpp-to-json==3.0.0a11 fprime-fpp-to-xml==3.0.0a11 fprime-fpp-to-layout==3.0.0a11 -fprime-gds==4.0.0a2 +fprime-gds==4.0.0a3 fprime-tools==4.0.0a1 fprime-visual==1.0.2 gcovr==8.2 From f43238a3f89818f1bff7b9275195a74d0b9b6771 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Fri, 6 Jun 2025 15:23:20 -0700 Subject: [PATCH 82/95] Update UTs to reflect last update --- .../SpacePacketDeframer.fpp | 2 +- .../test/ut/SpacePacketDeframerTester.cpp | 5 ++-- .../TCDeframer/test/ut/TCDeframerTester.cpp | 24 ++++++++++--------- Svc/CCSDS/TMFramer/TMFramer.cpp | 4 ---- Svc/CCSDS/TMFramer/TMFramer.hpp | 9 ++++--- .../TMFramer/test/ut/TMFramerTestMain.cpp | 5 ++++ Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp | 23 ++++++++++++++---- Svc/CCSDS/TMFramer/test/ut/TMFramerTester.hpp | 1 + .../CcsdsTCFrameDetectorTestMain.cpp | 2 +- 9 files changed, 49 insertions(+), 26 deletions(-) diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp index 5b922cc2c62..d80bc91d8e1 100644 --- a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp @@ -10,7 +10,7 @@ module CCSDS { @ Deframing received an invalid frame length event InvalidLength(transmitted: U16, actual: U32) \ severity warning high \ - format "Invalid length received. Header specified packet length of {} | Actual received data length: {}" + format "Invalid length received. Header specified packet byte size of {} | Actual received data length: {}" ############################################################################### # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # diff --git a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp index 71abf42a994..47c42a6134c 100644 --- a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp +++ b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp @@ -45,11 +45,12 @@ void SpacePacketDeframerTester ::testNominalDeframing() { U16 seqCount = static_cast(STest::Random::lowerUpper(0, 0x3FFF)); // random 14 bit sequence count U16 dataLength = static_cast(STest::Random::lowerUpper(1, MAX_TEST_PACKET_DATA_SIZE)); // bytes of data, random length U8 data[dataLength]; + U16 lengthToken = static_cast(dataLength - 1); // Length token is length - 1 for (FwIndexType i = 0; i < static_cast(dataLength); ++i) { data[i] = static_cast(i); } - Fw::Buffer buffer = this->assemblePacket(apid, seqCount, dataLength, data, dataLength); + Fw::Buffer buffer = this->assemblePacket(apid, seqCount, lengthToken, data, dataLength); ComCfg::FrameContext nullContext; this->invoke_to_dataIn(0, buffer, nullContext); @@ -92,7 +93,7 @@ void SpacePacketDeframerTester ::testDeframingIncorrectLength() { // Event logging failure ASSERT_EVENTS_SIZE(1); // No events should be generated in the nominal case ASSERT_EVENTS_InvalidLength_SIZE(1); // No events should be generated in the nominal case - ASSERT_EVENTS_InvalidLength(0, invalidLengthToken, realDataLength); + ASSERT_EVENTS_InvalidLength(0, invalidLengthToken + 1, realDataLength); // Event logs the size in bytes, so add 1 to length token } // ---------------------------------------------------------------------- diff --git a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp index 5e6459818ae..fb521bca6f3 100644 --- a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp +++ b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp @@ -42,7 +42,7 @@ void TCDeframerTester::testDataReturn() { } void TCDeframerTester::testNominalDeframing() { - // Frame: 5 bytes (header) + 1 byte (data) + 2 bytes (trailer) + // Frame: 5 bytes (header) + bytes (data) + 2 bytes (trailer) U16 scId = static_cast(STest::Random::lowerUpper(0, 0x3FF)); // random 10 bit Spacecraft ID U8 vcId = static_cast(STest::Random::lowerUpper(0, 0x3F)); // random 6 bit virtual channel ID U8 seqCount = static_cast(STest::Random::lowerUpper(0, 0xFF)); // random 8 bit sequence count @@ -110,10 +110,10 @@ void TCDeframerTester::testInvalidVcId() { void TCDeframerTester::testInvalidLengthToken() { U8 dataLength = static_cast(STest::Random::lowerUpper(1, 200)); // bytes of data, random length U8 data[dataLength]; - U8 fakeLength = 255; // more than max dataLength value + U8 incorrectLengthToken = dataLength + TCHeader::SERIALIZED_SIZE + TCTrailer::SERIALIZED_SIZE + 1; Fw::Buffer buffer = this->assembleFrameBuffer(data, dataLength); - buffer.getData()[3] = fakeLength; // Override length token to invalid value + buffer.getData()[3] = incorrectLengthToken; // Override length token to invalid value ComCfg::FrameContext nullContext; this->setComponentState(); @@ -125,7 +125,8 @@ void TCDeframerTester::testInvalidLengthToken() { ASSERT_EQ(this->fromPortHistory_dataReturnOut->at(0).data.getSize(), buffer.getSize()); ASSERT_EVENTS_SIZE(1); // exactly 1 event emitted ASSERT_EVENTS_InvalidFrameLength_SIZE(1); // event was emitted for invalid frame length - ASSERT_EVENTS_InvalidFrameLength(0, fakeLength, dataLength); + // event logs size in bytes which is length token + 1 + ASSERT_EVENTS_InvalidFrameLength(0, incorrectLengthToken + 1, dataLength + TCHeader::SERIALIZED_SIZE + TCTrailer::SERIALIZED_SIZE); } void TCDeframerTester::testInvalidCrc() { @@ -150,21 +151,22 @@ void TCDeframerTester::testInvalidCrc() { } void TCDeframerTester::setComponentState(U16 scid, U8 vcid, U8 sequenceNumber, bool acceptAllVcid) { - this->component.m_spacecraftId = scid; - this->component.m_vcId = vcid; - // this->component.m_sequenceCount = sequenceNumber; - this->component.m_acceptAllVcid = acceptAllVcid; + this->component.configure(vcid, scid, acceptAllVcid); + // this->component.m_spacecraftId = scid; + // this->component.m_vcId = vcid; + // // this->component.m_sequenceCount = sequenceNumber; + // this->component.m_acceptAllVcid = acceptAllVcid; } Fw::Buffer TCDeframerTester::assembleFrameBuffer(U8* data, U8 dataLength, U16 scid, U8 vcid, U8 seqNumber){ ::memset(this->m_frameData, 0, sizeof(this->m_frameData)); U16 frameLength = static_cast(TCHeader::SERIALIZED_SIZE + dataLength + TCTrailer::SERIALIZED_SIZE); - + U16 frameLengthToken = static_cast(frameLength - 1); // length token is length - 1 // Header this->m_frameData[0] = static_cast(scid >> 8); this->m_frameData[1] = static_cast(scid & 0xFF); - this->m_frameData[2] = static_cast((vcid << 2) | static_cast((dataLength >> 8) & 0x03)); - this->m_frameData[3] = dataLength & 0xFF; + this->m_frameData[2] = static_cast((vcid << 2) | static_cast((frameLengthToken >> 8) & 0x03)); + this->m_frameData[3] = frameLengthToken & 0xFF; this->m_frameData[4] = seqNumber; // Data diff --git a/Svc/CCSDS/TMFramer/TMFramer.cpp b/Svc/CCSDS/TMFramer/TMFramer.cpp index c3d69875242..9ec331ad520 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.cpp +++ b/Svc/CCSDS/TMFramer/TMFramer.cpp @@ -5,10 +5,6 @@ // ====================================================================== #include "Svc/CCSDS/TMFramer/TMFramer.hpp" -#include "Svc/CCSDS/Types/FppConstantsAc.hpp" -#include "Svc/CCSDS/Types/SpacePacketHeaderSerializableAc.hpp" -#include "Svc/CCSDS/Types/TMHeaderSerializableAc.hpp" -#include "Svc/CCSDS/Types/TMTrailerSerializableAc.hpp" #include "Svc/CCSDS/Utils/CRC16.hpp" #include "config/FppConstantsAc.hpp" diff --git a/Svc/CCSDS/TMFramer/TMFramer.hpp b/Svc/CCSDS/TMFramer/TMFramer.hpp index b4c87adadc1..c4e4474ec3f 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.hpp +++ b/Svc/CCSDS/TMFramer/TMFramer.hpp @@ -8,6 +8,10 @@ #define Svc_CCSDS_TMFramer_HPP #include "Svc/CCSDS/TMFramer/TMFramerComponentAc.hpp" +#include "Svc/CCSDS/Types/FppConstantsAc.hpp" +#include "Svc/CCSDS/Types/SpacePacketHeaderSerializableAc.hpp" +#include "Svc/CCSDS/Types/TMHeaderSerializableAc.hpp" +#include "Svc/CCSDS/Types/TMTrailerSerializableAc.hpp" namespace Svc { @@ -91,9 +95,8 @@ class TMFramer final : public TMFramerComponentBase { private: // Because the TM protocol use fixed width frames, and only one frame is in transit between ComQueue and // ComInterface at a time, we can use a member fixed-size buffer to hold the frame data - U8 m_frameBuffer[ComCfg::TmFrameFixedSize]; //!< Buffer to hold the frame data - BufferOwnershipState m_bufferState = - BufferOwnershipState::OWNED; //!< Whether m_frameBuffer is owned by the TMFramer or not + U8 m_frameBuffer[ComCfg::TmFrameFixedSize]; //!< Buffer to hold the frame data + BufferOwnershipState m_bufferState = BufferOwnershipState::OWNED; //!< wheter m_frameBuffer is owned by TMFramer // Current implementation uses a single virtual channel, so we can use a single virtual frame count U8 m_masterFrameCount; //!< Master Frame Count - 8 bits - wraps around at 255 diff --git a/Svc/CCSDS/TMFramer/test/ut/TMFramerTestMain.cpp b/Svc/CCSDS/TMFramer/test/ut/TMFramerTestMain.cpp index 32c934f49b8..ee98a92ee2a 100644 --- a/Svc/CCSDS/TMFramer/test/ut/TMFramerTestMain.cpp +++ b/Svc/CCSDS/TMFramer/test/ut/TMFramerTestMain.cpp @@ -31,6 +31,11 @@ TEST(TMFramer, testInputBufferTooLarge) { tester.testInputBufferTooLarge(); } +TEST(TMFramer, testBufferOwnershipState) { + Svc::CCSDS::TMFramerTester tester; + tester.testBufferOwnershipState(); +} + int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp index 3eb19698c39..6f30d309e95 100644 --- a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp +++ b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp @@ -103,6 +103,7 @@ void TMFramerTester ::testSeqCountWrapAround() { this->component.m_virtualFrameCount = 250; U8 countWrapAround = 250; // will wrap around to 0 after 255 for (U32 iter = 0; iter < 10; iter++) { + this->component.m_bufferState = TMFramer::BufferOwnershipState::OWNED; // reset state to OWNED this->invoke_to_dataIn(0, buffer, defaultContext); ASSERT_from_dataOut_SIZE(iter + 1); Fw::Buffer outBuffer = this->fromPortHistory_dataOut->at(iter).data; @@ -129,12 +130,26 @@ void TMFramerTester ::testDataReturn() { ComCfg::FrameContext defaultContext; // Send a buffer that is not the internal buffer of the component, and expect an assertion ASSERT_DEATH_IF_SUPPORTED(this->invoke_to_dataReturnIn(0, buffer, defaultContext), "TMFramer.cpp"); - - // Now send the expected buffer and expect it to be cleared - this->component.m_frameBuffer[0] = 0xFF; // Set some data in the internal buffer + + // Now send the expected buffer and expect state to go back to OWNED + this->component.m_bufferState = TMFramer::BufferOwnershipState::NOT_OWNED; Fw::Buffer internalBuffer(this->component.m_frameBuffer, sizeof(this->component.m_frameBuffer)); this->invoke_to_dataReturnIn(0, internalBuffer, defaultContext); - ASSERT_EQ(this->component.m_frameBuffer[0], 0x00); // data should have been cleared + ASSERT_EQ(this->component.m_bufferState, TMFramer::BufferOwnershipState::OWNED); + +} + +void TMFramerTester ::testBufferOwnershipState() { + U8 bufferData[10]; + Fw::Buffer buffer(bufferData, sizeof(bufferData)); + ComCfg::FrameContext context; + // force state to be NOT_OWNED and test that assertion is triggered + this->component.m_bufferState = TMFramer::BufferOwnershipState::NOT_OWNED; + ASSERT_DEATH_IF_SUPPORTED(this->invoke_to_dataIn(0, buffer, context), "TMFramer.cpp"); + this->component.m_bufferState = TMFramer::BufferOwnershipState::OWNED; + this->invoke_to_dataIn(0, buffer, context); // this should work now + ASSERT_EQ(this->component.m_bufferState, TMFramer::BufferOwnershipState::NOT_OWNED); + } // ---------------------------------------------------------------------- diff --git a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.hpp b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.hpp index 1d145deaba5..21925c9defb 100644 --- a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.hpp +++ b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.hpp @@ -47,6 +47,7 @@ class TMFramerTester final : public TMFramerGTestBase { void testSeqCountWrapAround(); void testInputBufferTooLarge(); void testDataReturn(); + void testBufferOwnershipState(); private: // ---------------------------------------------------------------------- diff --git a/Svc/FrameAccumulator/test/ut/detectors/CcsdsTCFrameDetectorTestMain.cpp b/Svc/FrameAccumulator/test/ut/detectors/CcsdsTCFrameDetectorTestMain.cpp index 71022304984..dff15dc22d5 100644 --- a/Svc/FrameAccumulator/test/ut/detectors/CcsdsTCFrameDetectorTestMain.cpp +++ b/Svc/FrameAccumulator/test/ut/detectors/CcsdsTCFrameDetectorTestMain.cpp @@ -51,7 +51,7 @@ FwSizeType generate_random_tc_frame(Types::CircularBuffer& circular_buffer) { } TCHeader tcHeader( EXPECTED_START_TOKEN, // Use a predefined token for flags and SC ID - static_cast(packet_size), // Length (and unused VcId) + static_cast(total_frame_size - 1), // Length (and unused VcId) static_cast(STest::Random::lowerUpper(0, 255)) // Random frame sequence number ); From a08101b6161ac2f373ae5ee9a9e99440dbb088aa Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Fri, 6 Jun 2025 15:30:19 -0700 Subject: [PATCH 83/95] Drop Python 3.8 support --- .github/workflows/pip-check.yml | 2 +- .github/workflows/python-format.yml | 4 ++-- README.md | 2 +- docs/getting-started/installing-fprime.md | 2 +- requirements.txt | 3 +-- 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/pip-check.yml b/.github/workflows/pip-check.yml index 583ef2fdd9f..81d6d1e06eb 100644 --- a/.github/workflows/pip-check.yml +++ b/.github/workflows/pip-check.yml @@ -16,7 +16,7 @@ jobs: runs-on: ${{ matrix.runner }} strategy: matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] # macos-13 is the last Intel-family runner; macos-latest is ARM runner: [macos-13, macos-latest, ubuntu-22.04, ubuntu-latest] steps: diff --git a/.github/workflows/python-format.yml b/.github/workflows/python-format.yml index c3492856804..fe076f6dd3c 100644 --- a/.github/workflows/python-format.yml +++ b/.github/workflows/python-format.yml @@ -13,10 +13,10 @@ jobs: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - - name: Setup Python 3.8 + - name: Setup Python 3.11 uses: actions/setup-python@v5 with: - python-version: 3.8 + python-version: 3.11 - name: Check formatting run: | pip install click==8.0.4 black==21.6b0 diff --git a/README.md b/README.md index 3bc921e9497..67485d7e6b3 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Learn more about [F´ key features](https://fprime.jpl.nasa.gov/overview). 1. Linux, Windows with WSL, or macOS operating system 2. [git](https://git-scm.com/) 3. [Clang](https://clang.llvm.org/) or [GNU C and C++ compilers](https://gcc.gnu.org/) (e.g. gcc and g++) -4. [Python 3.8+](https://www.python.org/downloads/), [virtual environments](https://docs.python.org/3/library/venv.html), and [PIP](https://pypi.org/project/pip/) +4. [Python 3.9+](https://www.python.org/downloads/), [virtual environments](https://docs.python.org/3/library/venv.html), and [PIP](https://pypi.org/project/pip/) ## Getting Started diff --git a/docs/getting-started/installing-fprime.md b/docs/getting-started/installing-fprime.md index 2a8593cced7..64eb78504c6 100644 --- a/docs/getting-started/installing-fprime.md +++ b/docs/getting-started/installing-fprime.md @@ -24,7 +24,7 @@ Requirements: 1. Linux, macOS, or WSL on Windows 2. git 3. CLang or GNU C and C++ compilers (e.g. gcc and g++) -4. [Python 3.8+](https://www.python.org/downloads/), virtual environments, and PIP +4. [Python 3.9+](https://www.python.org/downloads/), virtual environments, and PIP > [!NOTE] > Latest versions of PIP are strongly recommended. See [Recommended PIP Versions](#recommended-pip-versions) diff --git a/requirements.txt b/requirements.txt index 8ea4f4e4f10..1b26a9d0c27 100644 --- a/requirements.txt +++ b/requirements.txt @@ -68,8 +68,7 @@ PyYAML==6.0.2 pyzmq==26.2.0 requests==2.32.3 rich==13.9.2 -setuptools==78.1.1; python_version > "3.8" -setuptools==75.3.2; python_version <= "3.8" +setuptools==78.1.1 six==1.16.0 text-unidecode==1.3 tomli==2.0.1 From 0ed2a42d04290de480080fd847178588f4429f16 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Fri, 6 Jun 2025 15:33:13 -0700 Subject: [PATCH 84/95] Update FprimeRouter UTs for new APID routing --- Svc/FprimeRouter/test/ut/FprimeRouterTester.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Svc/FprimeRouter/test/ut/FprimeRouterTester.cpp b/Svc/FprimeRouter/test/ut/FprimeRouterTester.cpp index 857bdcf6c54..c8b0f5c3bf6 100644 --- a/Svc/FprimeRouter/test/ut/FprimeRouterTester.cpp +++ b/Svc/FprimeRouter/test/ut/FprimeRouterTester.cpp @@ -89,10 +89,9 @@ void FprimeRouterTester::mockReceivePacketType(Fw::ComPacketType packetType) { const FwPacketDescriptorType descriptorType = packetType; U8 data[sizeof descriptorType]; Fw::Buffer buffer(data, sizeof(data)); - ComCfg::FrameContext nullContext; - Fw::SerializeStatus status = buffer.getSerializer().serialize(descriptorType); - FW_ASSERT(status == Fw::FW_SERIALIZE_OK); - this->invoke_to_dataIn(0, buffer, nullContext); + ComCfg::FrameContext context; + context.setapid(static_cast(descriptorType)); + this->invoke_to_dataIn(0, buffer, context); } void FprimeRouterTester::connectPortsExceptUnknownData() { From ad58c750e55dad1e09ade9b6a2f971a1ecff47d7 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Fri, 6 Jun 2025 15:59:12 -0700 Subject: [PATCH 85/95] Fix spelling and RHEL8 cast warnings --- Svc/CCSDS/ApidManager/ApidManager.cpp | 2 +- Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp | 2 +- .../test/ut/SpacePacketDeframerTester.cpp | 2 +- Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp | 6 +++--- Svc/CCSDS/TMFramer/TMFramer.cpp | 2 +- Svc/CCSDS/TMFramer/TMFramer.hpp | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Svc/CCSDS/ApidManager/ApidManager.cpp b/Svc/CCSDS/ApidManager/ApidManager.cpp index df049f7e683..96840d340ea 100644 --- a/Svc/CCSDS/ApidManager/ApidManager.cpp +++ b/Svc/CCSDS/ApidManager/ApidManager.cpp @@ -69,7 +69,7 @@ void ApidManager::setNextSeqCount(ComCfg::APID::T apid, U16 seqCount) { return; } } - // This code should not be reahcable with the if statement in validateApidSeqCountIn_handler + // This code should not be reachable with the if statement in validateApidSeqCountIn_handler FW_ASSERT(false, static_cast(apid)); } diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp index 0cde8c0c556..7c676cd69a5 100644 --- a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.cpp @@ -48,7 +48,7 @@ void SpacePacketDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, // Space Packet protocol defines the Data Length as number of bytes minus 1 // so we need to add 1 to the length to get the actual data size - U16 pkt_length = header.getpacketDataLength() + 1; + U16 pkt_length = static_cast(header.getpacketDataLength() + 1); if (pkt_length > data.getSize() - SpacePacketHeader::SERIALIZED_SIZE) { U32 maxDataAvailable = data.getSize() - SpacePacketHeader::SERIALIZED_SIZE; this->log_WARNING_HI_InvalidLength(pkt_length, maxDataAvailable); diff --git a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp index 47c42a6134c..940361137ab 100644 --- a/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp +++ b/Svc/CCSDS/SpacePacketDeframer/test/ut/SpacePacketDeframerTester.cpp @@ -93,7 +93,7 @@ void SpacePacketDeframerTester ::testDeframingIncorrectLength() { // Event logging failure ASSERT_EVENTS_SIZE(1); // No events should be generated in the nominal case ASSERT_EVENTS_InvalidLength_SIZE(1); // No events should be generated in the nominal case - ASSERT_EVENTS_InvalidLength(0, invalidLengthToken + 1, realDataLength); // Event logs the size in bytes, so add 1 to length token + ASSERT_EVENTS_InvalidLength(0, static_cast(invalidLengthToken + 1), realDataLength); // Event logs the size in bytes, so add 1 to length token } // ---------------------------------------------------------------------- diff --git a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp index fb521bca6f3..a129778a247 100644 --- a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp +++ b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp @@ -110,7 +110,7 @@ void TCDeframerTester::testInvalidVcId() { void TCDeframerTester::testInvalidLengthToken() { U8 dataLength = static_cast(STest::Random::lowerUpper(1, 200)); // bytes of data, random length U8 data[dataLength]; - U8 incorrectLengthToken = dataLength + TCHeader::SERIALIZED_SIZE + TCTrailer::SERIALIZED_SIZE + 1; + U8 incorrectLengthToken = static_cast(dataLength + TCHeader::SERIALIZED_SIZE + TCTrailer::SERIALIZED_SIZE + 1); Fw::Buffer buffer = this->assembleFrameBuffer(data, dataLength); buffer.getData()[3] = incorrectLengthToken; // Override length token to invalid value @@ -126,7 +126,7 @@ void TCDeframerTester::testInvalidLengthToken() { ASSERT_EVENTS_SIZE(1); // exactly 1 event emitted ASSERT_EVENTS_InvalidFrameLength_SIZE(1); // event was emitted for invalid frame length // event logs size in bytes which is length token + 1 - ASSERT_EVENTS_InvalidFrameLength(0, incorrectLengthToken + 1, dataLength + TCHeader::SERIALIZED_SIZE + TCTrailer::SERIALIZED_SIZE); + ASSERT_EVENTS_InvalidFrameLength(0, static_cast(incorrectLengthToken + 1), static_cast(dataLength + TCHeader::SERIALIZED_SIZE + TCTrailer::SERIALIZED_SIZE)); } void TCDeframerTester::testInvalidCrc() { @@ -166,7 +166,7 @@ Fw::Buffer TCDeframerTester::assembleFrameBuffer(U8* data, U8 dataLength, U16 sc this->m_frameData[0] = static_cast(scid >> 8); this->m_frameData[1] = static_cast(scid & 0xFF); this->m_frameData[2] = static_cast((vcid << 2) | static_cast((frameLengthToken >> 8) & 0x03)); - this->m_frameData[3] = frameLengthToken & 0xFF; + this->m_frameData[3] = static_cast(frameLengthToken & 0xFF); this->m_frameData[4] = seqNumber; // Data diff --git a/Svc/CCSDS/TMFramer/TMFramer.cpp b/Svc/CCSDS/TMFramer/TMFramer.cpp index 9ec331ad520..edb6cbbbf82 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.cpp +++ b/Svc/CCSDS/TMFramer/TMFramer.cpp @@ -47,7 +47,7 @@ void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComC // - all flags to 0 except segment length id 0b11 per standard (4.1.2.7) // - First Header Pointer is always 0 since we are always wrapping a single entire packet at offset 0 U16 dataFieldStatus = 0; - dataFieldStatus |= 0x3 << TMSubfields::segLengthOffset; // Seg Length Id 0b11 per Standard (4.1.2.7.5) + dataFieldStatus |= 0x3 << TMSubfields::segLengthOffset; // Seg Length Id '11' (0x3) per Standard (4.1.2.7.5) header.setglobalVcId(globalVcId); header.setmasterFrameCount(this->m_masterFrameCount); diff --git a/Svc/CCSDS/TMFramer/TMFramer.hpp b/Svc/CCSDS/TMFramer/TMFramer.hpp index c4e4474ec3f..b65f997a1ec 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.hpp +++ b/Svc/CCSDS/TMFramer/TMFramer.hpp @@ -96,7 +96,7 @@ class TMFramer final : public TMFramerComponentBase { // Because the TM protocol use fixed width frames, and only one frame is in transit between ComQueue and // ComInterface at a time, we can use a member fixed-size buffer to hold the frame data U8 m_frameBuffer[ComCfg::TmFrameFixedSize]; //!< Buffer to hold the frame data - BufferOwnershipState m_bufferState = BufferOwnershipState::OWNED; //!< wheter m_frameBuffer is owned by TMFramer + BufferOwnershipState m_bufferState = BufferOwnershipState::OWNED; //!< whether m_frameBuffer is owned by TMFramer // Current implementation uses a single virtual channel, so we can use a single virtual frame count U8 m_masterFrameCount; //!< Master Frame Count - 8 bits - wraps around at 255 From a0d78ed220044e7922cae958ac3327546b77d901 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Fri, 6 Jun 2025 16:04:10 -0700 Subject: [PATCH 86/95] Fix spelling again... --- Svc/CCSDS/TMFramer/TMFramer.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Svc/CCSDS/TMFramer/TMFramer.hpp b/Svc/CCSDS/TMFramer/TMFramer.hpp index b65f997a1ec..dd540ce1e96 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.hpp +++ b/Svc/CCSDS/TMFramer/TMFramer.hpp @@ -22,7 +22,7 @@ class TMFramer final : public TMFramerComponentBase { static_assert(ComCfg::TmFrameFixedSize > TMHeader::SERIALIZED_SIZE + TMTrailer::SERIALIZED_SIZE, "TM Frame Fixed Size must be at least large enough to hold header, trailer and data"); - // These are to ensure the frame can hold the the packet buffer, its SP header and an idle packet of 1 byte + // These are to ensure the frame can hold the packet buffer, its SP header and an idle packet of 1 byte // This is because TM specifies a frame to be padded with an idle packet of at least 1 byte of idle data static_assert( ComCfg::TmFrameFixedSize >= FW_COM_BUFFER_MAX_SIZE + (2 * SpacePacketHeader::SERIALIZED_SIZE) + 1, From c4261bf2950e4af263332191454eb6cb9cb778b5 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Fri, 6 Jun 2025 17:22:31 -0700 Subject: [PATCH 87/95] Deserialize APID in FprimeDeframer only if it is valid --- Svc/FprimeDeframer/FprimeDeframer.cpp | 11 ++++++++--- .../test/ut/FprimeDeframerTestMain.cpp | 5 +++++ .../test/ut/FprimeDeframerTester.cpp | 19 ++++++++++++++++++- .../test/ut/FprimeDeframerTester.hpp | 3 +++ default/config/ComCfg.fpp | 1 - 5 files changed, 34 insertions(+), 5 deletions(-) diff --git a/Svc/FprimeDeframer/FprimeDeframer.cpp b/Svc/FprimeDeframer/FprimeDeframer.cpp index 20a5dd0e0cc..3315a4c49d4 100644 --- a/Svc/FprimeDeframer/FprimeDeframer.cpp +++ b/Svc/FprimeDeframer/FprimeDeframer.cpp @@ -57,12 +57,17 @@ void FprimeDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, cons this->dataReturnOut_out(0, data, context); // drop the frame return; } - // Extract packet descriptor from the packet data to set the APID for the Router + // -------- Attempt to extract APID from Payload -------- + // If PacketDescriptor translates to an invalid APID, let it default to FW_PACKET_UNKNOWN + // and let downstream components (e.g. custom router) handle it FwPacketDescriptorType packetDescriptor; status = deserializer.deserialize(packetDescriptor); FW_ASSERT(status == Fw::SerializeStatus::FW_SERIALIZE_OK, status); ComCfg::FrameContext contextCopy = context; - contextCopy.setapid(static_cast(packetDescriptor)); + // If a valid descriptor is deserialized, set it in the context + if (packetDescriptor < ComCfg::APID::INVALID_UNINITIALIZED) { + contextCopy.setapid(static_cast(packetDescriptor)); + } // ---------------- Validate Frame Trailer ---------------- // Deserialize transmitted trailer: trailer is at offset = len(header) + len(body) @@ -94,7 +99,7 @@ void FprimeDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, cons data.setSize(data.getSize() - FprimeProtocol::FrameHeader::SERIALIZED_SIZE - FprimeProtocol::FrameTrailer::SERIALIZED_SIZE); // Emit the deframed data - this->dataOut_out(0, data, context); + this->dataOut_out(0, data, contextCopy); } void FprimeDeframer ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer, const ComCfg::FrameContext& context) { diff --git a/Svc/FprimeDeframer/test/ut/FprimeDeframerTestMain.cpp b/Svc/FprimeDeframer/test/ut/FprimeDeframerTestMain.cpp index ccf09fce2c0..ac2efce5bef 100644 --- a/Svc/FprimeDeframer/test/ut/FprimeDeframerTestMain.cpp +++ b/Svc/FprimeDeframer/test/ut/FprimeDeframerTestMain.cpp @@ -12,6 +12,11 @@ TEST(FprimeDeframer, NominalFrame) { tester.testNominalFrame(); } +TEST(FprimeDeframer, NominalFrameApid) { + Svc::FprimeDeframerTester tester; + tester.testNominalFrameApid(); +} + TEST(FprimeDeframer, TruncatedFrame) { Svc::FprimeDeframerTester tester; tester.testTruncatedFrame(); diff --git a/Svc/FprimeDeframer/test/ut/FprimeDeframerTester.cpp b/Svc/FprimeDeframer/test/ut/FprimeDeframerTester.cpp index a745bbb78c8..ef6e6b5e52c 100644 --- a/Svc/FprimeDeframer/test/ut/FprimeDeframerTester.cpp +++ b/Svc/FprimeDeframer/test/ut/FprimeDeframerTester.cpp @@ -27,7 +27,7 @@ FprimeDeframerTester ::~FprimeDeframerTester() {} void FprimeDeframerTester ::testNominalFrame() { // Get random byte of data - U8 randomByte = static_cast(STest::Random::lowerUpper(0, 255)); + U8 randomByte = static_cast(STest::Random::lowerUpper(1, 255)); // | F´ start word | Length (= 1) | Data | Checksum (4 bytes) | U8 data[13] = {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x00, 0x00, 0x01, randomByte, 0x00, 0x00, 0x00, 0x00}; // Inject the checksum into the data and send it to the component under test @@ -38,6 +38,23 @@ void FprimeDeframerTester ::testNominalFrame() { ASSERT_from_dataReturnOut_SIZE(0); // nothing emitted on dataReturnOut // Assert that the data that was emitted on dataOut is equal to Data field above (randomByte) ASSERT_EQ(this->fromPortHistory_dataOut->at(0).data.getData()[0], randomByte); + // Not enough data to read a valid APID -> should default to FW_PACKET_UNKNOWN + ASSERT_EQ(this->fromPortHistory_dataOut->at(0).context.getapid(), ComCfg::APID::FW_PACKET_UNKNOWN); + ASSERT_EVENTS_SIZE(0); // no events emitted +} + +void FprimeDeframerTester ::testNominalFrameApid() { + // Get random byte of data which represents the APID (PacketDescriptor) + U8 randomByte = static_cast(STest::Random::lowerUpper(0, 255)); + // | F´ start word | Length (= 4) | PacketDescriptor (APID) | Checksum (4 bytes) | + U8 data[16] = {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, randomByte, 0x00, 0x00, 0x00, 0x00}; + // Inject the checksum into the data and send it to the component under test + this->injectChecksum(data, sizeof(data)); + this->mockReceiveData(data, sizeof(data)); + + ASSERT_from_dataOut_SIZE(1); // something emitted on dataOut + ASSERT_from_dataReturnOut_SIZE(0); // nothing emitted on dataReturnOut + ASSERT_EQ(this->fromPortHistory_dataOut->at(0).context.getapid(), randomByte); // APID should be set in context ASSERT_EVENTS_SIZE(0); // no events emitted } diff --git a/Svc/FprimeDeframer/test/ut/FprimeDeframerTester.hpp b/Svc/FprimeDeframer/test/ut/FprimeDeframerTester.hpp index 6818bbdf2a5..add45c66911 100644 --- a/Svc/FprimeDeframer/test/ut/FprimeDeframerTester.hpp +++ b/Svc/FprimeDeframer/test/ut/FprimeDeframerTester.hpp @@ -43,6 +43,9 @@ class FprimeDeframerTester : public FprimeDeframerGTestBase { //! Test receiving a nominal frame void testNominalFrame(); + //! Test receiving a nominal frame that contains a valid packet (with APID) + void testNominalFrameApid(); + //! Test receiving a truncated frame void testTruncatedFrame(); diff --git a/default/config/ComCfg.fpp b/default/config/ComCfg.fpp index 4172cb1f74e..2954d98d9f6 100644 --- a/default/config/ComCfg.fpp +++ b/default/config/ComCfg.fpp @@ -28,7 +28,6 @@ module ComCfg { FW_PACKET_IDLE = 0x0006 @< F Prime idle FW_PACKET_HAND = 0x00FE @< F Prime handshake FW_PACKET_UNKNOWN = 0x00FF @< F Prime unknown packet - MY_USER_APID_EXAMPLE = 0x0777 @< Example APID for user defined packets SPP_IDLE_PACKET = 0x07FF @< Per Space Packet Standard, all 1s (11bits) is reserved for Idle Packets INVALID_UNINITIALIZED = 0x0800 @< Anything equal or higher value is invalid and should not be used } default INVALID_UNINITIALIZED From b3c12839ff262d2adabc8966d930e25e4dabc29e Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Fri, 6 Jun 2025 17:59:29 -0700 Subject: [PATCH 88/95] Fix googletest warning?? --- Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp index a129778a247..4da0409099b 100644 --- a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp +++ b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp @@ -31,7 +31,7 @@ TCDeframerTester ::~TCDeframerTester() {} // ---------------------------------------------------------------------- void TCDeframerTester::testDataReturn() { - U8 data[1]; + U8 data[1] = {0}; Fw::Buffer buffer(data, sizeof(data)); ComCfg::FrameContext nullContext; this->invoke_to_dataReturnIn(0, buffer, nullContext); @@ -48,6 +48,9 @@ void TCDeframerTester::testNominalDeframing() { U8 seqCount = static_cast(STest::Random::lowerUpper(0, 0xFF)); // random 8 bit sequence count U8 dataLength = static_cast(STest::Random::lowerUpper(1, 200)); // bytes of data, random length U8 data[dataLength]; + for (FwIndexType i = 0; i < dataLength; i++) { + data[i] = i % std::numeric_limits::max(); + } Fw::Buffer buffer = this->assembleFrameBuffer(data, dataLength, scId, vcId, seqCount); ComCfg::FrameContext nullContext; From 052779efabea704a2787c173378d4c69172437cb Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Fri, 6 Jun 2025 18:08:29 -0700 Subject: [PATCH 89/95] static casting that u8 yall --- .../TCDeframer/test/ut/TCDeframerTester.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp index 4da0409099b..9c855e665c2 100644 --- a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp +++ b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp @@ -46,13 +46,14 @@ void TCDeframerTester::testNominalDeframing() { U16 scId = static_cast(STest::Random::lowerUpper(0, 0x3FF)); // random 10 bit Spacecraft ID U8 vcId = static_cast(STest::Random::lowerUpper(0, 0x3F)); // random 6 bit virtual channel ID U8 seqCount = static_cast(STest::Random::lowerUpper(0, 0xFF)); // random 8 bit sequence count - U8 dataLength = static_cast(STest::Random::lowerUpper(1, 200)); // bytes of data, random length - U8 data[dataLength]; - for (FwIndexType i = 0; i < dataLength; i++) { - data[i] = i % std::numeric_limits::max(); + U8 payloadLength = static_cast(STest::Random::lowerUpper(1, 200)); // bytes of data, random length + U8 payload[payloadLength]; + // Initialize payload with some data + for (FwIndexType i = 0; i < payloadLength; i++) { + payload[i] = static_cast(i % std::numeric_limits::max()); } - Fw::Buffer buffer = this->assembleFrameBuffer(data, dataLength, scId, vcId, seqCount); + Fw::Buffer buffer = this->assembleFrameBuffer(payload, payloadLength, scId, vcId, seqCount); ComCfg::FrameContext nullContext; this->setComponentState(scId, vcId, seqCount); @@ -60,9 +61,9 @@ void TCDeframerTester::testNominalDeframing() { ASSERT_from_dataOut_SIZE(1); Fw::Buffer outBuffer = this->fromPortHistory_dataOut->at(0).data; - ASSERT_EQ(outBuffer.getSize(), dataLength); - for (FwIndexType i = 0; i < dataLength; i++) { - ASSERT_EQ(outBuffer.getData()[i], data[i]); + ASSERT_EQ(outBuffer.getSize(), payloadLength); + for (FwIndexType i = 0; i < payloadLength; i++) { + ASSERT_EQ(outBuffer.getData()[i], payload[i]); } } From cb33f680fdee3c9db98a619c7964a550fe419e2a Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Tue, 10 Jun 2025 13:40:09 -0700 Subject: [PATCH 90/95] Use width FPP constants --- Svc/CCSDS/ApidManager/ApidManager.cpp | 19 ++++++++++++------- .../ApidManager/test/ut/ApidManagerTester.cpp | 7 ++++--- .../SpacePacketFramer/SpacePacketFramer.cpp | 2 +- Svc/CCSDS/Types/Types.fpp | 3 +++ 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/Svc/CCSDS/ApidManager/ApidManager.cpp b/Svc/CCSDS/ApidManager/ApidManager.cpp index 96840d340ea..0ab0cfe5324 100644 --- a/Svc/CCSDS/ApidManager/ApidManager.cpp +++ b/Svc/CCSDS/ApidManager/ApidManager.cpp @@ -5,6 +5,7 @@ // ====================================================================== #include "Svc/CCSDS/ApidManager/ApidManager.hpp" +#include "Svc/CCSDS/Types/FppConstantsAc.hpp" namespace Svc { @@ -40,22 +41,26 @@ U16 ApidManager ::getApidSeqCountIn_handler(FwIndexType portNum, const ComCfg::A // ---------------------------------------------------------------------- U16 ApidManager ::getAndIncrementSeqCount(ComCfg::APID::T apid) { - U16 seqCount = SEQUENCE_COUNT_ERROR; // Default to error value + U16 seqCount = SEQUENCE_COUNT_ERROR; // Default to error value // Search the APID in the sequence table for (U16 i = 0; i < MAX_TRACKED_APIDS; i++) { if (this->m_apidSequences[i].apid == apid) { seqCount = this->m_apidSequences[i].sequenceCount; - this->m_apidSequences[i].sequenceCount = static_cast((seqCount + 1) % (1 << 14)); // Increment for next call - return seqCount; // Return the current sequence count + // Increment entry for next call + this->m_apidSequences[i].sequenceCount = + static_cast((seqCount + 1) % (1 << SpacePacketSubfields::SeqCountWidth)); + return seqCount; // Return the current sequence count } } // If not found, search for an uninitialized entry to track this APID for (U16 i = 0; i < MAX_TRACKED_APIDS; i++) { if (this->m_apidSequences[i].apid == ComCfg::APID::INVALID_UNINITIALIZED) { - this->m_apidSequences[i].apid = apid; // Initialize this entry with the new APID - seqCount = this->m_apidSequences[i].sequenceCount; // Entries default to 0 unless otherwise specified - this->m_apidSequences[i].sequenceCount = static_cast((seqCount + 1) % (1 << 14)); // Increment for next call - return seqCount; // Return the initialized sequence count + this->m_apidSequences[i].apid = apid; // Initialize this entry with the new APID + seqCount = this->m_apidSequences[i].sequenceCount; // Entries default to 0 unless otherwise specified + // Increment entry for next call + this->m_apidSequences[i].sequenceCount = + static_cast((seqCount + 1) % (1 << SpacePacketSubfields::SeqCountWidth)); + return seqCount; // Return the initialized sequence count } } this->log_WARNING_HI_ApidTableFull(apid); diff --git a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp index e4f76d4b406..dc80b1495bb 100644 --- a/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp +++ b/Svc/CCSDS/ApidManager/test/ut/ApidManagerTester.cpp @@ -6,6 +6,7 @@ #include "ApidManagerTester.hpp" #include "STest/Random/Random.hpp" +#include "Svc/CCSDS/Types/FppConstantsAc.hpp" namespace Svc { @@ -115,7 +116,7 @@ void ApidManagerTester::ValidateSeqCountFailure::action(ApidManagerTester& teste testerState.clearHistory(); ComCfg::APID::T apid = testerState.shadow_getRandomTrackedApid(); U16 shadow_expectedSeqCount = testerState.shadow_seqCounts.at(apid); - U16 invalidSeqCount = static_cast((shadow_expectedSeqCount + 1) % (1 << 14)); // Or any other value that's different, ensure wrap around + U16 invalidSeqCount = static_cast((shadow_expectedSeqCount + 1) % (1 << SpacePacketSubfields::SeqCountWidth)); // Or any other value that's different, ensure wrap around // Invoke the port with the deliberately incorrect sequence count testerState.invoke_to_validateApidSeqCountIn(0, apid, invalidSeqCount); @@ -137,7 +138,7 @@ U16 ApidManagerTester::shadow_getAndIncrementSeqCount(ComCfg::APID::T apid) { auto found = this->shadow_seqCounts.find(apid); if (found != this->shadow_seqCounts.end()) { U16 seqCount = found->second; - found->second = static_cast((seqCount + 1) % (1 << 14)); // Increment for next call + found->second = static_cast((seqCount + 1) % (1 << SpacePacketSubfields::SeqCountWidth)); // Increment for next call return seqCount; // Return the current sequence count } // If APID not found, initialize a new entry @@ -153,7 +154,7 @@ void ApidManagerTester::shadow_validateApidSeqCount(ComCfg::APID::T apid, U16 ex // This simply updates the shadow state to the next expected sequence count auto found = this->shadow_seqCounts.find(apid); if (found != this->shadow_seqCounts.end()) { - found->second = static_cast((expectedSeqCount + 1) % (1 << 14)); + found->second = static_cast((expectedSeqCount + 1) % (1 << SpacePacketSubfields::SeqCountWidth)); } } diff --git a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp index c03054ba12a..d2aa3828728 100644 --- a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp +++ b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.cpp @@ -40,7 +40,7 @@ void SpacePacketFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, c // PVN is always 0 per Standard - Packet Type is 0 for Telemetry (downlink) - SecHdr flag is 0 for no secondary header U16 packetIdentification = 0; ComCfg::APID::T apid = context.getapid(); - FW_ASSERT((apid >> 11) == 0, static_cast(apid)); // apid must fit in 11 bits + FW_ASSERT((apid >> SpacePacketSubfields::ApidWidth) == 0, static_cast(apid)); // apid must fit in 11 bits packetIdentification |= static_cast(apid) & SpacePacketSubfields::ApidMask; // 11 bit APID U16 sequenceCount = this->getApidSeqCount_out(0, apid, 0); // retrieve the sequence count for this APID diff --git a/Svc/CCSDS/Types/Types.fpp b/Svc/CCSDS/Types/Types.fpp index f0b4e94b6bc..3dbd827a345 100644 --- a/Svc/CCSDS/Types/Types.fpp +++ b/Svc/CCSDS/Types/Types.fpp @@ -28,6 +28,9 @@ module CCSDS { constant SeqFlagsMask = 0xC000 @< 0b1100000000000000 constant SeqCountMask = 0x3FFF @< 0b0011111111111111 constant SeqFlagsOffset = 14 + # Widths + constant ApidWidth = 11 + constant SeqCountWidth = 14 } # ------------------------------------------------ From 586d07cab61ef2feeec9bd1101fcda90b1d777ad Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Tue, 10 Jun 2025 13:46:37 -0700 Subject: [PATCH 91/95] Add SDD links --- Svc/CCSDS/ApidManager/docs/sdd.md | 4 ++-- Svc/CCSDS/TCDeframer/docs/sdd.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Svc/CCSDS/ApidManager/docs/sdd.md b/Svc/CCSDS/ApidManager/docs/sdd.md index 5f5bd86cf4f..1beba09d5c6 100644 --- a/Svc/CCSDS/ApidManager/docs/sdd.md +++ b/Svc/CCSDS/ApidManager/docs/sdd.md @@ -2,7 +2,7 @@ The `Svc::CCSDS::ApidManager` component manages CCSDS Application Process Identifier (APID) sequence counts for the F Prime communications stack. It provides per-APID sequence count tracking and validation, supporting the construction and checking of CCSDS Space Packet headers by other components (such as `SpacePacketFramer` and `SpacePacketDeframer`). -The `ApidManager` is typically used in conjunction with the `SpacePacketFramer` (to provide incrementing sequence counts for each APID) and the `SpacePacketDeframer` (to validate received sequence counts and detect dropped or out-of-order packets). +The `ApidManager` is typically used in conjunction with the [`SpacePacketFramer`](../../SpacePacketFramer/docs/sdd.md) (to provide incrementing sequence counts for each APID) and the [`SpacePacketDeframer`](../../SpacePacketDeframer/docs/sdd.md) (to validate received sequence counts and detect dropped or out-of-order packets). ## Functionality @@ -22,7 +22,7 @@ The `ApidManager` is typically used in conjunction with the `SpacePacketFramer` | Name | Severity | Description | |------------------------|---------------|-----------------------------------------------------------------------------| -| UnexpectedSequenceCount| warning high | Received an unexpected sequence count for an APID. | +| UnexpectedSequenceCount| warning low | Received an unexpected sequence count for an APID. | | ApidTableFull | warning high | APID table is full; cannot track additional APIDs. | ## Usage diff --git a/Svc/CCSDS/TCDeframer/docs/sdd.md b/Svc/CCSDS/TCDeframer/docs/sdd.md index 62633ef77e1..d4ac2e820af 100644 --- a/Svc/CCSDS/TCDeframer/docs/sdd.md +++ b/Svc/CCSDS/TCDeframer/docs/sdd.md @@ -1,4 +1,4 @@ -# Svc::TCDeframer +# Svc::CCSDS::TCDeframer The `Svc::CCSDS::TCDeframer` is an implementation of the [DeframerInterface](../../../Interfaces/docs/sdd.md) for the CCSDS [TC Space Data Link Protocol](https://ccsds.org/Pubs/232x0b4e1c1.pdf). @@ -33,7 +33,7 @@ void configure(U16 vcId, U16 spacecraftId, bool acceptAllVcid); | Name | Severity | Description | |---|---|---| -| InvalidSpacecraftId | `activity low` | Deframing received an invalid SCID | +| InvalidSpacecraftId | `warning low` | Deframing received an invalid SCID | | InvalidFrameLength | `warning high` | Deframing received an invalid frame length | | InvalidVcId | `activity low` | Deframing received an invalid VCID | | InvalidCrc | `warning high` | Deframing received an invalid checksum | From 7119eb0304bb70188961181aa5a6de2103d09d0c Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Tue, 10 Jun 2025 14:00:36 -0700 Subject: [PATCH 92/95] Switch TMFramer/TCDeframer capitalization to TmFramer/TcDeframer --- Ref/Top/RefTopology.cpp | 4 +- Ref/Top/instances.fpp | 4 +- Ref/Top/topology.fpp | 4 +- Svc/CCSDS/CMakeLists.txt | 4 +- Svc/CCSDS/SpacePacketDeframer/docs/sdd.md | 2 +- Svc/CCSDS/SpacePacketFramer/docs/sdd.md | 2 +- Svc/CCSDS/TCDeframer/CMakeLists.txt | 10 ++-- Svc/CCSDS/TCDeframer/TCDeframer.cpp | 18 +++---- Svc/CCSDS/TCDeframer/TCDeframer.fpp | 2 +- Svc/CCSDS/TCDeframer/TCDeframer.hpp | 28 +++++------ Svc/CCSDS/TCDeframer/docs/sdd.md | 28 +++++------ .../TCDeframer/test/ut/TCDeframerTestMain.cpp | 30 +++++------ .../TCDeframer/test/ut/TCDeframerTester.cpp | 28 +++++------ .../TCDeframer/test/ut/TCDeframerTester.hpp | 24 ++++----- Svc/CCSDS/TMFramer/CMakeLists.txt | 10 ++-- Svc/CCSDS/TMFramer/TMFramer.cpp | 22 ++++---- Svc/CCSDS/TMFramer/TMFramer.fpp | 2 +- Svc/CCSDS/TMFramer/TMFramer.hpp | 28 +++++------ Svc/CCSDS/TMFramer/docs/sdd.md | 44 ++++++++-------- .../TMFramer/test/ut/TMFramerTestMain.cpp | 30 +++++------ Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp | 50 +++++++++---------- Svc/CCSDS/TMFramer/test/ut/TMFramerTester.hpp | 24 ++++----- Svc/FrameAccumulator/CMakeLists.txt | 8 +-- .../FrameDetector/CcsdsTCFrameDetector.cpp | 6 +-- .../FrameDetector/CcsdsTCFrameDetector.hpp | 6 +-- .../CcsdsTCFrameDetectorTestMain.cpp | 6 +-- 26 files changed, 211 insertions(+), 213 deletions(-) diff --git a/Ref/Top/RefTopology.cpp b/Ref/Top/RefTopology.cpp index 617a59ca7a2..c248b99150a 100644 --- a/Ref/Top/RefTopology.cpp +++ b/Ref/Top/RefTopology.cpp @@ -14,7 +14,7 @@ // Necessary project-specified types #include #include -#include +#include #include // Used for 1Hz synthetic cycling @@ -32,7 +32,7 @@ Fw::MallocAllocator mallocator; // The reference topology uses the F´ packet protocol when communicating with the ground and therefore uses the F´ // framing and deframing implementations. -Svc::FrameDetectors::CcsdsTCFrameDetector frameDetector; +Svc::FrameDetectors::CcsdsTcFrameDetector frameDetector; // The reference topology divides the incoming clock signal (1Hz) into sub-signals: 1Hz, 1/2Hz, and 1/4Hz and diff --git a/Ref/Top/instances.fpp b/Ref/Top/instances.fpp index 789f0f614bd..27725d02dc3 100644 --- a/Ref/Top/instances.fpp +++ b/Ref/Top/instances.fpp @@ -167,11 +167,11 @@ module Ref { instance frameAccumulator: Svc.FrameAccumulator base id 0x4B00 - instance tcDeframer: Svc.CCSDS.TCDeframer base id 0x4C00 + instance tcDeframer: Svc.CCSDS.TcDeframer base id 0x4C00 instance spacePacketDeframer: Svc.CCSDS.SpacePacketDeframer base id 0x5000 - instance tmFramer: Svc.CCSDS.TMFramer base id 0x5100 + instance tmFramer: Svc.CCSDS.TmFramer base id 0x5100 instance spacePacketFramer: Svc.CCSDS.SpacePacketFramer base id 0x5200 diff --git a/Ref/Top/topology.fpp b/Ref/Top/topology.fpp index 5fd9ed500ac..14e04c966bb 100644 --- a/Ref/Top/topology.fpp +++ b/Ref/Top/topology.fpp @@ -115,7 +115,7 @@ module Ref { spacePacketFramer.bufferAllocate -> commsBufferManager.bufferGetCallee spacePacketFramer.bufferDeallocate -> commsBufferManager.bufferSendIn spacePacketFramer.getApidSeqCount -> apidManager.getApidSeqCountIn - # SpacePacketFramer <-> TMFramer + # SpacePacketFramer <-> TmFramer spacePacketFramer.dataOut -> tmFramer.dataIn tmFramer.dataReturnOut -> spacePacketFramer.dataReturnIn # Framer <-> ComStub @@ -193,7 +193,7 @@ module Ref { # FrameAccumulator <-> Deframer frameAccumulator.dataOut -> tcDeframer.dataIn tcDeframer.dataReturnOut -> frameAccumulator.dataReturnIn - # TCDeframer <-> SpacePacketDeframer + # TcDeframer <-> SpacePacketDeframer tcDeframer.dataOut -> spacePacketDeframer.dataIn spacePacketDeframer.dataReturnOut -> tcDeframer.dataReturnIn # SpacePacketDeframer APID validation diff --git a/Svc/CCSDS/CMakeLists.txt b/Svc/CCSDS/CMakeLists.txt index bb80ac4ce41..400462e9cdd 100644 --- a/Svc/CCSDS/CMakeLists.txt +++ b/Svc/CCSDS/CMakeLists.txt @@ -2,6 +2,6 @@ add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Types/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Ports/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/SpacePacketDeframer/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/SpacePacketFramer/") -add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/TCDeframer/") -add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/TMFramer/") +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/TcDeframer/") +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/TmFramer/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/ApidManager/") diff --git a/Svc/CCSDS/SpacePacketDeframer/docs/sdd.md b/Svc/CCSDS/SpacePacketDeframer/docs/sdd.md index ff4df93b23b..2eb94e99c83 100644 --- a/Svc/CCSDS/SpacePacketDeframer/docs/sdd.md +++ b/Svc/CCSDS/SpacePacketDeframer/docs/sdd.md @@ -4,7 +4,7 @@ The `Svc::CCSDS::SpacePacketDeframer` is an implementation of the [DeframerInter It receives data containing a Space Packet on its input port and extracts the Space Packet. Please refer to the CCSDS [Space Packet Protocol specification (CCSDS 133.0-B-2)](https://ccsds.org/Pubs/133x0b2e2.pdf) for details on the packet format. -The `Svc::CCSDS::SpacePacketDeframer` is typically used downstream of a component that removes transfer frame headers, such as the `Svc::CCSDS::TCDeframer`. It validates the Space Packet header and extracts the payload. +The `Svc::CCSDS::SpacePacketDeframer` is typically used downstream of a component that removes transfer frame headers, such as the `Svc::CCSDS::TcDeframer`. It validates the Space Packet header and extracts the payload. ## Port Descriptions diff --git a/Svc/CCSDS/SpacePacketFramer/docs/sdd.md b/Svc/CCSDS/SpacePacketFramer/docs/sdd.md index cb0a82e7f79..de7b8b58c20 100644 --- a/Svc/CCSDS/SpacePacketFramer/docs/sdd.md +++ b/Svc/CCSDS/SpacePacketFramer/docs/sdd.md @@ -4,7 +4,7 @@ The `Svc::CCSDS::SpacePacketFramer` is an implementation of the [FramerInterface It receives user data on its input port and constructs a CCSDS Space Packet. Please refer to the CCSDS [Space Packet Protocol specification (CCSDS 133.0-B-2)](https://public.ccsds.org/Pubs/133x0b2e1.pdf) for details on the packet format. -The `Svc::CCSDS::SpacePacketFramer` is typically used upstream of a component that adds transfer frame headers, such as the `Svc::CCSDS::TMFramer`. It encapsulates user data into a Space Packet, adding the necessary header fields. +The `Svc::CCSDS::SpacePacketFramer` is typically used upstream of a component that adds transfer frame headers, such as the `Svc::CCSDS::TmFramer`. It encapsulates user data into a Space Packet, adding the necessary header fields. ## Configuration The `Svc::CCSDS::SpacePacketFramer` requires an Application Process Identifier (APID) for the Space Packets it generates. This APID is typically provided during instantiation or configuration. It also uses a sequence count, which is managed per APID via the `getApidSeqCount` port. diff --git a/Svc/CCSDS/TCDeframer/CMakeLists.txt b/Svc/CCSDS/TCDeframer/CMakeLists.txt index 22daab7cf44..c2d7734d4d3 100644 --- a/Svc/CCSDS/TCDeframer/CMakeLists.txt +++ b/Svc/CCSDS/TCDeframer/CMakeLists.txt @@ -12,19 +12,19 @@ register_fprime_library( SOURCES - "${CMAKE_CURRENT_LIST_DIR}/TCDeframer.cpp" + "${CMAKE_CURRENT_LIST_DIR}/TcDeframer.cpp" AUTOCODER_INPUTS - "${CMAKE_CURRENT_LIST_DIR}/TCDeframer.fpp" + "${CMAKE_CURRENT_LIST_DIR}/TcDeframer.fpp" DEPENDS Svc_CCSDS_Types ) register_fprime_ut( SOURCES - "${CMAKE_CURRENT_LIST_DIR}/test/ut/TCDeframerTestMain.cpp" - "${CMAKE_CURRENT_LIST_DIR}/test/ut/TCDeframerTester.cpp" + "${CMAKE_CURRENT_LIST_DIR}/test/ut/TcDeframerTestMain.cpp" + "${CMAKE_CURRENT_LIST_DIR}/test/ut/TcDeframerTester.cpp" AUTOCODER_INPUTS - "${CMAKE_CURRENT_LIST_DIR}/TCDeframer.fpp" + "${CMAKE_CURRENT_LIST_DIR}/TcDeframer.fpp" DEPENDS Svc_CCSDS_Types STest diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.cpp b/Svc/CCSDS/TCDeframer/TCDeframer.cpp index 91eb0959d52..bd4d7dfa046 100644 --- a/Svc/CCSDS/TCDeframer/TCDeframer.cpp +++ b/Svc/CCSDS/TCDeframer/TCDeframer.cpp @@ -1,10 +1,10 @@ // ====================================================================== -// \title TCDeframer.cpp +// \title TcDeframer.cpp // \author thomas-bc -// \brief cpp file for TCDeframer component implementation class +// \brief cpp file for TcDeframer component implementation class // ====================================================================== -#include "Svc/CCSDS/TCDeframer/TCDeframer.hpp" +#include "Svc/CCSDS/TcDeframer/TcDeframer.hpp" #include "Svc/CCSDS/Types/FppConstantsAc.hpp" #include "Svc/CCSDS/Types/TCHeaderSerializableAc.hpp" #include "Svc/CCSDS/Types/TCTrailerSerializableAc.hpp" @@ -18,12 +18,12 @@ namespace CCSDS { // Component construction and destruction // ---------------------------------------------------------------------- -TCDeframer ::TCDeframer(const char* const compName) - : TCDeframerComponentBase(compName), m_spacecraftId(ComCfg::SpacecraftId) {} +TcDeframer ::TcDeframer(const char* const compName) + : TcDeframerComponentBase(compName), m_spacecraftId(ComCfg::SpacecraftId) {} -TCDeframer ::~TCDeframer() {} +TcDeframer ::~TcDeframer() {} -void TCDeframer::configure(U16 vcId, U16 spacecraftId, bool acceptAllVcid) { +void TcDeframer::configure(U16 vcId, U16 spacecraftId, bool acceptAllVcid) { this->m_vcId = vcId; this->m_spacecraftId = spacecraftId; this->m_acceptAllVcid = acceptAllVcid; @@ -32,7 +32,7 @@ void TCDeframer::configure(U16 vcId, U16 spacecraftId, bool acceptAllVcid) { // Handler implementations for user-defined typed input ports // ---------------------------------------------------------------------- -void TCDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { +void TcDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { // CCSDS TC Format: // 5 octets - TC Primary Header // Up to 1019 octets - Data Field (including optional 2 octets frame error control field) @@ -107,7 +107,7 @@ void TCDeframer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const Co this->dataOut_out(0, data, context); } -void TCDeframer ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer, const ComCfg::FrameContext& context) { +void TcDeframer ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer, const ComCfg::FrameContext& context) { this->dataReturnOut_out(0, fwBuffer, context); } diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.fpp b/Svc/CCSDS/TCDeframer/TCDeframer.fpp index 7500f092fe8..0ba352f8c42 100644 --- a/Svc/CCSDS/TCDeframer/TCDeframer.fpp +++ b/Svc/CCSDS/TCDeframer/TCDeframer.fpp @@ -1,7 +1,7 @@ module Svc { module CCSDS { @ Deframer for the TC Space Data Link Protocol (CCSDS Standard) - passive component TCDeframer { + passive component TcDeframer { include "../../Interfaces/DeframerInterface.fppi" diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.hpp b/Svc/CCSDS/TCDeframer/TCDeframer.hpp index 8776b680d67..be9e6d74eca 100644 --- a/Svc/CCSDS/TCDeframer/TCDeframer.hpp +++ b/Svc/CCSDS/TCDeframer/TCDeframer.hpp @@ -1,35 +1,35 @@ // ====================================================================== -// \title TCDeframer.hpp +// \title TcDeframer.hpp // \author thomas-bc -// \brief hpp file for TCDeframer component implementation class +// \brief hpp file for TcDeframer component implementation class // ====================================================================== -#ifndef Svc_CCSDS_TCDeframer_HPP -#define Svc_CCSDS_TCDeframer_HPP +#ifndef Svc_CCSDS_TcDeframer_HPP +#define Svc_CCSDS_TcDeframer_HPP -#include "Svc/CCSDS/TCDeframer/TCDeframerComponentAc.hpp" +#include "Svc/CCSDS/TcDeframer/TcDeframerComponentAc.hpp" namespace Svc { namespace CCSDS { -class TCDeframer : public TCDeframerComponentBase { - friend class TCDeframerTester; +class TcDeframer : public TcDeframerComponentBase { + friend class TcDeframerTester; public: // ---------------------------------------------------------------------- // Component construction and destruction // ---------------------------------------------------------------------- - //! Construct TCDeframer object - TCDeframer(const char* const compName //!< The component name + //! Construct TcDeframer object + TcDeframer(const char* const compName //!< The component name ); - //! Destroy TCDeframer object - ~TCDeframer(); + //! Destroy TcDeframer object + ~TcDeframer(); - //! \brief Configure the TCDeframer to deframe only a specific VCID and spacecraft ID + //! \brief Configure the TcDeframer to deframe only a specific VCID and spacecraft ID //! - //! By default, the TCDeframer is configured with the spacecraft ID set in the config/ComCfg.fpp file, - //! and deframes all incoming frames regardless of their VCID. Should project instantiate a TCDeframer + //! By default, the TcDeframer is configured with the spacecraft ID set in the config/ComCfg.fpp file, + //! and deframes all incoming frames regardless of their VCID. Should project instantiate a TcDeframer //! with a different configuration, they can use this configure method to set the desired properties. //! //! \param vcId The virtual channel ID to accept (if acceptAllVcid is false) diff --git a/Svc/CCSDS/TCDeframer/docs/sdd.md b/Svc/CCSDS/TCDeframer/docs/sdd.md index d4ac2e820af..1fee26f114a 100644 --- a/Svc/CCSDS/TCDeframer/docs/sdd.md +++ b/Svc/CCSDS/TCDeframer/docs/sdd.md @@ -1,16 +1,16 @@ -# Svc::CCSDS::TCDeframer +# Svc::CCSDS::TcDeframer -The `Svc::CCSDS::TCDeframer` is an implementation of the [DeframerInterface](../../../Interfaces/docs/sdd.md) for the CCSDS [TC Space Data Link Protocol](https://ccsds.org/Pubs/232x0b4e1c1.pdf). +The `Svc::CCSDS::TcDeframer` is an implementation of the [DeframerInterface](../../../Interfaces/docs/sdd.md) for the CCSDS [TC Space Data Link Protocol](https://ccsds.org/Pubs/232x0b4e1c1.pdf). It receives payload data (such as a Space Packet or a VCA_SDU) on input and produces a TC frame on its output port as a result. Please refer to the CCSDS [TC specification (CCSDS 232.0-B-4)](https://ccsds.org/Pubs/232x0b4e1c1.pdf) for details on the frame format and protocol. -The `Svc::CCSDS::TCDeframer` is designed to work in the common F Prime telemetry stack, receiving data from an upstream [`Svc::ComQueue`](../../../ComQueue/docs/sdd.md) and passing frames to a [Communications Adapter](../../../Interfaces/docs/sdd.md), such as a Radio manager component or [`Svc::ComStub`](../../../ComStub/docs/sdd.md), for transmission on the wire. It is commonly coupled with the [`Svc::CCSDS::SpacePacketFramer`](../../SpacePacketFramer/docs/sdd.md) to wrap CCSDS Space Packets into TM frames. +The `Svc::CCSDS::TcDeframer` is designed to work in the common F Prime telemetry stack, receiving data from an upstream [`Svc::ComQueue`](../../../ComQueue/docs/sdd.md) and passing frames to a [Communications Adapter](../../../Interfaces/docs/sdd.md), such as a Radio manager component or [`Svc::ComStub`](../../../ComStub/docs/sdd.md), for transmission on the wire. It is commonly coupled with the [`Svc::CCSDS::SpacePacketFramer`](../../SpacePacketFramer/docs/sdd.md) to wrap CCSDS Space Packets into TM frames. -The TCDeframer currently functions only in the "Expedited Service" mode, for Type-B Frames. This means that should Type-A frames be received, no FARM checks would be performed on board. +The TcDeframer currently functions only in the "Expedited Service" mode, for Type-B Frames. This means that should Type-A frames be received, no FARM checks would be performed on board. ## Configuration -The `TCDeframer` component can be configured with a specific Virtual Channel ID (VCID) and Spacecraft ID. By default, it uses the spacecraft ID from `config/ComCfg.fpp` and accepts all VCIDs. +The `TcDeframer` component can be configured with a specific Virtual Channel ID (VCID) and Spacecraft ID. By default, it uses the spacecraft ID from `config/ComCfg.fpp` and accepts all VCIDs. ```cpp void configure(U16 vcId, U16 spacecraftId, bool acceptAllVcid); @@ -42,12 +42,12 @@ void configure(U16 vcId, U16 spacecraftId, bool acceptAllVcid); | Name | Description | Validation | |---|---|---| -| SVC-CCSDS-TC-DEFRAMER-001 | The TCDeframer shall deframe Telecommand (TC) Transfer Frames according to the CCSDS Space Data Link Protocol standard for Type-BD frames. | Unit Test, Inspection | -| SVC-CCSDS-TC-DEFRAMER-002 | The TCDeframer shall perform Frame Validation Check Procedures, including Spacecraft ID, Virtual Channel ID, Frame Length, and CRC. | Unit Test | -| SVC-CCSDS-TC-DEFRAMER-003 | The TCDeframer shall be configurable for a specific Spacecraft ID. | Unit Test, Inspection | -| SVC-CCSDS-TC-DEFRAMER-004 | The TCDeframer shall be configurable with a specific Virtual Channel ID (VCID) OR to accept all VCIDs. | Unit Test, Inspection | -| SVC-CCSDS-TC-DEFRAMER-005 | The TCDeframer shall log an `InvalidSpacecraftId` event if a frame with an unexpected Spacecraft ID is received. | Unit Test | -| SVC-CCSDS-TC-DEFRAMER-006 | The TCDeframer shall log an `InvalidFrameLength` event if a frame with an invalid length is received. | Unit Test | -| SVC-CCSDS-TC-DEFRAMER-007 | The TCDeframer shall log an `InvalidVcId` event if a frame with an unexpected VCID is received (when not configured to accept all VCIDs). | Unit Test | -| SVC-CCSDS-TC-DEFRAMER-008 | The TCDeframer shall log an `InvalidCrc` event if a frame fails the CRC check. | Unit Test | -| SVC-CCSDS-TC-DEFRAMER-009 | The TCDeframer shall provide an input port (`dataIn`) to receive framed data, and emit deframed data packets on its `dataOut` output port. | Unit Test | +| SVC-CCSDS-TC-DEFRAMER-001 | The TcDeframer shall deframe Telecommand (TC) Transfer Frames according to the CCSDS Space Data Link Protocol standard for Type-BD frames. | Unit Test, Inspection | +| SVC-CCSDS-TC-DEFRAMER-002 | The TcDeframer shall perform Frame Validation Check Procedures, including Spacecraft ID, Virtual Channel ID, Frame Length, and CRC. | Unit Test | +| SVC-CCSDS-TC-DEFRAMER-003 | The TcDeframer shall be configurable for a specific Spacecraft ID. | Unit Test, Inspection | +| SVC-CCSDS-TC-DEFRAMER-004 | The TcDeframer shall be configurable with a specific Virtual Channel ID (VCID) OR to accept all VCIDs. | Unit Test, Inspection | +| SVC-CCSDS-TC-DEFRAMER-005 | The TcDeframer shall log an `InvalidSpacecraftId` event if a frame with an unexpected Spacecraft ID is received. | Unit Test | +| SVC-CCSDS-TC-DEFRAMER-006 | The TcDeframer shall log an `InvalidFrameLength` event if a frame with an invalid length is received. | Unit Test | +| SVC-CCSDS-TC-DEFRAMER-007 | The TcDeframer shall log an `InvalidVcId` event if a frame with an unexpected VCID is received (when not configured to accept all VCIDs). | Unit Test | +| SVC-CCSDS-TC-DEFRAMER-008 | The TcDeframer shall log an `InvalidCrc` event if a frame fails the CRC check. | Unit Test | +| SVC-CCSDS-TC-DEFRAMER-009 | The TcDeframer shall provide an input port (`dataIn`) to receive framed data, and emit deframed data packets on its `dataOut` output port. | Unit Test | diff --git a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTestMain.cpp b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTestMain.cpp index 6d5bbb2b5ab..9f6f5ca4459 100644 --- a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTestMain.cpp +++ b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTestMain.cpp @@ -1,38 +1,38 @@ // ====================================================================== -// \title TCDeframerTestMain.cpp +// \title TcDeframerTestMain.cpp // \author thomas-bc -// \brief cpp file for TCDeframer component test main function +// \brief cpp file for TcDeframer component test main function // ====================================================================== -#include "TCDeframerTester.hpp" +#include "TcDeframerTester.hpp" -TEST(TCDeframer, testDataReturn) { - Svc::CCSDS::TCDeframerTester tester; +TEST(TcDeframer, testDataReturn) { + Svc::CCSDS::TcDeframerTester tester; tester.testDataReturn(); } -TEST(TCDeframer, testNominalDeframing) { - Svc::CCSDS::TCDeframerTester tester; +TEST(TcDeframer, testNominalDeframing) { + Svc::CCSDS::TcDeframerTester tester; tester.testNominalDeframing(); } -TEST(TCDeframer, testInvalidScId) { - Svc::CCSDS::TCDeframerTester tester; +TEST(TcDeframer, testInvalidScId) { + Svc::CCSDS::TcDeframerTester tester; tester.testInvalidScId(); } -TEST(TCDeframer, testInvalidVcId) { - Svc::CCSDS::TCDeframerTester tester; +TEST(TcDeframer, testInvalidVcId) { + Svc::CCSDS::TcDeframerTester tester; tester.testInvalidVcId(); } -TEST(TCDeframer, testInvalidLengthToken) { - Svc::CCSDS::TCDeframerTester tester; +TEST(TcDeframer, testInvalidLengthToken) { + Svc::CCSDS::TcDeframerTester tester; tester.testInvalidLengthToken(); } -TEST(TCDeframer, testInvalidCrc) { - Svc::CCSDS::TCDeframerTester tester; +TEST(TcDeframer, testInvalidCrc) { + Svc::CCSDS::TcDeframerTester tester; tester.testInvalidCrc(); } diff --git a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp index 9c855e665c2..9005534eb40 100644 --- a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp +++ b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp @@ -1,10 +1,10 @@ // ====================================================================== -// \title TCDeframerTester.cpp +// \title TcDeframerTester.cpp // \author thomas-bc -// \brief cpp file for TCDeframer component test harness implementation class +// \brief cpp file for TcDeframer component test harness implementation class // ====================================================================== -#include "TCDeframerTester.hpp" +#include "TcDeframerTester.hpp" #include "STest/Random/Random.hpp" #include "Svc/CCSDS/Utils/CRC16.hpp" #include "Svc/CCSDS/Types/TCHeaderSerializableAc.hpp" @@ -18,19 +18,19 @@ namespace CCSDS { // Construction and destruction // ---------------------------------------------------------------------- -TCDeframerTester ::TCDeframerTester() - : TCDeframerGTestBase("TCDeframerTester", TCDeframerTester::MAX_HISTORY_SIZE), component("TCDeframer") { +TcDeframerTester ::TcDeframerTester() + : TcDeframerGTestBase("TcDeframerTester", TcDeframerTester::MAX_HISTORY_SIZE), component("TcDeframer") { this->initComponents(); this->connectPorts(); } -TCDeframerTester ::~TCDeframerTester() {} +TcDeframerTester ::~TcDeframerTester() {} // ---------------------------------------------------------------------- // Tests // ---------------------------------------------------------------------- -void TCDeframerTester::testDataReturn() { +void TcDeframerTester::testDataReturn() { U8 data[1] = {0}; Fw::Buffer buffer(data, sizeof(data)); ComCfg::FrameContext nullContext; @@ -41,7 +41,7 @@ void TCDeframerTester::testDataReturn() { ASSERT_EQ(this->fromPortHistory_dataReturnOut->at(0).context, nullContext); } -void TCDeframerTester::testNominalDeframing() { +void TcDeframerTester::testNominalDeframing() { // Frame: 5 bytes (header) + bytes (data) + 2 bytes (trailer) U16 scId = static_cast(STest::Random::lowerUpper(0, 0x3FF)); // random 10 bit Spacecraft ID U8 vcId = static_cast(STest::Random::lowerUpper(0, 0x3F)); // random 6 bit virtual channel ID @@ -67,7 +67,7 @@ void TCDeframerTester::testNominalDeframing() { } } -void TCDeframerTester::testInvalidScId() { +void TcDeframerTester::testInvalidScId() { // Frame: 5 bytes (header) + 1 byte (data) + 2 bytes (trailer) U16 scId = static_cast(STest::Random::lowerUpper(1, 0x3FF)); // random 10 bit Spacecraft ID U8 dataLength = static_cast(STest::Random::lowerUpper(1, 200)); // bytes of data, random length @@ -90,7 +90,7 @@ void TCDeframerTester::testInvalidScId() { } -void TCDeframerTester::testInvalidVcId() { +void TcDeframerTester::testInvalidVcId() { U8 vcId = static_cast(STest::Random::lowerUpper(1, 0x3F)); // random 6 bit VCID U8 dataLength = static_cast(STest::Random::lowerUpper(1, 200)); // bytes of data, random length U8 data[dataLength]; @@ -111,7 +111,7 @@ void TCDeframerTester::testInvalidVcId() { ASSERT_EVENTS_InvalidVcId(0, static_cast(vcId - 1), vcId); // event was emitted for invalid VCID } -void TCDeframerTester::testInvalidLengthToken() { +void TcDeframerTester::testInvalidLengthToken() { U8 dataLength = static_cast(STest::Random::lowerUpper(1, 200)); // bytes of data, random length U8 data[dataLength]; U8 incorrectLengthToken = static_cast(dataLength + TCHeader::SERIALIZED_SIZE + TCTrailer::SERIALIZED_SIZE + 1); @@ -133,7 +133,7 @@ void TCDeframerTester::testInvalidLengthToken() { ASSERT_EVENTS_InvalidFrameLength(0, static_cast(incorrectLengthToken + 1), static_cast(dataLength + TCHeader::SERIALIZED_SIZE + TCTrailer::SERIALIZED_SIZE)); } -void TCDeframerTester::testInvalidCrc() { +void TcDeframerTester::testInvalidCrc() { U8 dataLength = static_cast(STest::Random::lowerUpper(1, 200)); // bytes of data, random length U8 data[dataLength]; @@ -154,7 +154,7 @@ void TCDeframerTester::testInvalidCrc() { ASSERT_EVENTS_InvalidCrc_SIZE(1); } -void TCDeframerTester::setComponentState(U16 scid, U8 vcid, U8 sequenceNumber, bool acceptAllVcid) { +void TcDeframerTester::setComponentState(U16 scid, U8 vcid, U8 sequenceNumber, bool acceptAllVcid) { this->component.configure(vcid, scid, acceptAllVcid); // this->component.m_spacecraftId = scid; // this->component.m_vcId = vcid; @@ -162,7 +162,7 @@ void TCDeframerTester::setComponentState(U16 scid, U8 vcid, U8 sequenceNumber, b // this->component.m_acceptAllVcid = acceptAllVcid; } -Fw::Buffer TCDeframerTester::assembleFrameBuffer(U8* data, U8 dataLength, U16 scid, U8 vcid, U8 seqNumber){ +Fw::Buffer TcDeframerTester::assembleFrameBuffer(U8* data, U8 dataLength, U16 scid, U8 vcid, U8 seqNumber){ ::memset(this->m_frameData, 0, sizeof(this->m_frameData)); U16 frameLength = static_cast(TCHeader::SERIALIZED_SIZE + dataLength + TCTrailer::SERIALIZED_SIZE); U16 frameLengthToken = static_cast(frameLength - 1); // length token is length - 1 diff --git a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.hpp b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.hpp index 1358e15adba..85ee6a31e98 100644 --- a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.hpp +++ b/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.hpp @@ -1,20 +1,20 @@ // ====================================================================== -// \title TCDeframerTester.hpp +// \title TcDeframerTester.hpp // \author thomas-bc -// \brief hpp file for TCDeframer component test harness implementation class +// \brief hpp file for TcDeframer component test harness implementation class // ====================================================================== -#ifndef Svc_CCSDS_TCDeframerTester_HPP -#define Svc_CCSDS_TCDeframerTester_HPP +#ifndef Svc_CCSDS_TcDeframerTester_HPP +#define Svc_CCSDS_TcDeframerTester_HPP -#include "Svc/CCSDS/TCDeframer/TCDeframer.hpp" -#include "Svc/CCSDS/TCDeframer/TCDeframerGTestBase.hpp" +#include "Svc/CCSDS/TcDeframer/TcDeframer.hpp" +#include "Svc/CCSDS/TcDeframer/TcDeframerGTestBase.hpp" namespace Svc { namespace CCSDS { -class TCDeframerTester final : public TCDeframerGTestBase { +class TcDeframerTester final : public TcDeframerGTestBase { public: // ---------------------------------------------------------------------- // Constants @@ -31,11 +31,11 @@ class TCDeframerTester final : public TCDeframerGTestBase { // Construction and destruction // ---------------------------------------------------------------------- - //! Construct object TCDeframerTester - TCDeframerTester(); + //! Construct object TcDeframerTester + TcDeframerTester(); - //! Destroy object TCDeframerTester - ~TCDeframerTester(); + //! Destroy object TcDeframerTester + ~TcDeframerTester(); public: // ---------------------------------------------------------------------- @@ -72,7 +72,7 @@ class TCDeframerTester final : public TCDeframerGTestBase { // ---------------------------------------------------------------------- //! The component under test - TCDeframer component; + TcDeframer component; U8 m_frameData[300]; // data buffer used to produce test frames }; diff --git a/Svc/CCSDS/TMFramer/CMakeLists.txt b/Svc/CCSDS/TMFramer/CMakeLists.txt index b716cb123f9..5c7b0818f15 100644 --- a/Svc/CCSDS/TMFramer/CMakeLists.txt +++ b/Svc/CCSDS/TMFramer/CMakeLists.txt @@ -12,19 +12,19 @@ register_fprime_library( SOURCES - "${CMAKE_CURRENT_LIST_DIR}/TMFramer.cpp" + "${CMAKE_CURRENT_LIST_DIR}/TmFramer.cpp" AUTOCODER_INPUTS - "${CMAKE_CURRENT_LIST_DIR}/TMFramer.fpp" + "${CMAKE_CURRENT_LIST_DIR}/TmFramer.fpp" DEPENDS Svc_CCSDS_Types ) register_fprime_ut( SOURCES - "${CMAKE_CURRENT_LIST_DIR}/test/ut/TMFramerTestMain.cpp" - "${CMAKE_CURRENT_LIST_DIR}/test/ut/TMFramerTester.cpp" + "${CMAKE_CURRENT_LIST_DIR}/test/ut/TmFramerTestMain.cpp" + "${CMAKE_CURRENT_LIST_DIR}/test/ut/TmFramerTester.cpp" AUTOCODER_INPUTS - "${CMAKE_CURRENT_LIST_DIR}/TMFramer.fpp" + "${CMAKE_CURRENT_LIST_DIR}/TmFramer.fpp" DEPENDS Svc_CCSDS_Types STest diff --git a/Svc/CCSDS/TMFramer/TMFramer.cpp b/Svc/CCSDS/TMFramer/TMFramer.cpp index edb6cbbbf82..2946c05af81 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.cpp +++ b/Svc/CCSDS/TMFramer/TMFramer.cpp @@ -1,10 +1,10 @@ // ====================================================================== -// \title TMFramer.cpp +// \title TmFramer.cpp // \author thomas-bc -// \brief cpp file for TMFramer component implementation class +// \brief cpp file for TmFramer component implementation class // ====================================================================== -#include "Svc/CCSDS/TMFramer/TMFramer.hpp" +#include "Svc/CCSDS/TmFramer/TmFramer.hpp" #include "Svc/CCSDS/Utils/CRC16.hpp" #include "config/FppConstantsAc.hpp" @@ -16,20 +16,18 @@ namespace CCSDS { // Component construction and destruction // ---------------------------------------------------------------------- -TMFramer ::TMFramer(const char* const compName) - : TMFramerComponentBase(compName), m_masterFrameCount(0), m_virtualFrameCount(0) {} +TmFramer ::TmFramer(const char* const compName) + : TmFramerComponentBase(compName), m_masterFrameCount(0), m_virtualFrameCount(0) {} -TMFramer ::~TMFramer() {} +TmFramer ::~TmFramer() {} // ---------------------------------------------------------------------- // Handler implementations for typed input ports // ---------------------------------------------------------------------- -void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { +void TmFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { FW_ASSERT(data.getSize() <= ComCfg::TmFrameFixedSize - TMHeader::SERIALIZED_SIZE - TMTrailer::SERIALIZED_SIZE, static_cast(data.getSize())); - // Ensure the buffer is owned by the TMFramer - // TODO: add UTs FW_ASSERT(this->m_bufferState == BufferOwnershipState::OWNED, static_cast(this->m_bufferState)); @@ -93,13 +91,13 @@ void TMFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComC this->dataReturnOut_out(0, data, context); // return ownership of the original data buffer } -void TMFramer ::comStatusIn_handler(FwIndexType portNum, Fw::Success& condition) { +void TmFramer ::comStatusIn_handler(FwIndexType portNum, Fw::Success& condition) { if (this->isConnected_comStatusOut_OutputPort(portNum)) { this->comStatusOut_out(portNum, condition); } } -void TMFramer ::dataReturnIn_handler(FwIndexType portNum, +void TmFramer ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& frameBuffer, const ComCfg::FrameContext& context) { // Assert that the returned buffer is the member, and set ownership state @@ -108,7 +106,7 @@ void TMFramer ::dataReturnIn_handler(FwIndexType portNum, this->m_bufferState = BufferOwnershipState::OWNED; } -void TMFramer ::fill_with_idle_packet(Fw::SerializeBufferBase& serializer) { +void TmFramer ::fill_with_idle_packet(Fw::SerializeBufferBase& serializer) { constexpr U16 endIndex = ComCfg::TmFrameFixedSize - TMTrailer::SERIALIZED_SIZE; constexpr U16 idleApid = static_cast(ComCfg::APID::SPP_IDLE_PACKET); const U16 startIndex = static_cast(serializer.getBuffLength()); diff --git a/Svc/CCSDS/TMFramer/TMFramer.fpp b/Svc/CCSDS/TMFramer/TMFramer.fpp index 34bd5ed1dc0..bb2b06dac15 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.fpp +++ b/Svc/CCSDS/TMFramer/TMFramer.fpp @@ -1,7 +1,7 @@ module Svc { module CCSDS { @ Deframer for the TM Space Data Link Protocol (CCSDS Standard) - passive component TMFramer { + passive component TmFramer { include "../../Interfaces/FramerInterface.fppi" diff --git a/Svc/CCSDS/TMFramer/TMFramer.hpp b/Svc/CCSDS/TMFramer/TMFramer.hpp index dd540ce1e96..237fad1c5aa 100644 --- a/Svc/CCSDS/TMFramer/TMFramer.hpp +++ b/Svc/CCSDS/TMFramer/TMFramer.hpp @@ -1,13 +1,13 @@ // ====================================================================== -// \title TMFramer.hpp +// \title TmFramer.hpp // \author thomas-bc -// \brief hpp file for TMFramer component implementation class +// \brief hpp file for TmFramer component implementation class // ====================================================================== -#ifndef Svc_CCSDS_TMFramer_HPP -#define Svc_CCSDS_TMFramer_HPP +#ifndef Svc_CCSDS_TmFramer_HPP +#define Svc_CCSDS_TmFramer_HPP -#include "Svc/CCSDS/TMFramer/TMFramerComponentAc.hpp" +#include "Svc/CCSDS/TmFramer/TmFramerComponentAc.hpp" #include "Svc/CCSDS/Types/FppConstantsAc.hpp" #include "Svc/CCSDS/Types/SpacePacketHeaderSerializableAc.hpp" #include "Svc/CCSDS/Types/TMHeaderSerializableAc.hpp" @@ -17,8 +17,8 @@ namespace Svc { namespace CCSDS { -class TMFramer final : public TMFramerComponentBase { - friend class TMFramerTester; +class TmFramer final : public TmFramerComponentBase { + friend class TmFramerTester; static_assert(ComCfg::TmFrameFixedSize > TMHeader::SERIALIZED_SIZE + TMTrailer::SERIALIZED_SIZE, "TM Frame Fixed Size must be at least large enough to hold header, trailer and data"); @@ -34,8 +34,8 @@ class TMFramer final : public TMFramerComponentBase { static constexpr U8 IDLE_DATA_PATTERN = 0x44; enum class BufferOwnershipState { - NOT_OWNED, //!< The buffer is currently not owned by the TMFramer - OWNED, //!< The buffer is currently owned by the TMFramer + NOT_OWNED, //!< The buffer is currently not owned by the TmFramer + OWNED, //!< The buffer is currently owned by the TmFramer }; public: @@ -43,12 +43,12 @@ class TMFramer final : public TMFramerComponentBase { // Component construction and destruction // ---------------------------------------------------------------------- - //! Construct TMFramer object - TMFramer(const char* const compName //!< The component name + //! Construct TmFramer object + TmFramer(const char* const compName //!< The component name ); - //! Destroy TMFramer object - ~TMFramer(); + //! Destroy TmFramer object + ~TmFramer(); private: // ---------------------------------------------------------------------- @@ -96,7 +96,7 @@ class TMFramer final : public TMFramerComponentBase { // Because the TM protocol use fixed width frames, and only one frame is in transit between ComQueue and // ComInterface at a time, we can use a member fixed-size buffer to hold the frame data U8 m_frameBuffer[ComCfg::TmFrameFixedSize]; //!< Buffer to hold the frame data - BufferOwnershipState m_bufferState = BufferOwnershipState::OWNED; //!< whether m_frameBuffer is owned by TMFramer + BufferOwnershipState m_bufferState = BufferOwnershipState::OWNED; //!< whether m_frameBuffer is owned by TmFramer // Current implementation uses a single virtual channel, so we can use a single virtual frame count U8 m_masterFrameCount; //!< Master Frame Count - 8 bits - wraps around at 255 diff --git a/Svc/CCSDS/TMFramer/docs/sdd.md b/Svc/CCSDS/TMFramer/docs/sdd.md index e4cdc859092..1062dcffddd 100644 --- a/Svc/CCSDS/TMFramer/docs/sdd.md +++ b/Svc/CCSDS/TMFramer/docs/sdd.md @@ -1,24 +1,24 @@ -# Svc::CCSDS::TMFramer +# Svc::CCSDS::TmFramer -The `Svc::CCSDS::TMFramer` is an implementation of the [FramerInterface](../../../Interfaces/docs/sdd.md) for the CCSDS [TM Space Data Link Protocol](https://ccsds.org/Pubs/132x0b3.pdf). +The `Svc::CCSDS::TmFramer` is an implementation of the [FramerInterface](../../../Interfaces/docs/sdd.md) for the CCSDS [TM Space Data Link Protocol](https://ccsds.org/Pubs/132x0b3.pdf). It receives payload data (such as a Space Packet or a VCA_SDU) on input and produces a TM frame on its output port as a result. Please refer to the CCSDS [TM specification (CCSDS 132.0-B-3)](https://ccsds.org/Pubs/132x0b3.pdf) for details on the frame format and protocol. -The `Svc::CCSDS::TMFramer` is designed to work in the common F Prime telemetry stack, receiving data from an upstream [`Svc::ComQueue`](../../../ComQueue/docs/sdd.md) and passing frames to a [Communications Adapter](../../../Interfaces/docs/sdd.md), such as a Radio manager component or [`Svc::ComStub`](../../../ComStub/docs/sdd.md), for transmission on the wire. It is commonly coupled with the [`Svc::CCSDS::SpacePacketFramer`](../../SpacePacketFramer/docs/sdd.md) to wrap CCSDS Space Packets into TM frames. +The `Svc::CCSDS::TmFramer` is designed to work in the common F Prime telemetry stack, receiving data from an upstream [`Svc::ComQueue`](../../../ComQueue/docs/sdd.md) and passing frames to a [Communications Adapter](../../../Interfaces/docs/sdd.md), such as a Radio manager component or [`Svc::ComStub`](../../../ComStub/docs/sdd.md), for transmission on the wire. It is commonly coupled with the [`Svc::CCSDS::SpacePacketFramer`](../../SpacePacketFramer/docs/sdd.md) to wrap CCSDS Space Packets into TM frames. ## Internals The TM protocol specifies a fixed frame size. This can be configured in the `config/ComCfg.fpp` file. -The `Svc::CCSDS::TMFramer` uses an internal (member) buffer to hold the fixed size frame. The buffer **must** be returned to the TMFramer via the `dataReturnIn` port once it has been used or consumed. When the buffer returns to the TMFramer it will reuse the buffer for the next frame. Should a component want to use the frame data past the time it is returned to the TMFramer, data should be copied before the original buffer is returned to the TMFramer via the `dataReturnIn` port. +The `Svc::CCSDS::TmFramer` uses an internal (member) buffer to hold the fixed size frame. The buffer **must** be returned to the TmFramer via the `dataReturnIn` port once it has been used or consumed. When the buffer returns to the TmFramer it will reuse the buffer for the next frame. Should a component want to use the frame data past the time it is returned to the TmFramer, data should be copied before the original buffer is returned to the TmFramer via the `dataReturnIn` port. ## Usage Examples -The `Svc::CCSDS::TMFramer` component, as well as the rest of the CCSDS communications stack, is used in the [`Ref/`](https://github.com/nasa/fprime/tree/devel/Ref) example application. It is also generated by the `fprime-util new --deployment` command. +The `Svc::CCSDS::TmFramer` component, as well as the rest of the CCSDS communications stack, is used in the [`Ref/`](https://github.com/nasa/fprime/tree/devel/Ref) example application. It is also generated by the `fprime-util new --deployment` command. ## CCSDS Header Fields -For each frame generated, the `Svc::CCSDS::TMFramer` will populate the CCSDS TM Primary Header fields as follows: +For each frame generated, the `Svc::CCSDS::TmFramer` will populate the CCSDS TM Primary Header fields as follows: | Field | Value | Notes | |---|---|---| @@ -26,8 +26,8 @@ For each frame generated, the `Svc::CCSDS::TMFramer` will populate the CCSDS TM | Spacecraft ID | Configured in `config/ComCfg.fpp` | Set in the project configuration | | Virtual Channel ID | Uses value passed in the `context` argument (defaults to 0) | Set by an upstream component | | Operational Control Field Flag | 0 | Unsupported | -| Master Channel Frame Count | Incremented for each frame | Managed internally by TMFramer | -| Virtual Channel Frame Count | Incremented for each frame | Managed internally by TMFramer. One TMFramer instance can only keep count of a single VCID. | +| Master Channel Frame Count | Incremented for each frame | Managed internally by TmFramer | +| Virtual Channel Frame Count | Incremented for each frame | Managed internally by TmFramer. One TmFramer instance can only keep count of a single VCID. | | Transfer Frame Secondary Header Flag | 0 | F Prime does not formally use secondary headers | | Synchronization Flag | 0 | 0 as Packets are inserted | | Packet Order Flag | 0 | As per protocol 4.1.2.7.4 | @@ -49,17 +49,17 @@ For each frame generated, the `Svc::CCSDS::TMFramer` will populate the CCSDS TM | Name | Description | Validation | |---|---|---| -| SVC-CCSDS-TM-FRAMER-001 | The TMFramer shall implement the `Svc.FramerInterface`. | Inspection, Unit Test | -| SVC-CCSDS-TM-FRAMER-002 | The TMFramer shall construct CCSDS Telemetry (TM) Transfer Frames compliant with the CCSDS 132.0-B-3 standard. | Unit Test, Inspection | -| SVC-CCSDS-TM-FRAMER-002 | The TMFramer shall use a fixed frame size that is configurable by the project. | Unit Test, Inspection | -| SVC-CCSDS-TM-FRAMER-003 | The TMFramer shall accept payload data (Space Packets or VCA_SDU) to be framed via its `dataIn` port. | Unit Test | -| SVC-CCSDS-TM-FRAMER-004 | The TMFramer shall output the constructed TM Transfer Frame via its `dataOut` port. | Unit Test | -| SVC-CCSDS-TM-FRAMER-005 | The TMFramer shall return ownership of the input buffer via the `dataReturnOut` port after the framing process is complete. | Unit Test | -| SVC-CCSDS-TM-FRAMER-006 | The TMFramer shall accept returned buffers (previously sent via `dataOut`) through the `dataReturnIn` port for deallocation or reuse. | Unit Test | -| SVC-CCSDS-TM-FRAMER-007 | The TMFramer shall receive communication status from downstream components via the `comStatusIn` port, and pass it through to `comStatusOut` | Unit Test, Integration Test | -| SVC-CCSDS-TM-FRAMER-008 | The TMFramer shall use exactly one Virtual Channel. | Unit Test, Integration Test | -| SVC-CCSDS-TM-FRAMER-009 | The TMFramer shall correctly populate all mandatory fields of the TM Transfer Frame Primary Header, including Transfer Frame Version Number, Spacecraft Identifier, Virtual Channel Identifier, Operational Control Field Flag, Master Channel Frame Count, Virtual Channel Frame Count, Transfer Frame Secondary Header Flag, Synchronization Flag, Packet Order Flag, Segment Length Identifier, and First Header Pointer. | Unit Test, Inspection | -| SVC-CCSDS-TM-FRAMER-010 | The TMFramer shall be configurable with a Spacecraft Identifier. | Inspection, Unit Test | -| SVC-CCSDS-TM-FRAMER-011 | The TMFramer shall use the Virtual Channel Identifier passed in the `context` object on `dataIn`. | Unit Test | -| SVC-CCSDS-TM-FRAMER-012 | The TMFramer shall manage Master Channel Frame Count and Virtual Channel Frame Count. | Unit Test | -| SVC-CCSDS-TM-FRAMER-013 | The TMFramer shall fill the data field of the TM Transfer Frame with the payload data received on `dataIn`, and fill up the rest of the fixed-size frame with a single Idle Packet as defined by the protocol. | Unit Test | +| SVC-CCSDS-TM-FRAMER-001 | The TmFramer shall implement the `Svc.FramerInterface`. | Inspection, Unit Test | +| SVC-CCSDS-TM-FRAMER-002 | The TmFramer shall construct CCSDS Telemetry (TM) Transfer Frames compliant with the CCSDS 132.0-B-3 standard. | Unit Test, Inspection | +| SVC-CCSDS-TM-FRAMER-002 | The TmFramer shall use a fixed frame size that is configurable by the project. | Unit Test, Inspection | +| SVC-CCSDS-TM-FRAMER-003 | The TmFramer shall accept payload data (Space Packets or VCA_SDU) to be framed via its `dataIn` port. | Unit Test | +| SVC-CCSDS-TM-FRAMER-004 | The TmFramer shall output the constructed TM Transfer Frame via its `dataOut` port. | Unit Test | +| SVC-CCSDS-TM-FRAMER-005 | The TmFramer shall return ownership of the input buffer via the `dataReturnOut` port after the framing process is complete. | Unit Test | +| SVC-CCSDS-TM-FRAMER-006 | The TmFramer shall accept returned buffers (previously sent via `dataOut`) through the `dataReturnIn` port for deallocation or reuse. | Unit Test | +| SVC-CCSDS-TM-FRAMER-007 | The TmFramer shall receive communication status from downstream components via the `comStatusIn` port, and pass it through to `comStatusOut` | Unit Test, Integration Test | +| SVC-CCSDS-TM-FRAMER-008 | The TmFramer shall use exactly one Virtual Channel. | Unit Test, Integration Test | +| SVC-CCSDS-TM-FRAMER-009 | The TmFramer shall correctly populate all mandatory fields of the TM Transfer Frame Primary Header, including Transfer Frame Version Number, Spacecraft Identifier, Virtual Channel Identifier, Operational Control Field Flag, Master Channel Frame Count, Virtual Channel Frame Count, Transfer Frame Secondary Header Flag, Synchronization Flag, Packet Order Flag, Segment Length Identifier, and First Header Pointer. | Unit Test, Inspection | +| SVC-CCSDS-TM-FRAMER-010 | The TmFramer shall be configurable with a Spacecraft Identifier. | Inspection, Unit Test | +| SVC-CCSDS-TM-FRAMER-011 | The TmFramer shall use the Virtual Channel Identifier passed in the `context` object on `dataIn`. | Unit Test | +| SVC-CCSDS-TM-FRAMER-012 | The TmFramer shall manage Master Channel Frame Count and Virtual Channel Frame Count. | Unit Test | +| SVC-CCSDS-TM-FRAMER-013 | The TmFramer shall fill the data field of the TM Transfer Frame with the payload data received on `dataIn`, and fill up the rest of the fixed-size frame with a single Idle Packet as defined by the protocol. | Unit Test | diff --git a/Svc/CCSDS/TMFramer/test/ut/TMFramerTestMain.cpp b/Svc/CCSDS/TMFramer/test/ut/TMFramerTestMain.cpp index ee98a92ee2a..734c808d05e 100644 --- a/Svc/CCSDS/TMFramer/test/ut/TMFramerTestMain.cpp +++ b/Svc/CCSDS/TMFramer/test/ut/TMFramerTestMain.cpp @@ -1,38 +1,38 @@ // ====================================================================== -// \title TMFramerTestMain.cpp +// \title TmFramerTestMain.cpp // \author thomas-bc -// \brief cpp file for TMFramer component test main function +// \brief cpp file for TmFramer component test main function // ====================================================================== -#include "TMFramerTester.hpp" +#include "TmFramerTester.hpp" -TEST(TMFramer, testComStatusPassthrough) { - Svc::CCSDS::TMFramerTester tester; +TEST(TmFramer, testComStatusPassthrough) { + Svc::CCSDS::TmFramerTester tester; tester.testComStatusPassthrough(); } -TEST(TMFramer, testDataReturn) { - Svc::CCSDS::TMFramerTester tester; +TEST(TmFramer, testDataReturn) { + Svc::CCSDS::TmFramerTester tester; tester.testDataReturn(); } -TEST(TMFramer, testNominalFraming) { - Svc::CCSDS::TMFramerTester tester; +TEST(TmFramer, testNominalFraming) { + Svc::CCSDS::TmFramerTester tester; tester.testNominalFraming(); } -TEST(TMFramer, testSeqCountWrapAround) { - Svc::CCSDS::TMFramerTester tester; +TEST(TmFramer, testSeqCountWrapAround) { + Svc::CCSDS::TmFramerTester tester; tester.testSeqCountWrapAround(); } -TEST(TMFramer, testInputBufferTooLarge) { - Svc::CCSDS::TMFramerTester tester; +TEST(TmFramer, testInputBufferTooLarge) { + Svc::CCSDS::TmFramerTester tester; tester.testInputBufferTooLarge(); } -TEST(TMFramer, testBufferOwnershipState) { - Svc::CCSDS::TMFramerTester tester; +TEST(TmFramer, testBufferOwnershipState) { + Svc::CCSDS::TmFramerTester tester; tester.testBufferOwnershipState(); } diff --git a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp index 6f30d309e95..75cc375da08 100644 --- a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp +++ b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp @@ -1,10 +1,10 @@ // ====================================================================== -// \title TMFramerTester.cpp +// \title TmFramerTester.cpp // \author thomas-bc -// \brief cpp file for TMFramer component test harness implementation class +// \brief cpp file for TmFramer component test harness implementation class // ====================================================================== -#include "TMFramerTester.hpp" +#include "TmFramerTester.hpp" #include "Svc/CCSDS/Types/TMHeaderSerializableAc.hpp" #include "Svc/CCSDS/Types/TMTrailerSerializableAc.hpp" #include "Svc/CCSDS/Types/SpacePacketHeaderSerializableAc.hpp" @@ -17,19 +17,19 @@ namespace CCSDS { // Construction and destruction // ---------------------------------------------------------------------- -TMFramerTester ::TMFramerTester() - : TMFramerGTestBase("TMFramerTester", TMFramerTester::MAX_HISTORY_SIZE), component("TMFramer") { +TmFramerTester ::TmFramerTester() + : TmFramerGTestBase("TmFramerTester", TmFramerTester::MAX_HISTORY_SIZE), component("TmFramer") { this->initComponents(); this->connectPorts(); } -TMFramerTester ::~TMFramerTester() {} +TmFramerTester ::~TmFramerTester() {} // ---------------------------------------------------------------------- // Tests // ---------------------------------------------------------------------- -void TMFramerTester ::testComStatusPassthrough() { +void TmFramerTester ::testComStatusPassthrough() { // Send a status message to the component Fw::Success inputStatus = Fw::Success::SUCCESS; this->invoke_to_comStatusIn(0, inputStatus); @@ -41,7 +41,7 @@ void TMFramerTester ::testComStatusPassthrough() { ASSERT_from_comStatusOut(1, inputStatus); // at index 1, received FAILURE } -void TMFramerTester ::testNominalFraming() { +void TmFramerTester ::testNominalFraming() { U8 bufferData[100]; Fw::Buffer buffer(bufferData, sizeof(bufferData)); ComCfg::FrameContext defaultContext; @@ -87,7 +87,7 @@ void TMFramerTester ::testNominalFraming() { } } -void TMFramerTester ::testSeqCountWrapAround() { +void TmFramerTester ::testSeqCountWrapAround() { U8 bufferData[100]; Fw::Buffer buffer(bufferData, sizeof(bufferData)); ComCfg::FrameContext defaultContext; @@ -103,7 +103,7 @@ void TMFramerTester ::testSeqCountWrapAround() { this->component.m_virtualFrameCount = 250; U8 countWrapAround = 250; // will wrap around to 0 after 255 for (U32 iter = 0; iter < 10; iter++) { - this->component.m_bufferState = TMFramer::BufferOwnershipState::OWNED; // reset state to OWNED + this->component.m_bufferState = TmFramer::BufferOwnershipState::OWNED; // reset state to OWNED this->invoke_to_dataIn(0, buffer, defaultContext); ASSERT_from_dataOut_SIZE(iter + 1); Fw::Buffer outBuffer = this->fromPortHistory_dataOut->at(iter).data; @@ -115,40 +115,40 @@ void TMFramerTester ::testSeqCountWrapAround() { } } -void TMFramerTester ::testInputBufferTooLarge() { +void TmFramerTester ::testInputBufferTooLarge() { const FwSizeType tooLargeSize = ComCfg::TmFrameFixedSize; // This is too large since we need room for header+trailer as well U8 bufferData[tooLargeSize]; Fw::Buffer buffer(bufferData, static_cast(tooLargeSize)); ComCfg::FrameContext defaultContext; // Send a buffer larger than the - ASSERT_DEATH_IF_SUPPORTED(this->invoke_to_dataIn(0, buffer, defaultContext), "TMFramer.cpp"); + ASSERT_DEATH_IF_SUPPORTED(this->invoke_to_dataIn(0, buffer, defaultContext), "TmFramer.cpp"); } -void TMFramerTester ::testDataReturn() { +void TmFramerTester ::testDataReturn() { U8 bufferData[10]; Fw::Buffer buffer(bufferData, sizeof(bufferData)); ComCfg::FrameContext defaultContext; // Send a buffer that is not the internal buffer of the component, and expect an assertion - ASSERT_DEATH_IF_SUPPORTED(this->invoke_to_dataReturnIn(0, buffer, defaultContext), "TMFramer.cpp"); + ASSERT_DEATH_IF_SUPPORTED(this->invoke_to_dataReturnIn(0, buffer, defaultContext), "TmFramer.cpp"); // Now send the expected buffer and expect state to go back to OWNED - this->component.m_bufferState = TMFramer::BufferOwnershipState::NOT_OWNED; + this->component.m_bufferState = TmFramer::BufferOwnershipState::NOT_OWNED; Fw::Buffer internalBuffer(this->component.m_frameBuffer, sizeof(this->component.m_frameBuffer)); this->invoke_to_dataReturnIn(0, internalBuffer, defaultContext); - ASSERT_EQ(this->component.m_bufferState, TMFramer::BufferOwnershipState::OWNED); + ASSERT_EQ(this->component.m_bufferState, TmFramer::BufferOwnershipState::OWNED); } -void TMFramerTester ::testBufferOwnershipState() { +void TmFramerTester ::testBufferOwnershipState() { U8 bufferData[10]; Fw::Buffer buffer(bufferData, sizeof(bufferData)); ComCfg::FrameContext context; // force state to be NOT_OWNED and test that assertion is triggered - this->component.m_bufferState = TMFramer::BufferOwnershipState::NOT_OWNED; - ASSERT_DEATH_IF_SUPPORTED(this->invoke_to_dataIn(0, buffer, context), "TMFramer.cpp"); - this->component.m_bufferState = TMFramer::BufferOwnershipState::OWNED; + this->component.m_bufferState = TmFramer::BufferOwnershipState::NOT_OWNED; + ASSERT_DEATH_IF_SUPPORTED(this->invoke_to_dataIn(0, buffer, context), "TmFramer.cpp"); + this->component.m_bufferState = TmFramer::BufferOwnershipState::OWNED; this->invoke_to_dataIn(0, buffer, context); // this should work now - ASSERT_EQ(this->component.m_bufferState, TMFramer::BufferOwnershipState::NOT_OWNED); + ASSERT_EQ(this->component.m_bufferState, TmFramer::BufferOwnershipState::NOT_OWNED); } @@ -156,16 +156,16 @@ void TMFramerTester ::testBufferOwnershipState() { // Helper functions // ---------------------------------------------------------------------- -U16 TMFramerTester::getFrameScId(U8* frameData) { +U16 TmFramerTester::getFrameScId(U8* frameData) { return static_cast((frameData[0] & 0x3F) << 4 | (frameData[1] >> 4)); } -U8 TMFramerTester::getFrameVcId(U8* frameData) { +U8 TmFramerTester::getFrameVcId(U8* frameData) { return static_cast((frameData[1] & 0x0E) >> 1); } -U8 TMFramerTester::getFrameMcCount(U8* frameData) { +U8 TmFramerTester::getFrameMcCount(U8* frameData) { return frameData[2]; } -U8 TMFramerTester::getFrameVcCount(U8* frameData) { +U8 TmFramerTester::getFrameVcCount(U8* frameData) { return frameData[3]; } diff --git a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.hpp b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.hpp index 21925c9defb..626e4ea33ac 100644 --- a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.hpp +++ b/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.hpp @@ -1,20 +1,20 @@ // ====================================================================== -// \title TMFramerTester.hpp +// \title TmFramerTester.hpp // \author thomas-bc -// \brief hpp file for TMFramer component test harness implementation class +// \brief hpp file for TmFramer component test harness implementation class // ====================================================================== -#ifndef Svc_CCSDS_TMFramerTester_HPP -#define Svc_CCSDS_TMFramerTester_HPP +#ifndef Svc_CCSDS_TmFramerTester_HPP +#define Svc_CCSDS_TmFramerTester_HPP -#include "Svc/CCSDS/TMFramer/TMFramer.hpp" -#include "Svc/CCSDS/TMFramer/TMFramerGTestBase.hpp" +#include "Svc/CCSDS/TmFramer/TmFramer.hpp" +#include "Svc/CCSDS/TmFramer/TmFramerGTestBase.hpp" namespace Svc { namespace CCSDS { -class TMFramerTester final : public TMFramerGTestBase { +class TmFramerTester final : public TmFramerGTestBase { public: // ---------------------------------------------------------------------- // Constants @@ -31,11 +31,11 @@ class TMFramerTester final : public TMFramerGTestBase { // Construction and destruction // ---------------------------------------------------------------------- - //! Construct object TMFramerTester - TMFramerTester(); + //! Construct object TmFramerTester + TmFramerTester(); - //! Destroy object TMFramerTester - ~TMFramerTester(); + //! Destroy object TmFramerTester + ~TmFramerTester(); public: // ---------------------------------------------------------------------- @@ -71,7 +71,7 @@ class TMFramerTester final : public TMFramerGTestBase { // ---------------------------------------------------------------------- //! The component under test - TMFramer component; + TmFramer component; }; } // namespace CCSDS diff --git a/Svc/FrameAccumulator/CMakeLists.txt b/Svc/FrameAccumulator/CMakeLists.txt index e6a096c73b1..6c97257908a 100644 --- a/Svc/FrameAccumulator/CMakeLists.txt +++ b/Svc/FrameAccumulator/CMakeLists.txt @@ -11,7 +11,7 @@ register_fprime_library( SOURCES "${CMAKE_CURRENT_LIST_DIR}/FrameAccumulator.cpp" "${CMAKE_CURRENT_LIST_DIR}/FrameDetector/FprimeFrameDetector.cpp" - "${CMAKE_CURRENT_LIST_DIR}/FrameDetector/CcsdsTCFrameDetector.cpp" + "${CMAKE_CURRENT_LIST_DIR}/FrameDetector/CcsdsTcFrameDetector.cpp" AUTOCODER_INPUTS "${CMAKE_CURRENT_LIST_DIR}/FrameAccumulator.fpp" DEPENDS @@ -46,11 +46,11 @@ register_fprime_ut( ) register_fprime_ut( - "Svc_FrameAccumulator_CcsdsTCFrameDetector_test" + "Svc_FrameAccumulator_CcsdsTcFrameDetector_test" SOURCES - "${CMAKE_CURRENT_LIST_DIR}/test/ut/detectors/CcsdsTCFrameDetectorTestMain.cpp" + "${CMAKE_CURRENT_LIST_DIR}/test/ut/detectors/CcsdsTcFrameDetectorTestMain.cpp" HEADERS - "${CMAKE_CURRENT_LIST_DIR}/FrameDetector/CcsdsTCFrameDetector.hpp" + "${CMAKE_CURRENT_LIST_DIR}/FrameDetector/CcsdsTcFrameDetector.hpp" DEPENDS STest UT_AUTO_HELPERS diff --git a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp index 90a3c646cd5..546601dd634 100644 --- a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp +++ b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp @@ -1,10 +1,10 @@ // ====================================================================== -// \title CcsdsTCFrameDetector.hpp +// \title CcsdsTcFrameDetector.hpp // \author thomas-bc // \brief hpp file for fprime frame detector definitions // ====================================================================== -#include "Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.hpp" +#include "Svc/FrameAccumulator/FrameDetector/CcsdsTcFrameDetector.hpp" #include "Svc/CCSDS/Types/FppConstantsAc.hpp" #include #include "config/FppConstantsAc.hpp" @@ -16,7 +16,7 @@ namespace Svc { namespace FrameDetectors { -FrameDetector::Status CcsdsTCFrameDetector::detect(const Types::CircularBuffer& data, FwSizeType& size_out) const { +FrameDetector::Status CcsdsTcFrameDetector::detect(const Types::CircularBuffer& data, FwSizeType& size_out) const { if (data.get_allocated_size() < CCSDS::TCHeader::SERIALIZED_SIZE + CCSDS::TCTrailer::SERIALIZED_SIZE) { size_out = CCSDS::TCHeader::SERIALIZED_SIZE + CCSDS::TCTrailer::SERIALIZED_SIZE; diff --git a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.hpp b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.hpp index 5962cc497e5..9f588cb7790 100644 --- a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.hpp +++ b/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.hpp @@ -1,5 +1,5 @@ // ====================================================================== -// \title CcsdsTCFrameDetector.hpp +// \title CcsdsTcFrameDetector.hpp // \author thomas-bc // \brief hpp file for fprime frame detector definitions // ====================================================================== @@ -14,7 +14,7 @@ namespace Svc { namespace FrameDetectors { //! \brief interface class used to codify what must be supported to allow frame detection -class CcsdsTCFrameDetector : public FrameDetector { +class CcsdsTcFrameDetector : public FrameDetector { public: //! \brief detect if a frame is available within the circular buffer //! @@ -46,7 +46,7 @@ class CcsdsTCFrameDetector : public FrameDetector { const U16 m_expectedFlagsAndScIdToken = 0x1 << CCSDS::TCSubfields::BypassFlagOffset | (ComCfg::FppConstant_SpacecraftId::SpacecraftId); -}; // class CcsdsTCFrameDetector +}; // class CcsdsTcFrameDetector } // namespace FrameDetectors } // namespace Svc diff --git a/Svc/FrameAccumulator/test/ut/detectors/CcsdsTCFrameDetectorTestMain.cpp b/Svc/FrameAccumulator/test/ut/detectors/CcsdsTCFrameDetectorTestMain.cpp index dff15dc22d5..7fa8b05a064 100644 --- a/Svc/FrameAccumulator/test/ut/detectors/CcsdsTCFrameDetectorTestMain.cpp +++ b/Svc/FrameAccumulator/test/ut/detectors/CcsdsTCFrameDetectorTestMain.cpp @@ -1,11 +1,11 @@ // ====================================================================== -// \title CcsdsTCFrameDetectorTestMain.cpp +// \title CcsdsTcFrameDetectorTestMain.cpp // \author thomas-bc // \brief cpp file for FrameAccumulator component test main function // ====================================================================== #include "STest/Random/Random.hpp" -#include "Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.hpp" +#include "Svc/FrameAccumulator/FrameDetector/CcsdsTcFrameDetector.hpp" #include "Svc/CCSDS/Utils/CRC16.hpp" #include "Svc/CCSDS/Types/TCHeaderSerializableAc.hpp" #include "Svc/CCSDS/Types/TCTrailerSerializableAc.hpp" @@ -28,7 +28,7 @@ class CcsdsFrameDetectorTest : public ::testing::Test { } U8 m_buffer[CIRCULAR_BUFFER_TEST_SIZE]; - Svc::FrameDetectors::CcsdsTCFrameDetector detector; + Svc::FrameDetectors::CcsdsTcFrameDetector detector; Types::CircularBuffer circular_buffer; }; From 1ecfe39548af41d57117a04363a8580b5805ebe6 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Tue, 10 Jun 2025 14:17:10 -0700 Subject: [PATCH 93/95] Use git mv to rename files and directory --- Svc/CCSDS/{TCDeframer => TcDeframer}/CMakeLists.txt | 0 .../{TCDeframer/TCDeframer.cpp => TcDeframer/TcDeframer.cpp} | 0 .../{TCDeframer/TCDeframer.fpp => TcDeframer/TcDeframer.fpp} | 0 .../{TCDeframer/TCDeframer.hpp => TcDeframer/TcDeframer.hpp} | 0 Svc/CCSDS/{TCDeframer => TcDeframer}/docs/sdd.md | 0 .../test/ut/TcDeframerTestMain.cpp} | 0 .../test/ut/TcDeframerTester.cpp} | 0 .../test/ut/TcDeframerTester.hpp} | 0 Svc/CCSDS/{TMFramer => TmFramer}/CMakeLists.txt | 0 Svc/CCSDS/{TMFramer/TMFramer.cpp => TmFramer/TmFramer.cpp} | 0 Svc/CCSDS/{TMFramer/TMFramer.fpp => TmFramer/TmFramer.fpp} | 0 Svc/CCSDS/{TMFramer/TMFramer.hpp => TmFramer/TmFramer.hpp} | 0 Svc/CCSDS/{TMFramer => TmFramer}/docs/sdd.md | 0 .../test/ut/TmFramerTestMain.cpp} | 0 .../ut/TMFramerTester.cpp => TmFramer/test/ut/TmFramerTester.cpp} | 0 .../ut/TMFramerTester.hpp => TmFramer/test/ut/TmFramerTester.hpp} | 0 .../{CcsdsTCFrameDetector.cpp => CcsdsTcFrameDetector.cpp} | 0 .../{CcsdsTCFrameDetector.hpp => CcsdsTcFrameDetector.hpp} | 0 18 files changed, 0 insertions(+), 0 deletions(-) rename Svc/CCSDS/{TCDeframer => TcDeframer}/CMakeLists.txt (100%) rename Svc/CCSDS/{TCDeframer/TCDeframer.cpp => TcDeframer/TcDeframer.cpp} (100%) rename Svc/CCSDS/{TCDeframer/TCDeframer.fpp => TcDeframer/TcDeframer.fpp} (100%) rename Svc/CCSDS/{TCDeframer/TCDeframer.hpp => TcDeframer/TcDeframer.hpp} (100%) rename Svc/CCSDS/{TCDeframer => TcDeframer}/docs/sdd.md (100%) rename Svc/CCSDS/{TCDeframer/test/ut/TCDeframerTestMain.cpp => TcDeframer/test/ut/TcDeframerTestMain.cpp} (100%) rename Svc/CCSDS/{TCDeframer/test/ut/TCDeframerTester.cpp => TcDeframer/test/ut/TcDeframerTester.cpp} (100%) rename Svc/CCSDS/{TCDeframer/test/ut/TCDeframerTester.hpp => TcDeframer/test/ut/TcDeframerTester.hpp} (100%) rename Svc/CCSDS/{TMFramer => TmFramer}/CMakeLists.txt (100%) rename Svc/CCSDS/{TMFramer/TMFramer.cpp => TmFramer/TmFramer.cpp} (100%) rename Svc/CCSDS/{TMFramer/TMFramer.fpp => TmFramer/TmFramer.fpp} (100%) rename Svc/CCSDS/{TMFramer/TMFramer.hpp => TmFramer/TmFramer.hpp} (100%) rename Svc/CCSDS/{TMFramer => TmFramer}/docs/sdd.md (100%) rename Svc/CCSDS/{TMFramer/test/ut/TMFramerTestMain.cpp => TmFramer/test/ut/TmFramerTestMain.cpp} (100%) rename Svc/CCSDS/{TMFramer/test/ut/TMFramerTester.cpp => TmFramer/test/ut/TmFramerTester.cpp} (100%) rename Svc/CCSDS/{TMFramer/test/ut/TMFramerTester.hpp => TmFramer/test/ut/TmFramerTester.hpp} (100%) rename Svc/FrameAccumulator/FrameDetector/{CcsdsTCFrameDetector.cpp => CcsdsTcFrameDetector.cpp} (100%) rename Svc/FrameAccumulator/FrameDetector/{CcsdsTCFrameDetector.hpp => CcsdsTcFrameDetector.hpp} (100%) diff --git a/Svc/CCSDS/TCDeframer/CMakeLists.txt b/Svc/CCSDS/TcDeframer/CMakeLists.txt similarity index 100% rename from Svc/CCSDS/TCDeframer/CMakeLists.txt rename to Svc/CCSDS/TcDeframer/CMakeLists.txt diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.cpp b/Svc/CCSDS/TcDeframer/TcDeframer.cpp similarity index 100% rename from Svc/CCSDS/TCDeframer/TCDeframer.cpp rename to Svc/CCSDS/TcDeframer/TcDeframer.cpp diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.fpp b/Svc/CCSDS/TcDeframer/TcDeframer.fpp similarity index 100% rename from Svc/CCSDS/TCDeframer/TCDeframer.fpp rename to Svc/CCSDS/TcDeframer/TcDeframer.fpp diff --git a/Svc/CCSDS/TCDeframer/TCDeframer.hpp b/Svc/CCSDS/TcDeframer/TcDeframer.hpp similarity index 100% rename from Svc/CCSDS/TCDeframer/TCDeframer.hpp rename to Svc/CCSDS/TcDeframer/TcDeframer.hpp diff --git a/Svc/CCSDS/TCDeframer/docs/sdd.md b/Svc/CCSDS/TcDeframer/docs/sdd.md similarity index 100% rename from Svc/CCSDS/TCDeframer/docs/sdd.md rename to Svc/CCSDS/TcDeframer/docs/sdd.md diff --git a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTestMain.cpp b/Svc/CCSDS/TcDeframer/test/ut/TcDeframerTestMain.cpp similarity index 100% rename from Svc/CCSDS/TCDeframer/test/ut/TCDeframerTestMain.cpp rename to Svc/CCSDS/TcDeframer/test/ut/TcDeframerTestMain.cpp diff --git a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp b/Svc/CCSDS/TcDeframer/test/ut/TcDeframerTester.cpp similarity index 100% rename from Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.cpp rename to Svc/CCSDS/TcDeframer/test/ut/TcDeframerTester.cpp diff --git a/Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.hpp b/Svc/CCSDS/TcDeframer/test/ut/TcDeframerTester.hpp similarity index 100% rename from Svc/CCSDS/TCDeframer/test/ut/TCDeframerTester.hpp rename to Svc/CCSDS/TcDeframer/test/ut/TcDeframerTester.hpp diff --git a/Svc/CCSDS/TMFramer/CMakeLists.txt b/Svc/CCSDS/TmFramer/CMakeLists.txt similarity index 100% rename from Svc/CCSDS/TMFramer/CMakeLists.txt rename to Svc/CCSDS/TmFramer/CMakeLists.txt diff --git a/Svc/CCSDS/TMFramer/TMFramer.cpp b/Svc/CCSDS/TmFramer/TmFramer.cpp similarity index 100% rename from Svc/CCSDS/TMFramer/TMFramer.cpp rename to Svc/CCSDS/TmFramer/TmFramer.cpp diff --git a/Svc/CCSDS/TMFramer/TMFramer.fpp b/Svc/CCSDS/TmFramer/TmFramer.fpp similarity index 100% rename from Svc/CCSDS/TMFramer/TMFramer.fpp rename to Svc/CCSDS/TmFramer/TmFramer.fpp diff --git a/Svc/CCSDS/TMFramer/TMFramer.hpp b/Svc/CCSDS/TmFramer/TmFramer.hpp similarity index 100% rename from Svc/CCSDS/TMFramer/TMFramer.hpp rename to Svc/CCSDS/TmFramer/TmFramer.hpp diff --git a/Svc/CCSDS/TMFramer/docs/sdd.md b/Svc/CCSDS/TmFramer/docs/sdd.md similarity index 100% rename from Svc/CCSDS/TMFramer/docs/sdd.md rename to Svc/CCSDS/TmFramer/docs/sdd.md diff --git a/Svc/CCSDS/TMFramer/test/ut/TMFramerTestMain.cpp b/Svc/CCSDS/TmFramer/test/ut/TmFramerTestMain.cpp similarity index 100% rename from Svc/CCSDS/TMFramer/test/ut/TMFramerTestMain.cpp rename to Svc/CCSDS/TmFramer/test/ut/TmFramerTestMain.cpp diff --git a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp b/Svc/CCSDS/TmFramer/test/ut/TmFramerTester.cpp similarity index 100% rename from Svc/CCSDS/TMFramer/test/ut/TMFramerTester.cpp rename to Svc/CCSDS/TmFramer/test/ut/TmFramerTester.cpp diff --git a/Svc/CCSDS/TMFramer/test/ut/TMFramerTester.hpp b/Svc/CCSDS/TmFramer/test/ut/TmFramerTester.hpp similarity index 100% rename from Svc/CCSDS/TMFramer/test/ut/TMFramerTester.hpp rename to Svc/CCSDS/TmFramer/test/ut/TmFramerTester.hpp diff --git a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp b/Svc/FrameAccumulator/FrameDetector/CcsdsTcFrameDetector.cpp similarity index 100% rename from Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.cpp rename to Svc/FrameAccumulator/FrameDetector/CcsdsTcFrameDetector.cpp diff --git a/Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.hpp b/Svc/FrameAccumulator/FrameDetector/CcsdsTcFrameDetector.hpp similarity index 100% rename from Svc/FrameAccumulator/FrameDetector/CcsdsTCFrameDetector.hpp rename to Svc/FrameAccumulator/FrameDetector/CcsdsTcFrameDetector.hpp From 333dec80afccfd83abb265ef5bfd433de74c8322 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Tue, 10 Jun 2025 14:24:55 -0700 Subject: [PATCH 94/95] oops forgot rename a test file --- ...FrameDetectorTestMain.cpp => CcsdsTcFrameDetectorTestMain.cpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Svc/FrameAccumulator/test/ut/detectors/{CcsdsTCFrameDetectorTestMain.cpp => CcsdsTcFrameDetectorTestMain.cpp} (100%) diff --git a/Svc/FrameAccumulator/test/ut/detectors/CcsdsTCFrameDetectorTestMain.cpp b/Svc/FrameAccumulator/test/ut/detectors/CcsdsTcFrameDetectorTestMain.cpp similarity index 100% rename from Svc/FrameAccumulator/test/ut/detectors/CcsdsTCFrameDetectorTestMain.cpp rename to Svc/FrameAccumulator/test/ut/detectors/CcsdsTcFrameDetectorTestMain.cpp From cdbbfe663479ed80f2b6268f239dab347019f266 Mon Sep 17 00:00:00 2001 From: thomas-bc Date: Wed, 11 Jun 2025 10:35:50 -0700 Subject: [PATCH 95/95] review changes: add annotations on all FPP ports --- Svc/CCSDS/ApidManager/ApidManager.fpp | 3 +++ Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp | 1 + Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.fpp | 4 ++++ 3 files changed, 8 insertions(+) diff --git a/Svc/CCSDS/ApidManager/ApidManager.fpp b/Svc/CCSDS/ApidManager/ApidManager.fpp index 1631012ecda..747d8a68ded 100644 --- a/Svc/CCSDS/ApidManager/ApidManager.fpp +++ b/Svc/CCSDS/ApidManager/ApidManager.fpp @@ -2,8 +2,11 @@ module Svc { module CCSDS { @ Maps output of ComQueue to CCSDS APIDs passive component ApidManager { + + @ Port to validate a given sequence count for a given APID guarded input port validateApidSeqCountIn: CCSDS.ApidSequenceCount + @ Port to request a sequence count for a given APID guarded input port getApidSeqCountIn: CCSDS.ApidSequenceCount @ Deframing received an unexpected sequence count diff --git a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp index d80bc91d8e1..34ae29a66b3 100644 --- a/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp +++ b/Svc/CCSDS/SpacePacketDeframer/SpacePacketDeframer.fpp @@ -5,6 +5,7 @@ module CCSDS { include "../../Interfaces/DeframerInterface.fppi" + @ Port to validate a received sequence count for a given APID output port validateApidSeqCount: CCSDS.ApidSequenceCount @ Deframing received an invalid frame length diff --git a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.fpp b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.fpp index 03aa9bfda5c..bb12f44684a 100644 --- a/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.fpp +++ b/Svc/CCSDS/SpacePacketFramer/SpacePacketFramer.fpp @@ -5,9 +5,13 @@ module CCSDS { include "../../Interfaces/FramerInterface.fppi" + @ Port to allocate a buffer for a space packet output port bufferAllocate: Fw.BufferGet + + @ Port to deallocate a buffer once space packet is sent output port bufferDeallocate: Fw.BufferSend + @ Port to retrieve the current sequence count for a given APID output port getApidSeqCount: CCSDS.ApidSequenceCount ###############################################################################