diff --git a/fsw/platform_inc/sch_lab_table.h b/fsw/platform_inc/sch_lab_table.h index 22e0993..b76cd8d 100644 --- a/fsw/platform_inc/sch_lab_table.h +++ b/fsw/platform_inc/sch_lab_table.h @@ -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; diff --git a/fsw/src/sch_lab_app.c b/fsw/src/sch_lab_app.c index 2539267..e30879b 100644 --- a/fsw/src/sch_lab_app.c +++ b/fsw/src/sch_lab_app.c @@ -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; @@ -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; @@ -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++) @@ -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 */ @@ -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 */ @@ -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 */ @@ -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); diff --git a/fsw/tables/sch_lab_table.c b/fsw/tables/sch_lab_table.c index 90920b8..db4d87c 100644 --- a/fsw/tables/sch_lab_table.c +++ b/fsw/tables/sch_lab_table.c @@ -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},