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 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 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 */ 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 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 */ 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 */ 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 */ 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 */ 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