Skip to content

Commit

Permalink
Fix #2358, adds TIME module command to set CFE_TIME_Print() format
Browse files Browse the repository at this point in the history
  • Loading branch information
CDKnightNASA committed Jun 8, 2023
1 parent 2bf3299 commit 10c81ea
Show file tree
Hide file tree
Showing 13 changed files with 286 additions and 16 deletions.
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_PrintState
{
/**
* @brief Print timestamp using format string.
*/
CFE_TIME_PrintState_DateTime = 0,

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

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

/**
* @brief Time print status values (how to print timestamps)
*
* @sa enum CFE_TIME_PrintState
*/
typedef uint8 CFE_TIME_PrintState_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_PrintState_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_PrintState_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_PrintState_Enum_t PrintState;
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_PrintState_Enum_t PrintState;
char PrintFormat[CFE_TIME_FORMAT_SIZE];
} CFE_TIME_HousekeepingTlm_Payload_t;

typedef struct CFE_TIME_HousekeepingTlm
Expand Down
79 changes: 65 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,78 @@ 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
/* temporary buffer to store the format so we can modify it to blot '%f' */
char FmtBuf[CFE_TIME_FORMAT_SIZE];
char *FmtPtr = FmtBuf;
char *PctF;
size_t OutChrs = 0;
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.PrintState)
{
case CFE_TIME_PrintState_DateTime:
gmtime_r(&sec, &tm);

strncpy(FmtPtr, CFE_TIME_Global.PrintFormat, CFE_TIME_FORMAT_SIZE);

while(*FmtPtr != '\0' && OutChrs < CFE_TIME_PRINTED_STRING_SIZE)
{
/* if we have "%f", call strftime for string before and string after */
PctF = strstr(FmtBuf, "%f");
if (PctF)
{
*PctF = '\0'; /* blot out "%f", for now */
}

TimeSz = strftime(PrintBuffer + OutChrs, CFE_TIME_PRINTED_STRING_SIZE - OutChrs, FmtPtr, &tm);

if (*FmtPtr && TimeSz == 0)
{
/* strftime returns 0 if the buffer is too small */
return CFE_TIME_FORMAT_TOO_LONG;
}

OutChrs += TimeSz;

/* we found/blotted %f above */
if (PctF)
{
/* write %f value */
if (OutChrs < CFE_TIME_PRINTED_STRING_SIZE - 5)
{
OutChrs += snprintf(PrintBuffer + OutChrs, CFE_TIME_PRINTED_STRING_SIZE - OutChrs, "%05d", mic);
}
else
{
return CFE_TIME_FORMAT_TOO_LONG;
}

/* go back through the loop with the remaining format */
FmtPtr = PctF + 2;
}
else
{
PrintBuffer[OutChrs] = '\0'; /* just in case, null-terminate the string */
break; /* break while */
}
}
break;
case CFE_TIME_PrintState_SecsSinceStart:
OutChrs += snprintf(PrintBuffer, CFE_TIME_PRINTED_STRING_SIZE, "%ld.%06d", (long int)sec, mic);
PrintBuffer[OutChrs] = '\0';
break;
default:
PrintBuffer[0] = '\0';
break;
}
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)))
{
CFE_TIME_SetPrintCmd((const CFE_TIME_SetPrintCmd_t *)SBBufPtr);
}
break;

default:

CFE_TIME_Global.CommandErrorCounter++;
Expand Down
13 changes: 13 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,16 @@ 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)
{
CFE_TIME_Global.PrintState = data->Payload.PrintState;
strncpy(CFE_TIME_Global.PrintFormat, data->Payload.PrintFormat, CFE_TIME_FORMAT_SIZE);
return CFE_SUCCESS;
}
9 changes: 9 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,12 @@ 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_Global.PrintState = CFE_TIME_PRINT_DEFAULT;
strncpy(CFE_TIME_Global.PrintFormat, CFE_TIME_PRINTFMT_DEFAULT, CFE_TIME_FORMAT_SIZE);
}

/*----------------------------------------------------------------
Expand Down Expand Up @@ -408,6 +414,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.PrintState = CFE_TIME_Global.PrintState;
}

/*----------------------------------------------------------------
Expand Down
16 changes: 16 additions & 0 deletions modules/time/fsw/src/cfe_time_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,16 @@ typedef struct
** One callback per app is allowed
*/
CFE_TIME_SynchCallbackRegEntry_t SynchCallback[CFE_PLATFORM_ES_MAX_APPLICATIONS];

/*
** What form should CFE_TIME_Print produce.
*/
CFE_TIME_PrintState_Enum_t PrintState;

/*
** For formatted CFE_TIME_Print output, use this format string.
*/
char PrintFormat[CFE_TIME_FORMAT_SIZE];
} CFE_TIME_Global_t;

/*
Expand Down Expand Up @@ -867,4 +877,10 @@ int32 CFE_TIME_Sub1HZAdjustmentCmd(const CFE_TIME_Sub1HZAdjustmentCmd_t *data);
*/
int32 CFE_TIME_SubAdjustCmd(const CFE_TIME_SubAdjustCmd_t *data);

/*---------------------------------------------------------------------------------------*/
/**
* @brief Time task ground command (print format adjust)
*/
int32 CFE_TIME_SetPrintCmd(const CFE_TIME_SetPrintCmd_t *data);

#endif /* CFE_TIME_UTILS_H */
Loading

0 comments on commit 10c81ea

Please sign in to comment.