]> begriffs open source - cmsis-freertos/blob - Demo/Posix_GCC/main.c
Update README.md - branch main is now the base branch
[cmsis-freertos] / Demo / Posix_GCC / main.c
1 /*
2  * FreeRTOS V202111.00
3  * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of
6  * this software and associated documentation files (the "Software"), to deal in
7  * the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9  * the Software, and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * https://www.FreeRTOS.org
23  * https://github.com/FreeRTOS
24  *
25  */
26
27 /******************************************************************************
28  * This project provides two demo applications.  A simple blinky style project,
29  * a more comprehensive test and demo application.
30  * The mainSELECTED_APPLICATION setting is used to select between
31  * the three
32  *
33  * If mainSELECTED_APPLICATION = BLINKY_DEMO the simple blinky demo will be built.
34  * The simply blinky demo is implemented and described in main_blinky.c.
35  *
36  * If mainSELECTED_APPLICATION = FULL_DEMO the more comprehensive test and demo
37  * application built. This is implemented and described in main_full.c.
38  *
39  * This file implements the code that is not demo specific, including the
40  * hardware setup and FreeRTOS hook functions.
41  *
42  *******************************************************************************
43  * NOTE: Linux will not be running the FreeRTOS demo threads continuously, so
44  * do not expect to get real time behaviour from the FreeRTOS Linux port, or
45  * this demo application.  Also, the timing information in the FreeRTOS+Trace
46  * logs have no meaningful units.  See the documentation page for the Linux
47  * port for further information:
48  * https://freertos.org/FreeRTOS-simulator-for-Linux.html
49  *
50  *******************************************************************************
51  */
52
53 /* Standard includes. */
54 #include <stdlib.h>
55 #include <stdio.h>
56 #include <unistd.h>
57 #include <stdarg.h>
58 #include <signal.h>
59 #include <errno.h>
60 #include <sys/select.h>
61
62 /* FreeRTOS kernel includes. */
63 #include "FreeRTOS.h"
64 #include "task.h"
65
66 /* Local includes. */
67 #include "console.h"
68
69 #define    BLINKY_DEMO    0
70 #define    FULL_DEMO      1
71
72 #ifdef BUILD_DIR
73     #define BUILD         BUILD_DIR
74 #else
75     #define BUILD         "./"
76 #endif
77
78 /* Demo type is passed as an argument */
79 #ifdef USER_DEMO
80     #define     mainSELECTED_APPLICATION    USER_DEMO
81 #else /* Default Setting */
82     #define    mainSELECTED_APPLICATION     BLINKY_DEMO
83 #endif
84
85 /* This demo uses heap_3.c (the libc provided malloc() and free()). */
86
87 /*-----------------------------------------------------------*/
88 extern void main_blinky( void );
89 extern void main_full( void );
90 static void traceOnEnter( void );
91
92 /*
93  * Only the comprehensive demo uses application hook (callback) functions.  See
94  * http://www.freertos.org/a00016.html for more information.
95  */
96 void vFullDemoTickHookFunction( void );
97 void vFullDemoIdleFunction( void );
98
99 /*
100  * Prototypes for the standard FreeRTOS application hook (callback) functions
101  * implemented within this file.  See http://www.freertos.org/a00016.html .
102  */
103 void vApplicationMallocFailedHook( void );
104 void vApplicationIdleHook( void );
105 void vApplicationStackOverflowHook( TaskHandle_t pxTask,
106                                     char * pcTaskName );
107 void vApplicationTickHook( void );
108 void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
109                                     StackType_t ** ppxIdleTaskStackBuffer,
110                                     uint32_t * pulIdleTaskStackSize );
111 void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
112                                      StackType_t ** ppxTimerTaskStackBuffer,
113                                      uint32_t * pulTimerTaskStackSize );
114
115 /*
116  * Writes trace data to a disk file when the trace recording is stopped.
117  * This function will simply overwrite any trace files that already exist.
118  */
119 static void prvSaveTraceFile( void );
120
121 /*
122  * Signal handler for Ctrl_C to cause the program to exit, and generate the
123  * profiling info.
124  */
125 static void handle_sigint( int signal );
126
127 /*-----------------------------------------------------------*/
128
129 /* When configSUPPORT_STATIC_ALLOCATION is set to 1 the application writer can
130  * use a callback function to optionally provide the memory required by the idle
131  * and timer tasks.  This is the stack that will be used by the timer task.  It is
132  * declared here, as a global, so it can be checked by a test that is implemented
133  * in a different file. */
134 StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
135
136 /* Notes if the trace is running or not. */
137 #if ( projCOVERAGE_TEST == 1 )
138     static BaseType_t xTraceRunning = pdFALSE;
139 #else
140     static BaseType_t xTraceRunning = pdTRUE;
141 #endif
142
143 /*-----------------------------------------------------------*/
144
145 int main( void )
146 {
147     /* SIGINT is not blocked by the posix port */
148     signal( SIGINT, handle_sigint );
149
150     /* Do not include trace code when performing a code coverage analysis. */
151     #if ( projCOVERAGE_TEST != 1 )
152         {
153             /* Initialise the trace recorder.  Use of the trace recorder is optional.
154              * See http://www.FreeRTOS.org/trace for more information. */
155             vTraceEnable( TRC_START );
156
157             /* Start the trace recording - the recording is written to a file if
158              * configASSERT() is called. */
159             printf( "\r\nTrace started.\r\nThe trace will be dumped to disk if a call to configASSERT() fails.\r\n" );
160
161             #if ( TRACE_ON_ENTER == 1 )
162                 printf( "\r\nThe trace will be dumped to disk if Enter is hit.\r\n" );
163             #endif
164             uiTraceStart();
165         }
166     #endif /* if ( projCOVERAGE_TEST != 1 ) */
167
168     console_init();
169     #if ( mainSELECTED_APPLICATION == BLINKY_DEMO )
170         {
171             console_print( "Starting echo blinky demo\n" );
172             main_blinky();
173         }
174     #elif ( mainSELECTED_APPLICATION == FULL_DEMO )
175         {
176             console_print( "Starting full demo\n" );
177             main_full();
178         }
179     #else
180         {
181             #error "The selected demo is not valid"
182         }
183     #endif /* if ( mainSELECTED_APPLICATION ) */
184
185     return 0;
186 }
187 /*-----------------------------------------------------------*/
188
189 void vApplicationMallocFailedHook( void )
190 {
191     /* vApplicationMallocFailedHook() will only be called if
192      * configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h.  It is a hook
193      * function that will get called if a call to pvPortMalloc() fails.
194      * pvPortMalloc() is called internally by the kernel whenever a task, queue,
195      * timer or semaphore is created.  It is also called by various parts of the
196      * demo application.  If heap_1.c, heap_2.c or heap_4.c is being used, then the
197      * size of the    heap available to pvPortMalloc() is defined by
198      * configTOTAL_HEAP_SIZE in FreeRTOSConfig.h, and the xPortGetFreeHeapSize()
199      * API function can be used to query the size of free heap space that remains
200      * (although it does not provide information on how the remaining heap might be
201      * fragmented).  See http://www.freertos.org/a00111.html for more
202      * information. */
203     vAssertCalled( __FILE__, __LINE__ );
204 }
205 /*-----------------------------------------------------------*/
206
207 void vApplicationIdleHook( void )
208 {
209     /* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set
210      * to 1 in FreeRTOSConfig.h.  It will be called on each iteration of the idle
211      * task.  It is essential that code added to this hook function never attempts
212      * to block in any way (for example, call xQueueReceive() with a block time
213      * specified, or call vTaskDelay()).  If application tasks make use of the
214      * vTaskDelete() API function to delete themselves then it is also important
215      * that vApplicationIdleHook() is permitted to return to its calling function,
216      * because it is the responsibility of the idle task to clean up memory
217      * allocated by the kernel to any task that has since deleted itself. */
218
219
220     usleep( 15000 );
221     traceOnEnter();
222
223     #if ( mainSELECTED_APPLICATION == FULL_DEMO )
224         {
225             /* Call the idle task processing used by the full demo.  The simple
226              * blinky demo does not use the idle task hook. */
227             vFullDemoIdleFunction();
228         }
229     #endif
230 }
231 /*-----------------------------------------------------------*/
232
233 void vApplicationStackOverflowHook( TaskHandle_t pxTask,
234                                     char * pcTaskName )
235 {
236     ( void ) pcTaskName;
237     ( void ) pxTask;
238
239     /* Run time stack overflow checking is performed if
240      * configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2.  This hook
241      * function is called if a stack overflow is detected.  This function is
242      * provided as an example only as stack overflow checking does not function
243      * when running the FreeRTOS POSIX port. */
244     vAssertCalled( __FILE__, __LINE__ );
245 }
246 /*-----------------------------------------------------------*/
247
248 void vApplicationTickHook( void )
249 {
250     /* This function will be called by each tick interrupt if
251     * configUSE_TICK_HOOK is set to 1 in FreeRTOSConfig.h.  User code can be
252     * added here, but the tick hook is called from an interrupt context, so
253     * code must not attempt to block, and only the interrupt safe FreeRTOS API
254     * functions can be used (those that end in FromISR()). */
255
256     #if ( mainSELECTED_APPLICATION == FULL_DEMO )
257         {
258             vFullDemoTickHookFunction();
259         }
260     #endif /* mainSELECTED_APPLICATION */
261 }
262
263 void traceOnEnter()
264 {
265     #if ( TRACE_ON_ENTER == 1 )
266         int xReturn;
267         struct timeval tv = { 0L, 0L };
268         fd_set fds;
269
270         FD_ZERO( &fds );
271         FD_SET( STDIN_FILENO, &fds );
272
273         xReturn = select( STDIN_FILENO + 1, &fds, NULL, NULL, &tv );
274
275         if( xReturn > 0 )
276         {
277             if( xTraceRunning == pdTRUE )
278             {
279                 prvSaveTraceFile();
280             }
281
282             /* clear the buffer */
283             char buffer[ 0 ];
284             read( STDIN_FILENO, &buffer, 1 );
285         }
286     #endif /* if ( TRACE_ON_ENTER == 1 ) */
287 }
288
289 void vLoggingPrintf( const char * pcFormat,
290                      ... )
291 {
292     va_list arg;
293
294     va_start( arg, pcFormat );
295     vprintf( pcFormat, arg );
296     va_end( arg );
297 }
298 /*-----------------------------------------------------------*/
299
300 void vApplicationDaemonTaskStartupHook( void )
301 {
302     /* This function will be called once only, when the daemon task starts to
303      * execute    (sometimes called the timer task).  This is useful if the
304      * application includes initialisation code that would benefit from executing
305      * after the scheduler has been started. */
306 }
307 /*-----------------------------------------------------------*/
308
309 void vAssertCalled( const char * const pcFileName,
310                     unsigned long ulLine )
311 {
312     static BaseType_t xPrinted = pdFALSE;
313     volatile uint32_t ulSetToNonZeroInDebuggerToContinue = 0;
314
315     /* Called if an assertion passed to configASSERT() fails.  See
316      * http://www.freertos.org/a00110.html#configASSERT for more information. */
317
318     /* Parameters are not used. */
319     ( void ) ulLine;
320     ( void ) pcFileName;
321
322
323     taskENTER_CRITICAL();
324     {
325         /* Stop the trace recording. */
326         if( xPrinted == pdFALSE )
327         {
328             xPrinted = pdTRUE;
329
330             if( xTraceRunning == pdTRUE )
331             {
332                 prvSaveTraceFile();
333             }
334         }
335
336         /* You can step out of this function to debug the assertion by using
337          * the debugger to set ulSetToNonZeroInDebuggerToContinue to a non-zero
338          * value. */
339         while( ulSetToNonZeroInDebuggerToContinue == 0 )
340         {
341             __asm volatile ( "NOP" );
342             __asm volatile ( "NOP" );
343         }
344     }
345     taskEXIT_CRITICAL();
346 }
347 /*-----------------------------------------------------------*/
348
349 static void prvSaveTraceFile( void )
350 {
351     /* Tracing is not used when code coverage analysis is being performed. */
352     #if ( projCOVERAGE_TEST != 1 )
353         {
354             FILE * pxOutputFile;
355
356             vTraceStop();
357
358             pxOutputFile = fopen( "Trace.dump", "wb" );
359
360             if( pxOutputFile != NULL )
361             {
362                 fwrite( RecorderDataPtr, sizeof( RecorderDataType ), 1, pxOutputFile );
363                 fclose( pxOutputFile );
364                 printf( "\r\nTrace output saved to Trace.dump\r\n" );
365             }
366             else
367             {
368                 printf( "\r\nFailed to create trace dump file\r\n" );
369             }
370         }
371     #endif /* if ( projCOVERAGE_TEST != 1 ) */
372 }
373 /*-----------------------------------------------------------*/
374
375 /* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an
376  * implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
377  * used by the Idle task. */
378 void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
379                                     StackType_t ** ppxIdleTaskStackBuffer,
380                                     uint32_t * pulIdleTaskStackSize )
381 {
382 /* If the buffers to be provided to the Idle task are declared inside this
383  * function then they must be declared static - otherwise they will be allocated on
384  * the stack and so not exists after this function exits. */
385     static StaticTask_t xIdleTaskTCB;
386     static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
387
388     /* Pass out a pointer to the StaticTask_t structure in which the Idle task's
389      * state will be stored. */
390     *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
391
392     /* Pass out the array that will be used as the Idle task's stack. */
393     *ppxIdleTaskStackBuffer = uxIdleTaskStack;
394
395     /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
396      * Note that, as the array is necessarily of type StackType_t,
397      * configMINIMAL_STACK_SIZE is specified in words, not bytes. */
398     *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
399 }
400 /*-----------------------------------------------------------*/
401
402 /* configUSE_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
403  * application must provide an implementation of vApplicationGetTimerTaskMemory()
404  * to provide the memory that is used by the Timer service task. */
405 void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
406                                      StackType_t ** ppxTimerTaskStackBuffer,
407                                      uint32_t * pulTimerTaskStackSize )
408 {
409 /* If the buffers to be provided to the Timer task are declared inside this
410  * function then they must be declared static - otherwise they will be allocated on
411  * the stack and so not exists after this function exits. */
412     static StaticTask_t xTimerTaskTCB;
413
414     /* Pass out a pointer to the StaticTask_t structure in which the Timer
415      * task's state will be stored. */
416     *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
417
418     /* Pass out the array that will be used as the Timer task's stack. */
419     *ppxTimerTaskStackBuffer = uxTimerTaskStack;
420
421     /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
422      * Note that, as the array is necessarily of type StackType_t,
423      * configMINIMAL_STACK_SIZE is specified in words, not bytes. */
424     *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
425 }
426
427 void handle_sigint( int signal )
428 {
429     int xReturn;
430
431     xReturn = chdir( BUILD ); /* changing dir to place gmon.out inside build */
432
433     if( xReturn == -1 )
434     {
435         printf( "chdir into %s error is %d\n", BUILD, errno );
436     }
437
438     exit( 2 );
439 }