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