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