From bb88193fda3f8269aa2c6a22143bb07a94d19de1 Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Tue, 31 Mar 2026 09:07:45 -0400 Subject: [PATCH 1/5] Fix #28, change bitmask to uint8 and simplify macro Use uint8 for the TLM bitmasks, which allows for a much simpler macro that should actually work --- config/default_sc_msgdefs.h | 4 ++-- eds/sc.xml | 12 ++++++------ fsw/src/sc_cmds.c | 12 ++++++++---- fsw/src/sc_cmds.h | 19 ++++++++----------- 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/config/default_sc_msgdefs.h b/config/default_sc_msgdefs.h index d67259e..489e90c 100644 --- a/config/default_sc_msgdefs.h +++ b/config/default_sc_msgdefs.h @@ -175,14 +175,14 @@ typedef struct uint32 NextRtsWakeupCnt; /**< \brief Next RTS Command Absolute Wakeup Count */ uint32 NextAtsTime; /**< \brief Next ATS Command Time (seconds) */ - uint16 RtsExecutingStatus[(SC_NUMBER_OF_RTS + 15) / 16]; + uint8 RtsExecutingStatusBits[(SC_NUMBER_OF_RTS + 7) / 8]; /**< \brief RTS executing status bit map where each uint16 represents 16 RTS numbers. Note: array index numbers and bit numbers use base zero indexing, but RTS numbers use base one indexing. Thus, the LSB (bit zero) of uint16 array index zero represents RTS number 1, and bit one of uint16 array index zero represents RTS number 2, etc. If an RTS is IDLE, then the corresponding bit is zero. If an RTS is EXECUTING, then the corresponding bit is one. */ - uint16 RtsDisabledStatus[(SC_NUMBER_OF_RTS + 15) / 16]; + uint8 RtsDisabledStatusBits[(SC_NUMBER_OF_RTS + 7) / 8]; /**< \brief RTS disabled status bit map where each uint16 represents 16 RTS numbers. Note: array index numbers and bit numbers use base zero indexing, but RTS numbers use base one indexing. Thus, the LSB (bit zero) of uint16 array index zero represents RTS number 1, and bit one of uint16 array diff --git a/eds/sc.xml b/eds/sc.xml index ee01f3d..a4ca86e 100644 --- a/eds/sc.xml +++ b/eds/sc.xml @@ -146,20 +146,20 @@ - + - Each BASE_TYPES/uint16 represents 16 RTS numbers. + Each entry represents 8 RTS numbers. Note: array Note: array index numbers and bit numbers use base zero indexing, but RTS numbers use base one indexing. - Thus, the LSB (bit zero) of BASE_TYPES/uint16 array index zero represents RTS number 1, and bit one of BASE_TYPES/uint16 + Thus, the LSB (bit zero) of uint8 array index zero represents RTS number 1, and bit one of uint8 array index zero represents RTS number 2, etc. If an RTS is ENABLED, then the corresponding bit is zero. If an RTS is DISABLED, then the corresponding bit is one. - + - Each BASE_TYPES/uint16 represents 16 RTS numbers. Note: array + Each entry represents 8 RTS numbers. Note: array index numbers and bit numbers use base zero indexing, but RTS numbers use base one indexing. Thus, - the LSB (bit zero) of BASE_TYPES/uint16 array index zero represents RTS number 1, and bit one of BASE_TYPES/uint16 array + the LSB (bit zero) of uint8 array index zero represents RTS number 1, and bit one of uint8 array index zero represents RTS number 2, etc. If an RTS is IDLE, then the corresponding bit is zero. If an RTS is EXECUTING, then the corresponding bit is one. diff --git a/fsw/src/sc_cmds.c b/fsw/src/sc_cmds.c index 2a9b832..57e2687 100644 --- a/fsw/src/sc_cmds.c +++ b/fsw/src/sc_cmds.c @@ -457,15 +457,19 @@ void SC_SendHkPacket(void) ** Fill out the RTS status bit mask ** First clear out the status mask */ - memset(SC_OperData.HkPacket.Payload.RtsExecutingStatus, 0, sizeof(SC_OperData.HkPacket.Payload.RtsExecutingStatus)); - memset(SC_OperData.HkPacket.Payload.RtsDisabledStatus, 0, sizeof(SC_OperData.HkPacket.Payload.RtsDisabledStatus)); + memset(SC_OperData.HkPacket.Payload.RtsExecutingStatusBits, + 0, + sizeof(SC_OperData.HkPacket.Payload.RtsExecutingStatusBits)); + memset(SC_OperData.HkPacket.Payload.RtsDisabledStatusBits, + 0, + sizeof(SC_OperData.HkPacket.Payload.RtsDisabledStatusBits)); for (i = 0; i < SC_NUMBER_OF_RTS; i++) { RtsInfoPtr = SC_GetRtsInfoObject(SC_RTS_IDX_C(i)); - SC_SET_HKTLM_RTS_MASK(SC_OperData.HkPacket.Payload.RtsDisabledStatus, i, RtsInfoPtr->DisabledFlag); - SC_SET_HKTLM_RTS_MASK(SC_OperData.HkPacket.Payload.RtsExecutingStatus, + SC_SET_HKTLM_RTS_MASK(SC_OperData.HkPacket.Payload.RtsDisabledStatusBits, i, RtsInfoPtr->DisabledFlag); + SC_SET_HKTLM_RTS_MASK(SC_OperData.HkPacket.Payload.RtsExecutingStatusBits, i, (RtsInfoPtr->RtsStatus == SC_Status_EXECUTING)); } /* end for */ diff --git a/fsw/src/sc_cmds.h b/fsw/src/sc_cmds.h index d1f437f..b8f6c7c 100644 --- a/fsw/src/sc_cmds.h +++ b/fsw/src/sc_cmds.h @@ -35,22 +35,19 @@ typedef enum APPEND } SC_TableType; -#define SC_HKTLM_MEMBER_SIZE(x) sizeof(((SC_HkTlm_Payload_t *)0)->x) - /* Macro to set/clear bits in the HK TLM bitmask for RTS status */ enum { - SC_BITS_PER_HKTLM_OCTET = SC_NUMBER_OF_RTS / SC_HKTLM_MEMBER_SIZE(RtsDisabledStatus), - SC_BITS_PER_HKTLM_WORD = SC_HKTLM_MEMBER_SIZE(RtsDisabledStatus[0]) * SC_BITS_PER_HKTLM_OCTET, + SC_BITS_PER_HKTLM_ENTRY = 8 /* by definition, as this now uses uint8 only */ }; -#define SC_SET_HKTLM_RTS_MASK(f, s, v) \ - do \ - { \ - if (v) \ - f[s / SC_BITS_PER_HKTLM_WORD] |= (1 << (s % SC_BITS_PER_HKTLM_WORD)); \ - else \ - f[s / SC_BITS_PER_HKTLM_WORD] &= ~(1 << (s % SC_BITS_PER_HKTLM_WORD)); \ +#define SC_SET_HKTLM_RTS_MASK(f, s, v) \ + do \ + { \ + if (v) \ + f[s / SC_BITS_PER_HKTLM_ENTRY] |= (1 << (s % SC_BITS_PER_HKTLM_ENTRY)); \ + else \ + f[s / SC_BITS_PER_HKTLM_ENTRY] &= ~(1 << (s % SC_BITS_PER_HKTLM_ENTRY)); \ } while (0) /** From 0eb48de0e08a7289f03c65323af807da52e0d872 Mon Sep 17 00:00:00 2001 From: Cameron Sykes Date: Thu, 16 Apr 2026 11:12:30 -0400 Subject: [PATCH 2/5] Fix #31, Make implicit padding explicit --- config/default_sc_msgdefs.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/config/default_sc_msgdefs.h b/config/default_sc_msgdefs.h index 489e90c..c40926f 100644 --- a/config/default_sc_msgdefs.h +++ b/config/default_sc_msgdefs.h @@ -150,7 +150,7 @@ typedef struct uint8 CmdErrCtr; /**< \brief Counts Request Errors */ uint8 CmdCtr; /**< \brief Counts Ground Requests */ - uint8 Padding8; /**< \brief Structure padding */ + uint8 Padding1; /**< \brief Structure padding */ uint16 SwitchPendFlag; /**< \brief Switch pending flag: 0 = NO, 1 = YES */ uint16 NumRtsActive; /**< \brief Number of RTSs currently active */ @@ -188,6 +188,8 @@ typedef struct the LSB (bit zero) of uint16 array index zero represents RTS number 1, and bit one of uint16 array index zero represents RTS number 2, etc. If an RTS is ENABLED, then the corresponding bit is zero. If an RTS is DISABLED, then the corresponding bit is one. */ + + uint8 Padding2[2]; } SC_HkTlm_Payload_t; /**\}*/ From 234b715e43e83fb402c4010b4a256eed6ed8c6e5 Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Mon, 20 Apr 2026 18:06:42 -0400 Subject: [PATCH 3/5] Fix #33, update bitmask definition in unit test Updates to match the change made in #29. Somehow this was missed in the first commit. --- unit-test/sc_cmds_tests.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unit-test/sc_cmds_tests.c b/unit-test/sc_cmds_tests.c index 1b13b22..6efeebf 100644 --- a/unit-test/sc_cmds_tests.c +++ b/unit-test/sc_cmds_tests.c @@ -837,8 +837,8 @@ void SC_SendHkPacket_Test(void) SC_RtsIndex_t RtsIndex = SC_RTS_IDX_C(SC_NUMBER_OF_RTS - 1); SC_RtsInfoEntry_t *RtsInfoPtr; SC_AtsInfoTable_t *AtsInfoPtr; - uint16 ExpectedRtsExecStatus[(SC_NUMBER_OF_RTS + 15) / 16]; - uint16 ExpectedRtsDisabledStatus[(SC_NUMBER_OF_RTS + 15) / 16]; + uint8 ExpectedRtsExecStatus[(SC_NUMBER_OF_RTS + 7) / 8]; + uint8 ExpectedRtsDisabledStatus[(SC_NUMBER_OF_RTS + 7) / 8]; memset(&ExpectedRtsExecStatus[0], 0u, sizeof(ExpectedRtsExecStatus)); memset(&ExpectedRtsDisabledStatus[0], 0u, sizeof(ExpectedRtsDisabledStatus)); From afbba6879b0da66fce47a5e7404c49ce58613588 Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Wed, 22 Apr 2026 11:07:58 -0400 Subject: [PATCH 4/5] Fix cFS/cFS#677, correct ATS table name The default definition for the ATS table did not agree wtih the default name in the registry for the ATS table. --- fsw/tables/sc_ats1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fsw/tables/sc_ats1.c b/fsw/tables/sc_ats1.c index b6bfbea..a37cde8 100644 --- a/fsw/tables/sc_ats1.c +++ b/fsw/tables/sc_ats1.c @@ -121,4 +121,4 @@ SC_AtsTable1_t SC_Ats1 = { SC_RESET_COUNTERS_CKSUM)}}}; /* Macro for table structure */ -CFE_TBL_FILEDEF(SC_Ats1, SC.AtsTable1, SC Example ATS_TBL1, sc_ats1.tbl) +CFE_TBL_FILEDEF(SC_Ats1, SC.ATS_TBL1, SC Example ATS_TBL1, sc_ats1.tbl) From e69162f88a2f1c01c5b961385cd082e6552db6fb Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Tue, 28 Apr 2026 11:38:51 -0400 Subject: [PATCH 5/5] Fix cFS/cFE#219, correct alignment of SC ATS table The ATS validation requires that all entries are aligned to a 32 bit boundary, but the table definition was not ensuring this. It also had an explicit size of 0 on the first entry (invalid) which prevented loading. --- fsw/tables/sc_ats1.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/fsw/tables/sc_ats1.c b/fsw/tables/sc_ats1.c index a37cde8..9e796d0 100644 --- a/fsw/tables/sc_ats1.c +++ b/fsw/tables/sc_ats1.c @@ -68,17 +68,22 @@ #define SC_RESET_COUNTERS_CKSUM (0x8E) #endif +typedef union +{ + uint32 Align32; + SC_AtsEntryHeader_t Hdr; +} SC_AlignedAtsEntryHeader_t; /* Custom table structure, modify as needed to add desired commands */ typedef struct { - SC_AtsEntryHeader_t hdr1; - SC_NoopCmd_t cmd1; - SC_AtsEntryHeader_t hdr2; - SC_EnableRtsCmd_t cmd2; - SC_AtsEntryHeader_t hdr3; - SC_StartRtsCmd_t cmd3; - SC_AtsEntryHeader_t hdr4; - SC_ResetCountersCmd_t cmd4; + SC_AlignedAtsEntryHeader_t hdr1; + SC_NoopCmd_t cmd1; + SC_AlignedAtsEntryHeader_t hdr2; + SC_EnableRtsCmd_t cmd2; + SC_AlignedAtsEntryHeader_t hdr3; + SC_StartRtsCmd_t cmd3; + SC_AlignedAtsEntryHeader_t hdr4; + SC_ResetCountersCmd_t cmd4; } SC_AtsStruct1_t; /* Define the union to size the table correctly */ @@ -94,13 +99,13 @@ typedef union /* Used designated intializers to be verbose, modify as needed/desired */ SC_AtsTable1_t SC_Ats1 = { .ats = {/* 1 */ - .hdr1 = {.CmdNumber = SC_COMMAND_NUM_INITIALIZER(1), + .hdr1.Hdr = {.CmdNumber = SC_COMMAND_NUM_INITIALIZER(1), .TimeTag_MS = SC_CMD1_TIME >> 16, .TimeTag_LS = SC_CMD1_TIME & 0xFFFF}, - .cmd1 = {CFE_MSG_CMD_HDR_INIT(SC_CMD_MID, 0, SC_NOOP_CC, SC_NOOP_CKSUM)}, + .cmd1 = {CFE_MSG_CMD_HDR_INIT(SC_CMD_MID, SC_MEMBER_SIZE(cmd1), SC_NOOP_CC, SC_NOOP_CKSUM)}, /* 2 */ - .hdr2 = {.CmdNumber = SC_COMMAND_NUM_INITIALIZER(2), + .hdr2.Hdr = {.CmdNumber = SC_COMMAND_NUM_INITIALIZER(2), .TimeTag_MS = SC_CMD2_TIME >> 16, .TimeTag_LS = SC_CMD2_TIME & 0xFFFF}, .cmd2 = {CFE_MSG_CMD_HDR_INIT(SC_CMD_MID, SC_MEMBER_SIZE(cmd2), SC_ENABLE_RTS_CC, SC_ENABLE_RTS1_CKSUM)}, @@ -108,13 +113,13 @@ SC_AtsTable1_t SC_Ats1 = { .cmd2.Payload = {.RtsNum = SC_RTS_NUM_INITIALIZER(1)}, /* 3 */ - .hdr3 = {.CmdNumber = SC_COMMAND_NUM_INITIALIZER(3), + .hdr3.Hdr = {.CmdNumber = SC_COMMAND_NUM_INITIALIZER(3), .TimeTag_MS = SC_CMD3_TIME >> 16, .TimeTag_LS = SC_CMD3_TIME & 0xFFFF}, .cmd3 = {CFE_MSG_CMD_HDR_INIT(SC_CMD_MID, SC_MEMBER_SIZE(cmd3), SC_START_RTS_CC, SC_START_RTS1_CKSUM)}, /* 4 */ - .hdr4 = {.CmdNumber = SC_COMMAND_NUM_INITIALIZER(4), + .hdr4.Hdr = {.CmdNumber = SC_COMMAND_NUM_INITIALIZER(4), .TimeTag_MS = SC_CMD4_TIME >> 16, .TimeTag_LS = SC_CMD4_TIME & 0xFFFF}, .cmd4 = {CFE_MSG_CMD_HDR_INIT(SC_CMD_MID, SC_MEMBER_SIZE(cmd4), SC_RESET_COUNTERS_CC,