• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2018, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file implements the OpenThread platform abstraction for logging.
32  */
33 
34 #include <openthread-core-config.h>
35 #include <openthread/config.h>
36 
37 #include <utils/code_utils.h>
38 #include <openthread/platform/alarm-milli.h>
39 #include <openthread/platform/logging.h>
40 
41 #include "SEGGER_RTT.h"
42 #include "logging_rtt.h"
43 
44 #if (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED)
45 #if (LOG_RTT_COLOR_ENABLE == 1)
46 #define RTT_COLOR_CODE_DEFAULT "\x1B[0m"
47 #define RTT_COLOR_CODE_RED "\x1B[1;31m"
48 #define RTT_COLOR_CODE_GREEN "\x1B[1;32m"
49 #define RTT_COLOR_CODE_YELLOW "\x1B[1;33m"
50 #define RTT_COLOR_CODE_CYAN "\x1B[1;36m"
51 #else // LOG_RTT_COLOR_ENABLE == 1
52 #define RTT_COLOR_CODE_DEFAULT ""
53 #define RTT_COLOR_CODE_RED ""
54 #define RTT_COLOR_CODE_GREEN ""
55 #define RTT_COLOR_CODE_YELLOW ""
56 #define RTT_COLOR_CODE_CYAN ""
57 #endif // LOG_RTT_COLOR_ENABLE == 1
58 
59 static bool sLogInitialized = false;
60 
61 #if LOG_RTT_BUFFER_INDEX != 0
62 static uint8_t sLogBuffer[LOG_RTT_BUFFER_SIZE];
63 #endif
64 
65 /**
66  * Function for getting color of a given level log.
67  *
68  * @param[in]  aLogLevel The log level.
69  *
70  * @returns  String with a log level color value.
71  */
levelToString(otLogLevel aLogLevel)72 static inline const char *levelToString(otLogLevel aLogLevel)
73 {
74     switch (aLogLevel)
75     {
76     case OT_LOG_LEVEL_CRIT:
77         return RTT_COLOR_CODE_RED;
78 
79     case OT_LOG_LEVEL_WARN:
80         return RTT_COLOR_CODE_YELLOW;
81 
82     case OT_LOG_LEVEL_INFO:
83         return RTT_COLOR_CODE_GREEN;
84 
85     case OT_LOG_LEVEL_DEBG:
86     default:
87         return RTT_COLOR_CODE_DEFAULT;
88     }
89 }
90 
91 #if (LOG_TIMESTAMP_ENABLE == 1)
92 /**
93  * Function for printing actual timestamp.
94  *
95  * @param[in,out]  aLogString Pointer to the log buffer.
96  * @param[in]      aMaxSize   Maximum size of the log buffer.
97  *
98  * @returns  Number of bytes successfully written to the log buffer.
99  */
logTimestamp(char * aLogString,uint16_t aMaxSize)100 static inline int logTimestamp(char *aLogString, uint16_t aMaxSize)
101 {
102     long unsigned int now = otPlatAlarmMilliGetNow();
103     return snprintf(aLogString, (size_t)aMaxSize, "%s[%010lu]", RTT_COLOR_CODE_CYAN, now);
104 }
105 #endif
106 
107 /**
108  * Function for printing log level.
109  *
110  * @param[in,out]  aLogString  Pointer to log buffer.
111  * @param[in]      aMaxSize    Maximum size of log buffer.
112  * @param[in]      aLogLevel   Log level.
113  *
114  * @returns  Number of bytes successfully written to the log buffer.
115  */
logLevel(char * aLogString,uint16_t aMaxSize,otLogLevel aLogLevel)116 static inline int logLevel(char *aLogString, uint16_t aMaxSize, otLogLevel aLogLevel)
117 {
118     return snprintf(aLogString, (size_t)aMaxSize, "%s ", levelToString(aLogLevel));
119 }
120 
utilsLogRttInit(void)121 void utilsLogRttInit(void)
122 {
123 #if LOG_RTT_BUFFER_INDEX != 0
124     int res = SEGGER_RTT_ConfigUpBuffer(LOG_RTT_BUFFER_INDEX, LOG_RTT_BUFFER_NAME, sLogBuffer, LOG_RTT_BUFFER_SIZE,
125                                         SEGGER_RTT_MODE_NO_BLOCK_TRIM);
126 #else
127     int res = SEGGER_RTT_SetFlagsUpBuffer(LOG_RTT_BUFFER_INDEX, SEGGER_RTT_MODE_NO_BLOCK_TRIM);
128 #endif
129 
130     otEXPECT(res >= 0);
131 
132     sLogInitialized = true;
133 
134 exit:
135     return;
136 }
137 
utilsLogRttDeinit(void)138 void utilsLogRttDeinit(void) { sLogInitialized = false; }
139 
utilsLogRttOutput(otLogLevel aLogLevel,otLogRegion aLogRegion,const char * aFormat,va_list ap)140 void utilsLogRttOutput(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, va_list ap)
141 {
142     (void)aLogRegion;
143 
144     uint16_t length = 0;
145     int      charsWritten;
146     char     logString[LOG_PARSE_BUFFER_SIZE + 1];
147 
148     otEXPECT(sLogInitialized == true);
149 
150 #if (LOG_TIMESTAMP_ENABLE == 1)
151     length += logTimestamp(logString, LOG_PARSE_BUFFER_SIZE);
152 #endif
153 
154     // Add level information.
155     length += logLevel(&logString[length], (LOG_PARSE_BUFFER_SIZE - length), aLogLevel);
156 
157     charsWritten = vsnprintf(&logString[length], (size_t)(LOG_PARSE_BUFFER_SIZE - length), aFormat, ap);
158     otEXPECT(charsWritten >= 0);
159     length += charsWritten;
160 
161     if (length > LOG_PARSE_BUFFER_SIZE)
162     {
163         length = LOG_PARSE_BUFFER_SIZE;
164     }
165 
166     logString[length++] = '\n';
167 
168     // Write user log to the RTT memory block.
169     SEGGER_RTT_WriteNoLock(LOG_RTT_BUFFER_INDEX, logString, length);
170 
171 exit:
172     return;
173 }
174 #endif // (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED)
175