mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-12-09 13:15:15 -05:00
First draft of a CRx MPU Port for FreeRTOS
This commit is contained in:
parent
58f0d36e76
commit
4a74745eb2
6 changed files with 4468 additions and 0 deletions
1332
portable/GCC/ARM_CRx_MPU/mpu_wrappers_v2_asm.S
Normal file
1332
portable/GCC/ARM_CRx_MPU/mpu_wrappers_v2_asm.S
Normal file
File diff suppressed because it is too large
Load diff
516
portable/GCC/ARM_CRx_MPU/mpu_wrappers_v2_asm.h
Normal file
516
portable/GCC/ARM_CRx_MPU/mpu_wrappers_v2_asm.h
Normal file
|
|
@ -0,0 +1,516 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.6.0
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MPU_PROTOTYPES_H
|
||||
#define MPU_PROTOTYPES_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/** Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from
|
||||
* redefining all the API functions to use the MPU wrappers. That should only
|
||||
* be done when task.h is included from an application file. */
|
||||
#ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
#endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
#include "timers.h"
|
||||
#include "event_groups.h"
|
||||
#include "stream_buffer.h"
|
||||
#include "mpu_prototypes.h"
|
||||
#include "mpu_syscall_numbers.h"
|
||||
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
typedef struct xTaskGenericNotifyParams
|
||||
{
|
||||
TaskHandle_t xTaskToNotify;
|
||||
UBaseType_t uxIndexToNotify;
|
||||
uint32_t ulValue;
|
||||
eNotifyAction eAction;
|
||||
uint32_t * pulPreviousNotificationValue;
|
||||
} xTaskGenericNotifyParams_t;
|
||||
|
||||
typedef struct xTaskGenericNotifyWaitParams
|
||||
{
|
||||
UBaseType_t uxIndexToWaitOn;
|
||||
uint32_t ulBitsToClearOnEntry;
|
||||
uint32_t ulBitsToClearOnExit;
|
||||
uint32_t * pulNotificationValue;
|
||||
TickType_t xTicksToWait;
|
||||
} xTaskGenericNotifyWaitParams_t;
|
||||
|
||||
typedef struct xTimerGenericCommandParams
|
||||
{
|
||||
TimerHandle_t xTimer;
|
||||
BaseType_t xCommandID;
|
||||
TickType_t xOptionalValue;
|
||||
BaseType_t * pxHigherPriorityTaskWoken;
|
||||
TickType_t xTicksToWait;
|
||||
} xTimerGenericCommandParams_t;
|
||||
|
||||
typedef struct xEventGroupWaitBitsParams
|
||||
{
|
||||
EventGroupHandle_t xEventGroup;
|
||||
EventBits_t uxBitsToWaitFor;
|
||||
BaseType_t xClearOnExit;
|
||||
BaseType_t xWaitForAllBits;
|
||||
TickType_t xTicksToWait;
|
||||
} xEventGroupWaitBitsParams_t;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
extern TickType_t MPU_xTaskGetTickCount( void ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
UBaseType_t MPU_uxTaskGetNumberOfTasks( void ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
char * MPU_pcTaskGetName( TaskHandle_t xTaskToQuery ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void MPU_vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t MPU_xTaskCheckForTimeOut(
|
||||
TimeOut_t * const pxTimeOut,
|
||||
TickType_t * const pxTicksToWait
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t MPU_xQueueGenericSend(
|
||||
QueueHandle_t xQueue,
|
||||
const void * const pvItemToQueue,
|
||||
TickType_t xTicksToWait,
|
||||
const BaseType_t xCopyPosition
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
UBaseType_t MPU_uxQueueMessagesWaiting( const QueueHandle_t xQueue
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
UBaseType_t MPU_uxQueueSpacesAvailable( const QueueHandle_t xQueue
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t MPU_xQueueReceive(
|
||||
QueueHandle_t xQueue,
|
||||
void * const pvBuffer,
|
||||
TickType_t xTicksToWait
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t MPU_xQueuePeek(
|
||||
QueueHandle_t xQueue,
|
||||
void * const pvBuffer,
|
||||
TickType_t xTicksToWait
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t MPU_xQueueSemaphoreTake( QueueHandle_t xQueue, TickType_t xTicksToWait )
|
||||
__attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t MPU_xStreamBufferSend(
|
||||
StreamBufferHandle_t xStreamBuffer,
|
||||
const void * pvTxData,
|
||||
size_t xDataLengthBytes,
|
||||
TickType_t xTicksToWait
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t MPU_xStreamBufferReceive(
|
||||
StreamBufferHandle_t xStreamBuffer,
|
||||
void * pvRxData,
|
||||
size_t xBufferLengthBytes,
|
||||
TickType_t xTicksToWait
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t MPU_xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t MPU_xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t MPU_xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t MPU_xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t MPU_xStreamBufferSetTriggerLevel(
|
||||
StreamBufferHandle_t xStreamBuffer,
|
||||
size_t xTriggerLevel
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t MPU_xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
EventBits_t MPU_xEventGroupWaitBits(
|
||||
EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToWaitFor,
|
||||
const BaseType_t xClearOnExit,
|
||||
const BaseType_t xWaitForAllBits,
|
||||
TickType_t xTicksToWait
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
EventBits_t MPU_xEventGroupClearBits(
|
||||
EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToClear
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
EventBits_t MPU_xEventGroupSetBits(
|
||||
EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToSet
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
EventBits_t MPU_xEventGroupSync(
|
||||
EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToSet,
|
||||
const EventBits_t uxBitsToWaitFor,
|
||||
TickType_t xTicksToWait
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( INCLUDE_xTaskDelayUntil == 1 )
|
||||
|
||||
BaseType_t MPU_xTaskDelayUntil(
|
||||
TickType_t * const pxPreviousWakeTime,
|
||||
const TickType_t xTimeIncrement
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
#endif /* if ( INCLUDE_xTaskDelayUntil == 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( INCLUDE_xTaskAbortDelay == 1 )
|
||||
|
||||
BaseType_t MPU_xTaskAbortDelay( TaskHandle_t xTask ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
#endif /* if ( INCLUDE_xTaskAbortDelay == 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( INCLUDE_vTaskDelay == 1 )
|
||||
|
||||
void MPU_vTaskDelay( const TickType_t xTicksToDelay ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
#endif /* if ( INCLUDE_vTaskDelay == 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( INCLUDE_uxTaskPriorityGet == 1 )
|
||||
|
||||
UBaseType_t MPU_uxTaskPriorityGet( const TaskHandle_t xTask ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
#endif /* if ( INCLUDE_uxTaskPriorityGet == 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( INCLUDE_eTaskGetState == 1 )
|
||||
|
||||
eTaskState MPU_eTaskGetState( TaskHandle_t xTask ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
#endif /* if ( INCLUDE_eTaskGetState == 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( INCLUDE_xTaskGetIdleTaskHandle == 1 )
|
||||
|
||||
TaskHandle_t MPU_xTaskGetIdleTaskHandle( void ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
#endif /* if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( INCLUDE_vTaskSuspend == 1 )
|
||||
|
||||
void MPU_vTaskSuspend( TaskHandle_t xTaskToSuspend ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
void MPU_vTaskResume( TaskHandle_t xTaskToResume ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
#endif /* if ( INCLUDE_vTaskSuspend == 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configGENERATE_RUN_TIME_STATS == 1 )
|
||||
configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetRunTimeCounter( const TaskHandle_t xTask
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetRunTimePercent( const TaskHandle_t xTask
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
#if( INCLUDE_xTaskGetIdleTaskHandle == 1 ) )
|
||||
configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetIdleRunTimePercent( void
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetIdleRunTimeCounter( void
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
#endif /* ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) */
|
||||
|
||||
#endif /* if ( ( configGENERATE_RUN_TIME_STATS == 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configUSE_APPLICATION_TASK_TAG == 1 )
|
||||
|
||||
void MPU_vTaskSetApplicationTaskTag(
|
||||
TaskHandle_t xTask,
|
||||
TaskHookFunction_t pxHookFunction
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
TaskHookFunction_t MPU_xTaskGetApplicationTaskTag( TaskHandle_t xTask
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
#endif /* if ( configUSE_APPLICATION_TASK_TAG == 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
|
||||
|
||||
void MPU_vTaskSetThreadLocalStoragePointer(
|
||||
TaskHandle_t xTaskToSet,
|
||||
BaseType_t xIndex,
|
||||
void * pvValue
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
void * MPU_pvTaskGetThreadLocalStoragePointer(
|
||||
TaskHandle_t xTaskToQuery,
|
||||
BaseType_t xIndex
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
#endif /* if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
|
||||
|
||||
UBaseType_t MPU_uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
#endif /* if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 )
|
||||
|
||||
configSTACK_DEPTH_TYPE MPU_uxTaskGetStackHighWaterMark2( TaskHandle_t xTask
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
#endif /* if ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
|
||||
|
||||
TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
#endif /* if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) \
|
||||
) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( INCLUDE_xTaskGetSchedulerState == 1 )
|
||||
|
||||
BaseType_t MPU_xTaskGetSchedulerState( void ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
#endif /* if ( INCLUDE_xTaskGetSchedulerState == 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configUSE_TRACE_FACILITY == 1 )
|
||||
|
||||
void MPU_vTaskGetInfo(
|
||||
TaskHandle_t xTask,
|
||||
TaskStatus_t * pxTaskStatus,
|
||||
BaseType_t xGetFreeStackSpace,
|
||||
eTaskState eState
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
UBaseType_t MPU_uxTaskGetSystemState(
|
||||
TaskStatus_t * const pxTaskStatusArray,
|
||||
const UBaseType_t uxArraySize,
|
||||
configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
UBaseType_t MPU_uxEventGroupGetNumber( void * xEventGroup ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
void MPU_vEventGroupSetNumber( void * xEventGroup, UBaseType_t uxEventGroupNumber )
|
||||
__attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
#endif /*( configUSE_TRACE_FACILITY == 1 )*/
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configUSE_TASK_NOTIFICATIONS == 1 )
|
||||
|
||||
BaseType_t MPU_xTaskGenericNotifyEntry( const xTaskGenericNotifyParams_t * pxParams
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
BaseType_t MPU_xTaskGenericNotifyWaitEntry( const xTaskGenericNotifyWaitParams_t * pxParams
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
uint32_t MPU_ulTaskGenericNotifyTake(
|
||||
UBaseType_t uxIndexToWaitOn,
|
||||
BaseType_t xClearCountOnExit,
|
||||
TickType_t xTicksToWait
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
BaseType_t MPU_xTaskGenericNotifyStateClear(
|
||||
TaskHandle_t xTask,
|
||||
UBaseType_t uxIndexToClear
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
uint32_t MPU_ulTaskGenericNotifyValueClear(
|
||||
TaskHandle_t xTask,
|
||||
UBaseType_t uxIndexToClear,
|
||||
uint32_t ulBitsToClear
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
#endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configUSE_RECURSIVE_MUTEXES == 1 )
|
||||
|
||||
BaseType_t MPU_xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait )
|
||||
__attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
BaseType_t MPU_xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
#if( INCLUDE_xSemaphoreGetMutexHolder == 1 )
|
||||
|
||||
TaskHandle_t MPU_xQueueGetMutexHolder( QueueHandle_t xSemaphore ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
#endif /* ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) */
|
||||
|
||||
#endif /* if ( configUSE_RECURSIVE_MUTEXES == 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configUSE_QUEUE_SETS == 1 )
|
||||
|
||||
QueueSetMemberHandle_t MPU_xQueueSelectFromSet(
|
||||
QueueSetHandle_t xQueueSet,
|
||||
const TickType_t xTicksToWait
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
BaseType_t MPU_xQueueAddToSet(
|
||||
QueueSetMemberHandle_t xQueueOrSemaphore,
|
||||
QueueSetHandle_t xQueueSet
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
#endif /* if ( configUSE_QUEUE_SETS == 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configQUEUE_REGISTRY_SIZE > 0 )
|
||||
|
||||
void MPU_vQueueAddToRegistry( QueueHandle_t xQueue, const char * pcName )
|
||||
__attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
void MPU_vQueueUnregisterQueue( QueueHandle_t xQueue ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
const char * MPU_pcQueueGetName( QueueHandle_t xQueue ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
#endif /* if ( configQUEUE_REGISTRY_SIZE > 0 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configUSE_TIMERS == 1 )
|
||||
|
||||
void * MPU_pvTimerGetTimerID( const TimerHandle_t xTimer ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
void MPU_vTimerSetTimerID( TimerHandle_t xTimer, void * pvNewID ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
BaseType_t MPU_xTimerIsTimerActive( TimerHandle_t xTimer ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
TaskHandle_t MPU_xTimerGetTimerDaemonTaskHandle( void ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
BaseType_t MPU_xTimerGenericCommandEntry( const xTimerGenericCommandParams_t * pxParams
|
||||
) __attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
const char * MPU_pcTimerGetName( TimerHandle_t xTimer ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
void MPU_vTimerSetReloadMode( TimerHandle_t xTimer, const BaseType_t uxAutoReload )
|
||||
__attribute__( ( naked ) ) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
BaseType_t MPU_xTimerGetReloadMode( TimerHandle_t xTimer ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
UBaseType_t MPU_uxTimerGetReloadMode( TimerHandle_t xTimer ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
TickType_t MPU_xTimerGetPeriod( TimerHandle_t xTimer ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
TickType_t MPU_xTimerGetExpiryTime( TimerHandle_t xTimer ) __attribute__( ( naked )
|
||||
) FREERTOS_SYSTEM_CALL;
|
||||
|
||||
#endif /* if ( configUSE_TIMERS == 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#endif /* MPU_PROTOTYPES_H */
|
||||
760
portable/GCC/ARM_CRx_MPU/port.c
Normal file
760
portable/GCC/ARM_CRx_MPU/port.c
Normal file
|
|
@ -0,0 +1,760 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.6.1
|
||||
* Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||
* all the API functions to use the MPU wrappers. That should only be done when
|
||||
* task.h is included from an application file. */
|
||||
#ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
#endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOSConfig.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "portmacro.h"
|
||||
#include "task.h"
|
||||
#include "mpu_syscall_numbers.h"
|
||||
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/** @brief Variable used to keep track of critical section nesting.
|
||||
* @ingroup Critical Sections
|
||||
* @note
|
||||
* This variable has to be stored as part of the task context and must be
|
||||
* initialised to a non zero value to ensure interrupts don't inadvertently
|
||||
* become unmasked before the scheduler starts. As it is stored as part of the
|
||||
* task context it will be set to 0 when the first task is started.
|
||||
*/
|
||||
PRIVILEGED_DATA volatile uint32_t ulCriticalNesting = 0xFFFF;
|
||||
|
||||
/** @brief Set to 1 to pend a context switch from an ISR.
|
||||
* @ingroup Interrupt Management
|
||||
*/
|
||||
PRIVILEGED_DATA volatile uint32_t ulPortYieldRequired = pdFALSE;
|
||||
|
||||
/** @brief Interrupt nesting depth, used to count the number of interrupts to unwind.
|
||||
* @ingroup Interrupt Management
|
||||
*/
|
||||
PRIVILEGED_DATA volatile uint32_t ulPortInterruptNesting = 0UL;
|
||||
|
||||
/** @brief Variable to track whether or not the scheduler has been started.
|
||||
* @ingroup Scheduler
|
||||
* @note This variable is set to pdTRUE when the scheduler is started.
|
||||
*/
|
||||
PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
|
||||
|
||||
/** @brief Used in portASM.S's IRQ Handler to clear an interrupt.
|
||||
* @ingroup Interrupt Management
|
||||
*/
|
||||
PRIVILEGED_DATA volatile uint32_t ulICCEOIR = configEOI_ADDRESS;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/** @brief Set a FreeRTOS Task's initial context
|
||||
*
|
||||
* @param pxTopOfStack Pointer to where the task's stack starts
|
||||
* @param pxCode Pointer to the function a task will run
|
||||
* @param pvParameters Pointer to any arguments to be passed to the task's function
|
||||
* @param xRunPrivileged Marks if the task is to be run in a privileged CPU mode.
|
||||
* @param xMPUSettings MPU settings to be loaded as part of a task's context
|
||||
* @return StackType_t* Pointer to where to restore the task's context from.
|
||||
*
|
||||
* @ingroup Task Context
|
||||
* @note pxTopOfStack must be a region of memory that is a valid MPU region size.
|
||||
*/
|
||||
StackType_t * pxPortInitialiseStack(
|
||||
StackType_t * pxTopOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters,
|
||||
BaseType_t xRunPrivileged,
|
||||
xMPU_SETTINGS * xMPUSettings
|
||||
) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
/** Setup the initial context of the task. The context is set exactly as
|
||||
* expected by the portRESTORE_CONTEXT() macro. */
|
||||
UBaseType_t ulContextIndex = MAX_CONTEXT_SIZE - 1U;
|
||||
|
||||
/* These two locations are used for SVC entry, fill them for debugging */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = 0xFEED2002;
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = 0xFEED1001;
|
||||
|
||||
if( xRunPrivileged == pdTRUE )
|
||||
{
|
||||
/* Current Program Status and Control Register */
|
||||
xMPUSettings->ulTaskFlags |= portTASK_IS_PRIVILEGED_FLAG;
|
||||
xMPUSettings->ulTaskFlags |= 0x1F000000;
|
||||
xMPUSettings->ulContext[ ulContextIndex ] = SYS_MODE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Current Program Status and Control Register */
|
||||
xMPUSettings->ulTaskFlags &= ( ~portTASK_IS_PRIVILEGED_FLAG );
|
||||
xMPUSettings->ulTaskFlags |= 0x10000000;
|
||||
xMPUSettings->ulContext[ ulContextIndex ] = USER_MODE;
|
||||
}
|
||||
|
||||
if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x00UL )
|
||||
{
|
||||
/* The task will start in THUMB mode, set the bit in the CPSR. */
|
||||
xMPUSettings->ulContext[ ulContextIndex ] |= portTHUMB_MODE_BIT;
|
||||
xMPUSettings->ulTaskFlags |= portSTACK_FRAME_HAS_PADDING_FLAG;
|
||||
}
|
||||
|
||||
/* Decrement ulContextIndex here after setting the CPSR */
|
||||
ulContextIndex--;
|
||||
|
||||
/** First we load the Memory Location of the Task's function.
|
||||
* Task Program Counter */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) pxCode;
|
||||
|
||||
/** A FreeRTOS Task is not designed to return or exit from its function.
|
||||
* As such a default Link Register is provided that will return to an
|
||||
* error handling function.
|
||||
* Task Link Register */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) portTASK_RETURN_ADDRESS;
|
||||
|
||||
/** Set the task's stack pointer to be the bottom of it's stack, since on this
|
||||
* CPU stacks grow upwards.
|
||||
* Task Stack Pointer */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) pxTopOfStack; /* SP */
|
||||
|
||||
/* Next the General Purpose Registers */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0x12121212; /* R12 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0x11111111; /* R11 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0x10101010; /* R10 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0x09090909; /* R9 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0x08080808; /* R8 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0x07070707; /* R7 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0x06060606; /* R6 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0x05050505; /* R5 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0x04040404; /* R4 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0x03030303; /* R3 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0x02020202; /* R2 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0x01010101; /* R1 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) pvParameters; /* R0 */
|
||||
|
||||
#ifdef portENABLE_FPU
|
||||
/* Initial Floating Point Context is the Floating Point Registers (FPRs) */
|
||||
/* There are 16 Double FPRs, D0-D15 on the Cortex-R FPU enabled chips */
|
||||
/* These map to the Single Precision FPRs, S0-S31 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD0000015; /* S31 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD1500000; /* S30 */
|
||||
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD0000014; /* S29 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD1400000; /* S28 */
|
||||
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD0000013; /* S27 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD1300000; /* S26 */
|
||||
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD0000012; /* S25 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD1200000; /* S24 */
|
||||
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD0000011; /* S23 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD1100000; /* S22 */
|
||||
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD0000010; /* S21 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD1000000; /* S20 */
|
||||
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD0000009; /* S19 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD9000000; /* S18 */
|
||||
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD0000008; /* S17 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD8000000; /* S16 */
|
||||
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD0000007; /* S15 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD7000000; /* S14 */
|
||||
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD0000006; /* S13 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD6000000; /* S12 */
|
||||
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD0000005; /* S11 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD5000000; /* S10 */
|
||||
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD0000004; /* S9 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD4000000; /* S8 */
|
||||
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD0000003; /* S7 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD3000000; /* S6 */
|
||||
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD0000002; /* S5 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD2000000; /* S4 */
|
||||
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD0000001; /* S3 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD1000000; /* S2 */
|
||||
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD0000000; /* S1 */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0xD0000000; /* S0 */
|
||||
|
||||
/* Floating Point Status and Control Register */
|
||||
xMPUSettings->ulContext[ ulContextIndex-- ] = ( StackType_t ) 0x00000000; /* FPSR */
|
||||
#endif /* portENABLE_FPU */
|
||||
|
||||
/* The task will start with a critical nesting count of 0. */
|
||||
xMPUSettings->ulContext[ ulContextIndex ] = portNO_CRITICAL_NESTING;
|
||||
|
||||
/* Ensure that the system call stack is double word aligned. */
|
||||
xMPUSettings->xSystemCallStackInfo.pulSystemCallStackPointer = &(
|
||||
xMPUSettings->xSystemCallStackInfo
|
||||
.ulSystemCallStackBuffer[ configSYSTEM_CALL_STACK_SIZE - 1 ]
|
||||
);
|
||||
xMPUSettings->xSystemCallStackInfo.pulSystemCallStackPointer =
|
||||
( uint32_t * ) ( ( uint32_t ) ( xMPUSettings->xSystemCallStackInfo
|
||||
.pulSystemCallStackPointer ) &
|
||||
( uint32_t ) ( ~( portBYTE_ALIGNMENT_MASK ) ) );
|
||||
|
||||
/* This is not NULL only for the duration of a system call. */
|
||||
xMPUSettings->xSystemCallStackInfo.pulTaskStackPointer = NULL;
|
||||
/* Set the System Call LR to go directly to vPortSystemCallExit */
|
||||
xMPUSettings->xSystemCallStackInfo.pulSystemCallLinkRegister = &vPortSystemCallExit;
|
||||
UBaseType_t ulStackIndex;
|
||||
/* Fill the System Call Stack with known values for debugging. */
|
||||
for( ulStackIndex = 0x0; ulStackIndex < configSYSTEM_CALL_STACK_SIZE; ulStackIndex++ )
|
||||
{
|
||||
xMPUSettings->xSystemCallStackInfo.ulSystemCallStackBuffer[ ulStackIndex ] =
|
||||
0x575B | ulStackIndex;
|
||||
}
|
||||
|
||||
/* Return the address where the context of this task should be restored from*/
|
||||
return ( &xMPUSettings->ulContext[ ulContextIndex ] );
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
/** @brief Returns the smallest valid MPU Region size that can hold a number of bytes.
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
* @param ulActualSizeInBytes Number of bytes to find a valid MPU region size for
|
||||
* @return uint32_t The smallest MPU region size that can hold the requested bytes.
|
||||
*/
|
||||
PRIVILEGED_FUNCTION static uint32_t prvGetMPURegionSizeSetting(
|
||||
uint32_t ulActualSizeInBytes
|
||||
);
|
||||
|
||||
static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes
|
||||
) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
uint32_t ulRegionSize, ulReturnValue = 4U;
|
||||
|
||||
/* 32 is the smallest region size, 31 is the largest valid value for
|
||||
* ulReturnValue. */
|
||||
for( ulRegionSize = 32UL; ulReturnValue < 31UL; ( ulRegionSize <<= 1UL ) )
|
||||
{
|
||||
if( ulActualSizeInBytes <= ulRegionSize )
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
ulReturnValue++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Shift the code by one before returning so it can be written directly
|
||||
* into the the correct bit position of the attribute register. */
|
||||
return ulReturnValue << 1UL;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
/** @brief Stores a FreeRTOS Task's MPU Settings in its TCB
|
||||
*
|
||||
* @param xMPUSettings The memory location in the TCB to store MPU settings
|
||||
* @param xRegions The MPU settings being requested by the task.
|
||||
* @param pxBottomOfStack The base address of the Task's Stack
|
||||
* @param ulStackDepth The length of the task's stack.
|
||||
*
|
||||
* @ingroup Task Context
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
* @note pxBottomOfStack must be aligned to a region size of length ulStackDepth.
|
||||
* @note ulStackDepth must be a power of 2 larger than 32 bytes.
|
||||
*/
|
||||
void vPortStoreTaskMPUSettings(
|
||||
xMPU_SETTINGS * xMPUSettings,
|
||||
const struct xMEMORY_REGION * const xRegions,
|
||||
StackType_t * pxBottomOfStack,
|
||||
uint32_t ulStackDepth
|
||||
) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
#if defined( __ARMCC_VERSION )
|
||||
|
||||
/* Declaration when these variable are defined in code instead of being
|
||||
* exported from linker scripts. */
|
||||
extern uint32_t * __SRAM_segment_start__;
|
||||
extern uint32_t * __SRAM_segment_end__;
|
||||
extern uint32_t * __privileged_data_start__;
|
||||
extern uint32_t * __privileged_data_end__;
|
||||
#else
|
||||
/* Declaration when these variable are exported from linker scripts. */
|
||||
extern uint32_t __SRAM_segment_start__[];
|
||||
extern uint32_t __SRAM_segment_end__[];
|
||||
|
||||
#endif /* if defined( __ARMCC_VERSION ) */
|
||||
uint32_t lIndex = 0x0;
|
||||
uint32_t ul = 0x0;
|
||||
|
||||
if( xRegions == NULL )
|
||||
{
|
||||
/* No MPU regions are specified so allow access to all of the RAM. */
|
||||
xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress = ( uint32_t
|
||||
) __SRAM_segment_start__;
|
||||
xMPUSettings->xRegion[ 0 ].ulRegionSize =
|
||||
( prvGetMPURegionSizeSetting(
|
||||
( uint32_t ) __SRAM_segment_end__ - ( uint32_t ) __SRAM_segment_start__
|
||||
) ) |
|
||||
portMPU_REGION_ENABLE;
|
||||
xMPUSettings->xRegion[ 0 ].ulRegionAttribute =
|
||||
portMPU_PRIV_RW_USER_RW_NOEXEC | portMPU_NORMAL_OIWTNOWA_SHARED;
|
||||
|
||||
/* Invalidate all other regions. */
|
||||
for( ul = 1; ul <= portNUM_CONFIGURABLE_REGIONS; ul++ )
|
||||
{
|
||||
xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = 0x0UL;
|
||||
xMPUSettings->xRegion[ ul ].ulRegionSize = 0x0UL;
|
||||
xMPUSettings->xRegion[ ul ].ulRegionAttribute = 0x0UL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This function is called automatically when the task is created - in
|
||||
* which case the stack region parameters will be valid. At all other
|
||||
* times the stack parameters will not be valid and it is assumed that the
|
||||
* stack region has already been configured. */
|
||||
|
||||
if( ulStackDepth > 0 )
|
||||
{
|
||||
uint32_t ulSmallestRegion = prvGetMPURegionSizeSetting( ulStackDepth * 0x4 );
|
||||
/* Define the region that allows access to the stack. */
|
||||
xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress = ( uint32_t ) pxBottomOfStack;
|
||||
xMPUSettings->xRegion[ 0 ].ulRegionSize =
|
||||
ulSmallestRegion | portMPU_REGION_ENABLE;
|
||||
xMPUSettings->xRegion[ 0 ].ulRegionAttribute =
|
||||
portMPU_PRIV_RW_USER_RW_NOEXEC | portMPU_NORMAL_OIWTNOWA_SHARED;
|
||||
}
|
||||
|
||||
for( ul = 1; ul <= portNUM_CONFIGURABLE_REGIONS; ul++ )
|
||||
{
|
||||
if( ( xRegions[ lIndex ] ).ulLengthInBytes > 0UL )
|
||||
{
|
||||
/* Translate the generic region definition contained in
|
||||
* xRegions into the R4 specific MPU settings that are then
|
||||
* stored in xMPUSettings. */
|
||||
xMPUSettings->xRegion[ ul ].ulRegionBaseAddress =
|
||||
( uint32_t ) xRegions[ lIndex ].pvBaseAddress;
|
||||
xMPUSettings->xRegion[ ul ].ulRegionSize =
|
||||
prvGetMPURegionSizeSetting( xRegions[ lIndex ].ulLengthInBytes ) |
|
||||
portMPU_REGION_ENABLE;
|
||||
xMPUSettings->xRegion[ ul ].ulRegionAttribute =
|
||||
xRegions[ lIndex ].ulParameters;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalidate the region. */
|
||||
xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = 0x0UL;
|
||||
xMPUSettings->xRegion[ ul ].ulRegionSize = 0x0UL;
|
||||
xMPUSettings->xRegion[ ul ].ulRegionAttribute = 0x0UL;
|
||||
}
|
||||
|
||||
lIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
/** @brief Set up a default MPU memory Map
|
||||
* @return PRIVILEGED_FUNCTION VOID
|
||||
* @ingroup MPU Control
|
||||
* @note This function shall be called before calling vPortStartFirstTask().
|
||||
* @note This function works by pulling variables from the linker script.
|
||||
* Ensure that the variables used in your linker script match up with the variable names
|
||||
* used at the start of this function.
|
||||
*/
|
||||
PRIVILEGED_FUNCTION static void prvSetupDefaultMPU( void )
|
||||
{
|
||||
#if defined( __ARMCC_VERSION )
|
||||
/* Declaration when these variable are defined in code instead of being
|
||||
* exported from linker scripts. */
|
||||
/* Sections used for FLASH */
|
||||
extern uint32_t * __FLASH_segment_start__;
|
||||
extern uint32_t * __FLASH_segment_end__;
|
||||
extern uint32_t * __privileged_functions_start__;
|
||||
extern uint32_t * __privileged_functions_end__;
|
||||
|
||||
/* Sections used for RAM */
|
||||
extern uint32_t * __SRAM_segment_start__;
|
||||
extern uint32_t * __SRAM_segment_end__;
|
||||
extern uint32_t * __privileged_data_start__;
|
||||
extern uint32_t * __privileged_data_end__;
|
||||
|
||||
/* Sections used for system peripherals, such as UART */
|
||||
extern uint32_t * __peripherals_start__;
|
||||
extern uint32_t * __peripherals_end__;
|
||||
|
||||
#else
|
||||
/* Declaration when these variable are exported from linker scripts. */
|
||||
/* Sections used for FLASH */
|
||||
extern uint32_t __FLASH_segment_start__[];
|
||||
extern uint32_t __FLASH_segment_end__[];
|
||||
extern uint32_t __privileged_functions_start__[];
|
||||
extern uint32_t __privileged_functions_end__[];
|
||||
|
||||
/* Sections used for RAM */
|
||||
extern uint32_t __SRAM_segment_start__[];
|
||||
extern uint32_t __SRAM_segment_end__[];
|
||||
extern uint32_t __privileged_data_start__[];
|
||||
extern uint32_t __privileged_data_end__[];
|
||||
|
||||
/* Sections used for system peripherals, such as UART */
|
||||
extern uint32_t __peripherals_start__[];
|
||||
extern uint32_t __peripherals_end__[];
|
||||
#endif /* if defined( __ARMCC_VERSION ) */
|
||||
uint32_t ulRegionStart;
|
||||
uint32_t ulRegionEnd;
|
||||
uint32_t ulRegionLength;
|
||||
|
||||
/* Ensure the MPU is disabled */
|
||||
prvMpuDisable();
|
||||
|
||||
/* Unprivileged and Privileged Read and Exec MPU Region for Flash */
|
||||
ulRegionStart = ( uint32_t ) __FLASH_segment_start__;
|
||||
ulRegionEnd = ( uint32_t ) __FLASH_segment_end__;
|
||||
ulRegionLength = ulRegionEnd - ulRegionStart;
|
||||
ulRegionLength = prvGetMPURegionSizeSetting( ulRegionLength ) | portMPU_REGION_ENABLE;
|
||||
|
||||
prvMpuSetRegion(
|
||||
portUNPRIVILEGED_FLASH_REGION,
|
||||
ulRegionStart,
|
||||
ulRegionLength,
|
||||
portMPU_PRIV_RO_USER_RO_EXEC | portMPU_NORMAL_OIWTNOWA_SHARED
|
||||
);
|
||||
|
||||
/* Privileged Read and Exec MPU Region for PRIVILEGED_FUNCTIONS. */
|
||||
ulRegionStart = ( uint32_t ) __privileged_functions_start__;
|
||||
ulRegionEnd = ( uint32_t ) __privileged_functions_end__;
|
||||
ulRegionLength = ulRegionEnd - ulRegionStart;
|
||||
ulRegionLength = prvGetMPURegionSizeSetting( ulRegionLength ) | portMPU_REGION_ENABLE;
|
||||
prvMpuSetRegion(
|
||||
portPRIVILEGED_FLASH_REGION,
|
||||
ulRegionStart,
|
||||
ulRegionLength,
|
||||
portMPU_PRIV_RO_USER_NA_EXEC | portMPU_NORMAL_OIWTNOWA_SHARED
|
||||
);
|
||||
|
||||
/* MPU Region for Peripheral Usage */
|
||||
ulRegionStart = ( uint32_t ) __peripherals_start__;
|
||||
ulRegionEnd = ( uint32_t ) __peripherals_end__;
|
||||
ulRegionLength = ulRegionEnd - ulRegionStart;
|
||||
ulRegionLength = prvGetMPURegionSizeSetting( ulRegionLength ) | portMPU_REGION_ENABLE;
|
||||
prvMpuSetRegion(
|
||||
portGENERAL_PERIPHERALS_REGION,
|
||||
ulRegionStart,
|
||||
ulRegionLength,
|
||||
portMPU_PRIV_RW_USER_RW_NOEXEC | portMPU_DEVICE_NONSHAREABLE
|
||||
);
|
||||
|
||||
/* All Read, and Privileged Write MPU Region for PRIVILEGED_DATA. */
|
||||
ulRegionStart = ( uint32_t ) __privileged_data_start__;
|
||||
ulRegionEnd = ( uint32_t ) __privileged_data_end__;
|
||||
ulRegionLength = ulRegionEnd - ulRegionStart;
|
||||
ulRegionLength = prvGetMPURegionSizeSetting( ulRegionLength ) | portMPU_REGION_ENABLE;
|
||||
prvMpuSetRegion(
|
||||
portPRIVILEGED_RAM_REGION,
|
||||
ulRegionStart,
|
||||
ulRegionLength,
|
||||
portMPU_PRIV_RW_USER_RO_NOEXEC | portMPU_NORMAL_OIWTNOWA_SHARED
|
||||
);
|
||||
|
||||
/* After setting default regions, enable the MPU */
|
||||
prvMpuEnable();
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/** @brief Determine if a FreeRTOS Task has been granted access to a memory region
|
||||
*
|
||||
* @param pvBuffer Base address of the memory region access is being requested.
|
||||
* @param ulBufferLength The length of the memory region that access is being requested.
|
||||
* @param ulAccessRequested The type of access being requested, either read or write.
|
||||
* @return BaseType_t pdTRUE if the task can access the region, pdFALSE otherwise
|
||||
*
|
||||
* @ingroup Task Context
|
||||
* @ingroup MPU Control
|
||||
*/
|
||||
BaseType_t xPortIsAuthorizedToAccessBuffer(
|
||||
const void * pvBuffer,
|
||||
uint32_t ulBufferLength,
|
||||
uint32_t ulAccessRequested
|
||||
) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
volatile uint32_t i, ulBufferStartAddress, ulBufferEndAddress;
|
||||
BaseType_t xAccessGranted = pdFALSE;
|
||||
|
||||
if( pdFALSE == xSchedulerRunning )
|
||||
{
|
||||
xAccessGranted = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Calling task's MPU settings. */
|
||||
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL );
|
||||
|
||||
uint32_t regionEndAddress = 0U;
|
||||
uint32_t regionLength = 0U;
|
||||
uint32_t regionStartAddress = 0u;
|
||||
|
||||
if( portTASK_IS_PRIVILEGED_FLAG ==
|
||||
( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) )
|
||||
{
|
||||
xAccessGranted = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Protect against buffer overflow range check */
|
||||
if( pdFALSE ==
|
||||
( ( uint32_t ) pvBuffer >
|
||||
( ( ( uint32_t ) 0 ) - ( uint32_t ) 1U ) - ulBufferLength - 1UL ) )
|
||||
{
|
||||
ulBufferStartAddress = ( uint32_t ) pvBuffer;
|
||||
ulBufferEndAddress = ( ( ( uint32_t ) pvBuffer ) + ulBufferLength - 1UL );
|
||||
|
||||
for( i = 0; i < portTOTAL_NUM_REGIONS_IN_TCB; i++ )
|
||||
{
|
||||
regionStartAddress =
|
||||
xTaskMpuSettings->xRegion[ i ].ulRegionBaseAddress;
|
||||
regionLength =
|
||||
1 << ( ( xTaskMpuSettings->xRegion[ i ].ulRegionSize >> 1 ) + 1U );
|
||||
regionEndAddress = regionStartAddress + regionLength;
|
||||
|
||||
if( ( ulBufferStartAddress >= regionStartAddress ) &&
|
||||
( ulBufferEndAddress <= regionEndAddress ) )
|
||||
{
|
||||
if( tskMPU_READ_PERMISSION == ulAccessRequested )
|
||||
{
|
||||
/* MPU CTRL Register Access Permission for unprivileged Read
|
||||
* is bX1X */
|
||||
if( portMPU_PRIV_RO_USER_RO_EXEC &
|
||||
xTaskMpuSettings->xRegion[ i ].ulRegionAttribute )
|
||||
{
|
||||
xAccessGranted = pdTRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* MPU CTRL Register Access Permission for unprivileged write is
|
||||
* b011 */
|
||||
else if( tskMPU_WRITE_PERMISSION & ulAccessRequested )
|
||||
{
|
||||
if( portMPU_PRIV_RW_USER_RW_EXEC ==
|
||||
( portMPU_PRIV_RW_USER_RW_EXEC &
|
||||
xTaskMpuSettings->xRegion[ i ].ulRegionAttribute ) )
|
||||
{
|
||||
xAccessGranted = pdTRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return xAccessGranted;
|
||||
}
|
||||
|
||||
#if( configENABLE_ACCESS_CONTROL_LIST == 1 )
|
||||
|
||||
BaseType_t xPortIsAuthorizedToAccessKernelObject( int32_t lInternalIndexOfKernelObject )
|
||||
/* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
uint32_t ulAccessControlListEntryIndex, ulAccessControlListEntryBit;
|
||||
BaseType_t xAccessGranted = pdFALSE;
|
||||
const xMPU_SETTINGS * xTaskMpuSettings;
|
||||
|
||||
if( xSchedulerRunning == pdFALSE )
|
||||
{
|
||||
/* Grant access to all the kernel objects before the scheduler
|
||||
* is started. It is necessary because there is no task running
|
||||
* yet and therefore, we cannot use the permissions of any
|
||||
* task. */
|
||||
xAccessGranted = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
|
||||
|
||||
ulAccessControlListEntryIndex =
|
||||
( ( uint32_t ) lInternalIndexOfKernelObject / portACL_ENTRY_SIZE_BITS );
|
||||
ulAccessControlListEntryBit =
|
||||
( ( uint32_t ) lInternalIndexOfKernelObject % portACL_ENTRY_SIZE_BITS );
|
||||
|
||||
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) ==
|
||||
portTASK_IS_PRIVILEGED_FLAG )
|
||||
{
|
||||
xAccessGranted = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( ( xTaskMpuSettings->ulAccessControlList[ ulAccessControlListEntryIndex ] &
|
||||
( 1U << ulAccessControlListEntryBit ) ) != 0 )
|
||||
{
|
||||
xAccessGranted = pdTRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return xAccessGranted;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
BaseType_t xPortIsAuthorizedToAccessKernelObject( int32_t lInternalIndexOfKernelObject
|
||||
) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
( void ) lInternalIndexOfKernelObject;
|
||||
|
||||
/* If Access Control List feature is not used, all the tasks have
|
||||
* access to all the kernel objects. */
|
||||
return pdTRUE;
|
||||
}
|
||||
|
||||
#endif /* #if ( configENABLE_ACCESS_CONTROL_LIST == 1 ) */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/** @brief Determine if the FreeRTOS Task was created as a privileged task
|
||||
*
|
||||
* @return BaseType_t pdTRUE if the task's ulTaskFlags mark it as privileged.
|
||||
* pdFALSE if the task was not created as a privileged task.
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
* @ingroup Task Context
|
||||
*/
|
||||
BaseType_t xPortIsTaskPrivileged( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
BaseType_t xTaskIsPrivileged = pdFALSE;
|
||||
|
||||
/* Calling task's MPU settings. */
|
||||
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL );
|
||||
|
||||
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) ==
|
||||
portTASK_IS_PRIVILEGED_FLAG )
|
||||
{
|
||||
xTaskIsPrivileged = pdTRUE;
|
||||
}
|
||||
|
||||
return xTaskIsPrivileged;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/** @brief Function that is used as the default Link Register address for a new Task
|
||||
*
|
||||
* @ingroup Task Context
|
||||
* @note This function is used as the default Link Register address if
|
||||
* configTASK_RETURN_ADDRESS is not defined in FreeRTOSConfig.h
|
||||
*
|
||||
*/
|
||||
void prvTaskExitError( void )
|
||||
{
|
||||
/* A function that implements a task must not exit or attempt to return to
|
||||
* its caller as there is nothing to return to. If a task wants to exit it
|
||||
* should instead call vTaskDelete( NULL ).
|
||||
*
|
||||
* Artificially force an assert() to be triggered if configASSERT() is
|
||||
* defined, then stop here so application writers can catch the error. */
|
||||
configASSERT( ulPortInterruptNesting == ~0UL );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/** @brief Start the FreeRTOS-Kernel's control of Tasks by starting the System Tick
|
||||
* Interrupt.
|
||||
*
|
||||
* @ingroup Scheduler
|
||||
* @return BaseType_t This function is not meant to be returned from.
|
||||
* If it does return it returns pdFALSE to mark that the scheduler could not be started.
|
||||
*/
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
#if defined( __ARMCC_VERSION )
|
||||
/* Declaration when these variable are defined in code instead of being
|
||||
* exported from linker scripts. */
|
||||
/* Sections used for Privileged Stacks to zero them out before starting tasks */
|
||||
extern uint32_t * __privileged_stacks_start__;
|
||||
extern uint32_t * __privileged_stacks_end__;
|
||||
#else /* if defined( __ARMCC_VERSION ) */
|
||||
/* Declaration when these variable are exported from linker scripts. */
|
||||
/* Sections used for Privileged Stacks to zero them out before starting tasks */
|
||||
/*
|
||||
extern uint32_t __privileged_stacks_start__[];
|
||||
extern uint32_t __privileged_stacks_end__[];
|
||||
*/
|
||||
#endif /* if defined( __ARMCC_VERSION ) */
|
||||
|
||||
/* Start the timer that generates the tick ISR. */
|
||||
configSETUP_TICK_INTERRUPT();
|
||||
|
||||
/* Reset the critical section nesting count read to execute the first task. */
|
||||
ulCriticalNesting = 0UL;
|
||||
|
||||
/* Configure the regions in the MPU that are common to all tasks. */
|
||||
prvSetupDefaultMPU();
|
||||
|
||||
xSchedulerRunning = pdTRUE;
|
||||
|
||||
/* Load the context of the first task, starting the FreeRTOS-Scheduler's control. */
|
||||
vPortStartFirstTask();
|
||||
|
||||
/* Will only get here if vTaskStartScheduler() was called with the CPU in
|
||||
* a non-privileged mode or the binary point register was not set to its lowest
|
||||
* possible value. prvTaskExitError() is referenced to prevent a compiler
|
||||
* warning about it being defined but not referenced in the case that the user
|
||||
* defines their own exit address. */
|
||||
( void ) prvTaskExitError();
|
||||
return 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/** @brief Function meant to end the FreeRTOS Scheduler, not implemented on this port.
|
||||
* @ingroup Scheduler
|
||||
*/
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
xSchedulerRunning = pdFALSE;
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
* Artificially force an assert. */
|
||||
configASSERT( xSchedulerRunning );
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
660
portable/GCC/ARM_CRx_MPU/portASM.S
Normal file
660
portable/GCC/ARM_CRx_MPU/portASM.S
Normal file
|
|
@ -0,0 +1,660 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.6.0
|
||||
* Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
.arm
|
||||
.syntax unified
|
||||
/* All code in the portASM.S file is intended to be run from a prvileged
|
||||
* operating mode, as such mark the entire file as privileged_functions */
|
||||
.section privileged_functions
|
||||
|
||||
#define FREERTOS_ASSEMBLY
|
||||
#include "portmacro_asm.h"
|
||||
#include "mpu_syscall_numbers.h"
|
||||
#undef FREERTOS_ASSEMBLY
|
||||
|
||||
/* External FreeRTOS-Kernel Variables */
|
||||
.extern pxCurrentTCB
|
||||
.extern ulPortInterruptNesting
|
||||
.extern ulICCEOIR
|
||||
.extern ulPortYieldRequired
|
||||
.extern __privileged_functions_start__
|
||||
.extern __privileged_functions_end__
|
||||
.extern __privileged_stacks_start__
|
||||
.extern __privileged_stacks_end__
|
||||
.extern __syscalls_flash_length__
|
||||
.extern __syscalls_flash_start__
|
||||
.extern __syscalls_flash_end__
|
||||
|
||||
/* External FreeRTOS-Kernel Functions */
|
||||
.extern vAssertCalled
|
||||
.extern vTaskSwitchContext
|
||||
.extern vApplicationIRQHandler
|
||||
|
||||
/******************************************************************************
|
||||
* portSAVE_CONTEXT is used to save all the registers, variables, and MPU
|
||||
* settings that make up a task's context.
|
||||
*****************************************************************************/
|
||||
.macro portSAVE_CONTEXT
|
||||
DSB
|
||||
ISB
|
||||
/* Move the SVC SP backwards before calling the SRS */
|
||||
SRSDB SP!, #SVC_MODE
|
||||
/* Change to Supervisor Mode for the Context Save */
|
||||
CPS #SVC_MODE
|
||||
/* Get the saved SPSR that was pushed to the SVC SP */
|
||||
LDR LR, [SP, #0x4]
|
||||
/* Move it to our SPSR so we can save the correct SP and LR */
|
||||
MSR SPSR_cxsf, LR
|
||||
/* Save the previous operating modes Registers, Stack Pointer, and Link Register */
|
||||
STMDB SP, {R0-R14}^
|
||||
/** Can't do a PUSH when using the ^ character, so need to manually move
|
||||
* the SP after pushing the registers */
|
||||
SUB SP, SP, #portREGISTER_CONTEXT_LENGTH
|
||||
#ifdef portENABLE_FPU
|
||||
/* Save the floating point context */
|
||||
/* Push the 16 floating point registers onto the stack */
|
||||
VPUSH {D0-D15}
|
||||
/* Load the FPSCR into R0 */
|
||||
FMRX R0, FPSCR
|
||||
/* Push the value of FPSCR onto the stack */
|
||||
PUSH {R0}
|
||||
#endif /* portENABLE_FPU */
|
||||
/* Load the address of ulCriticalNesting */
|
||||
LDR R0, =ulCriticalNesting
|
||||
/* Load the value of ulCriticalNesting into R0 */
|
||||
LDR R0, [R0]
|
||||
/* Push the value of ulCriticalNesting into the context */
|
||||
PUSH {R0}
|
||||
/* Load the address of pxCurrentTCB into R0 */
|
||||
LDR R0, =pxCurrentTCB
|
||||
/* Load the TCB into R0 */
|
||||
LDR R0, [R0]
|
||||
/* Set pxTopOfStack in the TCB to be the current Stack Pointer. This is
|
||||
* where to load the FreeRTOS-Task context from. */
|
||||
STR SP, [R0]
|
||||
/* Move the SVC SP forward to the scratch area in ulContext */
|
||||
ADD SP, SP, 0x8
|
||||
.endm
|
||||
|
||||
/******************************************************************************
|
||||
* portRESTORE_CONTEXT is used to restore all the registers, variables, and MPU
|
||||
* settings that make up a task's context.
|
||||
*****************************************************************************/
|
||||
.macro portRESTORE_CONTEXT
|
||||
/* Load the address of the current task TCB */
|
||||
LDR R0, =pxCurrentTCB
|
||||
/* Load the TCB into R0 */
|
||||
LDR R0, [R0]
|
||||
/* Set R1 to the second member of the TCB struct, xMPUSettings */
|
||||
ADD R1, R0, #0x4
|
||||
/* Set our SP to pxTopOfStack, the address of the Task context */
|
||||
LDR SP, [R0]
|
||||
/* Load the first per-task MPU region into R5 */
|
||||
MOV R5, #portFIRST_CONFIGURABLE_REGION
|
||||
/* Dynamically load the last MPU region */
|
||||
MRC p15, 0, R6, c0, c0, 0x4
|
||||
/* Move the number of MPU regions forward */
|
||||
LSR R6, #0x8
|
||||
/* Clear other bits, as there can only be 8-16 regions */
|
||||
AND R6, 0x1F
|
||||
/* When creating a loop label in a macro it has to be a numeric label. */
|
||||
123: /* For (R5 = portFIRST_CONFIGURABLE_REGION ; R5 <= portSTACK_REGION ; R5++ ) */
|
||||
/* Load values of struct MPU_REGION_REGISTERS into R1-R3 */
|
||||
LDMIA R1!, {R2-R4}
|
||||
/* Load the values set in xMPU_REGION_REGISTERS */
|
||||
/* R2 Will hold ulRegionSize */
|
||||
/* R3 will hold ulRegionAttribute */
|
||||
/* R4 will hold ulRegionBaseAddress */
|
||||
/* R5 will hold the MPU Region number */
|
||||
|
||||
/* Select the MPU Region using R5 */
|
||||
MCR p15, #0, R5, c6, c2, #0
|
||||
/* Set the MPU Region Base Address using ulRegionBaseAddress */
|
||||
MCR p15, #0, R4, c6, c1, #0
|
||||
/* Set the MPU Region Access Attributes using ulRegionAttribute */
|
||||
MCR p15, #0, R3, c6, c1, #4
|
||||
/* Set the MPU Region Size, and if the region is enabled using ulRegionSize */
|
||||
MCR p15, #0, R2, c6, c1, #2
|
||||
/* R5++ */
|
||||
ADD R5, R5, #1
|
||||
/* R5 <= R6 */
|
||||
CMP R5, #portSTACK_REGION
|
||||
/* R5 <= R6, loop again */
|
||||
BLE 123b
|
||||
/* R5 > portSTACK_REGION, all MPU regions have been restored */
|
||||
|
||||
/* Restore the critical section nesting depth. */
|
||||
/* Load the address of the ulCriticalNesting variable into R1 */
|
||||
LDR R1, =ulCriticalNesting
|
||||
/* Pop the previously saved value of ulCriticalNesting from ulContext */
|
||||
POP {R2}
|
||||
/* Store the value of ulCriticalNesting into address of ulCriticalNesting */
|
||||
STR R2, [R1]
|
||||
|
||||
#ifdef portENABLE_FPU
|
||||
/* Restore the Floating Point Context */
|
||||
/* Pop the value of FPSCR from ulContext */
|
||||
POP {R1}
|
||||
/* Move the saved FPSCR value into the FPSCR */
|
||||
VMSR FPSCR, R1
|
||||
/* Restore the Floating Point Registers */
|
||||
VPOP {D0-D15}
|
||||
#endif /* portENABLE_FPU*/
|
||||
/* At this point the SVC stack pointer will be in one of three places:
|
||||
* 1. ulContext[51] - This is the bottom of the context inside of the TCB for task saving
|
||||
* 1. ulContext[1] - We reloaded a nested context, the next context to restore is a task context
|
||||
* 2. ulSystemCallStackBuffer[?] - Restoring a nested context inside of an exception handler
|
||||
*/
|
||||
|
||||
/* Restore the register context, first need to load the mode bits */
|
||||
/* Set R1 to be past R0-R12 */
|
||||
ADD R1, SP, #portGPR_LENGTH
|
||||
/* Get the CPSR from the context, needed to set the SP and the LR */
|
||||
LDR R2, [R1, +#0x0C]
|
||||
/* Move the CPSR the into our SPSR */
|
||||
MSR SPSR_cxsf, R2
|
||||
/* Load the stored Stack Pointer and Link Register */
|
||||
LDM R1, {R13-R14}^
|
||||
/* Load R0-R12 from the context */
|
||||
POP {R0-R12}
|
||||
/* Jump over the already set R13 and R14 */
|
||||
ADD SP, SP, #0x8
|
||||
/* Return from the exception, loading the PC and CPSR */
|
||||
RFE SP!
|
||||
|
||||
.endm
|
||||
|
||||
/******************************************************************************
|
||||
* FreeRTOS_Tick_Handler is used to save context, increment the tick count, and
|
||||
* then switch tasks if neeeded
|
||||
*****************************************************************************/
|
||||
.align 4
|
||||
.global FreeRTOS_Tick_Handler
|
||||
.type FreeRTOS_Tick_Handler, %function
|
||||
FreeRTOS_Tick_Handler:
|
||||
/* Return to the interrupted instruction. */
|
||||
SUB LR, LR, #4
|
||||
/* Save the context of the current task. */
|
||||
portSAVE_CONTEXT
|
||||
/* Enter back into IRQ mode after saving task context */
|
||||
CPS #IRQ_MODE
|
||||
/* Clear interrupt flag in RTI. */
|
||||
LDR R0, =configRTI_ADDRESS
|
||||
MOV R1, #1
|
||||
STR R1, [R0]
|
||||
/* Increment the tick count, making any adjustments to the blocked lists
|
||||
that may be necessary. */
|
||||
BL xTaskIncrementTick
|
||||
/* If xTaskIncrementTick returned non-zero then select the next task to execute. */
|
||||
CMP R0, #0
|
||||
BLNE vTaskSwitchContext
|
||||
/* Swap to SVC Mode to restore the task context */
|
||||
CPS #SVC_MODE
|
||||
/* Restore the context of the task selected to execute. */
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
/* Yield to another task from within the FreeRTOS API */
|
||||
|
||||
.align 4
|
||||
.global vPortYieldWithinAPI
|
||||
.type vPortYieldWithinAPI, %function
|
||||
vPortYieldWithinAPI:
|
||||
/* Return to the interrupted instruction. */
|
||||
SUB LR, LR, #4
|
||||
/* Save the context of the current task */
|
||||
portSAVE_CONTEXT
|
||||
/* Swap back to IRQ Mode for selecting the next task */
|
||||
CPS #IRQ_MODE
|
||||
/* Clear the Interrupt Flag for vPortYieldWithinAPI */
|
||||
MOV R0, #configSSI_ADDRESS
|
||||
LDR R0, [R0]
|
||||
/* Select the next task to execute. */
|
||||
BL vTaskSwitchContext
|
||||
/* Swap back to SVC Mode for context restore */
|
||||
CPS #SVC_MODE
|
||||
/* Restore the context of the task selected to execute. */
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
/******************************************************************************
|
||||
* vPortStartFirstTask is used to start the scheduler.
|
||||
*****************************************************************************/
|
||||
.align 4
|
||||
.global vPortStartFirstTask
|
||||
.type vPortStartFirstTask, %function
|
||||
vPortStartFirstTask:
|
||||
/** This function is called from System Mode to start the FreeRTOS-Kernel.
|
||||
* This is done by restoring the context of the first task.
|
||||
* Restoring the context of a task will allow interrupts.
|
||||
* This allows the FreeRTOS Scheduler Tick to start, and therefore
|
||||
* starts the FreeRTOS-Kernel.
|
||||
*/
|
||||
/* Swap to SVC Mode for context restore */
|
||||
CPS #SVC_MODE
|
||||
/* Restore context of first task, which enables IRQs, starting the sys tick timer */
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
/******************************************************************************
|
||||
* The FreeRTOS SVC Handler is used to handle Supervisor Calls
|
||||
*****************************************************************************/
|
||||
/** Upon entering here the LR, or R14, will hold the address of the
|
||||
* following instruction. The instruction can be inspected to determine
|
||||
* what SVC # was raised.
|
||||
* This handler is ONLY safe when called from the exposed SVC wrapper functions
|
||||
* located after this handler in this file.
|
||||
*/
|
||||
|
||||
/* Checks:
|
||||
* 1. SVC is raised from the system call section (i.e. application is
|
||||
* not raising SVC directly).
|
||||
* 2. pxMpuSettings->xSystemCallStackInfo.pulTaskStack must be NULL as
|
||||
* it is non-NULL only during the execution of a system call (i.e.
|
||||
* between system call enter and exit).
|
||||
* 3. System call is not for a kernel API disabled by the configuration
|
||||
* in FreeRTOSConfig.h.
|
||||
* 4. We do not need to check that ucSystemCallNumber is within range
|
||||
* because the assembly SVC handler checks that before calling
|
||||
* this function.
|
||||
*/
|
||||
|
||||
.align 4
|
||||
.global FreeRTOS_SVC_Handler
|
||||
.type FreeRTOS_SVC_Handler, %function
|
||||
FreeRTOS_SVC_Handler:
|
||||
/* Push R11 and R12 to the bottom two, pre-resereved, addresses in ulContext */
|
||||
STM R13, {R11, R12}
|
||||
|
||||
/* -------------------- Caller Flash Location Check -------------------- */
|
||||
|
||||
/** The address of the caller will be in the Link Register (LR), it will be
|
||||
* the caller's Program Counter (PC). Check this address to ensure the
|
||||
* Supervisor call (SVC) was raised from inside the FreRTOS-Kernel. */
|
||||
|
||||
/* Get the starting address for FreeRTOS System Calls */
|
||||
LDR R12, =__syscalls_flash_start__
|
||||
/* Subtract the start point from the Program Counter of the caller */
|
||||
SUB R11, LR, R12
|
||||
/* Now check if it is less than the length of the section */
|
||||
LDR R12, =__syscalls_flash_length__
|
||||
/* Check if an SVC was raised after the end of FreeRTOS System Calls */
|
||||
CMP R11, R12
|
||||
/* If the SVC was raised from outside FreeRTOS System Calls exit */
|
||||
BGE SVC_Handler_Exit
|
||||
|
||||
/* ----------------------- Get Caller SVC Number ----------------------- */
|
||||
|
||||
svcNumberCheck:
|
||||
/* The SPSR will be the CPSR of the calling task, store it in R11 */
|
||||
MRS R11, SPSR
|
||||
/* Thumb Mode is bit 5 of the CPSR. And it with the CPSR for comparison check */
|
||||
ANDS R11, R11, #0x20
|
||||
|
||||
/* The SVC instruction will be 0x2 before LR in Thumb Mode, or 0x4 if not */
|
||||
|
||||
/* In Thumb Mode, so get instruction 0x2 before */
|
||||
LDRHNE R11, [LR, #-0x2]
|
||||
/* Not in Thumb Mode, so get the instruction 0x4 before */
|
||||
LDRHEQ R11, [LR, #-0x4]
|
||||
|
||||
/* ---------------------------- SVC Routing ---------------------------- */
|
||||
|
||||
/* Determine if the SVC number is below #NUM_SYSTEM_CALLS */
|
||||
CMP R11, #NUM_SYSTEM_CALLS
|
||||
/* If it is go to the entry point for FreeRTOS System Calls */
|
||||
BLT svcSystemCallEnter
|
||||
|
||||
/* Check if the caller is leaving a FreeRTOS System Call */
|
||||
CMP R11, #portSVC_SYSTEM_CALL_EXIT
|
||||
BEQ svcSystemCallExit
|
||||
|
||||
/* Check if the caller is requesting to yield */
|
||||
CMP R11, #portSVC_YIELD
|
||||
BEQ svcPortYield
|
||||
|
||||
/* If one of the above jumps wasn't taken, go straight to the exit */
|
||||
SVC_Handler_Exit:
|
||||
/** Restore the saved R11 and R12, then return to the caller */
|
||||
LDM SP, {R11, R12}
|
||||
/* This instruction loads the SPSR into the CPSR, performing the mode swap */
|
||||
MOVS PC, LR
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Save a FreeRTOS-Task's Context, select a new task, and then restore its context */
|
||||
svcPortYield:
|
||||
/* Restore the previously saved R11, R12 */
|
||||
LDM SP, {R11, R12}
|
||||
/* Save the context of the current task and select a new task to run. */
|
||||
portSAVE_CONTEXT
|
||||
/* Run the following function from the IRQ stack */
|
||||
CPS #IRQ_MODE
|
||||
/* Select a new task to swap to */
|
||||
BL vTaskSwitchContext
|
||||
/* Swap back to SVC Mode for context restore */
|
||||
CPS #SVC_MODE
|
||||
/* Restore the context of the task selected to execute. */
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
/* Swap a task back to using its task stack, and reset its privilege level if needed */
|
||||
svcSystemCallExit:
|
||||
/* Restore the Task Stack Pointer and Link Register */
|
||||
/* Load the address of pxCurrentTCB into R11 */
|
||||
LDR R11, =pxCurrentTCB
|
||||
/* Load pxCurrentTCB into R11 */
|
||||
LDR R11, [R11]
|
||||
/* Set R11 to be the location of xSystemCallStackInfo inside the TCB */
|
||||
ADD R11, R11, #portSYSTEM_CALL_INFO_OFFSET
|
||||
/* Restore the user mode Stack Pointer and Link Register */
|
||||
LDMIB R11, {R13-R14}^
|
||||
/* Zero out R12 so we can set ulTaskStackPointer back to NULL */
|
||||
AND R12, R12, #0x0
|
||||
/* Set pulTaskStackPointer to be 0x0 */
|
||||
STR R12, [R11, #0x4]
|
||||
/* Set pulLinkRegisterAtSystemCallEntry to be 0x0 */
|
||||
STR R12, [R11, #0x8]
|
||||
/* Load the ulTaskFlag so we can determine if we're going to lower privilege */
|
||||
LDM R11, {R12}
|
||||
/* Check if the task is privileged */
|
||||
CMP R12, #portTASK_IS_PRIVILEGED_FLAG
|
||||
/* If the task is privileged we can leave now */
|
||||
BEQ SVC_Handler_Exit
|
||||
/* Otherwise, we need to set the SPSR back to USER mode */
|
||||
MRS R12, SPSR
|
||||
/* Clear the last 4 bits, which are the MODE bits */
|
||||
BIC R12, R12, #0x0F
|
||||
/* Move the new value into the SPSR */
|
||||
MSR SPSR_cxsf, R12
|
||||
/* Jump back */
|
||||
B SVC_Handler_Exit
|
||||
|
||||
/* svcSystemCallEnter */
|
||||
/* Swap a task to using the ulSystemCallStack Buffer, and set its privilege high */
|
||||
svcSystemCallEnter:
|
||||
/* Load the base address of the uxSystemCallImplementations[] table into R14 */
|
||||
LDR R14, =uxSystemCallImplementations
|
||||
|
||||
/** Shift the value of R11, the SVC number, left by two to get the jump offset
|
||||
* Add this offset to R14, which holds the jump table address. This is the address
|
||||
* of the SVC that the relevant function is trying to complete.
|
||||
* Now when the Link Register is loaded as the Program Counter at the end of this
|
||||
* handler, the caller will immediately execute the requested function */
|
||||
LDR R14, [R14, R11, lsl #2]
|
||||
|
||||
/* Load the address of pxCurrentTCB into R11 */
|
||||
LDR R11, =pxCurrentTCB
|
||||
/* Load pxCurrentTCB into R11 */
|
||||
LDR R11, [R11]
|
||||
/* Set R11 to be the location of xSystemCallStackInfo inside the TCB */
|
||||
ADD R11, R11, #portSYSTEM_CALL_INFO_OFFSET
|
||||
/* Get the value in the TCB for ulTaskStackPointer */
|
||||
LDMIB R11!, { R12 }
|
||||
/* Make sure that ulTaskStackPointer was null, meaning that this is initial entry */
|
||||
TST R12, #0x0
|
||||
/** Hard code the ascii value of the function name and line number to call
|
||||
* assert if the ulTaskStackPointer is not null. */
|
||||
MOVWNE R0, #0x706F
|
||||
MOVTNE R0, #0x7274
|
||||
MOVNE R1, #458
|
||||
BNE vAssertCalled
|
||||
|
||||
/* Store the task's SP and LR to xSYSTEM_CALL_STACK_INFO */
|
||||
STM R11, {R13-R14}^
|
||||
/* It's a compilation warning to use the ! for writeback, so manually move R11 */
|
||||
ADD R11, R11, 0x8
|
||||
/* Load pulSystemCallStackPointer and pulSystemCallLinkRegister now */
|
||||
LDM R11, {R13-R14}^
|
||||
|
||||
/* Swap the SPSR to SYS_MODE for the System Call. Move SPSR into R12 */
|
||||
MRS R12, SPSR
|
||||
/* Set the MODE bits to SYS_MODE */
|
||||
ORR R12, R12, #SYS_MODE
|
||||
/* Assign the new value to SPSR */
|
||||
MSR SPSR_cxsf, R12
|
||||
/* Leave through the SVC Exit */
|
||||
B SVC_Handler_Exit
|
||||
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* vPortEnterCritical */
|
||||
.align 4
|
||||
.global vPortEnterCritical
|
||||
.type vPortEnterCritical, %function
|
||||
vPortEnterCritical:
|
||||
/* Disable IRQs */
|
||||
CPSID I
|
||||
/* Save scratch registers */
|
||||
PUSH {R0-R1}
|
||||
/* Load address of current critical nesting count */
|
||||
LDR R0, =ulCriticalNesting
|
||||
/* Load value of current critical nesting count */
|
||||
LDR R1, [R0]
|
||||
/* Add one to ulCriticalNesting */
|
||||
ADD R1, R1, #1
|
||||
/* Store the modified ulCriticalNesting back into RAM */
|
||||
STR R1, [R0]
|
||||
/* Return to caller */
|
||||
POP {R0-R1}
|
||||
BX LR
|
||||
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* vPortDisableInterrupts */
|
||||
.align 4
|
||||
.global vPortDisableInterrupts
|
||||
.type vPortDisableInterrupts, %function
|
||||
vPortDisableInterrupts:
|
||||
/* Disable IRQs */
|
||||
CPSID I
|
||||
/* Return to caller */
|
||||
BX LR
|
||||
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* vPortExitCritical */
|
||||
.align 4
|
||||
.global vPortExitCritical
|
||||
.type vPortExitCritical, %function
|
||||
vPortExitCritical:
|
||||
/* Store two scratch registers */
|
||||
PUSH {R0-R1}
|
||||
/* Load address of current critical nesting count */
|
||||
LDR R0, =ulCriticalNesting
|
||||
/* Load value of current critical nesting count */
|
||||
LDR R1, [R0]
|
||||
/* Check if the count is 0 */
|
||||
CMP R1, #0
|
||||
/* If ulCriticalNesting is greater than 0, Subtract 1 from it */
|
||||
SUBGT R1, R1, #1
|
||||
/* Store the modified ulCriticalNesting back into RAM */
|
||||
STRGT R1, [R0]
|
||||
/* Enable IRQs */
|
||||
CPSIE I
|
||||
/* Return to caller */
|
||||
POP {R0-R1}
|
||||
BX LR
|
||||
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* vPortEnableInterrupts */
|
||||
.align 4
|
||||
.global vPortEnableInterrupts
|
||||
.type vPortEnableInterrupts, %function
|
||||
vPortEnableInterrupts:
|
||||
/* Enable IRQs */
|
||||
CPSIE I
|
||||
/* Return to caller */
|
||||
BX LR
|
||||
|
||||
/******************************************************************************
|
||||
* prvMpuSetRegion is used to set the base address, access attributes,
|
||||
* and the size and enable bits of a selected MPU region.
|
||||
* void prvMpuSetRegion(unsigned region, unsigned base, unsigned size, unsigned access)
|
||||
*****************************************************************************/
|
||||
.align 4
|
||||
.global prvMpuSetRegion
|
||||
.type prvMpuSetRegion, %function
|
||||
prvMpuSetRegion:
|
||||
/* Only 15 possible regions, drop all other bits */
|
||||
AND R0, R0, #15
|
||||
/* Select the MPU Region selected by region */
|
||||
MCR p15, #0, R0, c6, c2, #0
|
||||
/* Set the Base Address to be base */
|
||||
MCR p15, #0, R1, c6, c1, #0
|
||||
/* Set the Access Attributes to be access */
|
||||
MCR p15, #0, R3, c6, c1, #4
|
||||
/* Set the Size and Enable bits to be size */
|
||||
MCR p15, #0, R2, c6, c1, #2
|
||||
BX LR
|
||||
|
||||
/******************************************************************************
|
||||
* prvMpuEnable is used to set the Enable bit of the MPU Enable Register to 1.
|
||||
*****************************************************************************/
|
||||
.align 4
|
||||
.global prvMpuEnable
|
||||
.type prvMpuEnable, %function
|
||||
prvMpuEnable:
|
||||
/* Read the current MPU control register into R0 */
|
||||
MRC p15, #0, R0, c1, c0, #0
|
||||
/* Set the enable bit to high */
|
||||
ORR R0, R0, #0x1
|
||||
/* Data sync */
|
||||
DSB
|
||||
/* Write out previous MPU control register with a high enable bit */
|
||||
MCR p15, #0, R0, c1, c0, #0
|
||||
/* Instruction sync */
|
||||
ISB
|
||||
BX LR
|
||||
|
||||
/******************************************************************************
|
||||
* prvMpuDisable is used to set the Enable bit of the MPU Enable Register to 0.
|
||||
*****************************************************************************/
|
||||
.align 4
|
||||
.global prvMpuDisable
|
||||
.type prvMpuDisable, %function
|
||||
prvMpuDisable:
|
||||
/* Read the MPU enable register values into R0 */
|
||||
MRC p15, #0, R0, c1, c0, #0
|
||||
/* Clear out all bits in R0 except for bit 1 */
|
||||
BIC R0, R0, #1
|
||||
/* Wait for all pending explicit data accesses to complete */
|
||||
DSB
|
||||
/* Write out to the MPU Enable Register */
|
||||
MCR p15, #0, R0, c1, c0, #0
|
||||
/* Flushes the pipeline and prefetch buffer(s) in the processor. */
|
||||
/* Ensures all following instructions are fetched from cache or memory. */
|
||||
ISB
|
||||
BX LR
|
||||
|
||||
.align 4
|
||||
.global FreeRTOS_IRQ_Handler
|
||||
.type FreeRTOS_IRQ_Handler, %function
|
||||
FreeRTOS_IRQ_Handler:
|
||||
/* Return to the interrupted instruction. */
|
||||
SUB LR, LR, #4
|
||||
|
||||
/* Save the return state to the IRQ stack */
|
||||
SRS SP!, #IRQ_MODE
|
||||
|
||||
/* Push used registers. */
|
||||
PUSH {R0-R3, R12}
|
||||
|
||||
/* Increment nesting count. R3 holds the address of ulPortInterruptNesting
|
||||
for future use. R1 holds the original ulPortInterruptNesting value for
|
||||
future use. */
|
||||
LDR R3, =ulPortInterruptNesting
|
||||
LDR R1, [R3]
|
||||
ADD R0, R1, #1
|
||||
STR R0, [R3]
|
||||
|
||||
/* Ensure bit 2 of the stack pointer is clear. R2 holds the bit 2 value for
|
||||
future use. */
|
||||
MOV R0, SP
|
||||
AND R2, R0, #4
|
||||
SUB SP, SP, R2
|
||||
|
||||
/* Call the interrupt handler. */
|
||||
PUSH {R0-R3, LR}
|
||||
BL vApplicationIRQHandler
|
||||
|
||||
/* Restore the registers */
|
||||
POP {R0-R3, LR}
|
||||
ADD SP, SP, R2
|
||||
|
||||
CPSID i
|
||||
DSB
|
||||
ISB
|
||||
|
||||
/* Write to the EOI register. */
|
||||
LDR R0, =ulICCEOIR
|
||||
LDR R2, [R0]
|
||||
STR R0, [R2]
|
||||
|
||||
/* Restore the old nesting count. */
|
||||
STR R1, [R3]
|
||||
|
||||
/* A context switch is never performed if the nesting count is not 0. */
|
||||
CMP R1, #0
|
||||
BNE exit_without_switch
|
||||
|
||||
/* Did the interrupt request a context switch? R1 holds the address of
|
||||
ulPortYieldRequired and R0 the value of ulPortYieldRequired for future use. */
|
||||
LDR R1, =ulPortYieldRequired
|
||||
LDR R0, [R1]
|
||||
CMP R0, #0
|
||||
BNE switch_before_exit
|
||||
|
||||
exit_without_switch:
|
||||
/* No context switch. Restore used registers, LR_irq and SPSR before returning. */
|
||||
POP {R0-R3, R12}
|
||||
CPS #IRQ_MODE
|
||||
POP {LR}
|
||||
MSR SPSR_cxsf, LR
|
||||
POP {LR}
|
||||
MOVS PC, LR
|
||||
|
||||
switch_before_exit:
|
||||
/* A context swtich is to be performed. Clear the context switch pending flag. */
|
||||
MOV R0, #0
|
||||
STR R0, [R1]
|
||||
|
||||
/* Restore used registers, LR-irq and SPSR before saving the context
|
||||
to the task stack. */
|
||||
POP {R0-R3, R12}
|
||||
CPS #IRQ_MODE
|
||||
POP {LR}
|
||||
MSR SPSR_cxsf, LR
|
||||
POP {LR}
|
||||
portSAVE_CONTEXT
|
||||
|
||||
/* Call the function that selects the new task to execute.
|
||||
vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD
|
||||
instructions, or 8 byte aligned stack allocated data. LR does not need
|
||||
saving as a new LR will be loaded by portRESTORE_CONTEXT anyway. */
|
||||
LDR R0, =vTaskSwitchContext
|
||||
BLX R0
|
||||
|
||||
/* Restore the context of, and branch to, the task selected to execute next. */
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
.end
|
||||
661
portable/GCC/ARM_CRx_MPU/portmacro.h
Normal file
661
portable/GCC/ARM_CRx_MPU/portmacro.h
Normal file
|
|
@ -0,0 +1,661 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V11.0.1
|
||||
* Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
/** @brief Functions, Defines, and Structs for use in the ARM_CRx_MPU FreeRTOS-Port
|
||||
* @file portmacro.h
|
||||
* @note The settings in this file configure FreeRTOS correctly for the given
|
||||
* hardware and compiler. These settings should not be altered.
|
||||
*/
|
||||
|
||||
/** @defgroup MPU Control
|
||||
* @brief APIs and Variables used to control the onboard MPU.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Include stdint for integer types of specific bit widths */
|
||||
#include <stdint.h>
|
||||
|
||||
/* ------------------------- FreeRTOS Config Check ------------------------- */
|
||||
|
||||
/* Include the FreeRTOS Config file first to get the includes being used */
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
#ifndef configENABLE_MPU
|
||||
#error "This port is only usable with configENABLE_MPU set to 1"
|
||||
#elif( configENABLE_MPU != 1 )
|
||||
#error "This port is only usable with configENABLE_MPU set to 1"
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#ifndef configUSE_MPU_WRAPPERS_V1
|
||||
#define configUSE_MPU_WRAPPERS_V1 0
|
||||
#elif( ( configUSE_MPU_WRAPPERS_V1 != 0 ) )
|
||||
#error "This port is only usable with configUSE_MPU_WRAPPERS_V1 set to 0"
|
||||
#endif /* ( configUSE_MPU_WRAPPERS_V1 != 0 ) */
|
||||
|
||||
#ifndef configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY
|
||||
#define configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY 1
|
||||
#elif( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY != 1 )
|
||||
#error This Port is only usable with configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY set to 1
|
||||
#endif /* ( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY != 1 ) */
|
||||
|
||||
/** @brief The size in Bytes that the Privileged System Call Stack should be.
|
||||
*
|
||||
* @ingroup MPU Privilege
|
||||
*
|
||||
* @note This stack is used when performing FreeRTOS System Calls. The stack pointer
|
||||
* is changed to use this region when a call to a function is made that goes through
|
||||
* the MPU Wrappers.
|
||||
*
|
||||
* This value should be a size that can be made into a MPU Region.
|
||||
*
|
||||
*/
|
||||
#ifndef configSYSTEM_CALL_STACK_SIZE
|
||||
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2.
|
||||
#endif /* configSYSTEM_CALL_STACK_SIZE */
|
||||
|
||||
#if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 )
|
||||
/* Check the configuration. */
|
||||
#if( configMAX_PRIORITIES > 32 )
|
||||
#error "configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when " \
|
||||
"configMAX_PRIORITIES is less than or equal to 32." \
|
||||
"It is very rare that a system requires more than 10 to 15 difference " \
|
||||
"priorities as tasks that share a priority will time slice."
|
||||
#endif /* ( configMAX_PRIORITIES > 32 ) */
|
||||
|
||||
/** @brief Mark that a task of the current priority is ready for execution
|
||||
*
|
||||
* @ingroup Scheduler
|
||||
*
|
||||
* @param[in] uxPriority Priority of task that can enter the ready state
|
||||
* @param[out] uxTopReadyPriority Bitmap of tasks that are in the ready state
|
||||
*/
|
||||
#define portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority ) \
|
||||
( uxTopReadyPriority ) |= ( 1UL << ( uxPriority ) )
|
||||
|
||||
/** @brief Mark that a task of the current priority has left the ready state
|
||||
*
|
||||
* @ingroup Scheduler
|
||||
*
|
||||
* @param[in] uxPriority Priority of task that is leaving the ready state
|
||||
* @param[out] uxTopReadyPriority Bitmap of tasks that are in the ready state
|
||||
*/
|
||||
#define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority ) \
|
||||
( uxTopReadyPriority ) &= ~( 1UL << ( uxPriority ) )
|
||||
|
||||
/** @brief Determine what the highest priority ready task is.
|
||||
*
|
||||
* @ingroup Scheduler
|
||||
*
|
||||
* @param[out] uxTopReadyPriority Bitmap of tasks that are in the ready state
|
||||
* @param[out] uxTopPriority The highest priority ready task's priority value.
|
||||
*/
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ) \
|
||||
uxTopPriority = ( 31UL - ulPortCountLeadingZeros( ( uxTopReadyPriority ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
#ifndef configSETUP_TICK_INTERRUPT
|
||||
#error configSETUP_TICK_INTERRUPT() must be defined in FreeRTOSConfig.h to call the function that sets up the tick interrupt.
|
||||
#endif /* configSETUP_TICK_INTERRUPT */
|
||||
|
||||
#ifndef configCLEAR_TICK_INTERRUPT
|
||||
#error configCLEAR_TICK_INTERRUPT must be defined in FreeRTOSConfig.h to clear which ever interrupt was used to generate the tick interrupt.
|
||||
#endif /* configCLEAR_TICK_INTERRUPT */
|
||||
|
||||
#ifndef configEOI_ADDRESS
|
||||
#error Did not define a memrory address to mark the end of an Interrupt
|
||||
#endif /* configEOI_ADDRESS */
|
||||
|
||||
#ifdef configUSE_TICKLESS_IDLE
|
||||
#if( configUSE_TICKLESS_IDLE != 0 )
|
||||
#error This port does not yet support tickless idle
|
||||
#endif /* ( configUSE_TICKLESS_IDLE != 0 ) */
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
|
||||
/* ------------------------- Port Type Definitions ------------------------- */
|
||||
|
||||
#include "portmacro_asm.h"
|
||||
|
||||
/** @brief Critical section nesting value to mark the end of a critical section.
|
||||
*
|
||||
* @ingroup Critical Sections
|
||||
*
|
||||
* @note
|
||||
* A critical section is exited when the critical section nesting count reaches
|
||||
* this value. When exiting a critical section IRQs are re-enabled.
|
||||
*/
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0x0 )
|
||||
|
||||
/** @brief Bit value used to mark if the CPU is currently executing in Thumb Mode.
|
||||
* @ingroup Task Context
|
||||
*/
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
|
||||
/** @brief Value used to check if a task's function is a Thumb function.
|
||||
* @ingroup Task Context
|
||||
*/
|
||||
#define portTHUMB_MODE_ADDRESS ( 0x01UL )
|
||||
|
||||
/** @brief Unsigned Data type equal to the data word operating size of the CPU.
|
||||
*
|
||||
* @ingroup Port Interface Specifications
|
||||
*
|
||||
* @note
|
||||
* The FreeRTOS-Kernel needs to be able to use an unsigned type that is
|
||||
* the most efficient, natural type for the targeted architecture.
|
||||
*/
|
||||
typedef uint32_t StackType_t;
|
||||
|
||||
/** @brief Signed Data type equal to the data word operating size of the CPU.
|
||||
*
|
||||
* @ingroup Port Interface Specifications
|
||||
*
|
||||
* @note
|
||||
* The FreeRTOS-Kernel needs to be able to use a signed type that is
|
||||
* the most efficient, natural type for the targeted architecture.
|
||||
*/
|
||||
typedef int32_t BaseType_t;
|
||||
|
||||
/** @brief Unsigned Data type equal to the data word operating size of the CPU.
|
||||
*
|
||||
* @ingroup Port Interface Specifications
|
||||
*
|
||||
* @note
|
||||
* The FreeRTOS-Kernel needs to be able to use an unsigned type that is
|
||||
* the most efficient, natural type for the targeted architecture.
|
||||
*/
|
||||
typedef uint32_t UBaseType_t;
|
||||
|
||||
/** @brief Integer type used for the Tick Counter
|
||||
*
|
||||
* @note
|
||||
* Use a 32-bit tick type on a 32-bit architecture, so reads of the tick count
|
||||
* do not need to be guarded with a critical section.
|
||||
*/
|
||||
typedef uint32_t TickType_t;
|
||||
|
||||
/** @brief Marks the direction the stack grows on the targeted CPU.
|
||||
*
|
||||
* @ingroup Port Interface Specifications
|
||||
*
|
||||
*/
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
|
||||
/** @brief Specifies at what number of bytes a stack pointer shall be aligned.
|
||||
*
|
||||
* @ingroup Port Interface Specifications
|
||||
*
|
||||
*/
|
||||
#define portBYTE_ALIGNMENT 8U
|
||||
|
||||
/** @brief Task function prototype macro as described on FreeRTOS.org
|
||||
*
|
||||
* @ingroup Port Interface Specifications
|
||||
*
|
||||
* @note
|
||||
* These are not required for this port but included in case common demo code
|
||||
* that uses these macros is used.
|
||||
*/
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) \
|
||||
void vFunction( void * pvParameters )
|
||||
|
||||
/** @brief Task function prototype macro as described on FreeRTOS.org
|
||||
*
|
||||
* @ingroup Port Interface Specifications
|
||||
*
|
||||
* @note
|
||||
* These are not required for this port but included in case common demo code
|
||||
* that uses these macros is used.
|
||||
*/
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
|
||||
/** @brief Wrapper for the no-op ARM Assembly Instruction
|
||||
* @ingroup Port Interface Specifications
|
||||
*/
|
||||
#define portNOP() __asm volatile( "NOP" )
|
||||
|
||||
/** @brief Wrapper for the Inline GCC Label
|
||||
* @ingroup Port Interface Specifications
|
||||
*/
|
||||
#define portINLINE __inline
|
||||
|
||||
/** @brief Wrapper for the ARM Memory Sync Assembly Instruction
|
||||
* @ingroup Port Interface Specifications
|
||||
*/
|
||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||
|
||||
/** @brief Defines if the system tick count can be accessed atomically
|
||||
*
|
||||
* @ingroup System Clock
|
||||
*/
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
|
||||
/** @brief Define the number of miliseconds between system ticks.
|
||||
*
|
||||
* @ingroup System Clock
|
||||
*/
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000UL / configTICK_RATE_HZ )
|
||||
|
||||
/** @brief Define the larges possible delay value for a task.
|
||||
*
|
||||
* @ingroup System Clock
|
||||
*/
|
||||
#define portMAX_DELAY ( TickType_t ) 0xFFFFFFFFUL
|
||||
|
||||
/* --------------------------- Port Assembly Handlers --------------------------- */
|
||||
|
||||
/** @brief Assembly FreeRTOS Supervisor Call Handler */
|
||||
void FreeRTOS_SVC_Handler( void );
|
||||
|
||||
/** @brief Assembly FreeRTOS Interrupt Handler */
|
||||
void FreeRTOS_IRQ_Handler( void );
|
||||
|
||||
/** @brief Assembly FreeRTOS IRQ Handler
|
||||
*
|
||||
* @ingroup Scheduler
|
||||
*
|
||||
* @note This must be installed as the handler for whichever peripheral is used
|
||||
* to generate the RTOS tick if using a VIM. */
|
||||
|
||||
/** @brief Decleration of the FreeRTOS Tick Handler.
|
||||
*
|
||||
* @ingroup Scheduler
|
||||
*
|
||||
* @note This must be installed as the handler for whichever peripheral is used
|
||||
* to generate the RTOS tick if using a VIM. */
|
||||
void FreeRTOS_Tick_Handler( void ) __attribute__( ( weak, interrupt( "IRQ" ) ) );
|
||||
|
||||
/** @brief Pend a context switch inside of the FreeRTOS-Kernel.
|
||||
* @ingroup Scheduler
|
||||
* @note This is used to raise a pending IRQ on a board that supplies a VIM.
|
||||
*/
|
||||
void vPortYieldWithinAPI( void ) __attribute__( ( weak, interrupt( "IRQ" ) ) );
|
||||
|
||||
/* --------------------------- Port Assembly Functions --------------------------- */
|
||||
|
||||
/** @brief Make a Supervisor Call to swap the currently running task out.
|
||||
*
|
||||
* @ingroup Scheduler
|
||||
* @note The FreeRTOS-Kernel needs a method to swap the current task that is
|
||||
* running. The FreeRTOS-Port needs to ensure that when this happens any
|
||||
* hardware specific values related to the current task’s context are properly
|
||||
* saved. A properly saved context can be restored to allow execution of the
|
||||
* task as if it was not interrupted.
|
||||
*/
|
||||
void vPortYield( void );
|
||||
|
||||
/** @brief Raise a Supervisor Call to swap the currently running task out. */
|
||||
#define portYIELD() vPortYield()
|
||||
|
||||
/** @brief Disable IRQs then increment the critical nesting count.
|
||||
* @ingroup Critical Section
|
||||
*/
|
||||
void vPortEnterCritical( void );
|
||||
|
||||
/** @brief Enter a Critical Section inside of the FreeRTOS-Kernel */
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
|
||||
/** @brief Enable IRQs and decrement the critical nesting count.
|
||||
* @ingroup Critical Section
|
||||
*/
|
||||
void vPortExitCritical( void );
|
||||
|
||||
/** @brief Exit a Critical Section inside of the FreeRTOS-Kernel.
|
||||
* @ingroup Critical Section
|
||||
*/
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
|
||||
/** @brief Set the IRQ bit of the CPSR high, enabling IRQs.
|
||||
* @ingroup Interrupt Management
|
||||
*/
|
||||
void vPortEnableInterrupts( void );
|
||||
|
||||
/** @brief Enable Interrupts by setting the IRQ allowed flag on the CPU
|
||||
* @ingroup Interrupt Management
|
||||
*/
|
||||
#define portENABLE_INTERRUPTS() vPortEnableInterrupts()
|
||||
|
||||
/** @brief Set the IRQ bit of the CPSR low, disabling IRQs.
|
||||
* @ingroup Interrupt Management
|
||||
*/
|
||||
void vPortDisableInterrupts( void );
|
||||
|
||||
/** @brief Enable Interrupts by lowering the IRQ allowed flag on the CPU.
|
||||
* @ingroup Interrupt Management
|
||||
*/
|
||||
#define portDISABLE_INTERRUPTS() vPortDisableInterrupts()
|
||||
|
||||
/** @brief Exit the FreeRTOS-Kernel, restoring the task's settings.
|
||||
*
|
||||
* @ingroup Port Privilege
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void vPortSystemCallExit( void );
|
||||
|
||||
/** @brief Load the context of the first task.
|
||||
*
|
||||
* @ingroup Scheduler
|
||||
*
|
||||
* @note This is an assembly function implemented in portASM.s, it loads the context
|
||||
* of the first task from pxCurrentTCB.
|
||||
*/
|
||||
void vPortStartFirstTask( void );
|
||||
|
||||
/** @brief Enable the onboard MPU
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void prvMpuEnable( void );
|
||||
|
||||
/** @brief Disable the onboard MPU
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
void prvMpuDisable( void );
|
||||
|
||||
/** @brief Assembly routine to set permissions for an MPU Region.
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
* @param[in] regionNumber The MPU Region Number to change permissions for
|
||||
* @param[in] baseAddress The base address of the MPU Region
|
||||
* @param[in] regionSize The number of bytes to make the MPU Region
|
||||
* @param[in] regionPermissions The permissions to assign to the MPU Region
|
||||
*
|
||||
* @note This is an Assembly Function implemented in portASM.S.
|
||||
* This is meant as a purely internal function that performs a raw write of the
|
||||
* provided values to the relevant MPU Registers. The inputs to this function
|
||||
* are checked internally before it is called in the port.c file.
|
||||
*/
|
||||
void prvMpuSetRegion(
|
||||
uint32_t regionNumber,
|
||||
uint32_t baseAddress,
|
||||
uint32_t regionSize,
|
||||
uint32_t regionPermissions
|
||||
);
|
||||
|
||||
/* ----------------------------- Port C Functions ----------------------------- */
|
||||
|
||||
/** @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @ingroup Port Privilege
|
||||
*
|
||||
* @note
|
||||
* The Privilege level is determined by checking if bits [4:0] of
|
||||
* the callers Current Program Status Register are in USER_MODE, 0x10
|
||||
*
|
||||
* @return
|
||||
* 0 If the CPSR Mode Bits are set to 0x10
|
||||
* 1 If the CPSR Mode Bits are set to 0x11-0x11F
|
||||
*
|
||||
*/
|
||||
BaseType_t xPortIsPrivileged( void );
|
||||
|
||||
/** @brief Check if the CPU is currently in a privileged operating mode
|
||||
*
|
||||
* @ingroup Port Privilege
|
||||
*
|
||||
* @return
|
||||
* 1 If the processor is privileged
|
||||
* 0 If the processor is not privileged
|
||||
*
|
||||
*/
|
||||
#define portIS_PRIVILEGED() xPortIsPrivileged()
|
||||
|
||||
/** @brief Check if ulTaskFlags has portTASK_IS_PRIVILEGED_FLAG.
|
||||
*
|
||||
* @ingroup Port Privilege
|
||||
*
|
||||
* @note
|
||||
* As this loads pxCurrentTCB to determine if the task's ulTaskFlags is privileged
|
||||
* or not, this function can return a different value than xPortIsPrivileged.
|
||||
*
|
||||
* @return
|
||||
* 0 If pxCurrentTCB's !( ulTaskFlags && portTASK_IS_PRIVILEGED_FLAG )
|
||||
* 1 If pxCurrentTCB's ( ulTaskFlags && portTASK_IS_PRIVILEGED_FLAG )
|
||||
*/
|
||||
BaseType_t xPortIsTaskPrivileged( void );
|
||||
|
||||
/** @brief Checks whether or not the currently running task is privileged.
|
||||
*
|
||||
* @ingroup Port Privilege
|
||||
*
|
||||
* @return
|
||||
* pdTRUE if the calling task is privileged
|
||||
* pdFALSE if the calling task is not privileged
|
||||
*/
|
||||
#define portIS_TASK_PRIVILEGED() xPortIsTaskPrivileged()
|
||||
|
||||
/** @brief Default return to catch tasks incorrectly exiting their functions. */
|
||||
void prvTaskExitError( void );
|
||||
|
||||
/** @brief User provided task return function.
|
||||
*
|
||||
* @ingroup Task Context
|
||||
*
|
||||
* @note Let the user override the pre-loading of the initial LR with
|
||||
* the address of prvTaskExitError() in case it messes up unwinding of
|
||||
* the stack in the debugger.
|
||||
*/
|
||||
#ifdef configTASK_RETURN_ADDRESS
|
||||
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
|
||||
#else
|
||||
#define configTASK_RETURN_ADDRESS prvTaskExitError
|
||||
#endif /* configTASK_RETURN_ADDRESS */
|
||||
|
||||
/** @brief Address of function a task should execute if it exits its assigned function.
|
||||
*
|
||||
* @ingroup Task Context
|
||||
*
|
||||
* @note If configTASK_RETURN_ADDRESS is not defined this value shall be set to
|
||||
* prvTaskExitError().
|
||||
*/
|
||||
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
|
||||
|
||||
/** @brief The lowest priority interrupt available on the CPU */
|
||||
#define portLOWEST_INTERRUPT_PRIORITY \
|
||||
( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
|
||||
|
||||
/** @brief The lowest priority interrupt that is usable by the system.
|
||||
* @ingroup Interrupt Management
|
||||
*/
|
||||
#define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL )
|
||||
|
||||
/** @brief Returns the number of leading zeros in a 32 bit variable.
|
||||
*
|
||||
* @param[in] ulBitmap 32 Bit long number to count zeros of.
|
||||
*
|
||||
* @return The number of leading zeros ulBitmap has.
|
||||
*/
|
||||
UBaseType_t ulPortCountLeadingZeros( UBaseType_t ulBitmap );
|
||||
|
||||
/* ------------------------- Port MPU Definitions ------------------------- */
|
||||
|
||||
/** @brief Mark that this port utilizes the onboard ARM MPU.
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
* @note The structures and methods of manipulating the MPU are contained
|
||||
* within the port layer. Fills the xMPUSettings structure with the memory
|
||||
* region information contained in xRegions.
|
||||
*
|
||||
*/
|
||||
#define portUSING_MPU_WRAPPERS 1
|
||||
|
||||
/** @brief Used to mark if a task should be created as a privileged task.
|
||||
*
|
||||
* @ingroup Task Context
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
* @note This is done by performing a bitwise OR of this value and the task priority.
|
||||
* For example, to create a privileged task at priority 2 the uxPriority
|
||||
* parameter should be set to ( 2 | portPRIVILEGE_BIT ).
|
||||
*/
|
||||
#define portPRIVILEGE_BIT ( 0x80000000UL )
|
||||
|
||||
/** @brief Mark that a Task has Stack Frame Padding
|
||||
*
|
||||
* @ingroup Task Context
|
||||
*
|
||||
* @note Flags used for xMPU_SETTINGS.ulTaskFlags member to mark the stack frame is
|
||||
* padded. */
|
||||
#define portSTACK_FRAME_HAS_PADDING_FLAG ( 1UL << 0UL )
|
||||
|
||||
#define portSYSTEM_CALL_STACK_SIZE configSYSTEM_CALL_STACK_SIZE
|
||||
|
||||
/** @brief Structure to hold the MPU Register Values
|
||||
* @struct xMPU_REGION_REGISTERS
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
* NOTE: Do not modify this structure. The ordering of this struct MUST
|
||||
* line up with the ordering explained in portRESTORE_CONTEXT.
|
||||
*/
|
||||
typedef struct MPU_REGION_REGISTERS
|
||||
{
|
||||
/** @brief Member used to hold the MPU register value for the Region Size
|
||||
* @struct xMPU_REGION_REGISTERS
|
||||
* @ingroup MPU Control
|
||||
*/
|
||||
uint32_t ulRegionSize;
|
||||
|
||||
/** @brief Member used to hold the MPU register value for the Region Attributes
|
||||
* @struct xMPU_REGION_REGISTERS
|
||||
* @ingroup MPU Control
|
||||
*/
|
||||
uint32_t ulRegionAttribute;
|
||||
|
||||
/** @brief Member used to hold the MPU register value for the Region Base Address.
|
||||
* @struct xMPU_REGION_REGISTERS
|
||||
* @ingroup MPU Control
|
||||
*/
|
||||
uint32_t ulRegionBaseAddress;
|
||||
} xMPU_REGION_REGISTERS;
|
||||
|
||||
/** @brief Structure to hold per-task System Call Stack information
|
||||
* @struct xSYSTEM_CALL_STACK_INFO
|
||||
*
|
||||
* @ingroup Port Privilege
|
||||
*
|
||||
* NOTE: Do not modify this structure. The ordering of this structure is expected to be
|
||||
* this way in the assembly code of the port.
|
||||
*/
|
||||
typedef struct SYSTEM_CALL_STACK_INFO
|
||||
{
|
||||
/** @brief Stack Pointer of the task when it made a FreeRTOS System Call
|
||||
* @note This will point to the start of ulSystemCallStackBuffer[]
|
||||
* @struct xSYSTEM_CALL_STACK_INFO
|
||||
* @ingroup Port Privilege
|
||||
*/
|
||||
uint32_t * pulTaskStackPointer;
|
||||
|
||||
/** @brief Link Register of the task when it made a FreeRTOS System Call
|
||||
* @struct xSYSTEM_CALL_STACK_INFO
|
||||
* @ingroup Port Privilege
|
||||
*/
|
||||
uint32_t * pulLinkRegisterAtSystemCallEntry;
|
||||
|
||||
/** @brief Pre-Set Stack Pointer to use when making a FreeRTOS System Call
|
||||
* @struct xSYSTEM_CALL_STACK_INFO
|
||||
* @ingroup Port Privilege
|
||||
*/
|
||||
uint32_t * pulSystemCallStackPointer;
|
||||
|
||||
/** @brief Pre-Set Link Register to exit a FreeRTOS System Call
|
||||
* @note This value is set in pxPortInitialiseStack to ensure after making
|
||||
* a FreeRTOS System Call that the last LR jump is to vPortSystemCallExit()
|
||||
* @struct xSYSTEM_CALL_STACK_INFO
|
||||
* @ingroup Port Privilege
|
||||
*/
|
||||
void * pulSystemCallLinkRegister;
|
||||
|
||||
/** @brief Buffer to be used when performing a FreeRTOS System Call
|
||||
* @struct xSYSTEM_CALL_STACK_INFO
|
||||
* @ingroup Port Privilege
|
||||
*/
|
||||
uint32_t ulSystemCallStackBuffer[ configSYSTEM_CALL_STACK_SIZE ];
|
||||
} xSYSTEM_CALL_STACK_INFO;
|
||||
|
||||
/** @brief Per-Task MPU Settings structure stored in the TCB
|
||||
* @struct xMPU_SETTINGS
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
* @ingroup Task Context
|
||||
* @ingroup Port Privilege
|
||||
*
|
||||
* NOTE: Do not modify this structure. The ordering of this structure is expected to be
|
||||
* this way in the assembly code of the port.
|
||||
*/
|
||||
typedef struct MPU_SETTINGS
|
||||
{
|
||||
/** @brief Array of Per-Task MPU Register Values. Loaded on Task Context Restore
|
||||
* @struct xMPU_SETTINGS
|
||||
*
|
||||
* @ingroup Task Context
|
||||
* @ingroup Port Privilege
|
||||
* @ingroup MPU Control
|
||||
*/
|
||||
xMPU_REGION_REGISTERS xRegion[ portTOTAL_NUM_REGIONS_IN_TCB ];
|
||||
|
||||
/** @brief Buffer that holds a Task's Context when being swapped out
|
||||
* @struct xMPU_SETTINGS
|
||||
* @ingroup Task Context
|
||||
*/
|
||||
uint32_t ulContext[ MAX_CONTEXT_SIZE ];
|
||||
|
||||
/** @brief Variable to hold FreeRTOS Privilege Settings
|
||||
* @struct xMPU_SETTINGS
|
||||
* @ingroup Task Context
|
||||
* @ingroup MPU Control
|
||||
*/
|
||||
uint32_t ulTaskFlags;
|
||||
|
||||
/** @brief System Call Info structure that is stored in the TCB
|
||||
* @struct xMPU_SETTINGS
|
||||
* @ingroup Task Context
|
||||
* @ingroup Port Privilege
|
||||
*/
|
||||
xSYSTEM_CALL_STACK_INFO xSystemCallStackInfo;
|
||||
} xMPU_SETTINGS;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
539
portable/GCC/ARM_CRx_MPU/portmacro_asm.h
Normal file
539
portable/GCC/ARM_CRx_MPU/portmacro_asm.h
Normal file
|
|
@ -0,0 +1,539 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.6.0
|
||||
* Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
#ifndef PORTMACRO_ASM_H
|
||||
#define PORTMACRO_ASM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
#ifndef configTOTAL_MPU_REGIONS
|
||||
#error "Set configTOTAL_MPU_REGIONS to the humber of MPU regions in FreeRTOSConfig.h"
|
||||
#endif /* configTOTAL_MPU_REGIONS */
|
||||
|
||||
#if( configTOTAL_MPU_REGIONS == 8 )
|
||||
#define portMPU_TOTAL_REGIONS ( 8UL )
|
||||
#elif( configTOTAL_MPU_REGIONS == 12 )
|
||||
#define portMPU_TOTAL_REGIONS ( 12UL )
|
||||
#elif( configTOTAL_MPU_REGIONS == 16 )
|
||||
#define portMPU_TOTAL_REGIONS ( 16UL )
|
||||
#else
|
||||
#error Please specify the number of MPU regions available for your microcontroller
|
||||
#endif
|
||||
|
||||
/** On the ArmV7-R Architecture the Operating mode of the Processor is set using
|
||||
* the Current Program Status and Control Register (CPSR) Mode bits, [4:0]
|
||||
* the only registers banked between modes are the CPSR, Stack Pointer (R13),
|
||||
* and the Link Register (R14). FIQ mode also banks the GPRs R8-R12
|
||||
* Of note, the only mode not "Privileged" is User Mode
|
||||
*
|
||||
* Additional information about the Processor Modes can be found here:
|
||||
* https://developer.arm.com/documentation/ddi0406/cb/System-Level-Architecture/The-System-Level-Programmers--Model/ARM-processor-modes-and-ARM-core-registers/ARM-processor-modes?lang=en
|
||||
*
|
||||
* */
|
||||
|
||||
/** @brief CPSR Mode bit field value for User Mode
|
||||
* @ingroup Port Privilege
|
||||
*/
|
||||
#define USER_MODE 0x10U
|
||||
|
||||
/** @brief CPSR Mode bit field value for Fast Interrupt Handler (FIQ) Mode
|
||||
* @ingroup Port Privilege
|
||||
*/
|
||||
#define FIQ_MODE 0x11U
|
||||
|
||||
/** @brief CPSR Mode bit field value for Interrupt Handler (IRQ) Mode
|
||||
* @ingroup Port Privilege
|
||||
*/
|
||||
#define IRQ_MODE 0x12U
|
||||
|
||||
/** @brief CPSR Mode bit field value for Supervisor (SVC) Mode
|
||||
* @ingroup Port Privilege
|
||||
*/
|
||||
#define SVC_MODE 0x13U
|
||||
|
||||
/** @brief CPSR Mode bit field value for Monitor (MON) Mode
|
||||
* @ingroup Port Privilege
|
||||
*/
|
||||
#define MON_MODE 0x16U
|
||||
|
||||
/** @brief CPSR Mode bit field value for Abort (ABT) Mode
|
||||
* @ingroup Port Privilege
|
||||
*/
|
||||
#define ABT_MODE 0x17U
|
||||
|
||||
/** @brief CPSR Mode bit field value for Hypervisor (HYP) Mode
|
||||
* @ingroup Port Privilege
|
||||
*/
|
||||
#define HYP_MODE 0x1AU
|
||||
|
||||
/** @brief CPSR Mode bit field value for Undefined (UND) Mode
|
||||
* @ingroup Port Privilege
|
||||
*/
|
||||
#define UND_MODE 0x1BU
|
||||
|
||||
/** @brief CPSR Mode bit field value for System (SYS) Mode
|
||||
* @ingroup Port Privilege
|
||||
*/
|
||||
#define SYS_MODE 0x1FU
|
||||
|
||||
/** @brief Mark that a Task Stack has padding values added
|
||||
* @ingroup Task Context
|
||||
*/
|
||||
#define portSTACK_FRAME_HAS_PADDING_FLAG ( 1UL << 0UL )
|
||||
|
||||
/** @brief Flag uses to mark that a FreeRTOS Task is privileged
|
||||
* @ingroup Port Privilege
|
||||
*/
|
||||
#define portTASK_IS_PRIVILEGED_FLAG ( 1UL << 1UL )
|
||||
|
||||
/** @brief SVC Number to use when requesting a context swap.
|
||||
* @ingroup Scheduler
|
||||
*/
|
||||
#define portSVC_YIELD 0x0100
|
||||
|
||||
/** @brief SVC Number to use when exiting a FreeRTOS System Call
|
||||
* @ingroup MPU Control
|
||||
*/
|
||||
#define portSVC_SYSTEM_CALL_EXIT 0x0104
|
||||
|
||||
/**
|
||||
* @addtogroup MPU Control
|
||||
* @note The Region Access Control Register is used to set MPU Region Settings.
|
||||
* Further information about this register can be found in Arm's documentation
|
||||
* https://developer.arm.com/documentation/ddi0363/g/System-Control/Register-descriptions/c6--MPU-memory-region-programming-registers
|
||||
*
|
||||
*/
|
||||
|
||||
/* MPU Sub Region region */
|
||||
#define portMPU_SUBREGION_0_DISABLE ( 0x1UL << 8UL )
|
||||
#define portMPU_SUBREGION_1_DISABLE ( 0x1UL << 9UL )
|
||||
#define portMPU_SUBREGION_2_DISABLE ( 0x1UL << 10UL )
|
||||
#define portMPU_SUBREGION_3_DISABLE ( 0x1UL << 11UL )
|
||||
#define portMPU_SUBREGION_4_DISABLE ( 0x1UL << 12UL )
|
||||
#define portMPU_SUBREGION_5_DISABLE ( 0x1UL << 13UL )
|
||||
#define portMPU_SUBREGION_6_DISABLE ( 0x1UL << 14UL )
|
||||
#define portMPU_SUBREGION_7_DISABLE ( 0x1UL << 15UL )
|
||||
|
||||
#define MPU_REGION_COUNT_OFFSET 8U
|
||||
#define MPU_REGION_COUNT_MASK ( 0xFFUL << MPU_REGION_COUNT_OFFSET )
|
||||
|
||||
#define portSTACK_GUARD \
|
||||
portMPU_SUBREGION_0_DISABLE | portMPU_SUBREGION_1_DISABLE | \
|
||||
portMPU_SUBREGION_2_DISABLE | portMPU_SUBREGION_3_DISABLE | \
|
||||
portMPU_SUBREGION_4_DISABLE | portMPU_SUBREGION_5_DISABLE | \
|
||||
portMPU_SUBREGION_6_DISABLE | portMPU_SUBREGION_7_DISABLE
|
||||
|
||||
#define portUND_STACK_GUARD portSTACK_GUARD & ~portMPU_SUBREGION_0_DISABLE
|
||||
#define portSVC_STACK_GUARD portSTACK_GUARD & ~portMPU_SUBREGION_1_DISABLE
|
||||
|
||||
#define portFIQ_STACK_GUARD \
|
||||
portSTACK_GUARD & ~portMPU_SUBREGION_2_DISABLE | ~portMPU_SUBREGION_3_DISABLE
|
||||
|
||||
#define portABT_STACK_GUARD \
|
||||
portSTACK_GUARD & ~portMPU_SUBREGION_4_DISABLE | ~portMPU_SUBREGION_5_DISABLE
|
||||
|
||||
#define portIRQ_STACK_GUARD \
|
||||
( ( portSTACK_GUARD ) & ( ~portMPU_SUBREGION_7_DISABLE ) & \
|
||||
( ~portMPU_SUBREGION_7_DISABLE ) )
|
||||
|
||||
/* Default MPU regions */
|
||||
#define portFIRST_CONFIGURABLE_REGION ( 0 )
|
||||
#define portLAST_CONFIGURABLE_REGION ( portMPU_TOTAL_REGIONS - 6UL )
|
||||
#define portSTACK_REGION ( portMPU_TOTAL_REGIONS - 5UL )
|
||||
#define portGENERAL_PERIPHERALS_REGION ( portMPU_TOTAL_REGIONS - 4UL )
|
||||
#define portUNPRIVILEGED_FLASH_REGION ( portMPU_TOTAL_REGIONS - 3UL )
|
||||
#define portPRIVILEGED_FLASH_REGION ( portMPU_TOTAL_REGIONS - 2UL )
|
||||
#define portPRIVILEGED_RAM_REGION ( portMPU_TOTAL_REGIONS - 1UL )
|
||||
#define portNUM_CONFIGURABLE_REGIONS \
|
||||
( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1UL )
|
||||
/* Plus one to make space for the stack region*/
|
||||
#define portTOTAL_NUM_REGIONS_IN_TCB ( portNUM_CONFIGURABLE_REGIONS + 1UL )
|
||||
|
||||
/* MPU region sizes */
|
||||
#define portMPU_SIZE_32B ( 0x04UL << 1UL )
|
||||
#define portMPU_SIZE_64B ( 0x05UL << 1UL )
|
||||
#define portMPU_SIZE_128B ( 0x06UL << 1UL )
|
||||
#define portMPU_SIZE_256B ( 0x07UL << 1UL )
|
||||
#define portMPU_SIZE_512B ( 0x08UL << 1UL )
|
||||
#define portMPU_SIZE_1KB ( 0x09UL << 1UL )
|
||||
#define portMPU_SIZE_2KB ( 0x0AUL << 1UL )
|
||||
#define portMPU_SIZE_4KB ( 0x0BUL << 1UL )
|
||||
#define portMPU_SIZE_8KB ( 0x0CUL << 1UL )
|
||||
#define portMPU_SIZE_16KB ( 0x0DUL << 1UL )
|
||||
#define portMPU_SIZE_32KB ( 0x0EUL << 1UL )
|
||||
#define portMPU_SIZE_64KB ( 0x0FUL << 1UL )
|
||||
#define portMPU_SIZE_128KB ( 0x10UL << 1UL )
|
||||
#define portMPU_SIZE_256KB ( 0x11UL << 1UL )
|
||||
#define portMPU_SIZE_512KB ( 0x12UL << 1UL )
|
||||
#define portMPU_SIZE_1MB ( 0x13UL << 1UL )
|
||||
#define portMPU_SIZE_2MB ( 0x14UL << 1UL )
|
||||
#define portMPU_SIZE_4MB ( 0x15UL << 1UL )
|
||||
#define portMPU_SIZE_8MB ( 0x16UL << 1UL )
|
||||
#define portMPU_SIZE_16MB ( 0x17UL << 1UL )
|
||||
#define portMPU_SIZE_32MB ( 0x18UL << 1UL )
|
||||
#define portMPU_SIZE_64MB ( 0x19UL << 1UL )
|
||||
#define portMPU_SIZE_128MB ( 0x1AUL << 1UL )
|
||||
#define portMPU_SIZE_256MB ( 0x1BUL << 1UL )
|
||||
#define portMPU_SIZE_512MB ( 0x1CUL << 1UL )
|
||||
#define portMPU_SIZE_1GB ( 0x1DUL << 1UL )
|
||||
#define portMPU_SIZE_2GB ( 0x1EUL << 1UL )
|
||||
#define portMPU_SIZE_4GB ( 0x1FUL << 1UL )
|
||||
|
||||
/** @brief Used to mark if a task should be created as a privileged task.
|
||||
*
|
||||
* @ingroup Task Context
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
* @note This is done by performing a bitwise OR of this value and the task priority.
|
||||
* For example, to create a privileged task at priority 2 the uxPriority
|
||||
* parameter should be set to ( 2 | portPRIVILEGE_BIT ).
|
||||
*/
|
||||
#define portPRIVILEGE_BIT ( 0x80000000UL )
|
||||
|
||||
/** @brief MPU Setting for a Strongly Ordered Memory Region
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
*/
|
||||
#define portMPU_REGION_STRONGLY_ORDERED ( 0x00UL )
|
||||
|
||||
/** @brief MPU Setting for a Strongly Ordered Memory Region
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
*/
|
||||
#define portMPU_REGION_DEVICE ( 0x01UL )
|
||||
|
||||
/** @brief MPU Setting for a Strongly Ordered Memory Region
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
*/
|
||||
#define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x03UL )
|
||||
|
||||
/** @brief MPU Setting for a Strongly Ordered Memory Region
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
*/
|
||||
#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 12UL )
|
||||
|
||||
/** @brief MPU Setting for a Strongly Ordered and Shareable Memory Region
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
*/
|
||||
#define portMPU_STRONGLYORDERED_SHAREABLE ( 0x0000UL )
|
||||
|
||||
/** @brief MPU Setting for a Device and Shareable Memory Region
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
*/
|
||||
#define portMPU_DEVICE_SHAREABLE ( 0x0001UL )
|
||||
|
||||
/** @brief MPU Setting for a Device and Non-Shareable Memory Region
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
*/
|
||||
#define portMPU_DEVICE_NONSHAREABLE ( 0x0010UL )
|
||||
|
||||
/** @brief MPU Setting for a Normal Outer & Inner Write-Through, No Write Allocate & Non
|
||||
* Shared
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
*/
|
||||
#define portMPU_NORMAL_OIWTNOWA_NONSHARED ( 0x0002UL )
|
||||
|
||||
/** @brief MPU Setting for a Normal Outer & Inner Write-Back, No Write Allocate & Non
|
||||
* Shared
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
*/
|
||||
#define portMPU_NORMAL_OIWBNOWA_NONSHARED ( 0x0003UL )
|
||||
|
||||
/** @brief MPU Setting for a Normal Outer & Inner Write-Through, no Write Allocate &
|
||||
* Shared
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
*/
|
||||
#define portMPU_NORMAL_OIWTNOWA_SHARED ( 0x0006UL )
|
||||
|
||||
/** @brief MPU Setting for a Normal Outer & Inner Write-back, no Write Allocate & Shared
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
*/
|
||||
#define portMPU_NORMAL_OIWBNOWA_SHARED ( 0x0007UL )
|
||||
|
||||
/** @brief MPU Setting for a Normal Outer & Inner Non-Cacheable & Non Shared
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
*/
|
||||
#define portMPU_NORMAL_OINC_NONSHARED ( 0x0008UL )
|
||||
|
||||
/** @brief MPU Setting for a Normal Outer & Inner Write-Back, Write Allocate & Non Shared
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
*/
|
||||
#define portMPU_NORMAL_OIWBWA_NONSHARED ( 0x000BUL )
|
||||
|
||||
/** @brief MPU Setting for a Normal Outer & Inner Non-Cacheable & Shared
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
*/
|
||||
#define portMPU_NORMAL_OINC_SHARED ( 0x000CUL )
|
||||
|
||||
/** @brief MPU Setting for a Normal Outer & Inner Write-Back, Write Allocate & Shared
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
*/
|
||||
#define portMPU_NORMAL_OIWBWA_SHARED ( 0x000FUL )
|
||||
|
||||
/** @brief MPU_CTRL value for: No Access and No Execute
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
* @brief No Access in a Privileged Operating Mode
|
||||
* No Access in User Mode
|
||||
* Cannot Execute Code from this region
|
||||
*/
|
||||
#define portMPU_PRIV_NA_USER_NA_NOEXEC ( 0x1000UL )
|
||||
|
||||
/** @brief MPU_CTRL value for Privileged Read and Exec
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
* @note Read Only Access in Privileged Operating Modes.
|
||||
* No Read/Write Access in User Mode
|
||||
* Allowed to Execute Code from this region
|
||||
*/
|
||||
#define portMPU_PRIV_RO_USER_NA_EXEC ( 0x0500UL )
|
||||
|
||||
/** @brief MPU_CTRL value for Privileged Read, Write, and Exec
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
* Read/Write in a Privileged Operating Mode
|
||||
* No Access in User Mode
|
||||
* Allowed to Execute Code from this region
|
||||
*/
|
||||
#define portMPU_PRIV_RW_USER_NA_EXEC ( 0x0100UL )
|
||||
|
||||
/** @brief MPU_CTRL value for Read Only and Execute
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
* @note Read Only in a Privileged Operating Mode
|
||||
* Read Only in User Mode
|
||||
* Allowed to Execute Code from this region
|
||||
* */
|
||||
#define portMPU_PRIV_RO_USER_RO_EXEC ( 0x0600UL )
|
||||
|
||||
/** @brief MPU_CTRL value for: Read, Execute, and Privileged Write
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
* @note Read/Write in a Privileged Operating Mode
|
||||
* Read Only in User Mode
|
||||
* Allowed to Execute Code from this region
|
||||
*/
|
||||
#define portMPU_PRIV_RW_USER_RO_EXEC ( 0x0200UL )
|
||||
|
||||
/** @brief MPU_CTRL value for: Read, Write, and Execute
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
* @note Read/Write in a Privileged Operating Mode
|
||||
* Read/write in User Mode
|
||||
* Allowed to Execute Code from this region
|
||||
*/
|
||||
#define portMPU_PRIV_RW_USER_RW_EXEC ( 0x0300UL )
|
||||
|
||||
/** @brief MPU_CTRL value for: Privileged Read, Write Only, no Execute
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
* @note Read/Write in a Privileged Operating Mode
|
||||
* No Access in User Mode
|
||||
* Cannot Execute Code from this region
|
||||
*/
|
||||
#define portMPU_PRIV_RW_USER_NA_NOEXEC ( 0x1100UL )
|
||||
|
||||
/** @brief MPU_CTRL value for: All Read, Privileged Write, no Execute
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
* Read/Write in a Privileged Operating Mode
|
||||
* Read Only in User Mode
|
||||
* Cannot Execute Code from this region
|
||||
*/
|
||||
#define portMPU_PRIV_RW_USER_RO_NOEXEC ( 0x1200UL )
|
||||
|
||||
/** @brief MPU_CTRL value for: Read, Write, no Execute
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
* @note Read/Write in a Privileged Operating Mode
|
||||
* Read/Write in User Mode
|
||||
* Cannot Execute Code from this region
|
||||
*/
|
||||
#define portMPU_PRIV_RW_USER_RW_NOEXEC ( 0x1300UL )
|
||||
|
||||
/** @brief MPU_CTRL value for: Privileged Read Only, No Execute
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
* @note Read Only in a Privileged Operating Mode
|
||||
* No Access in User Mode
|
||||
* Cannot Execute Code from this region
|
||||
*/
|
||||
#define portMPU_PRIV_RO_USER_NA_NOEXEC ( 0x1500UL )
|
||||
|
||||
/** @brief MPU_CTRL value for: Read Only, No Execute
|
||||
*
|
||||
* @ingroup MPU Control
|
||||
*
|
||||
* @note Read Only in a Privileged Operating Mode
|
||||
* Read Only in User Mode
|
||||
* Cannot Execute Code from this region
|
||||
*/
|
||||
#define portMPU_PRIV_RO_USER_RO_NOEXEC ( 0x1600UL )
|
||||
|
||||
/** @brief MPU_CTRL value to enable an MPU Region
|
||||
* @ingroup MPU Control
|
||||
*/
|
||||
#define portMPU_REGION_ENABLE ( 0x01UL )
|
||||
|
||||
/** @brief The lowest priority interrupt that is usable by the system */
|
||||
#define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL )
|
||||
|
||||
/** This following section is used to create the proper size for the ulContext array.
|
||||
* This array is where all registers related to a task's context are saved.
|
||||
* The size of this array will depend on if the system is using an integrated
|
||||
* Floating Point Unit (FPU) or not. If we are using the FPU we must save the
|
||||
* Floating Point Status and Control Register (FPSCR),
|
||||
* and the Floating Point Registers (FPRs). The FPSCR holds the conditional bits
|
||||
* used for floating point calculations. The FPRs hold the actual floating point bits.
|
||||
* The remainder of a task's context consists of the General Purpose Registers (GPRs).
|
||||
* General Purpose Registers are used to manipulate almost all variables.
|
||||
* The Current Program Status and Control Register, which holds the operating mode
|
||||
* and bits that correspond to any conditional checks, such as if statements.
|
||||
* And the Critical Nesting Depth of the task.
|
||||
*
|
||||
*
|
||||
* For more information about the FPU, FPSCR, and FPRs please reference ARM's website:
|
||||
* https://developer.arm.com/documentation/den0042/a/Floating-Point
|
||||
*
|
||||
* Additional information related to the Cortex R4-F's FPU Implementation:
|
||||
* https://developer.arm.com/documentation/ddi0363/e/fpu-programmer-s-model
|
||||
*
|
||||
* Additional information related to the Cortex R5-F's FPU Implementation:
|
||||
* https://developer.arm.com/documentation/ddi0460/d/FPU-Programmers-Model
|
||||
*
|
||||
* Additional information related to the ArmV7-R CPSR
|
||||
* https://developer.arm.com/documentation/ddi0406/cb/Application-Level-Architecture/Application-Level-Programmers--Model/The-Application-Program-Status-Register--APSR-?lang=en
|
||||
*
|
||||
* Additional information related to the GPRs:
|
||||
* https://developer.arm.com/documentation/ddi0406/cb/System-Level-Architecture/The-System-Level-Programmers--Model/ARM-processor-modes-and-ARM-core-registers/ARM-core-registers?lang=en
|
||||
*
|
||||
*/
|
||||
|
||||
/** @brief The length in ulContext for the General Purpose Registers in bytes
|
||||
* @note There are 13 GPRs, R0-R12 each is 32 bits, so 13 registers * 4 Bytes each
|
||||
*/
|
||||
#define portGPR_LENGTH ( 13U * 4U )
|
||||
|
||||
/** @brief The length in ulContext for all the registers in a context
|
||||
* @note There are the 13 GPRs, the Stack Pointer, and the Link Register
|
||||
*/
|
||||
#define portREGISTER_CONTEXT_LENGTH ( portGPR_LENGTH + ( 2 * 4U ) )
|
||||
|
||||
/** If you KNOW that your system will not utilize the FPU in any capacity
|
||||
* you can set portENABLE_FPU to 0, which will reduce the per-task RAM usage
|
||||
* by ( 32 FPRs + 32 bit FPSCR ) * 4 bytes per register = 132, or 0x84, Bytes Per Task
|
||||
* BE CAREFUL DISABLING THIS: Certain APIs will try and optimize themselves
|
||||
* by using the FPRs. If the FPU context is not saved and this happens it could be
|
||||
* exceedingly difficult to debug why a strcpy() or other similar function
|
||||
* seems to randomly fail.
|
||||
*/
|
||||
#ifndef configENABLE_FPU
|
||||
#define configENABLE_FPU 0
|
||||
#endif
|
||||
|
||||
/** @brief Mark if the Floating Point Registers will be saved.
|
||||
* @ingroup Task Context
|
||||
* @note When using the FPU, we must save additional registers into the task's context
|
||||
* These consist of the Floating Point Status and Control Register (FPSCR),
|
||||
* As well as the Floating Point Registers (FPRs)
|
||||
* Task Context which is stored in ulContext in order, consists of:
|
||||
* ulContext[ 0 ]: Critical Nesting Count: ulCriticalNesting
|
||||
* ulContext[ 1 ]: Floating Point Status and Control Register
|
||||
* ulContext[ 2 - 33 ]: Floating Point Registers: S0-S31
|
||||
* ulContext[ 34 - 46 ]: General Purpose Registers: R0-R12
|
||||
* ulContext[ 47 ]: Stack Pointer
|
||||
* ulContext[ 48 ]: Link Register
|
||||
* ulContext[ 49 ]: Program Counter
|
||||
* ulContext[ 50 ]: Current Program Status and Control Register
|
||||
* ulContext[ 51 ]: Supervisor Mode SRS PC Scratch Space
|
||||
* ulContext[ 52 ]: Supervisor Mode SRS CPSR Scratch Space
|
||||
*/
|
||||
#define portENABLE_FPU configENABLE_FPU
|
||||
|
||||
#if( portENABLE_FPU == 1 )
|
||||
/** @brief Length of a Task's Register Context when using an FPU. */
|
||||
#define MAX_CONTEXT_SIZE 52U
|
||||
#else
|
||||
/** @brief Length of a Task's Register Context when not using an FPU. */
|
||||
#define MAX_CONTEXT_SIZE 20U
|
||||
#endif
|
||||
/** @brief Numerical offset from the start of a TCB to xSystemCallStackInfo
|
||||
* @note In the exception handlers it is necessary to load this variable from the TCB.
|
||||
* This provides an easy way for the exception handlers to get this structure.
|
||||
* The numerical value here should be equal to:
|
||||
* sizeof( xRegion ) + sizeof( ulContext ) + sizeof( ulTaskFlags)
|
||||
*/
|
||||
#define portSYSTEM_CALL_INFO_OFFSET \
|
||||
( ( ( portTOTAL_NUM_REGIONS_IN_TCB * 3U ) + ( MAX_CONTEXT_SIZE ) + 1 ) * 4U )
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_ASM_H */
|
||||
Loading…
Add table
Add a link
Reference in a new issue