Core kernel files:

+ Change how queues are allocated and deleted so only one pvPortMalloc() or vPortFree() is required in place of the previous 2.
+ Where the TCB is allocated in relation to the stack is now dependent on the stack growth direction.  The stack will not grow into the TCB.
+ Introduce the configAPPLICATION_ALLOCATED_HEAP constant to allow the application to provide the array used by heap_4.c as its heap.  This allows the application writer to use qualifiers on the array to, for example, force the memory into faster RAM.

Demo application:
+ Add demo for SAMA5D4 using IAR.
This commit is contained in:
Richard Barry 2014-10-08 20:31:14 +00:00
parent ee541a347d
commit 9e66637bec
196 changed files with 70548 additions and 72 deletions

View file

@ -719,6 +719,10 @@ extern "C" {
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
#endif
#ifndef configAPPLICATION_ALLOCATED_HEAP
#define configAPPLICATION_ALLOCATED_HEAP 0
#endif
/* Definitions to allow backward compatibility with FreeRTOS versions prior to
V8 if desired. */
#ifndef configENABLE_BACKWARD_COMPATIBILITY

View file

@ -532,7 +532,6 @@ uint32_t ulReturn;
FreeRTOS maintains separate thread and ISR API functions to ensure
interrupt entry is as fast and simple as possible. */
configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
/* Priority grouping: The interrupt controller (GIC) allows the bits
@ -551,5 +550,3 @@ uint32_t ulReturn;
#endif /* configASSERT_DEFINED */
/*-----------------------------------------------------------*/

View file

@ -153,6 +153,7 @@ extern void vPortYield( void );
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portNOP()
#define portPOINTER_SIZE_TYPE uint16_t
/*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */

View file

@ -63,10 +63,12 @@
1 tab == 4 spaces!
*/
/* Standard includes. */
#include <stdio.h>
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
#include <stdio.h>
#ifdef __GNUC__
#include "mmsystem.h"

View file

@ -90,7 +90,13 @@ task.h is included from an application file. */
#define heapBITS_PER_BYTE ( ( size_t ) 8 )
/* Allocate the memory for the heap. */
static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
#if( configAPPLICATION_ALLOCATED_HEAP == 1 )
/* The application writer has already defined the array used for the RTOS
heap - probably so it can be placed in a special segment or address. */
extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
#else
static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
#endif /* configAPPLICATION_ALLOCATED_HEAP */
/* Define the linked list structure. This is used to link free blocks in order
of their memory address. */

View file

@ -120,7 +120,8 @@ zero. */
/*
* Definition of the queue used by the scheduler.
* Items are queued by copy, not reference.
* Items are queued by copy, not reference. See the following link for the
* rationale: http://www.freertos.org/Embedded-RTOS-Queues.html
*/
typedef struct QueueDefinition
{
@ -310,55 +311,68 @@ QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseT
Queue_t *pxNewQueue;
size_t xQueueSizeInBytes;
QueueHandle_t xReturn = NULL;
int8_t *pcAllocatedBuffer;
/* Remove compiler warnings about unused parameters should
configUSE_TRACE_FACILITY not be set to 1. */
( void ) ucQueueType;
/* Allocate the new queue structure. */
if( uxQueueLength > ( UBaseType_t ) 0 )
configASSERT( uxQueueLength > ( UBaseType_t ) 0 );
if( uxItemSize == ( UBaseType_t ) 0 )
{
pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) );
if( pxNewQueue != NULL )
/* There is not going to be a queue storage area. */
xQueueSizeInBytes = ( size_t ) 0;
}
else
{
/* The queue is one byte longer than asked for to make wrap checking
easier/faster. */
xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
}
/* Allocate the new queue structure and storage area. */
pcAllocatedBuffer = ( int8_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes );
if( pcAllocatedBuffer != NULL )
{
pxNewQueue = ( Queue_t * ) pcAllocatedBuffer; /*lint !e826 MISRA The buffer cannot be to small because it was dimensioned by sizeof( Queue_t ) + xQueueSizeInBytes. */
if( uxItemSize == ( UBaseType_t ) 0 )
{
/* Create the list of pointers to queue items. The queue is one byte
longer than asked for to make wrap checking easier/faster. */
xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
pxNewQueue->pcHead = ( int8_t * ) pvPortMalloc( xQueueSizeInBytes );
if( pxNewQueue->pcHead != NULL )
{
/* Initialise the queue members as described above where the
queue type is defined. */
pxNewQueue->uxLength = uxQueueLength;
pxNewQueue->uxItemSize = uxItemSize;
( void ) xQueueGenericReset( pxNewQueue, pdTRUE );
#if ( configUSE_TRACE_FACILITY == 1 )
{
pxNewQueue->ucQueueType = ucQueueType;
}
#endif /* configUSE_TRACE_FACILITY */
#if( configUSE_QUEUE_SETS == 1 )
{
pxNewQueue->pxQueueSetContainer = NULL;
}
#endif /* configUSE_QUEUE_SETS */
traceQUEUE_CREATE( pxNewQueue );
xReturn = pxNewQueue;
}
else
{
traceQUEUE_CREATE_FAILED( ucQueueType );
vPortFree( pxNewQueue );
}
/* No RAM was allocated for the queue storage area, but PC head
cannot be set to NULL because NULL is used as a key to say the queue
is used as a mutex. Therefore just set pcHead to point to the queue
as a benign value that is known to be within the memory map. */
pxNewQueue->pcHead = ( int8_t * ) pxNewQueue;
}
else
{
mtCOVERAGE_TEST_MARKER();
/* Jump past the queue structure to find the location of the queue
storage area - adding the padding bytes to get a better alignment. */
pxNewQueue->pcHead = pcAllocatedBuffer + sizeof( Queue_t );
}
/* Initialise the queue members as described above where the queue type
is defined. */
pxNewQueue->uxLength = uxQueueLength;
pxNewQueue->uxItemSize = uxItemSize;
( void ) xQueueGenericReset( pxNewQueue, pdTRUE );
#if ( configUSE_TRACE_FACILITY == 1 )
{
pxNewQueue->ucQueueType = ucQueueType;
}
#endif /* configUSE_TRACE_FACILITY */
#if( configUSE_QUEUE_SETS == 1 )
{
pxNewQueue->pxQueueSetContainer = NULL;
}
#endif /* configUSE_QUEUE_SETS */
traceQUEUE_CREATE( pxNewQueue );
xReturn = pxNewQueue;
}
else
{
@ -943,7 +957,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
{
traceQUEUE_PEEK( pxQueue );
/* We are not removing the data, so reset our read
/* The data is not being removed, so reset our read
pointer. */
pxQueue->u.pcReadFrom = pcOriginalReadPosition;
@ -1334,7 +1348,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
xReturn = errQUEUE_FULL;
}
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); //0.36
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
return xReturn;
}
@ -1625,6 +1639,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
configASSERT( pxQueue );
configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
configASSERT( pxQueue->uxItemSize != 0 ); /* Can't peek a semaphore. */
/* RTOS ports that support interrupt nesting have the concept of a maximum
system call (or maximum API call) interrupt priority. Interrupts that are
@ -1727,10 +1742,6 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
vQueueUnregisterQueue( pxQueue );
}
#endif
if( pxQueue->pcHead != NULL )
{
vPortFree( pxQueue->pcHead );
}
vPortFree( pxQueue );
}
/*-----------------------------------------------------------*/

View file

@ -412,7 +412,9 @@ static void prvInitialiseTCBVariables( TCB_t * const pxTCB, const char * const p
* currently in the Suspended state, or pdFALSE if the task referenced by xTask
* is in any other state.
*/
static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
#if ( INCLUDE_vTaskSuspend == 1 )
static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
#endif /* INCLUDE_vTaskSuspend */
/*
* Utility to ready all the lists used by the scheduler. This is called
@ -2915,34 +2917,72 @@ static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t *
{
TCB_t *pxNewTCB;
/* Allocate space for the TCB. Where the memory comes from depends on
the implementation of the port malloc function. */
pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
if( pxNewTCB != NULL )
/* If the stack grows down then allocate the stack then the TCB so the stack
does not grow into the TCB. Likewise if the stack grows up then allocate
the TCB then the stack. */
#if( portSTACK_GROWTH > 0 )
{
/* Allocate space for the stack used by the task being created.
The base of the stack memory stored in the TCB so the task can
be deleted later if required. */
pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocAligned( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ), puxStackBuffer ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
/* Allocate space for the TCB. Where the memory comes from depends on
the implementation of the port malloc function. */
pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
if( pxNewTCB->pxStack == NULL )
if( pxNewTCB != NULL )
{
/* Could not allocate the stack. Delete the allocated TCB. */
vPortFree( pxNewTCB );
pxNewTCB = NULL;
/* Allocate space for the stack used by the task being created.
The base of the stack memory stored in the TCB so the task can
be deleted later if required. */
pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocAligned( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ), puxStackBuffer ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
if( pxNewTCB->pxStack == NULL )
{
/* Could not allocate the stack. Delete the allocated TCB. */
vPortFree( pxNewTCB );
pxNewTCB = NULL;
}
}
}
#else /* portSTACK_GROWTH */
{
StackType_t *pxStack;
/* Allocate space for the stack used by the task being created. */
pxStack = ( StackType_t * ) pvPortMallocAligned( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ), puxStackBuffer ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
if( pxStack != NULL )
{
/* Allocate space for the TCB. Where the memory comes from depends
on the implementation of the port malloc function. */
pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
if( pxNewTCB != NULL )
{
/* Store the stack location in the TCB. */
pxNewTCB->pxStack = pxStack;
}
else
{
/* The stack cannot be used as the TCB was not created. Free it
again. */
vPortFree( pxStack );
}
}
else
{
/* Avoid dependency on memset() if it is not required. */
#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
{
/* Just to help debugging. */
( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) usStackDepth * sizeof( StackType_t ) );
}
#endif /* ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) ) */
pxNewTCB = NULL;
}
}
#endif /* portSTACK_GROWTH */
if( pxNewTCB != NULL )
{
/* Avoid dependency on memset() if it is not required. */
#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
{
/* Just to help debugging. */
( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) usStackDepth * sizeof( StackType_t ) );
}
#endif /* ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) ) */
}
return pxNewTCB;
}