Add ARMv7-R MPU Port (#938)
* Apply git review patch created by @aggargr
* Add necessary changes to the CMakeLists.txt file to build the port
diff --git a/.github/.cSpellWords.txt b/.github/.cSpellWords.txt
index ba8abfd..c41a050 100644
--- a/.github/.cSpellWords.txt
+++ b/.github/.cSpellWords.txt
@@ -549,6 +549,10 @@
NVIC
ODAT
ODSR
+OINC
+OIWBNOWA
+OIWBWA
+OIWTNOWA
OPMOD
optimisations
OPTIMISED
@@ -795,6 +799,15 @@
SWTRG
synchronise
SYSC
+sysclk
+Sysclk
+SysClk
+SYSClk
+SYSCLK
+sysclock
+Sysclock
+SysClock
+SYSCLOCK
TACCR
TACCTL
TACLR
@@ -877,6 +890,9 @@
unpadded
Unpadded
UNPADDED
+unprotect
+Unprotect
+Unprotected
UNRE
UNSUB
UNSUBACK
diff --git a/.github/scripts/kernel_checker.py b/.github/scripts/kernel_checker.py
index 130841a..b57b7f5 100755
--- a/.github/scripts/kernel_checker.py
+++ b/.github/scripts/kernel_checker.py
@@ -37,7 +37,8 @@
'FreeRTOS-openocd.c',
'Makefile',
'.DS_Store',
- 'cspell.config.yaml'
+ 'cspell.config.yaml',
+ '.clang-format'
]
KERNEL_IGNORED_EXTENSIONS = [
diff --git a/.github/workflows/formatting.yml b/.github/workflows/formatting.yml
index 14d41c9..2f36910 100644
--- a/.github/workflows/formatting.yml
+++ b/.github/workflows/formatting.yml
@@ -19,7 +19,7 @@
runs-on: ubuntu-20.04
steps:
- name: Apply Formatting Fix
- id: check-formatting
+ id: check-formatting
uses: FreeRTOS/CI-CD-Github-Actions/formatting-bot@main
with:
exclude-dirs: portable
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 07eeec4..6fd1ff5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -85,6 +85,7 @@
" GCC_ARM_CM85_NTZ_NONSECURE - Compiler: GCC Target: ARM Cortex-M85 non-trustzone non-secure\n"
" GCC_ARM_CM85_TFM - Compiler: GCC Target: ARM Cortex-M85 non-secure for TF-M\n"
" GCC_ARM_CR5 - Compiler: GCC Target: ARM Cortex-R5\n"
+ " GCC_ARM_CRX_MPU - Compiler: GCC Target: ARM Cortex-Rx with MPU\n"
" GCC_ARM_CRX_NOGIC - Compiler: GCC Target: ARM Cortex-Rx no GIC\n"
" GCC_ARM7_AT91FR40008 - Compiler: GCC Target: ARM7 Atmel AT91R40008\n"
" GCC_ARM7_AT91SAM7S - Compiler: GCC Target: ARM7 Atmel AT91SAM7S\n"
diff --git a/portable/CMakeLists.txt b/portable/CMakeLists.txt
index c067e97..af9321e 100644
--- a/portable/CMakeLists.txt
+++ b/portable/CMakeLists.txt
@@ -207,6 +207,11 @@
GCC/ARM_CR5/port.c
GCC/ARM_CR5/portASM.S>
+ $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CRX_MPU>:
+ GCC/ARM_CRx_MPU/port.c
+ GCC/ARM_CRx_MPU/portASM.S
+ GCC/ARM_CRx_MPU/mpu_wrappers_v2_asm.S>
+
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CRX_NOGIC>:
GCC/ARM_CRx_No_GIC/port.c
GCC/ARM_CRx_No_GIC/portASM.S>
@@ -836,6 +841,7 @@
# ARMv7-R ports for GCC
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CR5>:${CMAKE_CURRENT_LIST_DIR}/GCC/ARM_CR5>
+ $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CRX_MPU>:${CMAKE_CURRENT_LIST_DIR}/GCC/ARM_CRx_MPU>
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CRX_NOGIC>:${CMAKE_CURRENT_LIST_DIR}/GCC/ARM_CRx_No_GIC>
# ARMv4T ARM7TDMI ports for GCC
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 0000000..8d0f769
--- /dev/null
+++ b/portable/GCC/ARM_CRx_MPU/mpu_wrappers_v2_asm.S
@@ -0,0 +1,854 @@
+/*
+ * FreeRTOS Kernel <DEVELOPMENT BRANCH>
+ * Copyright (C) 2024 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
+ .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 ----------------------- */
+
+/*
+ * void vPortYield( void );
+ */
+.align 4
+.global vPortYield
+.type vPortYield, %function
+vPortYield:
+ SVC #portSVC_YIELD
+ BX LR
+
+/* ----------------------------------------------------------------------------------- */
+
+/*
+ * void vPortSystemCallExit( void );
+ */
+.align 4
+.global vPortSystemCallExit
+.type vPortSystemCallExit, %function
+vPortSystemCallExit:
+ SVC #portSVC_SYSTEM_CALL_EXIT
+ BX LR
+
+/* ----------------------------------------------------------------------------------- */
+
+/*
+ * BaseType_t xPortIsPrivileged( void );
+ *
+ * According to the Procedure Call Standard for the ARM Architecture (AAPCS):
+ * - Return value must be in R0.
+ */
+.align 4
+.global xPortIsPrivileged
+.type xPortIsPrivileged, %function
+xPortIsPrivileged:
+ MRS R0, CPSR /* R0 = CPSR. */
+ AND R0, R0, #0x1F /* R0 = R0 & 0x1F. Extract mode bits.*/
+ CMP R0, #USER_MODE /* If R0 == #USER_MODE. */
+ MOVEQ R0, #0x0 /* Then, set R0 to 0 to indicate that the processer is not privileged. */
+ MOVNE R0, #0x01 /* Otherwise, set R0 to 1 to indicate that the processer is privileged. */
+ BX LR
+
+/* ----------------------------------------------------------------------------------- */
+
+/*
+ * UBaseType_t ulPortCountLeadingZeros( UBaseType_t ulBitmap );
+ *
+ * According to the Procedure Call Standard for the ARM Architecture (AAPCS):
+ * - Parameter ulBitmap is passed in R0.
+ * - Return value must be in R0.
+ */
+.align 4
+.weak ulPortCountLeadingZeros
+.type ulPortCountLeadingZeros, %function
+ulPortCountLeadingZeros:
+ CLZ R0, R0
+ BX LR
+
+/* ------------------- End of Port Specific System Calls ------------------- */
+
+.macro INVOKE_SYSTEM_CALL systemCallNumber, systemCallImpl
+ PUSH {R0}
+ MRS R0, CPSR
+ AND R0, R0, #0x1F
+ CMP R0, #USER_MODE
+ POP {R0}
+ SVCEQ \systemCallNumber
+ B \systemCallImpl
+.endm
+
+/* ----------------------------------------------------------------------------------- */
+
+.extern MPU_xTaskGetTickCountImpl
+.align 4
+.global MPU_xTaskGetTickCount
+.type MPU_xTaskGetTickCount, function
+MPU_xTaskGetTickCount:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTaskGetTickCount, MPU_xTaskGetTickCountImpl
+
+/* ----------------------------------------------------------------------------------- */
+
+.extern MPU_uxTaskGetNumberOfTasksImpl
+.align 4
+.global MPU_uxTaskGetNumberOfTasks
+.type MPU_uxTaskGetNumberOfTasks, function
+MPU_uxTaskGetNumberOfTasks:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_uxTaskGetNumberOfTasks, MPU_uxTaskGetNumberOfTasksImpl
+
+/* ----------------------------------------------------------------------------------- */
+
+.extern MPU_vTaskSetTimeOutStateImpl
+.align 4
+.global MPU_vTaskSetTimeOutState
+.type MPU_vTaskSetTimeOutState, function
+MPU_vTaskSetTimeOutState:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_vTaskSetTimeOutState, MPU_vTaskSetTimeOutStateImpl
+
+/* ----------------------------------------------------------------------------------- */
+
+.extern MPU_xTaskCheckForTimeOutImpl
+.align 4
+.global MPU_xTaskCheckForTimeOut
+.type MPU_xTaskCheckForTimeOut, function
+MPU_xTaskCheckForTimeOut:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTaskCheckForTimeOut, MPU_xTaskCheckForTimeOutImpl
+
+/* ----------------------------------------------------------------------------------- */
+
+.extern MPU_xQueueGenericSendImpl
+.align 4
+.global MPU_xQueueGenericSend
+.type MPU_xQueueGenericSend, function
+MPU_xQueueGenericSend:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xQueueGenericSend, MPU_xQueueGenericSendImpl
+
+/* ----------------------------------------------------------------------------------- */
+
+.extern MPU_uxQueueMessagesWaitingImpl
+.align 4
+.global MPU_uxQueueMessagesWaiting
+.type MPU_uxQueueMessagesWaiting, function
+MPU_uxQueueMessagesWaiting:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_uxQueueMessagesWaiting, MPU_uxQueueMessagesWaitingImpl
+
+/* ----------------------------------------------------------------------------------- */
+
+.extern MPU_uxQueueSpacesAvailableImpl
+.align 4
+.global MPU_uxQueueSpacesAvailable
+.type MPU_uxQueueSpacesAvailable, function
+MPU_uxQueueSpacesAvailable:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_uxQueueSpacesAvailable, MPU_uxQueueSpacesAvailableImpl
+
+/* ----------------------------------------------------------------------------------- */
+
+.extern MPU_xQueueReceiveImpl
+.align 4
+.global MPU_xQueueReceive
+.type MPU_xQueueReceive, function
+MPU_xQueueReceive:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xQueueReceive, MPU_xQueueReceiveImpl
+
+/* ----------------------------------------------------------------------------------- */
+
+.extern MPU_xQueuePeekImpl
+.align 4
+.global MPU_xQueuePeek
+.type MPU_xQueuePeek, function
+MPU_xQueuePeek:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xQueuePeek, MPU_xQueuePeekImpl
+
+/* ----------------------------------------------------------------------------------- */
+
+.extern MPU_xQueueSemaphoreTakeImpl
+.align 4
+.global MPU_xQueueSemaphoreTake
+.type MPU_xQueueSemaphoreTake, function
+MPU_xQueueSemaphoreTake:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xQueueSemaphoreTake, MPU_xQueueSemaphoreTakeImpl
+
+/* ----------------------------------------------------------------------------------- */
+
+.extern MPU_xEventGroupWaitBitsImpl
+.align 4
+.global MPU_xEventGroupWaitBitsEntry
+.type MPU_xEventGroupWaitBitsEntry, function
+MPU_xEventGroupWaitBitsEntry:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xEventGroupWaitBits, MPU_xEventGroupWaitBitsImpl
+
+/* ----------------------------------------------------------------------------------- */
+
+.extern MPU_xEventGroupClearBitsImpl
+.align 4
+.global MPU_xEventGroupClearBits
+.type MPU_xEventGroupClearBits, function
+MPU_xEventGroupClearBits:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xEventGroupClearBits, MPU_xEventGroupClearBitsImpl
+
+/* ----------------------------------------------------------------------------------- */
+
+.extern MPU_xEventGroupSetBitsImpl
+.align 4
+.global MPU_xEventGroupSetBits
+.type MPU_xEventGroupSetBits, function
+MPU_xEventGroupSetBits:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xEventGroupSetBits, MPU_xEventGroupSetBitsImpl
+
+/* ----------------------------------------------------------------------------------- */
+
+.extern MPU_xEventGroupSyncImpl
+.align 4
+.global MPU_xEventGroupSync
+.type MPU_xEventGroupSync, function
+MPU_xEventGroupSync:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xEventGroupSync, MPU_xEventGroupSyncImpl
+
+/* ----------------------------------------------------------------------------------- */
+
+.extern MPU_xStreamBufferSendImpl
+.align 4
+.global MPU_xStreamBufferSend
+.type MPU_xStreamBufferSend, function
+MPU_xStreamBufferSend:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xStreamBufferSend, MPU_xStreamBufferSendImpl
+
+/* ----------------------------------------------------------------------------------- */
+
+.extern MPU_xStreamBufferReceiveImpl
+.align 4
+.global MPU_xStreamBufferReceive
+.type MPU_xStreamBufferReceive, function
+MPU_xStreamBufferReceive:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xStreamBufferReceive, MPU_xStreamBufferReceiveImpl
+
+/* ----------------------------------------------------------------------------------- */
+
+.extern MPU_xStreamBufferIsFullImpl
+.align 4
+.global MPU_xStreamBufferIsFull
+.type MPU_xStreamBufferIsFull, function
+MPU_xStreamBufferIsFull:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xStreamBufferIsFull, MPU_xStreamBufferIsFullImpl
+
+/* ----------------------------------------------------------------------------------- */
+
+.extern MPU_xStreamBufferIsEmptyImpl
+.align 4
+.global MPU_xStreamBufferIsEmpty
+.type MPU_xStreamBufferIsEmpty, function
+MPU_xStreamBufferIsEmpty:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xStreamBufferIsEmpty, MPU_xStreamBufferIsEmptyImpl
+
+/* ----------------------------------------------------------------------------------- */
+
+.extern MPU_xStreamBufferSpacesAvailableImpl
+.align 4
+.global MPU_xStreamBufferSpacesAvailable
+.type MPU_xStreamBufferSpacesAvailable, function
+MPU_xStreamBufferSpacesAvailable:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xStreamBufferSpacesAvailable, MPU_xStreamBufferSpacesAvailableImpl
+
+/* ----------------------------------------------------------------------------------- */
+
+.extern MPU_xStreamBufferBytesAvailableImpl
+.align 4
+.global MPU_xStreamBufferBytesAvailable
+.type MPU_xStreamBufferBytesAvailable, function
+MPU_xStreamBufferBytesAvailable:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xStreamBufferBytesAvailable, MPU_xStreamBufferBytesAvailableImpl
+
+/* ----------------------------------------------------------------------------------- */
+
+.extern MPU_xStreamBufferSetTriggerLevelImpl
+.align 4
+.global MPU_xStreamBufferSetTriggerLevel
+.type MPU_xStreamBufferSetTriggerLevel, function
+MPU_xStreamBufferSetTriggerLevel:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xStreamBufferSetTriggerLevel, MPU_xStreamBufferSetTriggerLevelImpl
+
+/* ----------------------------------------------------------------------------------- */
+
+.extern MPU_xStreamBufferNextMessageLengthBytesImpl
+.align 4
+.global MPU_xStreamBufferNextMessageLengthBytes
+.type MPU_xStreamBufferNextMessageLengthBytes, function
+MPU_xStreamBufferNextMessageLengthBytes:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xStreamBufferNextMessageLengthBytes, MPU_xStreamBufferNextMessageLengthBytesImpl
+
+/* ----------------------------------------------------------------------------------- */
+
+#if ( ( INCLUDE_xTaskDelayUntil == 1 ) || ( INCLUDE_vTaskDelayUntil == 1 ) )
+
+ .extern MPU_xTaskDelayUntilImpl
+ .align 4
+ .global MPU_xTaskDelayUntil
+ .type MPU_xTaskDelayUntil, function
+ MPU_xTaskDelayUntil:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTaskDelayUntil, MPU_xTaskDelayUntilImpl
+
+#endif /* if ( ( INCLUDE_xTaskDelayUntil == 1 ) || ( INCLUDE_vTaskDelayUntil == 1 ) ) */
+
+/* ----------------------------------------------------------------------------------- */
+
+#if ( INCLUDE_xTaskAbortDelay == 1 )
+
+ .extern MPU_xTaskAbortDelayImpl
+ .align 4
+ .global MPU_xTaskAbortDelay
+ .type MPU_xTaskAbortDelay, function
+ MPU_xTaskAbortDelay:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTaskAbortDelay, MPU_xTaskAbortDelayImpl
+
+#endif /* if ( INCLUDE_xTaskAbortDelay == 1 ) */
+
+/* ------------------------------------------------------------------------------- */
+
+#if ( INCLUDE_vTaskDelay == 1 )
+
+ .extern MPU_vTaskDelayImpl
+ .align 4
+ .global MPU_vTaskDelay
+ .type MPU_vTaskDelay, function
+ MPU_vTaskDelay:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_vTaskDelay, MPU_vTaskDelayImpl
+
+#endif /* if ( INCLUDE_vTaskDelay == 1 ) */
+
+/* ------------------------------------------------------------------------------- */
+
+#if ( INCLUDE_uxTaskPriorityGet == 1 )
+
+ .extern MPU_uxTaskPriorityGetImpl
+ .align 4
+ .global MPU_uxTaskPriorityGet
+ .type MPU_uxTaskPriorityGet, function
+ MPU_uxTaskPriorityGet:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_uxTaskPriorityGet, MPU_uxTaskPriorityGetImpl
+
+#endif /* if ( INCLUDE_uxTaskPriorityGet == 1 ) */
+
+/* ------------------------------------------------------------------------------- */
+
+#if ( INCLUDE_eTaskGetState == 1 )
+
+ .extern MPU_eTaskGetStateImpl
+ .align 4
+ .global MPU_eTaskGetState
+ .type MPU_eTaskGetState, function
+ MPU_eTaskGetState:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_eTaskGetState, MPU_eTaskGetStateImpl
+
+#endif /* if ( INCLUDE_eTaskGetState == 1 ) */
+
+/* ------------------------------------------------------------------------------- */
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+ .extern MPU_vTaskGetInfoImpl
+ .align 4
+ .global MPU_vTaskGetInfo
+ .type MPU_vTaskGetInfo, function
+ MPU_vTaskGetInfo:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_vTaskGetInfo, MPU_vTaskGetInfoImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+ .extern MPU_uxTaskGetSystemStateImpl
+ .align 4
+ .global MPU_uxTaskGetSystemState
+ .type MPU_uxTaskGetSystemState, function
+ MPU_uxTaskGetSystemState:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_uxTaskGetSystemState, MPU_uxTaskGetSystemStateImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+ .extern MPU_uxEventGroupGetNumberImpl
+ .align 4
+ .global MPU_uxEventGroupGetNumber
+ .type MPU_uxEventGroupGetNumber, function
+ MPU_uxEventGroupGetNumber:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_uxEventGroupGetNumber, MPU_uxEventGroupGetNumberImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+ .extern MPU_vEventGroupSetNumberImpl
+ .align 4
+ .global MPU_vEventGroupSetNumber
+ .type MPU_vEventGroupSetNumber, function
+ MPU_vEventGroupSetNumber:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_vEventGroupSetNumber, MPU_vEventGroupSetNumberImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+#endif /* if ( configUSE_TRACE_FACILITY == 1 ) */
+
+/* ------------------------------------------------------------------------------- */
+
+#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
+
+ .extern MPU_xTaskGetIdleTaskHandleImpl
+ .align 4
+ .global MPU_xTaskGetIdleTaskHandle
+ .type MPU_xTaskGetIdleTaskHandle, function
+ MPU_xTaskGetIdleTaskHandle:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTaskGetIdleTaskHandle, MPU_xTaskGetIdleTaskHandleImpl
+
+
+#endif /* if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) */
+
+/* ------------------------------------------------------------------------------- */
+
+#if ( INCLUDE_vTaskSuspend == 1 )
+
+ .extern MPU_vTaskSuspendImpl
+ .align 4
+ .global MPU_vTaskSuspend
+ .type MPU_vTaskSuspend, function
+ MPU_vTaskSuspend:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_vTaskSuspend, MPU_vTaskSuspendImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+ .extern MPU_vTaskResumeImpl
+ .align 4
+ .global MPU_vTaskResume
+ .type MPU_vTaskResume, function
+ MPU_vTaskResume:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_vTaskResume, MPU_vTaskResumeImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+#endif /* if ( INCLUDE_vTaskSuspend == 1 ) */
+
+/* ------------------------------------------------------------------------------- */
+
+#if ( configGENERATE_RUN_TIME_STATS == 1 )
+
+ .extern MPU_ulTaskGetRunTimeCounterImpl
+ .align 4
+ .global MPU_ulTaskGetRunTimeCounter
+ .type MPU_ulTaskGetRunTimeCounter, function
+ MPU_ulTaskGetRunTimeCounter:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_ulTaskGetRunTimeCounter, MPU_ulTaskGetRunTimeCounterImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+ .extern MPU_ulTaskGetRunTimePercentImpl
+ .align 4
+ .global MPU_ulTaskGetRunTimePercent
+ .type MPU_ulTaskGetRunTimePercent, function
+ MPU_ulTaskGetRunTimePercent:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_ulTaskGetRunTimePercent, MPU_ulTaskGetRunTimePercentImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+ #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
+
+ .extern MPU_ulTaskGetIdleRunTimePercentImpl
+ .align 4
+ .global MPU_ulTaskGetIdleRunTimePercent
+ .type MPU_ulTaskGetIdleRunTimePercent, function
+ MPU_ulTaskGetIdleRunTimePercent:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_ulTaskGetIdleRunTimePercent, MPU_ulTaskGetIdleRunTimePercentImpl
+
+ /* --------------------------------------------------------------------------- */
+
+ .extern MPU_ulTaskGetIdleRunTimeCounterImpl
+ .align 4
+ .global MPU_ulTaskGetIdleRunTimeCounter
+ .type MPU_ulTaskGetIdleRunTimeCounter, function
+ MPU_ulTaskGetIdleRunTimeCounter:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_ulTaskGetIdleRunTimeCounter, MPU_ulTaskGetIdleRunTimeCounterImpl
+
+ /* --------------------------------------------------------------------------- */
+
+ #endif /* if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) */
+
+#endif /* if ( configGENERATE_RUN_TIME_STATS == 1 )*/
+
+/* --------------------------------------------------------------------------- */
+
+#if ( configUSE_APPLICATION_TASK_TAG == 1 )
+
+ .extern MPU_vTaskSetApplicationTaskTagImpl
+ .align 4
+ .global MPU_vTaskSetApplicationTaskTag
+ .type MPU_vTaskSetApplicationTaskTag, function
+ MPU_vTaskSetApplicationTaskTag:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_vTaskSetApplicationTaskTag, MPU_vTaskSetApplicationTaskTagImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+ .extern MPU_xTaskGetApplicationTaskTagImpl
+ .align 4
+ .global MPU_xTaskGetApplicationTaskTag
+ .type MPU_xTaskGetApplicationTaskTag, function
+ MPU_xTaskGetApplicationTaskTag:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTaskGetApplicationTaskTag, MPU_xTaskGetApplicationTaskTagImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+#endif /* if ( configUSE_APPLICATION_TASK_TAG == 1 ) */
+
+/* ------------------------------------------------------------------------------- */
+
+#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
+
+ .extern MPU_vTaskSetThreadLocalStoragePointerImpl
+ .align 4
+ .global MPU_vTaskSetThreadLocalStoragePointer
+ .type MPU_vTaskSetThreadLocalStoragePointer, function
+ MPU_vTaskSetThreadLocalStoragePointer:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_vTaskSetThreadLocalStoragePointer, MPU_vTaskSetThreadLocalStoragePointerImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+ .extern MPU_pvTaskGetThreadLocalStoragePointerImpl
+ .align 4
+ .global MPU_pvTaskGetThreadLocalStoragePointer
+ .type MPU_pvTaskGetThreadLocalStoragePointer, function
+ MPU_pvTaskGetThreadLocalStoragePointer:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_pvTaskGetThreadLocalStoragePointer, MPU_pvTaskGetThreadLocalStoragePointerImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+#endif /* if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) */
+
+/* ------------------------------------------------------------------------------- */
+
+#if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
+
+ .extern MPU_uxTaskGetStackHighWaterMarkImpl
+ .align 4
+ .global MPU_uxTaskGetStackHighWaterMark
+ .type MPU_uxTaskGetStackHighWaterMark, function
+ MPU_uxTaskGetStackHighWaterMark:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_uxTaskGetStackHighWaterMark, MPU_uxTaskGetStackHighWaterMarkImpl
+
+#endif /* if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) */
+
+/* ------------------------------------------------------------------------------- */
+
+#if ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 )
+
+ .extern MPU_uxTaskGetStackHighWaterMark2Impl
+ .align 4
+ .global MPU_uxTaskGetStackHighWaterMark2
+ .type MPU_uxTaskGetStackHighWaterMark2, function
+ MPU_uxTaskGetStackHighWaterMark2:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_uxTaskGetStackHighWaterMark2, MPU_uxTaskGetStackHighWaterMark2Impl
+
+#endif /* if ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) */
+
+/* ------------------------------------------------------------------------------- */
+
+#if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
+
+ .extern MPU_xTaskGetCurrentTaskHandleImpl
+ .align 4
+ .global MPU_xTaskGetCurrentTaskHandle
+ .type MPU_xTaskGetCurrentTaskHandle, function
+ MPU_xTaskGetCurrentTaskHandle:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTaskGetCurrentTaskHandle, MPU_xTaskGetCurrentTaskHandleImpl
+
+#endif /* if( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
+
+/* ------------------------------------------------------------------------------- */
+
+#if ( INCLUDE_xTaskGetSchedulerState == 1 )
+
+ .extern MPU_xTaskGetSchedulerStateImpl
+ .align 4
+ .global MPU_xTaskGetSchedulerState
+ .type MPU_xTaskGetSchedulerState, function
+ MPU_xTaskGetSchedulerState:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTaskGetSchedulerState, MPU_xTaskGetSchedulerStateImpl
+
+
+#endif /* if ( INCLUDE_xTaskGetSchedulerState == 1 ) */
+
+/* ------------------------------------------------------------------------------- */
+
+#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) )
+
+ .extern MPU_xQueueGetMutexHolderImpl
+ .align 4
+ .global MPU_xQueueGetMutexHolder
+ .type MPU_xQueueGetMutexHolder, function
+ MPU_xQueueGetMutexHolder:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xQueueGetMutexHolder, MPU_xQueueGetMutexHolderImpl
+
+#endif /* if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) */
+
+/* ------------------------------------------------------------------------------- */
+
+#if ( configUSE_RECURSIVE_MUTEXES == 1 )
+
+ .extern MPU_xQueueTakeMutexRecursiveImpl
+ .align 4
+ .global MPU_xQueueTakeMutexRecursive
+ .type MPU_xQueueTakeMutexRecursive, function
+ MPU_xQueueTakeMutexRecursive:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xQueueTakeMutexRecursive, MPU_xQueueTakeMutexRecursiveImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+ .extern MPU_xQueueGiveMutexRecursiveImpl
+ .align 4
+ .global MPU_xQueueGiveMutexRecursive
+ .type MPU_xQueueGiveMutexRecursive, function
+ MPU_xQueueGiveMutexRecursive:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xQueueGiveMutexRecursive, MPU_xQueueGiveMutexRecursiveImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+#endif /* if ( configUSE_RECURSIVE_MUTEXES == 1 ) */
+
+/* ------------------------------------------------------------------------------- */
+
+#if ( configUSE_QUEUE_SETS == 1 )
+
+ .extern MPU_xQueueSelectFromSetImpl
+ .align 4
+ .global MPU_xQueueSelectFromSet
+ .type MPU_xQueueSelectFromSet, function
+ MPU_xQueueSelectFromSet:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xQueueSelectFromSet, MPU_xQueueSelectFromSetImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+ .extern MPU_xQueueAddToSetImpl
+ .align 4
+ .global MPU_xQueueAddToSet
+ .type MPU_xQueueAddToSet, function
+ MPU_xQueueAddToSet:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xQueueAddToSet, MPU_xQueueAddToSetImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+#endif /* if ( configUSE_QUEUE_SETS == 1 ) */
+
+/* ------------------------------------------------------------------------------- */
+
+#if ( configQUEUE_REGISTRY_SIZE > 0 )
+
+ .extern MPU_vQueueAddToRegistryImpl
+ .align 4
+ .global MPU_vQueueAddToRegistry
+ .type MPU_vQueueAddToRegistry, function
+ MPU_vQueueAddToRegistry:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_vQueueAddToRegistry, MPU_vQueueAddToRegistryImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+ .extern MPU_vQueueUnregisterQueueImpl
+ .align 4
+ .global MPU_vQueueUnregisterQueue
+ .type MPU_vQueueUnregisterQueue, function
+ MPU_vQueueUnregisterQueue:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_vQueueUnregisterQueue, MPU_vQueueUnregisterQueueImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+ .extern MPU_pcQueueGetNameImpl
+ .align 4
+ .global MPU_pcQueueGetName
+ .type MPU_pcQueueGetName, function
+ MPU_pcQueueGetName:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_pcQueueGetName, MPU_pcQueueGetNameImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+#endif /* if ( configQUEUE_REGISTRY_SIZE > 0 ) */
+
+/* ------------------------------------------------------------------------------- */
+
+#if ( configUSE_TIMERS == 1 )
+
+ .extern MPU_pvTimerGetTimerIDImpl
+ .align 4
+ .global MPU_pvTimerGetTimerID
+ .type MPU_pvTimerGetTimerID, function
+ MPU_pvTimerGetTimerID:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_pvTimerGetTimerID, MPU_pvTimerGetTimerIDImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+ .extern MPU_vTimerSetTimerIDImpl
+ .align 4
+ .global MPU_vTimerSetTimerID
+ .type MPU_vTimerSetTimerID, function
+ MPU_vTimerSetTimerID:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_vTimerSetTimerID, MPU_vTimerSetTimerIDImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+ .extern MPU_xTimerIsTimerActiveImpl
+ .align 4
+ .global MPU_xTimerIsTimerActive
+ .type MPU_xTimerIsTimerActive, function
+ MPU_xTimerIsTimerActive:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTimerIsTimerActive, MPU_xTimerIsTimerActiveImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+ .extern MPU_xTimerGetTimerDaemonTaskHandleImpl
+ .align 4
+ .global MPU_xTimerGetTimerDaemonTaskHandle
+ .type MPU_xTimerGetTimerDaemonTaskHandle, function
+ MPU_xTimerGetTimerDaemonTaskHandle:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTimerGetTimerDaemonTaskHandle, MPU_xTimerGetTimerDaemonTaskHandleImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+ .extern MPU_xTimerGenericCommandFromTaskImpl
+ .align 4
+ .global MPU_xTimerGenericCommandFromTaskEntry
+ .type MPU_xTimerGenericCommandFromTaskEntry, function
+ MPU_xTimerGenericCommandFromTaskEntry:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTimerGenericCommandFromTask, MPU_xTimerGenericCommandFromTaskImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+ .extern MPU_pcTimerGetNameImpl
+ .align 4
+ .global MPU_pcTimerGetName
+ .type MPU_pcTimerGetName, function
+ MPU_pcTimerGetName:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_pcTimerGetName, MPU_pcTimerGetNameImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+ .extern MPU_vTimerSetReloadModeImpl
+ .align 4
+ .global MPU_vTimerSetReloadMode
+ .type MPU_vTimerSetReloadMode, function
+ MPU_vTimerSetReloadMode:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_vTimerSetReloadMode, MPU_vTimerSetReloadModeImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+ .extern MPU_xTimerGetReloadModeImpl
+ .align 4
+ .global MPU_xTimerGetReloadMode
+ .type MPU_xTimerGetReloadMode, function
+ MPU_xTimerGetReloadMode:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTimerGetReloadMode, MPU_xTimerGetReloadModeImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+ .extern MPU_uxTimerGetReloadModeImpl
+ .align 4
+ .global MPU_uxTimerGetReloadMode
+ .type MPU_uxTimerGetReloadMode, function
+ MPU_uxTimerGetReloadMode:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_uxTimerGetReloadMode, MPU_uxTimerGetReloadModeImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+ .extern MPU_xTimerGetPeriodImpl
+ .align 4
+ .global MPU_xTimerGetPeriod
+ .type MPU_xTimerGetPeriod, function
+ MPU_xTimerGetPeriod:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTimerGetPeriod, MPU_xTimerGetPeriodImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+ .extern MPU_xTimerGetExpiryTimeImpl
+ .align 4
+ .global MPU_xTimerGetExpiryTime
+ .type MPU_xTimerGetExpiryTime, function
+ MPU_xTimerGetExpiryTime:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTimerGetExpiryTime, MPU_xTimerGetExpiryTimeImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+#endif /* if ( configUSE_TIMERS == 1 ) */
+
+/* ------------------------------------------------------------------------------- */
+
+#if ( configUSE_TASK_NOTIFICATIONS == 1 )
+
+ .extern MPU_xTaskGenericNotifyImpl
+ .align 4
+ .global MPU_xTaskGenericNotifyEntry
+ .type MPU_xTaskGenericNotifyEntry, function
+ MPU_xTaskGenericNotifyEntry:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTaskGenericNotify, MPU_xTaskGenericNotifyImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+ .extern MPU_xTaskGenericNotifyWaitImpl
+ .align 4
+ .global MPU_xTaskGenericNotifyWaitEntry
+ .type MPU_xTaskGenericNotifyWaitEntry, function
+ MPU_xTaskGenericNotifyWaitEntry:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTaskGenericNotifyWait, MPU_xTaskGenericNotifyWaitImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+ .extern MPU_ulTaskGenericNotifyTakeImpl
+ .align 4
+ .global MPU_ulTaskGenericNotifyTake
+ .type MPU_ulTaskGenericNotifyTake, function
+ MPU_ulTaskGenericNotifyTake:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_ulTaskGenericNotifyTake, MPU_ulTaskGenericNotifyTakeImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+ .extern MPU_xTaskGenericNotifyStateClearImpl
+ .align 4
+ .global MPU_xTaskGenericNotifyStateClear
+ .type MPU_xTaskGenericNotifyStateClear, function
+ MPU_xTaskGenericNotifyStateClear:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_xTaskGenericNotifyStateClear, MPU_xTaskGenericNotifyStateClearImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+ .extern MPU_ulTaskGenericNotifyValueClearImpl
+ .align 4
+ .global MPU_ulTaskGenericNotifyValueClear
+ .type MPU_ulTaskGenericNotifyValueClear, function
+ MPU_ulTaskGenericNotifyValueClear:
+ INVOKE_SYSTEM_CALL #SYSTEM_CALL_ulTaskGenericNotifyValueClear, MPU_ulTaskGenericNotifyValueClearImpl
+
+ /* ------------------------------------------------------------------------------- */
+
+#endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
+
+/* ------------------------------------------------------------------------------- */
+
+.end
diff --git a/portable/GCC/ARM_CRx_MPU/port.c b/portable/GCC/ARM_CRx_MPU/port.c
new file mode 100644
index 0000000..bef3a78
--- /dev/null
+++ b/portable/GCC/ARM_CRx_MPU/port.c
@@ -0,0 +1,843 @@
+/*
+ * FreeRTOS Kernel <DEVELOPMENT BRANCH>
+ * Copyright (C) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+/* Standard includes. */
+#include <stdint.h>
+
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
+ * all the API functions to use the MPU wrappers. That should only be done when
+ * task.h is included from an application file. */
+#ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+ #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+#endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
+
+/* Scheduler includes. */
+#include "FreeRTOS.h"
+#include "portmacro.h"
+#include "task.h"
+#include "mpu_syscall_numbers.h"
+
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+/* Max value that fits in a uint32_t type. */
+#define portUINT32_MAX ( ~( ( uint32_t ) 0 ) )
+
+/* Check if adding a and b will result in overflow. */
+#define portADD_UINT32_WILL_OVERFLOW( a, b ) ( ( a ) > ( portUINT32_MAX - ( b ) ) )
+/* ----------------------------------------------------------------------------------- */
+
+/**
+ * @brief Variable used to keep track of critical section nesting.
+ *
+ * @ingroup Critical Sections
+ *
+ * This variable is 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 UBaseType_t ulCriticalNesting = 0xFFFF;
+
+/**
+ * @brief Set to 1 to pend a context switch from an ISR.
+ *
+ * @ingroup Interrupt Management
+ */
+PRIVILEGED_DATA volatile UBaseType_t ulPortYieldRequired = pdFALSE;
+
+/**
+ * @brief Interrupt nesting depth, used to count the number of interrupts to unwind.
+ *
+ * @ingroup Interrupt Management
+ */
+PRIVILEGED_DATA volatile UBaseType_t ulPortInterruptNesting = 0UL;
+
+/**
+ * @brief Variable to track whether or not the scheduler has been started.
+ *
+ * @ingroup Scheduler
+ *
+ * This is the port specific version of the xSchedulerRunning in tasks.c.
+ */
+PRIVILEGED_DATA static BaseType_t prvPortSchedulerRunning = pdFALSE;
+
+/* -------------------------- Private Function Declarations -------------------------- */
+
+/**
+ * @brief Determine if the given MPU region settings authorizes the requested
+ * access to the given buffer.
+ *
+ * @ingroup Task Context
+ * @ingroup MPU Control
+ *
+ * @param xTaskMPURegion MPU region settings.
+ * @param ulBufferStart Start address of the given buffer.
+ * @param ulBufferLength Length of the given buffer.
+ * @param ulAccessRequested Access requested.
+ *
+ * @return pdTRUE if MPU region settins authorizes the requested access to the
+ * given buffer, pdFALSE otherwise.
+ */
+PRIVILEGED_FUNCTION static BaseType_t prvMPURegionAuthorizesBuffer( const xMPU_REGION_REGISTERS * xTaskMPURegion,
+ const uint32_t ulBufferStart,
+ const uint32_t ulBufferLength,
+ const uint32_t ulAccessRequested );
+
+/**
+ * @brief Determine the smallest MPU Region Size Encoding for the given MPU
+ * region size.
+ *
+ * @ingroup MPU Control
+ *
+ * @param ulActualMPURegionSize MPU region size in bytes.
+ *
+ * @return The smallest MPU Region Size Encoding for the given MPU region size.
+ */
+PRIVILEGED_FUNCTION static uint32_t prvGetMPURegionSizeEncoding( uint32_t ulActualMPURegionSize );
+
+/**
+ * @brief Set up MPU.
+ *
+ * @ingroup MPU Control
+ */
+PRIVILEGED_FUNCTION static void prvSetupMPU( void );
+
+/* -------------------------- Exported Function Declarations -------------------------- */
+
+/**
+ * @brief Enter critical section.
+ *
+ * @ingroup Critical Section
+ */
+PRIVILEGED_FUNCTION void vPortEnterCritical( void );
+
+/**
+ * @brief Exit critical section.
+ *
+ * @ingroup Critical Section
+ */
+PRIVILEGED_FUNCTION void vPortExitCritical( void );
+
+/* ----------------------------------------------------------------------------------- */
+
+/**
+ * @brief Setup a FreeRTOS task's initial context.
+ *
+ * @ingroup Task Context
+ *
+ * @param pxTopOfStack Top of stack.
+ * @param pxCode The task function.
+ * @param pvParameters Argument passed to the task function.
+ * @param xRunPrivileged Marks if the task is privileged.
+ * @param xMPUSettings MPU settings of the task.
+ *
+ * @return Location where to restore the task's context from.
+ */
+/* PRIVILEGED_FUNCTION */
+StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
+ TaskFunction_t pxCode,
+ void * pvParameters,
+ BaseType_t xRunPrivileged,
+ xMPU_SETTINGS * xMPUSettings )
+{
+ /* Setup the initial context of the task. The context is set exactly as
+ * expected by the portRESTORE_CONTEXT() macro. */
+ UBaseType_t ulIndex = CONTEXT_SIZE - 1U;
+
+ xSYSTEM_CALL_STACK_INFO * xSysCallInfo = NULL;
+
+ if( xRunPrivileged == pdTRUE )
+ {
+ xMPUSettings->ulTaskFlags |= portTASK_IS_PRIVILEGED_FLAG;
+ /* Current Program Status Register (CPSR). */
+ xMPUSettings->ulContext[ ulIndex ] = SYS_MODE;
+ }
+ else
+ {
+ xMPUSettings->ulTaskFlags &= ( ~portTASK_IS_PRIVILEGED_FLAG );
+ /* Current Program Status Register (CPSR). */
+ xMPUSettings->ulContext[ ulIndex ] = USER_MODE;
+ }
+
+ if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x0UL )
+ {
+ /* The task will cause the processor to start in THUMB state, set the
+ * Thumb state bit in the CPSR. */
+ xMPUSettings->ulContext[ ulIndex ] |= portTHUMB_MODE_BIT;
+ }
+
+ ulIndex--;
+
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) pxCode; /* PC. */
+ ulIndex--;
+
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
+ ulIndex--;
+
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) pxTopOfStack; /* SP. */
+ ulIndex--;
+
+ /* General Purpose Registers. */
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x12121212; /* R12. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x11111111; /* R11. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x10101010; /* R10. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x09090909; /* R9. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x08080808; /* R8. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x07070707; /* R7. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x06060606; /* R6. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x05050505; /* R5. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x04040404; /* R4. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x03030303; /* R3. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x02020202; /* R2. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x01010101; /* R1. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) pvParameters; /* R0. */
+ ulIndex--;
+
+ #if( portENABLE_FPU == 1 )
+ {
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000015; /* S31. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1500000; /* S30. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000014; /* S29. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1400000; /* S28. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000013; /* S27. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1300000; /* S26. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000012; /* S25. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1200000; /* S24. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000011; /* S23. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1100000; /* S22. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000010; /* S21. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1000000; /* S20. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000009; /* S19. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD9000000; /* S18. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000008; /* S17. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD8000000; /* S16. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000007; /* S15. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD7000000; /* S14. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000006; /* S13. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD6000000; /* S12. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000005; /* S11. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD5000000; /* S10. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000004; /* S9. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD4000000; /* S8. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000003; /* S7. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD3000000; /* S6. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000002; /* S5. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD2000000; /* S4. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000001; /* S3. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1000000; /* S2. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000000; /* S1. */
+ ulIndex--;
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000000; /* S0. */
+ ulIndex--;
+
+ xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x00000000; /* FPSR. */
+ ulIndex--;
+ }
+ #endif /* portENABLE_FPU */
+
+ /* The task will start with a critical nesting count of 0. */
+ xMPUSettings->ulContext[ ulIndex ] = portNO_CRITICAL_NESTING;
+
+ /* Ensure that the system call stack is double word aligned. */
+ xSysCallInfo = &( xMPUSettings->xSystemCallStackInfo );
+ xSysCallInfo->pulSystemCallStackPointer = &( xSysCallInfo->ulSystemCallStackBuffer[ configSYSTEM_CALL_STACK_SIZE - 1U ] );
+ xSysCallInfo->pulSystemCallStackPointer = ( uint32_t * ) ( ( ( uint32_t ) ( xSysCallInfo->pulSystemCallStackPointer ) ) &
+ ( ( uint32_t ) ( ~( portBYTE_ALIGNMENT_MASK ) ) ) );
+
+ /* This is not NULL only for the duration of a system call. */
+ xSysCallInfo->pulTaskStackPointer = NULL;
+
+ /* Set the System Call to return to vPortSystemCallExit. */
+ xSysCallInfo->pulSystemCallExitAddress = ( uint32_t * ) ( &vPortSystemCallExit );
+
+ /* Return the address where this task's context should be restored from. */
+ return &( xMPUSettings->ulContext[ ulIndex ] );
+}
+
+/* ----------------------------------------------------------------------------------- */
+
+/**
+ * @brief Store a FreeRTOS task's MPU settings in its TCB.
+ *
+ * @ingroup Task Context
+ * @ingroup MPU Control
+ *
+ * @param xMPUSettings The MPU settings in TCB.
+ * @param xRegions The updated MPU settings requested by the task.
+ * @param pxBottomOfStack The base address of the task's Stack.
+ * @param ulStackDepth The length of the task's stack.
+ */
+/* PRIVILEGED_FUNCTION */
+void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
+ const struct xMEMORY_REGION * const xRegions,
+ StackType_t * pxBottomOfStack,
+ uint32_t ulStackDepth )
+{
+ #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__;
+ #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 ulIndex = 0x0;
+ uint32_t ulRegionLength;
+ uint32_t ulRegionLengthEncoded;
+ uint32_t ulRegionLengthDecoded;
+
+ if( xRegions == NULL )
+ {
+ /* No MPU regions are specified so allow access to all of the RAM. */
+ ulRegionLength = ( uint32_t ) __SRAM_segment_end__ - ( uint32_t ) __SRAM_segment_start__;
+ ulRegionLengthEncoded = prvGetMPURegionSizeEncoding( ulRegionLength );
+ ulRegionLength |= portMPU_REGION_ENABLE;
+
+ /* MPU Settings is zero'd out in the TCB before this function is called.
+ * We, therefore, do not need to explicitly zero out unused MPU regions
+ * in xMPUSettings. */
+ ulIndex = portSTACK_REGION;
+
+ xMPUSettings->xRegion[ ulIndex ].ulRegionBaseAddress = ( uint32_t ) __SRAM_segment_start__;
+ xMPUSettings->xRegion[ ulIndex ].ulRegionSize = ( ulRegionLengthEncoded |
+ portMPU_REGION_ENABLE );
+ xMPUSettings->xRegion[ ulIndex ].ulRegionAttribute = ( portMPU_REGION_PRIV_RW_USER_RW_NOEXEC |
+ portMPU_REGION_NORMAL_OIWTNOWA_SHARED );
+ }
+ else
+ {
+ for( ulIndex = 0UL; ulIndex < portNUM_CONFIGURABLE_REGIONS; ulIndex++ )
+ {
+ /* If a length has been provided, the region is in use. */
+ if( ( xRegions[ ulIndex ] ).ulLengthInBytes > 0UL )
+ {
+ ulRegionLength = xRegions[ ulIndex ].ulLengthInBytes;
+ ulRegionLengthEncoded = prvGetMPURegionSizeEncoding( ulRegionLength );
+
+ /* MPU region base address must be aligned to the region size
+ * boundary. */
+ ulRegionLengthDecoded = 2UL << ( ulRegionLengthEncoded >> 1UL );
+ configASSERT( ( ( ( uint32_t ) xRegions[ ulIndex ].pvBaseAddress ) % ( ulRegionLengthDecoded ) ) == 0UL );
+
+ xMPUSettings->xRegion[ ulIndex ].ulRegionBaseAddress = ( uint32_t ) xRegions[ ulIndex ].pvBaseAddress;
+ xMPUSettings->xRegion[ ulIndex ].ulRegionSize = ( ulRegionLengthEncoded |
+ portMPU_REGION_ENABLE );
+ xMPUSettings->xRegion[ ulIndex ].ulRegionAttribute = xRegions[ ulIndex ].ulParameters;
+ }
+ else
+ {
+ xMPUSettings->xRegion[ ulIndex ].ulRegionBaseAddress = 0x0UL;
+ xMPUSettings->xRegion[ ulIndex ].ulRegionSize = 0x0UL;
+ xMPUSettings->xRegion[ ulIndex ].ulRegionAttribute = 0x0UL;
+ }
+ }
+
+ /* 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 != 0x0UL )
+ {
+ ulRegionLengthEncoded = prvGetMPURegionSizeEncoding( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) );
+
+ /* MPU region base address must be aligned to the region size
+ * boundary. */
+ ulRegionLengthDecoded = 2UL << ( ulRegionLengthEncoded >> 1UL );
+ configASSERT( ( ( uint32_t ) pxBottomOfStack % ( ulRegionLengthDecoded ) ) == 0U );
+
+ ulIndex = portSTACK_REGION;
+ xMPUSettings->xRegion[ ulIndex ].ulRegionBaseAddress = ( uint32_t ) pxBottomOfStack;
+ xMPUSettings->xRegion[ ulIndex ].ulRegionSize = ( ulRegionLengthEncoded |
+ portMPU_REGION_ENABLE );;
+ xMPUSettings->xRegion[ ulIndex ].ulRegionAttribute = ( portMPU_REGION_PRIV_RW_USER_RW_NOEXEC |
+ portMPU_REGION_NORMAL_OIWTNOWA_SHARED );
+ }
+ }
+}
+
+/* ----------------------------------------------------------------------------------- */
+
+/* PRIVILEGED_FUNCTION */
+BaseType_t xPortIsTaskPrivileged( void )
+{
+ 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;
+}
+
+/* ----------------------------------------------------------------------------------- */
+
+/* PRIVILEGED_FUNCTION */
+BaseType_t xPortStartScheduler( void )
+{
+ /* Start the timer that generates the tick ISR. */
+ configSETUP_TICK_INTERRUPT();
+
+ /* Configure MPU regions that are common to all tasks. */
+ prvSetupMPU();
+
+ prvPortSchedulerRunning = pdTRUE;
+
+ /* Load the context of the first task. */
+ 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 pdFALSE;
+}
+
+/* ----------------------------------------------------------------------------------- */
+
+/* PRIVILEGED_FUNCTION */
+static uint32_t prvGetMPURegionSizeEncoding( uint32_t ulActualMPURegionSize )
+{
+ uint32_t ulRegionSize, ulReturnValue = 4U;
+
+ /* 32 bytes is the smallest valid region for Cortex R4 and R5 CPUs. */
+ for( ulRegionSize = 0x20UL; ulReturnValue < 0x1FUL; ( ulRegionSize <<= 1UL ) )
+ {
+ if( ulActualMPURegionSize <= 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;
+}
+
+/* ----------------------------------------------------------------------------------- */
+
+/* PRIVILEGED_FUNCTION */
+static void prvSetupMPU( void )
+{
+#if defined( __ARMCC_VERSION )
+ /* Declaration when these variable are defined in code. */
+ /* 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__;
+#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__[];
+#endif /* if defined( __ARMCC_VERSION ) */
+
+ uint32_t ulRegionLength;
+ uint32_t ulRegionLengthEncoded;
+
+ /* Disable the MPU before programming it. */
+ vMPUDisable();
+
+ /* Priv: RX, Unpriv: RX for entire Flash. */
+ ulRegionLength = ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__;
+ ulRegionLengthEncoded = prvGetMPURegionSizeEncoding( ulRegionLength );
+ vMPUSetRegion( portUNPRIVILEGED_FLASH_REGION,
+ ( uint32_t ) __FLASH_segment_start__,
+ ( ulRegionLengthEncoded | portMPU_REGION_ENABLE ),
+ ( portMPU_REGION_PRIV_RO_USER_RO_EXEC |
+ portMPU_REGION_NORMAL_OIWTNOWA_SHARED ) );
+
+ /* Priv: RX, Unpriv: No access for privileged functions. */
+ ulRegionLength = ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __privileged_functions_start__;
+ ulRegionLengthEncoded = prvGetMPURegionSizeEncoding( ulRegionLength );
+ vMPUSetRegion( portPRIVILEGED_FLASH_REGION,
+ ( uint32_t ) __privileged_functions_start__,
+ ( ulRegionLengthEncoded | portMPU_REGION_ENABLE ),
+ ( portMPU_REGION_PRIV_RO_USER_NA_EXEC |
+ portMPU_REGION_NORMAL_OIWTNOWA_SHARED ) );
+
+ /* Priv: RW, Unpriv: No Access for privileged data. */
+ ulRegionLength = ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__;
+ ulRegionLengthEncoded = prvGetMPURegionSizeEncoding( ulRegionLength );
+ vMPUSetRegion( portPRIVILEGED_RAM_REGION,
+ ( uint32_t ) __privileged_data_start__,
+ ( ulRegionLengthEncoded | portMPU_REGION_ENABLE ),
+ ( portMPU_REGION_PRIV_RW_USER_NA_NOEXEC |
+ portMPU_REGION_PRIV_RW_USER_NA_NOEXEC ) );
+
+ /* Enable the MPU background region - it allows privileged operating modes
+ * access to unmapped regions of memory without generating a fault. */
+ vMPUEnableBackgroundRegion();
+
+ /* After setting default regions, enable the MPU. */
+ vMPUEnable();
+}
+
+/* ----------------------------------------------------------------------------------- */
+
+/* PRIVILEGED_FUNCTION */
+static BaseType_t prvMPURegionAuthorizesBuffer( const xMPU_REGION_REGISTERS * xTaskMPURegion,
+ const uint32_t ulBufferStart,
+ const uint32_t ulBufferLength,
+ const uint32_t ulAccessRequested )
+{
+ BaseType_t xAccessGranted = pdFALSE;
+ uint32_t ulBufferEnd;
+ uint32_t ulMPURegionLength;
+ uint32_t ulMPURegionStart;
+ uint32_t ulMPURegionEnd;
+ uint32_t ulMPURegionAccessPermissions;
+
+ if( portADD_UINT32_WILL_OVERFLOW( ulBufferStart, ( ulBufferLength - 1UL ) ) == pdFALSE )
+ {
+ ulBufferEnd = ulBufferStart + ulBufferLength - 1UL;
+ ulMPURegionLength = 2UL << ( xTaskMPURegion->ulRegionSize >> 1UL );
+ ulMPURegionStart = xTaskMPURegion->ulRegionBaseAddress;
+ ulMPURegionEnd = xTaskMPURegion->ulRegionBaseAddress + ulMPURegionLength - 1UL;
+
+ if( ( ulBufferStart >= ulMPURegionStart ) &&
+ ( ulBufferEnd <= ulMPURegionEnd ) &&
+ ( ulBufferStart <= ulBufferEnd ) )
+ {
+ ulMPURegionAccessPermissions = xTaskMPURegion->ulRegionAttribute & portMPU_REGION_AP_BITMASK;
+
+ if( ulAccessRequested == tskMPU_READ_PERMISSION ) /* RO. */
+ {
+ if( ( ulMPURegionAccessPermissions == portMPU_REGION_PRIV_RW_USER_RO ) ||
+ ( ulMPURegionAccessPermissions == portMPU_REGION_PRIV_RO_USER_RO ) )
+ {
+ xAccessGranted = pdTRUE;
+ }
+ }
+ else if( ( ulAccessRequested & tskMPU_WRITE_PERMISSION ) != 0UL ) /* W or RW. */
+ {
+ if( ulMPURegionAccessPermissions == portMPU_REGION_PRIV_RW_USER_RW )
+ {
+ xAccessGranted = pdTRUE;
+ }
+ }
+ }
+ }
+
+ return xAccessGranted;
+}
+
+/* ----------------------------------------------------------------------------------- */
+
+/* PRIVILEGED_FUNCTION */
+BaseType_t xPortIsAuthorizedToAccessBuffer( const void * pvBuffer,
+ uint32_t ulBufferLength,
+ uint32_t ulAccessRequested )
+{
+ BaseType_t xAccessGranted = pdFALSE;
+ uint32_t ulRegionIndex;
+ xMPU_SETTINGS * xTaskMPUSettings = NULL;
+
+ if( prvPortSchedulerRunning == pdFALSE )
+ {
+ /* Grant access to all the memory 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
+ {
+ /* Calling task's MPU settings. */
+ xTaskMPUSettings = xTaskGetMPUSettings( NULL );
+
+ if( ( xTaskMPUSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
+ {
+ /* Privileged tasks have access to all the memory. */
+ xAccessGranted = pdTRUE;
+ }
+ else
+ {
+ for( ulRegionIndex = 0x0UL; ulRegionIndex < portTOTAL_NUM_REGIONS_IN_TCB; ulRegionIndex++ )
+ {
+ xAccessGranted = prvMPURegionAuthorizesBuffer( &( xTaskMPUSettings->xRegion[ ulRegionIndex ] ),
+ ( uint32_t ) pvBuffer,
+ ulBufferLength,
+ ulAccessRequested );
+
+ if( xAccessGranted == pdTRUE )
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ return xAccessGranted;
+}
+
+/* ----------------------------------------------------------------------------------- */
+
+#if( configENABLE_ACCESS_CONTROL_LIST == 1 )
+
+/* PRIVILEGED_FUNCTION */
+BaseType_t xPortIsAuthorizedToAccessKernelObject( int32_t lInternalIndexOfKernelObject )
+{
+ uint32_t ulAccessControlListEntryIndex, ulAccessControlListEntryBit;
+ BaseType_t xAccessGranted = pdFALSE;
+ const xMPU_SETTINGS * xTaskMpuSettings;
+
+ if( prvPortSchedulerRunning == 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
+ {
+ /* Calling task's MPU settings. */
+ xTaskMpuSettings = xTaskGetMPUSettings( NULL );
+
+ 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 ) ) != 0UL )
+ {
+ xAccessGranted = pdTRUE;
+ }
+ }
+ }
+
+ return xAccessGranted;
+}
+
+#else
+
+/* PRIVILEGED_FUNCTION */
+BaseType_t xPortIsAuthorizedToAccessKernelObject( int32_t lInternalIndexOfKernelObject )
+{
+ ( 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 ) */
+
+/* ----------------------------------------------------------------------------------- */
+
+#if( configENABLE_ACCESS_CONTROL_LIST == 1 )
+
+/* PRIVILEGED_FUNCTION */
+void vPortGrantAccessToKernelObject( TaskHandle_t xInternalTaskHandle,
+ int32_t lInternalIndexOfKernelObject )
+{
+ uint32_t ulAccessControlListEntryIndex, ulAccessControlListEntryBit;
+ xMPU_SETTINGS * xTaskMpuSettings;
+
+ ulAccessControlListEntryIndex = ( ( uint32_t ) lInternalIndexOfKernelObject
+ / portACL_ENTRY_SIZE_BITS );
+ ulAccessControlListEntryBit = ( ( uint32_t ) lInternalIndexOfKernelObject
+ % portACL_ENTRY_SIZE_BITS );
+
+ xTaskMpuSettings = xTaskGetMPUSettings( xInternalTaskHandle );
+
+ xTaskMpuSettings->ulAccessControlList[ ulAccessControlListEntryIndex ] |= ( 1U << ulAccessControlListEntryBit );
+}
+
+#endif /* #if ( configENABLE_ACCESS_CONTROL_LIST == 1 ) */
+
+/* ----------------------------------------------------------------------------------- */
+
+#if( configENABLE_ACCESS_CONTROL_LIST == 1 )
+
+/* PRIVILEGED_FUNCTION */
+void vPortRevokeAccessToKernelObject( TaskHandle_t xInternalTaskHandle,
+ int32_t lInternalIndexOfKernelObject )
+{
+ uint32_t ulAccessControlListEntryIndex, ulAccessControlListEntryBit;
+ xMPU_SETTINGS * xTaskMpuSettings;
+
+ ulAccessControlListEntryIndex = ( ( uint32_t ) lInternalIndexOfKernelObject
+ / portACL_ENTRY_SIZE_BITS );
+ ulAccessControlListEntryBit = ( ( uint32_t ) lInternalIndexOfKernelObject
+ % portACL_ENTRY_SIZE_BITS );
+
+ xTaskMpuSettings = xTaskGetMPUSettings( xInternalTaskHandle );
+
+ xTaskMpuSettings->ulAccessControlList[ ulAccessControlListEntryIndex ] &= ~( 1U << ulAccessControlListEntryBit );
+}
+
+#endif /* #if ( configENABLE_ACCESS_CONTROL_LIST == 1 ) */
+
+/* ----------------------------------------------------------------------------------- */
+
+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( ;; )
+ {
+ }
+}
+
+/* ----------------------------------------------------------------------------------- */
+
+void vPortEndScheduler( void )
+{
+ prvPortSchedulerRunning = pdFALSE;
+
+ /* Not implemented in this port. Artificially force an assert. */
+ configASSERT( prvPortSchedulerRunning == pdTRUE );
+}
+
+/* ----------------------------------------------------------------------------------- */
+
+/* PRIVILEGED_FUNCTION */
+void vPortEnterCritical( void )
+{
+ portDISABLE_INTERRUPTS();
+
+ /* Now that interrupts are disabled, ulCriticalNesting can be accessed
+ * directly. Increment ulCriticalNesting to keep a count of how many times
+ * portENTER_CRITICAL() has been called. */
+ ulCriticalNesting++;
+
+ /* This is not the interrupt safe version of the enter critical function so
+ * assert() if it is being called from an interrupt context. Only API
+ * functions that end in "FromISR" can be used in an interrupt. Only assert
+ * if the critical nesting count is 1 to protect against recursive calls if
+ * the assert function also uses a critical section. */
+ if( ulCriticalNesting == 1 )
+ {
+ configASSERT( ulPortInterruptNesting == 0 );
+ }
+}
+/* ----------------------------------------------------------------------------------- */
+
+/* PRIVILEGED_FUNCTION */
+void vPortExitCritical( void )
+{
+ if( ulCriticalNesting > portNO_CRITICAL_NESTING )
+ {
+ /* Decrement the nesting count as the critical section is being
+ * exited. */
+ ulCriticalNesting--;
+
+ /* If the nesting level has reached zero then all interrupt
+ * priorities must be re-enabled. */
+ if( ulCriticalNesting == portNO_CRITICAL_NESTING )
+ {
+ /* Critical nesting has reached zero so all interrupt priorities
+ * should be unmasked. */
+ portENABLE_INTERRUPTS();
+ }
+ }
+}
+/* ----------------------------------------------------------------------------------- */
diff --git a/portable/GCC/ARM_CRx_MPU/portASM.S b/portable/GCC/ARM_CRx_MPU/portASM.S
new file mode 100644
index 0000000..cac0fc4
--- /dev/null
+++ b/portable/GCC/ARM_CRx_MPU/portASM.S
@@ -0,0 +1,498 @@
+/*
+ * FreeRTOS Kernel <DEVELOPMENT BRANCH>
+ * Copyright (C) 2024 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
+ .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 uxSystemCallImplementations
+ .extern ulPortInterruptNesting
+ .extern ulPortYieldRequired
+
+ /* External Llnker script variables. */
+ .extern __syscalls_flash_start__
+ .extern __syscalls_flash_end__
+
+ /* External FreeRTOS-Kernel functions. */
+ .extern vTaskSwitchContext
+ .extern vApplicationIRQHandler
+
+/* ----------------------------------------------------------------------------------- */
+
+/* Save the context of a FreeRTOS Task. */
+.macro portSAVE_CONTEXT
+ DSB
+ ISB
+ /* Push R0 and LR to the stack for current mode. */
+ PUSH { R0, LR }
+
+ LDR LR, =pxCurrentTCB /* LR = &( pxCurrentTCB ). */
+ LDR LR, [LR] /* LR = pxCurrentTCB. */
+ LDR LR, [LR] /* LR = pxTopOfStack i.e. the address where to store the task context. */
+
+ LDR R0, =ulCriticalNesting /* R0 = &( ulCriticalNesting ). */
+ LDR R0, [R0] /* R0 = ulCriticalNesting. */
+ STM LR!, { R0 } /* Store ulCriticalNesting. ! increments LR after storing. */
+
+#if ( portENABLE_FPU == 1 )
+ VMRS R0, FPSCR /* R0 = FPSCR. */
+ STM LR!, { R0 } /* Store FPSCR. */
+ VSTM LR!, { D0-D15 } /* Store D0-D15. */
+#endif /* ( portENABLE_FPU == 1 ) */
+
+ POP { R0 } /* Restore R0 to pre-exception value. */
+ /* STM (user registers) - In a PL1 mode other than System mode, STM (user
+ * registers) instruction stores multiple User mode registers to
+ * consecutive memory locations using an address from a base register. The
+ * processor reads the base register value normally, using the current mode
+ * to determine the correct Banked version of the register. This instruction
+ * cannot writeback to the base register.
+ *
+ * The following can be derived from the above description:
+ * - The macro portSAVE_CONTEXT MUST be called from a PL1 mode other than
+ * the System mode.
+ * - Base register LR of the current mode will be used which contains the
+ * location to store the context.
+ * - It will store R0-R14 of User mode i.e. pre-exception SP(R13) and LR(R14)
+ * will be stored. */
+ STM LR, { R0-R14 }^
+ ADD LR, LR, #60 /* R0-R14 - Total 155 register, each 4 byte wide. */
+
+ POP { R0 } /* Pre-exception PC is in R0. */
+ MRS R1, SPSR /* R1 = Pre-exception CPSR. */
+ STM LR!, { R0-R1 } /* Store pre-exception PC and CPSR. */
+
+.endm
+
+/* ----------------------------------------------------------------------------------- */
+
+/* Restore the context of a FreeRTOS Task. */
+.macro portRESTORE_CONTEXT
+ /* Load the pointer to the current task's Task Control Block (TCB). */
+ LDR LR, =pxCurrentTCB /* LR = &( pxCurrentTCB ). */
+ LDR LR, [LR] /* LR = pxCurrentTCB. */
+ ADD R1, LR, #0x4 /* R1 now points to the xMPUSettings in TCB. */
+ LDR LR, [LR] /* LR = pxTopOfStack i.e. the address where to restore the task context from. */
+
+ /* When creating a loop label in a macro it has to be a numeric label.
+ * for( R5 = portFIRST_CONFIGURABLE_REGION ; R5 <= portNUM_CONFIGURABLE_REGIONS ; R5++ ) */
+ MOV R5, #portFIRST_CONFIGURABLE_REGION
+ 123:
+ LDMIA R1!, { R2-R4 } /* R2 = ulRegionSize, R3 = ulRegionAttribute, R4 = ulRegionBaseAddress. */
+
+ MCR p15, #0, R5, c6, c2, #0 /* MPU Region Number Register. */
+ MCR p15, #0, R4, c6, c1, #0 /* MPU Region Base Address Register. */
+ MCR p15, #0, R3, c6, c1, #4 /* MPU Region Access Control Register. */
+ MCR p15, #0, R2, c6, c1, #2 /* MPU Region Size and Enable Register. */
+
+ ADD R5, R5, #1
+ CMP R5, #portNUM_CONFIGURABLE_REGIONS
+ BLE 123b
+
+ LDR R1, =ulCriticalNesting /* R1 = &( ulCriticalNesting ). */
+ LDM LR!, { R2 } /* R2 = Stored ulCriticalNesting. */
+ STR R2, [R1] /* Restore ulCriticalNesting. */
+
+#if ( portENABLE_FPU == 1 )
+ LDM LR!, { R1 } /* R1 = Stored FPSCR. */
+ VMSR FPSCR, R1 /* Restore FPSCR. */
+ VLDM LR!, { D0-D15 } /* Restore D0-D15. */
+#endif /* portENABLE_FPU*/
+
+ /* LDM (User registers) - In a PL1 mode other than System mode, LDM (User
+ * registers) loads multiple User mode registers from consecutive memory
+ * locations using an address from a base register. The registers loaded
+ * cannot include the PC. The processor reads the base register value
+ * normally, using the current mode to determine the correct Banked version
+ * of the register. This instruction cannot writeback to the base register.
+ *
+ * The following can be derived from the above description:
+ * - The macro portRESTORE_CONTEXT MUST be called from a PL1 mode other than
+ * the System mode.
+ * - Base register LR of the current mode will be used which contains the
+ * location to restore the context from.
+ * - It will restore R0-R14 of User mode i.e. SP(R13) and LR(R14) of User
+ * mode will be restored.
+ */
+ LDM LR, { R0-R14 }^
+ ADD LR, LR, #60 /* R0-R14 - Total 155 register, each 4 byte wide. */
+
+ RFE LR /* Restore PC and CPSR from the context. */
+
+.endm
+
+/* ----------------------------------------------------------------------------------- */
+
+/*
+ * void vPortStartFirstTask( void );
+ */
+.align 4
+.global vPortStartFirstTask
+.type vPortStartFirstTask, %function
+vPortStartFirstTask:
+ /* This function is called from System Mode to start the FreeRTOS-Kernel.
+ * As described in the portRESTORE_CONTEXT macro, portRESTORE_CONTEXT cannot
+ * be called from the System mode. We, therefore, switch to the Supervisor
+ * mode before calling portRESTORE_CONTEXT. */
+ CPS #SVC_MODE
+ portRESTORE_CONTEXT
+
+/* ----------------------------------------------------------------------------------- */
+
+.align 4
+.global FreeRTOS_SVC_Handler
+.type FreeRTOS_SVC_Handler, %function
+FreeRTOS_SVC_Handler:
+ PUSH { R11-R12 }
+
+ /* ------------------------- Caller Flash Location Check ------------------------- */
+
+ LDR R11, =__syscalls_flash_start__
+ LDR R12, =__syscalls_flash_end__
+ CMP LR, R11 /* If SVC instruction address is less than __syscalls_flash_start__, exit. */
+ BLT svcHandlerExit
+ CMP LR, R12 /* If SVC instruction address is greater than __syscalls_flash_end__, exit. */
+ BGT svcHandlerExit
+
+ /* ---------------------------- Get Caller SVC Number ---------------------------- */
+
+ MRS R11, SPSR /* LR = CPSR at the time of SVC. */
+ TST R11, #0x20 /* Check Thumb bit (5) in CPSR. */
+ LDRHNE R11, [LR, #-0x2] /* If Thumb, load halfword. */
+ BICNE R11, R11, #0xFF00 /* And extract immidiate field (i.e. SVC number). */
+ LDREQ R11, [LR, #-0x4] /* If ARM, load word. */
+ BICEQ R11, R11, #0xFF000000 /* And extract immidiate field (i.e. SVC number). */
+
+ /* --------------------------------- SVC Routing --------------------------------- */
+
+ /* If SVC Number < #NUM_SYSTEM_CALLS, go to svcSystemCallEnter. */
+ CMP R11, #NUM_SYSTEM_CALLS
+ BLT svcSystemCallEnter
+
+ /* If SVC Number == #portSVC_SYSTEM_CALL_EXIT, go to svcSystemCallExit. */
+ CMP R11, #portSVC_SYSTEM_CALL_EXIT
+ BEQ svcSystemCallExit
+
+ /* If SVC Number == #portSVC_YIELD, go to svcPortYield. */
+ CMP R11, #portSVC_YIELD
+ BEQ svcPortYield
+
+svcHandlerExit:
+ POP { R11-R12 }
+ MOVS PC, LR /* Copies the SPSR into the CPSR, performing the mode swap. */
+
+svcPortYield:
+ POP { R11-R12 }
+ portSAVE_CONTEXT
+ BL vTaskSwitchContext
+ portRESTORE_CONTEXT
+
+svcSystemCallExit:
+ LDR R11, =pxCurrentTCB /* R11 = &( pxCurrentTCB ). */
+ LDR R11, [R11] /* R11 = pxCurrentTCB. */
+ ADD R11, R11, #portSYSTEM_CALL_INFO_OFFSET /* R11 now points to xSystemCallStackInfo in TCB. */
+
+ /* Restore the user mode SP and LR. */
+ LDM R11, { R13-R14 }^
+
+ AND R12, R12, #0x0 /* R12 = 0. */
+ STR R12, [R11] /* xSystemCallStackInfo.pulTaskStackPointer = NULL. */
+ STR R12, [R11, #0x4] /* xSystemCallStackInfo.pulLinkRegisterAtSystemCallEntry = NULL. */
+
+ LDMDB R11, { R12 } /* R12 = ulTaskFlags. */
+
+ TST R12, #portTASK_IS_PRIVILEGED_FLAG
+ /* If the task is privileged, we can exit now. */
+ BNE svcHandlerExit
+ /* Otherwise, we need to switch back to User mode. */
+ MRS R12, SPSR
+ BIC R12, R12, #0x0F
+ MSR SPSR_cxsf, R12
+
+ B svcHandlerExit
+
+svcSystemCallEnter:
+ LDR R12, =uxSystemCallImplementations /* R12 = uxSystemCallImplementations. */
+ /* R12 = uxSystemCallImplementations[ R12 + ( R11 << 2 ) ].
+ * R12 now contains the address of the system call impl function. */
+ LDR R12, [R12, R11, lsl #2]
+
+ /* If R12 == NULL, exit. */
+ CMP R12, #0x0
+ BEQ svcHandlerExit
+
+ /* It is okay to clobber LR here because we do not need to return to the
+ * SVC enter location anymore. LR now contains the address of the system
+ * call impl function. */
+ MOV LR, R12
+
+ LDR R11, =pxCurrentTCB /* R11 = &( pxCurrentTCB ). */
+ LDR R11, [R11] /* R11 = pxCurrentTCB. */
+ ADD R11, R11, #portSYSTEM_CALL_INFO_OFFSET /* R11 now points to xSystemCallStackInfo in TCB. */
+
+ /* Store User mode SP and LR in xSystemCallStackInfo.pulTaskStackPointer and
+ * xSystemCallStackInfo.pulLinkRegisterAtSystemCallEntry. */
+ STM R11, { R13-R14 }^
+ ADD R11, R11, 0x8
+
+ /* Load User mode SP an LR with xSystemCallStackInfo.pulSystemCallStackPointer
+ * and xSystemCallStackInfo.pulSystemCallExitAddress. */
+ LDM R11, { R13-R14 }^
+
+ /* Change to SYS_MODE for the System Call. */
+ MRS R12, SPSR
+ ORR R12, R12, #SYS_MODE
+ MSR SPSR_cxsf, R12
+
+ B svcHandlerExit
+
+/* ----------------------------------------------------------------------------------- */
+
+/*
+ * void vPortDisableInterrupts( void );
+ */
+.align 4
+.global vPortDisableInterrupts
+.type vPortDisableInterrupts, %function
+vPortDisableInterrupts:
+ CPSID I
+ BX LR
+
+/* ----------------------------------------------------------------------------------- */
+
+/*
+ * void vPortEnableInterrupts( void );
+ */
+.align 4
+.global vPortEnableInterrupts
+.type vPortEnableInterrupts, %function
+vPortEnableInterrupts:
+ CPSIE I
+ BX LR
+
+/* ----------------------------------------------------------------------------------- */
+
+/*
+ * void vMPUSetRegion( uint32_t ulRegionNumber,
+ * uint32_t ulBaseAddress,
+ * uint32_t ulRegionSize,
+ * uint32_t ulRegionPermissions );
+ *
+ * According to the Procedure Call Standard for the ARM Architecture (AAPCS),
+ * paramters are passed in the following registers:
+ * R0 = ulRegionNumber.
+ * R1 = ulBaseAddress.
+ * R2 = ulRegionSize.
+ * R3 = ulRegionPermissions.
+ */
+.align 4
+.global vMPUSetRegion
+.type vMPUSetRegion, %function
+vMPUSetRegion:
+ AND R0, R0, #0x0F /* R0 = R0 & 0x0F. Max possible region number is 15. */
+
+ MCR p15, #0, R0, c6, c2, #0 /* MPU Region Number Register. */
+ MCR p15, #0, R1, c6, c1, #0 /* MPU Region Base Address Register. */
+ MCR p15, #0, R3, c6, c1, #4 /* MPU Region Access Control Register. */
+ MCR p15, #0, R2, c6, c1, #2 /* MPU Region Size and Enable Register. */
+
+ BX LR
+
+/* ----------------------------------------------------------------------------------- */
+
+/*
+ * void vMPUEnable( void );
+ */
+.align 4
+.global vMPUEnable
+.type vMPUEnable, %function
+vMPUEnable:
+ PUSH { R0 }
+
+ MRC p15, #0, R0, c1, c0, #0 /* R0 = System Control Register (SCTLR). */
+ ORR R0, R0, #0x1 /* R0 = R0 | 0x1. Set the M bit in SCTLR. */
+ DSB
+ MCR p15, #0, R0, c1, c0, #0 /* SCTLR = R0. */
+ ISB
+
+ POP { R0 }
+ BX LR
+
+/* ----------------------------------------------------------------------------------- */
+
+/*
+ * void vMPUDisable( void );
+ */
+.align 4
+.global vMPUDisable
+.type vMPUDisable, %function
+vMPUDisable:
+ PUSH { R0 }
+
+ MRC p15, #0, R0, c1, c0, #0 /* R0 = System Control Register (SCTLR). */
+ BIC R0, R0, #1 /* R0 = R0 & ~0x1. Clear the M bit in SCTLR. */
+ /* Wait for all pending data accesses to complete. */
+ DSB
+ MCR p15, #0, R0, c1, c0, #0 /* SCTLR = R0. */
+ /* Flush the pipeline and prefetch buffer(s) in the processor to ensure that
+ * all following instructions are fetched from cache or memory. */
+ ISB
+
+ POP { R0 }
+ BX LR
+
+/* ----------------------------------------------------------------------------------- */
+
+/*
+ * void vMPUEnableBackgroundRegion( void );
+ */
+.align 4
+.global vMPUEnableBackgroundRegion
+.type vMPUEnableBackgroundRegion, %function
+vMPUEnableBackgroundRegion:
+ PUSH { R0 }
+
+ MRC p15, #0, R0, c1, c0, #0 /* R0 = System Control Register (SCTLR). */
+ ORR R0, R0, #0x20000 /* R0 = R0 | 0x20000. Set the BR bit in SCTLR. */
+ MCR p15, #0, R0, c1, c0, #0 /* SCTLR = R0. */
+
+ POP { R0 }
+ BX LR
+
+/* ----------------------------------------------------------------------------------- */
+
+/*
+ * void vMPUDisableBackgroundRegion( void );
+ */
+.align 4
+.global vMPUDisableBackgroundRegion
+.type vMPUDisableBackgroundRegion, %function
+vMPUDisableBackgroundRegion:
+ PUSH { R0 }
+
+ MRC p15, 0, R0, c1, c0, 0 /* R0 = System Control Register (SCTLR). */
+ BIC R0, R0, #0x20000 /* R0 = R0 & ~0x20000. Clear the BR bit in SCTLR. */
+ MCR p15, 0, R0, c1, c0, 0 /* SCTLR = R0. */
+
+ POP { R0 }
+ BX LR
+
+/* ----------------------------------------------------------------------------------- */
+
+.align 4
+.global FreeRTOS_IRQ_Handler
+.type FreeRTOS_IRQ_Handler, %function
+FreeRTOS_IRQ_Handler:
+ SUB LR, LR, #4 /* Return to the interrupted instruction. */
+ SRSDB SP!, #IRQ_MODE /* Save return state (i.e. SPSR_irq and LR_irq) to the IRQ stack. */
+
+ /* Change to supervisor mode to allow reentry. It is necessary to ensure
+ * that a BL instruction within the interrupt handler code does not
+ * overwrite LR_irq. */
+ CPS #SVC_MODE
+
+ PUSH { R0-R3, R12 } /* Push AAPCS callee saved registers. */
+
+ /* Update interrupt nesting count. */
+ LDR R0, =ulPortInterruptNesting /* R0 = &( ulPortInterruptNesting ). */
+ LDR R1, [R0] /* R1 = ulPortInterruptNesting. */
+ ADD R2, R1, #1 /* R2 = R1 + 1. */
+ STR R2, [R0] /* Store the updated nesting count. */
+
+ /* Call the application provided IRQ handler. */
+ PUSH { R0-R3, LR }
+ BL vApplicationIRQHandler
+ POP { R0-R3, LR }
+
+ /* Disable IRQs incase vApplicationIRQHandler enabled them for re-entry. */
+ CPSID I
+ DSB
+ ISB
+
+ /* Restore the old interrupt nesting count. R0 holds the address of
+ * ulPortInterruptNesting and R1 holds original value of
+ * ulPortInterruptNesting. */
+ STR R1, [R0]
+
+ /* Context swtich is only performed when interrupt nesting count is 0. */
+ CMP R1, #0
+ BNE exit_without_switch
+
+ /* Check ulPortInterruptNesting to see if the interrupt requested a context
+ * switch. */
+ LDR R1, =ulPortYieldRequired /* R1 = &( ulPortYieldRequired ). */
+ LDR R0, [R1] /* R0 = ulPortYieldRequired. */
+ /* If ulPortYieldRequired != 0, goto switch_before_exit. */
+ CMP R0, #0
+ BNE switch_before_exit
+
+exit_without_switch:
+ POP { R0-R3, R12 } /* Restore AAPCS callee saved registers. */
+ CPS #IRQ_MODE
+ RFE SP!
+
+switch_before_exit:
+ /* A context swtich is to be performed. Clear ulPortYieldRequired. R1 holds
+ * the address of ulPortYieldRequired. */
+ MOV R0, #0
+ STR R0, [R1]
+
+ /* Restore AAPCS callee saved registers, SPSR_irq and LR_irq before saving
+ * the task context. */
+ POP { R0-R3, R12 }
+ CPS #IRQ_MODE
+ /* The contents of the IRQ stack at this point is the following:
+ * +----------+
+ * SP+4 | SPSR_irq |
+ * +----------+
+ * SP | LR_irq |
+ * +----------+
+ */
+ LDMIB SP!, { LR }
+ MSR SPSR_cxsf, LR
+ LDMDB SP, { LR }
+ ADD SP, SP, 0x4
+ portSAVE_CONTEXT
+
+ /* Call the function that selects the new task to execute. */
+ BLX vTaskSwitchContext
+
+ /* 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 0000000..4ca649f
--- /dev/null
+++ b/portable/GCC/ARM_CRx_MPU/portmacro.h
@@ -0,0 +1,522 @@
+/*
+ * FreeRTOS Kernel <DEVELOPMENT BRANCH>
+ * Copyright (C) 2024 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.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Include stdint for integer types of specific bit widths. */
+#include <stdint.h>
+
+/* ------------------------------ FreeRTOS Config Check ------------------------------ */
+
+#ifndef configSYSTEM_CALL_STACK_SIZE
+ #error "Define configSYSTEM_CALL_STACK_SIZE to a length, in bytes, " \
+ "to use when an unprivileged task makes a FreeRTOS Kernel call. "
+#endif /* configSYSTEM_CALL_STACK_SIZE */
+
+#if( configUSE_MPU_WRAPPERS_V1 == 1 )
+ #error This port is usable with MPU wrappers V2 only.
+#endif /* configUSE_MPU_WRAPPERS_V1 */
+
+#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 */
+
+/* ----------------------------------------------------------------------------------- */
+
+#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 given priority is ready.
+ *
+ * @ingroup Scheduler
+ *
+ * @param[in] uxPriority Priority of the task that is ready.
+ * @param[in] uxTopReadyPriority Bitmap of the ready tasks priorities.
+ */
+ #define portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority ) \
+ ( uxTopReadyPriority ) |= ( 1UL << ( uxPriority ) )
+
+ /**
+ * @brief Mark that a task of the given priority is no longer ready.
+ *
+ * @ingroup Scheduler
+ *
+ * @param[in] uxPriority Priority of the task that is no longer ready.
+ * @param[in] uxTopReadyPriority Bitmap of the ready tasks priorities.
+ */
+ #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority ) \
+ ( uxTopReadyPriority ) &= ~( 1UL << ( uxPriority ) )
+
+ /**
+ * @brief Determine the highest priority ready task's priority.
+ *
+ * @ingroup Scheduler
+ *
+ * @param[in] uxTopReadyPriority Bitmap of the ready tasks priorities.
+ * @param[in] uxTopPriority The highest priority ready task's priority.
+ */
+ #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ) \
+ ( uxTopPriority ) = ( 31UL - ulPortCountLeadingZeros( ( uxTopReadyPriority ) ) )
+
+#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
+
+/* ------------------------------ Port Type Definitions ------------------------------ */
+
+#include "portmacro_asm.h"
+
+/**
+ * @brief Critical section nesting value.
+ *
+ * @ingroup Critical Sections
+ *
+ * @note A task exits critical section and enables IRQs when its nesting count
+ * reaches this value.
+ */
+#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0x0 )
+
+/**
+ * @brief Bit in Current Program Status Register (CPSR) to indicate that CPU is
+ * in Thumb State.
+ *
+ * @ingroup Task Context
+ */
+#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
+
+/**
+ * @brief Bitmask to check if an address is of Thumb Code.
+ *
+ * @ingroup Task Context
+ */
+#define portTHUMB_MODE_ADDRESS ( 0x01UL )
+
+/**
+ * @brief Data type used to represent a stack word.
+ *
+ * @ingroup Port Interface Specifications
+ */
+typedef uint32_t StackType_t;
+
+/**
+ * @brief Signed data type equal to the data word operating size of the CPU.
+ *
+ * @ingroup Port Interface Specifications
+ */
+typedef int32_t BaseType_t;
+
+/**
+ * @brief Unsigned data type equal to the data word operating size of the CPU.
+ *
+ * @ingroup Port Interface Specifications
+ */
+typedef uint32_t UBaseType_t;
+
+/**
+ * @brief Data type used for the FreeRTOS Tick Counter.
+ *
+ * @note Using 32-bit tick type on a 32-bit architecture ensures that 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 stack pointer alignment requirements of the target CPU.
+ *
+ * @ingroup Port Interface Specifications
+ */
+#define portBYTE_ALIGNMENT 8U
+
+/**
+ * @brief Task function prototype macro as described on FreeRTOS.org.
+ *
+ * @ingroup Port Interface Specifications
+ *
+ * @note This is not required for this port but included in case common demo
+ * code uses it.
+ */
+#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 This is not required for this port but included in case common demo
+ * code uses it.
+ */
+#define portTASK_FUNCTION( vFunction, pvParameters ) \
+ void vFunction( void * pvParameters )
+
+/**
+ * @brief The no-op ARM assembly instruction.
+ *
+ * @ingroup Port Interface Specifications
+ */
+#define portNOP() __asm volatile( "NOP" )
+
+/**
+ * @brief The inline GCC label.
+ *
+ * @ingroup Port Interface Specifications
+ */
+#define portINLINE __inline
+
+/**
+ * @brief The memory access synchronization barrier.
+ *
+ * @ingroup Port Interface Specifications
+ */
+#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
+
+/**
+ * @brief Defines if the tick count can be accessed atomically.
+ *
+ * @ingroup System Clock
+ */
+#define portTICK_TYPE_IS_ATOMIC 1
+
+/**
+ * @brief The number of miliseconds between system ticks.
+ *
+ * @ingroup System Clock
+ */
+#define portTICK_PERIOD_MS ( ( TickType_t ) 1000UL / configTICK_RATE_HZ )
+
+/**
+ * @brief The largest possible delay value for any FreeRTOS API.
+ *
+ * @ingroup System Clock
+ */
+#define portMAX_DELAY ( TickType_t ) 0xFFFFFFFFUL
+
+/* ----------------------------- Port Assembly Functions ----------------------------- */
+
+/**
+ * @brief FreeRTOS Supervisor Call (SVC) Handler.
+ *
+ * @ingroup Scheduler
+ */
+void FreeRTOS_SVC_Handler( void );
+
+/**
+ * @brief FreeRTOS Interrupt Handler.
+ *
+ * @ingroup Scheduler
+ */
+void FreeRTOS_IRQ_Handler( void );
+
+/**
+ * @brief Yield the CPU.
+ *
+ * @ingroup Scheduler
+ */
+void vPortYield( void );
+
+#define portYIELD() vPortYield()
+
+/**
+ * @brief Enable interrupts.
+ *
+ * @ingroup Interrupt Management
+ */
+void vPortEnableInterrupts( void );
+
+#define portENABLE_INTERRUPTS() vPortEnableInterrupts()
+
+/**
+ * @brief Disable interrupts.
+ *
+ * @ingroup Interrupt Management
+ */
+void vPortDisableInterrupts( void );
+
+#define portDISABLE_INTERRUPTS() vPortDisableInterrupts()
+
+/**
+ * @brief Exit from a FreeRTO System Call.
+ *
+ * @ingroup Port Privilege
+ */
+void vPortSystemCallExit( void );
+
+/**
+ * @brief Start executing first task.
+ *
+ * @ingroup Scheduler
+ */
+void vPortStartFirstTask( void );
+
+/**
+ * @brief Enable the onboard MPU.
+ *
+ * @ingroup MPU Control
+ */
+void vMPUEnable( void );
+
+/**
+ * @brief Disable the onboard MPU.
+ *
+ * @ingroup MPU Control
+ */
+void vMPUDisable( void );
+
+/**
+ * @brief Enable the MPU Background Region.
+ *
+ * @ingroup MPU Control
+ */
+void vMPUEnableBackgroundRegion( void );
+
+/**
+ * @brief Disable the MPU Background Region.
+ *
+ * @ingroup MPU Control
+ */
+void vMPUDisableBackgroundRegion( void );
+
+/**
+ * @brief Set permissions for an MPU Region.
+ *
+ * @ingroup MPU Control
+ *
+ * @param[in] ulRegionNumber The MPU Region Number to set permissions for.
+ * @param[in] ulBaseAddress The base address of the MPU Region.
+ * @param[in] ulRegionSize The size of the MPU Region in bytes.
+ * @param[in] ulRegionPermissions The permissions associated with the MPU Region.
+ *
+ * @note This is an internal function and assumes that the inputs to this
+ * function are checked before calling this function.
+ */
+void vMPUSetRegion( uint32_t ulRegionNumber,
+ uint32_t ulBaseAddress,
+ uint32_t ulRegionSize,
+ uint32_t ulRegionPermissions );
+
+/* ------------------------------- Port.c Declarations ------------------------------- */
+
+/**
+ * @brief Enter critical section.
+ *
+ * @ingroup Critical Section
+ */
+void vPortEnterCritical( void );
+
+#define portENTER_CRITICAL() vPortEnterCritical()
+
+/**
+ * @brief Exit critical section.
+ *
+ * @ingroup Critical Section
+ */
+void vPortExitCritical( void );
+
+#define portEXIT_CRITICAL() vPortExitCritical()
+
+/**
+ * @brief Checks whether or not the processor is privileged.
+ *
+ * @ingroup Port Privilege
+ *
+ * @note The processor privilege level is determined by checking the
+ * mode bits [4:0] of the Current Program Status Register (CPSR).
+ *
+ * @return pdTRUE, if the processer is privileged, pdFALSE otherwise.
+ */
+BaseType_t xPortIsPrivileged( void );
+
+#define portIS_PRIVILEGED() xPortIsPrivileged()
+
+/**
+ * @brief Checks whether or not a task is privileged.
+ *
+ * @ingroup Port Privilege
+ *
+ * @note A task's privilege level is associated with the task and is different from
+ * the processor's privilege level returned by xPortIsPrivileged. For example,
+ * the processor is privileged when an unprivileged task executes a system call.
+ *
+ * @return pdTRUE if the task is privileged, pdFALSE otherwise.
+ */
+BaseType_t xPortIsTaskPrivileged( void );
+
+#define portIS_TASK_PRIVILEGED() xPortIsTaskPrivileged()
+
+/**
+ * @brief Default return address for tasks.
+ *
+ * @ingroup Task Context
+ *
+ * @note This function is used as the default return address for tasks if
+ * configTASK_RETURN_ADDRESS is not defined in FreeRTOSConfig.h.
+ */
+void prvTaskExitError( void );
+
+#ifdef configTASK_RETURN_ADDRESS
+ #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
+#else
+ #define portTASK_RETURN_ADDRESS prvTaskExitError
+#endif /* configTASK_RETURN_ADDRESS */
+
+/**
+ * @brief Returns the number of leading zeros in a 32 bit variable.
+ *
+ * @param[in] ulBitmap 32-Bit number to count leading zeros in.
+ *
+ * @return The number of leading zeros in ulBitmap.
+ */
+UBaseType_t ulPortCountLeadingZeros( UBaseType_t ulBitmap );
+
+/**
+ * @brief End the FreeRTOS scheduler.
+ *
+ * Not implemented on this port.
+ *
+ * @ingroup Scheduler
+ */
+void vPortEndScheduler( void );
+
+/* --------------------------------- MPU Definitions --------------------------------- */
+
+/**
+ * @brief Mark that this port utilizes the onboard ARM MPU.
+ *
+ * @ingroup MPU Control
+ */
+#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 A privileged task is created 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 Size of an Access Control List (ACL) entry in bits.
+ */
+#define portACL_ENTRY_SIZE_BITS ( 32UL )
+
+/**
+ * @brief Structure to hold the MPU Register Values.
+ *
+ * @struct xMPU_REGION_REGISTERS
+ *
+ * @ingroup MPU Control
+ *
+ * @note The ordering of this struct MUST be in sync with the ordering in
+ * portRESTORE_CONTEXT.
+ */
+typedef struct MPU_REGION_REGISTERS
+{
+ uint32_t ulRegionSize; /* Information for MPU Region Size and Enable Register. */
+ uint32_t ulRegionAttribute; /* Information for MPU Region Access Control Register. */
+ uint32_t ulRegionBaseAddress; /* Information for MPU Region Base Address Register. */
+} xMPU_REGION_REGISTERS;
+
+/**
+ * @brief Structure to hold per-task System Call Stack information.
+ *
+ * @struct xSYSTEM_CALL_STACK_INFO
+ *
+ * @ingroup Port Privilege
+ *
+ * @note The ordering of this structure MUST be in sync with the assembly code
+ * of the port.
+ */
+typedef struct SYSTEM_CALL_STACK_INFO
+{
+ uint32_t * pulTaskStackPointer; /**< Stack Pointer of the task when it made a FreeRTOS System Call. */
+ uint32_t * pulLinkRegisterAtSystemCallEntry; /**< Link Register of the task when it made a FreeRTOS System Call. */
+ uint32_t * pulSystemCallStackPointer; /**< Stack Pointer to use for executing a FreeRTOS System Call. */
+ uint32_t * pulSystemCallExitAddress; /**< System call exit address. */
+ uint32_t ulSystemCallStackBuffer[ configSYSTEM_CALL_STACK_SIZE ]; /**< Buffer to be used as stack when performing a FreeRTOS System Call. */
+} 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 The ordering of this structure MUST be in sync with the assembly code
+ * of the port.
+ */
+typedef struct MPU_SETTINGS
+{
+ xMPU_REGION_REGISTERS xRegion[ portTOTAL_NUM_REGIONS_IN_TCB ];
+ uint32_t ulTaskFlags;
+ xSYSTEM_CALL_STACK_INFO xSystemCallStackInfo;
+ uint32_t ulContext[ CONTEXT_SIZE ]; /**< Buffer used to store task context. */
+
+ #if( configENABLE_ACCESS_CONTROL_LIST == 1 )
+ uint32_t ulAccessControlList[ ( configPROTECTED_KERNEL_OBJECT_POOL_SIZE
+ / portACL_ENTRY_SIZE_BITS )
+ + 1UL ];
+ #endif
+} 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 0000000..a113ac0
--- /dev/null
+++ b/portable/GCC/ARM_CRx_MPU/portmacro_asm.h
@@ -0,0 +1,279 @@
+/*
+ * FreeRTOS Kernel <DEVELOPMENT BRANCH>
+ * Copyright (C) 2024 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"
+#elif( configTOTAL_MPU_REGIONS == 12 )
+ #define portMPU_TOTAL_REGIONS ( 12UL )
+#elif( configTOTAL_MPU_REGIONS == 16 )
+ #define portMPU_TOTAL_REGIONS ( 16UL )
+#else
+ #error "Set configTOTAL_MPU_REGIONS to the number of MPU regions in FreeRTOSConfig.h"
+#endif /* configTOTAL_MPU_REGIONS */
+
+/*
+ * The application write can disable Floating Point Unit (FPU) support by
+ * setting configENABLE_FPU to 0. Floating point context stored in TCB
+ * comprises of 32 floating point registers (D0-D31) and FPSCR register.
+ * Disabling FPU, therefore, reduces the per-task RAM usage by
+ * ( 32 + 1 ) * 4 = 132 bytes per task.
+ *
+ * BE CAREFUL DISABLING THIS: Certain standard library APIs try to optimize
+ * themselves by using the floating point registers. If the FPU support is
+ * disabled, the use of such APIs may result in memory corruption.
+ */
+#ifndef configENABLE_FPU
+ #define configENABLE_FPU 1
+#endif /* configENABLE_FPU */
+
+#define portENABLE_FPU configENABLE_FPU
+
+/* On the ArmV7-R Architecture the Operating mode of the Processor is set
+ * using the Current Program Status Register (CPSR) Mode bits, [4:0]. The only
+ * unprivileged mode 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 bits for various processor modes.
+ *
+ * @ingroup Port Privilege
+ */
+#define USER_MODE 0x10U
+#define FIQ_MODE 0x11U
+#define IRQ_MODE 0x12U
+#define SVC_MODE 0x13U
+#define MON_MODE 0x16U
+#define ABT_MODE 0x17U
+#define HYP_MODE 0x1AU
+#define UND_MODE 0x1BU
+#define SYS_MODE 0x1FU
+
+/**
+ * @brief Flag used to mark that a FreeRTOS Task is privileged.
+ *
+ * @ingroup Port Privilege
+ */
+#define portTASK_IS_PRIVILEGED_FLAG ( 1UL << 1UL )
+
+/**
+ * @brief SVC numbers for various scheduler operations.
+ *
+ * @ingroup Scheduler
+ *
+ * @note These value must not be used in mpu_syscall_numbers.h.
+ */
+#define portSVC_YIELD 0x0100U
+#define portSVC_SYSTEM_CALL_EXIT 0x0104U
+
+/**
+ * @brief Macros required to manipulate MPU.
+ *
+ * Further information about MPU 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 disable settings. This information is encoded in the MPU
+ * Region Size and Enable Register. */
+#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 )
+
+/* Default MPU regions. */
+#define portFIRST_CONFIGURABLE_REGION ( 0 )
+#define portLAST_CONFIGURABLE_REGION ( portMPU_TOTAL_REGIONS - 5UL )
+#define portSTACK_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. This information is encoded in the MPU Region Size and
+ * Enable Register. */
+#define portMPU_REGION_SIZE_32B ( 0x04UL << 1UL )
+#define portMPU_REGION_SIZE_64B ( 0x05UL << 1UL )
+#define portMPU_REGION_SIZE_128B ( 0x06UL << 1UL )
+#define portMPU_REGION_SIZE_256B ( 0x07UL << 1UL )
+#define portMPU_REGION_SIZE_512B ( 0x08UL << 1UL )
+#define portMPU_REGION_SIZE_1KB ( 0x09UL << 1UL )
+#define portMPU_REGION_SIZE_2KB ( 0x0AUL << 1UL )
+#define portMPU_REGION_SIZE_4KB ( 0x0BUL << 1UL )
+#define portMPU_REGION_SIZE_8KB ( 0x0CUL << 1UL )
+#define portMPU_REGION_SIZE_16KB ( 0x0DUL << 1UL )
+#define portMPU_REGION_SIZE_32KB ( 0x0EUL << 1UL )
+#define portMPU_REGION_SIZE_64KB ( 0x0FUL << 1UL )
+#define portMPU_REGION_SIZE_128KB ( 0x10UL << 1UL )
+#define portMPU_REGION_SIZE_256KB ( 0x11UL << 1UL )
+#define portMPU_REGION_SIZE_512KB ( 0x12UL << 1UL )
+#define portMPU_REGION_SIZE_1MB ( 0x13UL << 1UL )
+#define portMPU_REGION_SIZE_2MB ( 0x14UL << 1UL )
+#define portMPU_REGION_SIZE_4MB ( 0x15UL << 1UL )
+#define portMPU_REGION_SIZE_8MB ( 0x16UL << 1UL )
+#define portMPU_REGION_SIZE_16MB ( 0x17UL << 1UL )
+#define portMPU_REGION_SIZE_32MB ( 0x18UL << 1UL )
+#define portMPU_REGION_SIZE_64MB ( 0x19UL << 1UL )
+#define portMPU_REGION_SIZE_128MB ( 0x1AUL << 1UL )
+#define portMPU_REGION_SIZE_256MB ( 0x1BUL << 1UL )
+#define portMPU_REGION_SIZE_512MB ( 0x1CUL << 1UL )
+#define portMPU_REGION_SIZE_1GB ( 0x1DUL << 1UL )
+#define portMPU_REGION_SIZE_2GB ( 0x1EUL << 1UL )
+#define portMPU_REGION_SIZE_4GB ( 0x1FUL << 1UL )
+
+/* MPU memory types. This information is encoded in the TEX, S, C and B bits
+ * of the MPU Region Access Control Register. */
+#define portMPU_REGION_STRONGLY_ORDERED_SHAREABLE ( 0x00UL ) /* TEX=000, S=NA, C=0, B=0. */
+#define portMPU_REGION_DEVICE_SHAREABLE ( 0x01UL ) /* TEX=000, S=NA, C=0, B=1. */
+#define portMPU_REGION_NORMAL_OIWTNOWA_NONSHARED ( 0x02UL ) /* TEX=000, S=0, C=1, B=0. */
+#define portMPU_REGION_NORMAL_OIWTNOWA_SHARED ( 0x06UL ) /* TEX=000, S=1, C=1, B=0. */
+#define portMPU_REGION_NORMAL_OIWBNOWA_NONSHARED ( 0x03UL ) /* TEX=000, S=0, C=1, B=1. */
+#define portMPU_REGION_NORMAL_OIWBNOWA_SHARED ( 0x07UL ) /* TEX=000, S=1, C=1, B=1. */
+#define portMPU_REGION_NORMAL_OINC_NONSHARED ( 0x08UL ) /* TEX=001, S=0, C=0, B=0. */
+#define portMPU_REGION_NORMAL_OINC_SHARED ( 0x0CUL ) /* TEX=001, S=1, C=0, B=0. */
+#define portMPU_REGION_NORMAL_OIWBWA_NONSHARED ( 0x0BUL ) /* TEX=001, S=0, C=1, B=1. */
+#define portMPU_REGION_NORMAL_OIWBWA_SHARED ( 0x0FUL ) /* TEX=001, S=1, C=1, B=1. */
+#define portMPU_REGION_DEVICE_NONSHAREABLE ( 0x10UL ) /* TEX=010, S=NA, C=0, B=0. */
+
+/* MPU access permissions. This information is encoded in the XN and AP bits of
+ * the MPU Region Access Control Register. */
+#define portMPU_REGION_AP_BITMASK ( 0x07UL << 8UL )
+#define portMPU_REGION_XN_BITMASK ( 0x01UL << 12UL )
+
+#define portMPU_REGION_PRIV_NA_USER_NA ( 0x00UL << 8UL )
+#define portMPU_REGION_PRIV_NA_USER_NA_EXEC ( portMPU_REGION_PRIV_NA_USER_NA ) /* Priv: X, Unpriv: X. */
+#define portMPU_REGION_PRIV_NA_USER_NA_NOEXEC ( portMPU_REGION_PRIV_NA_USER_NA | \
+ portMPU_REGION_XN_BITMASK ) /* Priv: No Access, Unpriv: No Access. */
+
+#define portMPU_REGION_PRIV_RW_USER_NA ( 0x01UL << 8UL )
+#define portMPU_REGION_PRIV_RW_USER_NA_EXEC ( portMPU_REGION_PRIV_RW_USER_NA ) /* Priv: RWX, Unpriv: X. */
+#define portMPU_REGION_PRIV_RW_USER_NA_NOEXEC ( portMPU_REGION_PRIV_RW_USER_NA | \
+ portMPU_REGION_XN_BITMASK ) /* Priv: RW, Unpriv: No access. */
+
+#define portMPU_REGION_PRIV_RW_USER_RO ( 0x02UL << 8UL )
+#define portMPU_REGION_PRIV_RW_USER_RO_EXEC ( portMPU_REGION_PRIV_RW_USER_RO ) /* Priv: RWX, Unpriv: RX. */
+#define portMPU_REGION_PRIV_RW_USER_RO_NOEXEC ( portMPU_REGION_PRIV_RW_USER_RO | \
+ portMPU_REGION_XN_BITMASK ) /* Priv: RW, Unpriv: R. */
+
+#define portMPU_REGION_PRIV_RW_USER_RW ( 0x03UL << 8UL )
+#define portMPU_REGION_PRIV_RW_USER_RW_EXEC ( portMPU_REGION_PRIV_RW_USER_RW ) /* Priv: RWX, Unpriv: RWX. */
+#define portMPU_REGION_PRIV_RW_USER_RW_NOEXEC ( portMPU_REGION_PRIV_RW_USER_RW | \
+ portMPU_REGION_XN_BITMASK ) /* Priv: RW, Unpriv: RW. */
+
+#define portMPU_REGION_PRIV_RO_USER_NA ( 0x05UL << 8UL )
+#define portMPU_REGION_PRIV_RO_USER_NA_EXEC ( portMPU_REGION_PRIV_RO_USER_NA ) /* Priv: RX, Unpriv: X. */
+#define portMPU_REGION_PRIV_RO_USER_NA_NOEXEC ( portMPU_REGION_PRIV_RO_USER_NA | \
+ portMPU_REGION_XN_BITMASK ) /* Priv: R, Unpriv: No access. */
+
+#define portMPU_REGION_PRIV_RO_USER_RO ( 0x06UL << 8UL )
+#define portMPU_REGION_PRIV_RO_USER_RO_EXEC ( portMPU_REGION_PRIV_RO_USER_RO ) /* Priv: RX, Unpriv: RX. */
+#define portMPU_REGION_PRIV_RO_USER_RO_NOEXEC ( portMPU_REGION_PRIV_RO_USER_RO | \
+ portMPU_REGION_XN_BITMASK ) /* Priv: R, Unpriv: R. */
+
+/* MPU region management. */
+#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 12UL )
+#define portMPU_REGION_ENABLE ( 0x01UL )
+
+/**
+ * @brief The size (in words) of a task context.
+ *
+ * An array of this size is allocated in TCB where a task's context is saved
+ * when it is switched out.
+ *
+ * Information about Floating Point Unit (FPU):
+ * 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
+ *
+ */
+
+#if( portENABLE_FPU == 1 )
+ /*
+ * +-------------------+-------+----------+--------+----------+----------+----------+------+
+ * | ulCriticalNesting | FPSCR | S0-S31 | R0-R12 | SP (R13) | LR (R14) | PC (R15) | CPSR |
+ * +-------------------+-------+----------+--------+----------+----------+----------+------+
+ *
+ * <------------------><------><---------><--------><---------><--------><----------><----->
+ * 1 1 32 13 1 1 1 1
+ */
+ #define CONTEXT_SIZE 51U
+#else
+ /*
+ * +-------------------+--------+----------+----------+----------+------+
+ * | ulCriticalNesting | R0-R12 | SP (R13) | LR (R14) | PC (R15) | CPSR |
+ * +-------------------+--------+----------+----------+----------+------+
+ *
+ * <------------------><--------><---------><--------><----------><----->
+ * 1 13 1 1 1 1
+ */
+ #define CONTEXT_SIZE 18U
+#endif /* CONTEXT_SIZE */
+
+/**
+ * @brief Offset of xSystemCallStackInfo from the start of a TCB.
+ */
+#define portSYSTEM_CALL_INFO_OFFSET \
+ ( ( 1U /* pxTopOfStack. */ + \
+ ( portTOTAL_NUM_REGIONS_IN_TCB * 3U ) + \
+ 1U /* ulTaskFlags. */ \
+ ) * 4U )
+
+#ifdef __cplusplus
+} /* extern C */
+#endif
+
+#endif /* PORTMACRO_ASM_H */