Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: MAX44000 PWM_Tone_Library nexpaq_mdk
Fork of LED_Demo by
mbed_trace.c
00001 /* 00002 * Copyright (c) 2014-2015 ARM Limited. All rights reserved. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * Licensed under the Apache License, Version 2.0 (the License); you may 00005 * not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an AS IS BASIS, WITHOUT 00012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #include <stdio.h> 00017 #include <string.h> 00018 #include <stdarg.h> 00019 00020 #ifndef YOTTA_CFG_MBED_TRACE 00021 #define YOTTA_CFG_MBED_TRACE 1 00022 #define YOTTA_CFG_MBED_TRACE_FEA_IPV6 1 00023 #endif 00024 00025 #include "mbed-trace/mbed_trace.h" 00026 #if YOTTA_CFG_MBED_TRACE_FEA_IPV6 == 1 00027 #include "mbed-client-libservice/ip6string.h" 00028 #include "mbed-client-libservice/common_functions.h" 00029 #endif 00030 00031 #if defined(YOTTA_CFG_MBED_TRACE_MEM) 00032 #define MBED_TRACE_MEM_INCLUDE YOTTA_CFG_MBED_TRACE_MEM_INCLUDE 00033 #define MBED_TRACE_MEM_ALLOC YOTTA_CFG_MBED_TRACE_MEM_ALLOC 00034 #define MBED_TRACE_MEM_FREE YOTTA_CFG_MBED_TRACE_MEM_FREE 00035 #else /* YOTTA_CFG_MEMLIB */ 00036 // Default options 00037 #ifndef MBED_TRACE_MEM_INCLUDE 00038 #define MBED_TRACE_MEM_INCLUDE <stdlib.h> 00039 #endif 00040 #include MBED_TRACE_MEM_INCLUDE 00041 #ifndef MBED_TRACE_MEM_ALLOC 00042 #define MBED_TRACE_MEM_ALLOC malloc 00043 #endif 00044 #ifndef MBED_TRACE_MEM_FREE 00045 #define MBED_TRACE_MEM_FREE free 00046 #endif 00047 #endif /* YOTTA_CFG_MEMLIB */ 00048 00049 #define VT100_COLOR_ERROR "\x1b[31m" 00050 #define VT100_COLOR_WARN "\x1b[33m" 00051 #define VT100_COLOR_INFO "\x1b[39m" 00052 #define VT100_COLOR_DEBUG "\x1b[90m" 00053 00054 /** default max trace line size in bytes */ 00055 #ifdef YOTTA_CFG_MBED_TRACE_LINE_LENGTH 00056 #define DEFAULT_TRACE_LINE_LENGTH YOTTA_CFG_MBED_TRACE_LINE_LENGTH 00057 #else 00058 #define DEFAULT_TRACE_LINE_LENGTH 1024 00059 #endif 00060 /** default max temporary buffer size in bytes, used in 00061 trace_ipv6, trace_ipv6_prefix and trace_array */ 00062 #ifdef YOTTA_CFG_MBED_TRACE_TMP_LINE_LEN 00063 #define DEFAULT_TRACE_TMP_LINE_LEN YOTTA_CFG_MBED_TRACE_TMP_LINE_LEN 00064 #elif defined YOTTA_CFG_MTRACE_TMP_LINE_LEN 00065 #warning The YOTTA_CFG_MTRACE_TMP_LINE_LEN flag is deprecated! Use YOTTA_CFG_MBED_TRACE_TMP_LINE_LEN instead. 00066 #define DEFAULT_TRACE_TMP_LINE_LEN YOTTA_CFG_MTRACE_TMP_LINE_LEN 00067 #else 00068 #define DEFAULT_TRACE_TMP_LINE_LEN 128 00069 #endif 00070 /** default max filters (include/exclude) length in bytes */ 00071 #define DEFAULT_TRACE_FILTER_LENGTH 24 00072 00073 /** default print function, just redirect str to printf */ 00074 static void mbed_trace_realloc( char **buffer, int *length_ptr, int new_length); 00075 static void mbed_trace_default_print(const char *str); 00076 static void mbed_trace_reset_tmp(void); 00077 00078 typedef struct trace_s { 00079 /** trace configuration bits */ 00080 uint8_t trace_config; 00081 /** exclude filters list, related group name */ 00082 char *filters_exclude; 00083 /** include filters list, related group name */ 00084 char *filters_include; 00085 /** Filters length */ 00086 int filters_length; 00087 /** trace line */ 00088 char *line; 00089 /** trace line length */ 00090 int line_length; 00091 /** temporary data */ 00092 char *tmp_data; 00093 /** temporary data array length */ 00094 int tmp_data_length; 00095 /** temporary data pointer */ 00096 char *tmp_data_ptr; 00097 00098 /** prefix function, which can be used to put time to the trace line */ 00099 char *(*prefix_f)(size_t); 00100 /** suffix function, which can be used to some string to the end of trace line */ 00101 char *(*suffix_f)(void); 00102 /** print out function. Can be redirect to flash for example. */ 00103 void (*printf)(const char *); 00104 /** print out function for TRACE_LEVEL_CMD */ 00105 void (*cmd_printf)(const char *); 00106 /** mutex wait function which can be called to lock against a mutex. */ 00107 void (*mutex_wait_f)(void); 00108 /** mutex release function which must be used to release the mutex locked by mutex_wait_f. */ 00109 void (*mutex_release_f)(void); 00110 /** number of times the mutex has been locked */ 00111 int mutex_lock_count; 00112 } trace_t; 00113 00114 static trace_t m_trace = { 00115 .filters_exclude = 0, 00116 .filters_include = 0, 00117 .line = 0, 00118 .tmp_data = 0, 00119 .prefix_f = 0, 00120 .suffix_f = 0, 00121 .printf = 0, 00122 .cmd_printf = 0, 00123 .mutex_wait_f = 0, 00124 .mutex_release_f = 0, 00125 .mutex_lock_count = 0 00126 }; 00127 00128 int mbed_trace_init(void) 00129 { 00130 m_trace.trace_config = TRACE_MODE_COLOR | TRACE_ACTIVE_LEVEL_ALL | TRACE_CARRIAGE_RETURN; 00131 m_trace.line_length = DEFAULT_TRACE_LINE_LENGTH; 00132 if (m_trace.line == NULL) { 00133 m_trace.line = MBED_TRACE_MEM_ALLOC(m_trace.line_length); 00134 } 00135 m_trace.tmp_data_length = DEFAULT_TRACE_TMP_LINE_LEN; 00136 if (m_trace.tmp_data == NULL) { 00137 m_trace.tmp_data = MBED_TRACE_MEM_ALLOC(m_trace.tmp_data_length); 00138 } 00139 m_trace.tmp_data_ptr = m_trace.tmp_data; 00140 m_trace.filters_length = DEFAULT_TRACE_FILTER_LENGTH; 00141 if (m_trace.filters_exclude == NULL) { 00142 m_trace.filters_exclude = MBED_TRACE_MEM_ALLOC(m_trace.filters_length); 00143 } 00144 if (m_trace.filters_include == NULL) { 00145 m_trace.filters_include = MBED_TRACE_MEM_ALLOC(m_trace.filters_length); 00146 } 00147 00148 if (m_trace.line == NULL || 00149 m_trace.tmp_data == NULL || 00150 m_trace.filters_exclude == NULL || 00151 m_trace.filters_include == NULL) { 00152 //memory allocation fail 00153 mbed_trace_free(); 00154 return -1; 00155 } 00156 memset(m_trace.tmp_data, 0, m_trace.tmp_data_length); 00157 memset(m_trace.filters_exclude, 0, m_trace.filters_length); 00158 memset(m_trace.filters_include, 0, m_trace.filters_length); 00159 memset(m_trace.line, 0, m_trace.line_length); 00160 00161 m_trace.prefix_f = 0; 00162 m_trace.suffix_f = 0; 00163 m_trace.printf = mbed_trace_default_print; 00164 m_trace.cmd_printf = 0; 00165 00166 return 0; 00167 } 00168 void mbed_trace_free(void) 00169 { 00170 MBED_TRACE_MEM_FREE(m_trace.line); 00171 m_trace.line_length = 0; 00172 m_trace.line = 0; 00173 MBED_TRACE_MEM_FREE(m_trace.tmp_data); 00174 m_trace.tmp_data = 0; 00175 m_trace.tmp_data_ptr = 0; 00176 MBED_TRACE_MEM_FREE(m_trace.filters_exclude); 00177 m_trace.filters_exclude = 0; 00178 MBED_TRACE_MEM_FREE(m_trace.filters_include); 00179 m_trace.filters_include = 0; 00180 m_trace.filters_length = 0; 00181 m_trace.prefix_f = 0; 00182 m_trace.suffix_f = 0; 00183 m_trace.printf = mbed_trace_default_print; 00184 m_trace.cmd_printf = 0; 00185 m_trace.mutex_wait_f = 0; 00186 m_trace.mutex_release_f = 0; 00187 m_trace.mutex_lock_count = 0; 00188 } 00189 static void mbed_trace_realloc( char **buffer, int *length_ptr, int new_length) 00190 { 00191 MBED_TRACE_MEM_FREE(*buffer); 00192 *buffer = MBED_TRACE_MEM_ALLOC(new_length); 00193 *length_ptr = new_length; 00194 } 00195 void mbed_trace_buffer_sizes(int lineLength, int tmpLength) 00196 { 00197 if( lineLength > 0 ) { 00198 mbed_trace_realloc( &(m_trace.line), &m_trace.line_length, lineLength ); 00199 } 00200 if( tmpLength > 0 ) { 00201 mbed_trace_realloc( &(m_trace.tmp_data), &m_trace.tmp_data_length, tmpLength); 00202 mbed_trace_reset_tmp(); 00203 } 00204 } 00205 void mbed_trace_config_set(uint8_t config) 00206 { 00207 m_trace.trace_config = config; 00208 } 00209 uint8_t mbed_trace_config_get(void) 00210 { 00211 return m_trace.trace_config; 00212 } 00213 void mbed_trace_prefix_function_set(char *(*pref_f)(size_t)) 00214 { 00215 m_trace.prefix_f = pref_f; 00216 } 00217 void mbed_trace_suffix_function_set(char *(*suffix_f)(void)) 00218 { 00219 m_trace.suffix_f = suffix_f; 00220 } 00221 void mbed_trace_print_function_set(void (*printf)(const char *)) 00222 { 00223 m_trace.printf = printf; 00224 } 00225 void mbed_trace_cmdprint_function_set(void (*printf)(const char *)) 00226 { 00227 m_trace.cmd_printf = printf; 00228 } 00229 void mbed_trace_mutex_wait_function_set(void (*mutex_wait_f)(void)) 00230 { 00231 m_trace.mutex_wait_f = mutex_wait_f; 00232 } 00233 void mbed_trace_mutex_release_function_set(void (*mutex_release_f)(void)) 00234 { 00235 m_trace.mutex_release_f = mutex_release_f; 00236 } 00237 void mbed_trace_exclude_filters_set(char *filters) 00238 { 00239 if (filters) { 00240 (void)strncpy(m_trace.filters_exclude, filters, m_trace.filters_length); 00241 } else { 00242 m_trace.filters_exclude[0] = 0; 00243 } 00244 } 00245 const char *mbed_trace_exclude_filters_get(void) 00246 { 00247 return m_trace.filters_exclude; 00248 } 00249 const char *mbed_trace_include_filters_get(void) 00250 { 00251 return m_trace.filters_include; 00252 } 00253 void mbed_trace_include_filters_set(char *filters) 00254 { 00255 if (filters) { 00256 (void)strncpy(m_trace.filters_include, filters, m_trace.filters_length); 00257 } else { 00258 m_trace.filters_include[0] = 0; 00259 } 00260 } 00261 static int8_t mbed_trace_skip(int8_t dlevel, const char *grp) 00262 { 00263 if (dlevel >= 0 && grp != 0) { 00264 // filter debug prints only when dlevel is >0 and grp is given 00265 00266 /// @TODO this could be much better.. 00267 if (m_trace.filters_exclude[0] != '\0' && 00268 strstr(m_trace.filters_exclude, grp) != 0) { 00269 //grp was in exclude list 00270 return 1; 00271 } 00272 if (m_trace.filters_include[0] != '\0' && 00273 strstr(m_trace.filters_include, grp) == 0) { 00274 //grp was in include list 00275 return 1; 00276 } 00277 } 00278 return 0; 00279 } 00280 static void mbed_trace_default_print(const char *str) 00281 { 00282 puts(str); 00283 } 00284 void mbed_tracef(uint8_t dlevel, const char *grp, const char *fmt, ...) 00285 { 00286 va_list ap; 00287 va_start(ap, fmt); 00288 mbed_vtracef(dlevel, grp, fmt, ap); 00289 va_end(ap); 00290 } 00291 void mbed_vtracef(uint8_t dlevel, const char* grp, const char *fmt, va_list ap) 00292 { 00293 if ( m_trace.mutex_wait_f ) { 00294 m_trace.mutex_wait_f(); 00295 m_trace.mutex_lock_count++; 00296 } 00297 00298 if (NULL == m_trace.line) { 00299 goto end; 00300 } 00301 00302 m_trace.line[0] = 0; //by default trace is empty 00303 00304 if (mbed_trace_skip(dlevel, grp) || fmt == 0 || grp == 0 || !m_trace.printf) { 00305 //return tmp data pointer back to the beginning 00306 mbed_trace_reset_tmp(); 00307 goto end; 00308 } 00309 if ((m_trace.trace_config & TRACE_MASK_LEVEL) & dlevel) { 00310 bool color = (m_trace.trace_config & TRACE_MODE_COLOR) != 0; 00311 bool plain = (m_trace.trace_config & TRACE_MODE_PLAIN) != 0; 00312 bool cr = (m_trace.trace_config & TRACE_CARRIAGE_RETURN) != 0; 00313 00314 int retval = 0, bLeft = m_trace.line_length; 00315 char *ptr = m_trace.line; 00316 if (plain == true || dlevel == TRACE_LEVEL_CMD) { 00317 //add trace data 00318 retval = vsnprintf(ptr, bLeft, fmt, ap); 00319 if (dlevel == TRACE_LEVEL_CMD && m_trace.cmd_printf) { 00320 m_trace.cmd_printf(m_trace.line); 00321 m_trace.cmd_printf("\n"); 00322 } else { 00323 //print out whole data 00324 m_trace.printf(m_trace.line); 00325 } 00326 } else { 00327 if (color) { 00328 if (cr) { 00329 retval = snprintf(ptr, bLeft, "\r\x1b[2K"); 00330 if (retval >= bLeft) { 00331 retval = 0; 00332 } 00333 if (retval > 0) { 00334 ptr += retval; 00335 bLeft -= retval; 00336 } 00337 } 00338 if (bLeft > 0) { 00339 //include color in ANSI/VT100 escape code 00340 switch (dlevel) { 00341 case (TRACE_LEVEL_ERROR): 00342 retval = snprintf(ptr, bLeft, "%s", VT100_COLOR_ERROR); 00343 break; 00344 case (TRACE_LEVEL_WARN): 00345 retval = snprintf(ptr, bLeft, "%s", VT100_COLOR_WARN); 00346 break; 00347 case (TRACE_LEVEL_INFO): 00348 retval = snprintf(ptr, bLeft, "%s", VT100_COLOR_INFO); 00349 break; 00350 case (TRACE_LEVEL_DEBUG): 00351 retval = snprintf(ptr, bLeft, "%s", VT100_COLOR_DEBUG); 00352 break; 00353 default: 00354 color = 0; //avoid unneeded color-terminate code 00355 retval = 0; 00356 break; 00357 } 00358 if (retval >= bLeft) { 00359 retval = 0; 00360 } 00361 if (retval > 0 && color) { 00362 ptr += retval; 00363 bLeft -= retval; 00364 } 00365 } 00366 00367 } 00368 if (bLeft > 0 && m_trace.prefix_f) { 00369 //find out length of body 00370 size_t sz = 0; 00371 va_list ap2; 00372 va_copy(ap2, ap); 00373 sz = vsnprintf(NULL, 0, fmt, ap2) + retval + (retval ? 4 : 0); 00374 va_end(ap2); 00375 //add prefix string 00376 retval = snprintf(ptr, bLeft, "%s", m_trace.prefix_f(sz)); 00377 if (retval >= bLeft) { 00378 retval = 0; 00379 } 00380 if (retval > 0) { 00381 ptr += retval; 00382 bLeft -= retval; 00383 } 00384 } 00385 if (bLeft > 0) { 00386 //add group tag 00387 switch (dlevel) { 00388 case (TRACE_LEVEL_ERROR): 00389 retval = snprintf(ptr, bLeft, "[ERR ][%-4s]: ", grp); 00390 break; 00391 case (TRACE_LEVEL_WARN): 00392 retval = snprintf(ptr, bLeft, "[WARN][%-4s]: ", grp); 00393 break; 00394 case (TRACE_LEVEL_INFO): 00395 retval = snprintf(ptr, bLeft, "[INFO][%-4s]: ", grp); 00396 break; 00397 case (TRACE_LEVEL_DEBUG): 00398 retval = snprintf(ptr, bLeft, "[DBG ][%-4s]: ", grp); 00399 break; 00400 default: 00401 retval = snprintf(ptr, bLeft, " "); 00402 break; 00403 } 00404 if (retval >= bLeft) { 00405 retval = 0; 00406 } 00407 if (retval > 0) { 00408 ptr += retval; 00409 bLeft -= retval; 00410 } 00411 } 00412 if (retval > 0 && bLeft > 0) { 00413 //add trace text 00414 retval = vsnprintf(ptr, bLeft, fmt, ap); 00415 if (retval >= bLeft) { 00416 retval = 0; 00417 } 00418 if (retval > 0) { 00419 ptr += retval; 00420 bLeft -= retval; 00421 } 00422 } 00423 00424 if (retval > 0 && bLeft > 0 && m_trace.suffix_f) { 00425 //add suffix string 00426 retval = snprintf(ptr, bLeft, "%s", m_trace.suffix_f()); 00427 if (retval >= bLeft) { 00428 retval = 0; 00429 } 00430 if (retval > 0) { 00431 ptr += retval; 00432 bLeft -= retval; 00433 } 00434 } 00435 00436 if (retval > 0 && bLeft > 0 && color) { 00437 //add zero color VT100 when color mode 00438 retval = snprintf(ptr, bLeft, "\x1b[0m"); 00439 if (retval >= bLeft) { 00440 retval = 0; 00441 } 00442 if (retval > 0) { 00443 // not used anymore 00444 //ptr += retval; 00445 //bLeft -= retval; 00446 } 00447 } 00448 //print out whole data 00449 m_trace.printf(m_trace.line); 00450 } 00451 //return tmp data pointer back to the beginning 00452 mbed_trace_reset_tmp(); 00453 } 00454 00455 end: 00456 if ( m_trace.mutex_release_f ) { 00457 for ( ;m_trace.mutex_lock_count > 0; m_trace.mutex_lock_count-- ) { 00458 m_trace.mutex_release_f(); 00459 } 00460 } 00461 } 00462 static void mbed_trace_reset_tmp(void) 00463 { 00464 m_trace.tmp_data_ptr = m_trace.tmp_data; 00465 } 00466 const char *mbed_trace_last(void) 00467 { 00468 return m_trace.line; 00469 } 00470 /* Helping functions */ 00471 #define tmp_data_left() m_trace.tmp_data_length-(m_trace.tmp_data_ptr-m_trace.tmp_data) 00472 #if YOTTA_CFG_MBED_TRACE_FEA_IPV6 == 1 00473 char *mbed_trace_ipv6(const void *addr_ptr) 00474 { 00475 /** Acquire mutex. It is released before returning from mbed_vtracef. */ 00476 if ( m_trace.mutex_wait_f ) { 00477 m_trace.mutex_wait_f(); 00478 m_trace.mutex_lock_count++; 00479 } 00480 char *str = m_trace.tmp_data_ptr; 00481 if (str == NULL) { 00482 return ""; 00483 } 00484 if (tmp_data_left() < 41) { 00485 return ""; 00486 } 00487 if (addr_ptr == NULL) { 00488 return "<null>"; 00489 } 00490 str[0] = 0; 00491 m_trace.tmp_data_ptr += ip6tos(addr_ptr, str) + 1; 00492 return str; 00493 } 00494 char *mbed_trace_ipv6_prefix(const uint8_t *prefix, uint8_t prefix_len) 00495 { 00496 /** Acquire mutex. It is released before returning from mbed_vtracef. */ 00497 if ( m_trace.mutex_wait_f ) { 00498 m_trace.mutex_wait_f(); 00499 m_trace.mutex_lock_count++; 00500 } 00501 char *str = m_trace.tmp_data_ptr; 00502 if (str == NULL) { 00503 return ""; 00504 } 00505 if (tmp_data_left() < 45) { 00506 return ""; 00507 } 00508 00509 if ((prefix_len != 0 && prefix == NULL) || prefix_len > 128) { 00510 return "<err>"; 00511 } 00512 00513 m_trace.tmp_data_ptr += ip6_prefix_tos(prefix, prefix_len, str) + 1; 00514 return str; 00515 } 00516 #endif //YOTTA_CFG_MBED_TRACE_FEA_IPV6 00517 char *mbed_trace_array(const uint8_t *buf, uint16_t len) 00518 { 00519 /** Acquire mutex. It is released before returning from mbed_vtracef. */ 00520 if ( m_trace.mutex_wait_f ) { 00521 m_trace.mutex_wait_f(); 00522 m_trace.mutex_lock_count++; 00523 } 00524 int i, bLeft = tmp_data_left(); 00525 char *str, *wptr; 00526 str = m_trace.tmp_data_ptr; 00527 if (str == NULL || bLeft == 0) { 00528 return ""; 00529 } 00530 if (buf == NULL) { 00531 return "<null>"; 00532 } 00533 wptr = str; 00534 wptr[0] = 0; 00535 const uint8_t *ptr = buf; 00536 char overflow = 0; 00537 for (i = 0; i < len; i++) { 00538 if (bLeft <= 3) { 00539 overflow = 1; 00540 break; 00541 } 00542 int retval = snprintf(wptr, bLeft, "%02x:", *ptr++); 00543 if (retval <= 0 || retval > bLeft) { 00544 break; 00545 } 00546 bLeft -= retval; 00547 wptr += retval; 00548 } 00549 if (wptr > str) { 00550 if( overflow ) { 00551 // replace last character as 'star', 00552 // which indicate buffer len is not enough 00553 *(wptr - 1) = '*'; 00554 } else { 00555 //null to replace last ':' character 00556 *(wptr - 1) = 0; 00557 } 00558 } 00559 m_trace.tmp_data_ptr = wptr; 00560 return str; 00561 }
Generated on Tue Jul 12 2022 12:28:43 by
