]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace(streaming)/trcKernelPort.c
Update FreeRTOS+Trace recorder library to v3.0.2
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-Trace(streaming) / trcKernelPort.c
1 /*******************************************************************************\r
2  * Trace Recorder Library for Tracealyzer v3.0.2\r
3  * Percepio AB, www.percepio.com\r
4  *\r
5  * trcKernelPort.c\r
6  *\r
7  * The kernel-specific code for integration with FreeRTOS.\r
8  *\r
9  * Terms of Use\r
10  * This software (the "Tracealyzer Recorder Library") is the intellectual\r
11  * property of Percepio AB and may not be sold or in other ways commercially\r
12  * redistributed without explicit written permission by Percepio AB.\r
13  *\r
14  * Separate conditions applies for the SEGGER branded source code included.\r
15  *\r
16  * The recorder library is free for use together with Percepio products.\r
17  * You may distribute the recorder library in its original form, but public\r
18  * distribution of modified versions require approval by Percepio AB.\r
19  *\r
20  * Disclaimer\r
21  * The trace tool and recorder library is being delivered to you AS IS and\r
22  * Percepio AB makes no warranty as to its use or performance. Percepio AB does\r
23  * not and cannot warrant the performance or results you may obtain by using the\r
24  * software or documentation. Percepio AB make no warranties, express or\r
25  * implied, as to noninfringement of third party rights, merchantability, or\r
26  * fitness for any particular purpose. In no event will Percepio AB, its\r
27  * technology partners, or distributors be liable to you for any consequential,\r
28  * incidental or special damages, including any lost profits or lost savings,\r
29  * even if a representative of Percepio AB has been advised of the possibility\r
30  * of such damages, or for any claim by any third party. Some jurisdictions do\r
31  * not allow the exclusion or limitation of incidental, consequential or special\r
32  * damages, or the exclusion of implied warranties or limitations on how long an\r
33  * implied warranty may last, so the above limitations may not apply to you.\r
34  *\r
35  * Tabs are used for indent in this file (1 tab = 4 spaces)\r
36  *\r
37  * Copyright Percepio AB, 2015.\r
38  * www.percepio.com\r
39  ******************************************************************************/\r
40 \r
41 #include "trcKernelPort.h"\r
42 \r
43 #if (USE_TRACEALYZER_RECORDER == 1)\r
44 \r
45 #include <stdint.h>\r
46 #include "trcRecorder.h"\r
47 #include "trcStreamPort.h"\r
48 #include "task.h"\r
49 \r
50 /* TzCtrl task TCB */\r
51 static xTaskHandle HandleTzCtrl;\r
52 \r
53 /* Called by TzCtrl task periodically (every 100 ms) */\r
54 static void CheckRecorderStatus(void);\r
55 \r
56 /* The TzCtrl task - receives commands from Tracealyzer (start/stop) */\r
57 static portTASK_FUNCTION( TzCtrl, pvParameters );\r
58 \r
59 /* Monitored by TzCtrl task, that give warnings as User Events */\r
60 extern volatile uint32_t NoRoomForSymbol;\r
61 extern volatile uint32_t NoRoomForObjectData;\r
62 extern volatile uint32_t LongestSymbolName;\r
63 extern volatile uint32_t MaxBytesTruncated;\r
64 \r
65 #define TRC_PORT_MALLOC(size) pvPortMalloc(size)\r
66 #if ((TRC_STREAM_PORT_BLOCKING_TRANSFER == 1) && (TRC_MEASURE_BLOCKING_TIME == 1))\r
67 \r
68 /*** Used in blocking transfer mode, if enabled TRC_MEASURE_BLOCKING_TIME **************/\r
69 \r
70 /* The highest number of cycles used by SEGGER_RTT_Write. */\r
71 static volatile int32_t blockingCyclesMax;\r
72 \r
73 /* The number of times SEGGER_RTT_Write has blocked due to a full buffer. */\r
74 static volatile uint32_t blockingCount;\r
75 \r
76 /* User Event Channel for giving warnings regarding blocking */\r
77 static char* trcDiagnosticsChannel;\r
78 \r
79 #endif /*((TRC_STREAM_PORT_BLOCKING_TRANSFER==1) && (TRC_MEASURE_BLOCKING_TIME))*/\r
80 \r
81 TRC_STREAM_PORT_ALLOCATE_FIELDS()\r
82 \r
83 /* User Event Channel for giving warnings regarding NoRoomForSymbol etc. */\r
84 char* trcWarningChannel;\r
85 \r
86 /* Keeps track of previous values, to only react on changes. */\r
87 static uint32_t NoRoomForSymbol_last = 0;\r
88 static uint32_t NoRoomForObjectData_last = 0;\r
89 static uint32_t LongestSymbolName_last = 0;\r
90 static uint32_t MaxBytesTruncated_last = 0;\r
91 \r
92 /*******************************************************************************\r
93  * prvTraceGetCurrentTaskHandle\r
94  *\r
95  * Function that returns the handle to the currently executing task.\r
96  *\r
97  ******************************************************************************/\r
98 void* prvTraceGetCurrentTaskHandle(void)\r
99 {\r
100         return xTaskGetCurrentTaskHandle();\r
101 }\r
102 \r
103 /*******************************************************************************\r
104  * prvIsNewTCB\r
105  *\r
106  * Function that returns the handle to the currently executing task.\r
107  *\r
108  ******************************************************************************/\r
109 static void* pCurrentTCB = NULL;\r
110 uint32_t prvIsNewTCB(void* pNewTCB)\r
111 {\r
112         if (pCurrentTCB != pNewTCB)\r
113         {\r
114                 pCurrentTCB = pNewTCB;\r
115                 return 1;\r
116         }\r
117         return 0;\r
118 }\r
119 /*******************************************************************************\r
120  * CheckRecorderStatus\r
121  *\r
122  * Called by TzCtrl task periodically (every 100 ms - seems reasonable).\r
123  * Checks a number of diagnostic variables and give warnings as user events,\r
124  * in most cases including a suggested solution.\r
125  ******************************************************************************/\r
126 static void CheckRecorderStatus(void)\r
127 {\r
128         if (NoRoomForSymbol > NoRoomForSymbol_last)\r
129         {\r
130                 vTracePrintF(trcWarningChannel, "TRC_SYMBOL_TABLE_SLOTS too small. Add %d slots.",\r
131                         NoRoomForSymbol);\r
132 \r
133                 NoRoomForSymbol_last = NoRoomForSymbol;\r
134         }\r
135 \r
136         if (NoRoomForObjectData > NoRoomForObjectData_last)\r
137         {\r
138                 vTracePrintF(trcWarningChannel, "TRC_OBJECT_DATA_SLOTS too small. Add %d slots.",\r
139                         NoRoomForObjectData);\r
140 \r
141                 NoRoomForObjectData_last = NoRoomForObjectData;\r
142         }\r
143 \r
144         if (LongestSymbolName > LongestSymbolName_last)\r
145         {\r
146                 if (LongestSymbolName > TRC_SYMBOL_MAX_LENGTH)\r
147                 {\r
148                         vTracePrintF(trcWarningChannel, "TRC_SYMBOL_MAX_LENGTH too small. Add %d chars.",\r
149                                 LongestSymbolName);\r
150                 }\r
151                 LongestSymbolName_last = LongestSymbolName;\r
152         }\r
153 \r
154         if (MaxBytesTruncated > MaxBytesTruncated_last)\r
155         {\r
156                 /* Some string event generated a too long string that was truncated.\r
157                 This may happen for the following functions:\r
158                 - vTracePrintF\r
159                 - vTracePrintF\r
160                 - vTraceStoreKernelObjectName\r
161                 - vTraceStoreUserEventChannelName\r
162                 - vTraceSetISRProperties\r
163 \r
164                 A PSF event may store maximum 60 bytes payload, including data arguments\r
165                 and string characters. For User Events, also the User Event Channel ptr\r
166                 must be squeezed in, if a channel is specified. */\r
167 \r
168                 vTracePrintF(trcWarningChannel, "String event too long, up to %d bytes truncated.",\r
169                         MaxBytesTruncated);\r
170 \r
171                 MaxBytesTruncated_last = MaxBytesTruncated;\r
172         }\r
173 \r
174 #if ((TRC_STREAM_PORT_BLOCKING_TRANSFER==1) && (TRC_MEASURE_BLOCKING_TIME))\r
175         if (blockingCount > 0)\r
176         {\r
177                 /* At least one case of blocking since the last check and this is\r
178                 the longest case. */\r
179                 vTracePrintF(trcDiagnosticsChannel, "Longest since last: %d us",\r
180                         (uint32_t)blockingCyclesMax/(TRACE_CPU_CLOCK_HZ/1000000));\r
181 \r
182                 blockingCyclesMax = 0;\r
183         }\r
184 #endif\r
185 }\r
186 \r
187 /*******************************************************************************\r
188  * vTraceOnTraceBegin\r
189  *\r
190  * Called on trace begin.\r
191  ******************************************************************************/\r
192 void vTraceOnTraceBegin(void)\r
193 {\r
194         TRC_STREAM_PORT_ON_TRACE_BEGIN();\r
195 }\r
196 \r
197 /*******************************************************************************\r
198  * vTraceOnTraceEnd\r
199  *\r
200  * Called on trace end.\r
201  ******************************************************************************/\r
202 void vTraceOnTraceEnd(void)\r
203 {\r
204         TRC_STREAM_PORT_ON_TRACE_END();\r
205 }\r
206 \r
207 /*******************************************************************************\r
208  * TzCtrl\r
209  *\r
210  * Task for receiving commands from Tracealyzer and for recorder diagnostics.\r
211  *\r
212  ******************************************************************************/\r
213 static portTASK_FUNCTION( TzCtrl, pvParameters )\r
214 {\r
215         TracealyzerCommandType msg;\r
216         int bytes = 0;\r
217 \r
218         while (1)\r
219         {\r
220                 bytes = 0;\r
221                 TRC_STREAM_PORT_READ_DATA(&msg, sizeof(TracealyzerCommandType), &bytes);\r
222                 if (bytes != 0)\r
223                 {\r
224                         if (bytes == sizeof(TracealyzerCommandType))\r
225                         {\r
226                                 if (isValidCommand(&msg))\r
227                                 {\r
228                                         processCommand(&msg); /* Start or Stop currently... */\r
229                                 }\r
230                         }\r
231                 }\r
232 \r
233                 do\r
234                 {\r
235                         bytes = 0;\r
236                         TRC_STREAM_PORT_PERIODIC_SEND_DATA(&bytes);\r
237                 }\r
238                 while (bytes != 0);\r
239 \r
240                 CheckRecorderStatus();\r
241                 vTaskDelay(TRC_CTRL_TASK_DELAY);        /* 10ms */\r
242         }\r
243 }\r
244 \r
245 /*******************************************************************************\r
246  * Trace_Init\r
247  *\r
248  * The main initialization routine for the trace recorder. Configures the stream\r
249  * and activates the TzCtrl task.\r
250  * Also sets up the diagnostic User Event channels used by TzCtrl task.\r
251  *\r
252  ******************************************************************************/\r
253 void Trace_Init(void)\r
254 {\r
255         TRC_STREAM_PORT_INIT();\r
256 \r
257         trcWarningChannel = vTraceStoreUserEventChannelName("Warnings from Recorder");\r
258 \r
259 #if ((TRC_STREAM_PORT_BLOCKING_TRANSFER==1) && (TRC_MEASURE_BLOCKING_TIME))\r
260         trcDiagnosticsChannel = vTraceStoreUserEventChannelName("Blocking on trace buffer");\r
261 #endif\r
262 \r
263         /* Creates the TzCtrl task - receives trace commands (start, stop, ...) */\r
264         xTaskCreate( TzCtrl, "TzCtrl", configMINIMAL_STACK_SIZE, NULL, TRC_CTRL_TASK_PRIORITY, &HandleTzCtrl );\r
265 }\r
266 \r
267 #endif\r