/* Define an array that the task will both read from and write to. Make sure the size and alignment are appropriate for an MPU region (note this uses GCCsyntax). */staticunsignedchar ucOneKByte[ 1024 ] __attribute__((align( 1024 )));/* Define an array of MemoryRegion_t structures that configures an MPU regionallowing read/write access for 1024 bytes starting at the beginning of the ucOneKByte array. The other two of the maximum three definable regions are unused,so set to zero. */staticconstMemoryRegion_t xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] ={ /* Base address Length Parameters */ { ucOneKByte,1024, portMPU_REGION_READ_WRITE }, { 0,0,0 }, { 0,0,0 }};voidvATask( void*pvParameters ){ /* This task was created using xTaskCreateRestricted() to have access to a maximum of three MPU controlled memory regions. At some point it is required that these MPU regions are replaced with those defined in the xAltRegions const structure defined above. Use a call to vTaskAllocateMPURegions() for this purpose. NULL is used as the task handle to indicate that the change should be applied to the calling task.*/vTaskAllocateMPURegions( NULL, xAltRegions ); /* Now the task can continue its function, but from this point on can only access its stack and the ucOneKByte array (unless any other statically defined or shared regions have been declared elsewhere). */}
voidvAFunction( TaskHandle_t xTask ){ /* The task referenced by xTask is blocked to wait for something that the task calling this function has determined will never happen. Force the task referenced by xTask out of the Blocked state. */if( xTaskAbortDelay( xTask )== pdFAIL) { /* The task referenced by xTask was not in the Blocked state anyway. */ }else { /* The task referenced by xTask was in the Blocked state, but is not now. */ }}
/* Define a hook (callback) function – using the required prototype as demonstrated by Listing 8*/staticBaseType_tprvExampleTaskHook( void* pvParameter ){ /* Perform an action - this could be anything. In this example the hook is used to output debug trace information. pxCurrentTCB is the handle of the currently executing task. (vWriteTrace() is not an API function, its just used as an example.)*/vWriteTrace( pxCurrentTCB ); /* This example does not make use of the hook return value so just returns 0 in every case. */return0;}/* Define an example task that makes use of its tag value. */voidvAnotherTask( void*pvParameters ){ /* vTaskSetApplicationTaskTag() sets the ‘tag’ value associated with a task. NULL is used in place of a valid task handle to indicate that it should be the tag value of the calling task that gets set. In this example the ‘value’ being set is the hook function. */vTaskSetApplicationTaskTag( NULL, prvExampleTaskHook );for( ;; ) { /* The rest of the task code goes here. */ }}/* Define the traceTASK_SWITCHED_OUT() macro to call the hook function of eachtask that is switched out. pxCurrentTCB points to the handle of the currentlyrunning task. */#definetraceTASK_SWITCHED_OUT() xTaskCallApplicationTaskHook( pxCurrentTCB,0 )
/* Driver library function used to receive uxWantedBytes from an Rx buffer that is filled by a UART interrupt. If there are not enough bytes in the Rx buffer then the task enters the Blocked state until it is notified that more data has been placed into the buffer. If there is still not enough data then the task re-enters the Blocked state, and xTaskCheckForTimeOut() is used to re-calculate the Block time to ensure the total amount of time spent in the Blocked state does not exceed MAX_TIME_TO_WAIT. This continues until either the buffer contains at least uxWantedBytes bytes, or the total amount of time spent in the Blocked state reaches MAX_TIME_TO_WAIT – at which point the task reads however many bytes are available up to a maximum of uxWantedBytes.*/size_txUART_Receive(uint8_t*pucBuffer,size_t uxWantedBytes ){size_t uxReceived =0;TickType_t xTicksToWait = MAX_TIME_TO_WAIT;TimeOut_t xTimeOut; /* Initialize xTimeOut. This records the time at which this function was entered. */vTaskSetTimeOutState( &xTimeOut ); /* Loop until the buffer contains the wanted number of bytes, or a timeout occurs. */while( UART_bytes_in_rx_buffer( pxUARTInstance )< uxWantedBytes ) { /* The buffer didn’t contain enough data so this task is going to enter the Blocked state. Adjusting xTicksToWait to account for any time that has been spent in the Blocked state within this function so far to ensure the total amount of time spent in the Blocked state does not exceed MAX_TIME_TO_WAIT. */if( xTaskCheckForTimeOut( &xTimeOut,&xTicksToWait )!= pdFALSE ) { /* Timed out before the wanted number of bytes were available, exit the loop. */break; } /* Wait for a maximum of xTicksToWait ticks to be notified that the receive interrupt has placed more data intothe buffer. */ulTaskNotifyTake( pdTRUE, xTicksToWait ); } /* Attempt to read uxWantedBytes from the receive buffer into pucBuffer. The actual number of bytes read (which might be less than uxWantedBytes) is returned. */ uxReceived =UART_read_from_receive_buffer( pxUARTInstance, pucBuffer, uxWantedBytes );return uxReceived;}
/* Define a structure called xStruct and a variable of type xStruct. These are just used to demonstrate a parameter being passed into a task function. */typedefstruct A_STRUCT{char cStructMember1;char cStructMember2;} xStruct; /* Define a variable of the type xStruct to pass as the task parameter. */xStruct xParameter = { 1,2 };/* Define the task that will be created. Note the name of the function that implements the task is used as the first parameter in the call to xTaskCreate() below. */voidvTaskCode( void* pvParameters ){ xStruct *pxParameters; /* Cast the void * parameter back to the required type. */ pxParameters = ( xStruct * ) pvParameters; /* The parameter can now be accessed as expected. */if( pxParameters->cStructMember1 !=1 ) { /* Etc. */ } /* Enter an infinite loop to perform the task processing. */for( ;; ) { /* Task code goes here. */ }} /* Definea function that creates a task. This could be called either before or after the scheduler has been started. */voidvAnotherFunction( void ){ TaskHandle_txHandle; /* Create the task. */if( xTaskCreate( vTaskCode, /* Pointer to the function that implements the task. */"Demo task", /* Text name given to the task. */ STACK_SIZE, /* The size of the stack that should be created for the task. This is defined in words, not bytes. */ (void*) &xParameter, /* A reference to xParameters is used as the task parameter. This is cast to a void * to prevent compiler warnings. */ TASK_PRIORITY, /* The priority to assign to the newly created task.*/&xHandle /* The handle to the task being created will be placed in xHandle. */ )!= pdPASS ) { /* The task could not be created as there was insufficient heap memory remaining. If heap_1.c, heap_2.c or heap_4.c are included in the project then this situation can be trapped using the vApplicationMallocFailedHook() callback (or ‘hook’) function,and the amount of FreeRTOS heap memory that remains unallocated can be queried using the xPortGetFreeHeapSize() API function.*/ }else { /* The task was created successfully. The handle can now be used in other API functions, for example to change the priority of the task.*/vTaskPrioritySet( xHandle,2 ); } }
/* Dimensions the buffer that the task being created will use as its stack. NOTE: This is thenumber of words the stack will hold, not the number of bytes. For example, if each stack itemis 32-bits, and this is set to 100, then 400 bytes (100 * 32-bits) will be allocated. */#defineSTACK_SIZE200/* Structure that will hold the TCB of the task being created. */StaticTask_t xTaskBuffer;/* Buffer that the task being created will use as its stack. Note this is an array ofStackType_t variables. The size of StackType_t is dependent on the RTOS port. */StackType_t xStack[ STACK_SIZE ];/* Function that implements the task being created. */voidvTaskCode( void* pvParameters ){ /* The parameter value is expected to be 1 as 1 is passed in the pvParameters parameter in the call to xTaskCreateStatic(). */configASSERT( ( uint32_t ) pvParameters ==1UL );for( ;; ) { /* Task code goes here. */ }}/* Function that creates a task. */voidvFunction( void ){TaskHandle_t xHandle =NULL; /* Create the task without using any dynamic memory allocation. */ xHandle =xTaskCreateStatic( vTaskCode, /* Function that implements the task. */"NAME", /* Text name for the task. */ STACK_SIZE, /* The number of indexes in the xStack array. */ ( void* ) 1, /* Parameter passed into the task. */ tskIDLE_PRIORITY,/* Priority at which the task is created. */ xStack, /* Array to use as the task's stack. */&xTaskBuffer ); /* Variable to hold the task's data structure. */ /* puxStackBuffer and pxTaskBuffer were not NULL, so the task will have been created, and xHandle will be the task's handle. Use the handle to suspend the task. */vTaskSuspend( xHandle );}