Add ARM Cortex-M52 port support

Fixes #1305
- Add ARM_CM52 and ARM_CM52_NTZ port implementations for GCC and IAR compilers
This commit is contained in:
JidongMei 2025-11-13 17:29:38 +08:00
parent 439af33c52
commit f8091f70ba
48 changed files with 24103 additions and 19 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,621 @@
/*
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates
* <open-source-office@arm.com>
*
* 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 ensures that PRIVILEGED_FUNCTION
* is defined correctly and privileged functions are placed in correct sections. */
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
/* Portasm includes. */
#include "portasm.h"
/* System call numbers includes. */
#include "mpu_syscall_numbers.h"
/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE is needed to be defined only for the
* header files. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
#if ( configENABLE_MPU == 1 )
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{
__asm volatile
(
" .syntax unified \n"
" \n"
" program_mpu_first_task: \n"
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r0, [r3] \n" /* r0 = pxCurrentTCB. */
" \n"
" dmb \n" /* Complete outstanding transfers before disabling MPU. */
" ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
" bic r2, #1 \n" /* r2 = r2 & ~1 i.e. Clear the bit 0 in r2. */
" str r2, [r1] \n" /* Disable MPU. */
" \n"
" adds r0, #4 \n" /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */
" ldr r1, [r0] \n" /* r1 = *r0 i.e. r1 = MAIR0. */
" ldr r2, =0xe000edc0 \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r1, [r2] \n" /* Program MAIR0. */
" \n"
" adds r0, #4 \n" /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */
" ldr r1, =0xe000ed98 \n" /* r1 = 0xe000ed98 [Location of RNR]. */
" ldr r2, =0xe000ed9c \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
" \n"
" movs r3, #4 \n" /* r3 = 4. */
" str r3, [r1] \n" /* Program RNR = 4. */
" ldmia r0!, {r4-r11} \n" /* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
" \n"
#if ( configTOTAL_MPU_REGIONS == 16 )
" movs r3, #8 \n" /* r3 = 8. */
" str r3, [r1] \n" /* Program RNR = 8. */
" ldmia r0!, {r4-r11} \n" /* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
" movs r3, #12 \n" /* r3 = 12. */
" str r3, [r1] \n" /* Program RNR = 12. */
" ldmia r0!, {r4-r11} \n" /* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
#endif /* configTOTAL_MPU_REGIONS == 16 */
" \n"
" ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
" orr r2, #1 \n" /* r2 = r1 | 1 i.e. Set the bit 0 in r2. */
" str r2, [r1] \n" /* Enable MPU. */
" dsb \n" /* Force memory writes before continuing. */
" \n"
" restore_context_first_task: \n"
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n" /* r1 = pxCurrentTCB.*/
" ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */
" \n"
" restore_special_regs_first_task: \n"
#if ( configENABLE_PAC == 1 )
" ldmdb r2!, {r3-r6} \n" /* Read task's dedicated PAC key from the task's context. */
" msr PAC_KEY_P_0, r3 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_1, r4 \n"
" msr PAC_KEY_P_2, r5 \n"
" msr PAC_KEY_P_3, r6 \n"
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
" msr psp, r3 \n"
" msr psplim, r4 \n"
" msr control, r5 \n"
" ldr r4, =xSecureContext \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
" str r0, [r4] \n" /* Restore xSecureContext. */
" \n"
" restore_general_regs_first_task: \n"
" ldmdb r2!, {r4-r11} \n" /* r4-r11 contain hardware saved context. */
" stmia r3!, {r4-r11} \n" /* Copy the hardware saved context on the task stack. */
" ldmdb r2!, {r4-r11} \n" /* r4-r11 restored. */
" \n"
" restore_context_done_first_task: \n"
" str r2, [r1] \n" /* Save the location where the context should be saved next as the first member of TCB. */
" mov r0, #0 \n"
" msr basepri, r0 \n" /* Ensure that interrupts are enabled when the first task starts. */
" bx lr \n"
);
}
#else /* configENABLE_MPU */
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{
__asm volatile
(
" .syntax unified \n"
" \n"
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r3, [r2] \n" /* Read pxCurrentTCB. */
" ldr r0, [r3] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n"
#if ( configENABLE_PAC == 1 )
" ldmia r0!, {r1-r4} \n" /* Read task's dedicated PAC key from stack. */
" msr PAC_KEY_P_3, r1 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_2, r2 \n"
" msr PAC_KEY_P_1, r3 \n"
" msr PAC_KEY_P_0, r4 \n"
" clrm {r1-r4} \n" /* Clear r1-r4. */
#endif /* configENABLE_PAC */
" \n"
" ldm r0!, {r1-r3} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
" ldr r4, =xSecureContext \n"
" str r1, [r4] \n" /* Set xSecureContext to this task's value for the same. */
" msr psplim, r2 \n" /* Set this task's PSPLIM value. */
" mrs r1, control \n" /* Obtain current control register value. */
" orrs r1, r1, #2 \n" /* r1 = r1 | 0x2 - Set the second bit to use the program stack pointer (PSP). */
" msr control, r1 \n" /* Write back the new control register value. */
" adds r0, #32 \n" /* Discard everything up to r0. */
" msr psp, r0 \n" /* This is now the new top of stack to use in the task. */
" isb \n"
" mov r0, #0 \n"
" msr basepri, r0 \n" /* Ensure that interrupts are enabled when the first task starts. */
" bx r3 \n" /* Finally, branch to EXC_RETURN. */
);
}
#endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/
BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
{
__asm volatile
(
" .syntax unified \n"
" \n"
" mrs r0, control \n" /* r0 = CONTROL. */
" tst r0, #1 \n" /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
" ite ne \n"
" movne r0, #0 \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
" moveq r0, #1 \n" /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
" bx lr \n" /* Return. */
::: "r0", "memory"
);
}
/*-----------------------------------------------------------*/
void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{
__asm volatile
(
" .syntax unified \n"
" \n"
" mrs r0, control \n" /* Read the CONTROL register. */
" bic r0, #1 \n" /* Clear the bit 0. */
" msr control, r0 \n" /* Write back the new CONTROL value. */
" bx lr \n" /* Return to the caller. */
::: "r0", "memory"
);
}
/*-----------------------------------------------------------*/
void vResetPrivilege( void ) /* __attribute__ (( naked )) */
{
__asm volatile
(
" .syntax unified \n"
" \n"
" mrs r0, control \n" /* r0 = CONTROL. */
" orr r0, #1 \n" /* r0 = r0 | 1. */
" msr control, r0 \n" /* CONTROL = r0. */
" bx lr \n" /* Return to the caller. */
::: "r0", "memory"
);
}
/*-----------------------------------------------------------*/
void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{
__asm volatile
(
" .syntax unified \n"
" \n"
" ldr r0, =0xe000ed08 \n" /* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n" /* Read the VTOR register which gives the address of vector table. */
" ldr r0, [r0] \n" /* The first entry in vector table is stack pointer. */
" msr msp, r0 \n" /* Set the MSP back to the start of the stack. */
" cpsie i \n" /* Globally enable interrupts. */
" cpsie f \n"
" dsb \n"
" isb \n"
" svc %0 \n" /* System call to start the first task. */
" nop \n"
::"i" ( portSVC_START_SCHEDULER ) : "memory"
);
}
/*-----------------------------------------------------------*/
uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
{
__asm volatile
(
" .syntax unified \n"
" \n"
" mrs r0, basepri \n" /* r0 = basepri. Return original basepri value. */
" mov r1, %0 \n" /* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" msr basepri, r1 \n" /* Disable interrupts up to configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" dsb \n"
" isb \n"
" bx lr \n" /* Return. */
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
);
}
/*-----------------------------------------------------------*/
void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
{
__asm volatile
(
" .syntax unified \n"
" \n"
" msr basepri, r0 \n" /* basepri = ulMask. */
" dsb \n"
" isb \n"
" bx lr \n" /* Return. */
::: "memory"
);
}
/*-----------------------------------------------------------*/
#if ( configENABLE_MPU == 1 )
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{
__asm volatile
(
" .syntax unified \n"
" .extern SecureContext_SaveContext \n"
" .extern SecureContext_LoadContext \n"
" \n"
" ldr r3, =xSecureContext \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
" ldr r0, [r3] \n" /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n" /* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */
" ldr r2, [r1] \n" /* r2 = Location in TCB where the context should be saved. */
" \n"
" cbz r0, save_ns_context \n" /* No secure context to save. */
" save_s_context: \n"
" push {r0-r2, lr} \n"
" bl SecureContext_SaveContext \n" /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r0-r2, lr} \n"
" \n"
" save_ns_context: \n"
" mov r3, lr \n" /* r3 = LR (EXC_RETURN). */
" lsls r3, r3, #25 \n" /* r3 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
" bmi save_special_regs \n" /* r3 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used to store the stack frame. */
" \n"
" save_general_regs: \n"
" mrs r3, psp \n"
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" add r3, r3, #0x20 \n" /* Move r3 to location where s0 is saved. */
" tst lr, #0x10 \n"
" ittt eq \n"
" vstmiaeq r2!, {s16-s31} \n" /* Store s16-s31. */
" vldmiaeq r3, {s0-s16} \n" /* Copy hardware saved FP context into s0-s16. */
" vstmiaeq r2!, {s0-s16} \n" /* Store hardware saved FP context. */
" sub r3, r3, #0x20 \n" /* Set r3 back to the location of hardware saved context. */
#endif /* configENABLE_FPU || configENABLE_MVE */
" stmia r2!, {r4-r11} \n" /* Store r4-r11. */
" ldmia r3, {r4-r11} \n" /* Copy the hardware saved context into r4-r11. */
" stmia r2!, {r4-r11} \n" /* Store the hardware saved context. */
" \n"
" save_special_regs: \n"
" mrs r3, psp \n" /* r3 = PSP. */
" mrs r4, psplim \n" /* r4 = PSPLIM. */
" mrs r5, control \n" /* r5 = CONTROL. */
" stmia r2!, {r0, r3-r5, lr} \n" /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
#if ( configENABLE_PAC == 1 )
" mrs r3, PAC_KEY_P_0 \n" /* Read task's dedicated PAC key from the PAC key registers. */
" mrs r4, PAC_KEY_P_1 \n"
" mrs r5, PAC_KEY_P_2 \n"
" mrs r6, PAC_KEY_P_3 \n"
" stmia r2!, {r3-r6} \n" /* Store the task's dedicated PAC key on the task's context. */
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" str r2, [r1] \n" /* Save the location from where the context should be restored as the first member of TCB. */
" \n"
" select_next_task: \n"
" mov r0, %0 \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
" msr basepri, r0 \n" /* Disable interrupts up to configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" dsb \n"
" isb \n"
" bl vTaskSwitchContext \n"
" mov r0, #0 \n" /* r0 = 0. */
" msr basepri, r0 \n" /* Enable interrupts. */
" \n"
" program_mpu: \n"
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r0, [r3] \n" /* r0 = pxCurrentTCB.*/
" \n"
" dmb \n" /* Complete outstanding transfers before disabling MPU. */
" ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
" bic r2, #1 \n" /* r2 = r2 & ~1 i.e. Clear the bit 0 in r2. */
" str r2, [r1] \n" /* Disable MPU. */
" \n"
" adds r0, #4 \n" /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */
" ldr r1, [r0] \n" /* r1 = *r0 i.e. r1 = MAIR0. */
" ldr r2, =0xe000edc0 \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r1, [r2] \n" /* Program MAIR0. */
" \n"
" adds r0, #4 \n" /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */
" ldr r1, =0xe000ed98 \n" /* r1 = 0xe000ed98 [Location of RNR]. */
" ldr r2, =0xe000ed9c \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
" \n"
" movs r3, #4 \n" /* r3 = 4. */
" str r3, [r1] \n" /* Program RNR = 4. */
" ldmia r0!, {r4-r11} \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r2, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
" \n"
#if ( configTOTAL_MPU_REGIONS == 16 )
" movs r3, #8 \n" /* r3 = 8. */
" str r3, [r1] \n" /* Program RNR = 8. */
" ldmia r0!, {r4-r11} \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r2, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
" movs r3, #12 \n" /* r3 = 12. */
" str r3, [r1] \n" /* Program RNR = 12. */
" ldmia r0!, {r4-r11} \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r2, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
#endif /* configTOTAL_MPU_REGIONS == 16 */
" \n"
" ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
" orr r2, #1 \n" /* r2 = r2 | 1 i.e. Set the bit 0 in r2. */
" str r2, [r1] \n" /* Enable MPU. */
" dsb \n" /* Force memory writes before continuing. */
" \n"
" restore_context: \n"
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n" /* r1 = pxCurrentTCB.*/
" ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */
" \n"
" restore_special_regs: \n"
#if ( configENABLE_PAC == 1 )
" ldmdb r2!, {r3-r6} \n" /* Read task's dedicated PAC key from the task's context. */
" msr PAC_KEY_P_0, r3 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_1, r4 \n"
" msr PAC_KEY_P_2, r5 \n"
" msr PAC_KEY_P_3, r6 \n"
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
" msr psp, r3 \n"
" msr psplim, r4 \n"
" msr control, r5 \n"
" ldr r4, =xSecureContext \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
" str r0, [r4] \n" /* Restore xSecureContext. */
" cbz r0, restore_ns_context \n" /* No secure context to restore. */
" \n"
" restore_s_context: \n"
" push {r1-r3, lr} \n"
" bl SecureContext_LoadContext \n" /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r1-r3, lr} \n"
" \n"
" restore_ns_context: \n"
" mov r0, lr \n" /* r0 = LR (EXC_RETURN). */
" lsls r0, r0, #25 \n" /* r0 = r0 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
" bmi restore_context_done \n" /* r0 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used to store the stack frame. */
" \n"
" restore_general_regs: \n"
" ldmdb r2!, {r4-r11} \n" /* r4-r11 contain hardware saved context. */
" stmia r3!, {r4-r11} \n" /* Copy the hardware saved context on the task stack. */
" ldmdb r2!, {r4-r11} \n" /* r4-r11 restored. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst lr, #0x10 \n"
" ittt eq \n"
" vldmdbeq r2!, {s0-s16} \n" /* s0-s16 contain hardware saved FP context. */
" vstmiaeq r3!, {s0-s16} \n" /* Copy hardware saved FP context on the task stack. */
" vldmdbeq r2!, {s16-s31} \n" /* Restore s16-s31. */
#endif /* configENABLE_FPU || configENABLE_MVE */
" \n"
" restore_context_done: \n"
" str r2, [r1] \n" /* Save the location where the context should be saved next as the first member of TCB. */
" bx lr \n"
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
);
}
#else /* configENABLE_MPU */
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{
__asm volatile
(
" .syntax unified \n"
" .extern SecureContext_SaveContext \n"
" .extern SecureContext_LoadContext \n"
" \n"
" ldr r3, =xSecureContext \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
" ldr r0, [r3] \n" /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n" /* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */
" mrs r2, psp \n" /* Read PSP in r2. */
" \n"
" cbz r0, save_ns_context \n" /* No secure context to save. */
" save_s_context: \n"
" push {r0-r2, lr} \n"
" bl SecureContext_SaveContext \n" /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r0-r2, lr} \n"
" \n"
" save_ns_context: \n"
" mov r3, lr \n" /* r3 = LR (EXC_RETURN). */
" lsls r3, r3, #25 \n" /* r3 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
" bmi save_special_regs \n" /* If r3 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used. */
" \n"
" save_general_regs: \n"
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n"
" vstmdbeq r2!, {s16-s31} \n" /* Store the additional FP context registers which are not saved automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */
" stmdb r2!, {r4-r11} \n" /* Store the registers that are not saved automatically. */
" \n"
" save_special_regs: \n"
" mrs r3, psplim \n" /* r3 = PSPLIM. */
" stmdb r2!, {r0, r3, lr} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */
#if ( configENABLE_PAC == 1 )
" mrs r3, PAC_KEY_P_3 \n" /* Read task's dedicated PAC key from the PAC key registers. */
" mrs r4, PAC_KEY_P_2 \n"
" mrs r5, PAC_KEY_P_1 \n"
" mrs r6, PAC_KEY_P_0 \n"
" stmdb r2!, {r3-r6} \n" /* Store the task's dedicated PAC key on the stack. */
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" \n"
" str r2, [r1] \n" /* Save the new top of stack in TCB. */
" \n"
" select_next_task: \n"
" mov r0, %0 \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
" msr basepri, r0 \n" /* Disable interrupts up to configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" dsb \n"
" isb \n"
" bl vTaskSwitchContext \n"
" mov r0, #0 \n" /* r0 = 0. */
" msr basepri, r0 \n" /* Enable interrupts. */
" \n"
" restore_context: \n"
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n" /* Read pxCurrentTCB. */
" ldr r2, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
" \n"
" restore_special_regs: \n"
#if ( configENABLE_PAC == 1 )
" ldmia r2!, {r3-r6} \n" /* Read task's dedicated PAC key from stack. */
" msr PAC_KEY_P_3, r3 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_2, r4 \n"
" msr PAC_KEY_P_1, r5 \n"
" msr PAC_KEY_P_0, r6 \n"
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" ldmia r2!, {r0, r3, lr} \n" /* Read from stack - r0 = xSecureContext, r3 = PSPLIM and LR restored. */
" msr psplim, r3 \n" /* Restore the PSPLIM register value for the task. */
" ldr r3, =xSecureContext \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
" str r0, [r3] \n" /* Restore the task's xSecureContext. */
" cbz r0, restore_ns_context \n" /* If there is no secure context for the task, restore the non-secure context. */
" \n"
" restore_s_context: \n"
" push {r1-r3, lr} \n"
" bl SecureContext_LoadContext \n" /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r1-r3, lr} \n"
" \n"
" restore_ns_context: \n"
" mov r0, lr \n" /* r0 = LR (EXC_RETURN). */
" lsls r0, r0, #25 \n" /* r0 = r0 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
" bmi restore_context_done \n" /* r0 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used to store the stack frame. */
" \n"
" restore_general_regs: \n"
" ldmia r2!, {r4-r11} \n" /* Restore the registers that are not automatically restored. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n"
" vldmiaeq r2!, {s16-s31} \n" /* Restore the additional FP context registers which are not restored automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */
" \n"
" restore_context_done: \n"
" msr psp, r2 \n" /* Remember the new top of stack for the task. */
" bx lr \n"
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
);
}
#endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{
__asm volatile
(
".syntax unified \n"
".extern vPortSVCHandler_C \n"
".extern vSystemCallEnter \n"
".extern vSystemCallExit \n"
" \n"
"tst lr, #4 \n"
"ite eq \n"
"mrseq r0, msp \n"
"mrsne r0, psp \n"
" \n"
"ldr r1, [r0, #24] \n"
"ldrb r2, [r1, #-2] \n"
"cmp r2, %0 \n"
"blt syscall_enter \n"
"cmp r2, %1 \n"
"beq syscall_exit \n"
"b vPortSVCHandler_C \n"
" \n"
"syscall_enter: \n"
" mov r1, lr \n"
" b vSystemCallEnter \n"
" \n"
"syscall_exit: \n"
" mov r1, lr \n"
" b vSystemCallExit \n"
" \n"
: /* No outputs. */
: "i" ( NUM_SYSTEM_CALLS ), "i" ( portSVC_SYSTEM_CALL_EXIT )
: "r0", "r1", "r2", "memory"
);
}
#else /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{
__asm volatile
(
" .syntax unified \n"
" \n"
" tst lr, #4 \n"
" ite eq \n"
" mrseq r0, msp \n"
" mrsne r0, psp \n"
" ldr r1, =vPortSVCHandler_C \n"
" bx r1 \n"
);
}
#endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
/*-----------------------------------------------------------*/
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (( naked )) */
{
__asm volatile
(
" .syntax unified \n"
" \n"
" svc %0 \n" /* Secure context is allocated in the supervisor call. */
" bx lr \n" /* Return. */
::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"
);
}
/*-----------------------------------------------------------*/
void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{
__asm volatile
(
" .syntax unified \n"
" \n"
" ldr r2, [r0] \n" /* The first item in the TCB is the top of the stack. */
" ldr r1, [r2] \n" /* The first item on the stack is the task's xSecureContext. */
" cmp r1, #0 \n" /* Raise svc if task's xSecureContext is not NULL. */
" it ne \n"
" svcne %0 \n" /* Secure context is freed in the supervisor call. */
" bx lr \n" /* Return. */
::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
);
}
/*-----------------------------------------------------------*/

View file

@ -0,0 +1,114 @@
/*
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
#ifndef __PORT_ASM_H__
#define __PORT_ASM_H__
/* Scheduler includes. */
#include "FreeRTOS.h"
/* MPU wrappers includes. */
#include "mpu_wrappers.h"
/**
* @brief Restore the context of the first task so that the first task starts
* executing.
*/
void vRestoreContextOfFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/**
* @brief Checks whether or not the processor is privileged.
*
* @return 1 if the processor is already privileged, 0 otherwise.
*/
BaseType_t xIsPrivileged( void ) __attribute__( ( naked ) );
/**
* @brief Raises the privilege level by clearing the bit 0 of the CONTROL
* register.
*
* @note This is a privileged function and should only be called from the kernel
* code.
*
* Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
* Bit[0] = 0 --> The processor is running privileged
* Bit[0] = 1 --> The processor is running unprivileged.
*/
void vRaisePrivilege( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/**
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
* register.
*
* Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
* Bit[0] = 0 --> The processor is running privileged
* Bit[0] = 1 --> The processor is running unprivileged.
*/
void vResetPrivilege( void ) __attribute__( ( naked ) );
/**
* @brief Starts the first task.
*/
void vStartFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/**
* @brief Disables interrupts.
*/
uint32_t ulSetInterruptMask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/**
* @brief Enables interrupts.
*/
void vClearInterruptMask( uint32_t ulMask ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/**
* @brief PendSV Exception handler.
*/
void PendSV_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/**
* @brief SVC Handler.
*/
void SVC_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
/**
* @brief Allocate a Secure context for the calling task.
*
* @param[in] ulSecureStackSize The size of the stack to be allocated on the
* secure side for the calling task.
*/
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) __attribute__( ( naked ) );
/**
* @brief Free the task's secure context.
*
* @param[in] pulTCB Pointer to the Task Control Block (TCB) of the task.
*/
void vPortFreeSecureContext( uint32_t * pulTCB ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
#endif /* __PORT_ASM_H__ */

View file

@ -0,0 +1,80 @@
/*
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright (c) 2025 Arm Technology (China) Co., Ltd.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
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/*------------------------------------------------------------------------------
* Port specific definitions.
*
* The settings in this file configure FreeRTOS correctly for the given hardware
* and compiler.
*
* These settings should not be altered.
*------------------------------------------------------------------------------
*/
#ifndef configENABLE_MVE
#error configENABLE_MVE must be defined in FreeRTOSConfig.h. Set configENABLE_MVE to 1 to enable the MVE or 0 to disable the MVE.
#endif /* configENABLE_MVE */
/*-----------------------------------------------------------*/
/**
* Architecture specifics.
*/
#define portARCH_NAME "Cortex-M52"
#define portHAS_ARMV8M_MAIN_EXTENSION 1
#define portARMV8M_MINOR_VERSION 1
#define portDONT_DISCARD __attribute__( ( used ) )
/*-----------------------------------------------------------*/
/* ARMv8-M common port configurations. */
#include "portmacrocommon.h"
/*-----------------------------------------------------------*/
/**
* @brief Critical section management.
*/
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
/*-----------------------------------------------------------*/
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* PORTMACRO_H */

View file

@ -0,0 +1,582 @@
/*
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates
* <open-source-office@arm.com>
*
* 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 PORTMACROCOMMON_H
#define PORTMACROCOMMON_H
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/*------------------------------------------------------------------------------
* Port specific definitions.
*
* The settings in this file configure FreeRTOS correctly for the given hardware
* and compiler.
*
* These settings should not be altered.
*------------------------------------------------------------------------------
*/
#ifndef configENABLE_FPU
#error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU.
#endif /* configENABLE_FPU */
#ifndef configENABLE_MPU
#error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU.
#endif /* configENABLE_MPU */
#ifndef configENABLE_TRUSTZONE
#error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
#endif /* configENABLE_TRUSTZONE */
/*-----------------------------------------------------------*/
/**
* @brief Type definitions.
*/
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE uint32_t
#define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef unsigned long UBaseType_t;
#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
* not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1
#else
#error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width.
#endif
/*-----------------------------------------------------------*/
/**
* Architecture specifics.
*/
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8
#define portNOP()
#define portINLINE __inline
#ifndef portFORCE_INLINE
#define portFORCE_INLINE inline __attribute__( ( always_inline ) )
#endif
#define portHAS_STACK_OVERFLOW_CHECKING 1
/*-----------------------------------------------------------*/
/**
* @brief Extern declarations.
*/
extern BaseType_t xPortIsInsideInterrupt( void );
extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */;
extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */;
extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */;
extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
#if ( configENABLE_TRUSTZONE == 1 )
extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */
extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */;
#endif /* configENABLE_TRUSTZONE */
#if ( configENABLE_MPU == 1 )
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */
#if ( configENABLE_PAC == 1 )
/**
* @brief Generates 128-bit task's random PAC key.
*
* @param[out] pulTaskPacKey Pointer to a 4-word (128-bits) array to be
* filled with a 128-bit random number.
*/
void vApplicationGenerateTaskRandomPacKey( uint32_t * pulTaskPacKey );
#endif /* configENABLE_PAC */
/*-----------------------------------------------------------*/
/**
* @brief MPU specific constants.
*/
#if ( configENABLE_MPU == 1 )
#define portUSING_MPU_WRAPPERS 1
#define portPRIVILEGE_BIT ( 0x80000000UL )
#else
#define portPRIVILEGE_BIT ( 0x0UL )
#endif /* configENABLE_MPU */
/* MPU settings that can be overridden in FreeRTOSConfig.h. */
#ifndef configTOTAL_MPU_REGIONS
/* Define to 8 for backward compatibility. */
#define configTOTAL_MPU_REGIONS ( 8UL )
#endif
/* MPU regions. */
#define portPRIVILEGED_FLASH_REGION ( 0UL )
#define portUNPRIVILEGED_FLASH_REGION ( 1UL )
#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL )
#define portPRIVILEGED_RAM_REGION ( 3UL )
#define portSTACK_REGION ( 4UL )
#define portFIRST_CONFIGURABLE_REGION ( 5UL )
#define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL )
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
/* Device memory attributes used in MPU_MAIR registers.
*
* 8-bit values encoded as follows:
* Bit[7:4] - 0000 - Device Memory
* Bit[3:2] - 00 --> Device-nGnRnE
* 01 --> Device-nGnRE
* 10 --> Device-nGRE
* 11 --> Device-GRE
* Bit[1:0] - 00, Reserved.
*/
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */
#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */
#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */
/* Normal memory attributes used in MPU_MAIR registers. */
#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */
#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */
/* Attributes used in MPU_RBAR registers. */
#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL )
#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL )
#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL )
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL )
#define portMPU_REGION_READ_WRITE ( 1UL << 1UL )
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL )
#define portMPU_REGION_READ_ONLY ( 3UL << 1UL )
#define portMPU_REGION_EXECUTE_NEVER ( 1UL )
/*-----------------------------------------------------------*/
#if ( configENABLE_MPU == 1 )
/**
* @brief Settings to define an MPU region.
*/
typedef struct MPURegionSettings
{
uint32_t ulRBAR; /**< RBAR for the region. */
uint32_t ulRLAR; /**< RLAR for the region. */
} MPURegionSettings_t;
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
#ifndef configSYSTEM_CALL_STACK_SIZE
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2.
#endif
/**
* @brief System call stack.
*/
typedef struct SYSTEM_CALL_STACK_INFO
{
uint32_t ulSystemCallStackBuffer[ configSYSTEM_CALL_STACK_SIZE ];
uint32_t * pulSystemCallStack;
uint32_t * pulSystemCallStackLimit;
uint32_t * pulTaskStack;
uint32_t ulLinkRegisterAtSystemCallEntry;
uint32_t ulStackLimitRegisterAtSystemCallEntry;
} xSYSTEM_CALL_STACK_INFO;
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
/**
* @brief MPU settings as stored in the TCB.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
#if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><-----------------------------><-----------><---->
* 16 17 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 71
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/*
* +-----------+---------------+----------+-----------------+------------------------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | |
* | | | | PC, xPSR | CONTROL, EXC_RETURN | |
* +-----------+---------------+----------+-----------------+------------------------------+-----+
*
* <-----------><--------------><---------><----------------><-----------------------------><---->
* 16 17 8 8 5 1
*/
#define MAX_CONTEXT_SIZE 55
#elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | | | PC, xPSR | EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><---------------------><-----------><---->
* 16 17 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 70
#else /* if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
/*
* +-----------+---------------+----------+-----------------+----------------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | |
* | | | | PC, xPSR | EXC_RETURN | |
* +-----------+---------------+----------+-----------------+----------------------+-----+
*
* <-----------><--------------><---------><----------------><---------------------><---->
* 16 17 8 8 4 1
*/
#define MAX_CONTEXT_SIZE 54
#endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
#if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+------------------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +----------+-----------------+------------------------------+------------+-----+
*
* <---------><----------------><------------------------------><-----------><---->
* 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 38
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/*
* +----------+-----------------+------------------------------+-----+
* | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | |
* | | PC, xPSR | CONTROL, EXC_RETURN | |
* +----------+-----------------+------------------------------+-----+
*
* <---------><----------------><------------------------------><---->
* 8 8 5 1
*/
#define MAX_CONTEXT_SIZE 22
#elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+----------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | PC, xPSR | EXC_RETURN | | |
* +----------+-----------------+----------------------+------------+-----+
*
* <---------><----------------><----------------------><-----------><---->
* 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 37
#else /* #if( configENABLE_TRUSTZONE == 1 ) */
/*
* +----------+-----------------+----------------------+-----+
* | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | |
* | | PC, xPSR | EXC_RETURN | |
* +----------+-----------------+----------------------+-----+
*
* <---------><----------------><----------------------><---->
* 8 8 4 1
*/
#define MAX_CONTEXT_SIZE 21
#endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
/* Flags used for xMPU_SETTINGS.ulTaskFlags member. */
#define portSTACK_FRAME_HAS_PADDING_FLAG ( 1UL << 0UL )
#define portTASK_IS_PRIVILEGED_FLAG ( 1UL << 1UL )
/* Size of an Access Control List (ACL) entry in bits. */
#define portACL_ENTRY_SIZE_BITS ( 32U )
typedef struct MPU_SETTINGS
{
uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */
MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */
uint32_t ulContext[ MAX_CONTEXT_SIZE ];
uint32_t ulTaskFlags;
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
xSYSTEM_CALL_STACK_INFO xSystemCallStackInfo;
#if ( configENABLE_ACCESS_CONTROL_LIST == 1 )
uint32_t ulAccessControlList[ ( configPROTECTED_KERNEL_OBJECT_POOL_SIZE / portACL_ENTRY_SIZE_BITS ) + 1 ];
#endif
#endif
} xMPU_SETTINGS;
#endif /* configENABLE_MPU == 1 */
/*-----------------------------------------------------------*/
/**
* @brief Validate priority of ISRs that are allowed to call FreeRTOS
* system calls.
*/
#if ( configASSERT_DEFINED == 1 )
#if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 )
void vPortValidateInterruptPriority( void );
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
#endif
#endif
/**
* @brief SVC numbers.
*/
#define portSVC_ALLOCATE_SECURE_CONTEXT 100
#define portSVC_FREE_SECURE_CONTEXT 101
#define portSVC_START_SCHEDULER 102
#define portSVC_RAISE_PRIVILEGE 103
#define portSVC_SYSTEM_CALL_EXIT 104
#define portSVC_YIELD 105
/*-----------------------------------------------------------*/
/**
* @brief Scheduler utilities.
*/
#if ( configENABLE_MPU == 1 )
#define portYIELD() __asm volatile ( "svc %0" ::"i" ( portSVC_YIELD ) : "memory" )
#define portYIELD_WITHIN_API() vPortYield()
#else
#define portYIELD() vPortYield()
#define portYIELD_WITHIN_API() vPortYield()
#endif
#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portEND_SWITCHING_ISR( xSwitchRequired ) \
do \
{ \
if( xSwitchRequired ) \
{ \
traceISR_EXIT_TO_SCHEDULER(); \
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
} \
else \
{ \
traceISR_EXIT(); \
} \
} while( 0 )
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/
/**
* @brief Critical section management.
*/
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x )
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
/*-----------------------------------------------------------*/
/**
* @brief Tickless idle/low power functionality.
*/
#ifndef portSUPPRESS_TICKS_AND_SLEEP
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
#endif
/*-----------------------------------------------------------*/
/**
* @brief Task function macros as described on the FreeRTOS.org WEB site.
*/
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
/*-----------------------------------------------------------*/
#if ( configENABLE_TRUSTZONE == 1 )
/**
* @brief Allocate a secure context for the task.
*
* Tasks are not created with a secure context. Any task that is going to call
* secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a
* secure context before it calls any secure function.
*
* @param[in] ulSecureStackSize The size of the secure stack to be allocated.
*/
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize )
/**
* @brief Called when a task is deleted to delete the task's secure context,
* if it has one.
*
* @param[in] pxTCB The TCB of the task being deleted.
*/
#define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB )
#endif /* configENABLE_TRUSTZONE */
/*-----------------------------------------------------------*/
#if ( configENABLE_MPU == 1 )
/**
* @brief Checks whether or not the processor is privileged.
*
* @return 1 if the processor is already privileged, 0 otherwise.
*/
#define portIS_PRIVILEGED() xIsPrivileged()
/**
* @brief Raise an SVC request to raise privilege.
*
* The SVC handler checks that the SVC was raised from a system call and only
* then it raises the privilege. If this is called from any other place,
* the privilege is not raised.
*/
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" );
/**
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
* register.
*/
#define portRESET_PRIVILEGE() vResetPrivilege()
#else
#define portIS_PRIVILEGED()
#define portRAISE_PRIVILEGE()
#define portRESET_PRIVILEGE()
#endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/
#if ( configENABLE_MPU == 1 )
extern BaseType_t xPortIsTaskPrivileged( void );
/**
* @brief Checks whether or not the calling task is privileged.
*
* @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
*/
#define portIS_TASK_PRIVILEGED() xPortIsTaskPrivileged()
#endif /* configENABLE_MPU == 1 */
/*-----------------------------------------------------------*/
/**
* @brief Barriers.
*/
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
/*-----------------------------------------------------------*/
/* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION
* based on whether or not Mainline extension is implemented. */
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
#if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 )
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#else
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
#endif
#endif /* #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION */
/**
* @brief Port-optimised task selection.
*/
#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 )
/**
* @brief Count the number of leading zeros in a 32-bit value.
*/
static portFORCE_INLINE uint32_t ulPortCountLeadingZeros( uint32_t ulBitmap )
{
uint32_t ulReturn;
__asm volatile ( "clz %0, %1" : "=r" ( ulReturn ) : "r" ( ulBitmap ) : "memory" );
return ulReturn;
}
/* 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 different priorities as tasks that share a priority will time slice.
#endif
#if ( portHAS_ARMV8M_MAIN_EXTENSION == 0 )
#error ARMv8-M baseline implementations (such as Cortex-M23) do not support port-optimised task selection. Please set configUSE_PORT_OPTIMISED_TASK_SELECTION to 0 or leave it undefined.
#endif
/**
* @brief Store/clear the ready priorities in a bit map.
*/
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
/**
* @brief Get the priority of the highest-priority task that is ready to execute.
*/
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ulPortCountLeadingZeros( ( uxReadyPriorities ) ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/*-----------------------------------------------------------*/
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* PORTMACROCOMMON_H */

View file

@ -0,0 +1,354 @@
/*
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
/* Secure context includes. */
#include "secure_context.h"
/* Secure heap includes. */
#include "secure_heap.h"
/* Secure port macros. */
#include "secure_port_macros.h"
/**
* @brief CONTROL value for privileged tasks.
*
* Bit[0] - 0 --> Thread mode is privileged.
* Bit[1] - 1 --> Thread mode uses PSP.
*/
#define securecontextCONTROL_VALUE_PRIVILEGED 0x02
/**
* @brief CONTROL value for un-privileged tasks.
*
* Bit[0] - 1 --> Thread mode is un-privileged.
* Bit[1] - 1 --> Thread mode uses PSP.
*/
#define securecontextCONTROL_VALUE_UNPRIVILEGED 0x03
/**
* @brief Size of stack seal values in bytes.
*/
#define securecontextSTACK_SEAL_SIZE 8
/**
* @brief Stack seal value as recommended by ARM.
*/
#define securecontextSTACK_SEAL_VALUE 0xFEF5EDA5
/**
* @brief Maximum number of secure contexts.
*/
#ifndef secureconfigMAX_SECURE_CONTEXTS
#define secureconfigMAX_SECURE_CONTEXTS 8UL
#endif
/*-----------------------------------------------------------*/
/**
* @brief Pre-allocated array of secure contexts.
*/
SecureContext_t xSecureContexts[ secureconfigMAX_SECURE_CONTEXTS ];
/*-----------------------------------------------------------*/
/**
* @brief Get a free secure context for a task from the secure context pool (xSecureContexts).
*
* This function ensures that only one secure context is allocated for a task.
*
* @param[in] pvTaskHandle The task handle for which the secure context is allocated.
*
* @return Index of a free secure context in the xSecureContexts array.
*/
static uint32_t ulGetSecureContext( void * pvTaskHandle );
/**
* @brief Return the secure context to the secure context pool (xSecureContexts).
*
* @param[in] ulSecureContextIndex Index of the context in the xSecureContexts array.
*/
static void vReturnSecureContext( uint32_t ulSecureContextIndex );
/* These are implemented in assembly. */
extern void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext );
extern void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext );
/*-----------------------------------------------------------*/
static uint32_t ulGetSecureContext( void * pvTaskHandle )
{
/* Start with invalid index. */
uint32_t i, ulSecureContextIndex = secureconfigMAX_SECURE_CONTEXTS;
for( i = 0; i < secureconfigMAX_SECURE_CONTEXTS; i++ )
{
if( ( xSecureContexts[ i ].pucCurrentStackPointer == NULL ) &&
( xSecureContexts[ i ].pucStackLimit == NULL ) &&
( xSecureContexts[ i ].pucStackStart == NULL ) &&
( xSecureContexts[ i ].pvTaskHandle == NULL ) &&
( ulSecureContextIndex == secureconfigMAX_SECURE_CONTEXTS ) )
{
ulSecureContextIndex = i;
}
else if( xSecureContexts[ i ].pvTaskHandle == pvTaskHandle )
{
/* A task can only have one secure context. Do not allocate a second
* context for the same task. */
ulSecureContextIndex = secureconfigMAX_SECURE_CONTEXTS;
break;
}
}
return ulSecureContextIndex;
}
/*-----------------------------------------------------------*/
static void vReturnSecureContext( uint32_t ulSecureContextIndex )
{
xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = NULL;
xSecureContexts[ ulSecureContextIndex ].pucStackLimit = NULL;
xSecureContexts[ ulSecureContextIndex ].pucStackStart = NULL;
xSecureContexts[ ulSecureContextIndex ].pvTaskHandle = NULL;
}
/*-----------------------------------------------------------*/
secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
{
uint32_t ulIPSR, i;
static uint32_t ulSecureContextsInitialized = 0;
/* Read the Interrupt Program Status Register (IPSR) value. */
secureportREAD_IPSR( ulIPSR );
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
* when the processor is running in the Thread Mode. */
if( ( ulIPSR != 0 ) && ( ulSecureContextsInitialized == 0 ) )
{
/* Ensure to initialize secure contexts only once. */
ulSecureContextsInitialized = 1;
/* No stack for thread mode until a task's context is loaded. */
secureportSET_PSPLIM( securecontextNO_STACK );
secureportSET_PSP( securecontextNO_STACK );
/* Initialize all secure contexts. */
for( i = 0; i < secureconfigMAX_SECURE_CONTEXTS; i++ )
{
xSecureContexts[ i ].pucCurrentStackPointer = NULL;
xSecureContexts[ i ].pucStackLimit = NULL;
xSecureContexts[ i ].pucStackStart = NULL;
xSecureContexts[ i ].pvTaskHandle = NULL;
}
#if ( configENABLE_MPU == 1 )
{
/* Configure thread mode to use PSP and to be unprivileged. */
secureportSET_CONTROL( securecontextCONTROL_VALUE_UNPRIVILEGED );
}
#else /* configENABLE_MPU */
{
/* Configure thread mode to use PSP and to be privileged. */
secureportSET_CONTROL( securecontextCONTROL_VALUE_PRIVILEGED );
}
#endif /* configENABLE_MPU */
}
}
/*-----------------------------------------------------------*/
#if ( configENABLE_MPU == 1 )
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
uint32_t ulIsTaskPrivileged,
void * pvTaskHandle )
#else /* configENABLE_MPU */
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
void * pvTaskHandle )
#endif /* configENABLE_MPU */
{
uint8_t * pucStackMemory = NULL;
uint8_t * pucStackLimit;
uint32_t ulIPSR, ulSecureContextIndex;
SecureContextHandle_t xSecureContextHandle = securecontextINVALID_CONTEXT_ID;
#if ( configENABLE_MPU == 1 )
uint32_t * pulCurrentStackPointer = NULL;
#endif /* configENABLE_MPU */
/* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
* Register (PSPLIM) value. */
secureportREAD_IPSR( ulIPSR );
secureportREAD_PSPLIM( pucStackLimit );
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
* when the processor is running in the Thread Mode.
* Also do nothing, if a secure context us already loaded. PSPLIM is set to
* securecontextNO_STACK when no secure context is loaded. */
if( ( ulIPSR != 0 ) && ( pucStackLimit == securecontextNO_STACK ) )
{
/* Obtain a free secure context. */
ulSecureContextIndex = ulGetSecureContext( pvTaskHandle );
/* Were we able to get a free context? */
if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS )
{
/* Allocate the stack space. */
pucStackMemory = pvPortMalloc( ulSecureStackSize + securecontextSTACK_SEAL_SIZE );
if( pucStackMemory != NULL )
{
/* Since stack grows down, the starting point will be the last
* location. Note that this location is next to the last
* allocated byte for stack (excluding the space for seal values)
* because the hardware decrements the stack pointer before
* writing i.e. if stack pointer is 0x2, a push operation will
* decrement the stack pointer to 0x1 and then write at 0x1. */
xSecureContexts[ ulSecureContextIndex ].pucStackStart = pucStackMemory + ulSecureStackSize;
/* Seal the created secure process stack. */
*( uint32_t * ) ( pucStackMemory + ulSecureStackSize ) = securecontextSTACK_SEAL_VALUE;
*( uint32_t * ) ( pucStackMemory + ulSecureStackSize + 4 ) = securecontextSTACK_SEAL_VALUE;
/* The stack cannot go beyond this location. This value is
* programmed in the PSPLIM register on context switch.*/
xSecureContexts[ ulSecureContextIndex ].pucStackLimit = pucStackMemory;
xSecureContexts[ ulSecureContextIndex ].pvTaskHandle = pvTaskHandle;
#if ( configENABLE_MPU == 1 )
{
/* Store the correct CONTROL value for the task on the stack.
* This value is programmed in the CONTROL register on
* context switch. */
pulCurrentStackPointer = ( uint32_t * ) xSecureContexts[ ulSecureContextIndex ].pucStackStart;
pulCurrentStackPointer--;
if( ulIsTaskPrivileged )
{
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_PRIVILEGED;
}
else
{
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_UNPRIVILEGED;
}
/* Store the current stack pointer. This value is programmed in
* the PSP register on context switch. */
xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = ( uint8_t * ) pulCurrentStackPointer;
}
#else /* configENABLE_MPU */
{
/* Current SP is set to the starting of the stack. This
* value programmed in the PSP register on context switch. */
xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = xSecureContexts[ ulSecureContextIndex ].pucStackStart;
}
#endif /* configENABLE_MPU */
/* Ensure to never return 0 as a valid context handle. */
xSecureContextHandle = ulSecureContextIndex + 1UL;
}
}
}
return xSecureContextHandle;
}
/*-----------------------------------------------------------*/
secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle,
void * pvTaskHandle )
{
uint32_t ulIPSR, ulSecureContextIndex;
/* Read the Interrupt Program Status Register (IPSR) value. */
secureportREAD_IPSR( ulIPSR );
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
* when the processor is running in the Thread Mode. */
if( ulIPSR != 0 )
{
/* Only free if a valid context handle is passed. */
if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )
{
ulSecureContextIndex = xSecureContextHandle - 1UL;
/* Ensure that the secure context being deleted is associated with
* the task. */
if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
{
/* Free the stack space. */
vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
/* Return the secure context back to the free secure contexts pool. */
vReturnSecureContext( ulSecureContextIndex );
}
}
}
}
/*-----------------------------------------------------------*/
secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle,
void * pvTaskHandle )
{
uint8_t * pucStackLimit;
uint32_t ulSecureContextIndex;
if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )
{
ulSecureContextIndex = xSecureContextHandle - 1UL;
secureportREAD_PSPLIM( pucStackLimit );
/* Ensure that no secure context is loaded and the task is loading it's
* own context. */
if( ( pucStackLimit == securecontextNO_STACK ) &&
( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) )
{
SecureContext_LoadContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );
}
}
}
/*-----------------------------------------------------------*/
secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle,
void * pvTaskHandle )
{
uint8_t * pucStackLimit;
uint32_t ulSecureContextIndex;
if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )
{
ulSecureContextIndex = xSecureContextHandle - 1UL;
secureportREAD_PSPLIM( pucStackLimit );
/* Ensure that task's context is loaded and the task is saving it's own
* context. */
if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) &&
( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) )
{
SecureContext_SaveContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );
}
}
}
/*-----------------------------------------------------------*/

View file

@ -0,0 +1,138 @@
/*
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
#ifndef __SECURE_CONTEXT_H__
#define __SECURE_CONTEXT_H__
/* Standard includes. */
#include <stdint.h>
/* FreeRTOS includes. */
#include "FreeRTOSConfig.h"
/**
* @brief PSP value when no secure context is loaded.
*/
#define securecontextNO_STACK 0x0
/**
* @brief Invalid context ID.
*/
#define securecontextINVALID_CONTEXT_ID 0UL
/*-----------------------------------------------------------*/
/**
* @brief Structure to represent a secure context.
*
* @note Since stack grows down, pucStackStart is the highest address while
* pucStackLimit is the first address of the allocated memory.
*/
typedef struct SecureContext
{
uint8_t * pucCurrentStackPointer; /**< Current value of stack pointer (PSP). */
uint8_t * pucStackLimit; /**< Last location of the stack memory (PSPLIM). */
uint8_t * pucStackStart; /**< First location of the stack memory. */
void * pvTaskHandle; /**< Task handle of the task this context is associated with. */
} SecureContext_t;
/*-----------------------------------------------------------*/
/**
* @brief Opaque handle for a secure context.
*/
typedef uint32_t SecureContextHandle_t;
/*-----------------------------------------------------------*/
/**
* @brief Initializes the secure context management system.
*
* PSP is set to NULL and therefore a task must allocate and load a context
* before calling any secure side function in the thread mode.
*
* @note This function must be called in the handler mode. It is no-op if called
* in the thread mode.
*/
void SecureContext_Init( void );
/**
* @brief Allocates a context on the secure side.
*
* @note This function must be called in the handler mode. It is no-op if called
* in the thread mode.
*
* @param[in] ulSecureStackSize Size of the stack to allocate on secure side.
* @param[in] ulIsTaskPrivileged 1 if the calling task is privileged, 0 otherwise.
*
* @return Opaque context handle if context is successfully allocated, NULL
* otherwise.
*/
#if ( configENABLE_MPU == 1 )
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
uint32_t ulIsTaskPrivileged,
void * pvTaskHandle );
#else /* configENABLE_MPU */
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
void * pvTaskHandle );
#endif /* configENABLE_MPU */
/**
* @brief Frees the given context.
*
* @note This function must be called in the handler mode. It is no-op if called
* in the thread mode.
*
* @param[in] xSecureContextHandle Context handle corresponding to the
* context to be freed.
*/
void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle,
void * pvTaskHandle );
/**
* @brief Loads the given context.
*
* @note This function must be called in the handler mode. It is no-op if called
* in the thread mode.
*
* @param[in] xSecureContextHandle Context handle corresponding to the context
* to be loaded.
*/
void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle,
void * pvTaskHandle );
/**
* @brief Saves the given context.
*
* @note This function must be called in the handler mode. It is no-op if called
* in the thread mode.
*
* @param[in] xSecureContextHandle Context handle corresponding to the context
* to be saved.
*/
void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle,
void * pvTaskHandle );
#endif /* __SECURE_CONTEXT_H__ */

View file

@ -0,0 +1,97 @@
/*
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
/* Secure context includes. */
#include "secure_context.h"
/* Secure port macros. */
#include "secure_port_macros.h"
void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext ) __attribute__( ( naked ) );
void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext ) __attribute__( ( naked ) );
void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext )
{
/* pxSecureContext value is in r0. */
__asm volatile
(
" .syntax unified \n"
" \n"
" mrs r1, ipsr \n" /* r1 = IPSR. */
" cbz r1, load_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */
" ldmia r0!, {r1, r2} \n" /* r1 = pxSecureContext->pucCurrentStackPointer, r2 = pxSecureContext->pucStackLimit. */
" \n"
#if ( configENABLE_MPU == 1 )
" ldmia r1!, {r3} \n" /* Read CONTROL register value from task's stack. r3 = CONTROL. */
" msr control, r3 \n" /* CONTROL = r3. */
#endif /* configENABLE_MPU */
" \n"
" msr psplim, r2 \n" /* PSPLIM = r2. */
" msr psp, r1 \n" /* PSP = r1. */
" \n"
" load_ctx_therad_mode: \n"
" bx lr \n"
" \n"
::: "r0", "r1", "r2"
);
}
/*-----------------------------------------------------------*/
void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext )
{
/* pxSecureContext value is in r0. */
__asm volatile
(
" .syntax unified \n"
" \n"
" mrs r1, ipsr \n" /* r1 = IPSR. */
" cbz r1, save_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */
" mrs r1, psp \n" /* r1 = PSP. */
" \n"
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" vstmdb r1!, {s0} \n" /* Trigger the deferred stacking of FPU registers. */
" vldmia r1!, {s0} \n" /* Nullify the effect of the previous statement. */
#endif /* configENABLE_FPU || configENABLE_MVE */
" \n"
#if ( configENABLE_MPU == 1 )
" mrs r2, control \n" /* r2 = CONTROL. */
" stmdb r1!, {r2} \n" /* Store CONTROL value on the stack. */
#endif /* configENABLE_MPU */
" \n"
" str r1, [r0] \n" /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */
" movs r1, %0 \n" /* r1 = securecontextNO_STACK. */
" msr psplim, r1 \n" /* PSPLIM = securecontextNO_STACK. */
" msr psp, r1 \n" /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */
" \n"
" save_ctx_therad_mode: \n"
" bx lr \n"
" \n"
::"i" ( securecontextNO_STACK ) : "r1", "memory"
);
}
/*-----------------------------------------------------------*/

View file

@ -0,0 +1,485 @@
/*
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
/* Standard includes. */
#include <stdint.h>
/* Configuration includes. */
#include "FreeRTOSConfig.h"
/* Secure context heap includes. */
#include "secure_heap.h"
/* Secure port macros. */
#include "secure_port_macros.h"
/**
* @brief Total heap size.
*/
#ifndef secureconfigTOTAL_HEAP_SIZE
#define secureconfigTOTAL_HEAP_SIZE ( ( ( size_t ) ( 10 * 1024 ) ) )
#endif
/* No test marker by default. */
#ifndef mtCOVERAGE_TEST_MARKER
#define mtCOVERAGE_TEST_MARKER()
#endif
/* No tracing by default. */
#ifndef traceMALLOC
#define traceMALLOC( pvReturn, xWantedSize )
#endif
/* No tracing by default. */
#ifndef traceFREE
#define traceFREE( pv, xBlockSize )
#endif
/* Block sizes must not get too small. */
#define secureheapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) )
/* Assumes 8bit bytes! */
#define secureheapBITS_PER_BYTE ( ( size_t ) 8 )
/* Max value that fits in a size_t type. */
#define secureheapSIZE_MAX ( ~( ( size_t ) 0 ) )
/* Check if adding a and b will result in overflow. */
#define secureheapADD_WILL_OVERFLOW( a, b ) ( ( a ) > ( secureheapSIZE_MAX - ( b ) ) )
/* MSB of the xBlockSize member of an BlockLink_t structure is used to track
* the allocation status of a block. When MSB of the xBlockSize member of
* an BlockLink_t structure is set then the block belongs to the application.
* When the bit is free the block is still part of the free heap space. */
#define secureheapBLOCK_ALLOCATED_BITMASK ( ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 ) )
#define secureheapBLOCK_SIZE_IS_VALID( xBlockSize ) ( ( ( xBlockSize ) & secureheapBLOCK_ALLOCATED_BITMASK ) == 0 )
#define secureheapBLOCK_IS_ALLOCATED( pxBlock ) ( ( ( pxBlock->xBlockSize ) & secureheapBLOCK_ALLOCATED_BITMASK ) != 0 )
#define secureheapALLOCATE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) |= secureheapBLOCK_ALLOCATED_BITMASK )
#define secureheapFREE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) &= ~secureheapBLOCK_ALLOCATED_BITMASK )
/*-----------------------------------------------------------*/
/* Allocate the memory for the heap. */
#if ( configAPPLICATION_ALLOCATED_HEAP == 1 )
/* The application writer has already defined the array used for the RTOS
* heap - probably so it can be placed in a special segment or address. */
extern uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
#else /* configAPPLICATION_ALLOCATED_HEAP */
static uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
#endif /* configAPPLICATION_ALLOCATED_HEAP */
/**
* @brief The linked list structure.
*
* This is used to link free blocks in order of their memory address.
*/
typedef struct A_BLOCK_LINK
{
struct A_BLOCK_LINK * pxNextFreeBlock; /**< The next free block in the list. */
size_t xBlockSize; /**< The size of the free block. */
} BlockLink_t;
/*-----------------------------------------------------------*/
/**
* @brief Called automatically to setup the required heap structures the first
* time pvPortMalloc() is called.
*/
static void prvHeapInit( void );
/**
* @brief Inserts a block of memory that is being freed into the correct
* position in the list of free memory blocks.
*
* The block being freed will be merged with the block in front it and/or the
* block behind it if the memory blocks are adjacent to each other.
*
* @param[in] pxBlockToInsert The block being freed.
*/
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert );
/*-----------------------------------------------------------*/
/**
* @brief The size of the structure placed at the beginning of each allocated
* memory block must by correctly byte aligned.
*/
static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( secureportBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
/**
* @brief Create a couple of list links to mark the start and end of the list.
*/
static BlockLink_t xStart;
static BlockLink_t * pxEnd = NULL;
/**
* @brief Keeps track of the number of free bytes remaining, but says nothing
* about fragmentation.
*/
static size_t xFreeBytesRemaining = 0U;
static size_t xMinimumEverFreeBytesRemaining = 0U;
/*-----------------------------------------------------------*/
static void prvHeapInit( void )
{
BlockLink_t * pxFirstFreeBlock;
uint8_t * pucAlignedHeap;
size_t uxAddress;
size_t xTotalHeapSize = secureconfigTOTAL_HEAP_SIZE;
/* Ensure the heap starts on a correctly aligned boundary. */
uxAddress = ( size_t ) ucHeap;
if( ( uxAddress & secureportBYTE_ALIGNMENT_MASK ) != 0 )
{
uxAddress += ( secureportBYTE_ALIGNMENT - 1 );
uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
xTotalHeapSize -= uxAddress - ( size_t ) ucHeap;
}
pucAlignedHeap = ( uint8_t * ) uxAddress;
/* xStart is used to hold a pointer to the first item in the list of free
* blocks. The void cast is used to prevent compiler warnings. */
xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap;
xStart.xBlockSize = ( size_t ) 0;
/* pxEnd is used to mark the end of the list of free blocks and is inserted
* at the end of the heap space. */
uxAddress = ( ( size_t ) pucAlignedHeap ) + xTotalHeapSize;
uxAddress -= xHeapStructSize;
uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
pxEnd = ( void * ) uxAddress;
pxEnd->xBlockSize = 0;
pxEnd->pxNextFreeBlock = NULL;
/* To start with there is a single free block that is sized to take up the
* entire heap space, minus the space taken by pxEnd. */
pxFirstFreeBlock = ( void * ) pucAlignedHeap;
pxFirstFreeBlock->xBlockSize = uxAddress - ( size_t ) pxFirstFreeBlock;
pxFirstFreeBlock->pxNextFreeBlock = pxEnd;
/* Only one block exists - and it covers the entire usable heap space. */
xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
}
/*-----------------------------------------------------------*/
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert )
{
BlockLink_t * pxIterator;
uint8_t * puc;
/* Iterate through the list until a block is found that has a higher address
* than the block being inserted. */
for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock )
{
/* Nothing to do here, just iterate to the right position. */
}
/* Do the block being inserted, and the block it is being inserted after
* make a contiguous block of memory? */
puc = ( uint8_t * ) pxIterator;
if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
{
pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
pxBlockToInsert = pxIterator;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* Do the block being inserted, and the block it is being inserted before
* make a contiguous block of memory? */
puc = ( uint8_t * ) pxBlockToInsert;
if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
{
if( pxIterator->pxNextFreeBlock != pxEnd )
{
/* Form one big block from the two blocks. */
pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
}
else
{
pxBlockToInsert->pxNextFreeBlock = pxEnd;
}
}
else
{
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
}
/* If the block being inserted plugged a gap, so was merged with the block
* before and the block after, then it's pxNextFreeBlock pointer will have
* already been set, and should not be set here as that would make it point
* to itself. */
if( pxIterator != pxBlockToInsert )
{
pxIterator->pxNextFreeBlock = pxBlockToInsert;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
/*-----------------------------------------------------------*/
void * pvPortMalloc( size_t xWantedSize )
{
BlockLink_t * pxBlock;
BlockLink_t * pxPreviousBlock;
BlockLink_t * pxNewBlockLink;
void * pvReturn = NULL;
size_t xAdditionalRequiredSize;
size_t xAllocatedBlockSize = 0;
/* If this is the first call to malloc then the heap will require
* initialisation to setup the list of free blocks. */
if( pxEnd == NULL )
{
prvHeapInit();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
if( xWantedSize > 0 )
{
/* The wanted size must be increased so it can contain a BlockLink_t
* structure in addition to the requested amount of bytes. */
if( secureheapADD_WILL_OVERFLOW( xWantedSize, xHeapStructSize ) == 0 )
{
xWantedSize += xHeapStructSize;
/* Ensure that blocks are always aligned to the required number
* of bytes. */
if( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) != 0x00 )
{
/* Byte alignment required. */
xAdditionalRequiredSize = secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK );
if( secureheapADD_WILL_OVERFLOW( xWantedSize, xAdditionalRequiredSize ) == 0 )
{
xWantedSize += xAdditionalRequiredSize;
}
else
{
xWantedSize = 0;
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
xWantedSize = 0;
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* Check the requested block size is not so large that the top bit is set.
* The top bit of the block size member of the BlockLink_t structure is used
* to determine who owns the block - the application or the kernel, so it
* must be free. */
if( secureheapBLOCK_SIZE_IS_VALID( xWantedSize ) != 0 )
{
if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
{
/* Traverse the list from the start (lowest address) block until
* one of adequate size is found. */
pxPreviousBlock = &xStart;
pxBlock = xStart.pxNextFreeBlock;
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
{
pxPreviousBlock = pxBlock;
pxBlock = pxBlock->pxNextFreeBlock;
}
/* If the end marker was reached then a block of adequate size was
* not found. */
if( pxBlock != pxEnd )
{
/* Return the memory space pointed to - jumping over the
* BlockLink_t structure at its start. */
pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize );
/* This block is being returned for use so must be taken out
* of the list of free blocks. */
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
/* If the block is larger than required it can be split into
* two. */
if( ( pxBlock->xBlockSize - xWantedSize ) > secureheapMINIMUM_BLOCK_SIZE )
{
/* This block is to be split into two. Create a new
* block following the number of bytes requested. The void
* cast is used to prevent byte alignment warnings from the
* compiler. */
pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
secureportASSERT( ( ( ( size_t ) pxNewBlockLink ) & secureportBYTE_ALIGNMENT_MASK ) == 0 );
/* Calculate the sizes of two blocks split from the single
* block. */
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
pxBlock->xBlockSize = xWantedSize;
/* Insert the new block into the list of free blocks. */
pxNewBlockLink->pxNextFreeBlock = pxPreviousBlock->pxNextFreeBlock;
pxPreviousBlock->pxNextFreeBlock = pxNewBlockLink;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
xFreeBytesRemaining -= pxBlock->xBlockSize;
if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
{
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
xAllocatedBlockSize = pxBlock->xBlockSize;
/* The block is being returned - it is allocated and owned by
* the application and has no "next" block. */
secureheapALLOCATE_BLOCK( pxBlock );
pxBlock->pxNextFreeBlock = NULL;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
traceMALLOC( pvReturn, xAllocatedBlockSize );
/* Prevent compiler warnings when trace macros are not used. */
( void ) xAllocatedBlockSize;
#if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 )
{
if( pvReturn == NULL )
{
extern void vApplicationMallocFailedHook( void );
vApplicationMallocFailedHook();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
#endif /* if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 ) */
secureportASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) secureportBYTE_ALIGNMENT_MASK ) == 0 );
return pvReturn;
}
/*-----------------------------------------------------------*/
void vPortFree( void * pv )
{
uint8_t * puc = ( uint8_t * ) pv;
BlockLink_t * pxLink;
if( pv != NULL )
{
/* The memory being freed will have an BlockLink_t structure immediately
* before it. */
puc -= xHeapStructSize;
/* This casting is to keep the compiler from issuing warnings. */
pxLink = ( void * ) puc;
/* Check the block is actually allocated. */
secureportASSERT( secureheapBLOCK_IS_ALLOCATED( pxLink ) != 0 );
secureportASSERT( pxLink->pxNextFreeBlock == NULL );
if( secureheapBLOCK_IS_ALLOCATED( pxLink ) != 0 )
{
if( pxLink->pxNextFreeBlock == NULL )
{
/* The block is being returned to the heap - it is no longer
* allocated. */
secureheapFREE_BLOCK( pxLink );
secureportDISABLE_NON_SECURE_INTERRUPTS();
{
/* Add this block to the list of free blocks. */
xFreeBytesRemaining += pxLink->xBlockSize;
traceFREE( pv, pxLink->xBlockSize );
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
}
secureportENABLE_NON_SECURE_INTERRUPTS();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
}
/*-----------------------------------------------------------*/
size_t xPortGetFreeHeapSize( void )
{
return xFreeBytesRemaining;
}
/*-----------------------------------------------------------*/
size_t xPortGetMinimumEverFreeHeapSize( void )
{
return xMinimumEverFreeBytesRemaining;
}
/*-----------------------------------------------------------*/

View file

@ -0,0 +1,66 @@
/*
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
#ifndef __SECURE_HEAP_H__
#define __SECURE_HEAP_H__
/* Standard includes. */
#include <stdlib.h>
/**
* @brief Allocates memory from heap.
*
* @param[in] xWantedSize The size of the memory to be allocated.
*
* @return Pointer to the memory region if the allocation is successful, NULL
* otherwise.
*/
void * pvPortMalloc( size_t xWantedSize );
/**
* @brief Frees the previously allocated memory.
*
* @param[in] pv Pointer to the memory to be freed.
*/
void vPortFree( void * pv );
/**
* @brief Get the free heap size.
*
* @return Free heap size.
*/
size_t xPortGetFreeHeapSize( void );
/**
* @brief Get the minimum ever free heap size.
*
* @return Minimum ever free heap size.
*/
size_t xPortGetMinimumEverFreeHeapSize( void );
#endif /* __SECURE_HEAP_H__ */

View file

@ -0,0 +1,106 @@
/*
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
/* Standard includes. */
#include <stdint.h>
/* Secure init includes. */
#include "secure_init.h"
/* Secure port macros. */
#include "secure_port_macros.h"
/**
* @brief Constants required to manipulate the SCB.
*/
#define secureinitSCB_AIRCR ( ( volatile uint32_t * ) 0xe000ed0c ) /* Application Interrupt and Reset Control Register. */
#define secureinitSCB_AIRCR_VECTKEY_POS ( 16UL )
#define secureinitSCB_AIRCR_VECTKEY_MASK ( 0xFFFFUL << secureinitSCB_AIRCR_VECTKEY_POS )
#define secureinitSCB_AIRCR_PRIS_POS ( 14UL )
#define secureinitSCB_AIRCR_PRIS_MASK ( 1UL << secureinitSCB_AIRCR_PRIS_POS )
/**
* @brief Constants required to manipulate the FPU.
*/
#define secureinitFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
#define secureinitFPCCR_LSPENS_POS ( 29UL )
#define secureinitFPCCR_LSPENS_MASK ( 1UL << secureinitFPCCR_LSPENS_POS )
#define secureinitFPCCR_TS_POS ( 26UL )
#define secureinitFPCCR_TS_MASK ( 1UL << secureinitFPCCR_TS_POS )
#define secureinitNSACR ( ( volatile uint32_t * ) 0xe000ed8c ) /* Non-secure Access Control Register. */
#define secureinitNSACR_CP10_POS ( 10UL )
#define secureinitNSACR_CP10_MASK ( 1UL << secureinitNSACR_CP10_POS )
#define secureinitNSACR_CP11_POS ( 11UL )
#define secureinitNSACR_CP11_MASK ( 1UL << secureinitNSACR_CP11_POS )
/*-----------------------------------------------------------*/
secureportNON_SECURE_CALLABLE void SecureInit_DePrioritizeNSExceptions( void )
{
uint32_t ulIPSR;
/* Read the Interrupt Program Status Register (IPSR) value. */
secureportREAD_IPSR( ulIPSR );
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
* when the processor is running in the Thread Mode. */
if( ulIPSR != 0 )
{
*( secureinitSCB_AIRCR ) = ( *( secureinitSCB_AIRCR ) & ~( secureinitSCB_AIRCR_VECTKEY_MASK | secureinitSCB_AIRCR_PRIS_MASK ) ) |
( ( 0x05FAUL << secureinitSCB_AIRCR_VECTKEY_POS ) & secureinitSCB_AIRCR_VECTKEY_MASK ) |
( ( 0x1UL << secureinitSCB_AIRCR_PRIS_POS ) & secureinitSCB_AIRCR_PRIS_MASK );
}
}
/*-----------------------------------------------------------*/
secureportNON_SECURE_CALLABLE void SecureInit_EnableNSFPUAccess( void )
{
uint32_t ulIPSR;
/* Read the Interrupt Program Status Register (IPSR) value. */
secureportREAD_IPSR( ulIPSR );
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
* when the processor is running in the Thread Mode. */
if( ulIPSR != 0 )
{
/* CP10 = 1 ==> Non-secure access to the Floating Point Unit is
* permitted. CP11 should be programmed to the same value as CP10. */
*( secureinitNSACR ) |= ( secureinitNSACR_CP10_MASK | secureinitNSACR_CP11_MASK );
/* LSPENS = 0 ==> LSPEN is writable from non-secure state. This ensures
* that we can enable/disable lazy stacking in port.c file. */
*( secureinitFPCCR ) &= ~( secureinitFPCCR_LSPENS_MASK );
/* TS = 1 ==> Treat FP registers as secure i.e. callee saved FP
* registers (S16-S31) are also pushed to stack on exception entry and
* restored on exception return. */
*( secureinitFPCCR ) |= ( secureinitFPCCR_TS_MASK );
}
}
/*-----------------------------------------------------------*/

View file

@ -0,0 +1,54 @@
/*
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
#ifndef __SECURE_INIT_H__
#define __SECURE_INIT_H__
/**
* @brief De-prioritizes the non-secure exceptions.
*
* This is needed to ensure that the non-secure PendSV runs at the lowest
* priority. Context switch is done in the non-secure PendSV handler.
*
* @note This function must be called in the handler mode. It is no-op if called
* in the thread mode.
*/
void SecureInit_DePrioritizeNSExceptions( void );
/**
* @brief Sets up the Floating Point Unit (FPU) for Non-Secure access.
*
* Also sets FPCCR.TS=1 to ensure that the content of the Floating Point
* Registers are not leaked to the non-secure side.
*
* @note This function must be called in the handler mode. It is no-op if called
* in the thread mode.
*/
void SecureInit_EnableNSFPUAccess( void );
#endif /* __SECURE_INIT_H__ */

View file

@ -0,0 +1,140 @@
/*
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
#ifndef __SECURE_PORT_MACROS_H__
#define __SECURE_PORT_MACROS_H__
/**
* @brief Byte alignment requirements.
*/
#define secureportBYTE_ALIGNMENT 8
#define secureportBYTE_ALIGNMENT_MASK ( 0x0007 )
/**
* @brief Macro to declare a function as non-secure callable.
*/
#if defined( __IAR_SYSTEMS_ICC__ )
#define secureportNON_SECURE_CALLABLE __cmse_nonsecure_entry __root
#else
#define secureportNON_SECURE_CALLABLE __attribute__( ( cmse_nonsecure_entry ) ) __attribute__( ( used ) )
#endif
/**
* @brief Set the secure PRIMASK value.
*/
#define secureportSET_SECURE_PRIMASK( ulPrimaskValue ) \
__asm volatile ( "msr primask, %0" : : "r" ( ulPrimaskValue ) : "memory" )
/**
* @brief Set the non-secure PRIMASK value.
*/
#define secureportSET_NON_SECURE_PRIMASK( ulPrimaskValue ) \
__asm volatile ( "msr primask_ns, %0" : : "r" ( ulPrimaskValue ) : "memory" )
/**
* @brief Read the PSP value in the given variable.
*/
#define secureportREAD_PSP( pucOutCurrentStackPointer ) \
__asm volatile ( "mrs %0, psp" : "=r" ( pucOutCurrentStackPointer ) )
/**
* @brief Set the PSP to the given value.
*/
#define secureportSET_PSP( pucCurrentStackPointer ) \
__asm volatile ( "msr psp, %0" : : "r" ( pucCurrentStackPointer ) )
/**
* @brief Read the PSPLIM value in the given variable.
*/
#define secureportREAD_PSPLIM( pucOutStackLimit ) \
__asm volatile ( "mrs %0, psplim" : "=r" ( pucOutStackLimit ) )
/**
* @brief Set the PSPLIM to the given value.
*/
#define secureportSET_PSPLIM( pucStackLimit ) \
__asm volatile ( "msr psplim, %0" : : "r" ( pucStackLimit ) )
/**
* @brief Set the NonSecure MSP to the given value.
*/
#define secureportSET_MSP_NS( pucMainStackPointer ) \
__asm volatile ( "msr msp_ns, %0" : : "r" ( pucMainStackPointer ) )
/**
* @brief Set the CONTROL register to the given value.
*/
#define secureportSET_CONTROL( ulControl ) \
__asm volatile ( "msr control, %0" : : "r" ( ulControl ) : "memory" )
/**
* @brief Read the Interrupt Program Status Register (IPSR) value in the given
* variable.
*/
#define secureportREAD_IPSR( ulIPSR ) \
__asm volatile ( "mrs %0, ipsr" : "=r" ( ulIPSR ) )
/**
* @brief PRIMASK value to enable interrupts.
*/
#define secureportPRIMASK_ENABLE_INTERRUPTS_VAL 0
/**
* @brief PRIMASK value to disable interrupts.
*/
#define secureportPRIMASK_DISABLE_INTERRUPTS_VAL 1
/**
* @brief Disable secure interrupts.
*/
#define secureportDISABLE_SECURE_INTERRUPTS() secureportSET_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL )
/**
* @brief Disable non-secure interrupts.
*
* This effectively disables context switches.
*/
#define secureportDISABLE_NON_SECURE_INTERRUPTS() secureportSET_NON_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL )
/**
* @brief Enable non-secure interrupts.
*/
#define secureportENABLE_NON_SECURE_INTERRUPTS() secureportSET_NON_SECURE_PRIMASK( secureportPRIMASK_ENABLE_INTERRUPTS_VAL )
/**
* @brief Assert definition.
*/
#define secureportASSERT( x ) \
if( ( x ) == 0 ) \
{ \
secureportDISABLE_SECURE_INTERRUPTS(); \
secureportDISABLE_NON_SECURE_INTERRUPTS(); \
for( ; ; ) {; } \
}
#endif /* __SECURE_PORT_MACROS_H__ */