28 static uint32_t _logLineID = 0;
31 static int _lhLogBufIdx = 0;
33 #define _UNINITIALIZED 0xFFFFFFFF
35 static uint32_t _flashIdxCur;
36 static uint32_t _flashIdxOff;
37 static uint32_t _flashId;
38 static uint32_t _flashIdxIt = _UNINITIALIZED;
40 #define LH_ENTRY_LEN 128
41 #define LH_ENTRY_HDR 16
42 #define LH_LINE_LEN ( LH_ENTRY_LEN - LH_ENTRY_HDR )
48 #define SIZE_IN_ENTRIES ( LOGGING_SIZE / sizeof(LogEntry) )
50 #define BLOCK_ENTRIES ( BLOCK_BYTES / sizeof(LogEntry))
53 #define MAX_ITERATIONS (int)(__builtin_log2(SIZE_IN_ENTRIES)+2)
55 #define GET_ADDR(IDX) (IDX * sizeof(LogEntry) + LOGGING_OFFSET)
56 #define GET_NEXT(IDX) ((IDX + 1) % SIZE_IN_ENTRIES)
59 static bool _lhFlashInitialized =
false;
67 char line[LH_LINE_LEN];
72 static bool loadEntry(
LogEntry * entry,
int idx,
bool hdrOnly)
74 idx = idx % SIZE_IN_ENTRIES;
75 uint32_t addr = GET_ADDR(idx);
79 static bool getId(
int idx,
int *
id)
82 if (!loadEntry(&entry, idx,
true))
return false;
84 if (entry.magic == MAGIC) *
id = entry.id;
91 static inline bool less_than(uint32_t id1, uint32_t id2) {
92 return ( (id1 - id2) & 0x80000000);
96 bool lhFlashFormat() {
99 for (uint32_t addr = LOGGING_OFFSET; addr < LOGGING_OFFSET + LOGGING_SIZE; addr += BLOCK_BYTES)
112 _lhFlashInitialized =
false;
115 int maxIdx = SIZE_IN_ENTRIES - 1;
116 int pivotId, pivotNextId;
118 int maxIts = MAX_ITERATIONS;
123 if (!loadEntry(&le, 0,
true))
return false;
125 if (le.magic == MAGIC)
129 }
else if (le.magic != 0xFFFF) {
130 logWarn(
"Persistent logging memory invalid. Formatting...");
131 if (!lhFlashFormat()) {
135 logInfo(
"Persistent logging did not find any information written yet");
151 int pivotIdx = ( minIdx + maxIdx ) >> 1;
153 if (!getId(pivotIdx, &pivotId))
return false;
156 if (pivotId == -1 || less_than(pivotId, offId))
168 if (!getId(pivotIdx + 1, &pivotNextId))
return false;
171 if (less_than(pivotNextId, pivotId))
174 _flashIdxCur = GET_NEXT(pivotIdx);
187 logWarn(
"Persistent logging memory fragmented. Formatting...");
188 if (!lhFlashFormat())
return false;
198 _flashIdxOff = ((_flashIdxCur + BLOCK_ENTRIES - 1) / BLOCK_ENTRIES) * BLOCK_ENTRIES;
200 if (!getId(_flashIdxOff,&offId))
return false;
201 if (offId == -1) _flashIdxOff = 0;
203 logInfo(
"Persistent logging initiated: curIdx = %d, offIdx = %d, lastId = %d",
204 _flashIdxCur, _flashIdxOff, _flashId);
207 _flashId = ( _flashId + 1 ) & 0x7FFFFFFF;
208 _lhFlashInitialized =
true;
216 uint32_t lines = _logLineID - lastId;
235 int avail = (_flashIdxCur - _flashIdxOff + SIZE_IN_ENTRIES) % SIZE_IN_ENTRIES;
238 _flashIdxIt = _UNINITIALIZED;
242 if (count == 0 || count > avail) count = avail;
244 _flashIdxIt = (_flashIdxCur - count + SIZE_IN_ENTRIES) % SIZE_IN_ENTRIES;
252 if (_flashIdxIt == _UNINITIALIZED)
return false;
255 if (!loadEntry(&le, _flashIdxIt,
false))
return false;
258 int len = strlen(le.line);
259 if (len + 1 > bufSize) len = bufSize - 1;
261 memcpy(bufPtr, le.line, len);
264 _flashIdxIt = GET_NEXT(_flashIdxIt);
265 if (_flashIdxIt == _flashIdxCur) _flashIdxIt = _UNINITIALIZED;
271 static void lhStoreInFlash(
LogLevel level,
char * logOut)
277 if (_flashIdxCur == _flashIdxOff)
282 _flashIdxOff = (_flashIdxOff + BLOCK_ENTRIES ) % SIZE_IN_ENTRIES;
285 uint32_t addr = GET_ADDR(_flashIdxCur);
286 if ((addr % BLOCK_BYTES) == 0)
289 _lhFlashInitialized =
false;
301 strncpy(entry.line, logOut, LH_LINE_LEN);
302 entry.line[LH_LINE_LEN - 1] =
'\0';
306 _lhFlashInitialized =
false;
307 logError(
"Failed to store logging in flash");
312 _flashIdxCur = GET_NEXT(_flashIdxCur);
313 _flashId = ( _flashId + 1 ) & 0x7FFFFFFF;
332 int p = ( _lhLogBufIdx - idx ) - 1;
char * lhGetLine(int idx)
Returns a line from the in memory log, where index 0 is the last logged line.
Defines the configuration of the LM32 SOC for the CLBv2.
#define LH_BUFFER_WIDTH
Maximum width of the in memory log lines.
bool lhFlashInit()
Initializes the flash storage (may take a while).
Low level routines for LM32, including interrupt handling.
bool lhFlashItNext(char *bufPtr, int bufSize)
Get the next element.
#define LH_BUFFER_LENGTH
Maximum number of entries stored in memory.
void lhStore(LogLevel level, char *msg)
Stores a line in the buffer, and in flash if activated.
uint32_t lhGetLineById(uint32_t lastId, char **logLinePtr)
Returns the last log-line based on log-line ID.
#define E_INVSTATE
Generic error: Module is in a state in which.
bool lhEnableFlashWrite
Boolean to enable to disable the writing of logging to the flash.
#define logWarn(MSG,...)
Format a log message with warning level.
static bool errCondRebase(bool err, const char *name)
Transparent conditional error rebase.
Manages the global system error.
bool sfErase(uint32_t address)
Erase a sector in flash.
Info, general information.
void errPrint(bool clear)
Prints the last error.
bool lhFlashItStart(int count)
Start the iteration through the flash entries.
#define logError(MSG,...)
Format a log message with fatal level.
#define LOG_DEF(NAME,...)
Define a logger for a module.
bool sfRead(uint32_t address, uint8_t *data, uint32_t count)
Read from a specific address in flash.
bool errSet(uint32_t code, const char *error, const char *name)
Sets an error.
This driver implements access to the Serial Flash.
Implements a generic logger facility.
#define logInfo(MSG,...)
Write a log message with formatting on info level.
bool sfProg(uint32_t address, uint8_t *data, uint32_t count)
Program an page in flash.