1 /* USER CODE BEGIN Header */
2 /**
3 ******************************************************************************
4 * @file log_module.c
5 * @author MCD Application Team
6 * @brief Source file of the log module.
7 ******************************************************************************
8 * @attention
9 *
10 * Copyright (c) 2024 STMicroelectronics.
11 * All rights reserved.
12 *
13 * This software is licensed under terms that can be found in the LICENSE file
14 * in the root directory of this software component.
15 * If no LICENSE file comes with this software, it is provided AS-IS.
16 *
17 ******************************************************************************
18 */
19 /* USER CODE END Header */
20
21 /* Includes ------------------------------------------------------------------*/
22 #include <stdio.h> /* vsnprintf */
23
24 #include "log_module.h"
25 #include "stm32_adv_trace.h"
26 #include "utilities_conf.h"
27
28 /* Private includes ----------------------------------------------------------*/
29 /* USER CODE BEGIN Includes */
30
31 /* USER CODE END Includes */
32
33 /* Private typedef -----------------------------------------------------------*/
34 /* USER CODE BEGIN PTD */
35
36 /* USER CODE END PTD */
37
38 /* Private define ------------------------------------------------------------*/
39 /* Definition of 'End Of Line' */
40 #define ENDOFLINE_SIZE (0x01u)
41 #define ENDOFLINE_CHAR '\n'
42 /* USER CODE BEGIN PD */
43
44 /* USER CODE END PD */
45
46 /* Private macro -------------------------------------------------------------*/
47 /* USER CODE BEGIN PM */
48
49 /* USER CODE END PM */
50
51 /* Exported constants --------------------------------------------------------*/
52 /* Global const struct variables to make the life of the user easier */
53 const Log_Module_t LOG_MODULE_DEFAULT_CONFIGURATION =
54 {
55 .verbose_level = LOG_VERBOSE_ERROR,
56 .region_mask = (LOG_REGION_ALL_REGIONS)
57 };
58
59 const Log_Verbose_Level_t LOG_VERBOSE_DEFAULT = LOG_VERBOSE_ERROR;
60 const Log_Region_t LOG_REGION_MASK_DEFAULT = LOG_REGION_ALL_REGIONS;
61 const Log_Color_t LOG_COLOR_DEFAULT_CONFIGURATION[] =
62 {
63 LOG_COLOR_CODE_DEFAULT, // For Region BLE
64 LOG_COLOR_CODE_DEFAULT, // For Region System
65 LOG_COLOR_CODE_DEFAULT, // For Region APP
66 LOG_COLOR_CODE_RED, // For Region LinkLayer
67 LOG_COLOR_CODE_YELLOW, // For Region MAC
68 LOG_COLOR_CODE_GREEN, // For Region Zigbee
69 LOG_COLOR_CODE_GREEN, // For Region Thread
70 LOG_COLOR_CODE_DEFAULT, // For Region RTOS
71 /* USER CODE BEGIN LOG_COLOR_DEFAULT_CONFIGURATION */
72
73 /* USER CODE END LOG_COLOR_DEFAULT_CONFIGURATION */
74 };
75 /* USER CODE BEGIN EC */
76
77 /* USER CODE END EC */
78
79 /* Private variables ---------------------------------------------------------*/
80 static uint32_t current_region_mask;
81 static Log_Verbose_Level_t current_verbose_level;
82 static Log_Color_t current_color_list[32];
83 CallBack_TimeStamp * log_timestamp_function;
84 /* USER CODE BEGIN PV */
85
86 /* USER CODE END PV */
87
88 /* Private function prototypes -----------------------------------------------*/
89 static uint32_t Get_Region_Mask(Log_Region_t Region);
90
91 #if (LOG_INSERT_COLOR_INSIDE_THE_TRACE != 0)
92 static uint16_t RegionToColor(char * TextBuffer, uint16_t SizeMax, Log_Region_t Region);
93 #endif /* LOG_INSERT_COLOR_INSIDE_THE_TRACE != 0 */
94 /* USER CODE BEGIN PFP */
95
96 /* USER CODE END PFP */
97
98 /* Functions Definition ------------------------------------------------------*/
99 #if (LOG_INSERT_COLOR_INSIDE_THE_TRACE != 0)
100 /**
101 * @brief Add the color (in function of Region) on the start of Log sentence.
102 *
103 * @param TextBuffer Pointer on the log buffer
104 * @param SizeMax The maximum number of bytes that will be written to the buffer.
105 * @param Region Region of the log to apply its corresponding color.
106 *
107 * @return Length of the new Log.
108 */
RegionToColor(char * TextBuffer,uint16_t SizeMax,Log_Region_t Region)109 static uint16_t RegionToColor(char * TextBuffer, uint16_t SizeMax, Log_Region_t Region)
110 {
111 uint16_t text_length = 0;
112 Log_Color_t color;
113 static Log_Color_t previous_color = LOG_COLOR_NONE;
114
115 if (Region != LOG_MODULE_ALL_REGION_MASK)
116 {
117 color = current_color_list[Region];
118 }
119 else
120 {
121 color = LOG_COLOR_CODE_DEFAULT;
122 }
123
124 /* Insert Color code only if previous is not the same */
125 if (color != previous_color)
126 {
127 if (color == LOG_COLOR_CODE_DEFAULT)
128 {
129 snprintf(TextBuffer, SizeMax, "\x1b[0m");
130 }
131 else
132 {
133 snprintf(TextBuffer, SizeMax, "\x1b[0;%02dm", color);
134 }
135
136 previous_color = color;
137 text_length = strlen(TextBuffer);
138 }
139
140 return text_length;
141 }
142 #endif /* LOG_INSERT_COLOR_INSIDE_THE_TRACE != 0 */
143
Log_Module_PrintWithArg(Log_Verbose_Level_t VerboseLevel,Log_Region_t Region,const char * Text,va_list Args)144 void Log_Module_PrintWithArg(Log_Verbose_Level_t VerboseLevel, Log_Region_t Region, const char * Text, va_list Args)
145 {
146 uint16_t tmp_size = 0;
147 uint16_t buffer_size = 0;
148 char full_text[UTIL_ADV_TRACE_TMP_BUF_SIZE + 1u];
149
150 /* USER CODE BEGIN Log_Module_PrintWithArg_1 */
151
152 /* USER CODE END Log_Module_PrintWithArg_1 */
153
154 /* If the verbose level of the given log is not enabled, then we do not print the log */
155 if (VerboseLevel > current_verbose_level)
156 {
157 return;
158 }
159
160 /* If the region for the given log is not enabled, then we do not print the log */
161 if ((Get_Region_Mask(Region) & current_region_mask) == 0u)
162 {
163 return;
164 }
165
166 #if (LOG_INSERT_COLOR_INSIDE_THE_TRACE != 0)
167 /* Add to full_text the color matching the region */
168 tmp_size = RegionToColor(&full_text[buffer_size], (UTIL_ADV_TRACE_TMP_BUF_SIZE - buffer_size), Region);
169 buffer_size += tmp_size;
170 #endif /* LOG_INSERT_COLOR_INSIDE_THE_TRACE != 0 */
171
172 #if (LOG_INSERT_TIME_STAMP_INSIDE_THE_TRACE != 0)
173 if (log_timestamp_function != NULL)
174 {
175 tmp_size = UTIL_ADV_TRACE_TMP_BUF_SIZE - buffer_size;
176 log_timestamp_function(&full_text[buffer_size], tmp_size, &tmp_size);
177 buffer_size += tmp_size;
178 }
179 #endif /* LOG_INSERT_TIME_STAMP_INSIDE_THE_TRACE != 0 */
180
181 /* Copy the data */
182 tmp_size = (uint16_t)vsnprintf(&full_text[buffer_size], (UTIL_ADV_TRACE_TMP_BUF_SIZE - buffer_size), Text, Args);
183 buffer_size += tmp_size;
184
185 /* USER CODE BEGIN Log_Module_PrintWithArg_2 */
186
187 /* USER CODE END Log_Module_PrintWithArg_2 */
188
189 #if (LOG_INSERT_EOL_INSIDE_THE_TRACE != 0)
190 /* Add End Of Line if needed */
191 if (buffer_size > 1)
192 {
193 if ((full_text[buffer_size - 1] != ENDOFLINE_CHAR) && (full_text[buffer_size - 2] != ENDOFLINE_CHAR))
194 {
195 full_text[buffer_size++] = ENDOFLINE_CHAR;
196 full_text[buffer_size] = 0;
197 }
198 }
199 #endif /* LOG_INSERT_EOL_INSIDE_THE_TRACE != 0 */
200
201 /* USER CODE BEGIN Log_Module_PrintWithArg_3 */
202
203 /* USER CODE END Log_Module_PrintWithArg_3 */
204
205 /* Send full_text to ADV Traces */
206 UTIL_ADV_TRACE_Send((const uint8_t *)full_text, buffer_size);
207 }
208
Log_Module_Print(Log_Verbose_Level_t VerboseLevel,Log_Region_t Region,const char * Text,...)209 void Log_Module_Print(Log_Verbose_Level_t VerboseLevel, Log_Region_t Region, const char * Text, ...)
210 {
211 #if (CFG_LOG_SUPPORTED != 0)
212 va_list variadic_args;
213
214 va_start(variadic_args, Text);
215 Log_Module_PrintWithArg(VerboseLevel, Region, Text, variadic_args);
216 va_end(variadic_args);
217 #else /* (CFG_LOG_SUPPORTED != 0) */
218 UNUSED(VerboseLevel);
219 UNUSED(Region);
220 UNUSED(Text);
221 #endif /* (CFG_LOG_SUPPORTED != 0) */
222 }
223
Log_Module_Init(Log_Module_t LogConfiguration)224 void Log_Module_Init(Log_Module_t LogConfiguration)
225 {
226 UTIL_ADV_TRACE_Init();
227
228 memcpy(¤t_color_list, &LOG_COLOR_DEFAULT_CONFIGURATION, sizeof(LOG_COLOR_DEFAULT_CONFIGURATION));
229 Log_Module_Set_Verbose_Level(LogConfiguration.verbose_level);
230 Log_Module_Set_Multiple_Regions(LogConfiguration.region_mask);
231 log_timestamp_function = NULL;
232 }
233
Log_Module_DeInit(void)234 void Log_Module_DeInit(void)
235 {
236 UTIL_ADV_TRACE_DeInit();
237 }
238
Log_Module_Set_Verbose_Level(Log_Verbose_Level_t NewVerboseLevel)239 void Log_Module_Set_Verbose_Level(Log_Verbose_Level_t NewVerboseLevel)
240 {
241 current_verbose_level = NewVerboseLevel;
242 }
243
Log_Module_Set_Region(Log_Region_t NewRegion)244 void Log_Module_Set_Region(Log_Region_t NewRegion)
245 {
246 current_region_mask = Get_Region_Mask(NewRegion);
247 }
248
Log_Module_Add_Region(Log_Region_t NewRegion)249 void Log_Module_Add_Region(Log_Region_t NewRegion)
250 {
251 current_region_mask |= Get_Region_Mask(NewRegion);
252 }
253
Log_Module_Remove_Region(Log_Region_t Region)254 void Log_Module_Remove_Region(Log_Region_t Region)
255 {
256 current_region_mask &= ~Get_Region_Mask(Region);
257 }
258
Log_Module_Enable_All_Regions(void)259 void Log_Module_Enable_All_Regions(void)
260 {
261 Log_Module_Set_Region(LOG_REGION_ALL_REGIONS);
262 }
263
Get_Region_Mask(Log_Region_t Region)264 static uint32_t Get_Region_Mask(Log_Region_t Region)
265 {
266 if (Region == LOG_REGION_ALL_REGIONS)
267 {
268 /* Return the full mask */
269 return ((uint32_t)LOG_MODULE_ALL_REGION_MASK);
270 }
271 else
272 {
273 /* Return the bit matching the region */
274 return ((uint32_t)(1U << ((uint32_t)Region)));
275 }
276 }
277
Log_Module_Set_Multiple_Regions(uint32_t NewRegionMask)278 void Log_Module_Set_Multiple_Regions(uint32_t NewRegionMask)
279 {
280 current_region_mask = NewRegionMask;
281 }
282
Log_Module_Set_Color(Log_Region_t Region,Log_Color_t Color)283 void Log_Module_Set_Color(Log_Region_t Region, Log_Color_t Color)
284 {
285 if ( Region != LOG_MODULE_ALL_REGION_MASK )
286 {
287 current_color_list[Region] = Color;
288 }
289 }
290
Log_Module_RegisterTimeStampFunction(CallBack_TimeStamp * TimeStampFunction)291 void Log_Module_RegisterTimeStampFunction(CallBack_TimeStamp * TimeStampFunction)
292 {
293 log_timestamp_function = TimeStampFunction;
294 }
295
296 /* USER CODE BEGIN 0 */
297
298 /* USER CODE END 0 */
299