From cdfa81bcf78a65980ec8162497a2c5f493836dbb Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Tue, 27 Feb 2024 09:36:33 -0500 Subject: [PATCH] Fix #2519, Add runtime TopicId conversion routines to SB Adds the following APIs to convert TopicID to MsgID values at runtime: - CFE_SB_CmdTopicIdToMsgId() - CFE_SB_TlmTopicIdToMsgId() - CFE_SB_GlobalCmdTopicIdToMsgId() - CFE_SB_GlobalTlmTopicIdToMsgId() - CFE_SB_LocalCmdTopicIdToMsgId() - CFE_SB_LocalTlmTopicIdToMsgId() This includes coverage tests and stubs. If the config does not define the conversions, then these return the invalid msgID value. --- modules/core_api/fsw/inc/cfe_sb.h | 127 ++++++++++++ .../core_api/ut-stubs/src/cfe_config_stubs.c | 5 +- .../core_api/ut-stubs/src/cfe_sb_handlers.c | 139 +++++++++++++ modules/core_api/ut-stubs/src/cfe_sb_stubs.c | 104 ++++++++++ modules/sb/fsw/src/cfe_sb_msg_id_util.c | 165 +++++++++++++++ modules/sb/fsw/src/cfe_sb_util.c | 38 ---- modules/sb/ut-coverage/sb_UT.c | 195 +++++++++++------- modules/sb/ut-coverage/sb_UT.h | 10 + 8 files changed, 666 insertions(+), 117 deletions(-) diff --git a/modules/core_api/fsw/inc/cfe_sb.h b/modules/core_api/fsw/inc/cfe_sb.h index d08b5aca5..5c858e571 100644 --- a/modules/core_api/fsw/inc/cfe_sb.h +++ b/modules/core_api/fsw/inc/cfe_sb.h @@ -853,6 +853,133 @@ static inline CFE_SB_MsgId_t CFE_SB_ValueToMsgId(CFE_SB_MsgId_Atom_t MsgIdValue) CFE_SB_MsgId_t Result = CFE_SB_MSGID_C(MsgIdValue); return Result; } + +/*****************************************************************************/ +/** + * \brief Converts a topic ID and instance number combination into a MsgID value integer + * + * \par Description + * This function accepts a data pair of topic ID + instance number and returns the + * corresponding MsgID Value (integer) for commands. + * + * \par Assumptions and Notes: + * A topic ID identifies a certain data stream from an application, for example + * the CFE Software bus ground commands (CFE_MISSION_SB_CMD_TOPICID). In + * contrast to MsgID, the topic ID is consistent across all CPUs in a system, whereas + * each CPU instance will have a unique MsgID. + * + * CPU instance numbers are 1-based. The instance number of 0 is reserved + * for "global" MsgID values that are the same on all CPUs. The PSP function + * may be used to obtain the current CPU number for the host processor. + * + * \sa CFE_SB_TlmTopicIdToMsgId(), CFE_PSP_GetProcessorId() + * + * \return Integer representation of the #CFE_SB_MsgId_t + */ +CFE_SB_MsgId_Atom_t CFE_SB_CmdTopicIdToMsgId(uint16 TopicId, uint16 InstanceNum); + +/*****************************************************************************/ +/** + * \brief Converts a topic ID and instance number combination into a MsgID value integer + * + * \par Description + * This function accepts a data pair of topic ID + instance number and returns the + * corresponding MsgID Value (integer) for telemetry. + * + * \par Assumptions and Notes: + * A topic ID identifies a certain data stream from an application, for example + * the CFE Software bus housekeeping telemetry (CFE_MISSION_SB_HK_TLM_TOPICID). In + * contrast to MsgID, the topic ID is consistent across all CPUs in a system, whereas + * each CPU instance will have a unique MsgID. + * + * CPU instance numbers are 1-based. The instance number of 0 is reserved + * for "global" MsgID values that are the same on all CPUs. The PSP function + * may be used to obtain the current CPU number for the host processor. + * + * \sa CFE_SB_CmdTopicIdToMsgId(), CFE_PSP_GetProcessorId() + * + * \return Integer representation of the #CFE_SB_MsgId_t + */ +CFE_SB_MsgId_Atom_t CFE_SB_TlmTopicIdToMsgId(uint16 TopicId, uint16 InstanceNum); + +/*****************************************************************************/ +/** + * \brief Converts a topic ID to a MsgID value integer for Global commands + * + * \par Description + * This is a wrapper around CFE_SB_CmdTopicIdToMsgId() for topic IDs which + * are the same on all CPUs within a system (i.e. not specific to a certain + * processor) + * + * \par Assumptions and Notes: + * Global MsgIDs may be used when only a single instance of a service exists + * within the system. The CFE framework does not use this feature for commands, + * but is defined for future use. + * + * \sa CFE_SB_CmdTopicIdToMsgId(), CFE_SB_LocalCmdTopicIdToMsgId() + * + * \return Integer representation of the #CFE_SB_MsgId_t + */ +CFE_SB_MsgId_Atom_t CFE_SB_GlobalCmdTopicIdToMsgId(uint16 TopicId); + +/*****************************************************************************/ +/** + * \brief Converts a topic ID to a MsgID value integer for Global telemetry + * + * \par Description + * This is a wrapper around CFE_SB_TlmTopicIdToMsgId() for topic IDs which + * are the same on all CPUs within a system (i.e. not specific to a certain + * processor) + * + * \par Assumptions and Notes: + * Global MsgIDs may be used when only a single instance of a service exists + * within the system. An example for such telemetry is the time synchronization + * service published by CFE_TIME. + * + * \sa CFE_SB_TlmTopicIdToMsgId(), CFE_SB_LocalTlmTopicIdToMsgId() + * + * \return Integer representation of the #CFE_SB_MsgId_t + */ +CFE_SB_MsgId_Atom_t CFE_SB_GlobalTlmTopicIdToMsgId(uint16 TopicId); + +/*****************************************************************************/ +/** + * \brief Converts a topic ID to a MsgID value integer for local commands + * + * \par Description + * This is a wrapper around CFE_SB_CmdTopicIdToMsgId() for topic IDs which + * are unique on all CPUs within a system (i.e. specific to a certain + * processor) + * + * \par Assumptions and Notes: + * This assumes the caller is referring to a service running on the same + * processor instance as itself. + * + * \sa CFE_SB_CmdTopicIdToMsgId(), CFE_SB_LocalTlmTopicIdToMsgId() + * + * \return Integer representation of the #CFE_SB_MsgId_t + */ +CFE_SB_MsgId_Atom_t CFE_SB_LocalCmdTopicIdToMsgId(uint16 TopicId); + +/*****************************************************************************/ +/** + * \brief Converts a topic ID to a MsgID value integer for local telemetry + * + * \par Description + * This is a wrapper around CFE_SB_TlmTopicIdToMsgId() for topic IDs which + * are unique on all CPUs within a system (i.e. specific to a certain + * processor) + * + * \par Assumptions and Notes: + * This assumes the caller is referring to a service running on the same + * processor instance as itself. + * + * \sa CFE_SB_TlmTopicIdToMsgId(), CFE_SB_LocalCmdTopicIdToMsgId() + * + * \return Integer representation of the #CFE_SB_MsgId_t + */ +CFE_SB_MsgId_Atom_t CFE_SB_LocalTlmTopicIdToMsgId(uint16 TopicId); + /** @} */ #endif /* CFE_SB_H */ diff --git a/modules/core_api/ut-stubs/src/cfe_config_stubs.c b/modules/core_api/ut-stubs/src/cfe_config_stubs.c index 87a327692..f0d9b50c1 100644 --- a/modules/core_api/ut-stubs/src/cfe_config_stubs.c +++ b/modules/core_api/ut-stubs/src/cfe_config_stubs.c @@ -113,10 +113,11 @@ uint32 CFE_Config_GetValue(CFE_ConfigId_t ConfigId) * Generated stub function for CFE_Config_GetVersionString() * ---------------------------------------------------- */ -void CFE_Config_GetVersionString(char *Buf, size_t Size, const char *Component, const char *SrcVersion, const char *CodeName, const char *LastOffcRel) +void CFE_Config_GetVersionString(char *Buf, size_t Size, const char *Component, const char *SrcVersion, + const char *CodeName, const char *LastOffcRel) { UT_GenStub_AddParam(CFE_Config_GetVersionString, char *, Buf); - UT_GenStub_AddParam(CFE_Config_GetVersionString, size_t , Size); + UT_GenStub_AddParam(CFE_Config_GetVersionString, size_t, Size); UT_GenStub_AddParam(CFE_Config_GetVersionString, const char *, Component); UT_GenStub_AddParam(CFE_Config_GetVersionString, const char *, SrcVersion); UT_GenStub_AddParam(CFE_Config_GetVersionString, const char *, CodeName); diff --git a/modules/core_api/ut-stubs/src/cfe_sb_handlers.c b/modules/core_api/ut-stubs/src/cfe_sb_handlers.c index 7d23b2f2b..583223e44 100644 --- a/modules/core_api/ut-stubs/src/cfe_sb_handlers.c +++ b/modules/core_api/ut-stubs/src/cfe_sb_handlers.c @@ -66,10 +66,149 @@ static CFE_SB_StubMsg_MetaData_t *CFE_SB_StubMsg_GetMetaData(const CFE_MSG_Messa return MetaPtr; } + +/*------------------------------------------------------------ + * + * Helper function to fabricate a MsgID value for testing purposes + * + * Note this is not intended to match a real MsgID value used in flight + * software builds, it is just for UT. The fabricated value just needs + * to pass the "CFE_SB_IsValidMsgId()" test. + * + *------------------------------------------------------------*/ +static void UT_CFE_SB_FabricateMsgIdValue(UT_EntryKey_t FuncKey, bool IsCmd, uint16 TopicId, uint16 InstanceNum) +{ + CFE_SB_MsgId_Atom_t MsgIdValue; + + /* This makes the bits line up with the "traditional" use of the first 16 + * bits of a CCSDS space packet as a MsgId */ + MsgIdValue = 1; + if (IsCmd) + { + MsgIdValue |= 2; + } + MsgIdValue <<= 4; + MsgIdValue |= InstanceNum & 0xF; + MsgIdValue <<= 7; + MsgIdValue |= TopicId & 0x7F; + + UT_Stub_SetReturnValue(FuncKey, MsgIdValue); +} + /* ** Functions */ +/*------------------------------------------------------------ + * + * Default handler for CFE_SB_LocalCmdTopicIdToMsgId coverage stub function + * + *------------------------------------------------------------*/ +void UT_DefaultHandler_CFE_SB_LocalCmdTopicIdToMsgId(void *UserObj, UT_EntryKey_t FuncKey, + const UT_StubContext_t *Context) +{ + uint16 TopicId; + + if (!UT_Stub_GetInt32StatusCode(Context, NULL)) + { + TopicId = UT_Hook_GetArgValueByName(Context, "TopicId", uint16); + + UT_CFE_SB_FabricateMsgIdValue(FuncKey, true, TopicId, 1); + } +} + +/*------------------------------------------------------------ + * + * Default handler for CFE_SB_LocalTlmTopicIdToMsgId coverage stub function + * + *------------------------------------------------------------*/ +void UT_DefaultHandler_CFE_SB_LocalTlmTopicIdToMsgId(void *UserObj, UT_EntryKey_t FuncKey, + const UT_StubContext_t *Context) +{ + uint16 TopicId; + + if (!UT_Stub_GetInt32StatusCode(Context, NULL)) + { + TopicId = UT_Hook_GetArgValueByName(Context, "TopicId", uint16); + + UT_CFE_SB_FabricateMsgIdValue(FuncKey, false, TopicId, 1); + } +} + +/*------------------------------------------------------------ + * + * Default handler for CFE_SB_GlobalCmdTopicIdToMsgId coverage stub function + * + *------------------------------------------------------------*/ +void UT_DefaultHandler_CFE_SB_GlobalCmdTopicIdToMsgId(void *UserObj, UT_EntryKey_t FuncKey, + const UT_StubContext_t *Context) +{ + uint16 TopicId; + + if (!UT_Stub_GetInt32StatusCode(Context, NULL)) + { + TopicId = UT_Hook_GetArgValueByName(Context, "TopicId", uint16); + + UT_CFE_SB_FabricateMsgIdValue(FuncKey, true, TopicId, 0); + } +} + +/*------------------------------------------------------------ + * + * Default handler for CFE_SB_GlobalTlmTopicIdToMsgId coverage stub function + * + *------------------------------------------------------------*/ +void UT_DefaultHandler_CFE_SB_GlobalTlmTopicIdToMsgId(void *UserObj, UT_EntryKey_t FuncKey, + const UT_StubContext_t *Context) +{ + uint16 TopicId; + + if (!UT_Stub_GetInt32StatusCode(Context, NULL)) + { + TopicId = UT_Hook_GetArgValueByName(Context, "TopicId", uint16); + + UT_CFE_SB_FabricateMsgIdValue(FuncKey, false, TopicId, 0); + } +} + +/*------------------------------------------------------------ + * + * Default handler for CFE_SB_CmdTopicIdToMsgId coverage stub function + * + *------------------------------------------------------------*/ +void UT_DefaultHandler_CFE_SB_CmdTopicIdToMsgId(void *UserObj, UT_EntryKey_t FuncKey, const UT_StubContext_t *Context) +{ + uint16 TopicId; + uint16 InstanceNum; + + if (!UT_Stub_GetInt32StatusCode(Context, NULL)) + { + TopicId = UT_Hook_GetArgValueByName(Context, "TopicId", uint16); + InstanceNum = UT_Hook_GetArgValueByName(Context, "InstanceNum", uint16); + + UT_CFE_SB_FabricateMsgIdValue(FuncKey, true, TopicId, InstanceNum); + } +} + +/*------------------------------------------------------------ + * + * Default handler for CFE_SB_TlmTopicIdToMsgId coverage stub function + * + *------------------------------------------------------------*/ +void UT_DefaultHandler_CFE_SB_TlmTopicIdToMsgId(void *UserObj, UT_EntryKey_t FuncKey, const UT_StubContext_t *Context) +{ + uint16 TopicId; + uint16 InstanceNum; + + if (!UT_Stub_GetInt32StatusCode(Context, NULL)) + { + TopicId = UT_Hook_GetArgValueByName(Context, "TopicId", uint16); + InstanceNum = UT_Hook_GetArgValueByName(Context, "InstanceNum", uint16); + + UT_CFE_SB_FabricateMsgIdValue(FuncKey, false, TopicId, InstanceNum); + } +} + /*------------------------------------------------------------ * * Default handler for CFE_SB_CreatePipe coverage stub function diff --git a/modules/core_api/ut-stubs/src/cfe_sb_stubs.c b/modules/core_api/ut-stubs/src/cfe_sb_stubs.c index 369394492..93a9f80af 100644 --- a/modules/core_api/ut-stubs/src/cfe_sb_stubs.c +++ b/modules/core_api/ut-stubs/src/cfe_sb_stubs.c @@ -26,18 +26,24 @@ #include "utgenstub.h" void UT_DefaultHandler_CFE_SB_AllocateMessageBuffer(void *, UT_EntryKey_t, const UT_StubContext_t *); +void UT_DefaultHandler_CFE_SB_CmdTopicIdToMsgId(void *, UT_EntryKey_t, const UT_StubContext_t *); void UT_DefaultHandler_CFE_SB_CreatePipe(void *, UT_EntryKey_t, const UT_StubContext_t *); void UT_DefaultHandler_CFE_SB_DeletePipe(void *, UT_EntryKey_t, const UT_StubContext_t *); void UT_DefaultHandler_CFE_SB_GetPipeIdByName(void *, UT_EntryKey_t, const UT_StubContext_t *); void UT_DefaultHandler_CFE_SB_GetPipeName(void *, UT_EntryKey_t, const UT_StubContext_t *); void UT_DefaultHandler_CFE_SB_GetUserData(void *, UT_EntryKey_t, const UT_StubContext_t *); void UT_DefaultHandler_CFE_SB_GetUserDataLength(void *, UT_EntryKey_t, const UT_StubContext_t *); +void UT_DefaultHandler_CFE_SB_GlobalCmdTopicIdToMsgId(void *, UT_EntryKey_t, const UT_StubContext_t *); +void UT_DefaultHandler_CFE_SB_GlobalTlmTopicIdToMsgId(void *, UT_EntryKey_t, const UT_StubContext_t *); void UT_DefaultHandler_CFE_SB_IsValidMsgId(void *, UT_EntryKey_t, const UT_StubContext_t *); +void UT_DefaultHandler_CFE_SB_LocalCmdTopicIdToMsgId(void *, UT_EntryKey_t, const UT_StubContext_t *); +void UT_DefaultHandler_CFE_SB_LocalTlmTopicIdToMsgId(void *, UT_EntryKey_t, const UT_StubContext_t *); void UT_DefaultHandler_CFE_SB_MessageStringGet(void *, UT_EntryKey_t, const UT_StubContext_t *); void UT_DefaultHandler_CFE_SB_MessageStringSet(void *, UT_EntryKey_t, const UT_StubContext_t *); void UT_DefaultHandler_CFE_SB_ReceiveBuffer(void *, UT_EntryKey_t, const UT_StubContext_t *); void UT_DefaultHandler_CFE_SB_SetUserDataLength(void *, UT_EntryKey_t, const UT_StubContext_t *); void UT_DefaultHandler_CFE_SB_TimeStampMsg(void *, UT_EntryKey_t, const UT_StubContext_t *); +void UT_DefaultHandler_CFE_SB_TlmTopicIdToMsgId(void *, UT_EntryKey_t, const UT_StubContext_t *); void UT_DefaultHandler_CFE_SB_TransmitBuffer(void *, UT_EntryKey_t, const UT_StubContext_t *); void UT_DefaultHandler_CFE_SB_TransmitMsg(void *, UT_EntryKey_t, const UT_StubContext_t *); @@ -57,6 +63,23 @@ CFE_SB_Buffer_t *CFE_SB_AllocateMessageBuffer(size_t MsgSize) return UT_GenStub_GetReturnValue(CFE_SB_AllocateMessageBuffer, CFE_SB_Buffer_t *); } +/* + * ---------------------------------------------------- + * Generated stub function for CFE_SB_CmdTopicIdToMsgId() + * ---------------------------------------------------- + */ +CFE_SB_MsgId_Atom_t CFE_SB_CmdTopicIdToMsgId(uint16 TopicId, uint16 InstanceNum) +{ + UT_GenStub_SetupReturnBuffer(CFE_SB_CmdTopicIdToMsgId, CFE_SB_MsgId_Atom_t); + + UT_GenStub_AddParam(CFE_SB_CmdTopicIdToMsgId, uint16, TopicId); + UT_GenStub_AddParam(CFE_SB_CmdTopicIdToMsgId, uint16, InstanceNum); + + UT_GenStub_Execute(CFE_SB_CmdTopicIdToMsgId, Basic, UT_DefaultHandler_CFE_SB_CmdTopicIdToMsgId); + + return UT_GenStub_GetReturnValue(CFE_SB_CmdTopicIdToMsgId, CFE_SB_MsgId_Atom_t); +} + /* * ---------------------------------------------------- * Generated stub function for CFE_SB_CreatePipe() @@ -175,6 +198,38 @@ size_t CFE_SB_GetUserDataLength(const CFE_MSG_Message_t *MsgPtr) return UT_GenStub_GetReturnValue(CFE_SB_GetUserDataLength, size_t); } +/* + * ---------------------------------------------------- + * Generated stub function for CFE_SB_GlobalCmdTopicIdToMsgId() + * ---------------------------------------------------- + */ +CFE_SB_MsgId_Atom_t CFE_SB_GlobalCmdTopicIdToMsgId(uint16 TopicId) +{ + UT_GenStub_SetupReturnBuffer(CFE_SB_GlobalCmdTopicIdToMsgId, CFE_SB_MsgId_Atom_t); + + UT_GenStub_AddParam(CFE_SB_GlobalCmdTopicIdToMsgId, uint16, TopicId); + + UT_GenStub_Execute(CFE_SB_GlobalCmdTopicIdToMsgId, Basic, UT_DefaultHandler_CFE_SB_GlobalCmdTopicIdToMsgId); + + return UT_GenStub_GetReturnValue(CFE_SB_GlobalCmdTopicIdToMsgId, CFE_SB_MsgId_Atom_t); +} + +/* + * ---------------------------------------------------- + * Generated stub function for CFE_SB_GlobalTlmTopicIdToMsgId() + * ---------------------------------------------------- + */ +CFE_SB_MsgId_Atom_t CFE_SB_GlobalTlmTopicIdToMsgId(uint16 TopicId) +{ + UT_GenStub_SetupReturnBuffer(CFE_SB_GlobalTlmTopicIdToMsgId, CFE_SB_MsgId_Atom_t); + + UT_GenStub_AddParam(CFE_SB_GlobalTlmTopicIdToMsgId, uint16, TopicId); + + UT_GenStub_Execute(CFE_SB_GlobalTlmTopicIdToMsgId, Basic, UT_DefaultHandler_CFE_SB_GlobalTlmTopicIdToMsgId); + + return UT_GenStub_GetReturnValue(CFE_SB_GlobalTlmTopicIdToMsgId, CFE_SB_MsgId_Atom_t); +} + /* * ---------------------------------------------------- * Generated stub function for CFE_SB_IsValidMsgId() @@ -191,6 +246,38 @@ bool CFE_SB_IsValidMsgId(CFE_SB_MsgId_t MsgId) return UT_GenStub_GetReturnValue(CFE_SB_IsValidMsgId, bool); } +/* + * ---------------------------------------------------- + * Generated stub function for CFE_SB_LocalCmdTopicIdToMsgId() + * ---------------------------------------------------- + */ +CFE_SB_MsgId_Atom_t CFE_SB_LocalCmdTopicIdToMsgId(uint16 TopicId) +{ + UT_GenStub_SetupReturnBuffer(CFE_SB_LocalCmdTopicIdToMsgId, CFE_SB_MsgId_Atom_t); + + UT_GenStub_AddParam(CFE_SB_LocalCmdTopicIdToMsgId, uint16, TopicId); + + UT_GenStub_Execute(CFE_SB_LocalCmdTopicIdToMsgId, Basic, UT_DefaultHandler_CFE_SB_LocalCmdTopicIdToMsgId); + + return UT_GenStub_GetReturnValue(CFE_SB_LocalCmdTopicIdToMsgId, CFE_SB_MsgId_Atom_t); +} + +/* + * ---------------------------------------------------- + * Generated stub function for CFE_SB_LocalTlmTopicIdToMsgId() + * ---------------------------------------------------- + */ +CFE_SB_MsgId_Atom_t CFE_SB_LocalTlmTopicIdToMsgId(uint16 TopicId) +{ + UT_GenStub_SetupReturnBuffer(CFE_SB_LocalTlmTopicIdToMsgId, CFE_SB_MsgId_Atom_t); + + UT_GenStub_AddParam(CFE_SB_LocalTlmTopicIdToMsgId, uint16, TopicId); + + UT_GenStub_Execute(CFE_SB_LocalTlmTopicIdToMsgId, Basic, UT_DefaultHandler_CFE_SB_LocalTlmTopicIdToMsgId); + + return UT_GenStub_GetReturnValue(CFE_SB_LocalTlmTopicIdToMsgId, CFE_SB_MsgId_Atom_t); +} + /* * ---------------------------------------------------- * Generated stub function for CFE_SB_MessageStringGet() @@ -379,6 +466,23 @@ void CFE_SB_TimeStampMsg(CFE_MSG_Message_t *MsgPtr) UT_GenStub_Execute(CFE_SB_TimeStampMsg, Basic, UT_DefaultHandler_CFE_SB_TimeStampMsg); } +/* + * ---------------------------------------------------- + * Generated stub function for CFE_SB_TlmTopicIdToMsgId() + * ---------------------------------------------------- + */ +CFE_SB_MsgId_Atom_t CFE_SB_TlmTopicIdToMsgId(uint16 TopicId, uint16 InstanceNum) +{ + UT_GenStub_SetupReturnBuffer(CFE_SB_TlmTopicIdToMsgId, CFE_SB_MsgId_Atom_t); + + UT_GenStub_AddParam(CFE_SB_TlmTopicIdToMsgId, uint16, TopicId); + UT_GenStub_AddParam(CFE_SB_TlmTopicIdToMsgId, uint16, InstanceNum); + + UT_GenStub_Execute(CFE_SB_TlmTopicIdToMsgId, Basic, UT_DefaultHandler_CFE_SB_TlmTopicIdToMsgId); + + return UT_GenStub_GetReturnValue(CFE_SB_TlmTopicIdToMsgId, CFE_SB_MsgId_Atom_t); +} + /* * ---------------------------------------------------- * Generated stub function for CFE_SB_TransmitBuffer() diff --git a/modules/sb/fsw/src/cfe_sb_msg_id_util.c b/modules/sb/fsw/src/cfe_sb_msg_id_util.c index 08e11684b..f09725bd3 100644 --- a/modules/sb/fsw/src/cfe_sb_msg_id_util.c +++ b/modules/sb/fsw/src/cfe_sb_msg_id_util.c @@ -25,6 +25,171 @@ ** Include Files */ #include "cfe_sb_module_all.h" +#include "cfe_core_api_base_msgids.h" + +/* + * IMPORTANT: + * The "core_api_base_msgids.h" header should have defined the following macros: + * CFE_PLATFORM_CMD_TOPICID_TO_MIDV + * CFE_PLATFORM_TLM_TOPICID_TO_MIDV + * CFE_GLOBAL_CMD_TOPICID_TO_MIDV + * CFE_GLOBAL_TLM_TOPICID_TO_MIDV + * + * However, historically in CFE, MsgIDs were directly defined at compile-time (not run-time) + * and not based on a topic ID. It is possible that when using an older CFE configuration + * that it does not define these macros, and thus run-time conversion cannot be performed. + * + * If that is the case, then all these functions will return the invalid MsgID value (0). + * The coverage tests will fail (which should let the user know the feature is not working + * correctly) but CFE and related apps will still execute just fine so long as nothing + * relies on the run-time conversions. + */ + +#ifndef CFE_PLATFORM_CMD_TOPICID_TO_MIDV +#define CFE_PLATFORM_CMD_TOPICID_TO_MIDV(x) 0 +#endif + +#ifndef CFE_PLATFORM_TLM_TOPICID_TO_MIDV +#define CFE_PLATFORM_TLM_TOPICID_TO_MIDV(x) 0 +#endif + +#ifndef CFE_GLOBAL_CMD_TOPICID_TO_MIDV +#define CFE_GLOBAL_CMD_TOPICID_TO_MIDV(x) 0 +#endif + +#ifndef CFE_GLOBAL_TLM_TOPICID_TO_MIDV +#define CFE_GLOBAL_TLM_TOPICID_TO_MIDV(x) 0 +#endif + +/*---------------------------------------------------------------- + * + * Application-scope internal function + * See description in header file for argument/return detail + * + *-----------------------------------------------------------------*/ +size_t CFE_SB_MsgHdrSize(const CFE_MSG_Message_t *MsgPtr) +{ + size_t size = 0; + bool hassechdr = false; + CFE_MSG_Type_t type = CFE_MSG_Type_Invalid; + + if (MsgPtr == NULL) + { + return size; + } + + CFE_MSG_GetHasSecondaryHeader(MsgPtr, &hassechdr); + CFE_MSG_GetType(MsgPtr, &type); + + /* if secondary hdr is not present... */ + /* Since all cFE messages must have a secondary hdr this check is not needed */ + if (!hassechdr) + { + size = sizeof(CFE_MSG_Message_t); + } + else if (type == CFE_MSG_Type_Cmd) + { + size = sizeof(CFE_MSG_CommandHeader_t); + } + else if (type == CFE_MSG_Type_Tlm) + { + size = sizeof(CFE_MSG_TelemetryHeader_t); + } + + return size; +} + +/*---------------------------------------------------------------- + * + * Implemented per public API + * See description in header file for argument/return detail + * + *-----------------------------------------------------------------*/ +CFE_SB_MsgId_Atom_t CFE_SB_CmdTopicIdToMsgId(uint16 TopicId, uint16 InstanceNum) +{ + CFE_SB_MsgId_Atom_t MsgIdValue; + + /* Instance Number 0 is reserved for globals */ + if (InstanceNum == 0) + { + MsgIdValue = CFE_SB_GlobalTlmTopicIdToMsgId(TopicId); + } + else + { + MsgIdValue = CFE_PLATFORM_CMD_TOPICID_TO_MIDV(TopicId); + } + + return MsgIdValue; +} + +/*---------------------------------------------------------------- + * + * Implemented per public API + * See description in header file for argument/return detail + * + *-----------------------------------------------------------------*/ +CFE_SB_MsgId_Atom_t CFE_SB_TlmTopicIdToMsgId(uint16 TopicId, uint16 InstanceNum) +{ + CFE_SB_MsgId_Atom_t MsgIdValue; + + /* Instance Number 0 is reserved for globals */ + if (InstanceNum == 0) + { + MsgIdValue = CFE_SB_GlobalTlmTopicIdToMsgId(TopicId); + } + else + { + MsgIdValue = CFE_PLATFORM_TLM_TOPICID_TO_MIDV(TopicId); + } + + return MsgIdValue; +} + +/*---------------------------------------------------------------- + * + * Implemented per public API + * See description in header file for argument/return detail + * + *-----------------------------------------------------------------*/ +CFE_SB_MsgId_Atom_t CFE_SB_GlobalCmdTopicIdToMsgId(uint16 TopicId) +{ + return CFE_GLOBAL_CMD_TOPICID_TO_MIDV(TopicId); +} + +/*---------------------------------------------------------------- + * + * Implemented per public API + * See description in header file for argument/return detail + * + *-----------------------------------------------------------------*/ +CFE_SB_MsgId_Atom_t CFE_SB_GlobalTlmTopicIdToMsgId(uint16 TopicId) +{ + return CFE_GLOBAL_TLM_TOPICID_TO_MIDV(TopicId); +} + +/*---------------------------------------------------------------- + * + * Implemented per public API + * See description in header file for argument/return detail + * + *-----------------------------------------------------------------*/ +CFE_SB_MsgId_Atom_t CFE_SB_LocalCmdTopicIdToMsgId(uint16 TopicId) +{ + /* PSP-reported Instance number is used for locals */ + return CFE_SB_CmdTopicIdToMsgId(TopicId, CFE_PSP_GetProcessorId()); +} + +/*---------------------------------------------------------------- + * + * Implemented per public API + * See description in header file for argument/return detail + * + *-----------------------------------------------------------------*/ +CFE_SB_MsgId_Atom_t CFE_SB_LocalTlmTopicIdToMsgId(uint16 TopicId) +{ + /* PSP-reported Instance number is used for locals */ + return CFE_SB_TlmTopicIdToMsgId(TopicId, CFE_PSP_GetProcessorId()); +} /*---------------------------------------------------------------- * diff --git a/modules/sb/fsw/src/cfe_sb_util.c b/modules/sb/fsw/src/cfe_sb_util.c index 7a56762cb..cb7fc2463 100644 --- a/modules/sb/fsw/src/cfe_sb_util.c +++ b/modules/sb/fsw/src/cfe_sb_util.c @@ -35,44 +35,6 @@ #include -/*---------------------------------------------------------------- - * - * Application-scope internal function - * See description in header file for argument/return detail - * - *-----------------------------------------------------------------*/ -size_t CFE_SB_MsgHdrSize(const CFE_MSG_Message_t *MsgPtr) -{ - size_t size = 0; - bool hassechdr = false; - CFE_MSG_Type_t type = CFE_MSG_Type_Invalid; - - if (MsgPtr == NULL) - { - return size; - } - - CFE_MSG_GetHasSecondaryHeader(MsgPtr, &hassechdr); - CFE_MSG_GetType(MsgPtr, &type); - - /* if secondary hdr is not present... */ - /* Since all cFE messages must have a secondary hdr this check is not needed */ - if (!hassechdr) - { - size = sizeof(CFE_MSG_Message_t); - } - else if (type == CFE_MSG_Type_Cmd) - { - size = sizeof(CFE_MSG_CommandHeader_t); - } - else if (type == CFE_MSG_Type_Tlm) - { - size = sizeof(CFE_MSG_TelemetryHeader_t); - } - - return size; -} - /*---------------------------------------------------------------- * * Implemented per public API diff --git a/modules/sb/ut-coverage/sb_UT.c b/modules/sb/ut-coverage/sb_UT.c index 571c95a9e..b6b7cb141 100644 --- a/modules/sb/ut-coverage/sb_UT.c +++ b/modules/sb/ut-coverage/sb_UT.c @@ -3938,8 +3938,33 @@ void Test_SB_Utils(void) SB_UT_ADD_SUBTEST(Test_CFE_SB_MsgHdrSize); SB_UT_ADD_SUBTEST(Test_CFE_SB_GetUserData); SB_UT_ADD_SUBTEST(Test_CFE_SB_SetGetUserDataLength); - SB_UT_ADD_SUBTEST(Test_CFE_SB_ValidateMsgId); SB_UT_ADD_SUBTEST(Test_CFE_SB_ZeroCopyReleaseAppId); + + SB_UT_ADD_SUBTEST(Test_CFE_SB_ValidateMsgId); + + /* TopicID <-> MsgID conversion utilities implemented in msg_id_util.c */ + SB_UT_ADD_SUBTEST(Test_CFE_SB_CmdTopicIdToMsgId); + SB_UT_ADD_SUBTEST(Test_CFE_SB_TlmTopicIdToMsgId); + SB_UT_ADD_SUBTEST(Test_CFE_SB_GlobalCmdTopicIdToMsgId); + SB_UT_ADD_SUBTEST(Test_CFE_SB_GlobalTlmTopicIdToMsgId); + SB_UT_ADD_SUBTEST(Test_CFE_SB_LocalCmdTopicIdToMsgId); + SB_UT_ADD_SUBTEST(Test_CFE_SB_LocalTlmTopicIdToMsgId); +} + +static void UT_SB_Setup_MsgHdrSize(bool HasSec, CFE_MSG_Type_t MsgType) +{ + UT_ResetState(UT_KEY(CFE_MSG_GetHasSecondaryHeader)); + UT_ResetState(UT_KEY(CFE_MSG_GetType)); + + UT_SetDataBuffer(UT_KEY(CFE_MSG_GetHasSecondaryHeader), &HasSec, sizeof(HasSec), true); + UT_SetDataBuffer(UT_KEY(CFE_MSG_GetType), &MsgType, sizeof(MsgType), true); +} + +static void UT_SB_Check_MsgHdrSize(void *BasePtr, bool HasSec, CFE_MSG_Type_t MsgType, size_t ExpectedPayloadOffset) +{ + UT_SB_Setup_MsgHdrSize(HasSec, MsgType); + + UtAssert_EQ(size_t, CFE_SB_MsgHdrSize(BasePtr), ExpectedPayloadOffset); } /* @@ -3947,48 +3972,38 @@ void Test_SB_Utils(void) */ void Test_CFE_SB_MsgHdrSize(void) { - CFE_MSG_Message_t msg; - bool hassec; - CFE_MSG_Type_t type; + union + { + CFE_MSG_Message_t BaseObject; + CFE_MSG_CommandHeader_t CommandHeader; + CFE_MSG_TelemetryHeader_t TelemetryHeader; + } msg; memset(&msg, 0, sizeof(msg)); /* No secondary */ - hassec = false; - type = CFE_MSG_Type_Invalid; - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetHasSecondaryHeader), &hassec, sizeof(hassec), false); - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetType), &type, sizeof(type), false); - UtAssert_EQ(size_t, CFE_SB_MsgHdrSize(&msg), sizeof(CFE_MSG_Message_t)); + UT_SB_Check_MsgHdrSize(&msg, false, CFE_MSG_Type_Invalid, sizeof(msg.BaseObject)); /* Has secondary, tlm type */ - hassec = true; - type = CFE_MSG_Type_Tlm; - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetHasSecondaryHeader), &hassec, sizeof(hassec), false); - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetType), &type, sizeof(type), false); - UtAssert_EQ(size_t, CFE_SB_MsgHdrSize(&msg), sizeof(CFE_MSG_TelemetryHeader_t)); + UT_SB_Check_MsgHdrSize(&msg, true, CFE_MSG_Type_Tlm, sizeof(msg.TelemetryHeader)); /* Has secondary, cmd type */ - type = CFE_MSG_Type_Cmd; - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetHasSecondaryHeader), &hassec, sizeof(hassec), false); - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetType), &type, sizeof(type), false); - UtAssert_EQ(size_t, CFE_SB_MsgHdrSize(&msg), sizeof(CFE_MSG_CommandHeader_t)); + UT_SB_Check_MsgHdrSize(&msg, true, CFE_MSG_Type_Cmd, sizeof(msg.CommandHeader)); /* Has secondary, invalid type */ - type = CFE_MSG_Type_Invalid; - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetHasSecondaryHeader), &hassec, sizeof(hassec), false); - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetType), &type, sizeof(type), false); - UtAssert_ZERO(CFE_SB_MsgHdrSize(&msg)); + UT_SB_Check_MsgHdrSize(&msg, true, CFE_MSG_Type_Invalid, 0); - /* - * Note, this function currently has a type mismatch - it attempts to - * return CFE_SB_BAD_ARGUMENT if passed a NULL MsgPtr value, but that - * will be implicitly converted to size_t, and the result is - * platform-defined. - * - * The function is called for coverage, but the result is not verified - * due to this mismatch. - */ - UtAssert_VOIDCALL(CFE_SB_MsgHdrSize(NULL)); + /* Bad message argument (NULL) */ + UT_SB_Check_MsgHdrSize(NULL, true, CFE_MSG_Type_Invalid, 0); +} + +static void UT_SB_Check_GetUserData(void *BasePtr, bool HasSec, CFE_MSG_Type_t MsgType, size_t ExpectedPayloadOffset) +{ + const uint8_t *ExpectedPayloadPtr = (const uint8_t *)BasePtr + ExpectedPayloadOffset; + + UT_SB_Setup_MsgHdrSize(HasSec, MsgType); + + UtAssert_ADDRESS_EQ(CFE_SB_GetUserData(BasePtr), ExpectedPayloadPtr); } /* @@ -3997,45 +4012,42 @@ void Test_CFE_SB_MsgHdrSize(void) void Test_CFE_SB_GetUserData(void) { CFE_MSG_Message_t msg; - uint8 * expected; - bool hassec; - CFE_MSG_Type_t type = CFE_MSG_Type_Invalid; - struct + struct cmd_uint8 { CFE_MSG_CommandHeader_t CommandHeader; uint8 payload; } cmd_uint8; - struct + struct cmd_uint16 { CFE_MSG_CommandHeader_t CommandHeader; uint16 payload; } cmd_uint16; - struct + struct cmd_uint32 { CFE_MSG_CommandHeader_t CommandHeader; uint32 payload; } cmd_uint32; - struct + struct cmd_uint64 { CFE_MSG_CommandHeader_t CommandHeader; uint64 payload; } cmd_uint64; - struct + struct tlm_uint8 { CFE_MSG_TelemetryHeader_t TelemetryHeader; uint8 payload; } tlm_uint8; - struct + struct tlm_uint16 { CFE_MSG_TelemetryHeader_t TelemetryHeader; uint16 payload; } tlm_uint16; - struct + struct tlm_uint32 { CFE_MSG_TelemetryHeader_t TelemetryHeader; uint32 payload; } tlm_uint32; - struct + struct tlm_uint64 { CFE_MSG_TelemetryHeader_t TelemetryHeader; uint64 payload; @@ -4052,44 +4064,19 @@ void Test_CFE_SB_GetUserData(void) memset(&tlm_uint64, 0, sizeof(tlm_uint64)); /* No secondary */ - hassec = false; - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetHasSecondaryHeader), &hassec, sizeof(hassec), false); - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetType), &type, sizeof(type), false); - - /* Expected return */ - expected = (uint8 *)&msg + sizeof(CFE_MSG_Message_t); - UtAssert_ADDRESS_EQ(CFE_SB_GetUserData(&msg), expected); + UT_SB_Check_GetUserData(&msg, false, CFE_MSG_Type_Invalid, sizeof(CFE_MSG_Message_t)); /* Commands */ - hassec = true; - type = CFE_MSG_Type_Cmd; - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetHasSecondaryHeader), &hassec, sizeof(hassec), false); - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetType), &type, sizeof(type), false); - UtAssert_ADDRESS_EQ(CFE_SB_GetUserData(CFE_MSG_PTR(cmd_uint8.CommandHeader)), &(cmd_uint8.payload)); - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetHasSecondaryHeader), &hassec, sizeof(hassec), false); - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetType), &type, sizeof(type), false); - UtAssert_ADDRESS_EQ(CFE_SB_GetUserData(CFE_MSG_PTR(cmd_uint16.CommandHeader)), &(cmd_uint16.payload)); - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetHasSecondaryHeader), &hassec, sizeof(hassec), false); - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetType), &type, sizeof(type), false); - UtAssert_ADDRESS_EQ(CFE_SB_GetUserData(CFE_MSG_PTR(cmd_uint32.CommandHeader)), &(cmd_uint32.payload)); - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetHasSecondaryHeader), &hassec, sizeof(hassec), false); - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetType), &type, sizeof(type), false); - UtAssert_ADDRESS_EQ(CFE_SB_GetUserData(CFE_MSG_PTR(cmd_uint64.CommandHeader)), &(cmd_uint64.payload)); + UT_SB_Check_GetUserData(&cmd_uint8, true, CFE_MSG_Type_Cmd, offsetof(struct cmd_uint8, payload)); + UT_SB_Check_GetUserData(&cmd_uint16, true, CFE_MSG_Type_Cmd, offsetof(struct cmd_uint16, payload)); + UT_SB_Check_GetUserData(&cmd_uint32, true, CFE_MSG_Type_Cmd, offsetof(struct cmd_uint32, payload)); + UT_SB_Check_GetUserData(&cmd_uint64, true, CFE_MSG_Type_Cmd, offsetof(struct cmd_uint64, payload)); /* Telemetry */ - type = CFE_MSG_Type_Tlm; - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetHasSecondaryHeader), &hassec, sizeof(hassec), false); - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetType), &type, sizeof(type), false); - UtAssert_ADDRESS_EQ(CFE_SB_GetUserData(CFE_MSG_PTR(tlm_uint8.TelemetryHeader)), &(tlm_uint8.payload)); - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetHasSecondaryHeader), &hassec, sizeof(hassec), false); - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetType), &type, sizeof(type), false); - UtAssert_ADDRESS_EQ(CFE_SB_GetUserData(CFE_MSG_PTR(tlm_uint16.TelemetryHeader)), &(tlm_uint16.payload)); - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetHasSecondaryHeader), &hassec, sizeof(hassec), false); - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetType), &type, sizeof(type), false); - UtAssert_ADDRESS_EQ(CFE_SB_GetUserData(CFE_MSG_PTR(tlm_uint32.TelemetryHeader)), &(tlm_uint32.payload)); - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetHasSecondaryHeader), &hassec, sizeof(hassec), false); - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetType), &type, sizeof(type), false); - UtAssert_ADDRESS_EQ(CFE_SB_GetUserData(CFE_MSG_PTR(tlm_uint64.TelemetryHeader)), &(tlm_uint64.payload)); + UT_SB_Check_GetUserData(&tlm_uint8, true, CFE_MSG_Type_Tlm, offsetof(struct tlm_uint8, payload)); + UT_SB_Check_GetUserData(&tlm_uint16, true, CFE_MSG_Type_Tlm, offsetof(struct tlm_uint16, payload)); + UT_SB_Check_GetUserData(&tlm_uint32, true, CFE_MSG_Type_Tlm, offsetof(struct tlm_uint32, payload)); + UT_SB_Check_GetUserData(&tlm_uint64, true, CFE_MSG_Type_Tlm, offsetof(struct tlm_uint64, payload)); /* Bad inputs */ UtAssert_NULL(CFE_SB_GetUserData(NULL)); @@ -4149,6 +4136,60 @@ void Test_CFE_SB_ValidateMsgId(void) UtAssert_INT32_EQ(CFE_SB_ValidateMsgId(MsgId), CFE_SB_FAILED); } +void Test_CFE_SB_CmdTopicIdToMsgId(void) +{ + CFE_SB_MsgId_Atom_t MsgIdVal; + + MsgIdVal = CFE_SB_CmdTopicIdToMsgId(1, 1); + UtAssert_BOOL_TRUE(CFE_SB_IsValidMsgId(CFE_SB_ValueToMsgId(MsgIdVal))); + + MsgIdVal = CFE_SB_CmdTopicIdToMsgId(1, 0); + UtAssert_BOOL_TRUE(CFE_SB_IsValidMsgId(CFE_SB_ValueToMsgId(MsgIdVal))); +} + +void Test_CFE_SB_TlmTopicIdToMsgId(void) +{ + CFE_SB_MsgId_Atom_t MsgIdVal; + + MsgIdVal = CFE_SB_TlmTopicIdToMsgId(1, 1); + UtAssert_BOOL_TRUE(CFE_SB_IsValidMsgId(CFE_SB_ValueToMsgId(MsgIdVal))); + + MsgIdVal = CFE_SB_CmdTopicIdToMsgId(1, 0); + UtAssert_BOOL_TRUE(CFE_SB_IsValidMsgId(CFE_SB_ValueToMsgId(MsgIdVal))); +} + +void Test_CFE_SB_GlobalCmdTopicIdToMsgId(void) +{ + CFE_SB_MsgId_Atom_t MsgIdVal; + + MsgIdVal = CFE_SB_GlobalCmdTopicIdToMsgId(2); + UtAssert_BOOL_TRUE(CFE_SB_IsValidMsgId(CFE_SB_ValueToMsgId(MsgIdVal))); +} + +void Test_CFE_SB_GlobalTlmTopicIdToMsgId(void) +{ + CFE_SB_MsgId_Atom_t MsgIdVal; + + MsgIdVal = CFE_SB_GlobalTlmTopicIdToMsgId(2); + UtAssert_BOOL_TRUE(CFE_SB_IsValidMsgId(CFE_SB_ValueToMsgId(MsgIdVal))); +} + +void Test_CFE_SB_LocalCmdTopicIdToMsgId(void) +{ + CFE_SB_MsgId_Atom_t MsgIdVal; + + MsgIdVal = CFE_SB_LocalCmdTopicIdToMsgId(3); + UtAssert_BOOL_TRUE(CFE_SB_IsValidMsgId(CFE_SB_ValueToMsgId(MsgIdVal))); +} + +void Test_CFE_SB_LocalTlmTopicIdToMsgId(void) +{ + CFE_SB_MsgId_Atom_t MsgIdVal; + + MsgIdVal = CFE_SB_LocalTlmTopicIdToMsgId(3); + UtAssert_BOOL_TRUE(CFE_SB_IsValidMsgId(CFE_SB_ValueToMsgId(MsgIdVal))); +} + /* ** Test validating a msg id */ diff --git a/modules/sb/ut-coverage/sb_UT.h b/modules/sb/ut-coverage/sb_UT.h index bf72d1055..2fbbc9adc 100644 --- a/modules/sb/ut-coverage/sb_UT.h +++ b/modules/sb/ut-coverage/sb_UT.h @@ -2514,4 +2514,14 @@ void Test_SB_CCSDSPriHdr_Macros(void); void Test_SB_CCSDSSecHdr_Macros(void); void Test_SB_IdxPushPop(void); +/* + * TopicID <-> MsgID conversion test routines + */ +void Test_CFE_SB_CmdTopicIdToMsgId(void); +void Test_CFE_SB_TlmTopicIdToMsgId(void); +void Test_CFE_SB_GlobalCmdTopicIdToMsgId(void); +void Test_CFE_SB_GlobalTlmTopicIdToMsgId(void); +void Test_CFE_SB_LocalCmdTopicIdToMsgId(void); +void Test_CFE_SB_LocalTlmTopicIdToMsgId(void); + #endif /* SB_UT_H */