1 /*******************************************************************************
\r
2 * Tracealyzer v2.7.7 Recorder Library
\r
3 * Percepio AB, www.percepio.com
\r
6 * The public API of the trace recorder library.
\r
9 * This software is copyright Percepio AB. The recorder library is free for
\r
10 * use together with Percepio products. You may distribute the recorder library
\r
11 * in its original form, including modifications in trcHardwarePort.c/.h
\r
12 * given that these modification are clearly marked as your own modifications
\r
13 * and documented in the initial comment section of these source files.
\r
14 * This software is the intellectual property of Percepio AB and may not be
\r
15 * sold or in other ways commercially redistributed without explicit written
\r
16 * permission by Percepio AB.
\r
19 * The trace tool and recorder library is being delivered to you AS IS and
\r
20 * Percepio AB makes no warranty as to its use or performance. Percepio AB does
\r
21 * not and cannot warrant the performance or results you may obtain by using the
\r
22 * software or documentation. Percepio AB make no warranties, express or
\r
23 * implied, as to noninfringement of third party rights, merchantability, or
\r
24 * fitness for any particular purpose. In no event will Percepio AB, its
\r
25 * technology partners, or distributors be liable to you for any consequential,
\r
26 * incidental or special damages, including any lost profits or lost savings,
\r
27 * even if a representative of Percepio AB has been advised of the possibility
\r
28 * of such damages, or for any claim by any third party. Some jurisdictions do
\r
29 * not allow the exclusion or limitation of incidental, consequential or special
\r
30 * damages, or the exclusion of implied warranties or limitations on how long an
\r
31 * implied warranty may last, so the above limitations may not apply to you.
\r
33 * Tabs are used for indent in this file (1 tab = 4 spaces)
\r
35 * Copyright Percepio AB, 2012-2015.
\r
37 ******************************************************************************/
\r
46 #include "trcKernelPort.h"
\r
48 #if (USE_TRACEALYZER_RECORDER == 1)
\r
50 #ifndef USE_SEPARATE_USER_EVENT_BUFFER
\r
51 #define USE_SEPARATE_USER_EVENT_BUFFER 0
\r
54 /*******************************************************************************
\r
55 * TRACE_STOP_HOOK - Hook Pointer Data Type
\r
57 * Declares a data type for a call back function that will be invoked whenever
\r
58 * the recorder is stopped.
\r
59 ******************************************************************************/
\r
60 typedef void (*TRACE_STOP_HOOK)(void);
\r
62 /*******************************************************************************
\r
65 * Points to a call back function that is called from vTraceStop().
\r
66 ******************************************************************************/
\r
67 extern TRACE_STOP_HOOK vTraceStopHookPtr;
\r
69 /*******************************************************************************
\r
70 * vTraceInitTraceData
\r
72 * Allocates, if necessary, and initializes the recorder data structure, based
\r
73 * on the constants in trcConfig.h.
\r
74 ******************************************************************************/
\r
75 void vTraceInitTraceData(void);
\r
77 /*******************************************************************************
\r
78 * vTraceSetRecorderData
\r
80 * If custom allocation is used, this function must be called so the recorder
\r
81 * library knows where to save the trace data.
\r
82 ******************************************************************************/
\r
83 #if (TRACE_DATA_ALLOCATION == TRACE_DATA_ALLOCATION_CUSTOM)
\r
84 void vTraceSetRecorderData(void* pRecorderData);
\r
87 /*******************************************************************************
\r
90 * Sets a function to be called when the recorder is stopped.
\r
91 ******************************************************************************/
\r
92 void vTraceSetStopHook(TRACE_STOP_HOOK stopHookFunction);
\r
94 /*******************************************************************************
\r
97 * Starts the recorder. The recorder will not be started if an error has been
\r
98 * indicated using vTraceError, e.g. if any of the Nx constants in trcConfig.h
\r
99 * has a too small value (NTASK, NQUEUE, etc).
\r
101 * Returns 1 if the recorder was started successfully.
\r
102 * Returns 0 if the recorder start was prevented due to a previous internal
\r
103 * error. In that case, check vTraceGetLastError to get the error message.
\r
104 * Any error message is also presented when opening a trace file.
\r
106 ******************************************************************************/
\r
107 uint32_t uiTraceStart(void);
\r
109 /*******************************************************************************
\r
112 * Starts the recorder. The recorder will not be started if an error has been
\r
113 * indicated using vTraceError, e.g. if any of the Nx constants in trcConfig.h
\r
114 * has a too small value (NTASK, NQUEUE, etc).
\r
116 * This function is obsolete, but has been saved for backwards compatibility.
\r
117 * We recommend using uiTraceStart instead.
\r
118 ******************************************************************************/
\r
119 void vTraceStart(void);
\r
121 /*******************************************************************************
\r
124 * Stops the recorder. The recording can be resumed by calling vTraceStart.
\r
125 * This does not reset the recorder. Use vTraceClear is that is desired.
\r
126 ******************************************************************************/
\r
127 void vTraceStop(void);
\r
129 /*******************************************************************************
\r
130 * xTraceGetLastError
\r
132 * Gives the last error message, if any. NULL if no error message is stored.
\r
133 * Any error message is also presented when opening a trace file.
\r
134 ******************************************************************************/
\r
135 char* xTraceGetLastError(void);
\r
137 /*******************************************************************************
\r
140 * Resets the recorder. Only necessary if a restart is desired - this is not
\r
141 * needed in the startup initialization.
\r
142 ******************************************************************************/
\r
143 void vTraceClear(void);
\r
145 /*******************************************************************************
\r
148 * Removes any previous error message generated by recorder calling vTraceError.
\r
149 * By calling this function, it may be possible to start/restart the trace
\r
150 * despite errors in the recorder, but there is no guarantee that the trace
\r
151 * recorder will work correctly in that case, depending on the type of error.
\r
152 ******************************************************************************/
\r
153 void vTraceClearError(int resetErrorMessage);
\r
155 #if (INCLUDE_ISR_TRACING == 1)
\r
157 /*******************************************************************************
\r
158 * vTraceSetISRProperties
\r
160 * Registers an Interrupt Service Routine in the recorder library, This must be
\r
161 * called before using vTraceStoreISRBegin to store ISR events. This is
\r
162 * typically called in the startup of the system, before the scheduler is
\r
166 * #define ID_ISR_TIMER1 1 // lowest valid ID is 1
\r
167 * #define PRIO_OF_ISR_TIMER1 3 // the hardware priority of the interrupt
\r
169 * vTraceSetISRProperties(ID_ISR_TIMER1, "ISRTimer1", PRIO_OF_ISR_TIMER1);
\r
171 * void ISR_handler()
\r
173 * vTraceStoreISRBegin(ID_OF_ISR_TIMER1);
\r
175 * vTraceStoreISREnd(0);
\r
177 ******************************************************************************/
\r
178 void vTraceSetISRProperties(objectHandleType handle, const char* name, char priority);
\r
180 /*******************************************************************************
\r
181 * vTraceStoreISRBegin
\r
183 * Registers the beginning of an Interrupt Service Routine.
\r
184 * If allowing nested ISRs, this must be called with interrupts disabled.
\r
187 * #define ID_ISR_TIMER1 1 // lowest valid ID is 1
\r
188 * #define PRIO_OF_ISR_TIMER1 3 // the hardware priority of the interrupt
\r
190 * vTraceSetISRProperties(ID_ISR_TIMER1, "ISRTimer1", PRIO_OF_ISR_TIMER1);
\r
192 * void ISR_handler()
\r
194 * vTraceStoreISRBegin(ID_OF_ISR_TIMER1);
\r
196 * vTraceStoreISREnd(0);
\r
199 ******************************************************************************/
\r
200 void vTraceStoreISRBegin(objectHandleType id);
\r
202 /*******************************************************************************
\r
203 * vTraceStoreISREnd
\r
205 * Registers the end of an Interrupt Service Routine.
\r
207 * The parameter pendingISR indicates if the interrupt has requested a
\r
208 * task-switch (= 1) or if the interrupt returns to the earlier context (= 0)
\r
211 * #define ID_ISR_TIMER1 1 // lowest valid ID is 1
\r
212 * #define PRIO_OF_ISR_TIMER1 3 // the hardware priority of the interrupt
\r
214 * vTraceSetISRProperties(ID_ISR_TIMER1, "ISRTimer1", PRIO_OF_ISR_TIMER1);
\r
216 * void ISR_handler()
\r
218 * vTraceStoreISRBegin(ID_OF_ISR_TIMER1);
\r
220 * vTraceStoreISREnd(0);
\r
223 ******************************************************************************/
\r
224 void vTraceStoreISREnd(int pendingISR);
\r
227 /* If not including the ISR recording */
\r
229 void vTraceIncreaseISRActive(void);
\r
231 void vTraceDecreaseISRActive(void);
\r
233 #define vTraceSetISRProperties(handle, name, priority)
\r
234 #define vTraceStoreISRBegin(id) vTraceIncreaseISRActive()
\r
235 #define vTraceStoreISREnd() vTraceDecreaseISRActive()
\r
240 /******************************************************************************
\r
241 * vTraceTaskInstanceFinish(void)
\r
243 * Marks the current task instance as finished on the next kernel call.
\r
245 * If that kernel call is blocking, the instance ends after the blocking event
\r
246 * and the corresponding return event is then the start of the next instance.
\r
247 * If the kernel call is not blocking, the viewer instead splits the current
\r
248 * fragment right before the kernel call, which makes this call the first event
\r
249 * of the next instance.
\r
251 * See also USE_IMPLICIT_IFE_RULES in trcConfig.h
\r
257 * xQueueReceive(CommandQueue, &command, timeoutDuration);
\r
258 * processCommand(command);
\r
259 * vTraceInstanceFinish();
\r
262 *****************************************************************************/
\r
263 void vTraceTaskInstanceFinish(void);
\r
265 /******************************************************************************
\r
266 * vTraceTaskInstanceFinishDirect(void)
\r
268 * Marks the current task instance as finished at this very instant.
\r
269 * This makes the viewer to splits the current fragment at this point and begin
\r
270 * a new actor instance.
\r
272 * See also USE_IMPLICIT_IFE_RULES in trcConfig.h
\r
276 * This example will generate two instances for each loop iteration.
\r
277 * The first instance ends at vTraceInstanceFinishDirect(), while the second
\r
278 * instance ends at the next xQueueReceive call.
\r
282 * xQueueReceive(CommandQueue, &command, timeoutDuration);
\r
283 * ProcessCommand(command);
\r
284 * vTraceInstanceFinishDirect();
\r
285 * DoSometingElse();
\r
286 * vTraceInstanceFinish();
\r
290 *****************************************************************************/
\r
291 void vTraceTaskInstanceFinishDirect(void);
\r
293 /*******************************************************************************
\r
294 * vTraceGetTraceBuffer
\r
296 * Returns a pointer to the recorder data structure. Use this together with
\r
297 * uiTraceGetTraceBufferSize if you wish to implement an own store/upload
\r
298 * solution, e.g., in case a debugger connection is not available for uploading
\r
300 ******************************************************************************/
\r
301 void* vTraceGetTraceBuffer(void);
\r
303 /*******************************************************************************
\r
304 * uiTraceGetTraceBufferSize
\r
306 * Gets the size of the recorder data structure. For use together with
\r
307 * vTraceGetTraceBuffer if you wish to implement an own store/upload solution,
\r
308 * e.g., in case a debugger connection is not available for uploading the data.
\r
309 ******************************************************************************/
\r
310 uint32_t uiTraceGetTraceBufferSize(void);
\r
312 #if (INCLUDE_USER_EVENTS == 1)
\r
314 /*******************************************************************************
\r
317 * Creates user event labels for user event channels or for individual events.
\r
318 * User events can be used to log application events and data for display in
\r
319 * the visualization tool. A user event is identified by a label, i.e., a string,
\r
320 * which is stored in the recorder's symbol table.
\r
321 * When logging a user event, a numeric handle (reference) to this string is
\r
322 * used to identify the event. This is obtained by calling
\r
324 * xTraceOpenLabel()
\r
326 * whihc adds the string to the symbol table (if not already present)
\r
327 * and returns the corresponding handle.
\r
329 * This can be used in two ways:
\r
331 * 1. The handle is looked up every time, when storing the user event.
\r
334 * vTraceUserEvent(xTraceOpenLabel("MyUserEvent"));
\r
336 * 2. The label is registered just once, with the handle stored in an
\r
337 * application variable - much like using a file handle.
\r
340 * myEventHandle = xTraceOpenLabel("MyUserEvent");
\r
342 * vTraceUserEvent(myEventHandle);
\r
344 * The second option is faster since no lookup is required on each event, and
\r
345 * therefore recommended for user events that are frequently
\r
346 * executed and/or located in time-critical code. The lookup operation is
\r
347 * however fairly fast due to the design of the symbol table.
\r
348 ******************************************************************************/
\r
349 traceLabel xTraceOpenLabel(const char* label);
\r
351 /******************************************************************************
\r
354 * Basic user event (Standard and Professional Edition only)
\r
356 * Generates a User Event with a text label. The label is created/looked up
\r
357 * in the symbol table using xTraceOpenLabel.
\r
358 ******************************************************************************/
\r
359 void vTraceUserEvent(traceLabel eventLabel);
\r
361 /******************************************************************************
\r
364 * Advanced user events (Professional Edition only)
\r
366 * Generates User Event with formatted text and data, similar to a "printf".
\r
367 * It is very fast compared to a normal "printf" since this function only
\r
368 * stores the arguments. The actual formatting is done
\r
369 * on the host PC when the trace is displayed in the viewer tool.
\r
371 * User Event labels are created using xTraceOpenLabel.
\r
374 * traceLabel adc_uechannel = xTraceOpenLabel("ADC User Events");
\r
376 * vTracePrint(adc_uechannel,
\r
377 * "ADC channel %d: %lf volts",
\r
378 * ch, (double)adc_reading/(double)scale);
\r
380 * This can be combined into one line, if desired, but this is slower:
\r
382 * vTracePrint(xTraceOpenLabel("ADC User Events"),
\r
383 * "ADC channel %d: %lf volts",
\r
384 * ch, (double)adc_reading/(double)scale);
\r
386 * Calling xTraceOpenLabel multiple times will not create duplicate entries, but
\r
387 * it is of course faster to just do it once, and then keep the handle for later
\r
388 * use. If you donĀ“t have any data arguments, only a text label/string, it is
\r
389 * better to use vTraceUserEvent - it is faster.
\r
391 * Format specifiers supported:
\r
392 * %d - 32 bit signed integer
\r
393 * %u - 32 bit unsigned integer
\r
394 * %f - 32 bit float
\r
395 * %s - string (is copied to the recorder symbol table)
\r
396 * %hd - 16 bit signed integer
\r
397 * %hu - 16 bit unsigned integer
\r
398 * %bd - 8 bit signed integer
\r
399 * %bu - 8 bit unsigned integer
\r
400 * %lf - double-precision float (Note! See below...)
\r
402 * Up to 15 data arguments are allowed, with a total size of maximum 32 byte.
\r
403 * In case this is exceeded, the user event is changed into an error message.
\r
405 * The data is stored in trace buffer, and is packed to allow storing multiple
\r
406 * smaller data entries in the same 4-byte record, e.g., four 8-bit values.
\r
407 * A string requires two bytes, as the symbol table is limited to 64K. Storing
\r
408 * a double (%lf) uses two records, so this is quite costly. Use float (%f)
\r
409 * unless the higher precision is really necessary.
\r
411 * Note that the double-precision float (%lf) assumes a 64 bit double
\r
412 * representation. This does not seem to be the case on e.g. PIC24 and PIC32.
\r
413 * Before using a %lf argument on a 16-bit MCU, please verify that
\r
414 * "sizeof(double)" actually gives 8 as expected. If not, use %f instead.
\r
415 ******************************************************************************/
\r
416 void vTracePrintF(traceLabel eventLabel, const char* formatStr, ...);
\r
418 #if (USE_SEPARATE_USER_EVENT_BUFFER == 1)
\r
419 UserEventChannel xTraceRegisterChannelFormat(traceLabel channel, traceLabel formatStr);
\r
420 void vTraceChannelPrintF(UserEventChannel channel, ...);
\r
421 void vTraceChannelUserEvent(UserEventChannel channel);
\r
426 #define vTracePrintF(eventLabel, formatStr, ...);
\r
427 #define xTraceOpenLabel(label) 0
\r
428 #define vTraceUserEvent(eventLabel)
\r
434 /* Empty defines for user functions to avoid compiler errors if trace is not to be used */
\r
436 #define vTraceInitTraceData()
\r
437 #define uiTraceStart() (1) // Fake "success", if used when recorder is excluded from build
\r
438 #define vTraceStart()
\r
439 #define vTraceStop()
\r
440 #define vTraceClear()
\r
441 #define vTraceStartStatusMonitor()
\r
442 #define vTraceGetTraceBuffer() ((void*)0)
\r
443 #define uiTraceGetTraceBufferSize() 0
\r
444 #define xTraceOpenLabel(label) 0
\r
445 #define vTraceUserEvent(eventLabel)
\r
446 #define vTracePrintF(eventLabel,formatStr,...)
\r
447 #define vTraceExcludeTaskFromSchedulingTrace(name)
\r
449 #define vTraceSetISRProperties(handle, name, priority)
\r
450 #define vTraceStoreISRBegin(id)
\r
451 #define vTraceStoreISREnd(flag)
\r
452 #define vTraceExcludeTaskFromTrace(handle)
\r
453 #define vTraceSetQueueName(a, b)
\r
454 #define vTraceSetMutexName(a, b)
\r
455 #define vTraceSetSemaphoreName(a, b)
\r
456 #define vTraceSetEventGroupName(a, b)
\r
458 #define vTraceSetStopHook(a)
\r