Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix 2358 evs fmt mk2 #2382

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/src/mnem_maps/cfe_time_cmd_mnem_map
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ TIME_ADD1HZSTCF=$sc_$cpu_TIME_Add1HzSTCF \
TIME_SUB1HZSTCF=$sc_$cpu_TIME_Sub1HzSTCF \
TIME_STOPADD1HZ=$sc_$cpu_TIME_StopAdd1Hz \
TIME_STOPSUB1HZ=$sc_$cpu_TIME_StopSub1Hz \
TIME_SETSIGNAL=$sc_$cpu_TIME_SetSignal
TIME_SETSIGNAL=$sc_$cpu_TIME_SetSignal \
TIME_SETPRINT=$sc_$cpu_TIME_SetPrint
9 changes: 9 additions & 0 deletions modules/core_api/fsw/inc/cfe_error.h
Original file line number Diff line number Diff line change
Expand Up @@ -1362,6 +1362,15 @@ char *CFE_ES_StatusToString(CFE_Status_t status, CFE_StatusString_t *status_stri
*
*/
#define CFE_TIME_BAD_ARGUMENT ((CFE_Status_t)0xce000005)

/**
* @brief Time Format Production Too Long
*
* The formatting of a time into a string would overflow the
* output buffer length of CFE_TIME_PRINTED_STRING_SIZE.
*
*/
#define CFE_TIME_FORMAT_TOO_LONG ((CFE_Status_t)0xce000006)
/**@}*/

#endif /* CFE_ERROR_H */
5 changes: 4 additions & 1 deletion modules/core_api/fsw/inc/cfe_time_api_typedefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@
*/

#define CFE_TIME_PRINTED_STRING_SIZE \
24 /**< \brief Required size of buffer to be passed into #CFE_TIME_Print (includes null terminator) */
32 /**< \brief Required size of buffer to be passed into #CFE_TIME_Print (includes null terminator) */

#define CFE_TIME_FORMAT_SIZE \
32 /**< \brief The maximum length we will accept for the format string (incl. null)--affects cmd and tlm */

/*****************************************************************************/
/*
Expand Down
25 changes: 25 additions & 0 deletions modules/time/config/default_cfe_time_extern_typedefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -279,4 +279,29 @@ enum CFE_TIME_SetState
*/
typedef uint8 CFE_TIME_SetState_Enum_t;

enum CFE_TIME_PrintTimestamp
{
/**
* @brief Print timestamp using format string.
*/
CFE_TIME_PrintTimestamp_DateTime = 0,

/**
* @brief Print secs+micros since start/reset.
*/
CFE_TIME_PrintTimestamp_SecsSinceStart = 1,

/**
* @brief Do not print timestamps at all.
*/
CFE_TIME_PrintTimestamp_None = 2
};

/**
* @brief Time print status values (how to print timestamps)
*
* @sa enum CFE_TIME_PrintTimestamp
*/
typedef uint8 CFE_TIME_PrintTimestamp_Enum_t;

#endif /* CFE_TIME_EXTERN_TYPEDEFS_H */
22 changes: 22 additions & 0 deletions modules/time/config/default_cfe_time_fcncodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,28 @@
** \sa #CFE_TIME_SET_STATE_CC, #CFE_TIME_SET_SOURCE_CC
*/
#define CFE_TIME_SET_SIGNAL_CC 15 /* set clock signal (pri vs red) */

/** \cfetimecmd Set Print Format Options
**
** \par Description
** This command sets the time print mode/format (used by EVS when sending
** to stdout, and by ES for syslog messages).
**
** \cfecmdmnemonic \TIME_SETPRINT
**
** \par Command Structure
** #CFE_TIME_SetPrintCmd_t
**
** \par Command Verification
** Successful execution of this command may be verified by examining
** housekeeping output from the TIME module.
**
** \par Criticality
** This command is non-critical, usually used in ground systems and
** doing ground tests.
*/
#define CFE_TIME_SET_PRINT_CC 16 /* set print format command */

/** \} */

#endif
13 changes: 13 additions & 0 deletions modules/time/config/default_cfe_time_interface_cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,4 +198,17 @@
*/
#define CFE_MISSION_TIME_FS_FACTOR 789004800

/**
** \brief On boot, define the time print type.
*/
#define CFE_TIME_PRINT_DEFAULT CFE_TIME_PrintTimestamp_DateTime

/**
** \brief On boot, the CFE_TIME_Print() function will use
** the following strftime-like (+ microseconds) format
** when "printing" times. (Only relevant if CFE_TIME_PRINT_DEFAULT
** is set to CFE_TIME_PrintTimestamp_DateTime.)
*/
#define CFE_TIME_PRINTFMT_DEFAULT "%Y-%j %H:%M:%S.%f"

#endif
21 changes: 21 additions & 0 deletions modules/time/config/default_cfe_time_msgstruct.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,24 @@ typedef struct CFE_TIME_SetStateCmd
CFE_TIME_StateCmd_Payload_t Payload; /**< \brief Command payload */
} CFE_TIME_SetStateCmd_t;

/**
* \brief Payload for the command to set the time print format
*/
typedef struct CFE_TIME_SetPrintCmd_Payload
{
CFE_TIME_PrintTimestamp_Enum_t PrintTimestamp;
char PrintFormat[CFE_TIME_FORMAT_SIZE];
} CFE_TIME_SetPrintCmd_Payload_t;

/**
* \brief Command to set the time print format
*/
typedef struct CFE_TIME_SetPrintCmd
{
CFE_MSG_CommandHeader_t CommandHeader; /**< \brief Command header */
CFE_TIME_SetPrintCmd_Payload_t Payload;
} CFE_TIME_SetPrintCmd_t;

/**
* \brief Set time data source command payload
*/
Expand Down Expand Up @@ -273,6 +291,9 @@ typedef struct CFE_TIME_HousekeepingTlm_Payload
uint32 SubsecsDelay; /**< \cfetlmmnemonic \TIME_1HZDLYSSECS
\brief Current 1 Hz SCTF Delay (sub-seconds) */
#endif

CFE_TIME_PrintTimestamp_Enum_t PrintTimestamp;
char PrintFormat[CFE_TIME_FORMAT_SIZE];
} CFE_TIME_HousekeepingTlm_Payload_t;

typedef struct CFE_TIME_HousekeepingTlm
Expand Down
11 changes: 11 additions & 0 deletions modules/time/fsw/inc/cfe_time_eventids.h
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,17 @@
* message pipe.
*/
#define CFE_TIME_LEN_ERR_EID 49

/**
* \brief TIME Invalid Print Format Event ID
*
* \par Type: ERROR
*
* \par Cause:
*
* Invalid print format string or other print option specified.
*/
#define CFE_TIME_PRINTFORMAT_ERR_EID 50
/**\}*/

#endif /* CFE_TIME_EVENTS_H */
78 changes: 64 additions & 14 deletions modules/time/fsw/src/cfe_time_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -567,27 +567,77 @@ uint32 CFE_TIME_Micro2SubSecs(uint32 MicroSeconds)
*-----------------------------------------------------------------*/
CFE_Status_t CFE_TIME_Print(char *PrintBuffer, CFE_TIME_SysTime_t TimeToPrint)
{
size_t FmtLen = 0;
uint32 Micros = (CFE_TIME_Sub2MicroSecs(TimeToPrint.Subseconds) + CFE_MISSION_TIME_EPOCH_MICROS) / 10;
uint32 mic = (CFE_TIME_Sub2MicroSecs(TimeToPrint.Subseconds) + CFE_MISSION_TIME_EPOCH_MICROS) / 10;
time_t sec = TimeToPrint.Seconds + CFE_MISSION_TIME_EPOCH_SECONDS; // epoch is Jan 1, 1980
size_t OutChrs = 0; // tracks how many chars we've put into PrintBuffer
struct tm tm;
size_t TimeSz;

if (PrintBuffer == NULL)
{
return CFE_TIME_BAD_ARGUMENT;
}

time_t sec = TimeToPrint.Seconds + CFE_MISSION_TIME_EPOCH_SECONDS; // epoch is Jan 1, 1980
gmtime_r(&sec, &tm);
FmtLen = strftime(PrintBuffer, CFE_TIME_PRINTED_STRING_SIZE - 6, "%Y-%j-%H:%M:%S", &tm);
PrintBuffer += FmtLen;
*(PrintBuffer++) = '.';

*(PrintBuffer++) = '0' + (char)((Micros % 100000) / 10000);
*(PrintBuffer++) = '0' + (char)((Micros % 10000) / 1000);
*(PrintBuffer++) = '0' + (char)((Micros % 1000) / 100);
*(PrintBuffer++) = '0' + (char)((Micros % 100) / 10);
*(PrintBuffer++) = '0' + (char)(Micros % 10);
*PrintBuffer = '\0';
switch (CFE_TIME_Global.PrintTimestamp)
{
case CFE_TIME_PrintTimestamp_DateTime:
gmtime_r(&sec, &tm);

/*
** `PrintFormatMillis` points at the `%f` in PrintFormat, if there is a `%f`.
*/
if (CFE_TIME_Global.PrintFormatMillis)
{
/* ...blot out the `%f`, temporarily. */
CFE_TIME_Global.PrintFormatMillis[0] = '\0';
}

TimeSz = strftime(PrintBuffer, CFE_TIME_PRINTED_STRING_SIZE, CFE_TIME_Global.PrintFormat, &tm);

if (TimeSz == 0)
{
return CFE_TIME_FORMAT_TOO_LONG;
}

OutChrs += TimeSz;

if (CFE_TIME_Global.PrintFormatMillis)
{
/* unblot */
CFE_TIME_Global.PrintFormatMillis[0] = '%';

if (OutChrs + 6 > CFE_TIME_PRINTED_STRING_SIZE)
{
return CFE_TIME_FORMAT_TOO_LONG;
}

OutChrs += snprintf(PrintBuffer + OutChrs, CFE_TIME_PRINTED_STRING_SIZE - OutChrs, "%05d", mic);

/* it's likely the `%f` is last in the format string, check if there's any remainder...*/
if (CFE_TIME_Global.PrintFormatMillis[2])
{
TimeSz = strftime(PrintBuffer + OutChrs, CFE_TIME_PRINTED_STRING_SIZE, CFE_TIME_Global.PrintFormatMillis + 2, &tm);

if (TimeSz == 0)
{
return CFE_TIME_FORMAT_TOO_LONG;
}

OutChrs += TimeSz;
}
}
PrintBuffer[OutChrs] = '\0';
break;

case CFE_TIME_PrintTimestamp_SecsSinceStart:
OutChrs += snprintf(PrintBuffer, CFE_TIME_PRINTED_STRING_SIZE, "%ld.%06d", (long int)sec, mic);
PrintBuffer[OutChrs] = '\0';
break;

default:
PrintBuffer[0] = '\0';
break;
}
Comment on lines +581 to +640

Check notice

Code scanning / CodeQL

Long switch case

Switch has at least one case that is too long: [CFE_TIME_PrintTimestamp_DateTime (48 lines)](1).
return CFE_SUCCESS;
}

Expand Down
7 changes: 7 additions & 0 deletions modules/time/fsw/src/cfe_time_dispatch.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,13 @@ void CFE_TIME_TaskPipe(const CFE_SB_Buffer_t *SBBufPtr)
}
break;

case CFE_TIME_SET_PRINT_CC:
if (CFE_TIME_VerifyCmdLength(&SBBufPtr->Msg, sizeof(CFE_TIME_SetPrintCmd_t)))

Check warning

Code scanning / CodeQL

Side effect in a Boolean expression

This Boolean expression is not side-effect free.
{
CFE_TIME_SetPrintCmd((const CFE_TIME_SetPrintCmd_t *)SBBufPtr);
}
break;

default:

CFE_TIME_Global.CommandErrorCounter++;
Expand Down
11 changes: 11 additions & 0 deletions modules/time/fsw/src/cfe_time_task.c
Original file line number Diff line number Diff line change
Expand Up @@ -1090,3 +1090,14 @@ int32 CFE_TIME_Sub1HZAdjustmentCmd(const CFE_TIME_Sub1HZAdjustmentCmd_t *data)
CFE_TIME_1HzAdjImpl(&data->Payload, CFE_TIME_AdjustDirection_SUBTRACT);
return CFE_SUCCESS;
}

/*----------------------------------------------------------------
*
* Application-scope internal function
* See description in header file for argument/return detail
*
*-----------------------------------------------------------------*/
int32 CFE_TIME_SetPrintCmd(const CFE_TIME_SetPrintCmd_t *data)
{
return CFE_TIME_SetPrintFormat(data->Payload.PrintTimestamp, data->Payload.PrintFormat);
}
60 changes: 60 additions & 0 deletions modules/time/fsw/src/cfe_time_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,11 @@ void CFE_TIME_InitData(void)
*/
CFE_MSG_Init(CFE_MSG_PTR(CFE_TIME_Global.Local1HzCmd.CommandHeader), CFE_SB_ValueToMsgId(CFE_TIME_1HZ_CMD_MID),
sizeof(CFE_TIME_Global.Local1HzCmd));

/*
** Configure the default time print format.
*/
CFE_TIME_SetPrintFormat(CFE_TIME_PRINT_DEFAULT, CFE_TIME_PRINTFMT_DEFAULT);
}

/*----------------------------------------------------------------
Expand Down Expand Up @@ -408,6 +413,9 @@ void CFE_TIME_GetHkData(const CFE_TIME_Reference_t *Reference)
CFE_TIME_Global.HkPacket.Payload.SecondsDelay = Reference->AtToneDelay.Seconds;
CFE_TIME_Global.HkPacket.Payload.SubsecsDelay = Reference->AtToneDelay.Subseconds;
#endif

strncpy(CFE_TIME_Global.HkPacket.Payload.PrintFormat, CFE_TIME_Global.PrintFormat, CFE_TIME_FORMAT_SIZE);
CFE_TIME_Global.HkPacket.Payload.PrintTimestamp = CFE_TIME_Global.PrintTimestamp;
}

/*----------------------------------------------------------------
Expand Down Expand Up @@ -1035,3 +1043,55 @@ int32 CFE_TIME_CleanUpApp(CFE_ES_AppId_t AppId)

return Status;
}

/*----------------------------------------------------------------
*
* Application-scope internal function
* See description in header file for argument/return detail
*
*-----------------------------------------------------------------*/
int32 CFE_TIME_SetPrintFormat(CFE_TIME_PrintTimestamp_Enum_t PrintTimestamp, const char *PrintFormat)

Check notice

Code scanning / CodeQL

Long function without assertion

All functions of more than 10 lines should have at least one assertion.
{
if (PrintTimestamp < 0 || PrintTimestamp > CFE_TIME_PrintTimestamp_None)

Check warning

Code scanning / CodeQL

Comparison result is always the same

Comparison is always false because PrintTimestamp >= 0.
{
return CFE_TIME_BAD_ARGUMENT;
}

CFE_TIME_Global.PrintTimestamp = PrintTimestamp;

if (PrintTimestamp == CFE_TIME_PrintTimestamp_DateTime)
{
char *PctF;

/* null pointer or empty string */
if (PrintFormat == NULL || PrintFormat[0] == '\0')
{
return CFE_TIME_BAD_ARGUMENT;
}

CFE_TIME_Global.PrintFormatMillis = NULL;

strncpy(CFE_TIME_Global.PrintFormat, PrintFormat, CFE_TIME_FORMAT_SIZE);

/* find the (first) "%f", and mark it so that when we call CFE_TIME_Print() it can quickly process it. */
PctF = CFE_TIME_Global.PrintFormat;
while (PctF[0] != '\0') {
if (PctF[0] == '%')
{
switch (PctF[1])
{
case 'f':
CFE_TIME_Global.PrintFormatMillis = PctF;
break;
case '\0':
break;
default:
PctF++; /* skip forward two chars */
}
}
PctF++;
}
Comment on lines +1078 to +1093

Check warning

Code scanning / CodeQL

Unbounded loop

This loop does not have a fixed bound.
}

return CFE_SUCCESS;
}
Loading