@ -53,33 +53,44 @@
# include <conio.h>
/* Visual studio intrinsics used so the __debugbreak() function is available
should an assert get hit . */
* should an assert get hit . */
# include <intrin.h>
/* FreeRTOS kernel includes. */
# include "FreeRTOS.h"
# include "task.h"
/* This project provides two demo applications. A simple blinky style demo
application , and a more comprehensive test and demo application . The
mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is used to select between the two .
If mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is 1 then the blinky demo will be built .
The blinky demo is implemented and described in main_blinky . c .
/* FreeRTOS+Trace includes. */
# include "trcRecorder.h"
If mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is not 1 then the comprehensive test and
demo application will be built . The comprehensive test and demo application is
implemented and described in main_full . c . */
# define mainCREATE_SIMPLE_BLINKY_DEMO_ONLY 1
/* This project provides two demo applications. A simple blinky style demo
* application , and a more comprehensive test and demo application . The
* mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is used to select between the two .
*
* If mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is 1 then the blinky demo will be built .
* The blinky demo is implemented and described in main_blinky . c .
*
* If mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is not 1 then the comprehensive test and
* demo application will be built . The comprehensive test and demo application is
* implemented and described in main_full . c . */
# define mainCREATE_SIMPLE_BLINKY_DEMO_ONLY 0
/* This demo uses heap_5.c, and these constants define the sizes of the regions
that make up the total heap . heap_5 is only used for test and example purposes
as this demo could easily create one large heap region instead of multiple
smaller heap regions - in which case heap_4 . c would be the more appropriate
choice . See http : //www.freertos.org/a00111.html for an explanation. */
# define mainREGION_1_SIZE 8201
# define mainREGION_2_SIZE 31905
# define mainREGION_3_SIZE 7807
* that make up the total heap . heap_5 is only used for test and example purposes
* as this demo could easily create one large heap region instead of multiple
* smaller heap regions - in which case heap_4 . c would be the more appropriate
* choice . See http : //www.freertos.org/a00111.html for an explanation. */
# define mainREGION_1_SIZE 8201
# define mainREGION_2_SIZE 23905
# define mainREGION_3_SIZE 16807
/* This demo allows for users to perform actions with the keyboard. */
# define mainNO_KEY_PRESS_VALUE -1
# define mainOUTPUT_TRACE_KEY 't'
# define mainKEYBOARD_INTERRUPT_YIELD_MS 200
/* This demo allows to save a trace file. */
# define mainTRACE_FILE_NAME "Trace.dump"
/*-----------------------------------------------------------*/
@ -94,8 +105,8 @@ extern void main_full( void );
* Only the comprehensive demo uses application hook ( callback ) functions . See
* https : //www.FreeRTOS.org/a00016.html for more information.
*/
void vFullDemoTickHookFunction ( void ) ;
void vFullDemoIdleFunction ( void ) ;
extern void vFullDemoTickHookFunction ( void ) ;
extern void vFullDemoIdleFunction ( void ) ;
/*
* This demo uses heap_5 . c , so start by defining some heap regions . It is not
@ -103,7 +114,7 @@ void vFullDemoIdleFunction( void );
* region . Heap_5 is only used for test and example purposes . See
* https : //www.FreeRTOS.org/a00111.html for an explanation.
*/
static void prvInitialiseHeap ( void ) ;
static void prvInitialiseHeap ( void ) ;
/*
* Prototypes for the standard FreeRTOS application hook ( callback ) functions
@ -111,10 +122,15 @@ static void prvInitialiseHeap( void );
*/
void vApplicationMallocFailedHook ( void ) ;
void vApplicationIdleHook ( void ) ;
void vApplicationStackOverflowHook ( TaskHandle_t pxTask , char * pcTaskName ) ;
void vApplicationStackOverflowHook ( TaskHandle_t pxTask ,
char * pcTaskName ) ;
void vApplicationTickHook ( void ) ;
void vApplicationGetIdleTaskMemory ( StaticTask_t * * ppxIdleTaskTCBBuffer , StackType_t * * ppxIdleTaskStackBuffer , uint32_t * pulIdleTaskStackSize ) ;
void vApplicationGetTimerTaskMemory ( StaticTask_t * * ppxTimerTaskTCBBuffer , StackType_t * * ppxTimerTaskStackBuffer , uint32_t * pulTimerTaskStackSize ) ;
void vApplicationGetIdleTaskMemory ( StaticTask_t * * ppxIdleTaskTCBBuffer ,
StackType_t * * ppxIdleTaskStackBuffer ,
uint32_t * pulIdleTaskStackSize ) ;
void vApplicationGetTimerTaskMemory ( StaticTask_t * * ppxTimerTaskTCBBuffer ,
StackType_t * * ppxTimerTaskStackBuffer ,
uint32_t * pulTimerTaskStackSize ) ;
/*
* Writes trace data to a disk file when the trace recording is stopped .
@ -122,288 +138,409 @@ void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, Stack
*/
static void prvSaveTraceFile ( void ) ;
/*
* Windows thread function to capture keyboard input from outside of the
* FreeRTOS simulator . This thread passes data safely into the FreeRTOS
* simulator using a stream buffer .
*/
static DWORD WINAPI prvWindowsKeyboardInputThread ( void * pvParam ) ;
/*
* FreeRTOS task function that simulates keyboard interrupts by
* periodically polling data coming from the Windows thread
* capturing keyboard input .
*/
static void prvKeyboardInterruptSimulatorTask ( void * pvParam ) ;
/*
* Keyboard interrupt handler for the blinky demo .
*/
extern void vBlinkyKeyboardInterruptHandler ( int xKeyPressed ) ;
/*-----------------------------------------------------------*/
/* When configSUPPORT_STATIC_ALLOCATION is set to 1 the application writer can
use a callback function to optionally provide the memory required by the idle
and timer tasks . This is the stack that will be used by the timer task . It is
declared here , as a global , so it can be checked by a test that is implemented
in a different file . */
* use a callback function to optionally provide the memory required by the idle
* and timer tasks . This is the stack that will be used by the timer task . It is
* declared here , as a global , so it can be checked by a test that is implemented
* in a different file . */
StackType_t uxTimerTaskStack [ configTIMER_TASK_STACK_DEPTH ] ;
/* Notes if the trace is running or not. */
static BaseType_t xTraceRunning = pdTRUE ;
/* Thread handle for the keyboard input Windows thread. */
static HANDLE xWindowsKeyboardInputThreadHandle = NULL ;
/* This stores the last key pressed that has not been handled.
* Keyboard input is retrieved by the prvWindowsKeyboardInputThread
* Windows thread and stored here . This is then read by the idle
* task and handled appropriately . */
static int xKeyPressed = mainNO_KEY_PRESS_VALUE ;
/*-----------------------------------------------------------*/
int main ( void )
{
/* This demo uses heap_5.c, so start by defining some heap regions. heap_5
is only used for test and example reasons . Heap_4 is more appropriate . See
http : //www.freertos.org/a00111.html for an explanation. */
prvInitialiseHeap ( ) ;
/* Initialise the trace recorder. Use of the trace recorder is optional.
See http : //www.FreeRTOS.org/trace for more information. */
vTraceEnable ( TRC_START ) ;
/* The mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is described at the top
of this file . */
# if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 )
{
main_blinky ( ) ;
}
# else
{
/* Start the trace recording - the recording is written to a file if
configASSERT ( ) is called . */
printf ( " \r \n Trace started. \r \n The trace will be dumped to disk if a call to configASSERT() fails. \r \n " ) ;
printf ( " Uncomment the call to kbhit() in this file to also dump trace with a key press. \r \n " ) ;
uiTraceStart ( ) ;
main_full ( ) ;
}
# endif
return 0 ;
/* This demo uses heap_5.c, so start by defining some heap regions. heap_5
* is only used for test and example reasons . Heap_4 is more appropriate . See
* http : //www.freertos.org/a00111.html for an explanation. */
prvInitialiseHeap ( ) ;
/* Initialise the trace recorder. Use of the trace recorder is optional.
* See http : //www.FreeRTOS.org/trace for more information. */
vTraceEnable ( TRC_START ) ;
/* Start the trace recording - the recording is written to a file if
* configASSERT ( ) is called . */
printf (
" Trace started. \r \n "
" The trace will be dumped to the file \" %s \" whenever a call to configASSERT() \r \n "
" fails or the \' %c \' key is pressed. \r \n "
" Note that the trace output uses the ring buffer mode, meaning that the output trace \r \n "
" will only be the most recent data able to fit within the trace recorder buffer. \r \n " ,
mainTRACE_FILE_NAME , mainOUTPUT_TRACE_KEY ) ;
traceSTART ( ) ;
/* Start keyboard input handling thread. */
xWindowsKeyboardInputThreadHandle = CreateThread (
NULL , /* Pointer to thread security attributes. */
0 , /* Initial thread stack size, in bytes. */
prvWindowsKeyboardInputThread , /* Pointer to thread function. */
NULL , /* Argument for new thread. */
0 , /* Creation flags. */
NULL ) ;
/* Use the cores that are not used by the FreeRTOS tasks. */
SetThreadAffinityMask ( xWindowsKeyboardInputThreadHandle , ~ 0x01u ) ;
/* Start keyboard interrupt simulator task. */
xTaskCreate (
prvKeyboardInterruptSimulatorTask , /* The function that implements the task. */
" KeyboardInterrupt " , /* The text name assigned to the task - for debug only as it is not used by the kernel. */
configMINIMAL_STACK_SIZE , /* The size of the stack to allocate to the task. */
NULL , /* The parameter passed to the task - not used in this simple case. */
configMAX_PRIORITIES - 1 , /* The priority assigned to the task. The priority is very high as this task simulates an interrupt coming from the keyboard. */
NULL ) ; /* The task handle is not required, so NULL is passed. */
/* The mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is described at the top
* of this file . */
# if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 )
{
main_blinky ( ) ;
}
# else
{
main_full ( ) ;
}
# endif /* if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 ) */
return 0 ;
}
/*-----------------------------------------------------------*/
void vApplicationMallocFailedHook ( void )
{
/* vApplicationMallocFailedHook() will only be called if
configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig . h . It is a hook
function that will get called if a call to pvPortMalloc ( ) fails .
pvPortMalloc ( ) is called internally by the kernel whenever a task , queue ,
timer or semaphore is created . It is also called by various parts of the
demo application . If heap_1 . c , heap_2 . c or heap_4 . c is being used , then the
size of the heap available to pvPortMalloc ( ) is defined by
configTOTAL_HEAP_SIZE in FreeRTOSConfig . h , and the xPortGetFreeHeapSize ( )
API function can be used to query the size of free heap space that remains
( although it does not provide information on how the remaining heap might be
fragmented ) . See http : //www.freertos.org/a00111.html for more
information . */
vAssertCalled ( __LINE__ , __FILE__ ) ;
/* vApplicationMallocFailedHook() will only be called if
* configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig . h . It is a hook
* function that will get called if a call to pvPortMalloc ( ) fails .
* pvPortMalloc ( ) is called internally by the kernel whenever a task , queue ,
* timer or semaphore is created . It is also called by various parts of the
* demo application . If heap_1 . c , heap_2 . c or heap_4 . c is being used , then the
* size of the heap available to pvPortMalloc ( ) is defined by
* configTOTAL_HEAP_SIZE in FreeRTOSConfig . h , and the xPortGetFreeHeapSize ( )
* API function can be used to query the size of free heap space that remains
* ( although it does not provide information on how the remaining heap might be
* fragmented ) . See http : //www.freertos.org/a00111.html for more
* information . */
vAssertCalled ( __LINE__ , __FILE__ ) ;
}
/*-----------------------------------------------------------*/
void vApplicationIdleHook ( void )
{
/* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set
to 1 in FreeRTOSConfig . h . It will be called on each iteration of the idle
task . It is essential that code added to this hook function never attempts
to block in any way ( for example , call xQueueReceive ( ) with a block time
specified , or call vTaskDelay ( ) ) . If application tasks make use of the
vTaskDelete ( ) API function to delete themselves then it is also important
that vApplicationIdleHook ( ) is permitted to return to its calling function ,
because it is the responsibility of the idle task to clean up memory
allocated by the kernel to any task that has since deleted itself . */
/* Uncomment the following code to allow the trace to be stopped with any
key press . The code is commented out by default as the kbhit ( ) function
interferes with the run time behaviour . */
/*
if ( _kbhit ( ) ! = pdFALSE )
{
if ( xTraceRunning = = pdTRUE )
{
vTraceStop ( ) ;
prvSaveTraceFile ( ) ;
xTraceRunning = pdFALSE ;
}
}
*/
# if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY != 1 )
{
/* Call the idle task processing used by the full demo. The simple
blinky demo does not use the idle task hook . */
vFullDemoIdleFunction ( ) ;
}
# endif
/* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set
* to 1 in FreeRTOSConfig . h . It will be called on each iteration of the idle
* task . It is essential that code added to this hook function never attempts
* to block in any way ( for example , call xQueueReceive ( ) with a block time
* specified , or call vTaskDelay ( ) ) . If application tasks make use of the
* vTaskDelete ( ) API function to delete themselves then it is also important
* that vApplicationIdleHook ( ) is permitted to return to its calling function ,
* because it is the responsibility of the idle task to clean up memory
* allocated by the kernel to any task that has since deleted itself . */
# if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY != 1 )
{
/* Call the idle task processing used by the full demo. The simple
* blinky demo does not use the idle task hook . */
vFullDemoIdleFunction ( ) ;
}
# endif
}
/*-----------------------------------------------------------*/
void vApplicationStackOverflowHook ( TaskHandle_t pxTask , char * pcTaskName )
void vApplicationStackOverflowHook ( TaskHandle_t pxTask ,
char * pcTaskName )
{
( void ) pcTaskName ;
( void ) pxTask ;
/* Run time stack overflow checking is performed if
configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook
function is called if a stack overflow is detected . This function is
provided as an example only as stack overflow checking does not function
when running the FreeRTOS Windows port . */
vAssertCalled ( __LINE__ , __FILE__ ) ;
( void ) pcTaskName ;
( void ) pxTask ;
/* Run time stack overflow checking is performed if
* configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook
* function is called if a stack overflow is detected . This function is
* provided as an example only as stack overflow checking does not function
* when running the FreeRTOS Windows port . */
vAssertCalled ( __LINE__ , __FILE__ ) ;
}
/*-----------------------------------------------------------*/
void vApplicationTickHook ( void )
{
/* This function will be called by each tick interrupt if
configUSE_TICK_HOOK is set to 1 in FreeRTOSConfig . h . User code can be
added here , but the tick hook is called from an interrupt context , so
code must not attempt to block , and only the interrupt safe FreeRTOS API
functions can be used ( those that end in FromISR ( ) ) . */
# if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY != 1 )
{
vFullDemoTickHookFunction ( ) ;
}
# endif /* mainCREATE_SIMPLE_BLINKY_DEMO_ONLY */
/* This function will be called by each tick interrupt if
* configUSE_TICK_HOOK is set to 1 in FreeRTOSConfig . h . User code can be
* added here , but the tick hook is called from an interrupt context , so
* code must not attempt to block , and only the interrupt safe FreeRTOS API
* functions can be used ( those that end in FromISR ( ) ) . */
# if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY != 1 )
{
vFullDemoTickHookFunction ( ) ;
}
# endif /* mainCREATE_SIMPLE_BLINKY_DEMO_ONLY */
}
/*-----------------------------------------------------------*/
void vApplicationDaemonTaskStartupHook ( void )
{
/* This function will be called once only, when the daemon task starts to
execute ( sometimes called the timer task ) . This is useful if the
application includes initialisation code that would benefit from executing
after the scheduler has been started . */
/* This function will be called once only, when the daemon task starts to
* execute ( sometimes called the timer task ) . This is useful if the
* application includes initialisation code that would benefit from executing
* after the scheduler has been started . */
}
/*-----------------------------------------------------------*/
void vAssertCalled ( unsigned long ulLine , const char * const pcFileName )
void vAssertCalled ( unsigned long ulLine ,
const char * const pcFileName )
{
static BaseType_t xPrinted = pdFALSE ;
volatile uint32_t ulSetToNonZeroInDebuggerToContinue = 0 ;
/* Called if an assertion passed to configASSERT() fails. See
http : //www.freertos.org/a00110.html#configASSERT for more information. */
/* Parameters are not used. */
( void ) ulLine ;
( void ) pcFileName ;
printf ( " ASSERT! Line %ld, file %s, GetLastError() %ld \r \n " , ulLine , pcFileName , GetLastError ( ) ) ;
taskENTER_CRITICAL ( ) ;
{
/* Stop the trace recording . */
if ( xPrinted = = pdFALSE )
{
xPrinted = pdTRUE ;
if ( xTraceRunning = = pdTRUE )
{
vTraceStop ( ) ;
prvSaveTraceFile ( ) ;
}
}
/* Cause debugger break point if being debugged. */
__debugbreak ( ) ;
/* You can step out of this function to debug the assertion by using
the debugger to set ulSetToNonZeroInDebuggerToContinue to a non - zero
value . */
while ( ulSetToNonZeroInDebuggerToContinue = = 0 )
{
__asm { NOP } ;
__asm { NOP } ;
}
}
taskEXIT_CRITICAL ( ) ;
static BaseType_t xPrinted = pdFALSE ;
volatile uint32_t ulSetToNonZeroInDebuggerToContinue = 0 ;
/* Called if an assertion passed to configASSERT() fails. See
* http : //www.freertos.org/a00110.html#configASSERT for more information. */
/* Parameters are not used. */
( void ) ulLine ;
( void ) pcFileName ;
taskENTER_CRITICAL ( ) ;
{
printf ( " ASSERT! Line %ld, file %s, GetLastError() %ld \r \n " , ulLine , pcFileName , GetLastError ( ) ) ;
/* Stop the trace recording and save the trace . */
vTraceStop ( ) ;
prvSaveTraceFile ( ) ;
/* Cause debugger break point if being debugged. */
__debugbreak ( ) ;
/* You can step out of this function to debug the assertion by using
* the debugger to set ulSetToNonZeroInDebuggerToContinue to a non - zero
* value . */
while ( ulSetToNonZeroInDebuggerToContinue = = 0 )
{
__asm {
NOP
} ;
__asm {
NOP
} ;
}
/* Re-enable the trace recording. */
vTraceEnable ( TRC_START ) ;
}
taskEXIT_CRITICAL ( ) ;
}
/*-----------------------------------------------------------*/
static void prvSaveTraceFile ( void )
{
FILE * pxOutputFile ;
fopen_s ( & pxOutputFile , " Trace.dump " , " wb " ) ;
if ( pxOutputFile ! = NULL )
{
fwrite ( RecorderDataPtr , sizeof ( RecorderDataType ) , 1 , pxOutputFile ) ;
fclose ( pxOutputFile ) ;
printf ( " \r \n Trace output saved to Trace.dump \r \n " ) ;
}
else
{
printf ( " \r \n Failed to create trace dump file \r \n " ) ;
}
FILE * pxOutputFile ;
fopen_s ( & pxOutputFile , mainTRACE_FILE_NAME , " wb " ) ;
if ( pxOutputFile ! = NULL )
{
fwrite ( RecorderDataPtr , sizeof ( RecorderDataType ) , 1 , pxOutputFile ) ;
fclose ( pxOutputFile ) ;
printf ( " \r \n Trace output saved to %s \r \n \r \n " , mainTRACE_FILE_NAME ) ;
}
else
{
printf ( " \r \n Failed to create trace dump file \r \n \r \n " ) ;
}
}
/*-----------------------------------------------------------*/
static void prvInitialiseHeap ( void )
static void prvInitialiseHeap ( void )
{
/* The Windows demo could create one large heap region, in which case it would
be appropriate to use heap_4 . However , purely for demonstration purposes ,
heap_5 is used instead , so start by defining some heap regions . No
initialisation is required when any other heap implementation is used . See
http : //www.freertos.org/a00111.html for more information.
The xHeapRegions structure requires the regions to be defined in start address
order , so this just creates one big array , then populates the structure with
offsets into the array - with gaps in between and messy alignment just for test
purposes . */
static uint8_t ucHeap [ configTOTAL_HEAP_SIZE ] ;
volatile uint32_t ulAdditionalOffset = 19 ; /* Just to prevent 'condition is always true' warnings in configASSERT(). */
const HeapRegion_t xHeapRegions [ ] =
{
/* Start address with dummy offsets Size */
{ ucHeap + 1 , mainREGION_1_SIZE } ,
{ ucHeap + 15 + mainREGION_1_SIZE , mainREGION_2_SIZE } ,
{ ucHeap + 19 + mainREGION_1_SIZE + mainREGION_2_SIZE , mainREGION_3_SIZE } ,
{ NULL , 0 }
} ;
/* Sanity check that the sizes and offsets defined actually fit into the
array . */
configASSERT ( ( ulAdditionalOffset + mainREGION_1_SIZE + mainREGION_2_SIZE + mainREGION_3_SIZE ) < configTOTAL_HEAP_SIZE ) ;
/* Prevent compiler warnings when configASSERT() is not defined. */
( void ) ulAdditionalOffset ;
vPortDefineHeapRegions ( xHeapRegions ) ;
* be appropriate to use heap_4 . However , purely for demonstration purposes ,
* heap_5 is used instead , so start by defining some heap regions . No
* initialisation is required when any other heap implementation is used . See
* http : //www.freertos.org/a00111.html for more information.
*
* The xHeapRegions structure requires the regions to be defined in start address
* order , so this just creates one big array , then populates the structure with
* offsets into the array - with gaps in between and messy alignment just for test
* purposes . */
static uint8_t ucHeap [ configTOTAL_HEAP_SIZE ] ;
volatile uint32_t ulAdditionalOffset = 19 ; /* Just to prevent 'condition is always true' warnings in configASSERT(). */
const HeapRegion_t xHeapRegions [ ] =
{
/* Start address with dummy offsets Size */
{ ucHeap + 1 , mainREGION_1_SIZE } ,
{ ucHeap + 15 + mainREGION_1_SIZE , mainREGION_2_SIZE } ,
{ ucHeap + 19 + mainREGION_1_SIZE + mainREGION_2_SIZE , mainREGION_3_SIZE } ,
{ NULL , 0 }
} ;
/* Sanity check that the sizes and offsets defined actually fit into the
* array . */
configASSERT ( ( ulAdditionalOffset + mainREGION_1_SIZE + mainREGION_2_SIZE + mainREGION_3_SIZE ) < configTOTAL_HEAP_SIZE ) ;
/* Prevent compiler warnings when configASSERT() is not defined. */
( void ) ulAdditionalOffset ;
vPortDefineHeapRegions ( xHeapRegions ) ;
}
/*-----------------------------------------------------------*/
/* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an
implementation of vApplicationGetIdleTaskMemory ( ) to provide the memory that is
used by the Idle task . */
void vApplicationGetIdleTaskMemory ( StaticTask_t * * ppxIdleTaskTCBBuffer , StackType_t * * ppxIdleTaskStackBuffer , uint32_t * pulIdleTaskStackSize )
* implementation of vApplicationGetIdleTaskMemory ( ) to provide the memory that is
* used by the Idle task . */
void vApplicationGetIdleTaskMemory ( StaticTask_t * * ppxIdleTaskTCBBuffer ,
StackType_t * * ppxIdleTaskStackBuffer ,
uint32_t * pulIdleTaskStackSize )
{
/* If the buffers to be provided to the Idle task are declared inside this
function then they must be declared static - otherwise they will be allocated on
the stack and so not exists after this function exits . */
static StaticTask_t xIdleTaskTCB ;
static StackType_t uxIdleTaskStack [ configMINIMAL_STACK_SIZE ] ;
/* Pass out a pointer to the StaticTask_t structure in which the Idle task's
state will be stored . */
* ppxIdleTaskTCBBuffer = & xIdleTaskTCB ;
/* Pass out the array that will be used as the Idle task's stack. */
* ppxIdleTaskStackBuffer = uxIdleTaskStack ;
/* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
Note that , as the array is necessarily of type StackType_t ,
configMINIMAL_STACK_SIZE is specified in words , not bytes . */
* pulIdleTaskStackSize = configMINIMAL_STACK_SIZE ;
* function then they must be declared static - otherwise they will be allocated on
* the stack and so not exists after this function exits . */
static StaticTask_t xIdleTaskTCB ;
static StackType_t uxIdleTaskStack [ configMINIMAL_STACK_SIZE ] ;
/* Pass out a pointer to the StaticTask_t structure in which the Idle task's
* state will be stored . */
* ppxIdleTaskTCBBuffer = & xIdleTaskTCB ;
/* Pass out the array that will be used as the Idle task's stack. */
* ppxIdleTaskStackBuffer = uxIdleTaskStack ;
/* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
* Note that , as the array is necessarily of type StackType_t ,
* configMINIMAL_STACK_SIZE is specified in words , not bytes . */
* pulIdleTaskStackSize = configMINIMAL_STACK_SIZE ;
}
/*-----------------------------------------------------------*/
/* configUSE_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
application must provide an implementation of vApplicationGetTimerTaskMemory ( )
to provide the memory that is used by the Timer service task . */
void vApplicationGetTimerTaskMemory ( StaticTask_t * * ppxTimerTaskTCBBuffer , StackType_t * * ppxTimerTaskStackBuffer , uint32_t * pulTimerTaskStackSize )
* application must provide an implementation of vApplicationGetTimerTaskMemory ( )
* to provide the memory that is used by the Timer service task . */
void vApplicationGetTimerTaskMemory ( StaticTask_t * * ppxTimerTaskTCBBuffer ,
StackType_t * * ppxTimerTaskStackBuffer ,
uint32_t * pulTimerTaskStackSize )
{
/* If the buffers to be provided to the Timer task are declared inside this
function then they must be declared static - otherwise they will be allocated on
the stack and so not exists after this function exits . */
static StaticTask_t xTimerTaskTCB ;
* function then they must be declared static - otherwise they will be allocated on
* the stack and so not exists after this function exits . */
static StaticTask_t xTimerTaskTCB ;
/* Pass out a pointer to the StaticTask_t structure in which the Timer
* task ' s state will be stored . */
* ppxTimerTaskTCBBuffer = & xTimerTaskTCB ;
/* Pass out the array that will be used as the Timer task's stack. */
* ppxTimerTaskStackBuffer = uxTimerTaskStack ;
/* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
* Note that , as the array is necessarily of type StackType_t ,
* configMINIMAL_STACK_SIZE is specified in words , not bytes . */
* pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH ;
}
/*-----------------------------------------------------------*/
/*
* Windows thread function to capture keyboard input from outside of the
* FreeRTOS simulator . This thread passes data into the simulator using
* an integer .
*/
static DWORD WINAPI prvWindowsKeyboardInputThread ( void * pvParam )
{
( void ) pvParam ;
for ( ; ; )
{
xKeyPressed = _getch ( ) ;
}
}
/*-----------------------------------------------------------*/
/* Pass out a pointer to the StaticTask_t structure in which the Timer
task ' s state will be stored . */
* ppxTimerTaskTCBBuffer = & xTimerTaskTCB ;
static void prvKeyboardInterruptSimulatorTask ( void * pvParam )
{
( void ) pvParam ;
for ( ; ; )
{
/* Handle keyboard input. */
switch ( xKeyPressed )
{
case mainNO_KEY_PRESS_VALUE :
break ;
case mainOUTPUT_TRACE_KEY :
/* Saving the trace file requires Windows system calls, so enter a critical
section to prevent deadlock or errors resulting from calling a Windows
system call from within the FreeRTOS simulator . */
taskENTER_CRITICAL ( ) ;
{
vTraceStop ( ) ;
prvSaveTraceFile ( ) ;
vTraceEnable ( TRC_START ) ;
}
taskEXIT_CRITICAL ( ) ;
break ;
default :
# if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 )
{
/* Call the keyboard interrupt handler for the blinky demo. */
vBlinkyKeyboardInterruptHandler ( xKeyPressed ) ;
}
# endif
break ;
}
/* Clear the handled key press. */
xKeyPressed = mainNO_KEY_PRESS_VALUE ;
/* Yield to allow other tasks to run. */
vTaskDelay ( pdMS_TO_TICKS ( mainKEYBOARD_INTERRUPT_YIELD_MS ) ) ;
}
}
/* Pass out the array that will be used as the Timer task's stack. */
* ppxTimerTaskStackBuffer = uxTimerTaskStack ;
/* The below code is used by the trace recorder for timing . */
static uint32_t ulEntryTime = 0 ;
/* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
Note that , as the array is necessarily of type StackType_t ,
configMINIMAL_STACK_SIZE is specified in words , not bytes . */
* pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH ;
void vTraceTimerReset ( void )
{
ulEntryTime = xTaskGetTickCount ( ) ;
}
uint32_t uiTraceTimerGetFrequency ( void )
{
return configTICK_RATE_HZ ;
}
uint32_t uiTraceTimerGetValue ( void )
{
return ( xTaskGetTickCount ( ) - ulEntryTime ) ;
}