Skip to content

Commit

Permalink
Fix #103, add option to configure base tick rate
Browse files Browse the repository at this point in the history
SCH_LAB was fixed at 1Hz because it bound to the 1Hz tick from CFE_TIME.
This creates an OSAL timer instead, which posts a semaphore, and this
can serve as a much more flexible time source, with configurable rate.

This still binds to 1Hz and the SCH does not start its first message
until the first 1Hz is received, thereby keeping some form of 1Hz sync.
  • Loading branch information
jphickey committed Dec 6, 2021
1 parent 8124041 commit 0396089
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 7 deletions.
3 changes: 2 additions & 1 deletion fsw/platform_inc/sch_lab_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,13 @@
typedef struct
{
CFE_SB_MsgId_t MessageID; /* Message ID for the table entry */
uint32 PacketRate; /* Rate: Send packet every N seconds */
uint32 PacketRate; /* Rate: Send packet every N ticks */
CFE_MSG_FcnCode_t FcnCode; /* Command/Function code to set */
} SCH_LAB_ScheduleTableEntry_t;

typedef struct
{
uint32 TickRate; /* Ticks per second to configure for timer (0=default) */
SCH_LAB_ScheduleTableEntry_t Config[SCH_LAB_MAX_SCHEDULE_ENTRIES];
} SCH_LAB_ScheduleTable_t;

Expand Down
80 changes: 75 additions & 5 deletions fsw/src/sch_lab_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ typedef struct
typedef struct
{
SCH_LAB_StateEntry_t State[SCH_LAB_MAX_SCHEDULE_ENTRIES];
osal_id_t TimerId;
osal_id_t TimingSem;
CFE_TBL_Handle_t TblHandle;
CFE_SB_PipeId_t CmdPipe;
} SCH_LAB_GlobalData_t;
Expand All @@ -80,8 +82,9 @@ void SCH_Lab_AppMain(void)
{
int i;
uint32 SCH_OneHzPktsRcvd = 0;
uint32 Status = CFE_SUCCESS;
uint32 RunStatus = CFE_ES_RunStatus_APP_RUN;
int32 OsStatus;
CFE_Status_t Status;
uint32 RunStatus = CFE_ES_RunStatus_APP_RUN;
SCH_LAB_StateEntry_t *LocalStateEntry;
CFE_SB_Buffer_t * SBBufPtr;

Expand All @@ -99,16 +102,29 @@ void SCH_Lab_AppMain(void)
{
CFE_ES_PerfLogExit(SCH_MAIN_TASK_PERF_ID);

/* Pend on receipt of 1Hz packet */
Status = CFE_SB_ReceiveBuffer(&SBBufPtr, SCH_LAB_Global.CmdPipe, CFE_SB_PEND_FOREVER);
/* Pend on timing sem */
OsStatus = OS_CountSemTake(SCH_LAB_Global.TimingSem);
if (OsStatus == OS_SUCCESS)
{
/* check for arrival of the 1Hz - this should sync counts (TBD) */
Status = CFE_SB_ReceiveBuffer(&SBBufPtr, SCH_LAB_Global.CmdPipe, CFE_SB_POLL);
}
else
{
Status = CFE_STATUS_EXTERNAL_RESOURCE_FAIL;
}

CFE_ES_PerfLogEntry(SCH_MAIN_TASK_PERF_ID);

if (Status == CFE_SUCCESS)
{
SCH_OneHzPktsRcvd++;
}

if (OsStatus == OS_SUCCESS && SCH_OneHzPktsRcvd > 0)
{
/*
** Process table every second, sending packets that are ready
** Process table every tick, sending packets that are ready
*/
LocalStateEntry = SCH_LAB_Global.State;
for (i = 0; i < SCH_LAB_MAX_SCHEDULE_ENTRIES; i++)
Expand All @@ -132,6 +148,11 @@ void SCH_Lab_AppMain(void)

} /* end SCH_Lab_AppMain */

void SCH_LAB_LocalTimerCallback(osal_id_t object_id, void *arg)
{
OS_CountSemGive(SCH_LAB_Global.TimingSem);
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* */
/* SCH_LAB_AppInit() -- initialization */
Expand All @@ -141,12 +162,38 @@ int32 SCH_LAB_AppInit(void)
{
int i;
int32 Status;
int32 OsStatus;
uint32 TimerPeriod;
osal_id_t TimeBaseId;
SCH_LAB_ScheduleTable_t * ConfigTable;
SCH_LAB_ScheduleTableEntry_t *ConfigEntry;
SCH_LAB_StateEntry_t * LocalStateEntry;

memset(&SCH_LAB_Global, 0, sizeof(SCH_LAB_Global));

OsStatus = OS_CountSemCreate(&SCH_LAB_Global.TimingSem, "SCH_LAB", 0, 0);
if (OsStatus != OS_SUCCESS)
{
CFE_ES_WriteToSysLog("%s: OS_CountSemCreate failed:RC=%ld\n", __func__, (long)OsStatus);
return CFE_STATUS_EXTERNAL_RESOURCE_FAIL;
}

/* The underlying timebase object should have been created by the PSP */
OsStatus = OS_TimeBaseGetIdByName(&TimeBaseId, "cFS-Master");
if (OsStatus != OS_SUCCESS)
{
CFE_ES_WriteToSysLog("%s: OS_TimeBaseGetIdByName failed:RC=%ld\n", __func__, (long)OsStatus);
return CFE_STATUS_EXTERNAL_RESOURCE_FAIL;
}

/* Create the timer callback (but not set yet, as that requires the config table) */
OsStatus = OS_TimerAdd(&SCH_LAB_Global.TimerId, "SCH_LAB", TimeBaseId, SCH_LAB_LocalTimerCallback, NULL);
if (OsStatus != OS_SUCCESS)
{
CFE_ES_WriteToSysLog("%s: OS_TimerAdd failed:RC=%ld\n", __func__, (long)OsStatus);
return CFE_STATUS_EXTERNAL_RESOURCE_FAIL;
}

/*
** Register tables with cFE and load default data
*/
Expand Down Expand Up @@ -203,6 +250,22 @@ int32 SCH_LAB_AppInit(void)
++LocalStateEntry;
}

if (ConfigTable->TickRate == 0)
{
/* use default of 1 second */
CFE_ES_WriteToSysLog("%s: Using default tick rate of 1 second\n", __func__);
TimerPeriod = 1000000;
}
else
{
TimerPeriod = 1000000 / ConfigTable->TickRate;
if ((TimerPeriod * ConfigTable->TickRate) != 1000000)
{
CFE_ES_WriteToSysLog("%s: WARNING: tick rate of %lu is not an integer number of microseconds\n", __func__,
(unsigned long)ConfigTable->TickRate);
}
}

/*
** Release the table
*/
Expand All @@ -225,6 +288,13 @@ int32 SCH_LAB_AppInit(void)
OS_printf("SCH Error subscribing to 1hz!\n");
}

/* Set timer period */
OsStatus = OS_TimerSet(SCH_LAB_Global.TimerId, 1000000, TimerPeriod);
if (OsStatus != OS_SUCCESS)
{
CFE_ES_WriteToSysLog("%s: OS_TimerSet failed:RC=%ld\n", __func__, (long)OsStatus);
}

OS_printf("SCH Lab Initialized.%s\n", SCH_LAB_VERSION_STRING);

return (CFE_SUCCESS);
Expand Down
3 changes: 2 additions & 1 deletion fsw/tables/sch_lab_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@
** 3. If the table grows too big, increase SCH_LAB_MAX_SCHEDULE_ENTRIES
*/

SCH_LAB_ScheduleTable_t SCH_TBL_Structure = {.Config = {
SCH_LAB_ScheduleTable_t SCH_TBL_Structure = {.TickRate = 1,
.Config = {
{CFE_SB_MSGID_WRAP_VALUE(CFE_ES_SEND_HK_MID), 4, 0},
{CFE_SB_MSGID_WRAP_VALUE(CFE_EVS_SEND_HK_MID), 4, 0},
{CFE_SB_MSGID_WRAP_VALUE(CFE_TIME_SEND_HK_MID), 4, 0},
Expand Down

0 comments on commit 0396089

Please sign in to comment.