-
Notifications
You must be signed in to change notification settings - Fork 202
/
cfe_es_erlog.c
434 lines (385 loc) · 15.1 KB
/
cfe_es_erlog.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
/*
** GSC-18128-1, "Core Flight Executive Version 6.7"
**
** Copyright (c) 2006-2019 United States Government as represented by
** the Administrator of the National Aeronautics and Space Administration.
** All Rights Reserved.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*
** File:
** cfe_es_erlog.c
**
** Purpose:
** This file implements the cFE Executive Services Exception and Reset Log functions.
**
** References:
** Flight Software Branch C Coding Standard Version 1.0a
** cFE Flight Software Application Developers Guide
**
** Notes:
**
** Modification History:
**
*/
/*
** Required header files.
*/
#include "cfe_es_module_all.h"
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
/*----------------------------------------------------------------
*
* Function: CFE_ES_WriteToERLogWithContext
*
* Application-scope internal function
* See description in header file for argument/return detail
*
*-----------------------------------------------------------------*/
int32 CFE_ES_WriteToERLogWithContext(CFE_ES_LogEntryType_Enum_t EntryType, uint32 ResetType, uint32 ResetSubtype,
const char *Description, CFE_ES_AppId_t AppId, uint32 PspContextId)
{
uint32 LogIdx;
CFE_ES_ERLog_MetaData_t *EntryPtr;
CFE_TIME_SysTime_t PendingTime;
/*
* Snapshot the time before locking (different subsystem)
*/
PendingTime = CFE_TIME_GetTime();
/*
* Ensure that description string is not NULL.
*/
if (Description == NULL)
{
Description = "No Description String Given.";
}
/*
* This routine needs to lock in case it is called
* from concurrent threads
*/
CFE_ES_LockSharedData(__func__, __LINE__);
/*
** Try to clean up an invalid ER log index variable.
*/
if (CFE_ES_Global.ResetDataPtr->ERLogIndex >= CFE_PLATFORM_ES_ER_LOG_ENTRIES)
{
CFE_ES_Global.ResetDataPtr->ERLogIndex = 0;
}
LogIdx = CFE_ES_Global.ResetDataPtr->ERLogIndex;
/*
** Now that the Local Index variable is set, increment the index for the next entry.
*/
CFE_ES_Global.ResetDataPtr->ERLogIndex++;
if (CFE_ES_Global.ResetDataPtr->ERLogIndex >= CFE_PLATFORM_ES_ER_LOG_ENTRIES)
{
CFE_ES_Global.ResetDataPtr->ERLogIndex = 0;
}
/*
** Clear out the log entry we are about to use.
*/
EntryPtr = &CFE_ES_Global.ResetDataPtr->ERLog[LogIdx];
memset(EntryPtr, 0, sizeof(*EntryPtr));
/*
** Fill out the log fields
*/
EntryPtr->BaseInfo.LogEntryType = EntryType;
EntryPtr->BaseInfo.ResetType = ResetType;
EntryPtr->BaseInfo.ResetSubtype = ResetSubtype;
EntryPtr->BaseInfo.BootSource = CFE_ES_Global.ResetDataPtr->ResetVars.BootSource;
EntryPtr->BaseInfo.ProcessorResetCount = CFE_ES_Global.ResetDataPtr->ResetVars.ProcessorResetCount;
EntryPtr->BaseInfo.MaxProcessorResetCount = CFE_ES_Global.ResetDataPtr->ResetVars.MaxProcessorResetCount;
/*
** Copy the ES Reset variables to the log (before they are modified by the log entry).
*/
memcpy(&EntryPtr->BaseInfo.DebugVars, &CFE_ES_Global.DebugVars, sizeof(EntryPtr->BaseInfo.DebugVars));
/*
** Time Stamp the log entry with the system time
*/
EntryPtr->BaseInfo.TimeCode = PendingTime;
/*
** Copy the Description string to the log.
*/
strncpy(EntryPtr->BaseInfo.Description, Description, sizeof(EntryPtr->BaseInfo.Description) - 1);
EntryPtr->BaseInfo.Description[sizeof(EntryPtr->BaseInfo.Description) - 1] = '\0';
/*
* Store the context info (if any)
*/
EntryPtr->AppID = AppId;
EntryPtr->PspContextId = PspContextId;
/*
** Increment the number of ER log entries made
*/
CFE_ES_Global.ResetDataPtr->ERLogEntries++;
/*
* Shared data update is complete
*/
CFE_ES_UnlockSharedData(__func__, __LINE__);
return (CFE_SUCCESS);
}
/*----------------------------------------------------------------
*
* Function: CFE_ES_WriteToERLog
*
* Application-scope internal function
* See description in header file for argument/return detail
*
*-----------------------------------------------------------------*/
int32 CFE_ES_WriteToERLog(CFE_ES_LogEntryType_Enum_t EntryType, uint32 ResetType, uint32 ResetSubtype,
const char *Description)
{
/* passing 0xFFFFFFFF as the appid avoids confusion with actual appid 0 */
return CFE_ES_WriteToERLogWithContext(EntryType, ResetType, ResetSubtype, Description, CFE_ES_APPID_UNDEFINED,
CFE_ES_ERLOG_NO_CONTEXT);
}
/*----------------------------------------------------------------
*
* Function: CFE_ES_BackgroundERLogFileDataGetter
*
* Application-scope internal function
* See description in header file for argument/return detail
*
*-----------------------------------------------------------------*/
bool CFE_ES_BackgroundERLogFileDataGetter(void *Meta, uint32 RecordNum, void **Buffer, size_t *BufSize)
{
CFE_ES_BackgroundLogDumpGlobal_t *BgFilePtr;
CFE_ES_ERLog_FileEntry_t * FileBufferPtr;
CFE_ES_ERLog_MetaData_t * EntryPtr;
int32 PspStatus;
BgFilePtr = (CFE_ES_BackgroundLogDumpGlobal_t *)Meta;
FileBufferPtr = &BgFilePtr->EntryBuffer;
if (RecordNum < CFE_PLATFORM_ES_ER_LOG_ENTRIES)
{
EntryPtr = &CFE_ES_Global.ResetDataPtr->ERLog[RecordNum];
/* First wipe the buffer before re-use */
memset(FileBufferPtr, 0, sizeof(*FileBufferPtr));
CFE_ES_LockSharedData(__func__, __LINE__);
/* The basic info comes directly from the ES log */
FileBufferPtr->BaseInfo = EntryPtr->BaseInfo;
/*
* The context info, if available, comes from the PSP.
* This returns the actual size of the context info, or <0 on error.
*/
PspStatus = CFE_PSP_Exception_CopyContext(EntryPtr->PspContextId, &FileBufferPtr->Context,
sizeof(FileBufferPtr->Context));
if (PspStatus > 0)
{
FileBufferPtr->ContextSize = PspStatus;
}
else
{
/*
* errors here are OK - just means there is no context available.
* Record a size of 0 in the log file.
*/
FileBufferPtr->ContextSize = 0;
}
CFE_ES_UnlockSharedData(__func__, __LINE__);
/*
* Export data to caller for actual write
*/
*Buffer = FileBufferPtr;
*BufSize = sizeof(*FileBufferPtr);
}
else
{
*Buffer = NULL;
*BufSize = 0;
}
/* Check for EOF (last entry) */
return (RecordNum >= (CFE_PLATFORM_ES_ER_LOG_ENTRIES - 1));
}
/*----------------------------------------------------------------
*
* Function: CFE_ES_BackgroundERLogFileEventHandler
*
* Application-scope internal function
* See description in header file for argument/return detail
*
*-----------------------------------------------------------------*/
void CFE_ES_BackgroundERLogFileEventHandler(void *Meta, CFE_FS_FileWriteEvent_t Event, int32 Status, uint32 RecordNum,
size_t BlockSize, size_t Position)
{
CFE_ES_BackgroundLogDumpGlobal_t *BgFilePtr;
BgFilePtr = (CFE_ES_BackgroundLogDumpGlobal_t *)Meta;
/*
* Note that this runs in the context of ES background task (file writer background job)
* It does NOT run in the context of the CFE_TBL app task.
*
* Events should use CFE_EVS_SendEventWithAppID() rather than CFE_EVS_SendEvent()
* to get proper association with TBL task.
*/
switch (Event)
{
case CFE_FS_FileWriteEvent_COMPLETE:
CFE_EVS_SendEvent(CFE_ES_ERLOG2_EID, CFE_EVS_EventType_DEBUG, "%s written:Size=%lu",
BgFilePtr->FileWrite.FileName, (unsigned long)Position);
break;
case CFE_FS_FileWriteEvent_HEADER_WRITE_ERROR:
case CFE_FS_FileWriteEvent_RECORD_WRITE_ERROR:
CFE_EVS_SendEvent(CFE_ES_FILEWRITE_ERR_EID, CFE_EVS_EventType_ERROR,
"File write,byte cnt err,file %s,request=%u,actual=%u", BgFilePtr->FileWrite.FileName,
(int)BlockSize, (int)Status);
break;
case CFE_FS_FileWriteEvent_CREATE_ERROR:
CFE_EVS_SendEvent(CFE_ES_ERLOG2_ERR_EID, CFE_EVS_EventType_ERROR, "Error creating file %s, RC = %d",
BgFilePtr->FileWrite.FileName, (int)Status);
break;
default:
/* unhandled event - ignore */
break;
}
}
/*----------------------------------------------------------------
*
* Function: CFE_ES_RunExceptionScan
*
* Application-scope internal function
* See description in header file for argument/return detail
*
*-----------------------------------------------------------------*/
bool CFE_ES_RunExceptionScan(uint32 ElapsedTime, void *Arg)
{
int32 Status;
uint32 PspContextId;
char ReasonString[CFE_ES_ERLOG_DESCRIPTION_MAX_LENGTH];
CFE_ES_TaskInfo_t EsTaskInfo;
osal_id_t ExceptionTaskID;
uint32 ResetType;
CFE_ES_LogEntryType_Enum_t LogType;
CFE_ES_AppRecord_t * AppRecPtr;
if (CFE_PSP_Exception_GetCount() == 0)
{
/* no exceptions pending, nothing to do */
return false;
}
/*
* Note a reset type of 0 is not defined by the PSP -
* the real values are all nonzero
*/
ResetType = 0;
memset(&EsTaskInfo, 0, sizeof(EsTaskInfo));
Status = CFE_PSP_Exception_GetSummary(&PspContextId, &ExceptionTaskID, ReasonString, sizeof(ReasonString));
if (Status != CFE_PSP_SUCCESS)
{
/* reason string is not available - populate with something for the log */
snprintf(ReasonString, sizeof(ReasonString), "Unknown - CFE_PSP_ExceptionGetSummary() error %ld", (long)Status);
PspContextId = 0;
ExceptionTaskID = OS_OBJECT_ID_UNDEFINED;
} /* end if */
/*
* Note that writes to the ES ER log actually do not get propagated to the debug console.
* so by writing to SysLog here it becomes visible in both places.
*/
CFE_ES_WriteToSysLog("ExceptionID 0x%lx in TaskID %lu: %s\n", (unsigned long)PspContextId,
OS_ObjectIdToInteger(ExceptionTaskID), ReasonString);
/*
* If task ID is 0, this means it was a system level exception and
* not associated with a specific task.
*
* Otherwise, if it was related to a task, determine the associated AppID
* so the exception action can be checked.
*
* NOTE: the default exception handling is to restart the processor/system.
* There is an option to only restart the specific app needs, but this must
* be "opt-in", that is, the app was created initially with this option, and
* the exception is also traced back to that app. If either is not possible
* for whatever reason then the restart action (default) should be taken, as
* this gets the highest assurance that the system will be returned to a coherent
* state.
*/
if (OS_ObjectIdDefined(ExceptionTaskID))
{
Status = CFE_ES_GetTaskInfo(&EsTaskInfo, CFE_ES_TaskId_FromOSAL(ExceptionTaskID));
/*
* The App ID was found, now see if the ExceptionAction is set for a reset
*
* NOTE: if anything in this logic fails and the app which caused the exception is not
* postively identified, then this will just follow the default case of PSP reset.
*/
if (Status == CFE_SUCCESS)
{
AppRecPtr = CFE_ES_LocateAppRecordByID(EsTaskInfo.AppId);
CFE_ES_LockSharedData(__func__, __LINE__);
if (CFE_ES_AppRecordIsMatch(AppRecPtr, EsTaskInfo.AppId) &&
AppRecPtr->StartParams.ExceptionAction == CFE_ES_ExceptionAction_RESTART_APP)
{
/*
* Log the Application reset
*/
ResetType = CFE_ES_APP_RESTART;
}
CFE_ES_UnlockSharedData(__func__, __LINE__);
}
}
do
{
/*
* If no disposition is identified yet, then trigger a PSP reset.
* Need to determine if a processor or poweron reset is needed.
*/
if (ResetType == 0)
{
if (CFE_ES_Global.ResetDataPtr->ResetVars.ProcessorResetCount >=
CFE_ES_Global.ResetDataPtr->ResetVars.MaxProcessorResetCount)
{
CFE_ES_WriteToSysLog("Maximum Processor Reset count reached (%u)",
(unsigned int)CFE_ES_Global.ResetDataPtr->ResetVars.MaxProcessorResetCount);
ResetType = CFE_PSP_RST_TYPE_POWERON;
}
else
{
CFE_ES_WriteToSysLog("Processor Reset count not reached (%u/%u)",
(unsigned int)CFE_ES_Global.ResetDataPtr->ResetVars.ProcessorResetCount,
(unsigned int)CFE_ES_Global.ResetDataPtr->ResetVars.MaxProcessorResetCount);
/*
** Update the reset variables
*/
CFE_ES_Global.ResetDataPtr->ResetVars.ProcessorResetCount++;
CFE_ES_Global.ResetDataPtr->ResetVars.ES_CausedReset = true;
ResetType = CFE_PSP_RST_TYPE_PROCESSOR;
}
}
if (ResetType == CFE_ES_APP_RESTART)
{
LogType = CFE_ES_LogEntryType_APPLICATION;
}
else
{
LogType = CFE_ES_LogEntryType_CORE;
}
CFE_ES_WriteToERLogWithContext(LogType, ResetType, CFE_PSP_RST_SUBTYPE_EXCEPTION, ReasonString,
EsTaskInfo.AppId, PspContextId);
if (ResetType == CFE_ES_APP_RESTART)
{
/*
* Restart the App. This call is just a request
* to ES, but the request could fail. If that happens,
* proceed to a processor reset.
*/
Status = CFE_ES_RestartApp(EsTaskInfo.AppId);
if (Status != CFE_SUCCESS)
{
ResetType = 0;
snprintf(ReasonString, sizeof(ReasonString), "App Restart Failed");
}
}
else
{
/* normally this will not return */
CFE_PSP_Restart(ResetType);
}
} while (ResetType == 0);
return true; /* returning true because there was an exception to deal with */
}