1 /* 2 * Trace Recorder for Tracealyzer v4.6.6 3 * Copyright 2021 Percepio AB 4 * www.percepio.com 5 * 6 * SPDX-License-Identifier: Apache-2.0 7 */ 8 9 #ifndef TRC_RECORDER_H 10 #define TRC_RECORDER_H 11 12 /** 13 * @file 14 * 15 * @brief The public API of the Percepio trace recorder. 16 */ 17 18 #ifdef __cplusplus 19 extern "C" { 20 #endif 21 22 /** 23 * @brief Trace Recorder APIs 24 * @defgroup trace_recorder_apis Trace Recorder APIs 25 * @{ 26 * @} 27 */ 28 29 #define TRC_ACKNOWLEDGED (0xABC99123) 30 31 #include <trcDefines.h> 32 #include <trcConfig.h> 33 #include <trcKernelPortConfig.h> 34 #include <trcTypes.h> 35 36 #ifndef TRC_CFG_TEST_MODE 37 #define TRC_CFG_TEST_MODE 0 38 #endif 39 40 /* Unless defined by the kernel port, we assume there is no support for 41 * the classic snapshot mode and default to streaming mode where 42 * the new RingBuffer snapshot mode provides snapshot functionality. 43 */ 44 #ifndef TRC_CFG_RECORDER_MODE 45 #define TRC_CFG_RECORDER_MODE TRC_RECORDER_MODE_STREAMING 46 #endif 47 48 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) 49 #include <trcSnapshotConfig.h> 50 #include <trcKernelPortSnapshotConfig.h> 51 52 /* Calls xTraceError if the _assert condition is false. For void functions, 53 where no return value is to be provided. */ 54 #define TRC_ASSERT_VOID(_assert, _err) if (! (_assert)){ prvTraceError(_err); return; } 55 56 /* Calls xTraceError if the _assert condition is false. For non-void functions, 57 where a return value is to be provided. */ 58 #define TRC_ASSERT_RET(_assert, _err, _return) if (! (_assert)){ prvTraceError(_err); return _return; } 59 60 typedef uint8_t traceUBChannel; 61 typedef uint8_t traceObjectClass; 62 63 #undef traceHandle 64 #if (TRC_CFG_USE_16BIT_OBJECT_HANDLES == 1) 65 typedef uint16_t traceHandle; 66 #else /* (TRC_CFG_USE_16BIT_OBJECT_HANDLES == 1) */ 67 typedef uint8_t traceHandle; 68 #endif /* (TRC_CFG_USE_16BIT_OBJECT_HANDLES == 1) */ 69 70 #undef TraceISRHandle_t 71 #define TraceISRHandle_t traceHandle 72 73 #include <trcHardwarePort.h> 74 #include <trcKernelPort.h> 75 76 /* Not yet available in snapshot mode */ 77 #define vTraceConsoleChannelPrintF(fmt, ...) (void) 78 #define xTraceConsoleChannelPrintF(fmt, ...) (void) 79 #define prvTraceStoreEvent_None(...) 80 #define prvTraceStoreEvent_Handle(...) 81 #define prvTraceStoreEvent_Param(...) 82 #define prvTraceStoreEvent_HandleParam(...) 83 #define prvTraceStoreEvent_ParamParam(...) 84 #define prvTraceStoreEvent_HandleParamParam(...) 85 #define prvTraceStoreEvent_ParamParamParam(...) 86 87 #endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) */ 88 89 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) 90 #include <trcStreamingConfig.h> 91 #include <trcKernelPortStreamingConfig.h> 92 93 /* Unless specified in trcConfig.h we assume this is a single core target */ 94 #ifndef TRC_CFG_CORE_COUNT 95 #define TRC_CFG_CORE_COUNT 1 96 #endif 97 98 /* Unless specified in trcConfig.h we assume this is a single core target */ 99 #ifndef TRC_CFG_GET_CURRENT_CORE 100 #define TRC_CFG_GET_CURRENT_CORE() 0 101 #endif 102 103 /* Unless specified in trcConfig.h or trcKernelPortConfig.h we assume 104 * GCC statement expressions aren't supported. */ 105 #ifndef TRC_CFG_USE_GCC_STATEMENT_EXPR 106 #define TRC_CFG_USE_GCC_STATEMENT_EXPR 0 107 #endif 108 109 /* Backwards compatibility */ 110 #undef traceHandle 111 #define traceHandle TraceISRHandle_t 112 113 /* Maximum event size */ 114 #define TRC_MAX_BLOB_SIZE (16 * sizeof(uint32_t)) 115 116 /* Platform name length */ 117 #define TRC_PLATFORM_CFG_LENGTH 8 118 119 /* Header size */ 120 #define TRC_HEADER_BUFFER_SIZE (sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t) + (sizeof(char) * (TRC_PLATFORM_CFG_LENGTH)) + sizeof(uint16_t) + sizeof(uint8_t) + sizeof(uint8_t)) 121 122 typedef struct TraceHeaderBuffer 123 { 124 uint8_t buffer[TRC_HEADER_BUFFER_SIZE]; 125 } TraceHeaderBuffer_t; 126 127 #include <trcHardwarePort.h> 128 #include <trcKernelPort.h> 129 #include <trcString.h> 130 #include <trcStaticBuffer.h> 131 #include <trcError.h> 132 #include <trcEvent.h> 133 #include <trcEventBuffer.h> 134 #include <trcMultiCoreEventBuffer.h> 135 #include <trcTimestamp.h> 136 #include <trcEntryTable.h> 137 #include <trcStreamPort.h> 138 #include <trcISR.h> 139 #include <trcTask.h> 140 #include <trcObject.h> 141 #include <trcPrint.h> 142 #include <trcHeap.h> 143 #include <trcExtension.h> 144 #include <trcUtility.h> 145 #include <trcStackMonitor.h> 146 #include <trcInternalEventBuffer.h> 147 #include <trcDiagnostics.h> 148 #include <trcAssert.h> 149 150 #endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ 151 152 /* These includes offer functionality for Streaming mode only, but they are included here in order to avoid compilation errors */ 153 #include <trcInterval.h> 154 #include <trcStateMachine.h> 155 #include <trcCounter.h> 156 157 #if (TRC_USE_TRACEALYZER_RECORDER == 1) 158 159 /******************************************************************************/ 160 /*** Common API - both Snapshot and Streaming mode ****************************/ 161 /******************************************************************************/ 162 163 /** 164 * @brief 165 * 166 * Initializes the recorder data. xTraceInitialize() or xTraceEnable(...) 167 * must be called before any attempts at adding trace data/information. 168 * See xTraceEnable(...) for more information. 169 * 170 * @retval TRC_FAIL Failure 171 * @retval TRC_SUCCESS Success 172 */ 173 traceResult xTraceInitialize(void); 174 175 /** 176 * @brief 177 * 178 * This function enables tracing. 179 * To use the trace recorder, the startup must call xTraceInitialize() or 180 * xTraceEnable(...) before any RTOS calls are made (including "create" calls). 181 * Three start options are provided: 182 * 183 * TRC_START: Starts the tracing directly. In snapshot mode this allows for 184 * starting the trace at any point in your code, assuming xTraceInitialize() 185 * has been called in the startup. Can also be used for streaming without 186 * Tracealyzer control, e.g. to a local flash file system (assuming such a 187 * "stream port", see trcStreamPort.h). 188 * 189 * TRC_START_AWAIT_HOST: For streaming mode only. Initializes the trace recorder 190 * if necessary and waits for a Start command from Tracealyzer ("Start Recording" 191 * button). This call is intentionally blocking! By calling xTraceEnable with 192 * this option from the startup code, you start tracing at this point and capture 193 * the early events. 194 * 195 * TRC_START_FROM_HOST: For streaming mode only. Initializes the trace recorder 196 * if necessary and creates a task that waits for a Start command from 197 * Tracealyzer ("Start Recording" button). This call is not blocking. 198 * 199 * @example Usage examples 200 * 201 * Snapshot trace, from startup: 202 * <board init> 203 * xTraceEnable(TRC_START); // Will call xTraceInitialize() 204 * <RTOS init> 205 * 206 * Snapshot trace, from a later point: 207 * <board init> 208 * xTraceInitialize(); 209 * <RTOS init> 210 * ... 211 * xTraceEnable(TRC_START); // e.g., in task context, at some relevant event 212 * 213 * Streaming trace, from startup (can only be used with certain stream ports): 214 * <board startup> 215 * xTraceInitialize(); 216 * <RTOS startup> 217 * xTraceEnable(TRC_START); 218 * 219 * Streaming trace, from startup: 220 * <board init> 221 * xTraceEnable(TRC_START_AWAIT_HOST); // Blocks! 222 * <RTOS init> 223 * 224 * Streaming trace, from a later point: 225 * <board startup> 226 * xTraceInitialize(); 227 * <RTOS startup> 228 * xTraceEnable(TRC_START); 229 * 230 * Streaming trace, system executes normally until host starts tracing: 231 * <board startup> 232 * xTraceInitialize(); 233 * <RTOS startup> 234 * xTraceEnable(TRC_START_FROM_HOST) 235 * 236 * @param[in] uiStartOption Start option. 237 * 238 * @retval TRC_FAIL Failure 239 * @retval TRC_SUCCESS Success 240 */ 241 traceResult xTraceEnable(uint32_t uiStartOption); 242 243 /** 244 * @brief Disables tracing. 245 * 246 * @retval TRC_FAIL Failure 247 * @retval TRC_SUCCESS Success 248 */ 249 traceResult xTraceDisable(void); 250 251 /** 252 * @brief 253 * 254 * For snapshot mode only: Sets the "filter group" to assign when creating 255 * RTOS objects, such as tasks, queues, semaphores and mutexes. This together 256 * with vTraceSetFilterMask allows you to control what events that are recorded, 257 * based on the objects they refer to. 258 * 259 * There are 16 filter groups named FilterGroup0 .. FilterGroup15. 260 * 261 * Note: We don't recommend filtering out the Idle task, so make sure to call 262 * vTraceSetFilterGroup just before initializing the RTOS, in order to assign 263 * such "default" objects to the right Filter Group (typically group 0). 264 * 265 * Example: 266 * 267 * // Assign tasks T1 to FilterGroup0 (default) 268 * <Create Task T1> 269 * 270 * // Assign Q1 and Q2 to FilterGroup1 271 * vTraceSetFilterGroup(FilterGroup1); 272 * <Create Queue Q1> 273 * <Create Queue Q2> 274 * 275 * // Assigns Q3 to FilterGroup2 276 * vTraceSetFilterGroup(FilterGroup2); 277 * <Create Queue Q3> 278 * 279 * // Only include FilterGroup0 and FilterGroup2, exclude FilterGroup1 (Q1 and Q2) from the trace 280 * vTraceSetFilterMask( FilterGroup0 | FilterGroup2 ); 281 * 282 * // Assign the default RTOS objects (e.g. Idle task) to FilterGroup0 283 * vTraceSetFilterGroup(FilterGroup0); 284 * <Start the RTOS scheduler> 285 * 286 * Note that you may define your own names for the filter groups using 287 * preprocessor definitions, to make the code easier to understand. 288 * 289 * Example: 290 * 291 * #define BASE FilterGroup0 292 * #define USB_EVENTS FilterGroup1 293 * #define CAN_EVENTS FilterGroup2 294 * 295 * Note that filtering per event type (regardless of object) is also available 296 * in trcKernelPortConfig.h for certain kernels. 297 * 298 * @param[in] filterGroup Filter group 299 */ 300 void vTraceSetFilterGroup(uint16_t filterGroup); 301 302 /** 303 * @brief 304 * 305 * For snapshot mode only: Sets the "filter mask" that is used to filter 306 * the events by object. This can be used to reduce the trace data rate, i.e., 307 * if your streaming interface is a bottleneck or if you want longer snapshot 308 * traces without increasing the buffer size. 309 * 310 * Note: There are two kinds of filters in the recorder. The other filter type 311 * excludes all events of certain kinds (e.g., OS ticks). See trcConfig.h. 312 * 313 * The filtering is based on bitwise AND with the Filter Group ID, assigned 314 * to RTOS objects such as tasks, queues, semaphores and mutexes. 315 * This together with vTraceSetFilterGroup allows you to control what 316 * events that are recorded, based on the objects they refer to. 317 * 318 * See example for vTraceSetFilterGroup. 319 * 320 * @param[in] filterMask Filter mask 321 */ 322 void vTraceSetFilterMask(uint16_t filterMask); 323 324 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) 325 326 #include <stdarg.h> 327 328 /** 329 * @brief Returns lower 16 bits of a value 330 * 331 * @param[in] value The starting value 332 */ 333 #define TRACE_GET_LOW16(value) ((uint16_t)((value) & 0x0000FFFF)) 334 335 /** 336 * @brief Returns upper 16 bits 337 * 338 * @param[in] value The starting value 339 */ 340 #define TRACE_GET_HIGH16(value) ((uint16_t)(((value) >> 16) & 0x0000FFFF)) 341 342 /** 343 * @brief Sets lower 16 bits 344 * 345 * @param[in] current The starting value 346 * @param[in] value The value to set 347 */ 348 #define TRACE_SET_LOW16(current, value) (((current) & 0xFFFF0000) | (value)) 349 350 /** 351 * @brief Sets upper 16 bits 352 * 353 * @param[in] current The starting value 354 * @param[in] value The value to set 355 */ 356 #define TRACE_SET_HIGH16(current, value) (((current) & 0x0000FFFF) | (((uint32_t)(value)) << 16)) 357 358 #if defined (TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) 359 /** 360 * @brief Adds a task to the stack monitor 361 * 362 * @param[in] task The task 363 */ 364 void prvAddTaskToStackMonitor(void* task); 365 366 /** 367 * @brief Remove a task from the stack monitor 368 * 369 * @param[in] task The task 370 */ 371 void prvRemoveTaskFromStackMonitor(void* task); 372 373 /** 374 * @brief Reports on the current stack usage 375 */ 376 void prvReportStackUsage(void); 377 378 #else /* defined (TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) */ 379 380 #define prvAddTaskToStackMonitor(task) 381 #define prvRemoveTaskFromStackMonitor(task) 382 #define prvReportStackUsage() 383 384 #endif /* defined (TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) */ 385 386 /** 387 * @internal Deprecated - Registers an ISR 388 */ 389 traceHandle xTraceSetISRProperties(const char* szName, uint8_t uiPriority); 390 391 /** 392 * @brief 393 * 394 * Registers an ISR. 395 * 396 * Example: 397 * #define PRIO_ISR_TIMER1 3 // the hardware priority of the interrupt 398 * ... 399 * TraceISRHandle_t Timer1Handle; 400 * xTraceISRRegister("ISRTimer1", PRIO_ISR_TIMER1, &Timer1Handle); 401 * 402 * @param[in] szName ISR name 403 * @param[in] uiPriority ISR priority 404 * @param[in] pxISRHandle 405 * 406 * @retval TRC_FAIL Failure 407 * @retval TRC_SUCCESS Success 408 */ 409 traceResult xTraceISRRegister(const char* szName, uint32_t uiPriority, TraceISRHandle_t* pxISRHandle); 410 411 /** 412 * @brief 413 * 414 * Registers the beginning of an Interrupt Service Routine, using a TraceISRHandle_t 415 * provided by xTraceISRRegister. 416 * 417 * Example: 418 * #define PRIO_ISR_TIMER1 3 // the hardware priority of the interrupt 419 * ... 420 * TraceISRHandle_t Timer1Handle; 421 * xTraceISRRegister("ISRTimer1", PRIO_ISR_TIMER1, &Timer1Handle); 422 * ... 423 * void ISR_handler() 424 * { 425 * xTraceISRBegin(Timer1Handle); 426 * ... 427 * xTraceISREnd(0); 428 * } 429 * 430 * @param[in] xHandle Handle for the previously registered ISR 431 * 432 * @retval TRC_FAIL Failure 433 * @retval TRC_SUCCESS Success 434 */ 435 traceResult xTraceISRBegin(TraceISRHandle_t xHandle); 436 437 #define vTraceStoreISRBegin(__handle) (void)xTraceISRBegin((TraceISRHandle_t)(__handle)) 438 439 /** 440 * @brief 441 * 442 * Registers the end of an Interrupt Service Routine. 443 * 444 * The parameter pendingISR indicates if the interrupt has requested a 445 * task-switch (= 1), e.g., by signaling a semaphore. Otherwise (= 0) the 446 * interrupt is assumed to return to the previous context. 447 * 448 * Example: 449 * #define PRIO_ISR_TIMER1 3 // the hardware priority of the interrupt 450 * ... 451 * TraceISRHandle_t Timer1Handle; 452 * xTraceISRRegister("ISRTimer1", PRIO_ISR_TIMER1, &Timer1Handle); 453 * ... 454 * void ISR_handler() 455 * { 456 * xTraceISRBegin(Timer1Handle); 457 * ... 458 * xTraceISREnd(0); 459 * } 460 * 461 * @param[in] pendingISR Flag that indicates whether an ISR is pending 462 * 463 * @retval TRC_FAIL Failure 464 * @retval TRC_SUCCESS Success 465 */ 466 traceResult xTraceISREnd(int pendingISR); 467 468 #define vTraceStoreISREnd(__pendingISR) (void)xTraceISREnd(__pendingISR) 469 470 /** 471 * @brief Query if recorder is enabled 472 * 473 * @retval 1 if recorder is enabled 474 * @retval 0 if recorder is disabled 475 */ 476 uint32_t xTraceIsRecorderEnabled(void); 477 478 /** 479 * @brief 480 * 481 * @retval 1 if recorder is initialized 482 * @retval 0 if recorder isn't initialized 483 */ 484 uint32_t xTraceIsRecorderInitialized(void); 485 486 /** 487 * @brief 488 * 489 * Creates an event that ends the current task instance at this very instant. 490 * This makes the viewer to splits the current fragment at this point and begin 491 * a new actor instance, even if no task-switch has occurred. 492 * 493 * @retval TRC_FAIL Failure 494 * @retval TRC_SUCCESS Success 495 */ 496 traceResult xTraceTaskInstanceFinishedNow(void); 497 498 /** 499 * @brief 500 * 501 * Marks the current "task instance" as finished on the next kernel call. 502 * 503 * If that kernel call is blocking, the instance ends after the blocking event 504 * and the corresponding return event is then the start of the next instance. 505 * If the kernel call is not blocking, the viewer instead splits the current 506 * fragment right before the kernel call, which makes this call the first event 507 * of the next instance. 508 * 509 * @retval TRC_FAIL Failure 510 * @retval TRC_SUCCESS Success 511 */ 512 traceResult xTraceTaskInstanceFinishedNext(void); 513 514 /** 515 * @brief Registers a string and returns a handle that can be used when tracing 516 * 517 * @param[in] label Label 518 * @param[out] pxString String handle 519 * 520 * @retval TRC_FAIL Failure 521 * @retval TRC_SUCCESS Success 522 */ 523 traceResult xTraceStringRegister(const char* label, TraceStringHandle_t* pxString); 524 525 /** 526 * @brief Registers a string and returns a handle that can be used when tracing 527 * 528 * @deprecated Backwards compatibility 529 * 530 * @param[in] name Name. 531 * 532 * @return TraceStringHandle_t String handle 533 */ 534 TraceStringHandle_t xTraceRegisterString(const char* name); 535 536 #if (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) 537 /** 538 * @brief 539 * 540 * Generates "User Events", with formatted text and data, similar to a "printf". 541 * User Events can be used for very efficient logging from your application code. 542 * It is very fast since the actual string formatting is done on the host side, 543 * when the trace is displayed. The execution time is just some microseconds on 544 * a 32-bit MCU. 545 * 546 * User Events are shown as yellow labels in the main trace view of $PNAME. 547 * 548 * An advantage of User Events is that data can be plotted in the "User Event 549 * Signal Plot" view, visualizing any data you log as User Events, discrete 550 * states or control system signals (e.g. system inputs or outputs). 551 * 552 * You may group User Events into User Event Channels. The yellow User Event 553 * labels show the logged string, preceded by the channel name within brackets. 554 * 555 * Example: 556 * 557 * "[MyChannel] Hello World!" 558 * 559 * The User Event Channels are shown in the View Filter, which makes it easy to 560 * select what User Events you wish to display. User Event Channels are created 561 * using xTraceStringRegister(). 562 * 563 * Example: 564 * 565 * TraceStringHandle_t adc_uechannel; 566 * xTraceStringRegister("ADC User Events", &adc_uechannel); 567 * ... 568 * xTracePrintF(adc_uechannel, 569 * "ADC channel %d: %d volts", 570 * ch, adc_reading); 571 * 572 * The following format specifiers are supported in both modes: 573 * %d - signed integer. 574 * %u - unsigned integer. 575 * %X - hexadecimal, uppercase. 576 * %x - hexadecimal, lowercase. 577 * %s - string (see comment below) 578 * 579 * For integer formats (%d, %u, %x, %X) you may also use width and padding. 580 * If using -42 as data argument, two examples are: 581 * "%05d" -> "-0042" 582 * "%5d" -> " -42". 583 * 584 * String arguments are supported in both snapshot and streaming, but in streaming 585 * mode you need to use xTraceStringRegister and use the returned TraceStringHandle_t as 586 * the argument. In snapshot you simply provide a char* as argument. 587 * 588 * Snapshot: xTracePrintF(myChn, "my string: %s", str); 589 * Streaming: xTracePrintF(myChn, "my string: %s", strTraceString); 590 * 591 * In snapshot mode you can specify 8-bit or 16-bit arguments to reduce RAM usage: 592 * %hd -> 16 bit (h) signed integer (d). 593 * %bu -> 8 bit (b) unsigned integer (u). 594 * 595 * However, in streaming mode all data arguments are assumed to be 32 bit wide. 596 * Width specifiers (e.g. %hd) are accepted but ignored (%hd treated like %d). 597 * 598 * The maximum event size also differs between the modes. In streaming this is 599 * limited by a maximum payload size of 52 bytes, including format string and 600 * data arguments. So if using one data argument, the format string is limited 601 * to 48 byte, etc. If this is exceeded, the format string is truncated and you 602 * get a warning in Tracealyzer. 603 * 604 * In snapshot mode you are limited to maximum 15 arguments, that must not exceed 605 * 32 bytes in total (not counting the format string). If exceeded, the recorder 606 * logs an internal error (displayed when opening the trace) and stops recording. 607 * 608 * @param[in] chn Channel. 609 * @param[in] fmt Formatting. 610 * @param[in] ... 611 * 612 * @retval TRC_FAIL Failure 613 * @retval TRC_SUCCESS Success 614 */ 615 traceResult xTracePrintF(TraceStringHandle_t chn, const char* fmt, ...); 616 #else 617 #define xTracePrintF(chn, fmt, ...) ((void)(chn), (void)(fmt), TRC_SUCCESS) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */ 618 #endif 619 620 #if (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) 621 /** 622 * @brief 623 * 624 * xTracePrintF variant that accepts a va_list. 625 * See xTracePrintF documentation for further details. 626 * 627 * @param[in] eventLabel 628 * @param[in] formatStr 629 * @param[in] vl 630 * 631 * @retval TRC_FAIL Failure 632 * @retval TRC_SUCCESS Success 633 */ 634 traceResult xTraceVPrintF(TraceStringHandle_t eventLabel, const char* formatStr, va_list vl); 635 #else 636 #define xTraceVPrintF(chn, formatStr, vl) ((void)(chn), (void)(formatStr), (void)(vl), TRC_SUCCESS) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */ 637 #endif 638 639 #if (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) 640 /** 641 * @brief A faster version of xTracePrintF, that only allows for logging a string. 642 * 643 * Example: 644 * 645 * TraceStringHandle_t chn; 646 * xTraceStringRegister("MyChannel", &chn); 647 * ... 648 * xTracePrint(chn, "Hello World!"); 649 * 650 * @param[in] chn Channel. 651 * @param[in] str String. 652 * 653 * @retval TRC_FAIL Failure 654 * @retval TRC_SUCCESS Success 655 */ 656 traceResult xTracePrint(TraceStringHandle_t chn, const char* str); 657 #else 658 #define xTracePrint(chn, str) ((void)(chn), (void)(str), TRC_SUCCESS) 659 #endif 660 661 /******************************************************************************/ 662 /*** Extended API for Snapshot mode *******************************************/ 663 /******************************************************************************/ 664 665 /** 666 * @brief Trace stop callback type. 667 */ 668 typedef void(*TRACE_STOP_HOOK)(void); 669 670 /** 671 * @brief Sets a function to be called when the recorder is stopped. 672 * 673 * @note Snapshot mode only! 674 * 675 * @param[in] stopHookFunction 676 */ 677 void vTraceSetStopHook(TRACE_STOP_HOOK stopHookFunction); 678 679 /** 680 * @brief 681 * 682 * Resets the recorder. 683 * 684 * Only necessary if a restart is desired - this is not 685 * needed in the startup initialization. 686 * 687 * @note Snapshot mode only! 688 */ 689 void vTraceClear(void); 690 691 /*****************************************************************************/ 692 /*** INTERNAL SNAPSHOT FUNCTIONS *********************************************/ 693 /*****************************************************************************/ 694 695 #define TRC_UNUSED 696 697 #ifndef TRC_CFG_INCLUDE_OBJECT_DELETE 698 #define TRC_CFG_INCLUDE_OBJECT_DELETE 0 699 #endif 700 701 #ifndef TRC_CFG_INCLUDE_READY_EVENTS 702 #define TRC_CFG_INCLUDE_READY_EVENTS 1 703 #endif 704 705 #ifndef TRC_CFG_INCLUDE_OSTICK_EVENTS 706 #define TRC_CFG_INCLUDE_OSTICK_EVENTS 0 707 #endif 708 709 /* This macro will create a task in the object table */ 710 #undef trcKERNEL_HOOKS_TASK_CREATE 711 #define trcKERNEL_HOOKS_TASK_CREATE(SERVICE, CLASS, pxTCB) \ 712 if ((pxTCB) != 0) \ 713 { \ 714 TRACE_SET_OBJECT_NUMBER(TASK, pxTCB); \ 715 TRACE_SET_OBJECT_FILTER(TASK, pxTCB, CurrentFilterGroup); \ 716 prvTraceSetObjectName(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_GET_TASK_NAME(pxTCB)); \ 717 prvTraceSetPriorityProperty(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_GET_TASK_PRIORITY(pxTCB)); \ 718 if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ 719 if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \ 720 prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)); \ 721 } \ 722 else \ 723 { \ 724 /* pxTCB is null */ \ 725 if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ 726 { \ 727 prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, 0); \ 728 } \ 729 } 730 731 /* This macro will remove the task and store it in the event buffer */ 732 #undef trcKERNEL_HOOKS_TASK_DELETE 733 #define trcKERNEL_HOOKS_TASK_DELETE(SERVICE, SERVICE_NAME, SERVICE_PROP, pxTCB) \ 734 if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ 735 if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \ 736 prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)); \ 737 prvTraceStoreObjectNameOnCloseEvent(SERVICE_NAME, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_CLASS_TASK); \ 738 prvTraceStoreObjectPropertiesOnCloseEvent(SERVICE_PROP, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_CLASS_TASK); \ 739 prvTraceSetPriorityProperty(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_GET_TASK_PRIORITY(pxTCB)); \ 740 prvTraceSetObjectState(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TASK_STATE_INSTANCE_NOT_ACTIVE); \ 741 prvTraceFreeObjectHandle(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)); 742 743 744 /* This macro will setup a task in the object table */ 745 #undef trcKERNEL_HOOKS_OBJECT_CREATE 746 #define trcKERNEL_HOOKS_OBJECT_CREATE(SERVICE, CLASS, pxObject) \ 747 TRACE_SET_OBJECT_NUMBER(CLASS, pxObject); \ 748 TRACE_SET_OBJECT_FILTER(CLASS, pxObject, CurrentFilterGroup); \ 749 prvMarkObjectAsUsed(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject));\ 750 if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ 751 if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \ 752 prvTraceStoreKernelCall(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject)); \ 753 prvTraceSetObjectState(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), 0); 754 755 /* This macro will setup a task in the object table */ 756 #undef trcKERNEL_HOOKS_OBJECT_CREATE_FAILED 757 #define trcKERNEL_HOOKS_OBJECT_CREATE_FAILED(SERVICE, TRACE_CLASS)\ 758 if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ 759 { \ 760 prvTraceStoreKernelCall(SERVICE, TRACE_CLASS, 0); \ 761 } 762 763 /* This macro will remove the object and store it in the event buffer */ 764 #undef trcKERNEL_HOOKS_OBJECT_DELETE 765 #define trcKERNEL_HOOKS_OBJECT_DELETE(SERVICE, SERVICE_NAME, SERVICE_PROP, CLASS, pxObject) \ 766 if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ 767 if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \ 768 prvTraceStoreKernelCall(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject)); \ 769 prvTraceStoreObjectNameOnCloseEvent(SERVICE_NAME, TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject)); \ 770 prvTraceStoreObjectPropertiesOnCloseEvent(SERVICE_PROP, TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject)); \ 771 prvTraceFreeObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject)); 772 773 /* This macro will create a call to a kernel service with a certain result, with an object as parameter */ 774 #undef trcKERNEL_HOOKS_KERNEL_SERVICE 775 #define trcKERNEL_HOOKS_KERNEL_SERVICE(SERVICE, CLASS, pxObject) \ 776 if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ 777 if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \ 778 prvTraceStoreKernelCall(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject)); 779 780 /* This macro will create a call to a kernel service with a certain result, with a null object as parameter */ 781 #undef trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT 782 #define trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT(SERVICE, TRACECLASS) \ 783 if (TRACE_GET_TASK_FILTER(TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ 784 prvTraceStoreKernelCall(SERVICE, TRACECLASS, 0); 785 786 /* This macro will create a call to a kernel service with a certain result, with an object as parameter */ 787 #undef trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM 788 #define trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(SERVICE, CLASS, pxObject, param) \ 789 if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ 790 if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \ 791 prvTraceStoreKernelCallWithParam(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), (uint32_t)param); 792 793 /* This macro will create a call to a kernel service with a certain result, with a null object and other value as parameter */ 794 #undef trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT_WITH_PARAM 795 #define trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT_WITH_PARAM(SERVICE, TRACECLASS, param) \ 796 if (TRACE_GET_TASK_FILTER(TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ 797 prvTraceStoreKernelCallWithParam(SERVICE, TRACECLASS, 0, param); 798 799 /* This macro will create a call to a kernel service with a certain result, with an object as parameter */ 800 #undef trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY 801 #define trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY(SERVICE, param) \ 802 if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ 803 prvTraceStoreKernelCallWithNumericParamOnly(SERVICE, (uint32_t)param); 804 805 /* This macro will create a call to a kernel service with a certain result, with an object as parameter */ 806 #undef trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR 807 #define trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR(SERVICE, CLASS, pxObject) \ 808 if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \ 809 prvTraceStoreKernelCall(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject)); 810 811 /* This macro will create a call to a kernel service with a certain result, with a null object as parameter */ 812 #undef trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT_FROM_ISR 813 #define trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT_FROM_ISR(SERVICE, TRACECLASS) \ 814 prvTraceStoreKernelCall(SERVICE, TRACECLASS, 0); 815 816 /* This macro will create a call to a kernel service with a certain result, with an object as parameter */ 817 #undef trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM_FROM_ISR 818 #define trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM_FROM_ISR(SERVICE, CLASS, pxObject, param) \ 819 if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \ 820 prvTraceStoreKernelCallWithParam(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), (uint32_t)param); 821 822 /* This macro will create a call to a kernel service with a certain result, with a null object and other value as parameter */ 823 #undef trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT_WITH_PARAM_FROM_ISR 824 #define trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT_WITH_PARAM_FROM_ISR(SERVICE, TRACECLASS, param) \ 825 prvTraceStoreKernelCallWithParam(SERVICE, TRACECLASS, 0, param); 826 827 /* This macro will create a call to a kernel service with a certain result, with an object as parameter */ 828 #undef trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY_FROM_ISR 829 #define trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY_FROM_ISR(SERVICE, param) \ 830 prvTraceStoreKernelCallWithNumericParamOnly(SERVICE, (uint32_t)param); 831 832 /* This macro will set the state for an object */ 833 #undef trcKERNEL_HOOKS_SET_OBJECT_STATE 834 #define trcKERNEL_HOOKS_SET_OBJECT_STATE(CLASS, pxObject, STATE) \ 835 prvTraceSetObjectState(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), (uint8_t)STATE); 836 837 /* This macro will flag a certain task as a finished instance */ 838 #undef trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED 839 #define trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED() \ 840 if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ 841 prvTraceSetTaskInstanceFinished(TRACE_GET_TASK_NUMBER(TRACE_GET_CURRENT_TASK())); 842 843 #if (TRC_CFG_INCLUDE_READY_EVENTS == 1) 844 /* This macro will create an event to indicate that a task became Ready */ 845 #undef trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE 846 #define trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE(pxTCB) \ 847 if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \ 848 prvTraceStoreTaskReady(TRACE_GET_TASK_NUMBER(pxTCB)); 849 #else /*(TRC_CFG_INCLUDE_READY_EVENTS == 1)*/ 850 #undef trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE 851 #define trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE(pxTCB) 852 #endif /*(TRC_CFG_INCLUDE_READY_EVENTS == 1)*/ 853 854 /* This macro will update the internal tick counter and call prvTracePortGetTimeStamp(0) to update the internal counters */ 855 #undef trcKERNEL_HOOKS_INCREMENT_TICK 856 #define trcKERNEL_HOOKS_INCREMENT_TICK() \ 857 { \ 858 extern uint32_t uiTraceTickCount; \ 859 uiTraceTickCount++; \ 860 prvTracePortGetTimeStamp(0); \ 861 } 862 863 #if (TRC_CFG_INCLUDE_OSTICK_EVENTS == 1) 864 /* This macro will create an event indicating that the OS tick count has increased */ 865 #undef trcKERNEL_HOOKS_NEW_TIME 866 #define trcKERNEL_HOOKS_NEW_TIME(SERVICE, xValue) \ 867 prvTraceStoreKernelCallWithNumericParamOnly(SERVICE, xValue); 868 #else /*(TRC_CFG_INCLUDE_OSTICK_EVENTS == 1)*/ 869 #undef trcKERNEL_HOOKS_NEW_TIME 870 #define trcKERNEL_HOOKS_NEW_TIME(SERVICE, xValue) 871 #endif /*(TRC_CFG_INCLUDE_OSTICK_EVENTS == 1)*/ 872 873 /* This macro will create a task switch event to the currently executing task */ 874 #undef trcKERNEL_HOOKS_TASK_SWITCH 875 #define trcKERNEL_HOOKS_TASK_SWITCH( pxTCB ) \ 876 if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \ 877 prvTraceStoreTaskswitch(TRACE_GET_TASK_NUMBER(pxTCB)); 878 879 /* This macro will create an event to indicate that the task has been suspended */ 880 #undef trcKERNEL_HOOKS_TASK_SUSPEND 881 #define trcKERNEL_HOOKS_TASK_SUSPEND(SERVICE, pxTCB) \ 882 if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ 883 if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \ 884 prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)); \ 885 prvTraceSetTaskInstanceFinished((uint8_t)TRACE_GET_TASK_NUMBER(pxTCB)); 886 887 /* This macro will create an event to indicate that a task has called a wait/delay function */ 888 #undef trcKERNEL_HOOKS_TASK_DELAY 889 #define trcKERNEL_HOOKS_TASK_DELAY(SERVICE, pxTCB, xValue) \ 890 if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \ 891 { \ 892 prvTraceStoreKernelCallWithNumericParamOnly(SERVICE, xValue); \ 893 prvTraceSetTaskInstanceFinished((uint8_t)TRACE_GET_TASK_NUMBER(pxTCB)); \ 894 } 895 896 /* This macro will create an event to indicate that a task has gotten its priority changed */ 897 #undef trcKERNEL_HOOKS_TASK_PRIORITY_CHANGE 898 #define trcKERNEL_HOOKS_TASK_PRIORITY_CHANGE(SERVICE, pxTCB, uxNewPriority) \ 899 if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \ 900 { \ 901 prvTraceStoreKernelCallWithParam(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), prvTraceGetPriorityProperty(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)));\ 902 prvTraceSetPriorityProperty(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), (uint8_t)uxNewPriority); \ 903 } 904 905 /* This macro will create an event to indicate that the task has been resumed */ 906 #undef trcKERNEL_HOOKS_TASK_RESUME 907 #define trcKERNEL_HOOKS_TASK_RESUME(SERVICE, pxTCB) \ 908 if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ 909 if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \ 910 prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)); 911 912 /* This macro will create an event to indicate that the task has been resumed from ISR */ 913 #undef trcKERNEL_HOOKS_TASK_RESUME_FROM_ISR 914 #define trcKERNEL_HOOKS_TASK_RESUME_FROM_ISR(SERVICE, pxTCB) \ 915 if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \ 916 prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)); 917 918 #if !defined TRC_CFG_INCLUDE_READY_EVENTS || TRC_CFG_INCLUDE_READY_EVENTS == 1 919 /** 920 * @brief Dynamically enables ready events 921 * 922 * @param[in] flag Flag 923 */ 924 void prvTraceSetReadyEventsEnabled(uint32_t flag); 925 926 /** 927 * @brief Stores a Task Ready event 928 * 929 * @param[in] handle Task handle 930 */ 931 void prvTraceStoreTaskReady(traceHandle handle); 932 #else 933 #define prvTraceSetReadyEventsEnabled(status) (void)status; 934 #endif 935 936 /** 937 * @brief Stores a Low Power mode event 938 * 939 * @param[in] flag Flag 940 */ 941 void prvTraceStoreLowPower(uint32_t flag); 942 943 /** 944 * @brief Stores a Task Switch event 945 * 946 * @param[in] task_handle Task 947 */ 948 void prvTraceStoreTaskswitch(traceHandle task_handle); 949 950 #if (TRC_CFG_SCHEDULING_ONLY == 0) 951 952 /** 953 * @brief Stores a Kernel Service call event with an Object handle parameter 954 * 955 * @param[in] eventcode Event code 956 * @param[in] objectClass Object class 957 * @param[in] objectNumber Object handle 958 */ 959 void prvTraceStoreKernelCall(uint32_t eventcode, traceObjectClass objectClass, uint32_t objectNumber); 960 961 /** 962 * @brief Stores a Kernel Service call event with only a numeric parameter 963 * 964 * @param[in] evtcode Event code 965 * @param[in] param Parameter 966 */ 967 void prvTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint32_t param); 968 969 /** 970 * @brief Stores a Kernel Service call event with an Object handle and a numeric parameter 971 * 972 * @param[in] evtcode Event code 973 * @param[in] objectClass Object class 974 * @param[in] objectNumber Object handle 975 * @param[in] param Parameter 976 */ 977 void prvTraceStoreKernelCallWithParam(uint32_t evtcode, traceObjectClass objectClass, 978 uint32_t objectNumber, uint32_t param); 979 #else 980 981 #define prvTraceStoreKernelCall(eventcode, objectClass, byteParam) {} 982 #define prvTraceStoreKernelCallWithNumericParamOnly(evtcode, param) {} 983 #define prvTraceStoreKernelCallWithParam(evtcode, objectClass, objectNumber, param) {} 984 985 #endif 986 987 /** 988 * @brief Flags a task instance as finished 989 * 990 * @param[in] handle Task handle 991 */ 992 void prvTraceSetTaskInstanceFinished(traceHandle handle); 993 994 /** 995 * @brief Set priority 996 * 997 * @param[in] objectclass Object class 998 * @param[in] id Object handle 999 * @param[in] value Value 1000 */ 1001 void prvTraceSetPriorityProperty(uint8_t objectclass, traceHandle id, uint8_t value); 1002 1003 /** 1004 * @brief Get priority 1005 * 1006 * @param[in] objectclass Object class 1007 * @param[in] id Object handle 1008 * 1009 * @return uint8_t Value 1010 */ 1011 uint8_t prvTraceGetPriorityProperty(uint8_t objectclass, traceHandle id); 1012 1013 /** 1014 * @brief Set object state 1015 * 1016 * @param[in] objectclass Object class 1017 * @param[in] id Object handle 1018 * @param[in] value Value 1019 */ 1020 void prvTraceSetObjectState(uint8_t objectclass, traceHandle id, uint8_t value); 1021 1022 /** 1023 * @brief Mark object as used 1024 * 1025 * @param[in] objectclass Object class 1026 * @param[in] handle Object handle 1027 */ 1028 void prvMarkObjectAsUsed(traceObjectClass objectclass, traceHandle handle); 1029 1030 /** 1031 * @brief Stores the name of an object because it is being deleted 1032 * 1033 * @param[in] evtcode Event code 1034 * @param[in] handle Object handle 1035 * @param[in] objectclass Object class 1036 */ 1037 void prvTraceStoreObjectNameOnCloseEvent(uint8_t evtcode, traceHandle handle, 1038 traceObjectClass objectclass); 1039 1040 /** 1041 * @brief Stores the property of an object because it is being deleted 1042 * 1043 * @param[in] evtcode Event code 1044 * @param[in] handle Object handle 1045 * @param[in] objectclass Object class 1046 */ 1047 void prvTraceStoreObjectPropertiesOnCloseEvent(uint8_t evtcode, traceHandle handle, 1048 traceObjectClass objectclass); 1049 1050 /* Internal constants for task state */ 1051 #define TASK_STATE_INSTANCE_NOT_ACTIVE 0 1052 #define TASK_STATE_INSTANCE_ACTIVE 1 1053 1054 1055 #if (TRC_CFG_INCLUDE_ISR_TRACING == 0) 1056 1057 #undef vTraceSetISRProperties 1058 #define vTraceSetISRProperties(handle, name, priority) (void)(handle), (void)(name), (void)(priority) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */ 1059 1060 #undef vTraceStoreISRBegin 1061 #define vTraceStoreISRBegin(x) (void)(x) 1062 1063 #undef vTraceStoreISREnd 1064 #define vTraceStoreISREnd(x) (void)(x) 1065 1066 #undef xTraceSetISRProperties 1067 #define xTraceSetISRProperties(name, priority) ((void)(name), (void)(priority), (traceHandle)0) /* Comma operator in parenthesis is used to avoid "unused variable" compiler warnings and return 0 in a single statement */ 1068 1069 #endif /*(TRC_CFG_INCLUDE_ISR_TRACING == 0)*/ 1070 1071 /** 1072 * @brief 1073 * 1074 * Returns a pointer to the recorder data structure. Use this together with 1075 * uiTraceGetTraceBufferSize if you wish to implement an own store/upload 1076 * solution, e.g., in case a debugger connection is not available for uploading 1077 * the data. 1078 * 1079 * @return void* Buffer pointer 1080 */ 1081 void* xTraceGetTraceBuffer(void); 1082 1083 /** 1084 * @brief 1085 * 1086 * Gets the size of the recorder data structure. For use together with 1087 * xTraceGetTraceBuffer if you wish to implement an own store/upload solution, 1088 * e.g., in case a debugger connection is not available for uploading the data. 1089 * 1090 * @return uint32_t Buffer size 1091 */ 1092 uint32_t uiTraceGetTraceBufferSize(void); 1093 1094 #if (TRC_CFG_SCHEDULING_ONLY == 1) 1095 #undef TRC_CFG_INCLUDE_USER_EVENTS 1096 #define TRC_CFG_INCLUDE_USER_EVENTS 0 1097 #endif /*(TRC_CFG_SCHEDULING_ONLY == 1)*/ 1098 1099 #if ((TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_SCHEDULING_ONLY == 0)) && (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1) 1100 1101 /** 1102 * @brief Register a channel and fixed format string for use with the separate User Event Buffer functions 1103 * 1104 * @param[in] channel Channel name handle 1105 * @param[in] formatStr Format string that will be used for all events on this channel 1106 * 1107 * @return traceUBChannel Channel handle 1108 */ 1109 traceUBChannel xTraceRegisterUBChannel(TraceStringHandle_t channel, TraceStringHandle_t formatStr); 1110 1111 /** 1112 * @brief Creates a User Event using the channel, previously set format string and data parameters 1113 * 1114 * @param[in] channel Channel 1115 * @param[in] ... 1116 */ 1117 void vTraceUBData(traceUBChannel channel, ...); 1118 1119 /** 1120 * @brief Creates a User Event using the channel and previously set string 1121 * 1122 * @param[in] channel Channel 1123 */ 1124 void vTraceUBEvent(traceUBChannel channel); 1125 #else 1126 #define xTraceRegisterChannelFormat(eventLabel, formatStr) ((void)(eventLabel), (void)(formatStr), 0) 1127 #define vTraceUBData(label, ...) (void)(label) 1128 #endif /*(TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1)*/ 1129 1130 #define NEventCodes 0x100 1131 1132 /* Our local critical sections for the recorder */ 1133 #define trcCRITICAL_SECTION_BEGIN() {TRACE_ENTER_CRITICAL_SECTION(); recorder_busy++;} 1134 #define trcCRITICAL_SECTION_END() {recorder_busy--; TRACE_EXIT_CRITICAL_SECTION();} 1135 1136 #if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_Cortex_M) 1137 #define trcSR_ALLOC_CRITICAL_SECTION_ON_CORTEX_M_ONLY TRACE_ALLOC_CRITICAL_SECTION 1138 #define trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY trcCRITICAL_SECTION_BEGIN 1139 #define trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY trcCRITICAL_SECTION_END 1140 #else 1141 #define trcSR_ALLOC_CRITICAL_SECTION_ON_CORTEX_M_ONLY() {} 1142 #define trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY() recorder_busy++; 1143 #define trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY() recorder_busy--; 1144 #endif 1145 1146 /** 1147 * @brief Object handle stack struct. 1148 * 1149 * This data-structure is used to provide a mechanism for 1-byte trace object 1150 * handles. This way, only 1 byte is necessary instead of 4 bytes (a pointer) 1151 * when storing a reference to an object. This allows for up to 255 objects of 1152 * each object class active at any given moment. There can be more "historic" 1153 * objects, that have been deleted - that number is only limited by the size of 1154 * the symbol table. 1155 * 1156 * Note that handle zero (0) is not used, it is a code for an invalid handle. 1157 * 1158 * This data structure keeps track of the FREE handles, not the handles in use. 1159 * This data structure contains one stack per object class. When a handle is 1160 * allocated to an object, the next free handle is popped from the stack. When 1161 * a handle is released (on object delete), it is pushed back on the stack. 1162 * Note that there is no initialization code that pushed the free handles 1163 * initially, that is not necessary due to the following optimization: 1164 * 1165 * The stack of handles (objectHandles) is initially all zeros. Since zero 1166 * is not a valid handle, that is a signal of additional handles needed. 1167 * If a zero is received when popping a new handle, it is replaced by the 1168 * index of the popped handle instead. 1169 */ 1170 typedef struct 1171 { 1172 uint16_t indexOfNextAvailableHandle[ TRACE_NCLASSES ]; /**< For each object class, the index of the next handle to allocate */ 1173 uint16_t lowestIndexOfClass[ TRACE_NCLASSES ]; /**< The lowest index of this class (constant) */ 1174 uint16_t highestIndexOfClass[ TRACE_NCLASSES ]; /**< The highest index of this class (constant) */ 1175 uint16_t handleCountWaterMarksOfClass[ TRACE_NCLASSES ]; /**< The highest use count for this class (for statistics) */ 1176 traceHandle objectHandles[ TRACE_KERNEL_OBJECT_COUNT ]; /**< The free object handles - a set of stacks within this array */ 1177 } objectHandleStackType; 1178 1179 extern objectHandleStackType objectHandleStacks; 1180 1181 /** 1182 * @brief Object property table struct 1183 * 1184 * The Object Table contains name and other properties of the objects (tasks, 1185 * queues, mutexes, etc). The below data structures defines the properties of 1186 * each object class and are used to cast the byte buffer into a cleaner format. 1187 * 1188 * The values in the object table are continuously overwritten and always 1189 * represent the current state. If a property is changed during runtime, the OLD 1190 * value should be stored in the trace buffer, not the new value (since the new 1191 * value is found in the Object Property Table). 1192 * 1193 * For close events this mechanism is the old names are stored in the symbol 1194 * table), for "priority set" (the old priority is stored in the event data) 1195 * and for "isActive", where the value decides if the task switch event type 1196 * should be "new" or "resume". 1197 */ 1198 typedef struct 1199 { 1200 /* = NCLASSES */ 1201 uint32_t NumberOfObjectClasses; /**< */ 1202 uint32_t ObjectPropertyTableSizeInBytes; /**< */ 1203 1204 /* This is used to calculate the index in the dynamic object table 1205 (handle - 1 - nofStaticObjects = index)*/ 1206 #if (TRC_CFG_USE_16BIT_OBJECT_HANDLES == 1) 1207 traceHandle NumberOfObjectsPerClass[2*((TRACE_NCLASSES+1)/2)]; /** */ 1208 #else 1209 traceHandle NumberOfObjectsPerClass[4*((TRACE_NCLASSES+3)/4)]; /** */ 1210 #endif 1211 /* Allocation size rounded up to the closest multiple of 4 */ 1212 uint8_t NameLengthPerClass[ 4*((TRACE_NCLASSES+3)/4) ]; /**< */ 1213 1214 /* Allocation size rounded up to the closest multiple of 2 */ 1215 uint8_t TotalPropertyBytesPerClass[ 4*((TRACE_NCLASSES+3)/4) ]; /**< */ 1216 1217 /* */ 1218 uint16_t StartIndexOfClass[ 2*((TRACE_NCLASSES+1)/2) ]; /**< */ 1219 1220 /* The actual handles issued, should be Initiated to all zeros */ 1221 uint8_t objbytes[ 4*((TRACE_OBJECT_TABLE_SIZE+3)/4) ]; /**< */ 1222 } ObjectPropertyTableType; 1223 1224 /** 1225 * @brief Symbol table structure 1226 */ 1227 typedef struct 1228 { 1229 /* = SYMBOL_HISTORY_TABLE_SIZE_IN_BYTES */ 1230 uint32_t symTableSize; /**< */ 1231 1232 /* Entry 0 is reserved. Any reference to entry 0 implies NULL*/ 1233 uint32_t nextFreeSymbolIndex; /**< */ 1234 1235 /* Size rounded up to closest multiple of 4, to avoid alignment issues*/ 1236 uint8_t symbytes[4*(((TRC_CFG_SYMBOL_TABLE_SIZE)+3)/4)]; /**< */ 1237 1238 /* Used for lookups - Up to 64 linked lists within the symbol table 1239 connecting all entries with the same 6 bit checksum. 1240 This field holds the current list heads. Should be initiated to zeros */ 1241 uint16_t latestEntryOfChecksum[64]; /**< */ 1242 } symbolTableType; 1243 1244 1245 /******************************************************************************* 1246 * The data structures of the different events, all 4 bytes long 1247 ******************************************************************************/ 1248 1249 typedef struct 1250 { 1251 uint8_t type; 1252 uint8_t objHandle; 1253 uint16_t dts; /* differential timestamp - time since last event */ 1254 } TSEvent, TREvent; 1255 1256 typedef struct 1257 { 1258 uint8_t type; 1259 uint8_t dummy; 1260 uint16_t dts; /* differential timestamp - time since last event */ 1261 } LPEvent; 1262 1263 typedef struct 1264 { 1265 uint8_t type; 1266 uint8_t objHandle; 1267 uint16_t dts; /* differential timestamp - time since last event */ 1268 } KernelCall; 1269 1270 typedef struct 1271 { 1272 uint8_t type; 1273 uint8_t objHandle; 1274 uint8_t param; 1275 uint8_t dts; /* differential timestamp - time since last event */ 1276 } KernelCallWithParamAndHandle; 1277 1278 typedef struct 1279 { 1280 uint8_t type; 1281 uint8_t dts; /* differential timestamp - time since last event */ 1282 uint16_t param; 1283 } KernelCallWithParam16; 1284 1285 typedef struct 1286 { 1287 uint8_t type; 1288 uint8_t objHandle; /* the handle of the closed object */ 1289 uint16_t symbolIndex; /* the name of the closed object */ 1290 } ObjCloseNameEvent; 1291 1292 typedef struct 1293 { 1294 uint8_t type; 1295 uint8_t arg1; 1296 uint8_t arg2; 1297 uint8_t arg3; 1298 } ObjClosePropEvent; 1299 1300 typedef struct 1301 { 1302 uint8_t type; 1303 uint8_t unused1; 1304 uint8_t unused2; 1305 uint8_t dts; 1306 } TaskInstanceStatusEvent; 1307 1308 typedef struct 1309 { 1310 uint8_t type; 1311 uint8_t dts; 1312 uint16_t payload; /* the name of the user event */ 1313 } UserEvent; 1314 1315 typedef struct 1316 { 1317 uint8_t type; 1318 1319 /* 8 bits extra for storing DTS, if it does not fit in ordinary event 1320 (this one is always MSB if used) */ 1321 uint8_t xts_8; 1322 1323 /* 16 bits extra for storing DTS, if it does not fit in ordinary event. */ 1324 uint16_t xts_16; 1325 } XTSEvent; 1326 1327 typedef struct 1328 { 1329 uint8_t type; 1330 1331 uint8_t xps_8; 1332 uint16_t xps_16; 1333 } XPSEvent; 1334 1335 typedef struct{ 1336 uint8_t type; 1337 uint8_t dts; 1338 uint16_t size; 1339 } MemEventSize; 1340 1341 typedef struct{ 1342 uint8_t type; 1343 uint8_t addr_high; 1344 uint16_t addr_low; 1345 } MemEventAddr; 1346 1347 /******************************************************************************* 1348 * The separate user event buffer structure. Can be enabled in trcConfig.h. 1349 ******************************************************************************/ 1350 1351 #if (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1) 1352 typedef struct 1353 { 1354 TraceStringHandle_t name; 1355 TraceStringHandle_t defaultFormat; 1356 } ChannelFormatPair; 1357 1358 typedef struct 1359 { 1360 uint16_t bufferID; 1361 uint16_t version; 1362 uint32_t wraparoundCounter; 1363 uint32_t numberOfSlots; 1364 uint32_t nextSlotToWrite; 1365 uint8_t numberOfChannels; 1366 uint8_t padding1; 1367 uint8_t padding2; 1368 uint8_t padding3; 1369 ChannelFormatPair channels[(TRC_CFG_UB_CHANNELS)+1]; 1370 uint8_t channelBuffer[((TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE) + 3) & 0xFFFFFFFC]; /* 1 byte per slot, with padding for 4 byte alignment */ 1371 uint8_t dataBuffer[(TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE) * 4]; /* 4 bytes per slot */ 1372 1373 } UserEventBuffer; 1374 #endif /* (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1) */ 1375 1376 /******************************************************************************* 1377 * The main data structure, read by Tracealyzer from the RAM dump 1378 ******************************************************************************/ 1379 1380 typedef struct 1381 { 1382 volatile uint8_t startmarker0; /* Volatile is important, see init code. */ 1383 volatile uint8_t startmarker1; 1384 volatile uint8_t startmarker2; 1385 volatile uint8_t startmarker3; 1386 volatile uint8_t startmarker4; 1387 volatile uint8_t startmarker5; 1388 volatile uint8_t startmarker6; 1389 volatile uint8_t startmarker7; 1390 volatile uint8_t startmarker8; 1391 volatile uint8_t startmarker9; 1392 volatile uint8_t startmarker10; 1393 volatile uint8_t startmarker11; 1394 1395 /* Used to determine Kernel and Endianess */ 1396 uint16_t version; 1397 1398 /* Currently 7 */ 1399 uint8_t minor_version; 1400 1401 /* This should be 0 if lower IRQ priority values implies higher priority 1402 levels, such as on ARM Cortex M. If the opposite scheme is used, i.e., 1403 if higher IRQ priority values means higher priority, this should be 1. */ 1404 uint8_t irq_priority_order; 1405 1406 /* sizeof(RecorderDataType) - just for control */ 1407 uint32_t filesize; 1408 1409 /* Current number of events recorded */ 1410 uint32_t numEvents; 1411 1412 /* The buffer size, in number of event records */ 1413 uint32_t maxEvents; 1414 1415 /* The event buffer index, where to write the next event */ 1416 uint32_t nextFreeIndex; 1417 1418 /* 1 if the buffer is full, 0 otherwise */ 1419 uint32_t bufferIsFull; 1420 1421 /* The frequency of the clock/timer/counter used as time base */ 1422 uint32_t frequency; 1423 1424 /* The absolute timestamp of the last stored event, in the native 1425 timebase, modulo frequency! */ 1426 uint32_t absTimeLastEvent; 1427 1428 /* The number of seconds in total - lasts for 136 years */ 1429 uint32_t absTimeLastEventSecond; 1430 1431 /* 1 if the recorder has been started, 0 if not yet started or stopped. 1432 This is a 32 bit variable due to alignment issues. */ 1433 uint32_t recorderActive; 1434 1435 /* If > 0, tells the maximum time between two traced ISRs that execute 1436 back-to-back. If the time between vTraceStoreISREnd and a directly 1437 following vTraceISRBegin is above isrTailchainingThreshold, we assume a 1438 return to the previous context in between the ISRs, otherwise we assume 1439 the have executed back-to-back and don't show any fragment of the previous 1440 context in between. */ 1441 uint32_t isrTailchainingThreshold; 1442 1443 /* The maximum amount of heap memory that was allocated */ 1444 uint32_t heapMemMaxUsage; 1445 1446 /* The amount of heap memory used */ 1447 uint32_t heapMemUsage; 1448 1449 /* 0xF0F0F0F0 - for control only */ 1450 int32_t debugMarker0; 1451 1452 /* Set to value of TRC_CFG_USE_16BIT_OBJECT_HANDLES */ 1453 uint32_t isUsing16bitHandles; 1454 1455 /* The Object Property Table holds information about currently active 1456 tasks, queues, and other recorded objects. This is updated on each 1457 create call and includes object name and other properties. */ 1458 ObjectPropertyTableType ObjectPropertyTable; 1459 1460 /* 0xF1F1F1F1 - for control only */ 1461 int32_t debugMarker1; 1462 1463 /* The Symbol Table stores strings for User Events and is also used to 1464 store names of deleted objects, which still may be in the trace but no 1465 longer are available. */ 1466 symbolTableType SymbolTable; 1467 1468 /* For inclusion of float support, and for endian detection of floats. 1469 The value should be (float)1 or (uint32_t)0 */ 1470 #if (TRC_CFG_INCLUDE_FLOAT_SUPPORT == 1) 1471 float exampleFloatEncoding; 1472 #else 1473 uint32_t exampleFloatEncoding; 1474 #endif 1475 /* This is non-zero if an internal error occurred in the recorder, e.g., if 1476 one of the Nxxx constants was too small. The systemInfo string will then 1477 contain an error message that is displayed when attempting to view the 1478 trace file. */ 1479 uint32_t internalErrorOccured; 1480 1481 /* 0xF2F2F2F2 - for control only */ 1482 int32_t debugMarker2; 1483 1484 /* Error messages from the recorder. */ 1485 char systemInfo[80]; 1486 1487 /* 0xF3F3F3F3 - for control only */ 1488 int32_t debugMarker3; 1489 1490 /* The event data, in 4-byte records */ 1491 uint8_t eventData[ (TRC_CFG_EVENT_BUFFER_SIZE) * 4 ]; 1492 1493 #if (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1) 1494 UserEventBuffer userEventBuffer; 1495 #endif 1496 1497 /* This should always be 0 */ 1498 uint32_t endOfSecondaryBlocks; 1499 1500 uint8_t endmarker0; 1501 uint8_t endmarker1; 1502 uint8_t endmarker2; 1503 uint8_t endmarker3; 1504 uint8_t endmarker4; 1505 uint8_t endmarker5; 1506 uint8_t endmarker6; 1507 uint8_t endmarker7; 1508 uint8_t endmarker8; 1509 uint8_t endmarker9; 1510 uint8_t endmarker10; 1511 uint8_t endmarker11; 1512 } RecorderDataType; 1513 1514 extern RecorderDataType* RecorderDataPtr; 1515 1516 /* Internal functions */ 1517 1518 /** 1519 * @brief Signals a trace error 1520 * 1521 * @param[in] msg Message 1522 */ 1523 void prvTraceError(const char* msg); 1524 1525 /** 1526 * @brief 1527 * 1528 * Returns the current time based on the HWTC macros which provide a hardware 1529 * isolation layer towards the hardware timer/counter. 1530 * 1531 * The HWTC macros and prvTracePortGetTimeStamp is the main porting issue 1532 * or the trace recorder library. Typically you should not need to change 1533 * the code of prvTracePortGetTimeStamp if using the HWTC macros. 1534 * 1535 * @param[out] puiTimestamp Timestamp 1536 */ 1537 void prvTracePortGetTimeStamp(uint32_t *puiTimestamp); 1538 1539 /** 1540 * @brief Reserve an object handle 1541 * 1542 * @param[in] objectclass Object class 1543 * 1544 * @return traceHandle 1545 */ 1546 traceHandle prvTraceGetObjectHandle(traceObjectClass objectclass); 1547 1548 /** 1549 * @brief Free an object handle 1550 * 1551 * @param[in] objectclass Object class 1552 * @param[in] handle Handle 1553 */ 1554 void prvTraceFreeObjectHandle(traceObjectClass objectclass, 1555 traceHandle handle); 1556 1557 /* Private function. Use the public functions in trcKernelPort.h */ 1558 1559 /** 1560 * @brief Set the object name 1561 * 1562 * @param[in] objectclass Object class 1563 * @param[in] handle Handle 1564 * @param[in] name Name 1565 */ 1566 void prvTraceSetObjectName(traceObjectClass objectclass, 1567 traceHandle handle, 1568 const char* name); 1569 1570 /* Internal macros */ 1571 1572 #define TRACE_PROPERTY_NAME_GET(objectclass, objecthandle) \ 1573 (const char*)(& RecorderDataPtr->ObjectPropertyTable.objbytes \ 1574 [uiIndexOfObject(objecthandle, objectclass)]) 1575 1576 #define TRACE_PROPERTY_OBJECT_STATE(objectclass, handle) \ 1577 RecorderDataPtr->ObjectPropertyTable.objbytes[uiIndexOfObject(handle, objectclass) \ 1578 + RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[objectclass]] 1579 1580 #define TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, handle) \ 1581 RecorderDataPtr->ObjectPropertyTable.objbytes[uiIndexOfObject(handle, objectclass) \ 1582 + RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[objectclass] + 1] 1583 1584 /* DEBUG ASSERTS */ 1585 #if defined TRC_CFG_USE_TRACE_ASSERT && TRC_CFG_USE_TRACE_ASSERT != 0 1586 #define TRACE_ASSERT(eval, msg, defRetVal) \ 1587 if (!(eval)) \ 1588 { \ 1589 prvTraceError("TRACE_ASSERT: " msg); \ 1590 return defRetVal; \ 1591 } 1592 #else 1593 #define TRACE_ASSERT(eval, msg, defRetVal) 1594 #endif 1595 1596 typedef RecorderDataType TraceRecorderDataBuffer_t; 1597 1598 #endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)*/ 1599 1600 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) 1601 1602 #ifndef TRC_EXTERNAL_BUFFERS 1603 #define TRC_EXTERNAL_BUFFERS 0 1604 #endif 1605 1606 typedef struct TraceRecorderData 1607 { 1608 uint32_t uiSessionCounter; 1609 uint32_t uiRecorderEnabled; 1610 uint32_t uiTraceSystemState; 1611 1612 TraceAssertBuffer_t xAssertBuffer; 1613 #if (TRC_EXTERNAL_BUFFERS == 0) 1614 TraceHeaderBuffer_t xHeaderBuffer; 1615 TraceEntryTableBuffer_t xEntryTableBuffer; 1616 TraceTimestampBuffer_t xTimestampBuffer; 1617 #endif 1618 TraceStreamPortBuffer_t xStreamPortBuffer; 1619 TraceStaticBufferBuffer_t xStaticBufferBuffer; 1620 TraceEventDataBuffer_t xEventDataBuffer; 1621 TracePrintBuffer_t xPrintBuffer; 1622 TraceErrorBuffer_t xErrorBuffer; 1623 TraceISRInfoBuffer_t xISRInfoBuffer; 1624 TraceKernelPortDataBuffer_t xKernelPortBuffer; 1625 TraceTaskInfoBuffer_t xTaskInfoBuffer; 1626 TraceStackMonitorBuffer_t xStackMonitorBuffer; 1627 TraceDiagnosticsBuffer_t xDiagnosticsBuffer; 1628 } TraceRecorderData_t; 1629 1630 extern TraceRecorderData_t* pxTraceRecorderData; 1631 extern uint32_t RecorderInitialized; 1632 1633 #define TRC_RECORDER_DATA_BUFFER_SIZE (sizeof(TraceRecorderData_t)) 1634 1635 typedef struct TraceRecorderDataBuffer 1636 { 1637 uint8_t buffer[(TRC_RECORDER_DATA_BUFFER_SIZE)]; 1638 } TraceRecorderDataBuffer_t; 1639 1640 /** 1641 * @brief Initializes the header data 1642 * 1643 * @param[in] pxBuffer Pointer to header buffer 1644 * 1645 * @retval TRC_FAIL Failure 1646 * @retval TRC_SUCCESS Success 1647 */ 1648 traceResult xTraceHeaderInitialize(TraceHeaderBuffer_t* pxBuffer); 1649 1650 /** 1651 * @brief Query if recorder is enabled 1652 * 1653 * @retval 1 Recorder enabled 1654 * @retval 0 Recorder not enabled 1655 */ 1656 #define xTraceIsRecorderEnabled() (xTraceIsRecorderInitialized() & pxTraceRecorderData->uiRecorderEnabled) 1657 1658 /** 1659 * @brief Query if recorder initialized 1660 * 1661 * @retval 1 Recorder initialized 1662 * @retval 0 Recorder not initialized 1663 */ 1664 #define xTraceIsRecorderInitialized() xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_CORE) 1665 1666 /** 1667 * @brief Flag component as initialized 1668 * 1669 * @param[in] uiComponentBit Component bit 1670 * 1671 * @retval TRC_FAIL Failure 1672 * @retval TRC_SUCCESS Success 1673 */ 1674 #define xTraceSetComponentInitialized(uiComponentBit) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(RecorderInitialized |= (uiComponentBit), TRC_SUCCESS) 1675 1676 /** 1677 * @brief Query if component is initialized 1678 * 1679 * @param[in] uiComponentBit Component bit 1680 * 1681 * @retval 1 Component initialized 1682 * @retval 0 Component not initialized 1683 */ 1684 #define xTraceIsComponentInitialized(uiComponentBit) ((RecorderInitialized & (uiComponentBit)) ? 1 : 0) 1685 1686 /** 1687 * @brief Set the trace state 1688 * 1689 * @param[in] uiState State 1690 * 1691 * @retval TRC_FAIL Failure 1692 * @retval TRC_SUCCESS Success 1693 */ 1694 #define xTraceStateSet(uiState) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(pxTraceRecorderData->uiTraceSystemState = (uiState), TRC_SUCCESS) 1695 1696 /** 1697 * @brief Query the trace state 1698 * 1699 * @param[out] puiState State 1700 * 1701 * @retval TRC_FAIL Failure 1702 * @retval TRC_SUCCESS Success 1703 */ 1704 #define xTraceStateGet(puiState) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(*(puiState) = pxTraceRecorderData->uiTraceSystemState, TRC_SUCCESS) 1705 1706 /** 1707 * @brief Call this function periodically 1708 * 1709 * @retval TRC_FAIL Failure 1710 * @retval TRC_SUCCESS Success 1711 */ 1712 traceResult xTraceTzCtrl(void); 1713 1714 /******************************************************************************/ 1715 /*** INTERNAL STREAMING FUNCTIONS *********************************************/ 1716 /******************************************************************************/ 1717 1718 /** 1719 * @brief Stores an event without parameters 1720 * 1721 * @param[in] _eventID Event id 1722 */ 1723 #define prvTraceStoreEvent_None(_eventID) \ 1724 { \ 1725 TraceEventHandle_t _xEventHandle = 0; \ 1726 if (xTraceEventBegin(_eventID, 0, &_xEventHandle) == TRC_SUCCESS) \ 1727 { \ 1728 xTraceEventEnd(_xEventHandle); \ 1729 } \ 1730 } 1731 1732 /** 1733 * @brief Stores an event with a handle parameter 1734 * 1735 * @param[in] _eventID Event id 1736 * @param[in] _handle Handle 1737 */ 1738 #define prvTraceStoreEvent_Handle(_eventID, _handle) \ 1739 { \ 1740 TraceEventHandle_t _xEventHandle = 0; \ 1741 if (xTraceEventBegin(_eventID, sizeof(void*), &_xEventHandle) == TRC_SUCCESS) \ 1742 { \ 1743 xTraceEventAddPointer(_xEventHandle, (void*)(_handle)); \ 1744 xTraceEventEnd(_xEventHandle); \ 1745 } \ 1746 } 1747 1748 /** 1749 * @brief Stores an event with one 32-bit parameter 1750 * 1751 * @param[in] _eventID Event id 1752 * @param[in] _param1 Param 1753 */ 1754 #define prvTraceStoreEvent_Param(_eventID, _param1) \ 1755 { \ 1756 TraceEventHandle_t _xEventHandle = 0; \ 1757 if (xTraceEventBegin(_eventID, sizeof(uint32_t), &_xEventHandle) == TRC_SUCCESS) \ 1758 { \ 1759 xTraceEventAdd32(_xEventHandle, (uint32_t)(_param1)); \ 1760 xTraceEventEnd(_xEventHandle); \ 1761 } \ 1762 } 1763 1764 /** 1765 * @brief Stores an event with a handle and one 32-bit parameter 1766 * 1767 * @param[in] _eventID Event id 1768 * @param[in] _handle Handle 1769 * @param[in] _param1 Param 1770 */ 1771 #define prvTraceStoreEvent_HandleParam(_eventID, _handle, _param1) \ 1772 { \ 1773 TraceEventHandle_t _xEventHandle = 0; \ 1774 if (xTraceEventBegin(_eventID, sizeof(void*) + sizeof(uint32_t), &_xEventHandle) == TRC_SUCCESS) \ 1775 { \ 1776 xTraceEventAddPointer(_xEventHandle, (void*)(_handle)); \ 1777 xTraceEventAdd32(_xEventHandle, (uint32_t)(_param1)); \ 1778 xTraceEventEnd(_xEventHandle); \ 1779 } \ 1780 } 1781 1782 /** 1783 * @brief Stores an event with two 32-bit parameters 1784 * 1785 * @param[in] _eventID Event id 1786 * @param[in] _param1 Param 1 1787 * @param[in] _param2 Param 2 1788 */ 1789 #define prvTraceStoreEvent_ParamParam(_eventID, _param1, _param2) \ 1790 { \ 1791 TraceEventHandle_t _xEventHandle = 0; \ 1792 if (xTraceEventBegin(_eventID, sizeof(uint32_t) + sizeof(uint32_t), &_xEventHandle) == TRC_SUCCESS) \ 1793 { \ 1794 xTraceEventAdd32(_xEventHandle, (uint32_t)(_param1)); \ 1795 xTraceEventAdd32(_xEventHandle, (uint32_t)(_param2)); \ 1796 xTraceEventEnd(_xEventHandle); \ 1797 } \ 1798 } 1799 1800 /** 1801 * @brief Stores an event with a handle and two 32-bit parameters 1802 * 1803 * @param[in] _eventID Event id 1804 * @param[in] _handle Handle 1805 * @param[in] _param1 Param 1 1806 * @param[in] _param2 Param 2 1807 */ 1808 #define prvTraceStoreEvent_HandleParamParam(_eventID, _handle, _param1, _param2) \ 1809 { \ 1810 TraceEventHandle_t _xEventHandle = 0; \ 1811 if (xTraceEventBegin(_eventID, sizeof(void*) + sizeof(uint32_t) + sizeof(uint32_t), &_xEventHandle) == TRC_SUCCESS) \ 1812 { \ 1813 xTraceEventAddPointer(_xEventHandle, (void*)(_handle)); \ 1814 xTraceEventAdd32(_xEventHandle, (uint32_t)(_param1)); \ 1815 xTraceEventAdd32(_xEventHandle, (uint32_t)(_param2)); \ 1816 xTraceEventEnd(_xEventHandle); \ 1817 } \ 1818 } 1819 1820 /** 1821 * @brief Stores an event with three 32-bit parameters 1822 * 1823 * @param[in] _eventID Event id 1824 * @param[in] _param1 Param 1 1825 * @param[in] _param2 Param 2 1826 * @param[in] _param3 Param 3 1827 */ 1828 #define prvTraceStoreEvent_ParamParamParam(_eventID, _param1, _param2, _param3) \ 1829 { \ 1830 TraceEventHandle_t _xEventHandle = 0; \ 1831 if (xTraceEventBegin(_eventID, sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t), &_xEventHandle) == TRC_SUCCESS) \ 1832 { \ 1833 xTraceEventAdd32(_xEventHandle, (uint32_t)(_param1)); \ 1834 xTraceEventAdd32(_xEventHandle, (uint32_t)(_param2)); \ 1835 xTraceEventAdd32(_xEventHandle, (uint32_t)(_param3)); \ 1836 xTraceEventEnd(_xEventHandle); \ 1837 } \ 1838 } 1839 1840 /** 1841 * @brief Snapshot mode only. Trace stop hook. 1842 * 1843 * @param[in] x 1844 */ 1845 #define vTraceSetStopHook(x) (void)(x) 1846 1847 /** 1848 * @brief Snapshot mode only. Initialize timestamps. 1849 */ 1850 #define vTraceInitTimestamps() 1851 1852 #endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/ 1853 1854 #if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM) 1855 /** 1856 * @brief Set the recorder data buffer 1857 * 1858 * @param[in] pxBuffer Pointer to the recorder data buffer 1859 * 1860 * @retval TRC_FAIL Failure 1861 * @retval TRC_SUCCESS Success 1862 */ 1863 traceResult xTraceSetBuffer(TraceRecorderDataBuffer_t *pxBuffer); 1864 #else 1865 #define xTraceSetBuffer(p) (TRC_SUCCESS) 1866 #endif 1867 1868 /** 1869 * @brief Retrieve the event buffer and event buffer size 1870 * 1871 * @param[out] ppvBuffer Pointer where event buffer pointer will be written 1872 * @param[out] puiSize Event buffer size 1873 * 1874 * @retval TRC_FAIL Failure 1875 * @retval TRC_SUCCESS Success 1876 */ 1877 traceResult xTraceGetEventBuffer(void** ppvBuffer, TraceUnsignedBaseType_t * puiSize); 1878 1879 #else /* when TRC_USE_TRACEALYZER_RECORDER == 0 */ 1880 1881 #define xTraceInitialize() (TRC_SUCCESS) 1882 #define xTraceEnable(x) ((void)(x), TRC_SUCCESS) 1883 #define xTraceDisable() (TRC_SUCCESS) 1884 #define xTraceStringRegister(x, y) ((void)(x), (void)y, TRC_SUCCESS) /* Comma operator in parenthesis is used to avoid "unused variable" compiler warnings and return 0 in a single statement */ 1885 #define xTracePrint(chn, ...) ((void)(chn), TRC_SUCCESS) 1886 #define xTracePrintF(chn, fmt, ...) ((void)(chn), (void)(fmt), TRC_SUCCESS) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */ 1887 #define xTraceVPrintF(chn, formatStr, vl) ((void)(chn), (void)(formatStr), (void)(vl), TRC_SUCCESS) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */ 1888 #define xTraceTaskInstanceFinishedNow() 1889 #define xTraceTaskInstanceFinishedNext() 1890 #define vTraceStoreISRBegin(x) (void)(x) 1891 #define vTraceStoreISREnd(x) (void)(x) 1892 #define xTraceSetISRProperties(a, b) ((void)(a), (void)(b), (traceHandle)0) /* Comma operator in parenthesis is used to avoid "unused variable" compiler warnings and return 0 in a single statement */ 1893 #define xTraceRegisterChannelFormat(eventLabel, formatStr) ((void)(eventLabel), (void)(formatStr), 0) /* Comma operator in parenthesis is used to avoid "unused variable" compiler warnings and return 0 in a single statement */ 1894 #define vTraceUBData(label, ...) (void)(label) 1895 1896 #define vTraceSetFilterGroup(x) (void)(x) 1897 #define vTraceSetFilterMask(x) (void)(x) 1898 1899 #define prvTraceSetReadyEventsEnabled(status) (void)(status) 1900 1901 #define vTraceExcludeTask(handle) (void)(handle) 1902 1903 #define vTraceConsoleChannelPrintF(fmt, ...) (void)(fmt) 1904 1905 #ifndef TRC_ALLOC_CUSTOM_BUFFER 1906 #define TRC_ALLOC_CUSTOM_BUFFER(bufname) 1907 #endif 1908 1909 #define xTraceIsRecorderEnabled() (0) 1910 #define xTraceIsRecorderInitialized() (0) 1911 1912 #define xTraceSetBuffer(p) (TRC_SUCCESS) 1913 #define xTraceGetEventBuffer(p) (TRC_FAIL) 1914 1915 #define vTraceSetStopHook(x) (void)(x) 1916 1917 #define TraceRecorderDataBuffer_t uint32_t 1918 1919 #endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ 1920 1921 /** 1922 * @deprecated Backwards compatibility. Use xTraceInitialize instead. 1923 */ 1924 #define vTraceInitialize (void)xTraceInitialize 1925 1926 /** 1927 * @deprecated Backwards compatibility. Use xTraceEnable instead. 1928 */ 1929 #define vTraceEnable (void)xTraceEnable 1930 1931 /** 1932 * @deprecated Backwards compatibility. Use xTraceDisable instead. 1933 */ 1934 #define vTraceStop (void)xTraceDisable 1935 1936 /** 1937 * @deprecated Backwards compatibility. Use xTraceTaskInstanceFinishedNow instead. 1938 */ 1939 #define vTraceInstanceFinishedNow (void)xTraceTaskInstanceFinishedNow 1940 1941 /** 1942 * @deprecated Backwards compatibility. Use xTraceTaskInstanceFinishedNext instead. 1943 */ 1944 #define vTraceInstanceFinishedNext (void)xTraceTaskInstanceFinishedNext 1945 1946 /** 1947 * @deprecated Backwards compatibility. Use xTracePrintF instead. 1948 */ 1949 #define vTracePrintF (void)xTracePrintF 1950 1951 /** 1952 * @deprecated Backwards compatibility. Use xTraceVPrintF instead. 1953 */ 1954 #define vTraceVPrintF (void)xTraceVPrintF 1955 1956 /** 1957 * @deprecated Backwards compatibility. Use xTracePrint instead. 1958 */ 1959 #define vTracePrint (void)xTracePrint 1960 1961 /** 1962 * @deprecated Backwards compatibility. Use xTraceSetBuffer instead. 1963 */ 1964 #define vTraceSetRecorderDataBuffer(pxBuffer) xTraceSetBuffer((TraceRecorderDataBuffer_t*)(pxBuffer)) 1965 1966 #ifdef __cplusplus 1967 } 1968 #endif 1969 1970 #endif /* TRC_RECORDER_H */ 1971