diff --git a/portable/GCC/ARM_CRx_MPU/mpu_wrappers_v2_asm.S b/portable/GCC/ARM_CRx_MPU/mpu_wrappers_v2_asm.S new file mode 100644 index 000000000..cbbeda00a --- /dev/null +++ b/portable/GCC/ARM_CRx_MPU/mpu_wrappers_v2_asm.S @@ -0,0 +1,1332 @@ +/* + * FreeRTOS V202112.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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 + .section freertos_system_calls +#define FREERTOS_ASSEMBLY + #include "FreeRTOSConfig.h" + #include "portmacro_asm.h" + #include "mpu_syscall_numbers.h" +#undef FREERTOS_ASSEMBLY + +/* ------------------ Start of Port Specific System Calls ------------------ */ + +/** + * Function: void vPortYield + * Inputs: VOID +*/ +.align 4 +.global vPortYield +.type vPortYield, %function +vPortYield: + /* Make the SVC to swap tasks */ + SVC #portSVC_YIELD + /* After yielding to another task, resume executing the calling task */ + BX LR + + +/*-------------------------------------------------------------------------------*/ +/* vPortSystemCallExit */ +.align 4 +.global vPortSystemCallExit +.type vPortSystemCallExit, %function +vPortSystemCallExit: + /* Make the SVC to exit a system call */ + SVC #portSVC_SYSTEM_CALL_EXIT + /* After performing the requested FreeRTOS API, return to the calling task */ + BX LR + +/*-------------------------------------------------------------------------------*/ +/** + * Function: BaseType_t xPortIsPrivileged + * Inputs: VOID +*/ +.align 4 +.weak xPortIsPrivileged +.type xPortIsPrivileged, %function +xPortIsPrivileged: + /* Load value of SPSR into R0 */ + MRS R0, CPSR + /* Get the relevant mode bits */ + AND R0, R0, #0x1F + /* Check if we're in user mode */ + CMP R0, #USER_MODE + /* If we are in user mode set R0 to 0 for the return */ + MOVEQ R0, #0x0 + /* Otherwise set R0 to 1 for the return */ + MOVNE R0, #0x01 + BLX LR + +/*-------------------------------------------------------------------------------*/ +/** + * Function: UBaseType_t ulPortCountLeadingZeros + * Inputs: UBaseType_t ulBitmap +*/ +.align 4 +.weak ulPortCountLeadingZeros +.type ulPortCountLeadingZeros, %function +ulPortCountLeadingZeros: + /* Count the leading zeros and return in R0 */ + CLZ R0, R0 + BX LR + +/* ------------------- End of Port Specific System Calls ------------------- */ + +.macro processorInUserMode + /* Push R0 before using it */ + PUSH {R0} + /* Load value of SPSR into R0 */ + MRS R0, CPSR + /* Get the relevant mode bits */ + AND R0, R0, #0x1F + /* Determine if the CPU is in user mode */ + CMP R0, #USER_MODE + /* Restore the pushed register */ + POP {R0} +.endm + +/*---------------------------------------------------------------------------*/ + +.extern MPU_xTaskGetTickCountImpl +/** + * Function: TickType_t MPU_xTaskGetTickCount + * Inputs: void - No Inputs +*/ +.align 4 +.global MPU_xTaskGetTickCount +.type MPU_xTaskGetTickCount, function +MPU_xTaskGetTickCount: + processorInUserMode + SVCEQ #SYSTEM_CALL_xTaskGetTickCount + B MPU_xTaskGetTickCountImpl + +/*---------------------------------------------------------------------------*/ + +.extern MPU_uxTaskGetNumberOfTasksImpl +/** + * Function: UBaseType_t MPU_uxTaskGetNumberOfTasks + * Inputs: void - No Inputs +*/ +.align 4 +.global MPU_uxTaskGetNumberOfTasks +.type MPU_uxTaskGetNumberOfTasks, function +MPU_uxTaskGetNumberOfTasks: + processorInUserMode + SVCEQ #SYSTEM_CALL_uxTaskGetNumberOfTasks + B MPU_uxTaskGetNumberOfTasksImpl + +/*---------------------------------------------------------------------------*/ + +.extern MPU_vTaskSetTimeOutStateImpl +/** + * Function: void MPU_vTaskSetTimeOutState + * Inputs: TimeOut_t * const pxTimeOut +*/ +.align 4 +.global MPU_vTaskSetTimeOutState +.type MPU_vTaskSetTimeOutState, function +MPU_vTaskSetTimeOutState: + processorInUserMode + SVCEQ #SYSTEM_CALL_vTaskSetTimeOutState + B MPU_vTaskSetTimeOutStateImpl + +/*---------------------------------------------------------------------------*/ + +.extern MPU_xTaskCheckForTimeOutImpl +/** + * Function: BaseType_t MPU_xTaskCheckForTimeOut + * Inputs: TimeOut_t * const pxTimeOut + * Inputs: TickType_t * const pxTicksToWait +*/ +.align 4 +.global MPU_xTaskCheckForTimeOut +.type MPU_xTaskCheckForTimeOut, function +MPU_xTaskCheckForTimeOut: + processorInUserMode + SVCEQ #SYSTEM_CALL_xTaskCheckForTimeOut + B MPU_xTaskCheckForTimeOutImpl + +/*---------------------------------------------------------------------------*/ + +.extern MPU_xQueueGenericSendImpl +/** + * Function: BaseType_t MPU_xQueueGenericSend + * Inputs: QueueHandle_t xQueue + * Inputs: const void * const pvItemToQueue + * Inputs: TickType_t xTicksToWait + * Inputs: constBaseType_t xCopyPosition +*/ +.align 4 +.global MPU_xQueueGenericSend +.type MPU_xQueueGenericSend, function +MPU_xQueueGenericSend: + processorInUserMode + SVCEQ #SYSTEM_CALL_xQueueGenericSend + B MPU_xQueueGenericSendImpl + +/*---------------------------------------------------------------------------*/ + +.extern MPU_uxQueueMessagesWaitingImpl +/** + * Function: UBaseType_t MPU_uxQueueMessagesWaiting + * Inputs: const QueueHandle_t xQueue +*/ +.align 4 +.global MPU_uxQueueMessagesWaiting +.type MPU_uxQueueMessagesWaiting, function +MPU_uxQueueMessagesWaiting: + processorInUserMode + SVCEQ #SYSTEM_CALL_uxQueueMessagesWaiting + B MPU_uxQueueMessagesWaitingImpl + +/*---------------------------------------------------------------------------*/ + +.extern MPU_uxQueueSpacesAvailableImpl +/** + * Function: UBaseType_t MPU_uxQueueSpacesAvailable + * Inputs: const QueueHandle_t xQueue +*/ +.align 4 +.global MPU_uxQueueSpacesAvailable +.type MPU_uxQueueSpacesAvailable, function +MPU_uxQueueSpacesAvailable: + processorInUserMode + SVCEQ #SYSTEM_CALL_uxQueueSpacesAvailable + B MPU_uxQueueSpacesAvailableImpl + +/*---------------------------------------------------------------------------*/ + +.extern MPU_xQueueReceiveImpl +/** + * Function: BaseType_t MPU_xQueueReceive + * Inputs: QueueHandle_t xQueue + * Inputs: void * const pvBuffer + * Inputs: TickType_t xTicksToWait +*/ +.align 4 +.global MPU_xQueueReceive +.type MPU_xQueueReceive, function +MPU_xQueueReceive: + processorInUserMode + SVCEQ #SYSTEM_CALL_xQueueReceive + B MPU_xQueueReceiveImpl + +/*---------------------------------------------------------------------------*/ + +.extern MPU_xQueuePeekImpl +/** + * Function: BaseType_t MPU_xQueuePeek + * Inputs: QueueHandle_t xQueue + * Inputs: void * const pvBuffer + * Inputs: TickType_t xTicksToWait +*/ +.align 4 +.global MPU_xQueuePeek +.type MPU_xQueuePeek, function +MPU_xQueuePeek: + processorInUserMode + SVCEQ #SYSTEM_CALL_xQueuePeek + B MPU_xQueuePeekImpl + +/*---------------------------------------------------------------------------*/ + +.extern MPU_xQueueSemaphoreTakeImpl +/** + * Function: BaseType_t MPU_xQueueSemaphoreTake + * Inputs: QueueHandle_t xQueue + * Inputs: TickType_t xTicksToWait +*/ +.align 4 +.global MPU_xQueueSemaphoreTake +.type MPU_xQueueSemaphoreTake, function +MPU_xQueueSemaphoreTake: + processorInUserMode + SVCEQ #SYSTEM_CALL_xQueueSemaphoreTake + B MPU_xQueueSemaphoreTakeImpl + +/*---------------------------------------------------------------------------*/ + +.extern MPU_xEventGroupWaitBitsImpl +/** + * Function: EventBits_t MPU_xEventGroupWaitBitsEntry + * Inputs: const xEventGroupWaitBitsParams_t * pxParams +*/ +.align 4 +.global MPU_xEventGroupWaitBitsEntry +.type MPU_xEventGroupWaitBitsEntry, function +MPU_xEventGroupWaitBitsEntry: + processorInUserMode + SVCEQ #SYSTEM_CALL_xEventGroupWaitBits + B MPU_xEventGroupWaitBitsImpl + +/*---------------------------------------------------------------------------*/ + +.extern MPU_xEventGroupClearBitsImpl +/** + * Function: EventBits_t MPU_xEventGroupClearBits + * Inputs: EventGroupHandle_t xEventGroup + * Inputs: constEventBits_t uxBitsToClear +*/ +.align 4 +.global MPU_xEventGroupClearBits +.type MPU_xEventGroupClearBits, function +MPU_xEventGroupClearBits: + processorInUserMode + SVCEQ #SYSTEM_CALL_xEventGroupClearBits + B MPU_xEventGroupClearBitsImpl + +/*---------------------------------------------------------------------------*/ + +.extern MPU_xEventGroupSetBitsImpl +/** + * Function: EventBits_t MPU_xEventGroupSetBits + * Inputs: EventGroupHandle_t xEventGroup + * Inputs: constEventBits_t uxBitsToSet +*/ +.align 4 +.global MPU_xEventGroupSetBits +.type MPU_xEventGroupSetBits, function +MPU_xEventGroupSetBits: + processorInUserMode + SVCEQ #SYSTEM_CALL_xEventGroupSetBits + B MPU_xEventGroupSetBitsImpl + +/*---------------------------------------------------------------------------*/ + +.extern MPU_xEventGroupSyncImpl +/** + * Function: EventBits_t MPU_xEventGroupSync + * Inputs: EventGroupHandle_t xEventGroup + * Inputs: constEventBits_t uxBitsToSet + * Inputs: constEventBits_t uxBitsToWaitFor + * Inputs: TickType_t xTicksToWait +*/ +.align 4 +.global MPU_xEventGroupSync +.type MPU_xEventGroupSync, function +MPU_xEventGroupSync: + processorInUserMode + SVCEQ #SYSTEM_CALL_xEventGroupSync + B MPU_xEventGroupSyncImpl + +/*---------------------------------------------------------------------------*/ + +.extern MPU_xStreamBufferSendImpl +/** + * Function: size_t MPU_xStreamBufferSend + * Inputs: StreamBufferHandle_t xStreamBuffer + * Inputs: const void * pvTxData + * Inputs: size_t xDataLengthBytes + * Inputs: TickType_t xTicksToWait +*/ +.align 4 +.global MPU_xStreamBufferSend +.type MPU_xStreamBufferSend, function +MPU_xStreamBufferSend: + processorInUserMode + SVCEQ #SYSTEM_CALL_xStreamBufferSend + B MPU_xStreamBufferSendImpl + +/*---------------------------------------------------------------------------*/ + +.extern MPU_xStreamBufferReceiveImpl +/** + * Function: size_t MPU_xStreamBufferReceive + * Inputs: StreamBufferHandle_t xStreamBuffer + * Inputs: void * pvRxData + * Inputs: size_t xBufferLengthBytes + * Inputs: TickType_t xTicksToWait +*/ +.align 4 +.global MPU_xStreamBufferReceive +.type MPU_xStreamBufferReceive, function +MPU_xStreamBufferReceive: + processorInUserMode + SVCEQ #SYSTEM_CALL_xStreamBufferReceive + B MPU_xStreamBufferReceiveImpl + +/*---------------------------------------------------------------------------*/ + +.extern MPU_xStreamBufferIsFullImpl +/** + * Function: BaseType_t MPU_xStreamBufferIsFull + * Inputs: StreamBufferHandle_t xStreamBuffer +*/ +.align 4 +.global MPU_xStreamBufferIsFull +.type MPU_xStreamBufferIsFull, function +MPU_xStreamBufferIsFull: + processorInUserMode + SVCEQ #SYSTEM_CALL_xStreamBufferIsFull + B MPU_xStreamBufferIsFullImpl + +/*---------------------------------------------------------------------------*/ + +.extern MPU_xStreamBufferIsEmptyImpl +/** + * Function: BaseType_t MPU_xStreamBufferIsEmpty + * Inputs: StreamBufferHandle_t xStreamBuffer +*/ +.align 4 +.global MPU_xStreamBufferIsEmpty +.type MPU_xStreamBufferIsEmpty, function +MPU_xStreamBufferIsEmpty: + processorInUserMode + SVCEQ #SYSTEM_CALL_xStreamBufferIsEmpty + B MPU_xStreamBufferIsEmptyImpl + +/*---------------------------------------------------------------------------*/ + +.extern MPU_xStreamBufferSpacesAvailableImpl +/** + * Function: size_t MPU_xStreamBufferSpacesAvailable + * Inputs: StreamBufferHandle_t xStreamBuffer +*/ +.align 4 +.global MPU_xStreamBufferSpacesAvailable +.type MPU_xStreamBufferSpacesAvailable, function +MPU_xStreamBufferSpacesAvailable: + processorInUserMode + SVCEQ #SYSTEM_CALL_xStreamBufferSpacesAvailable + B MPU_xStreamBufferSpacesAvailableImpl + +/*---------------------------------------------------------------------------*/ + +.extern MPU_xStreamBufferBytesAvailableImpl +/** + * Function: size_t MPU_xStreamBufferBytesAvailable + * Inputs: StreamBufferHandle_t xStreamBuffer +*/ +.align 4 +.global MPU_xStreamBufferBytesAvailable +.type MPU_xStreamBufferBytesAvailable, function +MPU_xStreamBufferBytesAvailable: + processorInUserMode + SVCEQ #SYSTEM_CALL_xStreamBufferBytesAvailable + B MPU_xStreamBufferBytesAvailableImpl + +/*---------------------------------------------------------------------------*/ + +.extern MPU_xStreamBufferSetTriggerLevelImpl +/** + * Function: BaseType_t MPU_xStreamBufferSetTriggerLevel + * Inputs: StreamBufferHandle_t xStreamBuffer + * Inputs: size_t xTriggerLevel +*/ +.align 4 +.global MPU_xStreamBufferSetTriggerLevel +.type MPU_xStreamBufferSetTriggerLevel, function +MPU_xStreamBufferSetTriggerLevel: + processorInUserMode + SVCEQ #SYSTEM_CALL_xStreamBufferSetTriggerLevel + B MPU_xStreamBufferSetTriggerLevelImpl + +/*---------------------------------------------------------------------------*/ + +.extern MPU_xStreamBufferNextMessageLengthBytesImpl +/** + * Function: size_t MPU_xStreamBufferNextMessageLengthBytes + * Inputs: StreamBufferHandle_t xStreamBuffer +*/ +.align 4 +.global MPU_xStreamBufferNextMessageLengthBytes +.type MPU_xStreamBufferNextMessageLengthBytes, function +MPU_xStreamBufferNextMessageLengthBytes: + processorInUserMode + SVCEQ #SYSTEM_CALL_xStreamBufferNextMessageLengthBytes + B MPU_xStreamBufferNextMessageLengthBytesImpl + +/*---------------------------------------------------------------------------*/ + +#if INCLUDE_xTaskDelayUntil == 1 + .extern MPU_xTaskDelayUntilImpl + /** + * Function: TaskHandle_t MPU_xTaskDelayUntil + * Inputs: TickType_t * const pxPreviousWakeTime + * Inputs: constTickType_t xTimeIncrement + */ + .align 4 + .global MPU_xTaskDelayUntil + .type MPU_xTaskDelayUntil, function + MPU_xTaskDelayUntil: + processorInUserMode + SVCEQ #SYSTEM_CALL_xTaskDelayUntil + B MPU_xTaskDelayUntilImpl + + /*-----------------------------------------------------------------------*/ + +#endif /* if ( INCLUDE_xTaskDelayUntil == 1 ) */ + +#if INCLUDE_xTaskAbortDelay == 1 + +/*---------------------------------------------------------------------------*/ + + .extern MPU_xTaskAbortDelayImpl + /** + * Function: TaskHandle_t MPU_xTaskAbortDelay + * Inputs: TaskHandle_t xTask + */ + .align 4 + .global MPU_xTaskAbortDelay + .type MPU_xTaskAbortDelay, function + MPU_xTaskAbortDelay: + processorInUserMode + SVCEQ #SYSTEM_CALL_xTaskAbortDelay + B MPU_xTaskAbortDelayImpl + + /*-----------------------------------------------------------------------*/ + +#endif /* if ( INCLUDE_xTaskAbortDelay == 1 ) */ + +#if INCLUDE_vTaskDelay == 1 + + /*-----------------------------------------------------------------------*/ + + .extern MPU_vTaskDelayImpl + /** + * Function: void MPU_vTaskDelay + * Inputs: const TickType_t xTicksToDelay + */ + .align 4 + .global MPU_vTaskDelay + .type MPU_vTaskDelay, function + MPU_vTaskDelay: + processorInUserMode + SVCEQ #SYSTEM_CALL_vTaskDelay + B MPU_vTaskDelayImpl + + /*-----------------------------------------------------------------------*/ + +#endif /* if ( INCLUDE_vTaskDelay == 1 ) */ + +#if INCLUDE_uxTaskPriorityGet == 1 + + /*-----------------------------------------------------------------------*/ + + .extern MPU_uxTaskPriorityGetImpl + /** + * Function: UBaseType_t MPU_uxTaskPriorityGet + * Inputs: const TaskHandle_t xTask + */ + .align 4 + .global MPU_uxTaskPriorityGet + .type MPU_uxTaskPriorityGet, function + MPU_uxTaskPriorityGet: + processorInUserMode + SVCEQ #SYSTEM_CALL_uxTaskPriorityGet + B MPU_uxTaskPriorityGetImpl + + /*-----------------------------------------------------------------------*/ + +#endif /* if ( INCLUDE_uxTaskPriorityGet == 1 ) */ + +#if INCLUDE_eTaskGetState == 1 + + /*-----------------------------------------------------------------------*/ + + .extern MPU_eTaskGetStateImpl + /** + * Function: eTaskState MPU_eTaskGetState + * Inputs: TaskHandle_t xTask + */ + .align 4 + .global MPU_eTaskGetState + .type MPU_eTaskGetState, function + MPU_eTaskGetState: + processorInUserMode + SVCEQ #SYSTEM_CALL_eTaskGetState + B MPU_eTaskGetStateImpl + + /*-----------------------------------------------------------------------*/ + +#endif /* if ( INCLUDE_eTaskGetState == 1 ) */ + +#if configUSE_TRACE_FACILITY == 1 + + /*-----------------------------------------------------------------------*/ + + .extern MPU_vTaskGetInfoImpl + /** + * Function: void MPU_vTaskGetInfo + * Inputs: TaskHandle_t xTask + * Inputs: TaskStatus_t* pxTaskStatus + * Inputs: TaskHandle_t xGetFreeStackSpace + * Inputs: eTaskState eState + */ + .align 4 + .global MPU_vTaskGetInfo + .type MPU_vTaskGetInfo, function + MPU_vTaskGetInfo: + processorInUserMode + SVCEQ #SYSTEM_CALL_vTaskGetInfo + B MPU_vTaskGetInfoImpl + + /*-----------------------------------------------------------------------*/ + + .extern MPU_uxTaskGetSystemStateImpl + /** + * Function: UBaseType_t MPU_uxTaskGetSystemState + * Inputs: TaskStatus_t * const pxTaskStatusArray + * Inputs: constUBaseType_t uxArraySize + * Inputs: configRUN_TIME_COUNTER_TYPE* const pulTotalRunTime + */ + .align 4 + .global MPU_uxTaskGetSystemState + .type MPU_uxTaskGetSystemState, function + MPU_uxTaskGetSystemState: + processorInUserMode + SVCEQ #SYSTEM_CALL_uxTaskGetSystemState + B MPU_uxTaskGetSystemStateImpl + + /*-----------------------------------------------------------------------*/ + + .extern MPU_uxEventGroupGetNumberImpl + /** + * Function: UBaseType_t MPU_uxEventGroupGetNumber + * Inputs: void * xEventGroup + */ + .align 4 + .global MPU_uxEventGroupGetNumber + .type MPU_uxEventGroupGetNumber, function + MPU_uxEventGroupGetNumber: + processorInUserMode + SVCEQ #SYSTEM_CALL_uxEventGroupGetNumber + B MPU_uxEventGroupGetNumberImpl + + /*-----------------------------------------------------------------------*/ + + .extern MPU_vEventGroupSetNumberImpl + /** + * Function: void MPU_vEventGroupSetNumber + * Inputs: void * xEventGroup + * Inputs: UBaseType_t uxEventGroupNumber + */ + .align 4 + .global MPU_vEventGroupSetNumber + .type MPU_vEventGroupSetNumber, function + MPU_vEventGroupSetNumber: + processorInUserMode + SVCEQ #SYSTEM_CALL_vEventGroupSetNumber + B MPU_vEventGroupSetNumberImpl + + /*-----------------------------------------------------------------------*/ +#endif /* if ( configUSE_TRACE_FACILITY == 1 ) */ + +#if INCLUDE_xTaskGetIdleTaskHandle == 1 + + /*-----------------------------------------------------------------------*/ + .extern MPU_xTaskGetIdleTaskHandleImpl + /** + * Function: TaskHandle_t MPU_xTaskGetIdleTaskHandle + * Inputs: void - No Inputs + */ + .align 4 + .global MPU_xTaskGetIdleTaskHandle + .type MPU_xTaskGetIdleTaskHandle, function + MPU_xTaskGetIdleTaskHandle: + processorInUserMode + SVCEQ #SYSTEM_CALL_xTaskGetIdleTaskHandle + B MPU_xTaskGetIdleTaskHandleImpl + + /*-----------------------------------------------------------------------*/ + +#endif /* if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) */ + +#if INCLUDE_vTaskSuspend == 1 + + /*-----------------------------------------------------------------------*/ + + .extern MPU_vTaskSuspendImpl + /** + * Function: void MPU_vTaskSuspend + * Inputs: TaskHandle_t xTaskToSuspend + */ + .align 4 + .global MPU_vTaskSuspend + .type MPU_vTaskSuspend, function + MPU_vTaskSuspend: + processorInUserMode + SVCEQ #SYSTEM_CALL_vTaskSuspend + B MPU_vTaskSuspendImpl + + /*-----------------------------------------------------------------------*/ + + .extern MPU_vTaskResumeImpl + /** + * Function: void MPU_vTaskResume + * Inputs: TaskHandle_t xTaskToResume + */ + .align 4 + .global MPU_vTaskResume + .type MPU_vTaskResume, function + MPU_vTaskResume: + processorInUserMode + SVCEQ #SYSTEM_CALL_vTaskResume + B MPU_vTaskResumeImpl + + /*-----------------------------------------------------------------------*/ + +#endif /* if ( INCLUDE_vTaskSuspend == 1 ) */ + +#if configGENERATE_RUN_TIME_STATS == 1 + + /*-----------------------------------------------------------------------*/ + + .extern MPU_ulTaskGetRunTimeCounterImpl + /** + * Function: configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetRunTimeCounter + * Inputs: const TaskHandle_t xTask + */ + .align 4 + .global MPU_ulTaskGetRunTimeCounter + .type MPU_ulTaskGetRunTimeCounter, function + MPU_ulTaskGetRunTimeCounter: + processorInUserMode + SVCEQ #SYSTEM_CALL_ulTaskGetRunTimeCounter + B MPU_ulTaskGetRunTimeCounterImpl + + /*-----------------------------------------------------------------------*/ + + .extern MPU_ulTaskGetRunTimePercentImpl + /** + * Function: configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetRunTimePercent + * Inputs: const TaskHandle_t xTask + */ + .align 4 + .global MPU_ulTaskGetRunTimePercent + .type MPU_ulTaskGetRunTimePercent, function + MPU_ulTaskGetRunTimePercent: + processorInUserMode + SVCEQ #SYSTEM_CALL_ulTaskGetRunTimePercent + B MPU_ulTaskGetRunTimePercentImpl + + /*-----------------------------------------------------------------------*/ + + #if INCLUDE_xTaskGetIdleTaskHandle == 1 + + /*-------------------------------------------------------------------*/ + + .extern MPU_ulTaskGetIdleRunTimePercentImpl + /** + * Function: configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetIdleRunTimePercent + * Inputs: void + */ + .align 4 + .global MPU_ulTaskGetIdleRunTimePercent + .type MPU_ulTaskGetIdleRunTimePercent, function + MPU_ulTaskGetIdleRunTimePercent: + processorInUserMode + SVCEQ #SYSTEM_CALL_ulTaskGetIdleRunTimePercent + B MPU_ulTaskGetIdleRunTimePercentImpl + + /*-------------------------------------------------------------------*/ + + .extern MPU_ulTaskGetIdleRunTimeCounterImpl + /** + * Function: configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetIdleRunTimeCounter + * Inputs: void - No Inputs + */ + .align 4 + .global MPU_ulTaskGetIdleRunTimeCounter + .type MPU_ulTaskGetIdleRunTimeCounter, function + MPU_ulTaskGetIdleRunTimeCounter: + processorInUserMode + SVCEQ #SYSTEM_CALL_ulTaskGetIdleRunTimeCounter + B MPU_ulTaskGetIdleRunTimeCounterImpl + + /*-------------------------------------------------------------------*/ + + #endif /* if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) */ +#endif /* configGENERATE_RUN_TIME_STATS */ + +#if configUSE_APPLICATION_TASK_TAG == 1 + + /*-----------------------------------------------------------------------*/ + + .extern MPU_vTaskSetApplicationTaskTagImpl + /** + * Function: void MPU_vTaskSetApplicationTaskTag + * Inputs: TaskHandle_t xTask + * Inputs: TaskHookFunction_tpxHookFunction + */ + .align 4 + .global MPU_vTaskSetApplicationTaskTag + .type MPU_vTaskSetApplicationTaskTag, function + MPU_vTaskSetApplicationTaskTag: + processorInUserMode + SVCEQ #SYSTEM_CALL_vTaskSetApplicationTaskTag + B MPU_vTaskSetApplicationTaskTagImpl + + /*-----------------------------------------------------------------------*/ + + .extern MPU_xTaskGetApplicationTaskTagImpl + /** + * Function: TaskHookFunction_t MPU_xTaskGetApplicationTaskTag + * Inputs: TaskHandle_t xTask + */ + .align 4 + .global MPU_xTaskGetApplicationTaskTag + .type MPU_xTaskGetApplicationTaskTag, function + MPU_xTaskGetApplicationTaskTag: + processorInUserMode + SVCEQ #SYSTEM_CALL_xTaskGetApplicationTaskTag + B MPU_xTaskGetApplicationTaskTagImpl + + /*-----------------------------------------------------------------------*/ +#endif /* if ( configUSE_APPLICATION_TASK_TAG == 1 ) */ + +#if configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 + + /*-----------------------------------------------------------------------*/ + + .extern MPU_vTaskSetThreadLocalStoragePointerImpl + /** + * Function: void MPU_vTaskSetThreadLocalStoragePointer + * Inputs: TaskHandle_t xTaskToSet + * Inputs: TaskHandle_t xIndex + * Inputs: void * pvValue + */ + .align 4 + .global MPU_vTaskSetThreadLocalStoragePointer + .type MPU_vTaskSetThreadLocalStoragePointer, function + MPU_vTaskSetThreadLocalStoragePointer: + processorInUserMode + SVCEQ #SYSTEM_CALL_vTaskSetThreadLocalStoragePointer + B MPU_vTaskSetThreadLocalStoragePointerImpl + + /*-----------------------------------------------------------------------*/ + + .extern MPU_pvTaskGetThreadLocalStoragePointerImpl + /** + * Function: void * MPU_pvTaskGetThreadLocalStoragePointer + * Inputs: TaskHandle_t xTaskToQuery + * Inputs: TaskHandle_t xIndex + */ + .align 4 + .global MPU_pvTaskGetThreadLocalStoragePointer + .type MPU_pvTaskGetThreadLocalStoragePointer, function + MPU_pvTaskGetThreadLocalStoragePointer: + processorInUserMode + SVCEQ #SYSTEM_CALL_pvTaskGetThreadLocalStoragePointer + B MPU_pvTaskGetThreadLocalStoragePointerImpl + + /*-----------------------------------------------------------------------*/ + +#endif /* if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) */ + +#if INCLUDE_uxTaskGetStackHighWaterMark == 1 + + /*-----------------------------------------------------------------------*/ + + .extern MPU_uxTaskGetStackHighWaterMarkImpl + /** + * Function: UBaseType_t MPU_uxTaskGetStackHighWaterMark + * Inputs: TaskHandle_t xTask + */ + .align 4 + .global MPU_uxTaskGetStackHighWaterMark + .type MPU_uxTaskGetStackHighWaterMark, function + MPU_uxTaskGetStackHighWaterMark: + processorInUserMode + SVCEQ #SYSTEM_CALL_uxTaskGetStackHighWaterMark + B MPU_uxTaskGetStackHighWaterMarkImpl + + /*-----------------------------------------------------------------------*/ + +#endif /* if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) */ + + +#if INCLUDE_uxTaskGetStackHighWaterMark == 2 + + /*-----------------------------------------------------------------------*/ + + .extern MPU_uxTaskGetStackHighWaterMark2Impl + /** + * Function: configSTACK_DEPTH_TYPE MPU_uxTaskGetStackHighWaterMark2 + * Inputs: TaskHandle_t xTask + */ + .align 4 + .global MPU_uxTaskGetStackHighWaterMark2 + .type MPU_uxTaskGetStackHighWaterMark2, function + MPU_uxTaskGetStackHighWaterMark2: + processorInUserMode + SVCEQ #SYSTEM_CALL_uxTaskGetStackHighWaterMark2 + B MPU_uxTaskGetStackHighWaterMark2Impl + + /*-----------------------------------------------------------------------*/ + +#endif /* if ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) */ + + +#if INCLUDE_xTaskGetCurrentTaskHandle == 1 || configUSE_MUTEXES == 1 + + /*-----------------------------------------------------------------------*/ + + .extern MPU_xTaskGetCurrentTaskHandleImpl + /** + * Function: TaskHandle_t MPU_xTaskGetCurrentTaskHandle + * Inputs: void - No Inputs + */ + .align 4 + .global MPU_xTaskGetCurrentTaskHandle + .type MPU_xTaskGetCurrentTaskHandle, function + MPU_xTaskGetCurrentTaskHandle: + processorInUserMode + SVCEQ #SYSTEM_CALL_xTaskGetCurrentTaskHandle + B MPU_xTaskGetCurrentTaskHandleImpl + + /*-----------------------------------------------------------------------*/ + +#endif /* if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */ + +#if INCLUDE_xTaskGetSchedulerState == 1 + + /*-----------------------------------------------------------------------*/ + + .extern MPU_xTaskGetSchedulerStateImpl + /** + * Function: TaskHandle_t MPU_xTaskGetSchedulerState + * Inputs: void - No Inputs + */ + .align 4 + .global MPU_xTaskGetSchedulerState + .type MPU_xTaskGetSchedulerState, function + MPU_xTaskGetSchedulerState: + processorInUserMode + SVCEQ #SYSTEM_CALL_xTaskGetSchedulerState + B MPU_xTaskGetSchedulerStateImpl + + /*-----------------------------------------------------------------------*/ + +#endif /* if ( INCLUDE_xTaskGetSchedulerState == 1 ) */ + +#if configUSE_MUTEXES == 1 && INCLUDE_xSemaphoreGetMutexHolder + + /*-----------------------------------------------------------------------*/ + + .extern MPU_xQueueGetMutexHolderImpl + /** + * Function: TaskHandle_t MPU_xQueueGetMutexHolder + * Inputs: QueueHandle_t xSemaphore + */ + .align 4 + .global MPU_xQueueGetMutexHolder + .type MPU_xQueueGetMutexHolder, function + MPU_xQueueGetMutexHolder: + processorInUserMode + SVCEQ #SYSTEM_CALL_xQueueGetMutexHolder + B MPU_xQueueGetMutexHolderImpl + + /*-----------------------------------------------------------------------*/ + +#endif /* if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) */ + +#if configUSE_RECURSIVE_MUTEXES == 1 + + /*-----------------------------------------------------------------------*/ + + .extern MPU_xQueueTakeMutexRecursiveImpl + /** + * Function: TaskHandle_t MPU_xQueueTakeMutexRecursive + * Inputs: QueueHandle_t xMutex + * Inputs: TickType_t xTicksToWait + */ + .align 4 + .global MPU_xQueueTakeMutexRecursive + .type MPU_xQueueTakeMutexRecursive, function + MPU_xQueueTakeMutexRecursive: + processorInUserMode + SVCEQ #SYSTEM_CALL_xQueueTakeMutexRecursive + B MPU_xQueueTakeMutexRecursiveImpl + + /*-----------------------------------------------------------------------*/ + + .extern MPU_xQueueGiveMutexRecursiveImpl + /** + * Function: TaskHandle_t MPU_xQueueGiveMutexRecursive + * Inputs: QueueHandle_t pxMutex + */ + .align 4 + .global MPU_xQueueGiveMutexRecursive + .type MPU_xQueueGiveMutexRecursive, function + MPU_xQueueGiveMutexRecursive: + processorInUserMode + SVCEQ #SYSTEM_CALL_xQueueGiveMutexRecursive + B MPU_xQueueGiveMutexRecursiveImpl + + /*-----------------------------------------------------------------------*/ + +#endif /* if ( configUSE_RECURSIVE_MUTEXES == 1 ) */ + +#if configUSE_QUEUE_SETS == 1 + + /*-----------------------------------------------------------------------*/ + + .extern MPU_xQueueSelectFromSetImpl + /** + * Function: QueueSetMemberHandle_t MPU_xQueueSelectFromSet + * Inputs: QueueSetHandle_t xQueueSet + * Inputs: constTickType_t xTicksToWait + */ + .align 4 + .global MPU_xQueueSelectFromSet + .type MPU_xQueueSelectFromSet, function + MPU_xQueueSelectFromSet: + processorInUserMode + SVCEQ #SYSTEM_CALL_xQueueSelectFromSet + B MPU_xQueueSelectFromSetImpl + + /*-----------------------------------------------------------------------*/ + + .extern MPU_xQueueAddToSetImpl + /** + * Function: TaskHandle_t MPU_xQueueAddToSet + * Inputs: QueueSetMemberHandle_t xQueueOrSemaphore + * Inputs: QueueSetHandle_t xQueueSet + */ + .align 4 + .global MPU_xQueueAddToSet + .type MPU_xQueueAddToSet, function + MPU_xQueueAddToSet: + processorInUserMode + SVCEQ #SYSTEM_CALL_xQueueAddToSet + B MPU_xQueueAddToSetImpl + + /*-----------------------------------------------------------------------*/ + +#endif /* if ( configUSE_QUEUE_SETS == 1 ) */ + +#if configQUEUE_REGISTRY_SIZE == 1 + + /*-----------------------------------------------------------------------*/ + + .extern MPU_vQueueAddToRegistryImpl + /** + * Function: void MPU_vQueueAddToRegistry + * Inputs: QueueHandle_t xQueue + * Inputs: constchar * pcName + */ + .align 4 + .global MPU_vQueueAddToRegistry + .type MPU_vQueueAddToRegistry, function + MPU_vQueueAddToRegistry: + processorInUserMode + SVCEQ #SYSTEM_CALL_vQueueAddToRegistry + B MPU_vQueueAddToRegistryImpl + + /*-----------------------------------------------------------------------*/ + + .extern MPU_vQueueUnregisterQueueImpl + /** + * Function: void MPU_vQueueUnregisterQueue + * Inputs: QueueHandle_t xQueue + */ + .align 4 + .global MPU_vQueueUnregisterQueue + .type MPU_vQueueUnregisterQueue, function + MPU_vQueueUnregisterQueue: + processorInUserMode + SVCEQ #SYSTEM_CALL_vQueueUnregisterQueue + B MPU_vQueueUnregisterQueueImpl + + /*-----------------------------------------------------------------------*/ + + .extern MPU_pcQueueGetNameImpl + /** + * Function: const char * MPU_pcQueueGetName + * Inputs: QueueHandle_t xQueue + */ + .align 4 + .global MPU_pcQueueGetName + .type MPU_pcQueueGetName, function + MPU_pcQueueGetName: + processorInUserMode + SVCEQ #SYSTEM_CALL_pcQueueGetName + B MPU_pcQueueGetNameImpl + + /*-----------------------------------------------------------------------*/ + +#endif /* if ( configQUEUE_REGISTRY_SIZE > 0 ) */ + +#if configUSE_TIMERS == 1 + + /*-----------------------------------------------------------------------*/ + + .extern MPU_pvTimerGetTimerIDImpl + /** + * Function: void * MPU_pvTimerGetTimerID + * Inputs: const TimerHandle_t xTimer + */ + .align 4 + .global MPU_pvTimerGetTimerID + .type MPU_pvTimerGetTimerID, function + MPU_pvTimerGetTimerID: + processorInUserMode + SVCEQ #SYSTEM_CALL_pvTimerGetTimerID + B MPU_pvTimerGetTimerIDImpl + + /*-----------------------------------------------------------------------*/ + + .extern MPU_vTimerSetTimerIDImpl + /** + * Function: void MPU_vTimerSetTimerID + * Inputs: TimerHandle_t xTimer + * Inputs: void * pvNewID + */ + .align 4 + .global MPU_vTimerSetTimerID + .type MPU_vTimerSetTimerID, function + MPU_vTimerSetTimerID: + processorInUserMode + SVCEQ #SYSTEM_CALL_vTimerSetTimerID + B MPU_vTimerSetTimerIDImpl + + /*-----------------------------------------------------------------------*/ + + .extern MPU_xTimerIsTimerActiveImpl + /** + * Function: TaskHandle_t MPU_xTimerIsTimerActive + * Inputs: TimerHandle_t xTimer + */ + .align 4 + .global MPU_xTimerIsTimerActive + .type MPU_xTimerIsTimerActive, function + MPU_xTimerIsTimerActive: + processorInUserMode + SVCEQ #SYSTEM_CALL_xTimerIsTimerActive + B MPU_xTimerIsTimerActiveImpl + + /*-----------------------------------------------------------------------*/ + + .extern MPU_xTimerGetTimerDaemonTaskHandleImpl + /** + * Function: TaskHandle_t MPU_xTimerGetTimerDaemonTaskHandle + * Inputs: void - No Inputs + */ + .align 4 + .global MPU_xTimerGetTimerDaemonTaskHandle + .type MPU_xTimerGetTimerDaemonTaskHandle, function + MPU_xTimerGetTimerDaemonTaskHandle: + processorInUserMode + SVCEQ #SYSTEM_CALL_xTimerGetTimerDaemonTaskHandle + B MPU_xTimerGetTimerDaemonTaskHandleImpl + + /*-----------------------------------------------------------------------*/ + + .extern MPU_xTimerGenericCommandFromTaskImpl + /** + * Function: TaskHandle_t MPU_xTimerGenericCommandFromTaskEntry + * Inputs: const xTimerGenericCommandParams_t * pxParams + */ + .align 4 + .global MPU_xTimerGenericCommandFromTaskEntry + .type MPU_xTimerGenericCommandFromTaskEntry, function + MPU_xTimerGenericCommandFromTaskEntry: + processorInUserMode + SVCEQ #SYSTEM_CALL_xTimerGenericCommandFromTask + B MPU_xTimerGenericCommandFromTaskImpl + + /*-----------------------------------------------------------------------*/ + + + .extern MPU_pcTimerGetNameImpl + /** + * Function: const char * MPU_pcTimerGetName + * Inputs: TimerHandle_t xTimer + */ + .align 4 + .global MPU_pcTimerGetName + .type MPU_pcTimerGetName, function + MPU_pcTimerGetName: + processorInUserMode + SVCEQ #SYSTEM_CALL_pcTimerGetName + B MPU_pcTimerGetNameImpl + + /*-----------------------------------------------------------------------*/ + + .extern MPU_vTimerSetReloadModeImpl + /** + * Function: void MPU_vTimerSetReloadMode + * Inputs: TimerHandle_t xTimer + * Inputs: constBaseType_t uxAutoReload + */ + .align 4 + .global MPU_vTimerSetReloadMode + .type MPU_vTimerSetReloadMode, function + MPU_vTimerSetReloadMode: + processorInUserMode + SVCEQ #SYSTEM_CALL_vTimerSetReloadMode + B MPU_vTimerSetReloadModeImpl + + /*-----------------------------------------------------------------------*/ + + .extern MPU_xTimerGetReloadModeImpl + /** + * Function: TaskHandle_t MPU_xTimerGetReloadMode + * Inputs: TimerHandle_t xTimer + */ + .align 4 + .global MPU_xTimerGetReloadMode + .type MPU_xTimerGetReloadMode, function + MPU_xTimerGetReloadMode: + processorInUserMode + SVCEQ #SYSTEM_CALL_xTimerGetReloadMode + B MPU_xTimerGetReloadModeImpl + + /*-----------------------------------------------------------------------*/ + + .extern MPU_uxTimerGetReloadModeImpl + /** + * Function: UBaseType_t MPU_uxTimerGetReloadMode + * Inputs: TimerHandle_t xTimer + */ + .align 4 + .global MPU_uxTimerGetReloadMode + .type MPU_uxTimerGetReloadMode, function + MPU_uxTimerGetReloadMode: + processorInUserMode + SVCEQ #SYSTEM_CALL_uxTimerGetReloadMode + B MPU_uxTimerGetReloadModeImpl + + /*-----------------------------------------------------------------------*/ + + .extern MPU_xTimerGetPeriodImpl + /** + * Function: TickType_t MPU_xTimerGetPeriod + * Inputs: TimerHandle_t xTimer + */ + .align 4 + .global MPU_xTimerGetPeriod + .type MPU_xTimerGetPeriod, function + MPU_xTimerGetPeriod: + processorInUserMode + SVCEQ #SYSTEM_CALL_xTimerGetPeriod + B MPU_xTimerGetPeriodImpl + + /*-----------------------------------------------------------------------*/ + + .extern MPU_xTimerGetExpiryTimeImpl + /** + * Function: TickType_t MPU_xTimerGetExpiryTime + * Inputs: TimerHandle_t xTimer + */ + .align 4 + .global MPU_xTimerGetExpiryTime + .type MPU_xTimerGetExpiryTime, function + MPU_xTimerGetExpiryTime: + processorInUserMode + SVCEQ #SYSTEM_CALL_xTimerGetExpiryTime + B MPU_xTimerGetExpiryTimeImpl + + /*-----------------------------------------------------------------------*/ + +#endif /* if ( configUSE_TIMERS == 1 ) */ + +#if configUSE_TASK_NOTIFICATIONS == 1 + .extern MPU_xTaskGenericNotifyImpl + /** + * Function: TaskHandle_t MPU_xTaskGenericNotifyEntry + * Inputs: const xTaskGenericNotifyParams_t * pxParams + */ + .align 4 + .global MPU_xTaskGenericNotifyEntry + .type MPU_xTaskGenericNotifyEntry, function + MPU_xTaskGenericNotifyEntry: + processorInUserMode + SVCEQ #SYSTEM_CALL_xTaskGenericNotify + B MPU_xTaskGenericNotifyImpl + + /*-----------------------------------------------------------------------*/ + + .extern MPU_xTaskGenericNotifyWaitImpl + /** + * Function: TaskHandle_t MPU_xTaskGenericNotifyWaitEntry + * Inputs: const xTaskGenericNotifyWaitParams_t * pxParams + */ + .align 4 + .global MPU_xTaskGenericNotifyWaitEntry + .type MPU_xTaskGenericNotifyWaitEntry, function + MPU_xTaskGenericNotifyWaitEntry: + processorInUserMode + SVCEQ #SYSTEM_CALL_xTaskGenericNotifyWait + B MPU_xTaskGenericNotifyWaitImpl + + /*-----------------------------------------------------------------------*/ + + .extern MPU_ulTaskGenericNotifyTakeImpl + /** + * Function: uint32_t MPU_ulTaskGenericNotifyTake + * Inputs: UBaseType_t uxIndexToWaitOn + * Inputs: TaskHandle_t xClearCountOnExit + * Inputs: TickType_t xTicksToWait + */ + .align 4 + .global MPU_ulTaskGenericNotifyTake + .type MPU_ulTaskGenericNotifyTake, function + MPU_ulTaskGenericNotifyTake: + processorInUserMode + SVCEQ #SYSTEM_CALL_ulTaskGenericNotifyTake + B MPU_ulTaskGenericNotifyTakeImpl + + /*-----------------------------------------------------------------------*/ + + .extern MPU_xTaskGenericNotifyStateClearImpl + /** + * Function: TaskHandle_t MPU_xTaskGenericNotifyStateClear + * Inputs: TaskHandle_t xTask + * Inputs: UBaseType_t uxIndexToClear + */ + .align 4 + .global MPU_xTaskGenericNotifyStateClear + .type MPU_xTaskGenericNotifyStateClear, function + MPU_xTaskGenericNotifyStateClear: + processorInUserMode + SVCEQ #SYSTEM_CALL_xTaskGenericNotifyStateClear + B MPU_xTaskGenericNotifyStateClearImpl + + /*-----------------------------------------------------------------------*/ + + .extern MPU_ulTaskGenericNotifyValueClearImpl + /** + * Function: uint32_t MPU_ulTaskGenericNotifyValueClear + * Inputs: TaskHandle_t xTask + * Inputs: UBaseType_t uxIndexToClear + * Inputs: uint32_t ulBitsToClear + */ + .align 4 + .global MPU_ulTaskGenericNotifyValueClear + .type MPU_ulTaskGenericNotifyValueClear, function + MPU_ulTaskGenericNotifyValueClear: + processorInUserMode + SVCEQ #SYSTEM_CALL_ulTaskGenericNotifyValueClear + B MPU_ulTaskGenericNotifyValueClearImpl + + /*-----------------------------------------------------------------------*/ + +#endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */ diff --git a/portable/GCC/ARM_CRx_MPU/mpu_wrappers_v2_asm.h b/portable/GCC/ARM_CRx_MPU/mpu_wrappers_v2_asm.h new file mode 100644 index 000000000..faf6c9b86 --- /dev/null +++ b/portable/GCC/ARM_CRx_MPU/mpu_wrappers_v2_asm.h @@ -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 + +/** 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 */ diff --git a/portable/GCC/ARM_CRx_MPU/port.c b/portable/GCC/ARM_CRx_MPU/port.c new file mode 100644 index 000000000..7427aa7c5 --- /dev/null +++ b/portable/GCC/ARM_CRx_MPU/port.c @@ -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 + +/* 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 ); +} + +/*---------------------------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CRx_MPU/portASM.S b/portable/GCC/ARM_CRx_MPU/portASM.S new file mode 100644 index 000000000..7ea5ad42c --- /dev/null +++ b/portable/GCC/ARM_CRx_MPU/portASM.S @@ -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 diff --git a/portable/GCC/ARM_CRx_MPU/portmacro.h b/portable/GCC/ARM_CRx_MPU/portmacro.h new file mode 100644 index 000000000..cf46ac0c6 --- /dev/null +++ b/portable/GCC/ARM_CRx_MPU/portmacro.h @@ -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 + +/* ------------------------- 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 */ diff --git a/portable/GCC/ARM_CRx_MPU/portmacro_asm.h b/portable/GCC/ARM_CRx_MPU/portmacro_asm.h new file mode 100644 index 000000000..c2d0c02ef --- /dev/null +++ b/portable/GCC/ARM_CRx_MPU/portmacro_asm.h @@ -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 */