mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-08-19 17:48:33 -04:00
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:
parent
ee541a347d
commit
9e66637bec
196 changed files with 70548 additions and 72 deletions
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue