1 /* See Project CHIP LICENSE file for licensing information. */
2 #include <platform/logging/LogV.h>
4 #include <core/CHIPConfig.h>
5 #include <platform/CHIPDeviceConfig.h>
7 #include <support/SafeString.h>
8 #include <support/logging/CHIPLogging.h>
10 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
11 #include <openthread/platform/logging.h>
16 #include <retargetserial.h>
22 #include "PigweedLogger.h"
25 // RTT Buffer size and name
26 #ifndef LOG_RTT_BUFFER_INDEX
27 #define LOG_RTT_BUFFER_INDEX 0
31 * @def LOG_RTT_BUFFER_NAME
33 * RTT's name. Only used if LOG_RTT_BUFFER_INDEX is not 0. Otherwise,
34 * the buffer name is fixed to "Terminal".
37 #ifndef LOG_RTT_BUFFER_NAME
38 #define LOG_RTT_BUFFER_NAME "Terminal"
42 * @def LOG_RTT_BUFFER_SIZE
44 * LOG RTT's buffer size. Only used if LOG_RTT_BUFFER_INDEX is not 0. To
45 * configure buffer #0 size, check the BUFFER_SIZE_UP definition in
49 #ifndef LOG_RTT_BUFFER_SIZE
50 #define LOG_RTT_BUFFER_SIZE 256
54 #include "SEGGER_RTT.h"
55 #include "SEGGER_RTT_Conf.h"
57 #define LOG_ERROR "<error > "
58 #define LOG_WARN "<warn > "
59 #define LOG_INFO "<info > "
60 #define LOG_DETAIL "<detail> "
61 #define LOG_LWIP "<lwip > "
62 #define LOG_EFR32 "<efr32 > "
63 // If a new category string LOG_* is created, add it in the MaxStringLength arguments below
64 static constexpr size_t kMaxCategoryStrLen = chip::MaxStringLength(LOG_ERROR, LOG_WARN, LOG_INFO, LOG_DETAIL, LOG_LWIP, LOG_EFR32);
67 static bool sLogInitialized = false;
69 #if LOG_RTT_BUFFER_INDEX != 0
70 static uint8_t sLogBuffer[LOG_RTT_BUFFER_SIZE];
71 static uint8_t sCmdLineBuffer[LOG_RTT_BUFFER_SIZE];
76 * Print a log message to RTT
78 static void PrintLog(const char * msg)
84 SEGGER_RTT_WriteNoLock(LOG_RTT_BUFFER_INDEX, msg, sz);
86 PigweedLogger::putString(msg, sz);
89 const char * newline = "\r\n";
91 SEGGER_RTT_WriteNoLock(LOG_RTT_BUFFER_INDEX, newline, sz);
93 PigweedLogger::putString(newline, sz);
97 #endif // EFR32_LOG_ENABLED
100 * Initialize Segger RTT for logging
102 extern "C" void efr32LogInit(void)
104 #if EFR32_LOG_ENABLED
105 #if LOG_RTT_BUFFER_INDEX != 0
106 SEGGER_RTT_ConfigUpBuffer(LOG_RTT_BUFFER_INDEX, LOG_RTT_BUFFER_NAME, sLogBuffer, LOG_RTT_BUFFER_SIZE,
107 SEGGER_RTT_MODE_NO_BLOCK_TRIM);
109 SEGGER_RTT_ConfigDownBuffer(LOG_RTT_BUFFER_INDEX, LOG_RTT_BUFFER_NAME, sCmdLineBuffer, LOG_RTT_BUFFER_SIZE,
110 SEGGER_RTT_MODE_NO_BLOCK_SKIP);
112 SEGGER_RTT_SetFlagsUpBuffer(LOG_RTT_BUFFER_INDEX, SEGGER_RTT_MODE_NO_BLOCK_TRIM);
115 #ifdef PW_RPC_ENABLED
116 PigweedLogger::init();
118 sLogInitialized = true;
119 #endif // EFR32_LOG_ENABLED
123 * General-purpose logging function
125 extern "C" void efr32Log(const char * aFormat, ...)
129 va_start(v, aFormat);
130 #if EFR32_LOG_ENABLED
131 char formattedMsg[CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE];
132 static_assert(sizeof(formattedMsg) > kMaxCategoryStrLen); // Greater than to at least accommodate a ending Null Character
134 strcpy(formattedMsg, LOG_EFR32);
135 size_t prefixLen = strlen(formattedMsg);
136 size_t len = vsnprintf(formattedMsg + prefixLen, sizeof formattedMsg - prefixLen, aFormat, v);
138 if (len >= sizeof formattedMsg - prefixLen)
140 formattedMsg[sizeof formattedMsg - 1] = '\0';
143 PrintLog(formattedMsg);
144 #endif // EFR32_LOG_ENABLED
150 namespace DeviceLayer {
153 * Called whenever a log message is emitted by Chip or LwIP.
155 * This function is intended be overridden by the application to, e.g.,
156 * schedule output of queued log entries.
158 void __attribute__((weak)) OnLogOutput(void) {}
160 } // namespace DeviceLayer
168 * CHIP log output functions.
170 void LogV(const char * module, uint8_t category, const char * aFormat, va_list v)
172 #if EFR32_LOG_ENABLED && _CHIP_USE_LOGGING
173 if (IsCategoryEnabled(category))
175 char formattedMsg[CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE];
176 size_t formattedMsgLen;
178 // len for Category string + "[" + Module name + "] " (Brackets and space =3)
179 constexpr size_t maxPrefixLen = kMaxCategoryStrLen + chip::Logging::kMaxModuleNameLen + 3;
180 static_assert(sizeof(formattedMsg) > maxPrefixLen); // Greater than to at least accommodate a ending Null Character
184 case kLogCategory_Error:
185 strcpy(formattedMsg, LOG_ERROR);
187 case kLogCategory_Progress:
189 strcpy(formattedMsg, LOG_INFO);
191 case kLogCategory_Detail:
192 strcpy(formattedMsg, LOG_DETAIL);
196 formattedMsgLen = strlen(formattedMsg);
198 // Form the log prefix, e.g. "[DL] "
199 snprintf(formattedMsg + formattedMsgLen, sizeof(formattedMsg) - formattedMsgLen, "[%s] ", module);
200 formattedMsg[sizeof(formattedMsg) - 1] = 0;
201 formattedMsgLen = strlen(formattedMsg);
203 size_t len = vsnprintf(formattedMsg + formattedMsgLen, sizeof formattedMsg - formattedMsgLen, aFormat, v);
205 if (len >= sizeof formattedMsg - formattedMsgLen)
207 formattedMsg[sizeof formattedMsg - 1] = '\0';
210 PrintLog(formattedMsg);
213 // Let the application know that a log message has been emitted.
214 chip::DeviceLayer::OnLogOutput();
215 #endif // EFR32_LOG_ENABLED && _CHIP_USE_LOGGING
218 } // namespace Platform
219 } // namespace Logging
223 * LwIP log output function.
225 extern "C" void LwIPLog(const char * aFormat, ...)
229 va_start(v, aFormat);
230 #if EFR32_LOG_ENABLED
231 char formattedMsg[CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE];
233 strcpy(formattedMsg, LOG_LWIP);
234 size_t prefixLen = strlen(formattedMsg);
235 size_t len = vsnprintf(formattedMsg + prefixLen, sizeof formattedMsg - prefixLen, aFormat, v);
237 if (len >= sizeof formattedMsg - prefixLen)
239 formattedMsg[sizeof formattedMsg - 1] = '\0';
242 PrintLog(formattedMsg);
244 #if configCHECK_FOR_STACK_OVERFLOW
245 // Force a stack overflow check.
246 if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
250 // Let the application know that a log message has been emitted.
251 chip::DeviceLayer::OnLogOutput();
252 #endif // EFR32_LOG_ENABLED
257 * Platform logging function for OpenThread
259 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
260 extern "C" void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char * aFormat, ...)
265 va_start(v, aFormat);
266 #if EFR32_LOG_ENABLED
267 char formattedMsg[CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE];
273 case OT_LOG_LEVEL_CRIT:
274 strcpy(formattedMsg, LOG_ERROR "[ot] ");
276 case OT_LOG_LEVEL_WARN:
277 strcpy(formattedMsg, LOG_WARN "[ot] ");
279 case OT_LOG_LEVEL_NOTE:
280 strcpy(formattedMsg, LOG_INFO "[ot] ");
282 case OT_LOG_LEVEL_INFO:
283 strcpy(formattedMsg, LOG_INFO "[ot] ");
285 case OT_LOG_LEVEL_DEBG:
286 strcpy(formattedMsg, LOG_DETAIL "[ot] ");
289 strcpy(formattedMsg, LOG_DETAIL "[ot] ");
293 size_t prefixLen = strlen(formattedMsg);
294 size_t len = vsnprintf(formattedMsg + prefixLen, sizeof(formattedMsg) - prefixLen, aFormat, v);
296 if (len >= sizeof formattedMsg - prefixLen)
298 formattedMsg[sizeof formattedMsg - 1] = '\0';
301 PrintLog(formattedMsg);
303 #if configCHECK_FOR_STACK_OVERFLOW
304 // Force a stack overflow check.
305 if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
310 // Let the application know that a log message has been emitted.
311 chip::DeviceLayer::OnLogOutput();
312 #endif // EFR32_LOG_ENABLED
315 #endif // CHIP_ENABLE_OPENTHREAD
317 #if HARD_FAULT_LOG_ENABLE && EFR32_LOG_ENABLED
320 * Log register contents to UART when a hard fault occurs.
322 extern "C" void debugHardfault(uint32_t * sp)
324 uint32_t cfsr = SCB->CFSR;
325 uint32_t hfsr = SCB->HFSR;
326 uint32_t mmfar = SCB->MMFAR;
327 uint32_t bfar = SCB->BFAR;
332 uint32_t r12 = sp[4];
335 uint32_t psr = sp[7];
336 char formattedMsg[32];
338 if (sLogInitialized == false)
343 snprintf(formattedMsg, sizeof formattedMsg, LOG_ERROR "HardFault:\n");
344 PrintLog(formattedMsg);
345 snprintf(formattedMsg, sizeof formattedMsg, "SCB->CFSR 0x%08lx", cfsr);
346 PrintLog(formattedMsg);
347 snprintf(formattedMsg, sizeof formattedMsg, "SCB->HFSR 0x%08lx", hfsr);
348 PrintLog(formattedMsg);
349 snprintf(formattedMsg, sizeof formattedMsg, "SCB->MMFAR 0x%08lx", mmfar);
350 PrintLog(formattedMsg);
351 snprintf(formattedMsg, sizeof formattedMsg, "SCB->BFAR 0x%08lx", bfar);
352 PrintLog(formattedMsg);
353 snprintf(formattedMsg, sizeof formattedMsg, "SP 0x%08lx", (uint32_t) sp);
354 PrintLog(formattedMsg);
355 snprintf(formattedMsg, sizeof formattedMsg, "R0 0x%08lx\n", r0);
356 PrintLog(formattedMsg);
357 snprintf(formattedMsg, sizeof formattedMsg, "R1 0x%08lx\n", r1);
358 PrintLog(formattedMsg);
359 snprintf(formattedMsg, sizeof formattedMsg, "R2 0x%08lx\n", r2);
360 PrintLog(formattedMsg);
361 snprintf(formattedMsg, sizeof formattedMsg, "R3 0x%08lx\n", r3);
362 PrintLog(formattedMsg);
363 snprintf(formattedMsg, sizeof formattedMsg, "R12 0x%08lx\n", r12);
364 PrintLog(formattedMsg);
365 snprintf(formattedMsg, sizeof formattedMsg, "LR 0x%08lx\n", lr);
366 PrintLog(formattedMsg);
367 snprintf(formattedMsg, sizeof formattedMsg, "PC 0x%08lx\n", pc);
368 PrintLog(formattedMsg);
369 snprintf(formattedMsg, sizeof formattedMsg, "PSR 0x%08lx\n", psr);
370 PrintLog(formattedMsg);
377 * Override default hard-fault handler
379 extern "C" __attribute__((naked)) void HardFault_Handler(void)
381 __asm volatile("tst lr, #4 \n"
385 "ldr r1, debugHardfault_address \n"
387 "debugHardfault_address: .word debugHardfault \n");
390 #endif // HARD_FAULT_LOG_ENABLE && EFR32_LOG_ENABLED