]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace(streaming)/Demo.c
Update FreeRTOS+Trace recorder library to v3.0.2
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-Trace(streaming) / Demo.c
1 /*******************************************************************************\r
2  * Tracealyzer v3.0.0 Demo Application\r
3  * Percepio AB, www.percepio.com\r
4  *\r
5  * traceDemoApp.c\r
6  *\r
7  * Demo application for Tracealyzer demo project.\r
8  *\r
9  * Terms of Use\r
10  * This software is copyright Percepio AB. The recorder library is free for\r
11  * use together with Percepio products. You may distribute the recorder library\r
12  * in its original form, including modifications in trcHardwarePort.c/.h\r
13  * given that these modification are clearly marked as your own modifications\r
14  * and documented in the initial comment section of these source files.\r
15  * This software is the intellectual property of Percepio AB and may not be\r
16  * sold or in other ways commercially redistributed without explicit written\r
17  * permission by Percepio AB.\r
18  *\r
19  * Disclaimer\r
20  * The trace tool and recorder library is being delivered to you AS IS and\r
21  * Percepio AB makes no warranty as to its use or performance. Percepio AB does\r
22  * not and cannot warrant the performance or results you may obtain by using the\r
23  * software or documentation. Percepio AB make no warranties, express or\r
24  * implied, as to noninfringement of third party rights, merchantability, or\r
25  * fitness for any particular purpose. In no event will Percepio AB, its\r
26  * technology partners, or distributors be liable to you for any consequential,\r
27  * incidental or special damages, including any lost profits or lost savings,\r
28  * even if a representative of Percepio AB has been advised of the possibility\r
29  * of such damages, or for any claim by any third party. Some jurisdictions do\r
30  * not allow the exclusion or limitation of incidental, consequential or special\r
31  * damages, or the exclusion of implied warranties or limitations on how long an\r
32  * implied warranty may last, so the above limitations may not apply to you.\r
33  *\r
34  * Tabs are used for indent in this file (1 tab = 4 spaces)\r
35  *\r
36  * Copyright Percepio AB, 2014.\r
37  * www.percepio.com\r
38  ******************************************************************************/\r
39 \r
40 \r
41 /* Standard includes. */\r
42 #include <stdio.h>\r
43 #include <stdint.h>\r
44 \r
45 /* Kernel includes. */\r
46 #include <FreeRTOS.h>\r
47 #include "task.h"\r
48 #include "queue.h"\r
49 #include "semphr.h"\r
50 \r
51 #if (configUSE_TIMERS == 1)\r
52         #include "timers.h"\r
53 #endif\r
54 \r
55 #include "trcRecorder.h"\r
56 \r
57 #define ISR3_PERIOD 18\r
58 #define ISR2_PERIOD 24\r
59 #define ISR1_PERIOD 30\r
60 \r
61 #define EXECTIME_CONTROLLER 1\r
62 #define EXECTIME_SUPERV 2\r
63 #define EXECTIME_SENSOR 1\r
64 \r
65 typedef struct\r
66 {\r
67         int32_t code;\r
68         int32_t value;\r
69         char data[512]; // Makes the Memory Heap Utilization graph more interresting!\r
70 } QueueMessage;\r
71 \r
72 #define MSGCODE_SENSOR_VALUE 1\r
73 #define MSGCODE_CONTROL_VALUE 10\r
74 #define MSGCODE_CONTROL_DEFAULT_VALUE 99\r
75 \r
76 static portTASK_FUNCTION_PROTO( trcDemoTaskSensor, pvParameters );\r
77 static portTASK_FUNCTION_PROTO( trcDemoTaskActuator, pvParameters );\r
78 static portTASK_FUNCTION_PROTO( trcDemoTaskController, pvParameters );\r
79 static portTASK_FUNCTION( trcDemoTaskSuperv, pvParameters );\r
80 static portTASK_FUNCTION( trcDemoISR, pvParameters );\r
81 \r
82 #if (configUSE_TIMERS == 1)\r
83 xTimerHandle timer;\r
84 void myTimerHandler(xTimerHandle tmr);\r
85 #endif\r
86 \r
87 xQueueHandle sensorQ, actuatorQ;\r
88 xSemaphoreHandle Sem1, Sem2, Sem3;\r
89 \r
90 void doSomeWork(uint32_t n);\r
91 \r
92 int readSensor(int i);\r
93 \r
94 /******************************************************************************\r
95 * doSomeWork\r
96 *\r
97 * Performs a busy wait for X milliseconds. Used to generate suitable execution\r
98 * times in the demo application, in a portable way.\r
99 ******************************************************************************/\r
100 void doSomeWork(uint32_t ms)\r
101 {\r
102         portTickType old = xTaskGetTickCount();\r
103         portTickType new = 0;\r
104         while (ms > 0)\r
105         {\r
106                 new = xTaskGetTickCount();\r
107                 if (old < new)\r
108                 {\r
109                         /* If uiTraceTickCount has changed, we only reduce 1ms of the wait\r
110                                 time. This way we do not count time that this task has waited\r
111                                 for other tasks. This will result in somewhat correct execution\r
112                                 times. */\r
113                         old = new;\r
114                         ms--;\r
115                 }\r
116         }\r
117 }\r
118 \r
119 /******************************************************************************\r
120 * readSensor\r
121 *\r
122 * Simulates a set of sensors/inputs, using a simple physics simulation.\r
123 * The values are intentionally ints (rather than floats) to avoid very slow\r
124 * execution times on chips without hardware floating point support.\r
125 ******************************************************************************/\r
126 int readSensor(int i)\r
127 {\r
128         static int pos[3] = {40, 80, 120};\r
129         static int speed[3] = {0, 0, -3};\r
130         static int acc[3] = {0, 0, 0};\r
131 \r
132         i--;\r
133 \r
134         acc[i] = (-pos[i] >> 3);\r
135         speed[i] += acc[i];\r
136         pos[i] += speed[i];\r
137 \r
138         return (int)pos[i];\r
139 }\r
140 \r
141 /******************************************************************************\r
142 * trcDemoTaskSensor\r
143 *\r
144 * The "Sensor" tasks (three instances of this code). Reads data using\r
145 * "readSensor" when trigged by the timer interrupt through a semaphore.\r
146 ******************************************************************************/\r
147 static portTASK_FUNCTION( trcDemoTaskSensor, pvParameters )\r
148 {\r
149         char name[30] = "SensorX\0";\r
150         QueueMessage sensorReading;\r
151         unsigned char idx = (unsigned char)(*(int*)pvParameters);\r
152         xSemaphoreHandle mySem = NULL;\r
153 \r
154         /* Change 'X' to the index */\r
155         name[6] = '0' + idx;\r
156 \r
157         switch (idx)\r
158         {\r
159                 case 1: mySem = Sem1; break;\r
160                 case 2: mySem = Sem2; break;\r
161                 case 3: mySem = Sem3; break;\r
162         }\r
163 \r
164         vTraceStoreUserEventChannelName(name);\r
165 \r
166         /* Initialize xNextWakeTime - this only needs to be done once. */\r
167 \r
168         sensorReading.value = 0;\r
169         sensorReading.code = 0;\r
170 \r
171         for( ;; )\r
172         {\r
173 \r
174                 xSemaphoreTake(mySem, 0xFFFFFFFF);\r
175 \r
176                 sensorReading.code = idx;\r
177                 sensorReading.value = readSensor(idx);\r
178 \r
179                 doSomeWork(EXECTIME_SENSOR);\r
180 \r
181                 vTracePrintF(name , "Sending msg %d", sensorReading.value);\r
182 \r
183                 if (xQueueSend(sensorQ, &sensorReading, 1) != pdTRUE)\r
184                 {\r
185                         vTracePrint(name, "Sensor queue full. Sample dropped!");\r
186                 }\r
187                 vTraceInstanceFinishedNow();\r
188         }\r
189 }\r
190 \r
191 \r
192 \r
193 /******************************************************************************\r
194 * trcDemoTaskSuperv\r
195 *\r
196 * The "Supervisor" task. Performs no action in the simulation, apart from\r
197 * preempting other tasks in the scheduling.\r
198 ******************************************************************************/\r
199 static portTASK_FUNCTION( trcDemoTaskSuperv, pvParameters )\r
200 {\r
201         int counter = 0;\r
202         \r
203         #if (configUSE_TIMERS == 1)\r
204         static int timerState = 0;\r
205         #endif\r
206 \r
207         portTickType xNextWakeTime;\r
208         (void)pvParameters;\r
209 \r
210         xNextWakeTime = xTaskGetTickCount();\r
211 \r
212         #if (configUSE_TIMERS == 1)\r
213         timer = xTimerCreate("Tmr5", 5, 1, (void*)42, myTimerHandler);\r
214         xTimerChangePeriod(timer, 10, 0);\r
215         #endif\r
216 \r
217         for( ;; )\r
218         {               \r
219                 vTaskDelayUntil( &xNextWakeTime, 40);\r
220                 \r
221                 counter = (counter + 1) % 16;\r
222                 \r
223                 if (counter == 8) vTaskPrioritySet(NULL, 2);\r
224                 \r
225                 if (counter == 0) vTaskPrioritySet(NULL, 3);\r
226                                 \r
227                 doSomeWork(EXECTIME_SUPERV);\r
228 \r
229                 #if (configUSE_TIMERS == 1)\r
230                 if (timerState == 0)\r
231                 {\r
232                         xTimerStart(timer, 0);\r
233                         timerState = 1;\r
234                 }\r
235                 else if (timerState == 1)\r
236                 {\r
237                         xTimerStop(timer, 0);\r
238                         timerState = 0;\r
239                 }\r
240                 #endif\r
241         }\r
242 }\r
243 \r
244 /******************************************************************************\r
245 * trcDemoTaskController\r
246 *\r
247 * The "Controller" task. Periodically reads all accumulated messages in SensorQ\r
248 * (i.e., those produced by the Sensor tasks since the last execution of\r
249 * the Controller task). Calculates their mean value and send this to Actuator.\r
250 ******************************************************************************/\r
251 static portTASK_FUNCTION( trcDemoTaskController, pvParameters )\r
252 {\r
253         portTickType xNextWakeTime;\r
254         QueueMessage* sensorReading;\r
255         QueueMessage actuatorMessage;\r
256         int32_t sum[4];\r
257         int32_t count[4];\r
258 \r
259         (void)pvParameters;\r
260 \r
261         vTraceStoreUserEventChannelName("UE TEST");\r
262 \r
263         /* Initialize xNextWakeTime - this only needs to be done once. */\r
264         xNextWakeTime = xTaskGetTickCount();\r
265         for(;;)\r
266         {\r
267                 sum[1] = 0;\r
268                 sum[2] = 0;\r
269                 sum[3] = 0;\r
270                 count[1] = 0;\r
271                 count[2] = 0;\r
272                 count[3] = 0;\r
273 \r
274                 vTaskDelayUntil(&xNextWakeTime, 60);\r
275 \r
276                 for(;;)\r
277                 {\r
278                         // To demostrate malloc/free tracing\r
279                         sensorReading = ( QueueMessage * ) pvPortMalloc( sizeof( QueueMessage ) );\r
280 \r
281                         if (xQueueReceive(sensorQ, sensorReading, 0) != pdTRUE)\r
282                         {\r
283                                 vPortFree(sensorReading);\r
284                                 break;\r
285                         }\r
286                         else\r
287                         {\r
288                                 if (sensorReading->code >= 1 && sensorReading->code <= 3)\r
289                                 {\r
290                                         sum[sensorReading->code] += sensorReading->value;\r
291                                         count[sensorReading->code]++;\r
292                                 }\r
293                         }\r
294                         doSomeWork(EXECTIME_CONTROLLER);\r
295                         \r
296                         //vTracePrintF(0, "0x%4x", 111);\r
297                         //vTracePrintF(0, "0x%04x", 111);\r
298                         //vTracePrintF(0, "0x%4X", 111);\r
299                         //vTracePrintF(0, "0x%04X", 111);\r
300                         //\r
301                         //vTracePrint(0, "123456789012345678901234567890123456789012345678901234567890");\r
302                         //vTracePrint("UE TEST", "1234567890123456789012345678901234567890123456789012345");\r
303                         //vTracePrint("UE TEST", "12345678901234567890123456789012345678901234567890123456");\r
304                         //vTracePrint("UE TEST", "123456789012345678901234567890123456789012345678901234567");\r
305                         //vTracePrint("UE TEST", "12345678901234567890123456789012345678901234567890");\r
306                         //\r
307                         //vTracePrintF("UE TEST", "%5d", 42);\r
308                         //vTracePrintF("UE TEST", "%05d", 42);\r
309                         //vTracePrintF("UE TEST", "%5d", -42);\r
310                         //vTracePrintF("UE TEST", "%05d", -42);\r
311                         //vTracePrintF("UE TEST", "%05d", -1042);\r
312                         //vTracePrintF("UE TEST", "%05d", -11042);\r
313                         //\r
314                         //vTracePrintF("UE TEST", "%5u", -1);\r
315                         //vTracePrintF("UE TEST", "%05u", -1);\r
316                         //vTracePrintF("UE TEST", "%5u", 10);\r
317                         //vTracePrintF("UE TEST", "%05u", 10);\r
318                         //\r
319                         //vTracePrintF("UE TEST", "%5u", 11042);\r
320                         //vTracePrintF("UE TEST", "%05u", 11042);\r
321                         //\r
322                         //vTracePrintF("UE TEST", "%5u", 111042);\r
323                         //vTracePrintF("UE TEST", "%05u", 111042);\r
324                         //\r
325                         //vTracePrintF("UE TEST", "%15d", 111042);\r
326                         //vTracePrintF("UE TEST", "%015d", 111042);\r
327 \r
328                         vPortFree(sensorReading);\r
329                         vTraceInstanceFinishedNow();\r
330 \r
331                 }\r
332 \r
333                 actuatorMessage.code = MSGCODE_CONTROL_VALUE;\r
334                 actuatorMessage.value = 0;\r
335 \r
336                 if (count[1] > 0)\r
337                         actuatorMessage.value += (int32_t)(0.5 * sum[1]/count[1]);\r
338                 if (count[2] > 0)\r
339                         actuatorMessage.value += (int32_t)(0.25 * sum[2]/count[2]);\r
340                 if (count[3] > 0)\r
341                         actuatorMessage.value += (int32_t)(0.25 * sum[3]/count[3]);\r
342 \r
343                 xQueueSend(actuatorQ, &actuatorMessage, 10000);\r
344         }\r
345 }\r
346 \r
347 /******************************************************************************\r
348 * trcDemoISR\r
349 *\r
350 * The "FakeISR" task, that simulates the ISRTimer interrupts, which triggers\r
351 * the Sensor tasks.\r
352 ******************************************************************************/\r
353 static portTASK_FUNCTION( trcDemoISR, pvParameters )\r
354 {\r
355         portTickType xNextWakeTime;\r
356         portBASE_TYPE dummy;\r
357         int i = 0;\r
358 \r
359         (void)pvParameters;\r
360 \r
361         /* Initialize xNextWakeTime - this only needs to be done once. */\r
362         xNextWakeTime = xTaskGetTickCount();\r
363         vTraceSetISRProperties("ISRTimer1", 3);\r
364         vTraceSetISRProperties("ISRTimer2", 2);\r
365         vTraceSetISRProperties("ISRTimer3", 1);\r
366         vTaskDelayUntil( &xNextWakeTime, 1);\r
367 \r
368         for( ;; )\r
369         {\r
370                 i++;\r
371 \r
372                 if (i % ISR3_PERIOD == 0)\r
373                 {\r
374                         portENTER_CRITICAL();\r
375                         vTraceStoreISRBegin((void*)"ISRTimer3");\r
376                         xSemaphoreGiveFromISR(Sem3, &dummy);\r
377                         vTraceStoreISREndManual(dummy);\r
378                         portEXIT_CRITICAL();\r
379                 }\r
380 \r
381                 if (i % ISR2_PERIOD == 0)\r
382                 {\r
383                         portENTER_CRITICAL();\r
384                         vTraceStoreISRBegin((void*)"ISRTimer2");\r
385                         xSemaphoreGiveFromISR(Sem2, &dummy);\r
386                         vTraceStoreISREndManual(dummy);\r
387                         portEXIT_CRITICAL();\r
388                 }\r
389 \r
390                 if (i % ISR1_PERIOD == 0)\r
391                 {\r
392                         portENTER_CRITICAL();\r
393                         vTraceStoreISRBegin((void*)"ISRTimer1");\r
394                         xSemaphoreGiveFromISR(Sem1, &dummy);\r
395                         vTraceStoreISREndManual(dummy);\r
396                         portEXIT_CRITICAL();\r
397 \r
398 \r
399                 }\r
400 \r
401                 vTaskDelayUntil( &xNextWakeTime, 1);\r
402         }\r
403 }\r
404 \r
405 /******************************************************************************\r
406 * trcDemoTaskActuator\r
407 *\r
408 * The "Actuator" task, just reads the data from Controller and logs it in a\r
409 * User Event (i.e., the "vTracePrintF" calls).\r
410 ******************************************************************************/\r
411 static portTASK_FUNCTION( trcDemoTaskActuator, pvParameters )\r
412 {\r
413         QueueMessage inMessage;\r
414         (void)pvParameters;\r
415         vTraceStoreUserEventChannelName("Actuator Out Signal");\r
416 \r
417         for( ;; )\r
418         {\r
419                 vTraceInstanceFinishedNow();\r
420                 /* Place this task in blocked state until it is time to run again. */\r
421                 if (xQueueReceive(actuatorQ, &inMessage, 35) != pdTRUE)\r
422                 {\r
423                         vTracePrintF("Actuator Out Signal", "No data...");\r
424                 }\r
425                 else\r
426                 {\r
427                         if (inMessage.code == MSGCODE_CONTROL_VALUE)\r
428                         {\r
429                                 vTracePrintF("Actuator Out Signal", "Out: %d",\r
430                                                          inMessage.value);\r
431                         }\r
432                 }\r
433         }\r
434 }\r
435 \r
436 #if (configUSE_TIMERS == 1)\r
437 void myTimerHandler(xTimerHandle tmr)\r
438 {\r
439         (void) tmr;\r
440         vTracePrintF("Timer", "Timer handler!");\r
441 }\r
442 #endif\r
443 \r
444 int sensorTaskID1 = 1;\r
445 int sensorTaskID2 = 2;\r
446 int sensorTaskID3 = 3;\r
447 \r
448 #define vTaskCreateNotTraced( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority ) \\r
449         { void* this_pxCreatedTask; \\r
450         vTraceSetReadyEventsEnabled(0); \\r
451         xTaskGenericCreate( ( pvTaskCode ), ( pcName ), ( usStackDepth ), ( pvParameters ), ( uxPriority ), ( &this_pxCreatedTask ), ( NULL ), ( NULL ) ); \\r
452         vTraceSetReadyEventsEnabled(1); \\r
453         if (this_pxCreatedTask != NULL){ vTraceExcludeTaskFromTrace(this_pxCreatedTask); }else{ return -42;} }\r
454 \r
455 /******************************************************************************\r
456 * trcDemoTaskActuator\r
457 *\r
458 * The "Actuator" task, just reads the data from Controller and logs it in a\r
459 * User Event (i.e., the "vTracePrintF" calls).\r
460 ******************************************************************************/\r
461 int vStartDemoApplication(void)\r
462 {\r
463         void* objectHandle = NULL;\r
464 \r
465         vTraceStoreUserEventChannelName("Messages");\r
466 \r
467         vTracePrint("Messages", "Demo starting...");\r
468         vTracePrint("Messages", "vTraceUserEvent creates basic User Events.");\r
469         vTracePrint("Messages", "vTracePrintF creates advanced user events, like printf");\r
470         //vTracePrintF("Messages", "A float: %f (should be 1)", (float)1.0);\r
471         //vTracePrintF("Messages", "A double: %lf (should be 1)", (double)1.0);\r
472         //vTracePrintF("Messages", "A signed 8-bit value: %bd (should be -1)", -1);\r
473 \r
474         vTraceStoreUserEventChannelName("Timer");\r
475         \r
476         sensorQ = xQueueCreate(15, sizeof(QueueMessage) );\r
477         if( sensorQ == 0 )\r
478         {\r
479                 vTracePrint("Messages", "Could not create SensorQ!\n");\r
480                 return -1;\r
481         }\r
482         vTraceSetQueueName(sensorQ, "SensorQueue");\r
483 \r
484         actuatorQ = xQueueCreate(3, sizeof(QueueMessage) );\r
485         if( actuatorQ == 0 )\r
486         {\r
487                 vTracePrint("Messages", "Could not create ActuatorQ!\n");\r
488                 return -2;\r
489         }\r
490         vTraceSetQueueName(actuatorQ, "ActuatorQueue");\r
491 \r
492         vSemaphoreCreateBinary(Sem1);\r
493         if( Sem1 == NULL )\r
494         {\r
495                 vTracePrint("Messages", "Could not create Sem1!\n");\r
496                 return -3;\r
497         }\r
498         vTraceSetSemaphoreName(Sem1, "SemaphSenX");\r
499 \r
500         vSemaphoreCreateBinary(Sem2);\r
501         if( Sem2 == NULL )\r
502         {\r
503                 vTracePrint("Messages", "Could not create Sem2!\n");\r
504                 return -4;\r
505         }\r
506         vTraceSetSemaphoreName(Sem2, "SemaphSenY");\r
507 \r
508         vSemaphoreCreateBinary(Sem3);\r
509         if( Sem3 == NULL )\r
510         {\r
511                 vTracePrint("Messages", "Could not create Sem3!\n");\r
512                 return -5;\r
513         }\r
514         vTraceSetSemaphoreName(Sem3, "SemaphSenZ");\r
515 \r
516         xTaskCreate( trcDemoTaskSensor, "SensorX",\r
517                                 configMINIMAL_STACK_SIZE*2, &sensorTaskID1, 8, &objectHandle );\r
518         if (objectHandle == NULL)\r
519         {\r
520                 return -6;\r
521         }\r
522 \r
523         xTaskCreate( trcDemoTaskSensor, "SensorY",\r
524                                 configMINIMAL_STACK_SIZE*2, &sensorTaskID2, 7, &objectHandle );\r
525         if (objectHandle == NULL)\r
526         {\r
527                 return -7;\r
528         }\r
529 \r
530         xTaskCreate( trcDemoTaskSensor, "SensorZ",\r
531                                 configMINIMAL_STACK_SIZE*2, &sensorTaskID3, 6, &objectHandle );\r
532         if (objectHandle == NULL)\r
533         {\r
534                 return -8;\r
535         }\r
536 \r
537         xTaskCreate( trcDemoTaskController, "Control",\r
538                                 configMINIMAL_STACK_SIZE*2, NULL, 4, &objectHandle );\r
539         if (objectHandle == NULL)\r
540         {\r
541                 return -9;\r
542         }\r
543 \r
544         xTaskCreate( trcDemoTaskActuator, "Actuator",\r
545                                 configMINIMAL_STACK_SIZE*2, NULL, 5, &objectHandle );\r
546         if (objectHandle == NULL)\r
547         {\r
548                 return -10;\r
549         }\r
550 \r
551         xTaskCreate( trcDemoTaskSuperv, "Superv",\r
552                                 configMINIMAL_STACK_SIZE*2, NULL, 3, &objectHandle );\r
553         if (objectHandle == NULL)\r
554         {\r
555                 return -11;\r
556         }\r
557         \r
558         xTaskCreate( trcDemoISR, "(Hide)FakeISR",\r
559                                 configMINIMAL_STACK_SIZE*2, NULL, configMAX_PRIORITIES-1, &objectHandle);\r
560         if (objectHandle == NULL)\r
561         {\r
562                 return -12;\r
563         }\r
564         \r
565         return 0;\r
566 }\r