trcBase.h
Go to the documentation of this file.
1 /*******************************************************************************
2  * Tracealyzer v3.0.2 Recorder Library
3  * Percepio AB, www.percepio.com
4  *
5  * trcBase.h
6  *
7  * Core functionality of the Tracealyzer recorder library.
8  *
9  * Terms of Use
10  * This software is copyright Percepio AB. The recorder library is free for
11  * use together with Percepio products. You may distribute the recorder library
12  * in its original form, including modifications in trcHardwarePort.c/.h
13  * given that these modification are clearly marked as your own modifications
14  * and documented in the initial comment section of these source files.
15  * This software is the intellectual property of Percepio AB and may not be
16  * sold or in other ways commercially redistributed without explicit written
17  * permission by Percepio AB.
18  *
19  * Disclaimer
20  * The trace tool and recorder library is being delivered to you AS IS and
21  * Percepio AB makes no warranty as to its use or performance. Percepio AB does
22  * not and cannot warrant the performance or results you may obtain by using the
23  * software or documentation. Percepio AB make no warranties, express or
24  * implied, as to noninfringement of third party rights, merchantability, or
25  * fitness for any particular purpose. In no event will Percepio AB, its
26  * technology partners, or distributors be liable to you for any consequential,
27  * incidental or special damages, including any lost profits or lost savings,
28  * even if a representative of Percepio AB has been advised of the possibility
29  * of such damages, or for any claim by any third party. Some jurisdictions do
30  * not allow the exclusion or limitation of incidental, consequential or special
31  * damages, or the exclusion of implied warranties or limitations on how long an
32  * implied warranty may last, so the above limitations may not apply to you.
33  *
34  * Tabs are used for indent in this file (1 tab = 4 spaces)
35  *
36  * Copyright Percepio AB, 2014.
37  * www.percepio.com
38  ******************************************************************************/
39 
40 #ifndef TRCBASE_H
41 #define TRCBASE_H
42 
43 #define TRACE_MINOR_VERSION 4
44 #define TRACE_STORE_MODE_STOP_WHEN_FULL 1
45 #define TRACE_STORE_MODE_RING_BUFFER 2
46 #define TRACE_DATA_ALLOCATION_STATIC 1
47 #define TRACE_DATA_ALLOCATION_DYNAMIC 2
48 #define TRACE_DATA_ALLOCATION_CUSTOM 3
49 
50 #include "trcKernelPort.h"
51 
52 #if (USE_TRACEALYZER_RECORDER == 1)
53 
54 #include <stdio.h>
55 #include <string.h>
56 
57 #ifndef USE_SEPARATE_USER_EVENT_BUFFER
58 #define USE_SEPARATE_USER_EVENT_BUFFER 0
59 #endif
60 
61 #ifndef TRACE_SR_ALLOC_CRITICAL_SECTION
62 #define TRACE_SR_ALLOC_CRITICAL_SECTION()
63 #endif
64 
65 /* Max number of event codes supported */
66 #define NEventCodes 0x100
67 
68 /* Keeps track of the recorder's critical sections */
69 extern volatile int recorder_busy;
70 
71 /* Our local critical sections for the recorder */
72 #define trcCRITICAL_SECTION_BEGIN() {TRACE_ENTER_CRITICAL_SECTION(); recorder_busy++;}
73 #define trcCRITICAL_SECTION_END() {recorder_busy--; TRACE_EXIT_CRITICAL_SECTION();}
74 
75 /* Structure to handle the exclude flags for all objects and tasks. We add some extra objects since index 0 is not used for each object class. */
76 extern uint8_t excludedObjects[(TRACE_KERNEL_OBJECT_COUNT + TRACE_NCLASSES) / 8 + 1];
77 
78 /* Structure to handle the exclude flags for all event codes */
79 extern uint8_t excludedEventCodes[NEventCodes / 8 + 1];
80 
81 /******************************************************************************
82  * ObjectHandleStack
83  * This data-structure is used to provide a mechanism for 1-byte trace object
84  * handles. This way, only 1 byte is necessary instead of 4 bytes (a pointer)
85  * when storing a reference to an object. This allows for up to 255 objects of
86  * each object class active at any given moment. There can be more "historic"
87  * objects, that have been deleted - that number is only limited by the size of
88  * the symbol table.
89  * Note that handle zero (0) is not used, it is a code for an invalid handle.
90  *
91  * This data structure keeps track of the FREE handles, not the handles in use.
92  * This data structure contains one stack per object class. When a handle is
93  * allocated to an object, the next free handle is popped from the stack. When
94  * a handle is released (on object delete), it is pushed back on the stack.
95  * Note that there is no initialization code that pushed the free handles
96  * initially, that is not necessary due to the following optimization:
97  *
98  * The stack of handles (objectHandles) is initially all zeros. Since zero
99  * is not a valid handle, that is a signal of additional handles needed.
100  * If a zero is received when popping a new handle, it is replaced by the
101  * index of the popped handle instead.
102  *
103  *****************************************************************************/
104 typedef struct
105 {
106  /* For each object class, the index of the next handle to allocate */
107  uint16_t indexOfNextAvailableHandle[ TRACE_NCLASSES ];
108 
109  /* The lowest index of this class (constant) */
110  uint16_t lowestIndexOfClass[ TRACE_NCLASSES ];
111 
112  /* The highest index of this class (constant) */
113  uint16_t highestIndexOfClass[ TRACE_NCLASSES ];
114 
115  /* The highest use count for this class (for statistics) */
116  uint16_t handleCountWaterMarksOfClass[ TRACE_NCLASSES ];
117 
118  /* The free object handles - a set of stacks within this array */
119  objectHandleType objectHandles[ TRACE_KERNEL_OBJECT_COUNT ];
120 
121 } objectHandleStackType;
122 
123 extern objectHandleStackType objectHandleStacks;
124 
125 /******************************************************************************
126  * Object Property Table
127  * The Object Table contains name and other properties of the objects (tasks,
128  * queues, mutexes, etc). The below data structures defines the properties of
129  * each object class and are used to cast the byte buffer into a cleaner format.
130  *
131  * The values in the object table are continuously overwritten and always
132  * represent the current state. If a property is changed during runtime, the OLD
133  * value should be stored in the trace buffer, not the new value (since the new
134  * value is found in the Object Property Table).
135  * For close events this mechanism is the old names are stored in the symbol
136  * table), for "priority set" (the old priority is stored in the event data)
137  * and for "isActive", where the value decides if the task switch event type
138  * should be "new" or "resume".
139  ******************************************************************************/
140 
141 typedef struct
142 {
143  /* = NCLASSES */
144  uint32_t NumberOfObjectClasses;
145 
146  uint32_t ObjectPropertyTableSizeInBytes;
147 
148  /* This is used to calculate the index in the dynamic object table
149  (handle - 1 - nofStaticObjects = index)*/
150 #if (USE_16BIT_OBJECT_HANDLES == 1)
151  objectHandleType NumberOfObjectsPerClass[2*((TRACE_NCLASSES+1)/2)];
152 #else
153  objectHandleType NumberOfObjectsPerClass[4*((TRACE_NCLASSES+3)/4)];
154 #endif
155 
156  /* Allocation size rounded up to the closest multiple of 4 */
157  uint8_t NameLengthPerClass[ 4*((TRACE_NCLASSES+3)/4) ];
158 
159  uint8_t TotalPropertyBytesPerClass[ 4*((TRACE_NCLASSES+3)/4) ];
160 
161  /* Allocation size rounded up to the closest multiple of 2 */
162  uint16_t StartIndexOfClass[ 2*((TRACE_NCLASSES+1)/2) ];
163 
164  /* The actual handles issued, should be Initiated to all zeros */
165  uint8_t objbytes[ 4*((TRACE_OBJECT_TABLE_SIZE+3)/4) ];
166 } ObjectPropertyTableType;
167 
168 /* Symbol table data structure */
169 typedef struct
170 {
171  /* = SYMBOL_HISTORY_TABLE_SIZE_IN_BYTES */
172  uint32_t symTableSize;
173 
174  /* Entry 0 is reserved. Any reference to entry 0 implies NULL*/
175  uint32_t nextFreeSymbolIndex;
176 
177  /* Size rounded up to closest multiple of 4, to avoid alignment issues*/
178  uint8_t symbytes[4*((SYMBOL_TABLE_SIZE+3)/4)];
179 
180  /* Used for lookups - Up to 64 linked lists within the symbol table
181  connecting all entries with the same 6 bit checksum.
182  This field holds the current list heads. Should be initiated to zeros */
183  uint16_t latestEntryOfChecksum[64];
184 } symbolTableType;
185 
186 
187 /*******************************************************************************
188  * The data structures of the different events, all 4 bytes long
189  ******************************************************************************/
190 
191 typedef struct
192 {
193  uint8_t type;
194  uint8_t objHandle;
195  uint16_t dts; /* differential timestamp - time since last event */
196 } TSEvent, TREvent;
197 
198 typedef struct
199 {
200  uint8_t type;
201  uint8_t dummy;
202  uint16_t dts; /* differential timestamp - time since last event */
203 } LPEvent;
204 
205 typedef struct
206 {
207  uint8_t type;
208  uint8_t objHandle;
209  uint16_t dts; /* differential timestamp - time since last event */
210 } KernelCall;
211 
212 typedef struct
213 {
214  uint8_t type;
215  uint8_t objHandle;
216  uint8_t param;
217  uint8_t dts; /* differential timestamp - time since last event */
218 } KernelCallWithParamAndHandle;
219 
220 typedef struct
221 {
222  uint8_t type;
223  uint8_t dts; /* differential timestamp - time since last event */
224  uint16_t param;
225 } KernelCallWithParam16;
226 
227 typedef struct
228 {
229  uint8_t type;
230  uint8_t objHandle; /* the handle of the closed object */
231  uint16_t symbolIndex; /* the name of the closed object */
232 } ObjCloseNameEvent;
233 
234 typedef struct
235 {
236  uint8_t type;
237  uint8_t arg1;
238  uint8_t arg2;
239  uint8_t arg3;
240 } ObjClosePropEvent;
241 
242 typedef struct
243 {
244  uint8_t type;
245  uint8_t unused1;
246  uint8_t unused2;
247  uint8_t dts;
248 } TaskInstanceStatusEvent;
249 
250 typedef struct
251 {
252  uint8_t type;
253  uint8_t dts;
254  uint16_t payload; /* the name of the user event */
255 } UserEvent;
256 
257 typedef struct
258 {
259  uint8_t type;
260 
261  /* 8 bits extra for storing DTS, if it does not fit in ordinary event
262  (this one is always MSB if used) */
263  uint8_t xts_8;
264 
265  /* 16 bits extra for storing DTS, if it does not fit in ordinary event. */
266  uint16_t xts_16;
267 } XTSEvent;
268 
269 typedef struct
270 {
271  uint8_t type;
272 
273  uint8_t xps_8;
274  uint16_t xps_16;
275 } XPSEvent;
276 
277 typedef struct{
278  uint8_t type;
279  uint8_t dts;
280  uint16_t size;
281 } MemEventSize;
282 
283 typedef struct{
284  uint8_t type;
285  uint8_t addr_high;
286  uint16_t addr_low;
287 } MemEventAddr;
288 
289 /*******************************************************************************
290  * The separate user event buffer structure. Can be enabled in trcConfig.h.
291  ******************************************************************************/
292 
293 #if (USE_SEPARATE_USER_EVENT_BUFFER == 1)
294 typedef struct
295 {
296  traceLabel name;
297  traceLabel defaultFormat;
298 } ChannelFormatPair;
299 
300 typedef struct
301 {
302  uint16_t bufferID;
303  uint16_t version;
304  uint32_t wraparoundCounter;
305  uint32_t numberOfSlots;
306  uint32_t nextSlotToWrite;
307  uint8_t numberOfChannels;
308  uint8_t padding1;
309  uint8_t padding2;
310  uint8_t padding3;
311  ChannelFormatPair channels[CHANNEL_FORMAT_PAIRS+1];
312  uint8_t channelBuffer[(USER_EVENT_BUFFER_SIZE + 3) & 0xFFFFFFFC]; /* 1 byte per slot, with padding for 4 byte alignment */
313  uint8_t dataBuffer[USER_EVENT_BUFFER_SIZE * 4]; /* 4 bytes per slot */
314 
315 } UserEventBuffer;
316 #endif
317 
318 /*******************************************************************************
319  * The main data structure, read by Tracealyzer from the RAM dump
320  ******************************************************************************/
321 
322 typedef struct
323 {
324  uint8_t startmarker0;
325  uint8_t startmarker1;
326  uint8_t startmarker2;
327  uint8_t startmarker3;
328  uint8_t startmarker4;
329  uint8_t startmarker5;
330  uint8_t startmarker6;
331  uint8_t startmarker7;
332  uint8_t startmarker8;
333  uint8_t startmarker9;
334  uint8_t startmarker10;
335  uint8_t startmarker11;
336 
337  /* Used to determine Kernel and Endianess */
338  uint16_t version;
339 
340  /* Currently 3 */
341  uint8_t minor_version;
342 
343  /* This should be 0 if lower IRQ priority values implies higher priority
344  levels, such as on ARM Cortex M. If the opposite scheme is used, i.e.,
345  if higher IRQ priority values means higher priority, this should be 1. */
346  uint8_t irq_priority_order;
347 
348  /* sizeof(RecorderDataType) - just for control */
349  uint32_t filesize;
350 
351  /* Current number of events recorded */
352  uint32_t numEvents;
353 
354  /* The buffer size, in number of event records */
355  uint32_t maxEvents;
356 
357  /* The event buffer index, where to write the next event */
358  uint32_t nextFreeIndex;
359 
360  /* 1 if the buffer is full, 0 otherwise */
361  uint32_t bufferIsFull;
362 
363  /* The frequency of the clock/timer/counter used as time base */
364  uint32_t frequency;
365 
366  /* The absolute timestamp of the last stored event, in the native
367  timebase, modulo frequency! */
368  uint32_t absTimeLastEvent;
369 
370  /* The number of seconds in total - lasts for 136 years */
371  uint32_t absTimeLastEventSecond;
372 
373  /* 1 if the recorder has been started, 0 if not yet started or stopped.
374  This is a 32 bit variable due to alignment issues. */
375  uint32_t recorderActive;
376 
377  /* Not used, remains for compatibility and future use */
378  uint8_t notused[28];
379 
380  /* The amount of heap memory remaining at the last malloc or free event */
381  uint32_t heapMemUsage;
382 
383  /* 0xF0F0F0F0 - for control only */
384  int32_t debugMarker0;
385 
386  /* Set to value of USE_16BIT_OBJECT_HANDLES */
387  uint32_t isUsing16bitHandles;
388 
389  /* The Object Property Table holds information about currently active
390  tasks, queues, and other recorded objects. This is updated on each
391  create call and includes object name and other properties. */
392  ObjectPropertyTableType ObjectPropertyTable;
393 
394  /* 0xF1F1F1F1 - for control only */
395  int32_t debugMarker1;
396 
397  /* The Symbol Table stores strings for User Events and is also used to
398  store names of deleted objects, which still may be in the trace but no
399  longer are available. */
400  symbolTableType SymbolTable;
401 
402  /* For inclusion of float support, and for endian detection of floats.
403  The value should be (float)1 or (uint32_t)0 */
404 #if (INCLUDE_FLOAT_SUPPORT == 1)
405  float exampleFloatEncoding;
406 #else
407  uint32_t exampleFloatEncoding;
408 #endif
409  /* This is non-zero if an internal error occurred in the recorder, e.g., if
410  one of the Nxxx constants was too small. The systemInfo string will then
411  contain an error message that is displayed when attempting to view the
412  trace file. */
413  uint32_t internalErrorOccured;
414 
415  /* 0xF2F2F2F2 - for control only */
416  int32_t debugMarker2;
417 
418  /* Error messages from the recorder. */
419  char systemInfo[80];
420 
421  /* 0xF3F3F3F3 - for control only */
422  int32_t debugMarker3;
423 
424  /* The event data, in 4-byte records */
425  uint8_t eventData[ EVENT_BUFFER_SIZE * 4 ];
426 
427 #if (USE_SEPARATE_USER_EVENT_BUFFER == 1)
428  UserEventBuffer userEventBuffer;
429 #endif
430 
431  /* This should always be 0 */
432  uint32_t endOfSecondaryBlocks;
433 
434  uint8_t endmarker0;
435  uint8_t endmarker1;
436  uint8_t endmarker2;
437  uint8_t endmarker3;
438  uint8_t endmarker4;
439  uint8_t endmarker5;
440  uint8_t endmarker6;
441  uint8_t endmarker7;
442  uint8_t endmarker8;
443  uint8_t endmarker9;
444  uint8_t endmarker10;
445  uint8_t endmarker11;
446 } RecorderDataType;
447 
448 extern RecorderDataType* RecorderDataPtr;
449 
450 /* Internal functions */
451 
452 uint16_t prvTraceGetDTS(uint16_t param_maxDTS);
453 
454 void prvTraceGetChecksum(const char *pname, uint8_t* pcrc, uint8_t* plength);
455 
456 traceLabel prvTraceCreateSymbolTableEntry(const char* name,
457  uint8_t crc6,
458  uint8_t len,
459  traceLabel channel);
460 
461 traceLabel prvTraceLookupSymbolTableEntry(const char* name,
462  uint8_t crc6,
463  uint8_t len,
464  traceLabel channel);
465 
466 traceLabel prvTraceOpenSymbol(const char* name, traceLabel userEventChannel);
467 
468 void prvTraceUpdateCounters(void);
469 
470 void prvCheckDataToBeOverwrittenForMultiEntryEvents(uint8_t nEntries);
471 
472 objectHandleType xTraceGetObjectHandle(traceObjectClass objectclass);
473 
474 void vTraceFreeObjectHandle(traceObjectClass objectclass,
475  objectHandleType handle);
476 
477 void vTraceSetObjectName(traceObjectClass objectclass,
478  objectHandleType handle,
479  const char* name);
480 
481 void* xTraceNextFreeEventBufferSlot(void);
482 
483 #if (USE_16BIT_OBJECT_HANDLES == 1)
484 unsigned char prvTraceGet8BitHandle(objectHandleType handle);
485 #else
486 #define prvTraceGet8BitHandle(x) ((unsigned char)x)
487 #endif
488 
489 
490 uint16_t uiIndexOfObject(objectHandleType objecthandle,
491  uint8_t objectclass);
492 
493 /*******************************************************************************
494  * vTraceError
495  *
496  * Called by various parts in the recorder. Stops the recorder and stores a
497  * pointer to an error message, which is printed by the monitor task.
498  ******************************************************************************/
499 void vTraceError(const char* msg);
500 
501 /*******************************************************************************
502  * prvTraceInitTraceData
503  *
504  * Allocates and initializes the recorder data structure, based on the constants
505  * in trcConfig.h. This allows for allocating the data on the heap, instead of
506  * using a static declaration.
507  ******************************************************************************/
508 void prvTraceInitTraceData(void);
509 
510 /* Internal macros */
511 
512 #define TRACE_PROPERTY_NAME_GET(objectclass, objecthandle) \
513 (const char*)(& RecorderDataPtr->ObjectPropertyTable.objbytes \
514 [uiIndexOfObject(objecthandle, objectclass)])
515 
516 #define TRACE_PROPERTY_OBJECT_STATE(objectclass, handle) \
517 RecorderDataPtr->ObjectPropertyTable.objbytes[uiIndexOfObject(handle, objectclass) \
518 + RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[objectclass]]
519 
520 #define TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, handle) \
521 RecorderDataPtr->ObjectPropertyTable.objbytes[uiIndexOfObject(handle, objectclass) \
522 + RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[objectclass] + 1]
523 
524 #define TRACE_SET_FLAG_ISEXCLUDED(flags, bitIndex) flags[(bitIndex) >> 3] |= (1 << ((bitIndex) & 7))
525 #define TRACE_CLEAR_FLAG_ISEXCLUDED(flags, bitIndex) flags[(bitIndex) >> 3] &= ~(1 << ((bitIndex) & 7))
526 #define TRACE_GET_FLAG_ISEXCLUDED(flags, bitIndex) (flags[(bitIndex) >> 3] & (1 << ((bitIndex) & 7)))
527 
528 #define TRACE_SET_EVENT_CODE_FLAG_ISEXCLUDED(eventCode) TRACE_SET_FLAG_ISEXCLUDED(excludedEventCodes, eventCode)
529 #define TRACE_CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(eventCode) TRACE_CLEAR_FLAG_ISEXCLUDED(excludedEventCodes, eventCode)
530 #define TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(eventCode) TRACE_GET_FLAG_ISEXCLUDED(excludedEventCodes, eventCode)
531 
532 /* DEBUG ASSERTS */
533 #if defined USE_TRACE_ASSERT && USE_TRACE_ASSERT != 0
534 #define TRACE_ASSERT(eval, msg, defRetVal) \
535 if (!(eval)) \
536 { \
537  vTraceError("TRACE_ASSERT: " msg); \
538  return defRetVal; \
539 }
540 #else
541 #define TRACE_ASSERT(eval, msg, defRetVal)
542 #endif
543 
544 #endif
545 
546 #endif
547 
548 
549 
550 
#define SYMBOL_TABLE_SIZE
Definition: trcConfig.h:296
#define USER_EVENT_BUFFER_SIZE
Definition: trcConfig.h:463
unsigned int unsigned int len
Definition: startup.cpp:197
uint8_t objectHandleType
Definition: trcTypes.h:53
uint8_t traceObjectClass
Definition: trcTypes.h:56
uint16_t traceLabel
Definition: trcTypes.h:46
#define EVENT_BUFFER_SIZE
Definition: trcConfig.h:150
To use the FreeRTOS so play with it a little *uses roughly of and uses roughly of RAM *The larger the size
Definition: readme.txt:4
#define CHANNEL_FORMAT_PAIRS
Definition: trcConfig.h:474