Add missing implementation of GenericHub (#4420)

* Revise GenericHub model

* Revise GenericHub model

* Revise GenericHub model

* Update spelling

* Revise annotations

* Revise annotations for GenericHub model

* Revise annotations in GenericHub model

* Revise GenericHub model

* Revise GenericHub model

* Revise GenericHub model

* Revise GenericHub

* Revise GenericHub

* Revise GenericHub model

* Revise GenericHub model

* Revise GenericHub config

* Revise GenericHub model

* Revise GenericHub model

* Clean up naming in GenericHub implementation

* Revise GenericHub port names

* Revise annotations in GenericHub model

* Revise annotations in GenericHub model

* Revise annotations in GenericHub model

* Add ByteStreamDriverClient

* Revise ByteStreamDriverClient

* Revise ByteStreamDriverClient

* Revise driver interfaces

* Add PassiveByteStreamDriverClientSendAsync interface

* Add PassiveAsyncByteStreamDriverClient interface

* Add PassiveBufferDriver

* Revise PassiveByteStreamDriverClient interfaces

* Revise PassiveBufferDriver

* Revise Drv interfaces

* Revise PassiveBufferDriver

* Add PassiveBufferDriverClient

* Revise GenericHub model

Use interfaces from Drv

* Revise annotations in GenericHub model

* Revise FPP models

Point FPP to a non-released version with a bug fix

* Add ByteStreamBufferAdapter

* Revise ByteStreamBufferAdapter model

* Revise ByteStreamBufferAdapter

* Revise ByteStreamBufferAdapter

* Add AsyncByteStreamBufferAdapter

* Revise AsyncByteStreamBufferAdapter

* Revsie AsyncByteStreamBufferAdapter

* Revise AsyncByteStreamBufferAdapter

* Revise annotations in FPP model

* Revise ByteStreamBufferAdapter

* Bump fpp version

* Revise GenericHub model

* Revise GenericHub interface

* Revise GenericHub interface

* Fix typo in FPP annotations

* Revise Generic Hub model

* Fix spelling and formatting

* Review recommendations

---------

Co-authored-by: Rob Bocchino <bocchino@jpl.nasa.gov>
Co-authored-by: thomas-bc <thomas.boyerchammard@gmail.com>
This commit is contained in:
mshahabn 2025-12-02 17:56:34 -08:00 committed by GitHub
parent cddf38bb6f
commit e0afd3c3fb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
34 changed files with 998 additions and 290 deletions

View File

@ -18,7 +18,6 @@ arduino
ARef
argcomplete
ARGN
binaryfile
ARINC
arpa
ASize
@ -36,6 +35,7 @@ bfree
BHn
bibtex
Bies
binaryfile
BINDIR
bitmaps
bitshifts
@ -43,6 +43,7 @@ bitwidth
bocchino
boolt
bsd
BSDI
bst
BUFFERALLOCATE
BUFFERALLOCATIONFAILED

View File

@ -0,0 +1,52 @@
// ======================================================================
// \title AsyncByteStreamBufferAdapter.cpp
// \author bocchino
// \brief cpp file for AsyncByteStreamBufferAdapter component implementation class
// ======================================================================
#include "Drv/AsyncByteStreamBufferAdapter/AsyncByteStreamBufferAdapter.hpp"
namespace Drv {
// ----------------------------------------------------------------------
// Component construction and destruction
// ----------------------------------------------------------------------
AsyncByteStreamBufferAdapter::AsyncByteStreamBufferAdapter(const char* const compName)
: AsyncByteStreamBufferAdapterComponentBase(compName) {}
AsyncByteStreamBufferAdapter::~AsyncByteStreamBufferAdapter() {}
// ----------------------------------------------------------------------
// Handler implementations for typed input ports
// ----------------------------------------------------------------------
void AsyncByteStreamBufferAdapter::bufferIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) {
// TODO: If m_driverIsReady then send fwBuffer on toByteStreamDriver_out
// TODO: Otherwise
// TODO: Log the error
// TODO: Send fwBuffer on bufferInReturn_out
}
void AsyncByteStreamBufferAdapter::bufferOutReturn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) {
// TODO: Send fwBuffer on fromByteStreamDriverReturn_out
}
void AsyncByteStreamBufferAdapter::byteStreamDriverReady_handler(FwIndexType portNum) {
this->m_driverIsReady = true;
}
void AsyncByteStreamBufferAdapter::fromByteStreamDriver_handler(FwIndexType portNum,
Fw::Buffer& buffer,
const Drv::ByteStreamStatus& status) {
// TODO: If the status is OK, then send buffer on toByteStreamDriver_out
// TODO: Otherwise log the error and send buffer on fromByteStreamDriverReturn_out
}
void AsyncByteStreamBufferAdapter::toByteStreamDriverReturn_handler(FwIndexType portNum,
Fw::Buffer& buffer,
const Drv::ByteStreamStatus& status) {
// TODO: Send fwBuffer on bufferInReturn_out
}
} // namespace Drv

View File

@ -0,0 +1,33 @@
module Drv {
@ A passive component for mediating between the AsyncByteStreamDriver
@ interface and the PassiveBufferDriver interface
@
@ Sample topology:
@
@ -----------------------------------------------------------
@ | |
@ | AsyncByteStreamDriver <--> AsyncByteStreamBufferAdapter | <--> PassiveBufferDriverClient
@ | |
@ -----------------------------------------------------------
@
@ The two components in the box function together as a PassiveBufferDriver:
@
@ -------------------------------------------------
@ | |
@ | PassiveBufferDriver | <--> PassiveBufferDriverClient
@ | |
@ -------------------------------------------------
@
passive component AsyncByteStreamBufferAdapter {
@ AsyncByteStreamBufferAdapter is a passive client of the
@ AsyncByteStreamDriver interface
import PassiveAsyncByteStreamDriverClient
@ AsyncByteStreamBufferAdapter is a PassiveBufferDriver
import PassiveBufferDriver
}
}

View File

@ -0,0 +1,80 @@
// ======================================================================
// \title AsyncByteStreamBufferAdapter.hpp
// \author bocchino
// \brief hpp file for AsyncByteStreamBufferAdapter component implementation class
// ======================================================================
#ifndef Drv_AsyncByteStreamBufferAdapter_HPP
#define Drv_AsyncByteStreamBufferAdapter_HPP
#include "Drv/AsyncByteStreamBufferAdapter/AsyncByteStreamBufferAdapterComponentAc.hpp"
namespace Drv {
class AsyncByteStreamBufferAdapter final : public AsyncByteStreamBufferAdapterComponentBase {
public:
// ----------------------------------------------------------------------
// Component construction and destruction
// ----------------------------------------------------------------------
//! Construct AsyncByteStreamBufferAdapter object
AsyncByteStreamBufferAdapter(const char* const compName //!< The component name
);
//! Destroy AsyncByteStreamBufferAdapter object
~AsyncByteStreamBufferAdapter();
private:
// ----------------------------------------------------------------------
// Handler implementations for typed input ports
// ----------------------------------------------------------------------
//! Handler implementation for bufferIn
//!
//! Port for receiving buffers
void bufferIn_handler(FwIndexType portNum, //!< The port number
Fw::Buffer& fwBuffer //!< The buffer
) override;
//! Handler implementation for bufferOutReturn
//!
//! Port for receiving buffers sent on bufferOut and then returned
void bufferOutReturn_handler(FwIndexType portNum, //!< The port number
Fw::Buffer& fwBuffer //!< The buffer
) override;
//! Handler implementation for byteStreamDriver
//!
//! Port for receiving ready signals from the driver
//! Sample connection: byteStreamDriver.ready -> byteStreamDriverClient.byteStreamReady
void byteStreamDriverReady_handler(FwIndexType portNum //!< The port number
) override;
//! Handler implementation for fromByteStreamDriver
//!
//! Port for receiving data from the driver
//! Sample connection: byteStreamDriver.$recv -> byteStreamDriverClient.fromDriver
void fromByteStreamDriver_handler(FwIndexType portNum, //!< The port number
Fw::Buffer& buffer,
const Drv::ByteStreamStatus& status) override;
//! Handler implementation for toByteStreamDriverReturn
//!
//! Port for receiving buffers sent on toByteStreamDriver and then returned
//! Sample connection: driver.sendReturnOut -> client.toByteStreamDriverReturn
void toByteStreamDriverReturn_handler(FwIndexType portNum, //!< The port number
Fw::Buffer& buffer,
const Drv::ByteStreamStatus& status) override;
private:
// ----------------------------------------------------------------------
// Private member variables
// ----------------------------------------------------------------------
//! Whether the driver is ready
bool m_driverIsReady = false;
};
} // namespace Drv
#endif

View File

@ -0,0 +1,10 @@
set(SOURCE_FILES
"${CMAKE_CURRENT_LIST_DIR}/AsyncByteStreamBufferAdapter.fpp"
"${CMAKE_CURRENT_LIST_DIR}/AsyncByteStreamBufferAdapter.cpp"
)
set(MOD_DEPS
"Fw/Logger"
)
register_fprime_module()

View File

@ -0,0 +1,47 @@
// ======================================================================
// \title ByteStreamBufferAdapter.cpp
// \author bocchino
// \brief cpp file for ByteStreamBufferAdapter component implementation class
// ======================================================================
#include "Drv/ByteStreamBufferAdapter/ByteStreamBufferAdapter.hpp"
namespace Drv {
// ----------------------------------------------------------------------
// Component construction and destruction
// ----------------------------------------------------------------------
ByteStreamBufferAdapter::ByteStreamBufferAdapter(const char* const compName)
: ByteStreamBufferAdapterComponentBase(compName) {}
ByteStreamBufferAdapter::~ByteStreamBufferAdapter() {}
// ----------------------------------------------------------------------
// Handler implementations for typed input ports
// ----------------------------------------------------------------------
void ByteStreamBufferAdapter::bufferIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) {
// TODO: If m_driverIsReady then
// TODO: Send fwBuffer on toByteStreamDriver_out
// TODO: Check the return status. If there is an error, then log it to the Logger.
// TODO: Otherwise log the error
// TODO: Send fwBuffer on bufferInReturn_out
}
void ByteStreamBufferAdapter::bufferOutReturn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) {
// TODO: Send fwBuffer on fromByteStreamDriverReturn_out
}
void ByteStreamBufferAdapter::fromByteStreamDriver_handler(FwIndexType portNum,
Fw::Buffer& buffer,
const Drv::ByteStreamStatus& status) {
// TODO: If the status is OK, then send buffer on toByteStreamDriver_out
// TODO: Otherwise log the error and send buffer on fromByteStreamDriverReturn_out
}
void ByteStreamBufferAdapter::byteStreamDriverReady_handler(FwIndexType portNum) {
this->m_driverIsReady = true;
}
} // namespace Drv

View File

@ -0,0 +1,33 @@
module Drv {
@ A passive component for mediating between the ByteStreamDriver
@ interface and the PassiveBufferDriver interface
@
@ Sample topology:
@
@ -------------------------------------------------
@ | |
@ | ByteStreamDriver <--> ByteStreamBufferAdapter | <--> PassiveBufferDriverClient
@ | |
@ -------------------------------------------------
@
@ The two components in the box function together as a PassiveBufferDriver:
@
@ -------------------------------------------------
@ | |
@ | PassiveBufferDriver | <--> PassiveBufferDriverClient
@ | |
@ -------------------------------------------------
@
passive component ByteStreamBufferAdapter {
@ ByteStreamBufferAdapter is a passive client of the ByteStreamDriver
@ interface
import PassiveByteStreamDriverClient
@ ByteStreamBufferAdapter is a PassiveBufferDriver
import PassiveBufferDriver
}
}

View File

@ -0,0 +1,72 @@
// ======================================================================
// \title ByteStreamBufferAdapter.hpp
// \author bocchino
// \brief hpp file for ByteStreamBufferAdapter component implementation class
// ======================================================================
#ifndef Drv_ByteStreamBufferAdapter_HPP
#define Drv_ByteStreamBufferAdapter_HPP
#include "Drv/ByteStreamBufferAdapter/ByteStreamBufferAdapterComponentAc.hpp"
namespace Drv {
class ByteStreamBufferAdapter final : public ByteStreamBufferAdapterComponentBase {
public:
// ----------------------------------------------------------------------
// Component construction and destruction
// ----------------------------------------------------------------------
//! Construct ByteStreamBufferAdapter object
ByteStreamBufferAdapter(const char* const compName //!< The component name
);
//! Destroy ByteStreamBufferAdapter object
~ByteStreamBufferAdapter();
private:
// ----------------------------------------------------------------------
// Handler implementations for typed input ports
// ----------------------------------------------------------------------
//! Handler implementation for bufferIn
//!
//! Port for receiving buffers
void bufferIn_handler(FwIndexType portNum, //!< The port number
Fw::Buffer& fwBuffer //!< The buffer
) override;
//! Handler implementation for bufferOutReturn
//!
//! Port for receiving buffers sent on bufferOut and then returned
void bufferOutReturn_handler(FwIndexType portNum, //!< The port number
Fw::Buffer& fwBuffer //!< The buffer
) override;
//! Handler implementation for byteStreamIn
//!
//! Port for receiving data from the driver
//! Sample connection: byteStreamDriver.$recv -> byteStreamDriverClient.byteStreamIn
void fromByteStreamDriver_handler(FwIndexType portNum, //!< The port number
Fw::Buffer& buffer,
const Drv::ByteStreamStatus& status) override;
//! Handler implementation for byteStreamReady
//!
//! Port for receiving ready signals from the driver
//! Sample connection: byteStreamDriver.ready -> byteStreamDriverClient.byteStreamDriverReady
void byteStreamDriverReady_handler(FwIndexType portNum //!< The port number
) override;
private:
// ----------------------------------------------------------------------
// Private member variables
// ----------------------------------------------------------------------
//! Whether the driver is ready
bool m_driverIsReady = false;
};
} // namespace Drv
#endif

View File

@ -0,0 +1,10 @@
set(SOURCE_FILES
"${CMAKE_CURRENT_LIST_DIR}/ByteStreamBufferAdapter.fpp"
"${CMAKE_CURRENT_LIST_DIR}/ByteStreamBufferAdapter.cpp"
)
set(MOD_DEPS
"Fw/Logger"
)
register_fprime_module()

View File

@ -5,11 +5,13 @@ add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Interfaces/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Ports/")
# Components
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/AsyncByteStreamBufferAdapter/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/ByteStreamBufferAdapter/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/ByteStreamDriverModel/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/LinuxGpioDriver/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/LinuxUartDriver/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/LinuxSpiDriver/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/LinuxI2cDriver/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/LinuxSpiDriver/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/LinuxUartDriver/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Ip/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/TcpClient/")

View File

@ -12,6 +12,11 @@ register_fprime_module(
"${CMAKE_CURRENT_LIST_DIR}/ByteStreamDriver.fpp"
"${CMAKE_CURRENT_LIST_DIR}/Gpio.fpp"
"${CMAKE_CURRENT_LIST_DIR}/I2c.fpp"
"${CMAKE_CURRENT_LIST_DIR}/PassiveAsyncByteStreamDriverClient.fpp"
"${CMAKE_CURRENT_LIST_DIR}/PassiveBufferDriver.fpp"
"${CMAKE_CURRENT_LIST_DIR}/PassiveBufferDriverClient.fpp"
"${CMAKE_CURRENT_LIST_DIR}/PassiveByteStreamDriverClient.fpp"
"${CMAKE_CURRENT_LIST_DIR}/PassiveByteStreamDriverClientReadyRecv.fpp"
"${CMAKE_CURRENT_LIST_DIR}/Spi.fpp"
"${CMAKE_CURRENT_LIST_DIR}/Tick.fpp"
INTERFACE

View File

@ -0,0 +1,25 @@
module Drv {
@ The send interface of passive client of an asynchronous byte stream driver
interface PassiveByteStreamDriverClientSendAsync {
@ Port for sending data to the driver
@ Sample connection: client.toByteStreamDriver -> driver.$send
output port toByteStreamDriver: Fw.BufferSend
@ Port for receiving buffers sent on toByteStreamDriver and then returned
@ Sample connection: driver.sendReturnOut -> client.toByteStreamDriverReturn
sync input port toByteStreamDriverReturn: Drv.ByteStreamData
}
@ A passive client of an asynchronous byte stream driver
interface PassiveAsyncByteStreamDriverClient {
import PassiveByteStreamDriverClientReadyRecv
import PassiveByteStreamDriverClientSendAsync
}
}

View File

@ -0,0 +1,14 @@
module Drv {
@ A passive buffer driver
interface PassiveBufferDriver {
@ The interface for sending data to the driver
import Fw.PassiveBufferIn
@ The interface for receiving data from the driver
import Fw.PassiveBufferOut
}
}

View File

@ -0,0 +1,40 @@
module Drv {
@ The send interface of passive client of a buffer driver
interface PassiveBufferDriverClientSend {
@ Port for sending data to the driver
@ Sample connection: client.toBufferDriver -> driver.bufferIn
output port toBufferDriver: Fw.BufferSend
@ Port for receiving buffers sent on toBufferDriver and then returned
@ Sample connection: driver.bufferInReturn -> client.toBufferDriverReturn
sync input port toBufferDriverReturn: Fw.BufferSend
}
@ The receive interface of passive client of a buffer driver
interface PassiveBufferDriverClientRecv {
@ Port for receiving data from the driver
@ Sample connection: driver.bufferOut -> client.fromBufferDriver
sync input port fromBufferDriver: Fw.BufferSend
@ Port for returning buffers received on fromBufferDriver
@ Sample connection: client.fromBufferDriverReturn -> driver.bufferOutReturn
output port fromBufferDriverReturn: Fw.BufferSend
}
@ A passive client of a buffer driver
interface PassiveBufferDriverClient {
@ The interface for sending data to the driver
import PassiveBufferDriverClientSend
@ The interface for receiving data from the driver
import PassiveBufferDriverClientRecv
}
}

View File

@ -0,0 +1,22 @@
module Drv {
@ The send interface of passive client of a synchronous byte stream driver
interface PassiveByteStreamDriverClientSendSync {
@ Port for sending data to the driver
@ Sample connection: client.toByteStreamDriver -> driver.$send
output port toByteStreamDriver: Drv.ByteStreamSend
}
@ A passive client of a synchronous byte stream driver
interface PassiveByteStreamDriverClient {
@ The ready and receive interfaces
import PassiveByteStreamDriverClientReadyRecv
@ The send interface
import PassiveByteStreamDriverClientSendSync
}
}

View File

@ -0,0 +1,26 @@
module Drv {
@ The ready and receive interfaces for a byte stream driver client
interface PassiveByteStreamDriverClientReadyRecv {
# ----------------------------------------------------------------------
# Ready interface
# ----------------------------------------------------------------------
@ Port for receiving ready signals from the driver
@ Sample connection: byteStreamDriver.ready -> byteStreamDriverClient.byteStreamDriverReady
sync input port byteStreamDriverReady: Drv.ByteStreamReady
# ----------------------------------------------------------------------
# Receive interface
# ----------------------------------------------------------------------
@ Port for receiving data from the driver
@ Sample connection: byteStreamDriver.$recv -> byteStreamDriverClient.fromDriver
sync input port fromByteStreamDriver: Drv.ByteStreamData
@ Port for returning ownership of buffers received on fromDriver
@ Sample connection: byteStreamDriverClient.byteStreamReturn -> byteStreamDriver.recvReturnIn
output port fromByteStreamDriverReturn: Fw.BufferSend
}
}

View File

@ -16,4 +16,26 @@ module Fw {
$size: FwSizeType
) -> Fw.Buffer
@ The bufferIn interface for a passive component
interface PassiveBufferIn {
@ Port for receiving buffers
sync input port bufferIn: BufferSend
@ Port for returning buffers received on bufferIn
output port bufferInReturn: BufferSend
}
@ The bufferOut interface for a passive component
interface PassiveBufferOut {
@ Port for sending buffers
output port bufferOut: BufferSend
@ Port for receiving buffers sent on bufferOut and then returned
sync input port bufferOutReturn: BufferSend
}
}

View File

@ -10,7 +10,7 @@ register_fprime_module(
AUTOCODER_INPUTS
"${CMAKE_CURRENT_LIST_DIR}/GenericHub.fpp"
SOURCES
"${CMAKE_CURRENT_LIST_DIR}/GenericHubComponentImpl.cpp"
"${CMAKE_CURRENT_LIST_DIR}/GenericHub.cpp"
EXCLUDE_FROM_ALL
)
### UTs ###

View File

@ -1,5 +1,5 @@
// ======================================================================
// \title GenericHubComponentImpl.cpp
// \title GenericHub.cpp
// \author mstarch
// \brief cpp file for GenericHub component implementation class
//
@ -11,7 +11,7 @@
// ======================================================================
#include <Fw/FPrimeBasicTypes.hpp>
#include <Svc/GenericHub/GenericHubComponentImpl.hpp>
#include <Svc/GenericHub/GenericHub.hpp>
#include "Fw/Logger/Logger.hpp"
#include "Fw/Types/Assert.hpp"
@ -24,19 +24,15 @@ namespace Svc {
// Construction, initialization, and destruction
// ----------------------------------------------------------------------
GenericHubComponentImpl ::GenericHubComponentImpl(const char* const compName) : GenericHubComponentBase(compName) {}
GenericHub::GenericHub(const char* const compName) : GenericHubComponentBase(compName) {}
GenericHubComponentImpl ::~GenericHubComponentImpl() {}
GenericHub::~GenericHub() {}
void GenericHubComponentImpl ::send_data(const HubType type,
const FwIndexType port,
const U8* data,
const FwSizeType size) {
void GenericHub::send_data(const HubType type, const FwIndexType port, const U8* data, const FwSizeType size) {
FW_ASSERT(data != nullptr);
Fw::SerializeStatus status;
// Buffer to send and a buffer used to write to it
Fw::Buffer outgoing =
dataOutAllocate_out(0, static_cast<U32>(size + sizeof(U32) + sizeof(U32) + sizeof(FwBuffSizeType)));
Fw::Buffer outgoing = allocate_out(0, static_cast<U32>(size + sizeof(U32) + sizeof(U32) + sizeof(FwBuffSizeType)));
auto serialize = outgoing.getSerializer();
// Write data to our buffer
status = serialize.serializeFrom(static_cast<U32>(type));
@ -46,19 +42,24 @@ void GenericHubComponentImpl ::send_data(const HubType type,
status = serialize.serializeFrom(data, size);
FW_ASSERT(status == Fw::FW_SERIALIZE_OK, static_cast<FwAssertArgType>(status));
outgoing.setSize(static_cast<U32>(serialize.getSize()));
dataOut_out(0, outgoing);
toBufferDriver_out(0, outgoing);
}
// ----------------------------------------------------------------------
// Handler implementations for user-defined typed input ports
// ----------------------------------------------------------------------
void GenericHubComponentImpl ::buffersIn_handler(const FwIndexType portNum, Fw::Buffer& fwBuffer) {
void GenericHub::bufferIn_handler(const FwIndexType portNum, Fw::Buffer& fwBuffer) {
send_data(HUB_TYPE_BUFFER, portNum, fwBuffer.getData(), fwBuffer.getSize());
bufferDeallocate_out(0, fwBuffer);
bufferInReturn_out(portNum, fwBuffer);
}
void GenericHubComponentImpl ::dataIn_handler(const FwIndexType portNum, Fw::Buffer& fwBuffer) {
void GenericHub::bufferOutReturn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) {
// Return the buffer
fromBufferDriverReturn_out(0, fwBuffer);
}
void GenericHub::fromBufferDriver_handler(const FwIndexType portNum, Fw::Buffer& fwBuffer) {
HubType type = HUB_TYPE_MAX;
U32 type_in = 0;
U32 port = 0;
@ -85,13 +86,13 @@ void GenericHubComponentImpl ::dataIn_handler(const FwIndexType portNum, Fw::Buf
Fw::ExternalSerializeBuffer wrapper(rawData, rawSize);
status = wrapper.setBuffLen(rawSize);
FW_ASSERT(status == Fw::FW_SERIALIZE_OK, static_cast<FwAssertArgType>(status));
portOut_out(static_cast<FwIndexType>(port), wrapper);
serialOut_out(static_cast<FwIndexType>(port), wrapper);
// Deallocate the existing buffer
dataInDeallocate_out(0, fwBuffer);
fromBufferDriverReturn_out(0, fwBuffer);
} else if (type == HUB_TYPE_BUFFER) {
// Fw::Buffers can reuse the existing data buffer as the storage type! No deallocation done.
fwBuffer.set(rawData, rawSize, fwBuffer.getContext());
buffersOut_out(static_cast<FwIndexType>(port), fwBuffer);
bufferOut_out(static_cast<FwIndexType>(port), fwBuffer);
} else if (type == HUB_TYPE_EVENT) {
FwEventIdType id;
Fw::Time timeTag;
@ -109,10 +110,10 @@ void GenericHubComponentImpl ::dataIn_handler(const FwIndexType portNum, Fw::Buf
FW_ASSERT(status == Fw::FW_SERIALIZE_OK, static_cast<FwAssertArgType>(status));
// Send it!
this->LogSend_out(static_cast<FwIndexType>(port), id, timeTag, severity, args);
this->eventOut_out(static_cast<FwIndexType>(port), id, timeTag, severity, args);
// Deallocate the existing buffer
dataInDeallocate_out(0, fwBuffer);
fromBufferDriverReturn_out(0, fwBuffer);
} else if (type == HUB_TYPE_CHANNEL) {
FwChanIdType id;
Fw::Time timeTag;
@ -127,14 +128,19 @@ void GenericHubComponentImpl ::dataIn_handler(const FwIndexType portNum, Fw::Buf
FW_ASSERT(status == Fw::FW_SERIALIZE_OK, static_cast<FwAssertArgType>(status));
// Send it!
this->TlmSend_out(static_cast<FwIndexType>(port), id, timeTag, val);
this->tlmOut_out(static_cast<FwIndexType>(port), id, timeTag, val);
// Return the received buffer
fromBufferDriverReturn_out(0, fwBuffer);
}
}
void GenericHub::toBufferDriverReturn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) {
// Deallocate the existing buffer
dataInDeallocate_out(0, fwBuffer);
}
deallocate_out(portNum, fwBuffer);
}
void GenericHubComponentImpl ::LogRecv_handler(const FwIndexType portNum,
void GenericHub::eventIn_handler(const FwIndexType portNum,
FwEventIdType id,
Fw::Time& timeTag,
const Fw::LogSeverity& severity,
@ -156,10 +162,7 @@ void GenericHubComponentImpl ::LogRecv_handler(const FwIndexType portNum,
this->send_data(HubType::HUB_TYPE_EVENT, portNum, buffer, size);
}
void GenericHubComponentImpl ::TlmRecv_handler(const FwIndexType portNum,
FwChanIdType id,
Fw::Time& timeTag,
Fw::TlmBuffer& val) {
void GenericHub::tlmIn_handler(const FwIndexType portNum, FwChanIdType id, Fw::Time& timeTag, Fw::TlmBuffer& val) {
Fw::SerializeStatus status = Fw::FW_SERIALIZE_OK;
U8 buffer[sizeof(FwChanIdType) + Fw::Time::SERIALIZED_SIZE + FW_TLM_BUFFER_MAX_SIZE];
Fw::ExternalSerializeBuffer serializer(buffer, sizeof(buffer));
@ -178,7 +181,7 @@ void GenericHubComponentImpl ::TlmRecv_handler(const FwIndexType portNum,
// Handler implementations for user-defined serial input ports
// ----------------------------------------------------------------------
void GenericHubComponentImpl ::portIn_handler(FwIndexType portNum, /*!< The port number*/
void GenericHub::serialIn_handler(FwIndexType portNum, /*!< The port number*/
Fw::SerializeBufferBase& Buffer /*!< The serialization buffer*/
) {
send_data(HUB_TYPE_PORT, portNum, Buffer.getBuffAddr(), Buffer.getSize());

View File

@ -1,54 +1,187 @@
module Svc {
@ A generic hub component
@| ----------------------------------------------------------------------
@| A generic hub component
@| ----------------------------------------------------------------------
@| In F Prime, a *hub* is a mechanism for implementing logical port connections
@| that physically span two F Prime deployments. The pattern is called a "hub"
@| because any number of logical connections may be multiplexed through a single
@| pair of hubs. For example, a pair of logical connections like this
@|
@| A1 --> B1
@| A2 --> B2,
@|
@| where Ai and Bi are component instances in separate deployments A and B,
@| can be implemented using hubs HA and HB like this:
@|
@| A1 -->--+ +-->-- B1
@| | |
@| HA ~~> HB
@| | |
@| A2 -->--+ +-->-- B2
@|
@| The notation ~~> represents data transport between deployments,
@| e.g., via shared memory or across a network connection.
@|
@| The GenericHub component provides a generic capability for implementing a
@| hub. Typically there is a pair of instances of GenericHub, one in each
@| deployment, and each instance is paired with a driver for doing the
@| communication. Sending data between the deployments looks like this:
@|
@| FSW --> GenericHub --> Driver ~~> Driver --> GenericHub --> FSW
@|
@| The driver must be a *buffer driver*, i.e., any combination of component
@| instances that sends and receives Fw.Buffer objects across a network.
@| For example, the driver may be a pair consisting of (1) a ByteStreamDriver
@| component that implements ByteStreamDriverInterface and
@| (2) a ByteStreamBufferAdapter.
@|
@| The driver is specific to the transport mechanism.
@| The GenericHub may be paired with any driver that conforms to
@| its interface, and so can support any transport mechanism.
@| ----------------------------------------------------------------------
passive component GenericHub {
# ----------------------------------------------------------------------
# Mimic Ports
# Ports for sending data from FSW to the hub
# ----------------------------------------------------------------------
# These ports establish the "send" interface from the rest of FSW to the hub.
# ----------------------------------------------------------------------
# Each of these ports has the following behavior:
# 1. Invoke allocate to allocate a buffer B.
# 2. Serialize the hub message type (event, telemetry, serial, buffer),
# the port number, and the data into B.
# 3. Emit B on toBufferDriver.
#
# Sample connections:
#
# eventProducer.eventOut -> genericHub.eventIn
# telemetryProducer.tlmOut -> genericHub.tlmIn
#
# valueProducer0.valueOut[0] -> genericHub.serialIn[0]
# valueProducer1.valueOut[1] -> genericHub.serialIn[1]
#
# bufferProducer0.bufferOut -> genericHub.bufferIn[0]
# genericHub.bufferInReturn[0] -> bufferProducer0.bufferIn
# bufferProducer1.bufferOut -> genericHub.bufferIn[1]
# genericHub.bufferInReturn[1] -> bufferProducer1.bufferIn
# ----------------------------------------------------------------------
@ Telemetry input port for mimicking an event processor
sync input port TlmRecv: Fw.Tlm
@ Port for sending events to the hub
sync input port eventIn: Fw.Log
@ Event input port for mimicking an event processor
sync input port LogRecv: Fw.Log
@ Port for sending telemetry to the hub
sync input port tlmIn: Fw.Tlm
@ Cross-hub event output port
output port LogSend: Fw.Log
@ Ports for sending serial data to the hub
@ You can connect any typed output ports to these input ports, so
@ long as the data carried by the ports is serialized by value.
@ Do not connect ports that emit Fw.Buffer objects, because these objects
@ store pointers to data that is not serialized across the port
@ interface. To connect output ports that emit buffers, use
@ buffersIn below.
sync input port serialIn: [GenericHubCfg.NumSerialInputPorts] serial
@ Cross-hub telemetry output port
output port TlmSend: Fw.Tlm
@ Ports for sending buffer data to the hub
@ Output ports connected to these ports must emit Fw.Buffer objects.
@ On invocation, each of these ports allocates a new buffer B, copies the
@ data from the incoming buffer to B, and returns the incoming
@ buffer to the sender for deallocation.
@
sync input port bufferIn: [GenericHubCfg.NumBufferInputPorts] Fw.BufferSend
@ Ports for returning buffers arriving on buffersIn
output port bufferInReturn: [GenericHubCfg.NumBufferInputPorts] Fw.BufferSend
@ bufferIn and bufferInReturn ports must match
match bufferIn with bufferInReturn
# ----------------------------------------------------------------------
# General Ports
# Ports for sending data from the hub to a buffer driver
# ----------------------------------------------------------------------
# These ports establish the "send" interface from the hub to a buffer driver.
#
# Sample connections:
#
# genericHub.allocate -> bufferManager.bufferGetCallee
# genericHub.toBufferDriver -> bufferDriver.bufferIn
# bufferDriver.bufferInReturn -> genericHub.toBufferDriverReturn
# genericHub.deallocate -> bufferManager.bufferSendIn
# ----------------------------------------------------------------------
@ Input array of generic ports to shuttle to the other side of the hub connection
sync input port portIn: [GenericHubInputPorts] serial
@ This interface provides ports allocate and deallocate
import Svc.BufferAllocation
@ Output array of generic ports shuttled from the other side of the hub connection
output port portOut: [GenericHubOutputPorts] serial
@ This interface provides ports toBufferDriver and toBufferDriverReturn
import Drv.PassiveBufferDriverClientSend
@ Input array of generic ports shuttling in copy-free buffers form external sources
sync input port buffersIn: [GenericHubInputBuffers] Fw.BufferSend
# ----------------------------------------------------------------------
# Ports for receiving data from a buffer driver to the hub
# ----------------------------------------------------------------------
# These ports establish the "receive" interface from a driver to the hub.
# Each of these ports has the following behavior:
# 1. Unpack the incoming buffer into hub message type, port number, and data.
# 2. If the hub message type is event, telemetry, or serial,
# then pass the data by value to the receiver and invoke fromBufferDriverReturn
# to return the incoming buffer for deallocation.
# 3. Otherwise adjust the metadata of the incoming buffer to point
# to the data, and emit the same buffer on bufferOut. When the
# buffer is returned on bufferOutReturn, invoke fromBufferDriverReturn to return it.
#
# Sample connections:
#
# bufferDriver.bufferOut -> genericHub.fromBufferDriver
# genericHub.fromBufferDriverReturn -> bufferDriver.bufferOutReturn
# ----------------------------------------------------------------------
@ Output array of generic ports shuttling in copy-free buffers form external sources
output port buffersOut: [GenericHubOutputBuffers] Fw.BufferSend
@ This interface provides ports fromBufferDriver and fromBufferDriverReturn
import Drv.PassiveBufferDriverClientRecv
@ Buffer return from incoming bufferIn calls
output port bufferDeallocate: Fw.BufferSend
# ----------------------------------------------------------------------
# Ports for receiving data from the hub to FSW
# ----------------------------------------------------------------------
# These ports establish the "receive" interface from the hub to FSW
#
# Sample connections:
#
# genericHub.eventOut -> eventManager.eventIn
# genericHub.tlmOut -> tlmDb.eventIn
#
# genericHub.serialOut[0] -> valueConsumer0.valueIn[0]
# genericHub.serialOut[1] -> valueConsumer1.valueIn[1]
#
# genericHub.bufferOut[0] -> bufferConsumer0.bufferIn
# bufferConsumer0.bufferInReturn -> genericHub.bufferOutReturn[0]
# genericHub.bufferOut[1] -> bufferConsumer1.bufferIn
# bufferConsumer1.bufferInReturn -> genericHub.bufferOutReturn[1]
# ----------------------------------------------------------------------
@ Data output to remote hub
output port dataOut: Fw.BufferSend
@ Port for receiving events
@ Data emitted on this port is copied from a buffer received on fromBufferDriver,
@ and the buffer is returned.
output port eventOut: Fw.Log
@ Data input from remote hub
sync input port dataIn: Fw.BufferSend
@ Port for receiving telemetry channels
@ Data emitted on this port is copied from a buffer received on fromBufferDriver,
@ and the buffer is returned.
output port tlmOut: Fw.Tlm
@ Deallocation of buffer passed into data in
output port dataInDeallocate: Fw.BufferSend
@ Ports for receiving serial data
@ You can connect each of these output ports to any typed input port.
@ Data emitted on one of these ports is copied from a buffer received on fromBufferDriver,
@ and the buffer is returned.
output port serialOut: [GenericHubCfg.NumSerialOutputPorts] serial
@ Allocation of buffer passed to passed out dataOut
output port dataOutAllocate: Fw.BufferGet
@ Ports for receiving buffer data
@ A buffer emitted on one of these ports is a buffer received on fromBufferDriver,
@ With adjusted metadata to point to the data stored in the buffer.
output port bufferOut: [GenericHubCfg.NumBufferOutputPorts] Fw.BufferSend
@ Ports for receiving buffers sent on bufferOut and then returned
sync input port bufferOutReturn: [GenericHubCfg.NumBufferOutputPorts] Fw.BufferSend
@ bufferOut and bufferOutReturn ports must match
match bufferOut with bufferOutReturn
}

View File

@ -1,17 +1,110 @@
// ======================================================================
// GenericHub.hpp
// Standardization header for GenericHub
// \title GenericHub.hpp
// \author mstarch
// \brief hpp file for GenericHub component implementation class
//
// \copyright
// Copyright 2009-2015, by the California Institute of Technology.
// ALL RIGHTS RESERVED. United States Government Sponsorship
// acknowledged.
//
// ======================================================================
#ifndef Svc_GenericHub_HPP
#define Svc_GenericHub_HPP
#include "Svc/GenericHub/GenericHubComponentImpl.hpp"
#include "Svc/GenericHub/GenericHubComponentAc.hpp"
namespace Svc {
using GenericHub = GenericHubComponentImpl;
class GenericHub final : public GenericHubComponentBase {
public:
/**
* HubType:
*
* Type of serialized data on the wire. Allows for expanding them on the opposing end.
*/
enum HubType {
HUB_TYPE_PORT, //!< Port type transmission
HUB_TYPE_BUFFER, //!< Buffer type transmission
HUB_TYPE_EVENT, //!< Event transmission
HUB_TYPE_CHANNEL, //!< Telemetry channel type
HUB_TYPE_MAX
};
}
// ----------------------------------------------------------------------
// Construction, initialization, and destruction
// ----------------------------------------------------------------------
//! Construct object GenericHub
//!
GenericHub(const char* const compName /*!< The component name*/
);
//! Destroy object GenericHub
//!
~GenericHub();
private:
// ----------------------------------------------------------------------
// Handler implementations for user-defined typed input ports
// ----------------------------------------------------------------------
//! Handler implementation for bufferIn
//!
void bufferIn_handler(const FwIndexType portNum, /*!< The port number*/
Fw::Buffer& fwBuffer) override;
//! Handler implementation for bufferOutReturn
//!
//! Ports for receiving buffers sent on bufferOut and then returned
void bufferOutReturn_handler(FwIndexType portNum, //!< The port number
Fw::Buffer& fwBuffer //!< The buffer
) override;
//! Handler implementation for fromBufferDriver
//!
void fromBufferDriver_handler(const FwIndexType portNum, /*!< The port number*/
Fw::Buffer& fwBuffer) override;
//! Handler implementation for toBufferDriverReturn
//!
//! Port for receiving buffers sent on toBufferDriver and then returned
void toBufferDriverReturn_handler(FwIndexType portNum, //!< The port number
Fw::Buffer& fwBuffer //!< The buffer
) override;
//! Handler implementation for eventIn
//!
void eventIn_handler(const FwIndexType portNum, /*!< The port number*/
FwEventIdType id, /*!< Log ID */
Fw::Time& timeTag, /*!< Time Tag */
const Fw::LogSeverity& severity, /*!< The severity argument */
Fw::LogBuffer& args /*!< Buffer containing serialized log entry */
) override;
//! Handler implementation for tlmIn
//!
void tlmIn_handler(const FwIndexType portNum, /*!< The port number*/
FwChanIdType id, /*!< Telemetry Channel ID */
Fw::Time& timeTag, /*!< Time Tag */
Fw::TlmBuffer& val /*!< Buffer containing serialized telemetry value */
) override;
// ----------------------------------------------------------------------
// Handler implementations for user-defined serial input ports
// ----------------------------------------------------------------------
//! Handler implementation for serialIn
//!
void serialIn_handler(FwIndexType portNum, /*!< The port number*/
Fw::SerializeBufferBase& Buffer /*!< The serialization buffer*/
) override;
// Helpers and members
void send_data(const HubType type, const FwIndexType port, const U8* data, const FwSizeType size);
};
} // end namespace Svc
#endif

View File

@ -1,97 +0,0 @@
// ======================================================================
// \title GenericHubComponentImpl.hpp
// \author mstarch
// \brief hpp file for GenericHub component implementation class
//
// \copyright
// Copyright 2009-2015, by the California Institute of Technology.
// ALL RIGHTS RESERVED. United States Government Sponsorship
// acknowledged.
//
// ======================================================================
#ifndef GenericHub_HPP
#define GenericHub_HPP
#include "Svc/GenericHub/GenericHubComponentAc.hpp"
namespace Svc {
class GenericHubComponentImpl final : public GenericHubComponentBase {
public:
/**
* HubType:
*
* Type of serialized data on the wire. Allows for expanding them on the opposing end.
*/
enum HubType {
HUB_TYPE_PORT, //!< Port type transmission
HUB_TYPE_BUFFER, //!< Buffer type transmission
HUB_TYPE_EVENT, //!< Event transmission
HUB_TYPE_CHANNEL, //!< Telemetry channel type
HUB_TYPE_MAX
};
constexpr static FwSizeType GENERIC_HUB_DATA_SIZE = 1024;
// ----------------------------------------------------------------------
// Construction, initialization, and destruction
// ----------------------------------------------------------------------
//! Construct object GenericHub
//!
GenericHubComponentImpl(const char* const compName /*!< The component name*/
);
//! Destroy object GenericHub
//!
~GenericHubComponentImpl();
private:
// ----------------------------------------------------------------------
// Handler implementations for user-defined typed input ports
// ----------------------------------------------------------------------
//! Handler implementation for buffersIn
//!
void buffersIn_handler(const FwIndexType portNum, /*!< The port number*/
Fw::Buffer& fwBuffer);
//! Handler implementation for dataIn
//!
void dataIn_handler(const FwIndexType portNum, /*!< The port number*/
Fw::Buffer& fwBuffer);
//! Handler implementation for LogRecv
//!
void LogRecv_handler(const FwIndexType portNum, /*!< The port number*/
FwEventIdType id, /*!< Log ID */
Fw::Time& timeTag, /*!< Time Tag */
const Fw::LogSeverity& severity, /*!< The severity argument */
Fw::LogBuffer& args /*!< Buffer containing serialized log entry */
);
//! Handler implementation for TlmRecv
//!
void TlmRecv_handler(const FwIndexType portNum, /*!< The port number*/
FwChanIdType id, /*!< Telemetry Channel ID */
Fw::Time& timeTag, /*!< Time Tag */
Fw::TlmBuffer& val /*!< Buffer containing serialized telemetry value */
);
// ----------------------------------------------------------------------
// Handler implementations for user-defined serial input ports
// ----------------------------------------------------------------------
//! Handler implementation for portIn
//!
void portIn_handler(FwIndexType portNum, /*!< The port number*/
Fw::SerializeBufferBase& Buffer /*!< The serialization buffer*/
);
// Helpers and members
void send_data(const HubType type, const FwIndexType port, const U8* data, const FwSizeType size);
};
} // end namespace Svc
#endif

View File

@ -43,21 +43,22 @@ GenericHubTester ::~GenericHubTester() {}
// ----------------------------------------------------------------------
void GenericHubTester ::test_in_out() {
U32 max = std::min(this->componentIn.getNum_portIn_InputPorts(), this->componentOut.getNum_portOut_OutputPorts());
U32 max =
std::min(this->componentIn.getNum_serialIn_InputPorts(), this->componentOut.getNum_serialOut_OutputPorts());
for (U32 i = 0; i < max; i++) {
send_random_comm(i);
ASSERT_from_dataInDeallocate_SIZE(1);
fromPortHistory_dataInDeallocate->clear();
ASSERT_from_fromBufferDriverReturn_SIZE(1);
fromPortHistory_fromBufferDriverReturn->clear();
}
}
void GenericHubTester ::test_buffer_io() {
U32 max =
std::min(this->componentIn.getNum_buffersIn_InputPorts(), this->componentOut.getNum_buffersOut_OutputPorts());
std::min(this->componentIn.getNum_bufferIn_InputPorts(), this->componentOut.getNum_bufferOut_OutputPorts());
for (U32 i = 0; i < max; i++) {
send_random_buffer(i);
ASSERT_from_dataInDeallocate_SIZE(1);
fromPortHistory_dataInDeallocate->clear();
ASSERT_from_fromBufferDriverReturn_SIZE(1);
fromPortHistory_fromBufferDriverReturn->clear();
}
}
@ -65,18 +66,18 @@ void GenericHubTester ::test_random_io() {
for (U32 i = 0; i < 10000; i++) {
U32 choice = STest::Pick::lowerUpper(0, 1);
if (choice) {
U32 port = STest::Pick::lowerUpper(0, std::min(this->componentIn.getNum_portIn_InputPorts(),
this->componentOut.getNum_portOut_OutputPorts()) -
U32 port = STest::Pick::lowerUpper(0, std::min(this->componentIn.getNum_serialIn_InputPorts(),
this->componentOut.getNum_serialOut_OutputPorts()) -
1);
send_random_comm(port);
} else {
U32 port = STest::Pick::lowerUpper(0, std::min(this->componentIn.getNum_buffersIn_InputPorts(),
this->componentOut.getNum_buffersOut_OutputPorts()) -
U32 port = STest::Pick::lowerUpper(0, std::min(this->componentIn.getNum_bufferIn_InputPorts(),
this->componentOut.getNum_bufferOut_OutputPorts()) -
1);
send_random_buffer(port);
}
ASSERT_from_dataInDeallocate_SIZE(1);
fromPortHistory_dataInDeallocate->clear();
ASSERT_from_fromBufferDriverReturn_SIZE(1);
fromPortHistory_fromBufferDriverReturn->clear();
}
}
@ -90,15 +91,16 @@ void GenericHubTester ::random_fill(Fw::SerializeBufferBase& buffer, U32 max_siz
void GenericHubTester ::test_telemetry() {
Fw::TlmBuffer buffer;
clearFromPortHistory();
random_fill(buffer, FW_TLM_BUFFER_MAX_SIZE);
Fw::Time time(100, 200);
invoke_to_TlmRecv(0, 123, time, buffer);
invoke_to_tlmIn(0, 123, time, buffer);
// **must** deallocate buffer
ASSERT_from_dataInDeallocate_SIZE(1);
ASSERT_from_TlmSend_SIZE(1);
ASSERT_from_TlmSend(0, 123, time, buffer);
// **must** return buffer
ASSERT_from_fromBufferDriverReturn_SIZE(1);
ASSERT_from_tlmOut_SIZE(1);
ASSERT_from_tlmOut(0, 123, time, buffer);
clearFromPortHistory();
}
@ -108,12 +110,12 @@ void GenericHubTester ::test_events() {
random_fill(buffer, FW_LOG_BUFFER_MAX_SIZE);
Fw::Time time(100, 200);
invoke_to_LogRecv(0, 123, time, severity, buffer);
invoke_to_eventIn(0, 123, time, severity, buffer);
// **must** deallocate buffer
ASSERT_from_dataInDeallocate_SIZE(1);
ASSERT_from_LogSend_SIZE(1);
ASSERT_from_LogSend(0, 123, time, severity, buffer);
ASSERT_from_fromBufferDriverReturn_SIZE(1);
ASSERT_from_eventOut_SIZE(1);
ASSERT_from_eventOut(0, 123, time, severity, buffer);
clearFromPortHistory();
}
// Helpers
@ -121,9 +123,9 @@ void GenericHubTester ::test_events() {
void GenericHubTester ::send_random_comm(U32 port) {
random_fill(m_comm, FW_COM_BUFFER_MAX_SIZE);
m_current_port = port;
invoke_to_portIn(m_current_port, m_comm);
// Ensure that the data out was called, and that the portOut unwrapped properly
ASSERT_from_dataOut_SIZE(m_comm_in + m_buffer_out + 1);
invoke_to_serialIn(m_current_port, m_comm);
// Ensure that the data out was called, and that the serialOut unwrapped properly
ASSERT_from_toBufferDriver_SIZE(m_comm_in + m_buffer_out + 1);
ASSERT_EQ(m_comm_in + 1, m_comm_out);
m_comm_in++;
}
@ -136,12 +138,12 @@ void GenericHubTester ::send_random_buffer(U32 port) {
random_fill(serializer, max_random_size);
m_buffer.setSize(max_random_size);
m_current_port = port;
invoke_to_buffersIn(m_current_port, m_buffer);
ASSERT_from_bufferDeallocate_SIZE(1);
ASSERT_from_bufferDeallocate(0, m_buffer);
fromPortHistory_bufferDeallocate->clear();
// Ensure that the data out was called, and that the portOut unwrapped properly
ASSERT_from_dataOut_SIZE(m_buffer_in + m_comm_out + 1);
invoke_to_bufferIn(m_current_port, m_buffer);
ASSERT_from_bufferInReturn_SIZE(1);
ASSERT_from_bufferInReturn(0, m_buffer);
fromPortHistory_bufferInReturn->clear();
// Ensure that the data out was called, and that the serialOut unwrapped properly
ASSERT_from_toBufferDriver_SIZE(m_buffer_in + m_comm_out + 1);
ASSERT_EQ(m_buffer_in + 1, m_buffer_out);
m_buffer_in++;
}
@ -150,36 +152,36 @@ void GenericHubTester ::send_random_buffer(U32 port) {
// Handlers for typed from ports
// ----------------------------------------------------------------------
void GenericHubTester ::from_LogSend_handler(const FwIndexType portNum,
void GenericHubTester ::from_eventOut_handler(const FwIndexType portNum,
FwEventIdType id,
Fw::Time& timeTag,
const Fw::LogSeverity& severity,
Fw::LogBuffer& args) {
this->pushFromPortEntry_LogSend(id, timeTag, severity, args);
this->pushFromPortEntry_eventOut(id, timeTag, severity, args);
}
void GenericHubTester ::from_TlmSend_handler(const FwIndexType portNum,
void GenericHubTester ::from_tlmOut_handler(const FwIndexType portNum,
FwChanIdType id,
Fw::Time& timeTag,
Fw::TlmBuffer& val) {
this->pushFromPortEntry_TlmSend(id, timeTag, val);
this->pushFromPortEntry_tlmOut(id, timeTag, val);
}
void GenericHubTester ::from_dataOut_handler(const FwIndexType portNum, Fw::Buffer& fwBuffer) {
void GenericHubTester ::from_toBufferDriver_handler(const FwIndexType portNum, Fw::Buffer& fwBuffer) {
ASSERT_NE(fwBuffer.getData(), nullptr) << "Empty buffer to deallocate";
ASSERT_GE(fwBuffer.getData(), m_data_for_allocation) << "Incorrect data pointer deallocated";
ASSERT_LT(fwBuffer.getData(), m_data_for_allocation + sizeof(m_data_for_allocation))
<< "Incorrect data pointer deallocated";
// Reuse m_allocate to pass into the otherside of the hub
this->pushFromPortEntry_dataOut(fwBuffer);
invoke_to_dataIn(0, fwBuffer);
this->pushFromPortEntry_toBufferDriver(fwBuffer);
invoke_to_fromBufferDriver(0, fwBuffer);
}
// ----------------------------------------------------------------------
// Handlers for serial from ports
// ----------------------------------------------------------------------
void GenericHubTester ::from_buffersOut_handler(const FwIndexType portNum, Fw::Buffer& fwBuffer) {
void GenericHubTester ::from_bufferOut_handler(const FwIndexType portNum, Fw::Buffer& fwBuffer) {
m_buffer_out++;
// Assert the buffer came through exactly on the right port
ASSERT_EQ(portNum, m_current_port);
@ -189,11 +191,12 @@ void GenericHubTester ::from_buffersOut_handler(const FwIndexType portNum, Fw::B
U8 byte2 = reinterpret_cast<U8*>(m_buffer.getData())[i];
ASSERT_EQ(byte1, byte2);
}
// Pretend to deallocate like file uplink would
this->from_dataInDeallocate_handler(0, fwBuffer);
this->invoke_to_bufferOutReturn(portNum, fwBuffer);
// this->from_fromBufferDriverReturn_handler(0, fwBuffer);
}
void GenericHubTester ::from_portOut_handler(FwIndexType portNum, /*!< The port number*/
void GenericHubTester ::from_serialOut_handler(FwIndexType portNum, /*!< The port number*/
Fw::SerializeBufferBase& Buffer /*!< The serialization buffer*/
) {
m_comm_out++;
@ -203,31 +206,32 @@ void GenericHubTester ::from_portOut_handler(FwIndexType portNum, /*!
for (U32 i = 0; i < Buffer.getSize(); i++) {
ASSERT_EQ(Buffer.getBuffAddr()[i], m_comm.getBuffAddr()[i]);
}
ASSERT_from_buffersOut_SIZE(0);
ASSERT_from_bufferOut_SIZE(0);
}
Fw::Buffer GenericHubTester ::from_dataOutAllocate_handler(const FwIndexType portNum, const FwSizeType size) {
Fw::Buffer GenericHubTester ::from_allocate_handler(const FwIndexType portNum, const FwSizeType size) {
EXPECT_EQ(m_allocate.getData(), nullptr) << "Allocation buffer is still in use";
EXPECT_LE(size, sizeof(m_data_for_allocation)) << "Allocation buffer is still in use";
EXPECT_LE(size, sizeof(m_data_for_allocation)) << "Allocation buffer size mismatch";
m_allocate.set(m_data_for_allocation, size);
return m_allocate;
}
void GenericHubTester ::from_bufferDeallocate_handler(const FwIndexType portNum, Fw::Buffer& fwBuffer) {
void GenericHubTester ::from_bufferInReturn_handler(const FwIndexType portNum, Fw::Buffer& fwBuffer) {
// Check buffer deallocations here
ASSERT_EQ(fwBuffer.getData(), m_buffer.getData()) << "Ensure that the buffer was deallocated";
ASSERT_EQ(fwBuffer.getSize(), m_buffer.getSize()) << "Ensure that the buffer was deallocated";
this->pushFromPortEntry_bufferDeallocate(fwBuffer);
this->pushFromPortEntry_bufferInReturn(fwBuffer);
}
void GenericHubTester ::from_dataInDeallocate_handler(const FwIndexType portNum, Fw::Buffer& fwBuffer) {
void GenericHubTester ::from_fromBufferDriverReturn_handler(const FwIndexType portNum, Fw::Buffer& fwBuffer) {
ASSERT_NE(fwBuffer.getData(), nullptr) << "Empty buffer to deallocate";
ASSERT_GE(fwBuffer.getData(), m_data_for_allocation) << "Incorrect data pointer deallocated";
ASSERT_LT(fwBuffer.getData(), m_data_for_allocation + sizeof(m_data_for_allocation))
<< "Incorrect data pointer deallocated";
this->pushFromPortEntry_fromBufferDriverReturn(fwBuffer);
invoke_to_toBufferDriverReturn(portNum, fwBuffer);
m_allocate.set(nullptr, 0);
this->pushFromPortEntry_dataInDeallocate(fwBuffer);
}
// ----------------------------------------------------------------------
@ -235,59 +239,72 @@ void GenericHubTester ::from_dataInDeallocate_handler(const FwIndexType portNum,
// ----------------------------------------------------------------------
void GenericHubTester ::connectPorts() {
// buffersIn
// bufferIn
U32 max =
std::min(this->componentIn.getNum_buffersIn_InputPorts(), this->componentOut.getNum_buffersOut_OutputPorts());
std::min(this->componentIn.getNum_bufferIn_InputPorts(), this->componentOut.getNum_bufferOut_OutputPorts());
for (U32 i = 0; i < max; ++i) {
this->connect_to_buffersIn(i, this->componentIn.get_buffersIn_InputPort(i));
this->connect_to_bufferIn(i, this->componentIn.get_bufferIn_InputPort(i));
}
// LogRecv
this->connect_to_LogRecv(0, this->componentIn.get_LogRecv_InputPort(0));
// eventIn
this->connect_to_eventIn(0, this->componentIn.get_eventIn_InputPort(0));
// TlmRecv
this->connect_to_TlmRecv(0, this->componentIn.get_TlmRecv_InputPort(0));
// tlmIn
this->connect_to_tlmIn(0, this->componentIn.get_tlmIn_InputPort(0));
// dataIn
this->connect_to_dataIn(0, this->componentOut.get_dataIn_InputPort(0));
// fromBufferDriver
this->connect_to_fromBufferDriver(0, this->componentOut.get_fromBufferDriver_InputPort(0));
// buffersOut
// bufferOut
for (U32 i = 0; i < max; ++i) {
this->componentOut.set_buffersOut_OutputPort(i, this->get_from_buffersOut(i));
this->componentOut.set_bufferOut_OutputPort(i, this->get_from_bufferOut(i));
}
// LogSend
this->componentOut.set_LogSend_OutputPort(0, this->get_from_LogSend(0));
// eventOut
this->componentOut.set_eventOut_OutputPort(0, this->get_from_eventOut(0));
// TlmSend
this->componentOut.set_TlmSend_OutputPort(0, this->get_from_TlmSend(0));
// tlmOut
this->componentOut.set_tlmOut_OutputPort(0, this->get_from_tlmOut(0));
// dataOut
this->componentIn.set_dataOut_OutputPort(0, this->get_from_dataOut(0));
// toBufferDriver
this->componentIn.set_toBufferDriver_OutputPort(0, this->get_from_toBufferDriver(0));
// toBufferDriverReturn
this->connect_to_toBufferDriverReturn(0, this->componentIn.get_toBufferDriverReturn_InputPort(0));
// bufferOutReturn
for (U32 i = 0; i < max; ++i) {
this->connect_to_bufferOutReturn(i, this->componentOut.get_bufferOutReturn_InputPort(i));
}
// bufferAllocate
this->componentIn.set_dataOutAllocate_OutputPort(0, this->get_from_dataOutAllocate(0));
this->componentIn.set_allocate_OutputPort(0, this->get_from_allocate(0));
// buffer Return
this->componentOut.set_fromBufferDriverReturn_OutputPort(0, this->get_from_fromBufferDriverReturn(0));
// dataDeallocate
this->componentOut.set_dataInDeallocate_OutputPort(0, this->get_from_dataInDeallocate(0));
this->componentIn.set_deallocate_OutputPort(0, this->get_from_deallocate(0));
// bufferDeallocate
this->componentIn.set_bufferDeallocate_OutputPort(0, this->get_from_bufferDeallocate(0));
// bufferInReturn
for (FwIndexType i = 0; i < GenericHubCfg::NumBufferInputPorts; i++) {
this->componentIn.set_bufferInReturn_OutputPort(i, this->get_from_bufferInReturn(i));
}
// ----------------------------------------------------------------------
// Connect serial output ports
// ----------------------------------------------------------------------
max = std::min(this->componentIn.getNum_portIn_InputPorts(), this->componentOut.getNum_portOut_OutputPorts());
max = std::min(this->componentIn.getNum_serialIn_InputPorts(), this->componentOut.getNum_serialOut_OutputPorts());
for (U32 i = 0; i < max; ++i) {
this->componentOut.set_portOut_OutputPort(i, this->get_from_portOut(i));
this->componentOut.set_serialOut_OutputPort(i, this->get_from_serialOut(i));
}
// ----------------------------------------------------------------------
// Connect serial input ports
// ----------------------------------------------------------------------
// portIn
// serialIn
for (U32 i = 0; i < max; ++i) {
this->connect_to_portIn(i, this->componentIn.get_portIn_InputPort(i));
this->connect_to_serialIn(i, this->componentIn.get_serialIn_InputPort(i));
}
}

View File

@ -14,7 +14,7 @@
#define TESTER_HPP
#include <Fw/Com/ComBuffer.hpp>
#include "GenericHubGTestBase.hpp"
#include "Svc/GenericHub/GenericHubComponentImpl.hpp"
#include "Svc/GenericHub/GenericHub.hpp"
// Larger than com buffer size
#define DATA_SIZE (FW_COM_BUFFER_MAX_SIZE * 10 + sizeof(U32) + sizeof(U32) + sizeof(FwBuffSizeType))
@ -65,46 +65,46 @@ class GenericHubTester : public GenericHubGTestBase {
// Handlers for typed from ports
// ----------------------------------------------------------------------
//! Handler for from_LogSend
//! Handler for from_eventOut
//!
void from_LogSend_handler(const FwIndexType portNum, /*!< The port number*/
void from_eventOut_handler(const FwIndexType portNum, /*!< The port number*/
FwEventIdType id, /*!< Log ID */
Fw::Time& timeTag, /*!< Time Tag */
const Fw::LogSeverity& severity, /*!< The severity argument */
Fw::LogBuffer& args /*!< Buffer containing serialized log entry */
);
//! Handler for from_TlmSend
//! Handler for from_tlmOut
//!
void from_TlmSend_handler(const FwIndexType portNum, /*!< The port number*/
void from_tlmOut_handler(const FwIndexType portNum, /*!< The port number*/
FwChanIdType id, /*!< Telemetry Channel ID */
Fw::Time& timeTag, /*!< Time Tag */
Fw::TlmBuffer& val /*!< Buffer containing serialized telemetry value */
);
//! Handler for from_buffersOut
//! Handler for from_bufferOut
//!
void from_buffersOut_handler(const FwIndexType portNum, /*!< The port number*/
void from_bufferOut_handler(const FwIndexType portNum, /*!< The port number*/
Fw::Buffer& fwBuffer);
//! Handler for from_bufferDeallocate
//! Handler for from_bufferInReturn
//!
void from_bufferDeallocate_handler(const FwIndexType portNum, /*!< The port number*/
void from_bufferInReturn_handler(const FwIndexType portNum, /*!< The port number*/
Fw::Buffer& fwBuffer);
//! Handler for from_dataOutAllocate
//! Handler for from_allocate
//!
Fw::Buffer from_dataOutAllocate_handler(const FwIndexType portNum, /*!< The port number*/
Fw::Buffer from_allocate_handler(const FwIndexType portNum, /*!< The port number*/
FwSizeType size);
//! Handler for from_dataOut
//! Handler for from_toBufferDriver
//!
void from_dataOut_handler(const FwIndexType portNum, /*!< The port number*/
void from_toBufferDriver_handler(const FwIndexType portNum, /*!< The port number*/
Fw::Buffer& fwBuffer);
//! Handler for from_dataDeallocate
//!
void from_dataInDeallocate_handler(const FwIndexType portNum, /*!< The port number*/
void from_fromBufferDriverReturn_handler(const FwIndexType portNum, /*!< The port number*/
Fw::Buffer& fwBuffer);
private:
@ -112,9 +112,9 @@ class GenericHubTester : public GenericHubGTestBase {
// Handlers for serial from ports
// ----------------------------------------------------------------------
//! Handler for from_portOut
//! Handler for from_serialOut
//!
void from_portOut_handler(FwIndexType portNum, /*!< The port number*/
void from_serialOut_handler(FwIndexType portNum, /*!< The port number*/
Fw::SerializeBufferBase& Buffer /*!< The serialization buffer*/
);
@ -144,8 +144,8 @@ class GenericHubTester : public GenericHubGTestBase {
//! The component under test
//!
GenericHubComponentImpl componentIn;
GenericHubComponentImpl componentOut;
GenericHub componentIn;
GenericHub componentOut;
Fw::ComBuffer m_comm;
Fw::Buffer m_buffer;
Fw::Buffer m_allocate;

View File

@ -0,0 +1,51 @@
# GenericHub Unit Testing
Two Generic Hub component are instantiated in the unit test; one being the data transmitter and the other one being the receiver. In these unit tests, the two Generic Hubs are directly connected to each other. In real world Generic Hub will be connected to a buffer driver, that will interface with its counterpart on the other side.
## Testing Configuration
### Configuration 1
In this test configuration data from the event-in, tlm-in or serial-in ports is processed by Generic Hub-In and sent to Generic Hub-Out via toBufferDriver port. Generic Hub-Out receives it on fromBufferDriver port, processes the incoming data and sends it to one of the corresponding output ports. Unit test verifies the data sent on input ports of Generic Hub-In matches to the data coming out of the output ports of Generic Hub-Out.
In this test method a port connection is also established fromBufferDriverReturn port of Generic Hub out to toBufferDriverInReturn. This is done to test that original buffer allocation from Generic Hub In is deallocated after the test.
**Note:** The two Generic Hubs are directly connected in this test, instead of being connected via Buffer Driver. The red lines show the interface between the two hubs
The numbering (1,2,3..) in red shows the order in which the data will be processed by the two Generic Hub components
![Top Level Generic Hub](./img/generic_hub_testing_1.svg)
For more details see Events/Tlm/Serial data transfer sequence diagrams below
### Test Method 2
In this test method data from the buffer-in port is processed by Generic Hub In and sent to Generic Hub Out via toBufferDriver port. Generic Hub Out receives it on fromBufferDriver port, processes the incoming data and sends it to one of the corresponding output ports. Unit test verifies the data sent on input ports of Generic Hub in to the data coming out of the output ports of Generic Hub Out.
In this test method a port connection is also established fromBufferDriverReturn port of Generic Hub out to toBufferDriverInReturn. This is done to test that original buffer allocation from Generic Hub In is deallocated after the test.
The numbering (1,2,3..) in red shows the order in which the data will be processed by the two Generic Hub components
![Top Level Generic Hub](./img/generic_hub_testing_2.svg)
For more details see buffer data transfer sequence diagram below
## Sequence Diagram
### Scenario for Events-In/Events-Out Testing
![Top Level Generic Hub](./img/event_data_transfer.svg)
### Scenario for Telemetry-In/Telemetry-Out Testing
![Top Level Generic Hub](./img/telem_data_transfer.svg)
### Scenario for Serial-data-In/Serial-data-Out Testing
![Top Level Generic Hub](./img/serial_data_transfer.svg)
### Scenario for Buffer-data-In/Buffer-data-Out Testing
![Top Level Generic Hub](./img/buffer_data_transfer.svg)

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 406 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 322 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 185 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 184 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 320 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 318 KiB

View File

@ -59,12 +59,3 @@ constant FwAssertTextSize = 256
@ the constants FW_ASSERT_TEXT_SIZE and FW_LOG_STRING_MAX_SIZE, set
@ in FpConfig.h.
constant AssertFatalAdapterEventFileSize = FileNameStringSize
# ----------------------------------------------------------------------
# Hub connections. Connections on all deployments should mirror these settings.
# ----------------------------------------------------------------------
constant GenericHubInputPorts = 10
constant GenericHubOutputPorts = 10
constant GenericHubInputBuffers = 10
constant GenericHubOutputBuffers = 10

View File

@ -6,11 +6,12 @@
register_fprime_config(
AUTOCODER_INPUTS
"${CMAKE_CURRENT_LIST_DIR}/AcConstants.fpp"
"${CMAKE_CURRENT_LIST_DIR}/DpCfg.fpp"
"${CMAKE_CURRENT_LIST_DIR}/ComCfg.fpp"
"${CMAKE_CURRENT_LIST_DIR}/DpCfg.fpp"
"${CMAKE_CURRENT_LIST_DIR}/FpConfig.fpp"
"${CMAKE_CURRENT_LIST_DIR}/FpConstants.fpp"
"${CMAKE_CURRENT_LIST_DIR}/FpySequencerCfg.fpp"
"${CMAKE_CURRENT_LIST_DIR}/GenericHubCfg.fpp"
"${CMAKE_CURRENT_LIST_DIR}/MemoryAllocation.fpp"
"${CMAKE_CURRENT_LIST_DIR}/MemoryAllocation.hpp"
"${CMAKE_CURRENT_LIST_DIR}/PlatformCfg.fpp"

View File

@ -0,0 +1,16 @@
# ======================================================================
# GenericHub configuration
# ======================================================================
module Svc {
module GenericHubCfg {
constant NumSerialInputPorts = 10
constant NumBufferInputPorts = 10
constant NumSerialOutputPorts = 10
constant NumBufferOutputPorts = 10
}
}