1 /**
2 ******************************************************************************
3 * @file dbg_trace.c
4 * @author MCD Application Team
5 * @brief This file contains the Interface with BLE Drivers functions.
6 ******************************************************************************
7 * @attention
8 *
9 * <h2><center>© Copyright (c) 2019 STMicroelectronics.
10 * All rights reserved.</center></h2>
11 *
12 * This software component is licensed by ST under BSD 3-Clause license,
13 * the "License"; You may not use this file except in compliance with the
14 * License. You may obtain a copy of the License at:
15 * opensource.org/licenses/BSD-3-Clause
16 *
17 ******************************************************************************
18 */
19
20
21 /* Includes ------------------------------------------------------------------*/
22 #include "utilities_common.h"
23 #include "stm_queue.h"
24 #include "dbg_trace.h"
25
26 /* Definition of the function */
27 #if !defined(__GNUC__) /* SW4STM32 */
28 size_t __write(int handle, const unsigned char * buf, size_t bufSize);
29 #endif
30
31 /** @addtogroup TRACE
32 * @{
33 */
34
35
36 /** @defgroup TRACE_LOG
37 * @brief TRACE Logging functions
38 * @{
39 */
40
41 /* Private typedef -----------------------------------------------------------*/
42 /** @defgroup TRACE Log private typedef
43 * @{
44 */
45
46 /**
47 * @}
48 */
49
50 /* Private defines -----------------------------------------------------------*/
51 /** @defgroup TRACE Log private defines
52 * @{
53 */
54
55 /**
56 * @}
57 */
58
59 /* Private macros ------------------------------------------------------------*/
60 /** @defgroup TRACE Log private macros
61 * @{
62 */
63 /**
64 * @}
65 */
66
67 /* Private variables ---------------------------------------------------------*/
68 /** @defgroup TRACE Log private variables
69 * @{
70 */
71 #if (( CFG_DEBUG_TRACE_FULL != 0 ) || ( CFG_DEBUG_TRACE_LIGHT != 0 ))
72 #if (DBG_TRACE_USE_CIRCULAR_QUEUE != 0)
73 static queue_t MsgDbgTraceQueue;
74 static uint8_t MsgDbgTraceQueueBuff[DBG_TRACE_MSG_QUEUE_SIZE];
75 #endif
76 __IO ITStatus DbgTracePeripheralReady = SET;
77 #endif
78 /**
79 * @}
80 */
81
82 /* Global variables ----------------------------------------------------------*/
83 /** @defgroup TRACE Log Global variable
84 * @{
85 */
86 /**
87 * @}
88 */
89
90 /* Private function prototypes -----------------------------------------------*/
91 /** @defgroup TRACE Log private function prototypes
92 * @{
93 */
94 #if (( CFG_DEBUG_TRACE_FULL != 0 ) || ( CFG_DEBUG_TRACE_LIGHT != 0 ))
95 static void DbgTrace_TxCpltCallback(void);
96 #endif
97
98
99 /**
100 * @}
101 */
102
103
104 /* Private Functions Definition ------------------------------------------------------*/
105 /** @defgroup TRACE Log Private function
106 * @{
107 */
108
109
110 /* Functions Definition ------------------------------------------------------*/
111 /** @defgroup TRACE Log APIs
112 * @{
113 */
114
115 /**
116 * @brief DbgTraceGetFileName: Return filename string extracted from full path information
117 * @param *fullPath Fullpath string (path + filename)
118 * @retval char* Pointer on filename string
119 */
120
DbgTraceGetFileName(const char * fullpath)121 const char *DbgTraceGetFileName(const char *fullpath)
122 {
123 const char *ret = fullpath;
124
125 if (strrchr(fullpath, '\\') != NULL)
126 {
127 ret = strrchr(fullpath, '\\') + 1;
128 }
129 else if (strrchr(fullpath, '/') != NULL)
130 {
131 ret = strrchr(fullpath, '/') + 1;
132 }
133
134 return ret;
135 }
136
137 /**
138 * @brief DbgTraceBuffer: Output buffer content information to output Stream
139 * @param *pBuffer Pointer on buffer to be output
140 * @param u32Length buffer Size
141 * @paramt strFormat string as expected by "printf" function. Used to desrcibe buffer content information.
142 * @param ... Paremeters to be "formatted" in strFormat string (if any)
143 * @retval None
144 */
145
DbgTraceBuffer(const void * pBuffer,uint32_t u32Length,const char * strFormat,...)146 void DbgTraceBuffer(const void *pBuffer, uint32_t u32Length, const char *strFormat, ...)
147 {
148 va_list vaArgs;
149 uint32_t u32Index;
150 va_start(vaArgs, strFormat);
151 vprintf(strFormat, vaArgs);
152 va_end(vaArgs);
153 for (u32Index = 0; u32Index < u32Length; u32Index ++)
154 {
155 printf(" %02X", ((const uint8_t *) pBuffer)[u32Index]);
156 }
157 }
158
159 #if (( CFG_DEBUG_TRACE_FULL != 0 ) || ( CFG_DEBUG_TRACE_LIGHT != 0 ))
160 /**
161 * @brief DBG_TRACE USART Tx Transfer completed callback
162 * @param UartHandle: UART handle.
163 * @note Indicate the end of the transmission of a DBG_TRACE trace buffer to DBG_TRACE USART. If queue
164 * contains new trace data to transmit, start a new transmission.
165 * @retval None
166 */
DbgTrace_TxCpltCallback(void)167 static void DbgTrace_TxCpltCallback(void)
168 {
169 #if (DBG_TRACE_USE_CIRCULAR_QUEUE != 0)
170 uint8_t* buf;
171 uint16_t bufSize;
172
173 BACKUP_PRIMASK();
174
175 DISABLE_IRQ(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
176 /* Remove element just sent to UART */
177 CircularQueue_Remove(&MsgDbgTraceQueue,&bufSize);
178
179 /* Sense if new data to be sent */
180 buf=CircularQueue_Sense(&MsgDbgTraceQueue,&bufSize);
181
182
183 if ( buf != NULL)
184 {
185 RESTORE_PRIMASK();
186 DbgOutputTraces((uint8_t*)buf, bufSize, DbgTrace_TxCpltCallback);
187 }
188 else
189 {
190 DbgTracePeripheralReady = SET;
191 RESTORE_PRIMASK();
192 }
193
194 #else
195 BACKUP_PRIMASK();
196
197 DISABLE_IRQ(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
198
199 DbgTracePeripheralReady = SET;
200
201 RESTORE_PRIMASK();
202 #endif
203 }
204 #endif
205
DbgTraceInit(void)206 void DbgTraceInit( void )
207 {
208 #if (( CFG_DEBUG_TRACE_FULL != 0 ) || ( CFG_DEBUG_TRACE_LIGHT != 0 ))
209 DbgOutputInit();
210 #if (DBG_TRACE_USE_CIRCULAR_QUEUE != 0)
211 CircularQueue_Init(&MsgDbgTraceQueue, MsgDbgTraceQueueBuff, DBG_TRACE_MSG_QUEUE_SIZE, 0, CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG);
212 #endif
213 #endif
214 return;
215 }
216
217
218 #if (( CFG_DEBUG_TRACE_FULL != 0 ) || ( CFG_DEBUG_TRACE_LIGHT != 0 ))
219 #if defined(__GNUC__) /* SW4STM32 (GCC) */
220 /**
221 * @brief _write: override the __write standard lib function to redirect printf to USART.
222 * @param handle output handle (STDIO, STDERR...)
223 * @param buf buffer to write
224 * @param bufsize buffer size
225 * @param ...: arguments to be formatted in format string
226 * @retval none
227 */
_write(int handle,const unsigned char * buf,size_t bufSize)228 size_t _write(int handle, const unsigned char * buf, size_t bufSize)
229 {
230 return ( DbgTraceWrite(handle, buf, bufSize) );
231 }
232
233 #else
234 /**
235 * @brief __write: override the _write standard lib function to redirect printf to USART.
236 * @param handle output handle (STDIO, STDERR...)
237 * @param buf buffer to write
238 * @param bufsize buffer size
239 * @param ...: arguments to be formatted in format string
240 * @retval none
241 */
__write(int handle,const unsigned char * buf,size_t bufSize)242 size_t __write(int handle, const unsigned char * buf, size_t bufSize)
243 {
244 return ( DbgTraceWrite(handle, buf, bufSize) );
245 }
246 #endif /* #if defined(__GNUC__) */
247
248 /**
249 * @brief Override the standard lib function to redirect printf to USART.
250 * @param handle output handle (STDIO, STDERR...)
251 * @param buf buffer to write
252 * @param bufsize buffer size
253 * @retval Number of elements written
254 */
DbgTraceWrite(int handle,const unsigned char * buf,size_t bufSize)255 size_t DbgTraceWrite(int handle, const unsigned char * buf, size_t bufSize)
256 {
257 size_t chars_written = 0;
258 uint8_t* buffer;
259
260 BACKUP_PRIMASK();
261
262 /* Ignore flushes */
263 if ( handle == -1 )
264 {
265 chars_written = ( size_t ) 0;
266 }
267 /* Only allow stdout/stderr output */
268 else if ( ( handle != 1 ) && ( handle != 2 ) )
269 {
270 chars_written = ( size_t ) - 1;
271 }
272 /* Parameters OK, call the low-level character output routine */
273 else if (bufSize != 0)
274 {
275 chars_written = bufSize;
276 /* If queue emepty and TX free, send directly */
277 /* CS Start */
278
279 #if (DBG_TRACE_USE_CIRCULAR_QUEUE != 0)
280 DISABLE_IRQ(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
281 buffer=CircularQueue_Add(&MsgDbgTraceQueue,(uint8_t*)buf, bufSize,1);
282 if (buffer && DbgTracePeripheralReady)
283 {
284 DbgTracePeripheralReady = RESET;
285 RESTORE_PRIMASK();
286 DbgOutputTraces((uint8_t*)buffer, bufSize, DbgTrace_TxCpltCallback);
287 }
288 else
289 {
290 RESTORE_PRIMASK();
291 }
292 #else
293 DISABLE_IRQ(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
294 DbgTracePeripheralReady = RESET;
295 RESTORE_PRIMASK();
296
297 DbgOutputTraces((uint8_t*)buf, bufSize, DbgTrace_TxCpltCallback);
298 while (!DbgTracePeripheralReady);
299 #endif
300 /* CS END */
301 }
302 return ( chars_written );
303 }
304
305 #if defined ( __CC_ARM ) /* Keil */
306
307 /* For KEIL re-implement our own version of fputc */
fputc(int ch,FILE * f)308 int fputc(int ch, FILE *f)
309 {
310 /* temp char avoids endianness issue */
311 char tempch = ch;
312 /* Write one character to Debug Circular Queue */
313 DbgTraceWrite(1U, (const unsigned char *) &tempch, 1);
314 return ch;
315 }
316
317 #endif /* #if defined ( __CC_ARM ) */
318
319 #endif /* #if (( CFG_DEBUG_TRACE_FULL != 0 ) || ( CFG_DEBUG_TRACE_LIGHT != 0 )) */
320
321 /**
322 * @}
323 */
324
325 /**
326 * @}
327 */
328
329 /**
330 * @}
331 */
332 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
333