/* 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). */
static unsigned char ucOneKByte[ 1024 ] __attribute__((align( 1024 )));
/* Define an array of MemoryRegion_t structures that configures an MPU region
allowing
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. */
static const MemoryRegion_t xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] =
{
/* Base address Length Parameters */
{ ucOneKByte, 1024, portMPU_REGION_READ_WRITE },
{ 0, 0, 0 },
{ 0, 0, 0 }
};
void vATask( 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). */
}
void vAFunction( 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*/
static BaseType_t prvExampleTaskHook( 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. */
return 0;
}
/* Define an example task that makes use of its tag value. */
void vAnotherTask( 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 each
task that is switched out. pxCurrentTCB points to the handle of the currently
running task. */
#define traceTASK_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_t xUART_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. */
typedef struct 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. */
void vTaskCode( 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. */
void vAnotherFunction( 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 the
number of words the stack will hold, not the number of bytes. For example, if each stack item
is 32-bits, and this is set to 100, then 400 bytes (100 * 32-bits) will be allocated. */
#define STACK_SIZE 200
/* 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 of
StackType_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. */
void vTaskCode( 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. */
void vFunction( 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 );
}