1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** USBX Component */
16 /** */
17 /** Utility */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 /* Include necessary system files. */
23
24 #define UX_SOURCE_CODE
25
26 #include "ux_api.h"
27
28
29 #ifdef UX_ENABLE_DEBUG_LOG
30
31 /**************************************************************************/
32 /* */
33 /* FUNCTION RELEASE */
34 /* */
35 /* _ux_utility_debug_log PORTABLE C */
36 /* 6.1 */
37 /* AUTHOR */
38 /* */
39 /* Chaoqiong Xiao, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* This function logs a debug msg in a circular queue. The queue */
44 /* must be initialized during the init of USBX. */
45 /* */
46 /* */
47 /* INPUT */
48 /* */
49 /* debug_location C string to locate the debug, */
50 /* for example source file name. */
51 /* debug_message C string of message */
52 /* debug_code Debug code */
53 /* debug_parameter_1 First parameter */
54 /* debug_parameter_2 Second parameter */
55 /* */
56 /* */
57 /* OUTPUT */
58 /* */
59 /* None */
60 /* */
61 /* CALLS */
62 /* */
63 /* _ux_utility_string_length_check Check C string and return */
64 /* its length if null-terminated */
65 /* _tx_time_get Return system clock time */
66 /* */
67 /* CALLED BY */
68 /* */
69 /* Application */
70 /* */
71 /* RELEASE HISTORY */
72 /* */
73 /* DATE NAME DESCRIPTION */
74 /* */
75 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
76 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
77 /* verified memset and memcpy */
78 /* cases, used UX prefix to */
79 /* refer to TX symbols instead */
80 /* of using them directly, */
81 /* resulting in version 6.1 */
82 /* */
83 /**************************************************************************/
_ux_utility_debug_log(UCHAR * debug_location,UCHAR * debug_message,ULONG debug_code,ULONG debug_parameter_1,ULONG debug_parameter_2)84 VOID _ux_utility_debug_log(UCHAR *debug_location, UCHAR *debug_message, ULONG debug_code,
85 ULONG debug_parameter_1, ULONG debug_parameter_2)
86 {
87
88 UINT debug_location_string_length;
89 UINT debug_message_string_length;
90 ULONG total_debug_message_length;
91 ULONG parameter_length;
92 ULONG parameter_shift;
93 UCHAR parameter_hexa;
94 ULONG local_parameter_value;
95 ULONG current_time;
96 UX_INTERRUPT_SAVE_AREA
97
98 /* Is USBX system completely initialized ? */
99 if (_ux_system -> ux_system_debug_log_size == 0)
100
101 /* Not yet. */
102 return;
103
104 /* Entering critical area. Disable interrupts. */
105 UX_DISABLE
106
107 /* Store the debug value as the last debug value recorded. */
108 _ux_system -> ux_system_debug_code = debug_code;
109
110 /* Increment the debug value code count. */
111 _ux_system -> ux_system_debug_count++;
112
113 /* Calculate the string length. */
114 debug_location_string_length = UX_DEBUG_LOG_SIZE;
115 _ux_utility_string_length_check(source, &debug_location_string_length, UX_DEBUG_LOG_SIZE);
116 debug_message_string_length = UX_DEBUG_LOG_SIZE;
117 _ux_utility_string_length_check(source, &debug_message_string_length, UX_DEBUG_LOG_SIZE);
118
119 /* Calculate the length of the entire message string. 1 fixed string, then 1 hexa
120 decimal, then 2 strings then 2 hexa decimal numbers in the format 0x00000000
121 separated by commas and . at the end, zero terminated. */
122 total_debug_message_length = debug_location_string_length + debug_message_string_length + 10 + 10 + 10 + 10 + 5;
123
124 /* Can we accommodate this debug value message at the current location ? */
125 if (total_debug_message_length >= _ux_system -> ux_system_debug_log_size)
126 return;
127 if (_ux_system -> ux_system_debug_log_head + total_debug_message_length >
128 ux_system -> ux_system_debug_log_buffer + _ux_system -> ux_system_debug_log_size)
129 {
130
131 /* The debug value log to insert goes beyond the end of the log buffer, rewind to the beginning. */
132 _ux_system -> ux_system_debug_log_head = _ux_system -> ux_system_debug_log_buffer;
133 }
134
135 /* Copy the time strings and parameters in the log buffer. */
136 _ux_utility_memory_copy(_ux_system -> ux_system_debug_log_head, "At time : ", 10); /* Use case of memcpy is verified. */
137 _ux_system -> ux_system_debug_log_head += 10;
138
139 /* Get the time value from TX. */
140 current_time = _tx_time_get();
141
142 /* Reset the value of the length.*/
143 parameter_length = 0;
144
145 /* Init the shift value. */
146 parameter_shift = 32 - 4;
147
148 /* We parse the hexa value parameter and build the hexa value one byte at a type. */
149 while(parameter_length < 8)
150 {
151
152 /* Shift the 4 bit value we are interested in. We keep the lowest nibble. */
153 local_parameter_value = (current_time >> parameter_shift) & 0x0f;
154
155 /* See if this value is from 0-9 or A to F. */
156 if (local_parameter_value <= 9)
157
158 /* We have a digit. */
159 parameter_hexa = (UCHAR) (local_parameter_value + '0');
160
161 else
162
163 /* We have 'A' to 'F' value. */
164 parameter_hexa = (UCHAR) (local_parameter_value - 10 + 'A');
165
166 /* Store the converted hexa value. */
167 *_ux_system -> ux_system_debug_log_head = parameter_hexa;
168
169 /* Next position. */
170 _ux_system -> ux_system_debug_log_head++;
171
172 /* Update length. */
173 parameter_length++;
174
175 /* Continue shifting by one nibble. */
176 parameter_shift = parameter_shift - 4;
177 }
178
179 /* Add the comma after the time. */
180 *_ux_system -> ux_system_debug_log_head = ',';
181 _ux_system -> ux_system_debug_log_head++;
182
183 /* Copy the strings and parameters in the log buffer. */
184 _ux_utility_memory_copy(_ux_system -> ux_system_debug_log_head, debug_location, debug_location_string_length); /* Use case of memcpy is verified. */
185 _ux_system -> ux_system_debug_log_head += debug_location_string_length;
186 *_ux_system -> ux_system_debug_log_head = ',';
187 _ux_system -> ux_system_debug_log_head++;
188 _ux_utility_memory_copy(_ux_system -> ux_system_debug_log_head, debug_message, debug_message_string_length); /* Use case of memcpy is verified. */
189 _ux_system -> ux_system_debug_log_head += debug_message_string_length;
190 *_ux_system -> ux_system_debug_log_head = ',';
191 _ux_system -> ux_system_debug_log_head++;
192
193 /* Create the hexa string for parameter 1. */
194 *_ux_system -> ux_system_debug_log_head = '0';
195 _ux_system -> ux_system_debug_log_head++;
196 *_ux_system -> ux_system_debug_log_head = 'x';
197 _ux_system -> ux_system_debug_log_head++;
198
199 /* Reset the value of the length.*/
200 parameter_length = 0;
201
202 /* Init the shift value. */
203 parameter_shift = 32 - 4;
204
205 /* We parse the hexa value parameter and build the hexa value one byte at a type. */
206 while(parameter_length < 8)
207 {
208
209 /* Shift the 4 bit value we are interested in. We keep the lowest nibble. */
210 local_parameter_value = (debug_parameter_1 >> parameter_shift) & 0x0f;
211
212 /* See if this value is from 0-9 or A to F. */
213 if (local_parameter_value <= 9)
214
215 /* We have a digit. */
216 parameter_hexa = (UCHAR) (local_parameter_value + '0');
217
218 else
219
220 /* We have 'A' to 'F' value. */
221 parameter_hexa = (UCHAR) (local_parameter_value - 10 + 'A');
222
223 /* Store the converted hexa value. */
224 *_ux_system -> ux_system_debug_log_head = parameter_hexa;
225
226 /* Next position. */
227 _ux_system -> ux_system_debug_log_head++;
228
229 /* Update length. */
230 parameter_length++;
231
232 /* Continue shifting by one nibble. */
233 parameter_shift = parameter_shift - 4;
234 }
235
236 /* Add the comma between the 2 hexa values. */
237 *_ux_system -> ux_system_debug_log_head = ',';
238 _ux_system -> ux_system_debug_log_head++;
239
240 /* Create the hexa string for parameter 2. */
241 *_ux_system -> ux_system_debug_log_head = '0';
242 _ux_system -> ux_system_debug_log_head++;
243 *_ux_system -> ux_system_debug_log_head = 'x';
244 _ux_system -> ux_system_debug_log_head++;
245
246 /* Reset the value of the length.*/
247 parameter_length = 0;
248
249 /* Init the shift value. */
250 parameter_shift = 32 - 4;
251
252 /* We parse the hexa value parameter and build the hexa value one byte at a type. */
253 while(parameter_length < 8)
254 {
255
256 /* Shift the 4 bit value we are interested in. We keep the lowest nibble. */
257 local_parameter_value = (debug_parameter_2 >> parameter_shift) & 0x0f;
258
259 /* See if this value is from 0-9 or A to F. */
260 if (local_parameter_value <= 9)
261
262 /* We have a digit. */
263 parameter_hexa = (UCHAR) (local_parameter_value + '0');
264
265 else
266
267 /* We have 'A' to 'F' value. */
268 parameter_hexa = (UCHAR) (local_parameter_value - 10 + 'A');
269
270 /* Store the converted hexa value. */
271 *_ux_system -> ux_system_debug_log_head = parameter_hexa;
272
273 /* Next position. */
274 _ux_system -> ux_system_debug_log_head++;
275
276 /* Update length. */
277 parameter_length++;
278
279 /* Continue shifting by one nibble. */
280 parameter_shift = parameter_shift - 4;
281 }
282
283 /* Add the termination dot at the end. */
284 *_ux_system -> ux_system_debug_log_head = '.';
285 _ux_system -> ux_system_debug_log_head++;
286
287 /* Add the CR/LF end of the string. */
288 *_ux_system -> ux_system_debug_log_head = 0x0d;
289 _ux_system -> ux_system_debug_log_head++;
290 *_ux_system -> ux_system_debug_log_head = 0x0a;
291 _ux_system -> ux_system_debug_log_head++;
292
293 /* Add the zero end of the string. */
294 *_ux_system -> ux_system_debug_log_head = 0x00;
295 _ux_system -> ux_system_debug_log_head++;
296
297 /* The log string is put into the log buffer. It can stay here until
298 a break into debugger by the developer or be passed to a callback registered
299 by the application. */
300 if (_ux_system -> ux_system_debug_callback_function != UX_NULL)
301 {
302
303 /* The callback function is defined, call it. */
304 _ux_system -> ux_system_debug_callback_function(_ux_system -> ux_system_debug_log_tail, debug_code);
305
306 /* Update the tail. */
307 _ux_system -> ux_system_debug_log_tail += total_debug_message_length;
308
309 }
310
311 /* Restore interrupts. */
312 UX_RESTORE
313
314 /* We are done here. No return codes. */
315 return;
316 }
317
318 #endif
319