Pre-allocate secure-side context structures

This commit improves ARMv8-M security by pre-allocating secure-side task
context structures and changing how tasks reference a secure-side
context structure when calling a secure function. The new configuration
constant secureconfigMAX_SECURE_CONTEXTS sets the number of secure
context structures to pre-allocate. secureconfigMAX_SECURE_CONTEXTS
defaults to 8 if left undefined.

Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>
diff --git a/portable/ARMv8M/secure/context/portable/GCC/ARM_CM23/secure_context_port.c b/portable/ARMv8M/secure/context/portable/GCC/ARM_CM23/secure_context_port.c
index 047ed8e..8677b22 100644
--- a/portable/ARMv8M/secure/context/portable/GCC/ARM_CM23/secure_context_port.c
+++ b/portable/ARMv8M/secure/context/portable/GCC/ARM_CM23/secure_context_port.c
@@ -36,56 +36,60 @@
     #error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.

 #endif

 

-secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle )

+void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext )

 {

-    /* xSecureContextHandle value is in r0. */

+    /* 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 = xSecureContextHandle->pucCurrentStackPointer, r2 = xSecureContextHandle->pucStackLimit. */

+        " .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. */

+            " ldmia r1!, {r3}               \n" /* Read CONTROL register value from task's stack. r3 = CONTROL. */

+            " msr control, r3               \n" /* CONTROL = r3. */

         #endif /* configENABLE_MPU */

-        "	msr psplim, r2							\n"/* PSPLIM = r2. */

-        "	msr psp, r1								\n"/* PSP = r1. */

-        "											\n"

-        " load_ctx_therad_mode:						\n"

-        "	nop										\n"

-        "											\n"

+        "                                   \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"

     );

 }

 /*-----------------------------------------------------------*/

 

-secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle )

+void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext )

 {

-    /* xSecureContextHandle value is in r0. */

+    /* 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. */

+        " .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_MPU == 1 )

-            "	mrs r2, control							\n"/* r2 = CONTROL. */

-            "	subs r1, r1, #4							\n"/* Make space for the CONTROL value on the stack. */

-            "	str r1, [r0]							\n"/* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */

-            "	stmia r1!, {r2}							\n"/* Store CONTROL value on the stack. */

+            " mrs r2, control               \n" /* r2 = CONTROL. */

+            " subs r1, r1, #4               \n" /* Make space for the CONTROL value on the stack. */

+            " str r1, [r0]                  \n" /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */

+            " stmia r1!, {r2}               \n" /* Store CONTROL value on the stack. */

         #else /* configENABLE_MPU */

-            "	str r1, [r0]							\n"/* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */

+            " str r1, [r0]                  \n" /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */

         #endif /* configENABLE_MPU */

-        "	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"

-        "	nop										\n"

-        "											\n"

+        "                                   \n"

+        " 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"

     );

 }

diff --git a/portable/ARMv8M/secure/context/portable/GCC/ARM_CM33/secure_context_port.c b/portable/ARMv8M/secure/context/portable/GCC/ARM_CM33/secure_context_port.c
index 4c6d0be..0731abe 100644
--- a/portable/ARMv8M/secure/context/portable/GCC/ARM_CM33/secure_context_port.c
+++ b/portable/ARMv8M/secure/context/portable/GCC/ARM_CM33/secure_context_port.c
@@ -32,57 +32,62 @@
 /* Secure port macros. */

 #include "secure_port_macros.h"

 

-secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle )

+void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext )

 {

-    /* xSecureContextHandle value is in r0. */

+    /* 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 = xSecureContextHandle->pucCurrentStackPointer, r2 = xSecureContextHandle->pucStackLimit. */

+        " .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. */

+            " ldmia r1!, {r3}               \n" /* Read CONTROL register value from task's stack. r3 = CONTROL. */

+            " msr control, r3               \n" /* CONTROL = r3. */

         #endif /* configENABLE_MPU */

-        "	msr psplim, r2							\n"/* PSPLIM = r2. */

-        "	msr psp, r1								\n"/* PSP = r1. */

-        "											\n"

-        " load_ctx_therad_mode:						\n"

-        "	nop										\n"

-        "											\n"

+        "                                   \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"

     );

 }

 /*-----------------------------------------------------------*/

 

-secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle )

+void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext )

 {

-    /* xSecureContextHandle value is in r0. */

+    /* 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. */

+        " .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 )

-            "	vstmdb r1!, {s0}						\n"/* Trigger the defferred stacking of FPU registers. */

-            "	vldmia r1!, {s0}						\n"/* Nullify the effect of the pervious statement. */

+            " vstmdb r1!, {s0}              \n" /* Trigger the defferred stacking of FPU registers. */

+            " vldmia r1!, {s0}              \n" /* Nullify the effect of the pervious statement. */

         #endif /* configENABLE_FPU */

+        "                                   \n"

         #if ( configENABLE_MPU == 1 )

-            "	mrs r2, control							\n"/* r2 = CONTROL. */

-            "	stmdb r1!, {r2}							\n"/* Store CONTROL value on the stack. */

+            " mrs r2, control               \n" /* r2 = CONTROL. */

+            " stmdb r1!, {r2}               \n" /* Store CONTROL value on the stack. */

         #endif /* configENABLE_MPU */

-        "	str r1, [r0]							\n"/* Save the top of stack in context. xSecureContextHandle->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"

-        "	nop										\n"

-        "											\n"

+        "                                   \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"

     );

 }

diff --git a/portable/ARMv8M/secure/context/portable/IAR/ARM_CM23/secure_context_port.c b/portable/ARMv8M/secure/context/portable/IAR/ARM_CM23/secure_context_port.c
deleted file mode 100644
index d8ca0f5..0000000
--- a/portable/ARMv8M/secure/context/portable/IAR/ARM_CM23/secure_context_port.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*

- * 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"

-

-/* Functions implemented in assembler file. */

-extern void SecureContext_LoadContextAsm( SecureContextHandle_t xSecureContextHandle );

-extern void SecureContext_SaveContextAsm( SecureContextHandle_t xSecureContextHandle );

-

-secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle )

-{

-    SecureContext_LoadContextAsm( xSecureContextHandle );

-}

-/*-----------------------------------------------------------*/

-

-secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle )

-{

-    SecureContext_SaveContextAsm( xSecureContextHandle );

-}

-/*-----------------------------------------------------------*/

diff --git a/portable/ARMv8M/secure/context/portable/IAR/ARM_CM23/secure_context_port_asm.s b/portable/ARMv8M/secure/context/portable/IAR/ARM_CM23/secure_context_port_asm.s
index 8fbb49a..cf245b9 100644
--- a/portable/ARMv8M/secure/context/portable/IAR/ARM_CM23/secure_context_port_asm.s
+++ b/portable/ARMv8M/secure/context/portable/IAR/ARM_CM23/secure_context_port_asm.s
@@ -26,52 +26,56 @@
  *

  */

 

-	SECTION .text:CODE:NOROOT(2)

-	THUMB

+    SECTION .text:CODE:NOROOT(2)

+    THUMB

 

-	PUBLIC SecureContext_LoadContextAsm

-	PUBLIC SecureContext_SaveContextAsm

+    PUBLIC SecureContext_LoadContextAsm

+    PUBLIC SecureContext_SaveContextAsm

 

 #if ( configENABLE_FPU == 1 )

-	#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.

+    #error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.

 #endif

 /*-----------------------------------------------------------*/

 

 SecureContext_LoadContextAsm:

-	/* xSecureContextHandle value is in r0. */

-	mrs r1, ipsr							/* r1 = IPSR. */

-	cbz r1, load_ctx_therad_mode			/* Do nothing if the processor is running in the Thread Mode. */

-	ldmia r0!, {r1, r2}						/* r1 = xSecureContextHandle->pucCurrentStackPointer, r2 = xSecureContextHandle->pucStackLimit. */

-#if ( configENABLE_MPU == 1 )

-	ldmia r1!, {r3}							/* Read CONTROL register value from task's stack. r3 = CONTROL. */

-	msr control, r3							/* CONTROL = r3. */

-#endif /* configENABLE_MPU */

-	msr psplim, r2							/* PSPLIM = r2. */

-	msr psp, r1								/* PSP = r1. */

+    /* pxSecureContext value is in r0. */

+    mrs r1, ipsr                    /* r1 = IPSR. */

+    cbz r1, load_ctx_therad_mode    /* Do nothing if the processor is running in the Thread Mode. */

+    ldmia r0!, {r1, r2}             /* r1 = pxSecureContext->pucCurrentStackPointer, r2 = pxSecureContext->pucStackLimit. */

 

-	load_ctx_therad_mode:

-		bx lr

+#if ( configENABLE_MPU == 1 )

+    ldmia r1!, {r3}                 /* Read CONTROL register value from task's stack. r3 = CONTROL. */

+    msr control, r3                 /* CONTROL = r3. */

+#endif /* configENABLE_MPU */

+

+    msr psplim, r2                  /* PSPLIM = r2. */

+    msr psp, r1                     /* PSP = r1. */

+

+    load_ctx_therad_mode:

+        bx lr

 /*-----------------------------------------------------------*/

 

 SecureContext_SaveContextAsm:

-	/* xSecureContextHandle value is in r0. */

-	mrs r1, ipsr							/* r1 = IPSR. */

-	cbz r1, save_ctx_therad_mode			/* Do nothing if the processor is running in the Thread Mode. */

-	mrs r1, psp								/* r1 = PSP. */

-#if ( configENABLE_MPU == 1 )

-	mrs r2, control							/* r2 = CONTROL. */

-	subs r1, r1, #4							/* Make space for the CONTROL value on the stack. */

-	str r1, [r0]							/* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */

-	stmia r1!, {r2}							/* Store CONTROL value on the stack. */

-#else /* configENABLE_MPU */

-	str r1, [r0]							/* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */

-#endif /* configENABLE_MPU */

-	movs r1, #0								/* r1 = securecontextNO_STACK. */

-	msr psplim, r1							/* PSPLIM = securecontextNO_STACK. */

-	msr psp, r1								/* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */

+    /* pxSecureContext value is in r0. */

+    mrs r1, ipsr                    /* r1 = IPSR. */

+    cbz r1, save_ctx_therad_mode    /* Do nothing if the processor is running in the Thread Mode. */

+    mrs r1, psp                     /* r1 = PSP. */

 

-	save_ctx_therad_mode:

-		bx lr

+#if ( configENABLE_MPU == 1 )

+    mrs r2, control                 /* r2 = CONTROL. */

+    subs r1, r1, #4                 /* Make space for the CONTROL value on the stack. */

+    str r1, [r0]                    /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */

+    stmia r1!, {r2}                 /* Store CONTROL value on the stack. */

+#else /* configENABLE_MPU */

+    str r1, [r0]                    /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */

+#endif /* configENABLE_MPU */

+

+    movs r1, #0                     /* r1 = securecontextNO_STACK. */

+    msr psplim, r1                  /* PSPLIM = securecontextNO_STACK. */

+    msr psp, r1                     /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */

+

+    save_ctx_therad_mode:

+        bx lr

 /*-----------------------------------------------------------*/

 

-	END

+    END

diff --git a/portable/ARMv8M/secure/context/portable/IAR/ARM_CM33/secure_context_port.c b/portable/ARMv8M/secure/context/portable/IAR/ARM_CM33/secure_context_port.c
deleted file mode 100644
index d8ca0f5..0000000
--- a/portable/ARMv8M/secure/context/portable/IAR/ARM_CM33/secure_context_port.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*

- * 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"

-

-/* Functions implemented in assembler file. */

-extern void SecureContext_LoadContextAsm( SecureContextHandle_t xSecureContextHandle );

-extern void SecureContext_SaveContextAsm( SecureContextHandle_t xSecureContextHandle );

-

-secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle )

-{

-    SecureContext_LoadContextAsm( xSecureContextHandle );

-}

-/*-----------------------------------------------------------*/

-

-secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle )

-{

-    SecureContext_SaveContextAsm( xSecureContextHandle );

-}

-/*-----------------------------------------------------------*/

diff --git a/portable/ARMv8M/secure/context/portable/IAR/ARM_CM33/secure_context_port_asm.s b/portable/ARMv8M/secure/context/portable/IAR/ARM_CM33/secure_context_port_asm.s
index 297679b..0df0a1b 100644
--- a/portable/ARMv8M/secure/context/portable/IAR/ARM_CM33/secure_context_port_asm.s
+++ b/portable/ARMv8M/secure/context/portable/IAR/ARM_CM33/secure_context_port_asm.s
@@ -26,49 +26,54 @@
  *

  */

 

-	SECTION .text:CODE:NOROOT(2)

-	THUMB

+    SECTION .text:CODE:NOROOT(2)

+    THUMB

 

-	PUBLIC SecureContext_LoadContextAsm

-	PUBLIC SecureContext_SaveContextAsm

+    PUBLIC SecureContext_LoadContextAsm

+    PUBLIC SecureContext_SaveContextAsm

 /*-----------------------------------------------------------*/

 

 SecureContext_LoadContextAsm:

-	/* xSecureContextHandle value is in r0. */

-	mrs r1, ipsr							/* r1 = IPSR. */

-	cbz r1, load_ctx_therad_mode			/* Do nothing if the processor is running in the Thread Mode. */

-	ldmia r0!, {r1, r2}						/* r1 = xSecureContextHandle->pucCurrentStackPointer, r2 = xSecureContextHandle->pucStackLimit. */

-#if ( configENABLE_MPU == 1 )

-	ldmia r1!, {r3}							/* Read CONTROL register value from task's stack. r3 = CONTROL. */

-	msr control, r3							/* CONTROL = r3. */

-#endif /* configENABLE_MPU */

-	msr psplim, r2							/* PSPLIM = r2. */

-	msr psp, r1								/* PSP = r1. */

+    /* pxSecureContext value is in r0. */

+    mrs r1, ipsr                        /* r1 = IPSR. */

+    cbz r1, load_ctx_therad_mode        /* Do nothing if the processor is running in the Thread Mode. */

+    ldmia r0!, {r1, r2}                 /* r1 = pxSecureContext->pucCurrentStackPointer, r2 = pxSecureContext->pucStackLimit. */

 

-	load_ctx_therad_mode:

-		bx lr

+#if ( configENABLE_MPU == 1 )

+    ldmia r1!, {r3}                     /* Read CONTROL register value from task's stack. r3 = CONTROL. */

+    msr control, r3                     /* CONTROL = r3. */

+#endif /* configENABLE_MPU */

+

+    msr psplim, r2                      /* PSPLIM = r2. */

+    msr psp, r1                         /* PSP = r1. */

+

+    load_ctx_therad_mode:

+        bx lr

 /*-----------------------------------------------------------*/

 

 SecureContext_SaveContextAsm:

-	/* xSecureContextHandle value is in r0. */

-	mrs r1, ipsr							/* r1 = IPSR. */

-	cbz r1, save_ctx_therad_mode			/* Do nothing if the processor is running in the Thread Mode. */

-	mrs r1, psp								/* r1 = PSP. */

-#if ( configENABLE_FPU == 1 )

-	vstmdb r1!, {s0}						/* Trigger the defferred stacking of FPU registers. */

-	vldmia r1!, {s0}						/* Nullify the effect of the pervious statement. */

-#endif /* configENABLE_FPU */

-#if ( configENABLE_MPU == 1 )

-	mrs r2, control							/* r2 = CONTROL. */

-	stmdb r1!, {r2}							/* Store CONTROL value on the stack. */

-#endif /* configENABLE_MPU */

-	str r1, [r0]							/* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */

-	movs r1, #0								/* r1 = securecontextNO_STACK. */

-	msr psplim, r1							/* PSPLIM = securecontextNO_STACK. */

-	msr psp, r1								/* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */

+    /* pxSecureContext value is in r0. */

+    mrs r1, ipsr                        /* r1 = IPSR. */

+    cbz r1, save_ctx_therad_mode        /* Do nothing if the processor is running in the Thread Mode. */

+    mrs r1, psp                         /* r1 = PSP. */

 

-	save_ctx_therad_mode:

-		bx lr

+#if ( configENABLE_FPU == 1 )

+    vstmdb r1!, {s0}                    /* Trigger the defferred stacking of FPU registers. */

+    vldmia r1!, {s0}                    /* Nullify the effect of the pervious statement. */

+#endif /* configENABLE_FPU */

+

+#if ( configENABLE_MPU == 1 )

+    mrs r2, control                     /* r2 = CONTROL. */

+    stmdb r1!, {r2}                     /* Store CONTROL value on the stack. */

+#endif /* configENABLE_MPU */

+

+    str r1, [r0]                        /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */

+    movs r1, #0                         /* r1 = securecontextNO_STACK. */

+    msr psplim, r1                      /* PSPLIM = securecontextNO_STACK. */

+    msr psp, r1                         /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */

+

+    save_ctx_therad_mode:

+        bx lr

 /*-----------------------------------------------------------*/

 

-	END

+    END

diff --git a/portable/ARMv8M/secure/context/secure_context.c b/portable/ARMv8M/secure/context/secure_context.c
index deede89..96a5662 100644
--- a/portable/ARMv8M/secure/context/secure_context.c
+++ b/portable/ARMv8M/secure/context/secure_context.c
@@ -50,25 +50,74 @@
  * Bit[1] - 1 --> Thread mode uses PSP.

  */

 #define securecontextCONTROL_VALUE_UNPRIVILEGED    0x03

+

+/**

+ * @brief Invalid context ID.

+ */

+#define securecontextINVALID_CONTEXT_ID            0UL

+

+/**

+ * @brief Maximum number of secure contexts.

+ */

+#ifndef secureconfigMAX_SECURE_CONTEXTS

+    #define secureconfigMAX_SECURE_CONTEXTS        8UL

+#endif

 /*-----------------------------------------------------------*/

 

 /**

- * @brief Structure to represent secure context.

- *

- * @note Since stack grows down, pucStackStart is the highest address while

- * pucStackLimit is the first addess of the allocated memory.

+ * @brief Pre-allocated array of secure contexts.

  */

-typedef struct SecureContext

+SecureContext_t xSecureContexts[ secureconfigMAX_SECURE_CONTEXTS ];

+/*-----------------------------------------------------------*/

+

+/**

+ * @brief Get a free context from the secure context pool (xSecureContexts).

+ *

+ * @return Index of a free context in the xSecureContexts array.

+ */

+static uint32_t ulGetSecureContext( void );

+

+/**

+ * @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 )

 {

-    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. */

-} SecureContext_t;

+    uint32_t ulSecureContextIndex;

+

+    for( ulSecureContextIndex = 0; ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS; ulSecureContextIndex++ )

+    {

+        if( ( xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer == NULL ) &&

+            ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == NULL ) &&

+            ( xSecureContexts[ ulSecureContextIndex ].pucStackStart == NULL ) )

+        {

+            break;

+        }

+    }

+

+    return ulSecureContextIndex;

+}

+/*-----------------------------------------------------------*/

+

+static void vReturnSecureContext( uint32_t ulSecureContextIndex )

+{

+    xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = NULL;

+    xSecureContexts[ ulSecureContextIndex ].pucStackLimit = NULL;

+    xSecureContexts[ ulSecureContextIndex ].pucStackStart = NULL;

+}

 /*-----------------------------------------------------------*/

 

 secureportNON_SECURE_CALLABLE void SecureContext_Init( void )

 {

-    uint32_t ulIPSR;

+    uint32_t ulIPSR, i;

 

     /* Read the Interrupt Program Status Register (IPSR) value. */

     secureportREAD_IPSR( ulIPSR );

@@ -81,6 +130,14 @@
         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;

+        }

+

         #if ( configENABLE_MPU == 1 )

             {

                 /* Configure thread mode to use PSP and to be unprivileged. */

@@ -88,7 +145,7 @@
             }

         #else /* configENABLE_MPU */

             {

-                /* Configure thread mode to use PSP and to be privileged.. */

+                /* Configure thread mode to use PSP and to be privileged. */

                 secureportSET_CONTROL( securecontextCONTROL_VALUE_PRIVILEGED );

             }

         #endif /* configENABLE_MPU */

@@ -104,8 +161,8 @@
 #endif /* configENABLE_MPU */

 {

     uint8_t * pucStackMemory = NULL;

-    uint32_t ulIPSR;

-    SecureContextHandle_t xSecureContextHandle = NULL;

+    uint32_t ulIPSR, ulSecureContextIndex;

+    SecureContextHandle_t xSecureContextHandle;

 

     #if ( configENABLE_MPU == 1 )

         uint32_t * pulCurrentStackPointer = NULL;

@@ -118,10 +175,11 @@
      * when the processor is running in the Thread Mode. */

     if( ulIPSR != 0 )

     {

-        /* Allocate the context structure. */

-        xSecureContextHandle = ( SecureContextHandle_t ) pvPortMalloc( sizeof( SecureContext_t ) );

+        /* Ontain a free secure context. */

+        ulSecureContextIndex = ulGetSecureContext();

 

-        if( xSecureContextHandle != NULL )

+        /* Were we able to get a free context? */

+        if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS )

         {

             /* Allocate the stack space. */

             pucStackMemory = pvPortMalloc( ulSecureStackSize );

@@ -134,18 +192,18 @@
                  * 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. */

-                xSecureContextHandle->pucStackStart = pucStackMemory + ulSecureStackSize;

+                xSecureContexts[ ulSecureContextIndex ].pucStackStart = pucStackMemory + ulSecureStackSize;

 

                 /* The stack cannot go beyond this location. This value is

                  * programmed in the PSPLIM register on context switch.*/

-                xSecureContextHandle->pucStackLimit = pucStackMemory;

+                xSecureContexts[ ulSecureContextIndex ].pucStackLimit = pucStackMemory;

 

                 #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 * ) xSecureContextHandle->pucStackStart;

+                        pulCurrentStackPointer = ( uint32_t * ) xSecureContexts[ ulSecureContextIndex ].pucStackStart;

                         pulCurrentStackPointer--;

 

                         if( ulIsTaskPrivileged )

@@ -159,22 +217,22 @@
 

                         /* Store the current stack pointer. This value is programmed in

                          * the PSP register on context switch. */

-                        xSecureContextHandle->pucCurrentStackPointer = ( uint8_t * ) pulCurrentStackPointer;

+                        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. */

-                        xSecureContextHandle->pucCurrentStackPointer = xSecureContextHandle->pucStackStart;

+                        xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = xSecureContexts[ ulSecureContextIndex ].pucStackStart;

                     }

                 #endif /* configENABLE_MPU */

+

+                /* Ensure to never return 0 as a valid context handle. */

+                xSecureContextHandle = ulSecureContextIndex + 1UL;

             }

             else

             {

-                /* Free the context to avoid memory leak and make sure to return

-                 * NULL to indicate failure. */

-                vPortFree( xSecureContextHandle );

-                xSecureContextHandle = NULL;

+                xSecureContextHandle = securecontextINVALID_CONTEXT_ID;

             }

         }

     }

@@ -185,7 +243,7 @@
 

 secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle )

 {

-    uint32_t ulIPSR;

+    uint32_t ulIPSR, ulSecureContextIndex;

 

     /* Read the Interrupt Program Status Register (IPSR) value. */

     secureportREAD_IPSR( ulIPSR );

@@ -194,14 +252,43 @@
      * when the processor is running in the Thread Mode. */

     if( ulIPSR != 0 )

     {

-        /* Ensure that valid parameters are passed. */

-        secureportASSERT( xSecureContextHandle != NULL );

+        /* Only free if a valid context handle is passed. */

+        if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )

+        {

+            ulSecureContextIndex = xSecureContextHandle - 1UL;

 

-        /* Free the stack space. */

-        vPortFree( xSecureContextHandle->pucStackLimit );

+            /* Free the stack space. */

+            vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );

 

-        /* Free the context itself. */

-        vPortFree( xSecureContextHandle );

+            /* Return the context back to the free contexts pool. */

+            vReturnSecureContext( ulSecureContextIndex );

+        }

+    }

+}

+/*-----------------------------------------------------------*/

+

+secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle )

+{

+    uint32_t ulSecureContextIndex;

+

+    if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )

+    {

+        ulSecureContextIndex = xSecureContextHandle - 1UL;

+

+        SecureContext_LoadContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );

+    }

+}

+/*-----------------------------------------------------------*/

+

+secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle )

+{

+    uint32_t ulSecureContextIndex;

+

+    if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )

+    {

+        ulSecureContextIndex = xSecureContextHandle - 1UL;

+

+        SecureContext_SaveContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );

     }

 }

 /*-----------------------------------------------------------*/

diff --git a/portable/ARMv8M/secure/context/secure_context.h b/portable/ARMv8M/secure/context/secure_context.h
index 77a9332..b7a3ba5 100644
--- a/portable/ARMv8M/secure/context/secure_context.h
+++ b/portable/ARMv8M/secure/context/secure_context.h
@@ -36,15 +36,29 @@
 #include "FreeRTOSConfig.h"

 

 /**

- * @brief PSP value when no task's context is loaded.

+ * @brief PSP value when no secure context is loaded.

  */

 #define securecontextNO_STACK    0x0

+/*-----------------------------------------------------------*/

 

 /**

- * @brief Opaque handle.

+ * @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.

  */

-struct SecureContext;

-typedef struct SecureContext * SecureContextHandle_t;

+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. */

+} SecureContext_t;

+/*-----------------------------------------------------------*/

+

+/**

+ * @brief Opaque handle for a secure context.

+ */

+typedef uint32_t SecureContextHandle_t;

 /*-----------------------------------------------------------*/

 

 /**

diff --git a/portable/ARMv8M/secure/heap/secure_heap.c b/portable/ARMv8M/secure/heap/secure_heap.c
index 0100ad0..099b01f 100644
--- a/portable/ARMv8M/secure/heap/secure_heap.c
+++ b/portable/ARMv8M/secure/heap/secure_heap.c
@@ -38,7 +38,9 @@
 /**

  * @brief Total heap size.

  */

-#define secureconfigTOTAL_HEAP_SIZE    ( ( ( size_t ) ( 10 * 1024 ) ) )

+#ifndef secureconfigTOTAL_HEAP_SIZE

+    #define secureconfigTOTAL_HEAP_SIZE    ( ( ( size_t ) ( 10 * 1024 ) ) )

+#endif

 

 /* No test marker by default. */

 #ifndef mtCOVERAGE_TEST_MARKER

diff --git a/portable/GCC/ARM_CM23/secure/secure_context.c b/portable/GCC/ARM_CM23/secure/secure_context.c
index deede89..96a5662 100644
--- a/portable/GCC/ARM_CM23/secure/secure_context.c
+++ b/portable/GCC/ARM_CM23/secure/secure_context.c
@@ -50,25 +50,74 @@
  * Bit[1] - 1 --> Thread mode uses PSP.

  */

 #define securecontextCONTROL_VALUE_UNPRIVILEGED    0x03

+

+/**

+ * @brief Invalid context ID.

+ */

+#define securecontextINVALID_CONTEXT_ID            0UL

+

+/**

+ * @brief Maximum number of secure contexts.

+ */

+#ifndef secureconfigMAX_SECURE_CONTEXTS

+    #define secureconfigMAX_SECURE_CONTEXTS        8UL

+#endif

 /*-----------------------------------------------------------*/

 

 /**

- * @brief Structure to represent secure context.

- *

- * @note Since stack grows down, pucStackStart is the highest address while

- * pucStackLimit is the first addess of the allocated memory.

+ * @brief Pre-allocated array of secure contexts.

  */

-typedef struct SecureContext

+SecureContext_t xSecureContexts[ secureconfigMAX_SECURE_CONTEXTS ];

+/*-----------------------------------------------------------*/

+

+/**

+ * @brief Get a free context from the secure context pool (xSecureContexts).

+ *

+ * @return Index of a free context in the xSecureContexts array.

+ */

+static uint32_t ulGetSecureContext( void );

+

+/**

+ * @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 )

 {

-    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. */

-} SecureContext_t;

+    uint32_t ulSecureContextIndex;

+

+    for( ulSecureContextIndex = 0; ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS; ulSecureContextIndex++ )

+    {

+        if( ( xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer == NULL ) &&

+            ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == NULL ) &&

+            ( xSecureContexts[ ulSecureContextIndex ].pucStackStart == NULL ) )

+        {

+            break;

+        }

+    }

+

+    return ulSecureContextIndex;

+}

+/*-----------------------------------------------------------*/

+

+static void vReturnSecureContext( uint32_t ulSecureContextIndex )

+{

+    xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = NULL;

+    xSecureContexts[ ulSecureContextIndex ].pucStackLimit = NULL;

+    xSecureContexts[ ulSecureContextIndex ].pucStackStart = NULL;

+}

 /*-----------------------------------------------------------*/

 

 secureportNON_SECURE_CALLABLE void SecureContext_Init( void )

 {

-    uint32_t ulIPSR;

+    uint32_t ulIPSR, i;

 

     /* Read the Interrupt Program Status Register (IPSR) value. */

     secureportREAD_IPSR( ulIPSR );

@@ -81,6 +130,14 @@
         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;

+        }

+

         #if ( configENABLE_MPU == 1 )

             {

                 /* Configure thread mode to use PSP and to be unprivileged. */

@@ -88,7 +145,7 @@
             }

         #else /* configENABLE_MPU */

             {

-                /* Configure thread mode to use PSP and to be privileged.. */

+                /* Configure thread mode to use PSP and to be privileged. */

                 secureportSET_CONTROL( securecontextCONTROL_VALUE_PRIVILEGED );

             }

         #endif /* configENABLE_MPU */

@@ -104,8 +161,8 @@
 #endif /* configENABLE_MPU */

 {

     uint8_t * pucStackMemory = NULL;

-    uint32_t ulIPSR;

-    SecureContextHandle_t xSecureContextHandle = NULL;

+    uint32_t ulIPSR, ulSecureContextIndex;

+    SecureContextHandle_t xSecureContextHandle;

 

     #if ( configENABLE_MPU == 1 )

         uint32_t * pulCurrentStackPointer = NULL;

@@ -118,10 +175,11 @@
      * when the processor is running in the Thread Mode. */

     if( ulIPSR != 0 )

     {

-        /* Allocate the context structure. */

-        xSecureContextHandle = ( SecureContextHandle_t ) pvPortMalloc( sizeof( SecureContext_t ) );

+        /* Ontain a free secure context. */

+        ulSecureContextIndex = ulGetSecureContext();

 

-        if( xSecureContextHandle != NULL )

+        /* Were we able to get a free context? */

+        if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS )

         {

             /* Allocate the stack space. */

             pucStackMemory = pvPortMalloc( ulSecureStackSize );

@@ -134,18 +192,18 @@
                  * 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. */

-                xSecureContextHandle->pucStackStart = pucStackMemory + ulSecureStackSize;

+                xSecureContexts[ ulSecureContextIndex ].pucStackStart = pucStackMemory + ulSecureStackSize;

 

                 /* The stack cannot go beyond this location. This value is

                  * programmed in the PSPLIM register on context switch.*/

-                xSecureContextHandle->pucStackLimit = pucStackMemory;

+                xSecureContexts[ ulSecureContextIndex ].pucStackLimit = pucStackMemory;

 

                 #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 * ) xSecureContextHandle->pucStackStart;

+                        pulCurrentStackPointer = ( uint32_t * ) xSecureContexts[ ulSecureContextIndex ].pucStackStart;

                         pulCurrentStackPointer--;

 

                         if( ulIsTaskPrivileged )

@@ -159,22 +217,22 @@
 

                         /* Store the current stack pointer. This value is programmed in

                          * the PSP register on context switch. */

-                        xSecureContextHandle->pucCurrentStackPointer = ( uint8_t * ) pulCurrentStackPointer;

+                        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. */

-                        xSecureContextHandle->pucCurrentStackPointer = xSecureContextHandle->pucStackStart;

+                        xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = xSecureContexts[ ulSecureContextIndex ].pucStackStart;

                     }

                 #endif /* configENABLE_MPU */

+

+                /* Ensure to never return 0 as a valid context handle. */

+                xSecureContextHandle = ulSecureContextIndex + 1UL;

             }

             else

             {

-                /* Free the context to avoid memory leak and make sure to return

-                 * NULL to indicate failure. */

-                vPortFree( xSecureContextHandle );

-                xSecureContextHandle = NULL;

+                xSecureContextHandle = securecontextINVALID_CONTEXT_ID;

             }

         }

     }

@@ -185,7 +243,7 @@
 

 secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle )

 {

-    uint32_t ulIPSR;

+    uint32_t ulIPSR, ulSecureContextIndex;

 

     /* Read the Interrupt Program Status Register (IPSR) value. */

     secureportREAD_IPSR( ulIPSR );

@@ -194,14 +252,43 @@
      * when the processor is running in the Thread Mode. */

     if( ulIPSR != 0 )

     {

-        /* Ensure that valid parameters are passed. */

-        secureportASSERT( xSecureContextHandle != NULL );

+        /* Only free if a valid context handle is passed. */

+        if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )

+        {

+            ulSecureContextIndex = xSecureContextHandle - 1UL;

 

-        /* Free the stack space. */

-        vPortFree( xSecureContextHandle->pucStackLimit );

+            /* Free the stack space. */

+            vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );

 

-        /* Free the context itself. */

-        vPortFree( xSecureContextHandle );

+            /* Return the context back to the free contexts pool. */

+            vReturnSecureContext( ulSecureContextIndex );

+        }

+    }

+}

+/*-----------------------------------------------------------*/

+

+secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle )

+{

+    uint32_t ulSecureContextIndex;

+

+    if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )

+    {

+        ulSecureContextIndex = xSecureContextHandle - 1UL;

+

+        SecureContext_LoadContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );

+    }

+}

+/*-----------------------------------------------------------*/

+

+secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle )

+{

+    uint32_t ulSecureContextIndex;

+

+    if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )

+    {

+        ulSecureContextIndex = xSecureContextHandle - 1UL;

+

+        SecureContext_SaveContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );

     }

 }

 /*-----------------------------------------------------------*/

diff --git a/portable/GCC/ARM_CM23/secure/secure_context.h b/portable/GCC/ARM_CM23/secure/secure_context.h
index 77a9332..b7a3ba5 100644
--- a/portable/GCC/ARM_CM23/secure/secure_context.h
+++ b/portable/GCC/ARM_CM23/secure/secure_context.h
@@ -36,15 +36,29 @@
 #include "FreeRTOSConfig.h"

 

 /**

- * @brief PSP value when no task's context is loaded.

+ * @brief PSP value when no secure context is loaded.

  */

 #define securecontextNO_STACK    0x0

+/*-----------------------------------------------------------*/

 

 /**

- * @brief Opaque handle.

+ * @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.

  */

-struct SecureContext;

-typedef struct SecureContext * SecureContextHandle_t;

+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. */

+} SecureContext_t;

+/*-----------------------------------------------------------*/

+

+/**

+ * @brief Opaque handle for a secure context.

+ */

+typedef uint32_t SecureContextHandle_t;

 /*-----------------------------------------------------------*/

 

 /**

diff --git a/portable/GCC/ARM_CM23/secure/secure_context_port.c b/portable/GCC/ARM_CM23/secure/secure_context_port.c
index 047ed8e..8677b22 100644
--- a/portable/GCC/ARM_CM23/secure/secure_context_port.c
+++ b/portable/GCC/ARM_CM23/secure/secure_context_port.c
@@ -36,56 +36,60 @@
     #error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.

 #endif

 

-secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle )

+void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext )

 {

-    /* xSecureContextHandle value is in r0. */

+    /* 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 = xSecureContextHandle->pucCurrentStackPointer, r2 = xSecureContextHandle->pucStackLimit. */

+        " .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. */

+            " ldmia r1!, {r3}               \n" /* Read CONTROL register value from task's stack. r3 = CONTROL. */

+            " msr control, r3               \n" /* CONTROL = r3. */

         #endif /* configENABLE_MPU */

-        "	msr psplim, r2							\n"/* PSPLIM = r2. */

-        "	msr psp, r1								\n"/* PSP = r1. */

-        "											\n"

-        " load_ctx_therad_mode:						\n"

-        "	nop										\n"

-        "											\n"

+        "                                   \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"

     );

 }

 /*-----------------------------------------------------------*/

 

-secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle )

+void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext )

 {

-    /* xSecureContextHandle value is in r0. */

+    /* 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. */

+        " .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_MPU == 1 )

-            "	mrs r2, control							\n"/* r2 = CONTROL. */

-            "	subs r1, r1, #4							\n"/* Make space for the CONTROL value on the stack. */

-            "	str r1, [r0]							\n"/* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */

-            "	stmia r1!, {r2}							\n"/* Store CONTROL value on the stack. */

+            " mrs r2, control               \n" /* r2 = CONTROL. */

+            " subs r1, r1, #4               \n" /* Make space for the CONTROL value on the stack. */

+            " str r1, [r0]                  \n" /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */

+            " stmia r1!, {r2}               \n" /* Store CONTROL value on the stack. */

         #else /* configENABLE_MPU */

-            "	str r1, [r0]							\n"/* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */

+            " str r1, [r0]                  \n" /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */

         #endif /* configENABLE_MPU */

-        "	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"

-        "	nop										\n"

-        "											\n"

+        "                                   \n"

+        " 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"

     );

 }

diff --git a/portable/GCC/ARM_CM23/secure/secure_heap.c b/portable/GCC/ARM_CM23/secure/secure_heap.c
index 0100ad0..099b01f 100644
--- a/portable/GCC/ARM_CM23/secure/secure_heap.c
+++ b/portable/GCC/ARM_CM23/secure/secure_heap.c
@@ -38,7 +38,9 @@
 /**

  * @brief Total heap size.

  */

-#define secureconfigTOTAL_HEAP_SIZE    ( ( ( size_t ) ( 10 * 1024 ) ) )

+#ifndef secureconfigTOTAL_HEAP_SIZE

+    #define secureconfigTOTAL_HEAP_SIZE    ( ( ( size_t ) ( 10 * 1024 ) ) )

+#endif

 

 /* No test marker by default. */

 #ifndef mtCOVERAGE_TEST_MARKER

diff --git a/portable/GCC/ARM_CM33/secure/secure_context.c b/portable/GCC/ARM_CM33/secure/secure_context.c
index deede89..96a5662 100644
--- a/portable/GCC/ARM_CM33/secure/secure_context.c
+++ b/portable/GCC/ARM_CM33/secure/secure_context.c
@@ -50,25 +50,74 @@
  * Bit[1] - 1 --> Thread mode uses PSP.

  */

 #define securecontextCONTROL_VALUE_UNPRIVILEGED    0x03

+

+/**

+ * @brief Invalid context ID.

+ */

+#define securecontextINVALID_CONTEXT_ID            0UL

+

+/**

+ * @brief Maximum number of secure contexts.

+ */

+#ifndef secureconfigMAX_SECURE_CONTEXTS

+    #define secureconfigMAX_SECURE_CONTEXTS        8UL

+#endif

 /*-----------------------------------------------------------*/

 

 /**

- * @brief Structure to represent secure context.

- *

- * @note Since stack grows down, pucStackStart is the highest address while

- * pucStackLimit is the first addess of the allocated memory.

+ * @brief Pre-allocated array of secure contexts.

  */

-typedef struct SecureContext

+SecureContext_t xSecureContexts[ secureconfigMAX_SECURE_CONTEXTS ];

+/*-----------------------------------------------------------*/

+

+/**

+ * @brief Get a free context from the secure context pool (xSecureContexts).

+ *

+ * @return Index of a free context in the xSecureContexts array.

+ */

+static uint32_t ulGetSecureContext( void );

+

+/**

+ * @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 )

 {

-    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. */

-} SecureContext_t;

+    uint32_t ulSecureContextIndex;

+

+    for( ulSecureContextIndex = 0; ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS; ulSecureContextIndex++ )

+    {

+        if( ( xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer == NULL ) &&

+            ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == NULL ) &&

+            ( xSecureContexts[ ulSecureContextIndex ].pucStackStart == NULL ) )

+        {

+            break;

+        }

+    }

+

+    return ulSecureContextIndex;

+}

+/*-----------------------------------------------------------*/

+

+static void vReturnSecureContext( uint32_t ulSecureContextIndex )

+{

+    xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = NULL;

+    xSecureContexts[ ulSecureContextIndex ].pucStackLimit = NULL;

+    xSecureContexts[ ulSecureContextIndex ].pucStackStart = NULL;

+}

 /*-----------------------------------------------------------*/

 

 secureportNON_SECURE_CALLABLE void SecureContext_Init( void )

 {

-    uint32_t ulIPSR;

+    uint32_t ulIPSR, i;

 

     /* Read the Interrupt Program Status Register (IPSR) value. */

     secureportREAD_IPSR( ulIPSR );

@@ -81,6 +130,14 @@
         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;

+        }

+

         #if ( configENABLE_MPU == 1 )

             {

                 /* Configure thread mode to use PSP and to be unprivileged. */

@@ -88,7 +145,7 @@
             }

         #else /* configENABLE_MPU */

             {

-                /* Configure thread mode to use PSP and to be privileged.. */

+                /* Configure thread mode to use PSP and to be privileged. */

                 secureportSET_CONTROL( securecontextCONTROL_VALUE_PRIVILEGED );

             }

         #endif /* configENABLE_MPU */

@@ -104,8 +161,8 @@
 #endif /* configENABLE_MPU */

 {

     uint8_t * pucStackMemory = NULL;

-    uint32_t ulIPSR;

-    SecureContextHandle_t xSecureContextHandle = NULL;

+    uint32_t ulIPSR, ulSecureContextIndex;

+    SecureContextHandle_t xSecureContextHandle;

 

     #if ( configENABLE_MPU == 1 )

         uint32_t * pulCurrentStackPointer = NULL;

@@ -118,10 +175,11 @@
      * when the processor is running in the Thread Mode. */

     if( ulIPSR != 0 )

     {

-        /* Allocate the context structure. */

-        xSecureContextHandle = ( SecureContextHandle_t ) pvPortMalloc( sizeof( SecureContext_t ) );

+        /* Ontain a free secure context. */

+        ulSecureContextIndex = ulGetSecureContext();

 

-        if( xSecureContextHandle != NULL )

+        /* Were we able to get a free context? */

+        if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS )

         {

             /* Allocate the stack space. */

             pucStackMemory = pvPortMalloc( ulSecureStackSize );

@@ -134,18 +192,18 @@
                  * 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. */

-                xSecureContextHandle->pucStackStart = pucStackMemory + ulSecureStackSize;

+                xSecureContexts[ ulSecureContextIndex ].pucStackStart = pucStackMemory + ulSecureStackSize;

 

                 /* The stack cannot go beyond this location. This value is

                  * programmed in the PSPLIM register on context switch.*/

-                xSecureContextHandle->pucStackLimit = pucStackMemory;

+                xSecureContexts[ ulSecureContextIndex ].pucStackLimit = pucStackMemory;

 

                 #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 * ) xSecureContextHandle->pucStackStart;

+                        pulCurrentStackPointer = ( uint32_t * ) xSecureContexts[ ulSecureContextIndex ].pucStackStart;

                         pulCurrentStackPointer--;

 

                         if( ulIsTaskPrivileged )

@@ -159,22 +217,22 @@
 

                         /* Store the current stack pointer. This value is programmed in

                          * the PSP register on context switch. */

-                        xSecureContextHandle->pucCurrentStackPointer = ( uint8_t * ) pulCurrentStackPointer;

+                        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. */

-                        xSecureContextHandle->pucCurrentStackPointer = xSecureContextHandle->pucStackStart;

+                        xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = xSecureContexts[ ulSecureContextIndex ].pucStackStart;

                     }

                 #endif /* configENABLE_MPU */

+

+                /* Ensure to never return 0 as a valid context handle. */

+                xSecureContextHandle = ulSecureContextIndex + 1UL;

             }

             else

             {

-                /* Free the context to avoid memory leak and make sure to return

-                 * NULL to indicate failure. */

-                vPortFree( xSecureContextHandle );

-                xSecureContextHandle = NULL;

+                xSecureContextHandle = securecontextINVALID_CONTEXT_ID;

             }

         }

     }

@@ -185,7 +243,7 @@
 

 secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle )

 {

-    uint32_t ulIPSR;

+    uint32_t ulIPSR, ulSecureContextIndex;

 

     /* Read the Interrupt Program Status Register (IPSR) value. */

     secureportREAD_IPSR( ulIPSR );

@@ -194,14 +252,43 @@
      * when the processor is running in the Thread Mode. */

     if( ulIPSR != 0 )

     {

-        /* Ensure that valid parameters are passed. */

-        secureportASSERT( xSecureContextHandle != NULL );

+        /* Only free if a valid context handle is passed. */

+        if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )

+        {

+            ulSecureContextIndex = xSecureContextHandle - 1UL;

 

-        /* Free the stack space. */

-        vPortFree( xSecureContextHandle->pucStackLimit );

+            /* Free the stack space. */

+            vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );

 

-        /* Free the context itself. */

-        vPortFree( xSecureContextHandle );

+            /* Return the context back to the free contexts pool. */

+            vReturnSecureContext( ulSecureContextIndex );

+        }

+    }

+}

+/*-----------------------------------------------------------*/

+

+secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle )

+{

+    uint32_t ulSecureContextIndex;

+

+    if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )

+    {

+        ulSecureContextIndex = xSecureContextHandle - 1UL;

+

+        SecureContext_LoadContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );

+    }

+}

+/*-----------------------------------------------------------*/

+

+secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle )

+{

+    uint32_t ulSecureContextIndex;

+

+    if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )

+    {

+        ulSecureContextIndex = xSecureContextHandle - 1UL;

+

+        SecureContext_SaveContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );

     }

 }

 /*-----------------------------------------------------------*/

diff --git a/portable/GCC/ARM_CM33/secure/secure_context.h b/portable/GCC/ARM_CM33/secure/secure_context.h
index 77a9332..b7a3ba5 100644
--- a/portable/GCC/ARM_CM33/secure/secure_context.h
+++ b/portable/GCC/ARM_CM33/secure/secure_context.h
@@ -36,15 +36,29 @@
 #include "FreeRTOSConfig.h"

 

 /**

- * @brief PSP value when no task's context is loaded.

+ * @brief PSP value when no secure context is loaded.

  */

 #define securecontextNO_STACK    0x0

+/*-----------------------------------------------------------*/

 

 /**

- * @brief Opaque handle.

+ * @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.

  */

-struct SecureContext;

-typedef struct SecureContext * SecureContextHandle_t;

+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. */

+} SecureContext_t;

+/*-----------------------------------------------------------*/

+

+/**

+ * @brief Opaque handle for a secure context.

+ */

+typedef uint32_t SecureContextHandle_t;

 /*-----------------------------------------------------------*/

 

 /**

diff --git a/portable/GCC/ARM_CM33/secure/secure_context_port.c b/portable/GCC/ARM_CM33/secure/secure_context_port.c
index 4c6d0be..0731abe 100644
--- a/portable/GCC/ARM_CM33/secure/secure_context_port.c
+++ b/portable/GCC/ARM_CM33/secure/secure_context_port.c
@@ -32,57 +32,62 @@
 /* Secure port macros. */

 #include "secure_port_macros.h"

 

-secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle )

+void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext )

 {

-    /* xSecureContextHandle value is in r0. */

+    /* 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 = xSecureContextHandle->pucCurrentStackPointer, r2 = xSecureContextHandle->pucStackLimit. */

+        " .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. */

+            " ldmia r1!, {r3}               \n" /* Read CONTROL register value from task's stack. r3 = CONTROL. */

+            " msr control, r3               \n" /* CONTROL = r3. */

         #endif /* configENABLE_MPU */

-        "	msr psplim, r2							\n"/* PSPLIM = r2. */

-        "	msr psp, r1								\n"/* PSP = r1. */

-        "											\n"

-        " load_ctx_therad_mode:						\n"

-        "	nop										\n"

-        "											\n"

+        "                                   \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"

     );

 }

 /*-----------------------------------------------------------*/

 

-secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle )

+void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext )

 {

-    /* xSecureContextHandle value is in r0. */

+    /* 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. */

+        " .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 )

-            "	vstmdb r1!, {s0}						\n"/* Trigger the defferred stacking of FPU registers. */

-            "	vldmia r1!, {s0}						\n"/* Nullify the effect of the pervious statement. */

+            " vstmdb r1!, {s0}              \n" /* Trigger the defferred stacking of FPU registers. */

+            " vldmia r1!, {s0}              \n" /* Nullify the effect of the pervious statement. */

         #endif /* configENABLE_FPU */

+        "                                   \n"

         #if ( configENABLE_MPU == 1 )

-            "	mrs r2, control							\n"/* r2 = CONTROL. */

-            "	stmdb r1!, {r2}							\n"/* Store CONTROL value on the stack. */

+            " mrs r2, control               \n" /* r2 = CONTROL. */

+            " stmdb r1!, {r2}               \n" /* Store CONTROL value on the stack. */

         #endif /* configENABLE_MPU */

-        "	str r1, [r0]							\n"/* Save the top of stack in context. xSecureContextHandle->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"

-        "	nop										\n"

-        "											\n"

+        "                                   \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"

     );

 }

diff --git a/portable/GCC/ARM_CM33/secure/secure_heap.c b/portable/GCC/ARM_CM33/secure/secure_heap.c
index 0100ad0..099b01f 100644
--- a/portable/GCC/ARM_CM33/secure/secure_heap.c
+++ b/portable/GCC/ARM_CM33/secure/secure_heap.c
@@ -38,7 +38,9 @@
 /**

  * @brief Total heap size.

  */

-#define secureconfigTOTAL_HEAP_SIZE    ( ( ( size_t ) ( 10 * 1024 ) ) )

+#ifndef secureconfigTOTAL_HEAP_SIZE

+    #define secureconfigTOTAL_HEAP_SIZE    ( ( ( size_t ) ( 10 * 1024 ) ) )

+#endif

 

 /* No test marker by default. */

 #ifndef mtCOVERAGE_TEST_MARKER

diff --git a/portable/IAR/ARM_CM23/secure/secure_context.c b/portable/IAR/ARM_CM23/secure/secure_context.c
index deede89..96a5662 100644
--- a/portable/IAR/ARM_CM23/secure/secure_context.c
+++ b/portable/IAR/ARM_CM23/secure/secure_context.c
@@ -50,25 +50,74 @@
  * Bit[1] - 1 --> Thread mode uses PSP.

  */

 #define securecontextCONTROL_VALUE_UNPRIVILEGED    0x03

+

+/**

+ * @brief Invalid context ID.

+ */

+#define securecontextINVALID_CONTEXT_ID            0UL

+

+/**

+ * @brief Maximum number of secure contexts.

+ */

+#ifndef secureconfigMAX_SECURE_CONTEXTS

+    #define secureconfigMAX_SECURE_CONTEXTS        8UL

+#endif

 /*-----------------------------------------------------------*/

 

 /**

- * @brief Structure to represent secure context.

- *

- * @note Since stack grows down, pucStackStart is the highest address while

- * pucStackLimit is the first addess of the allocated memory.

+ * @brief Pre-allocated array of secure contexts.

  */

-typedef struct SecureContext

+SecureContext_t xSecureContexts[ secureconfigMAX_SECURE_CONTEXTS ];

+/*-----------------------------------------------------------*/

+

+/**

+ * @brief Get a free context from the secure context pool (xSecureContexts).

+ *

+ * @return Index of a free context in the xSecureContexts array.

+ */

+static uint32_t ulGetSecureContext( void );

+

+/**

+ * @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 )

 {

-    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. */

-} SecureContext_t;

+    uint32_t ulSecureContextIndex;

+

+    for( ulSecureContextIndex = 0; ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS; ulSecureContextIndex++ )

+    {

+        if( ( xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer == NULL ) &&

+            ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == NULL ) &&

+            ( xSecureContexts[ ulSecureContextIndex ].pucStackStart == NULL ) )

+        {

+            break;

+        }

+    }

+

+    return ulSecureContextIndex;

+}

+/*-----------------------------------------------------------*/

+

+static void vReturnSecureContext( uint32_t ulSecureContextIndex )

+{

+    xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = NULL;

+    xSecureContexts[ ulSecureContextIndex ].pucStackLimit = NULL;

+    xSecureContexts[ ulSecureContextIndex ].pucStackStart = NULL;

+}

 /*-----------------------------------------------------------*/

 

 secureportNON_SECURE_CALLABLE void SecureContext_Init( void )

 {

-    uint32_t ulIPSR;

+    uint32_t ulIPSR, i;

 

     /* Read the Interrupt Program Status Register (IPSR) value. */

     secureportREAD_IPSR( ulIPSR );

@@ -81,6 +130,14 @@
         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;

+        }

+

         #if ( configENABLE_MPU == 1 )

             {

                 /* Configure thread mode to use PSP and to be unprivileged. */

@@ -88,7 +145,7 @@
             }

         #else /* configENABLE_MPU */

             {

-                /* Configure thread mode to use PSP and to be privileged.. */

+                /* Configure thread mode to use PSP and to be privileged. */

                 secureportSET_CONTROL( securecontextCONTROL_VALUE_PRIVILEGED );

             }

         #endif /* configENABLE_MPU */

@@ -104,8 +161,8 @@
 #endif /* configENABLE_MPU */

 {

     uint8_t * pucStackMemory = NULL;

-    uint32_t ulIPSR;

-    SecureContextHandle_t xSecureContextHandle = NULL;

+    uint32_t ulIPSR, ulSecureContextIndex;

+    SecureContextHandle_t xSecureContextHandle;

 

     #if ( configENABLE_MPU == 1 )

         uint32_t * pulCurrentStackPointer = NULL;

@@ -118,10 +175,11 @@
      * when the processor is running in the Thread Mode. */

     if( ulIPSR != 0 )

     {

-        /* Allocate the context structure. */

-        xSecureContextHandle = ( SecureContextHandle_t ) pvPortMalloc( sizeof( SecureContext_t ) );

+        /* Ontain a free secure context. */

+        ulSecureContextIndex = ulGetSecureContext();

 

-        if( xSecureContextHandle != NULL )

+        /* Were we able to get a free context? */

+        if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS )

         {

             /* Allocate the stack space. */

             pucStackMemory = pvPortMalloc( ulSecureStackSize );

@@ -134,18 +192,18 @@
                  * 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. */

-                xSecureContextHandle->pucStackStart = pucStackMemory + ulSecureStackSize;

+                xSecureContexts[ ulSecureContextIndex ].pucStackStart = pucStackMemory + ulSecureStackSize;

 

                 /* The stack cannot go beyond this location. This value is

                  * programmed in the PSPLIM register on context switch.*/

-                xSecureContextHandle->pucStackLimit = pucStackMemory;

+                xSecureContexts[ ulSecureContextIndex ].pucStackLimit = pucStackMemory;

 

                 #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 * ) xSecureContextHandle->pucStackStart;

+                        pulCurrentStackPointer = ( uint32_t * ) xSecureContexts[ ulSecureContextIndex ].pucStackStart;

                         pulCurrentStackPointer--;

 

                         if( ulIsTaskPrivileged )

@@ -159,22 +217,22 @@
 

                         /* Store the current stack pointer. This value is programmed in

                          * the PSP register on context switch. */

-                        xSecureContextHandle->pucCurrentStackPointer = ( uint8_t * ) pulCurrentStackPointer;

+                        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. */

-                        xSecureContextHandle->pucCurrentStackPointer = xSecureContextHandle->pucStackStart;

+                        xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = xSecureContexts[ ulSecureContextIndex ].pucStackStart;

                     }

                 #endif /* configENABLE_MPU */

+

+                /* Ensure to never return 0 as a valid context handle. */

+                xSecureContextHandle = ulSecureContextIndex + 1UL;

             }

             else

             {

-                /* Free the context to avoid memory leak and make sure to return

-                 * NULL to indicate failure. */

-                vPortFree( xSecureContextHandle );

-                xSecureContextHandle = NULL;

+                xSecureContextHandle = securecontextINVALID_CONTEXT_ID;

             }

         }

     }

@@ -185,7 +243,7 @@
 

 secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle )

 {

-    uint32_t ulIPSR;

+    uint32_t ulIPSR, ulSecureContextIndex;

 

     /* Read the Interrupt Program Status Register (IPSR) value. */

     secureportREAD_IPSR( ulIPSR );

@@ -194,14 +252,43 @@
      * when the processor is running in the Thread Mode. */

     if( ulIPSR != 0 )

     {

-        /* Ensure that valid parameters are passed. */

-        secureportASSERT( xSecureContextHandle != NULL );

+        /* Only free if a valid context handle is passed. */

+        if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )

+        {

+            ulSecureContextIndex = xSecureContextHandle - 1UL;

 

-        /* Free the stack space. */

-        vPortFree( xSecureContextHandle->pucStackLimit );

+            /* Free the stack space. */

+            vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );

 

-        /* Free the context itself. */

-        vPortFree( xSecureContextHandle );

+            /* Return the context back to the free contexts pool. */

+            vReturnSecureContext( ulSecureContextIndex );

+        }

+    }

+}

+/*-----------------------------------------------------------*/

+

+secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle )

+{

+    uint32_t ulSecureContextIndex;

+

+    if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )

+    {

+        ulSecureContextIndex = xSecureContextHandle - 1UL;

+

+        SecureContext_LoadContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );

+    }

+}

+/*-----------------------------------------------------------*/

+

+secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle )

+{

+    uint32_t ulSecureContextIndex;

+

+    if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )

+    {

+        ulSecureContextIndex = xSecureContextHandle - 1UL;

+

+        SecureContext_SaveContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );

     }

 }

 /*-----------------------------------------------------------*/

diff --git a/portable/IAR/ARM_CM23/secure/secure_context.h b/portable/IAR/ARM_CM23/secure/secure_context.h
index 77a9332..b7a3ba5 100644
--- a/portable/IAR/ARM_CM23/secure/secure_context.h
+++ b/portable/IAR/ARM_CM23/secure/secure_context.h
@@ -36,15 +36,29 @@
 #include "FreeRTOSConfig.h"

 

 /**

- * @brief PSP value when no task's context is loaded.

+ * @brief PSP value when no secure context is loaded.

  */

 #define securecontextNO_STACK    0x0

+/*-----------------------------------------------------------*/

 

 /**

- * @brief Opaque handle.

+ * @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.

  */

-struct SecureContext;

-typedef struct SecureContext * SecureContextHandle_t;

+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. */

+} SecureContext_t;

+/*-----------------------------------------------------------*/

+

+/**

+ * @brief Opaque handle for a secure context.

+ */

+typedef uint32_t SecureContextHandle_t;

 /*-----------------------------------------------------------*/

 

 /**

diff --git a/portable/IAR/ARM_CM23/secure/secure_context_port.c b/portable/IAR/ARM_CM23/secure/secure_context_port.c
deleted file mode 100644
index d8ca0f5..0000000
--- a/portable/IAR/ARM_CM23/secure/secure_context_port.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*

- * 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"

-

-/* Functions implemented in assembler file. */

-extern void SecureContext_LoadContextAsm( SecureContextHandle_t xSecureContextHandle );

-extern void SecureContext_SaveContextAsm( SecureContextHandle_t xSecureContextHandle );

-

-secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle )

-{

-    SecureContext_LoadContextAsm( xSecureContextHandle );

-}

-/*-----------------------------------------------------------*/

-

-secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle )

-{

-    SecureContext_SaveContextAsm( xSecureContextHandle );

-}

-/*-----------------------------------------------------------*/

diff --git a/portable/IAR/ARM_CM23/secure/secure_context_port_asm.s b/portable/IAR/ARM_CM23/secure/secure_context_port_asm.s
index 8fbb49a..cf245b9 100644
--- a/portable/IAR/ARM_CM23/secure/secure_context_port_asm.s
+++ b/portable/IAR/ARM_CM23/secure/secure_context_port_asm.s
@@ -26,52 +26,56 @@
  *

  */

 

-	SECTION .text:CODE:NOROOT(2)

-	THUMB

+    SECTION .text:CODE:NOROOT(2)

+    THUMB

 

-	PUBLIC SecureContext_LoadContextAsm

-	PUBLIC SecureContext_SaveContextAsm

+    PUBLIC SecureContext_LoadContextAsm

+    PUBLIC SecureContext_SaveContextAsm

 

 #if ( configENABLE_FPU == 1 )

-	#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.

+    #error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.

 #endif

 /*-----------------------------------------------------------*/

 

 SecureContext_LoadContextAsm:

-	/* xSecureContextHandle value is in r0. */

-	mrs r1, ipsr							/* r1 = IPSR. */

-	cbz r1, load_ctx_therad_mode			/* Do nothing if the processor is running in the Thread Mode. */

-	ldmia r0!, {r1, r2}						/* r1 = xSecureContextHandle->pucCurrentStackPointer, r2 = xSecureContextHandle->pucStackLimit. */

-#if ( configENABLE_MPU == 1 )

-	ldmia r1!, {r3}							/* Read CONTROL register value from task's stack. r3 = CONTROL. */

-	msr control, r3							/* CONTROL = r3. */

-#endif /* configENABLE_MPU */

-	msr psplim, r2							/* PSPLIM = r2. */

-	msr psp, r1								/* PSP = r1. */

+    /* pxSecureContext value is in r0. */

+    mrs r1, ipsr                    /* r1 = IPSR. */

+    cbz r1, load_ctx_therad_mode    /* Do nothing if the processor is running in the Thread Mode. */

+    ldmia r0!, {r1, r2}             /* r1 = pxSecureContext->pucCurrentStackPointer, r2 = pxSecureContext->pucStackLimit. */

 

-	load_ctx_therad_mode:

-		bx lr

+#if ( configENABLE_MPU == 1 )

+    ldmia r1!, {r3}                 /* Read CONTROL register value from task's stack. r3 = CONTROL. */

+    msr control, r3                 /* CONTROL = r3. */

+#endif /* configENABLE_MPU */

+

+    msr psplim, r2                  /* PSPLIM = r2. */

+    msr psp, r1                     /* PSP = r1. */

+

+    load_ctx_therad_mode:

+        bx lr

 /*-----------------------------------------------------------*/

 

 SecureContext_SaveContextAsm:

-	/* xSecureContextHandle value is in r0. */

-	mrs r1, ipsr							/* r1 = IPSR. */

-	cbz r1, save_ctx_therad_mode			/* Do nothing if the processor is running in the Thread Mode. */

-	mrs r1, psp								/* r1 = PSP. */

-#if ( configENABLE_MPU == 1 )

-	mrs r2, control							/* r2 = CONTROL. */

-	subs r1, r1, #4							/* Make space for the CONTROL value on the stack. */

-	str r1, [r0]							/* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */

-	stmia r1!, {r2}							/* Store CONTROL value on the stack. */

-#else /* configENABLE_MPU */

-	str r1, [r0]							/* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */

-#endif /* configENABLE_MPU */

-	movs r1, #0								/* r1 = securecontextNO_STACK. */

-	msr psplim, r1							/* PSPLIM = securecontextNO_STACK. */

-	msr psp, r1								/* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */

+    /* pxSecureContext value is in r0. */

+    mrs r1, ipsr                    /* r1 = IPSR. */

+    cbz r1, save_ctx_therad_mode    /* Do nothing if the processor is running in the Thread Mode. */

+    mrs r1, psp                     /* r1 = PSP. */

 

-	save_ctx_therad_mode:

-		bx lr

+#if ( configENABLE_MPU == 1 )

+    mrs r2, control                 /* r2 = CONTROL. */

+    subs r1, r1, #4                 /* Make space for the CONTROL value on the stack. */

+    str r1, [r0]                    /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */

+    stmia r1!, {r2}                 /* Store CONTROL value on the stack. */

+#else /* configENABLE_MPU */

+    str r1, [r0]                    /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */

+#endif /* configENABLE_MPU */

+

+    movs r1, #0                     /* r1 = securecontextNO_STACK. */

+    msr psplim, r1                  /* PSPLIM = securecontextNO_STACK. */

+    msr psp, r1                     /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */

+

+    save_ctx_therad_mode:

+        bx lr

 /*-----------------------------------------------------------*/

 

-	END

+    END

diff --git a/portable/IAR/ARM_CM23/secure/secure_heap.c b/portable/IAR/ARM_CM23/secure/secure_heap.c
index 0100ad0..099b01f 100644
--- a/portable/IAR/ARM_CM23/secure/secure_heap.c
+++ b/portable/IAR/ARM_CM23/secure/secure_heap.c
@@ -38,7 +38,9 @@
 /**

  * @brief Total heap size.

  */

-#define secureconfigTOTAL_HEAP_SIZE    ( ( ( size_t ) ( 10 * 1024 ) ) )

+#ifndef secureconfigTOTAL_HEAP_SIZE

+    #define secureconfigTOTAL_HEAP_SIZE    ( ( ( size_t ) ( 10 * 1024 ) ) )

+#endif

 

 /* No test marker by default. */

 #ifndef mtCOVERAGE_TEST_MARKER

diff --git a/portable/IAR/ARM_CM33/secure/secure_context.c b/portable/IAR/ARM_CM33/secure/secure_context.c
index deede89..96a5662 100644
--- a/portable/IAR/ARM_CM33/secure/secure_context.c
+++ b/portable/IAR/ARM_CM33/secure/secure_context.c
@@ -50,25 +50,74 @@
  * Bit[1] - 1 --> Thread mode uses PSP.

  */

 #define securecontextCONTROL_VALUE_UNPRIVILEGED    0x03

+

+/**

+ * @brief Invalid context ID.

+ */

+#define securecontextINVALID_CONTEXT_ID            0UL

+

+/**

+ * @brief Maximum number of secure contexts.

+ */

+#ifndef secureconfigMAX_SECURE_CONTEXTS

+    #define secureconfigMAX_SECURE_CONTEXTS        8UL

+#endif

 /*-----------------------------------------------------------*/

 

 /**

- * @brief Structure to represent secure context.

- *

- * @note Since stack grows down, pucStackStart is the highest address while

- * pucStackLimit is the first addess of the allocated memory.

+ * @brief Pre-allocated array of secure contexts.

  */

-typedef struct SecureContext

+SecureContext_t xSecureContexts[ secureconfigMAX_SECURE_CONTEXTS ];

+/*-----------------------------------------------------------*/

+

+/**

+ * @brief Get a free context from the secure context pool (xSecureContexts).

+ *

+ * @return Index of a free context in the xSecureContexts array.

+ */

+static uint32_t ulGetSecureContext( void );

+

+/**

+ * @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 )

 {

-    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. */

-} SecureContext_t;

+    uint32_t ulSecureContextIndex;

+

+    for( ulSecureContextIndex = 0; ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS; ulSecureContextIndex++ )

+    {

+        if( ( xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer == NULL ) &&

+            ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == NULL ) &&

+            ( xSecureContexts[ ulSecureContextIndex ].pucStackStart == NULL ) )

+        {

+            break;

+        }

+    }

+

+    return ulSecureContextIndex;

+}

+/*-----------------------------------------------------------*/

+

+static void vReturnSecureContext( uint32_t ulSecureContextIndex )

+{

+    xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = NULL;

+    xSecureContexts[ ulSecureContextIndex ].pucStackLimit = NULL;

+    xSecureContexts[ ulSecureContextIndex ].pucStackStart = NULL;

+}

 /*-----------------------------------------------------------*/

 

 secureportNON_SECURE_CALLABLE void SecureContext_Init( void )

 {

-    uint32_t ulIPSR;

+    uint32_t ulIPSR, i;

 

     /* Read the Interrupt Program Status Register (IPSR) value. */

     secureportREAD_IPSR( ulIPSR );

@@ -81,6 +130,14 @@
         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;

+        }

+

         #if ( configENABLE_MPU == 1 )

             {

                 /* Configure thread mode to use PSP and to be unprivileged. */

@@ -88,7 +145,7 @@
             }

         #else /* configENABLE_MPU */

             {

-                /* Configure thread mode to use PSP and to be privileged.. */

+                /* Configure thread mode to use PSP and to be privileged. */

                 secureportSET_CONTROL( securecontextCONTROL_VALUE_PRIVILEGED );

             }

         #endif /* configENABLE_MPU */

@@ -104,8 +161,8 @@
 #endif /* configENABLE_MPU */

 {

     uint8_t * pucStackMemory = NULL;

-    uint32_t ulIPSR;

-    SecureContextHandle_t xSecureContextHandle = NULL;

+    uint32_t ulIPSR, ulSecureContextIndex;

+    SecureContextHandle_t xSecureContextHandle;

 

     #if ( configENABLE_MPU == 1 )

         uint32_t * pulCurrentStackPointer = NULL;

@@ -118,10 +175,11 @@
      * when the processor is running in the Thread Mode. */

     if( ulIPSR != 0 )

     {

-        /* Allocate the context structure. */

-        xSecureContextHandle = ( SecureContextHandle_t ) pvPortMalloc( sizeof( SecureContext_t ) );

+        /* Ontain a free secure context. */

+        ulSecureContextIndex = ulGetSecureContext();

 

-        if( xSecureContextHandle != NULL )

+        /* Were we able to get a free context? */

+        if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS )

         {

             /* Allocate the stack space. */

             pucStackMemory = pvPortMalloc( ulSecureStackSize );

@@ -134,18 +192,18 @@
                  * 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. */

-                xSecureContextHandle->pucStackStart = pucStackMemory + ulSecureStackSize;

+                xSecureContexts[ ulSecureContextIndex ].pucStackStart = pucStackMemory + ulSecureStackSize;

 

                 /* The stack cannot go beyond this location. This value is

                  * programmed in the PSPLIM register on context switch.*/

-                xSecureContextHandle->pucStackLimit = pucStackMemory;

+                xSecureContexts[ ulSecureContextIndex ].pucStackLimit = pucStackMemory;

 

                 #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 * ) xSecureContextHandle->pucStackStart;

+                        pulCurrentStackPointer = ( uint32_t * ) xSecureContexts[ ulSecureContextIndex ].pucStackStart;

                         pulCurrentStackPointer--;

 

                         if( ulIsTaskPrivileged )

@@ -159,22 +217,22 @@
 

                         /* Store the current stack pointer. This value is programmed in

                          * the PSP register on context switch. */

-                        xSecureContextHandle->pucCurrentStackPointer = ( uint8_t * ) pulCurrentStackPointer;

+                        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. */

-                        xSecureContextHandle->pucCurrentStackPointer = xSecureContextHandle->pucStackStart;

+                        xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = xSecureContexts[ ulSecureContextIndex ].pucStackStart;

                     }

                 #endif /* configENABLE_MPU */

+

+                /* Ensure to never return 0 as a valid context handle. */

+                xSecureContextHandle = ulSecureContextIndex + 1UL;

             }

             else

             {

-                /* Free the context to avoid memory leak and make sure to return

-                 * NULL to indicate failure. */

-                vPortFree( xSecureContextHandle );

-                xSecureContextHandle = NULL;

+                xSecureContextHandle = securecontextINVALID_CONTEXT_ID;

             }

         }

     }

@@ -185,7 +243,7 @@
 

 secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle )

 {

-    uint32_t ulIPSR;

+    uint32_t ulIPSR, ulSecureContextIndex;

 

     /* Read the Interrupt Program Status Register (IPSR) value. */

     secureportREAD_IPSR( ulIPSR );

@@ -194,14 +252,43 @@
      * when the processor is running in the Thread Mode. */

     if( ulIPSR != 0 )

     {

-        /* Ensure that valid parameters are passed. */

-        secureportASSERT( xSecureContextHandle != NULL );

+        /* Only free if a valid context handle is passed. */

+        if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )

+        {

+            ulSecureContextIndex = xSecureContextHandle - 1UL;

 

-        /* Free the stack space. */

-        vPortFree( xSecureContextHandle->pucStackLimit );

+            /* Free the stack space. */

+            vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );

 

-        /* Free the context itself. */

-        vPortFree( xSecureContextHandle );

+            /* Return the context back to the free contexts pool. */

+            vReturnSecureContext( ulSecureContextIndex );

+        }

+    }

+}

+/*-----------------------------------------------------------*/

+

+secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle )

+{

+    uint32_t ulSecureContextIndex;

+

+    if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )

+    {

+        ulSecureContextIndex = xSecureContextHandle - 1UL;

+

+        SecureContext_LoadContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );

+    }

+}

+/*-----------------------------------------------------------*/

+

+secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle )

+{

+    uint32_t ulSecureContextIndex;

+

+    if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )

+    {

+        ulSecureContextIndex = xSecureContextHandle - 1UL;

+

+        SecureContext_SaveContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );

     }

 }

 /*-----------------------------------------------------------*/

diff --git a/portable/IAR/ARM_CM33/secure/secure_context.h b/portable/IAR/ARM_CM33/secure/secure_context.h
index 77a9332..b7a3ba5 100644
--- a/portable/IAR/ARM_CM33/secure/secure_context.h
+++ b/portable/IAR/ARM_CM33/secure/secure_context.h
@@ -36,15 +36,29 @@
 #include "FreeRTOSConfig.h"

 

 /**

- * @brief PSP value when no task's context is loaded.

+ * @brief PSP value when no secure context is loaded.

  */

 #define securecontextNO_STACK    0x0

+/*-----------------------------------------------------------*/

 

 /**

- * @brief Opaque handle.

+ * @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.

  */

-struct SecureContext;

-typedef struct SecureContext * SecureContextHandle_t;

+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. */

+} SecureContext_t;

+/*-----------------------------------------------------------*/

+

+/**

+ * @brief Opaque handle for a secure context.

+ */

+typedef uint32_t SecureContextHandle_t;

 /*-----------------------------------------------------------*/

 

 /**

diff --git a/portable/IAR/ARM_CM33/secure/secure_context_port.c b/portable/IAR/ARM_CM33/secure/secure_context_port.c
deleted file mode 100644
index d8ca0f5..0000000
--- a/portable/IAR/ARM_CM33/secure/secure_context_port.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*

- * 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"

-

-/* Functions implemented in assembler file. */

-extern void SecureContext_LoadContextAsm( SecureContextHandle_t xSecureContextHandle );

-extern void SecureContext_SaveContextAsm( SecureContextHandle_t xSecureContextHandle );

-

-secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle )

-{

-    SecureContext_LoadContextAsm( xSecureContextHandle );

-}

-/*-----------------------------------------------------------*/

-

-secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle )

-{

-    SecureContext_SaveContextAsm( xSecureContextHandle );

-}

-/*-----------------------------------------------------------*/

diff --git a/portable/IAR/ARM_CM33/secure/secure_context_port_asm.s b/portable/IAR/ARM_CM33/secure/secure_context_port_asm.s
index 297679b..0df0a1b 100644
--- a/portable/IAR/ARM_CM33/secure/secure_context_port_asm.s
+++ b/portable/IAR/ARM_CM33/secure/secure_context_port_asm.s
@@ -26,49 +26,54 @@
  *

  */

 

-	SECTION .text:CODE:NOROOT(2)

-	THUMB

+    SECTION .text:CODE:NOROOT(2)

+    THUMB

 

-	PUBLIC SecureContext_LoadContextAsm

-	PUBLIC SecureContext_SaveContextAsm

+    PUBLIC SecureContext_LoadContextAsm

+    PUBLIC SecureContext_SaveContextAsm

 /*-----------------------------------------------------------*/

 

 SecureContext_LoadContextAsm:

-	/* xSecureContextHandle value is in r0. */

-	mrs r1, ipsr							/* r1 = IPSR. */

-	cbz r1, load_ctx_therad_mode			/* Do nothing if the processor is running in the Thread Mode. */

-	ldmia r0!, {r1, r2}						/* r1 = xSecureContextHandle->pucCurrentStackPointer, r2 = xSecureContextHandle->pucStackLimit. */

-#if ( configENABLE_MPU == 1 )

-	ldmia r1!, {r3}							/* Read CONTROL register value from task's stack. r3 = CONTROL. */

-	msr control, r3							/* CONTROL = r3. */

-#endif /* configENABLE_MPU */

-	msr psplim, r2							/* PSPLIM = r2. */

-	msr psp, r1								/* PSP = r1. */

+    /* pxSecureContext value is in r0. */

+    mrs r1, ipsr                        /* r1 = IPSR. */

+    cbz r1, load_ctx_therad_mode        /* Do nothing if the processor is running in the Thread Mode. */

+    ldmia r0!, {r1, r2}                 /* r1 = pxSecureContext->pucCurrentStackPointer, r2 = pxSecureContext->pucStackLimit. */

 

-	load_ctx_therad_mode:

-		bx lr

+#if ( configENABLE_MPU == 1 )

+    ldmia r1!, {r3}                     /* Read CONTROL register value from task's stack. r3 = CONTROL. */

+    msr control, r3                     /* CONTROL = r3. */

+#endif /* configENABLE_MPU */

+

+    msr psplim, r2                      /* PSPLIM = r2. */

+    msr psp, r1                         /* PSP = r1. */

+

+    load_ctx_therad_mode:

+        bx lr

 /*-----------------------------------------------------------*/

 

 SecureContext_SaveContextAsm:

-	/* xSecureContextHandle value is in r0. */

-	mrs r1, ipsr							/* r1 = IPSR. */

-	cbz r1, save_ctx_therad_mode			/* Do nothing if the processor is running in the Thread Mode. */

-	mrs r1, psp								/* r1 = PSP. */

-#if ( configENABLE_FPU == 1 )

-	vstmdb r1!, {s0}						/* Trigger the defferred stacking of FPU registers. */

-	vldmia r1!, {s0}						/* Nullify the effect of the pervious statement. */

-#endif /* configENABLE_FPU */

-#if ( configENABLE_MPU == 1 )

-	mrs r2, control							/* r2 = CONTROL. */

-	stmdb r1!, {r2}							/* Store CONTROL value on the stack. */

-#endif /* configENABLE_MPU */

-	str r1, [r0]							/* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */

-	movs r1, #0								/* r1 = securecontextNO_STACK. */

-	msr psplim, r1							/* PSPLIM = securecontextNO_STACK. */

-	msr psp, r1								/* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */

+    /* pxSecureContext value is in r0. */

+    mrs r1, ipsr                        /* r1 = IPSR. */

+    cbz r1, save_ctx_therad_mode        /* Do nothing if the processor is running in the Thread Mode. */

+    mrs r1, psp                         /* r1 = PSP. */

 

-	save_ctx_therad_mode:

-		bx lr

+#if ( configENABLE_FPU == 1 )

+    vstmdb r1!, {s0}                    /* Trigger the defferred stacking of FPU registers. */

+    vldmia r1!, {s0}                    /* Nullify the effect of the pervious statement. */

+#endif /* configENABLE_FPU */

+

+#if ( configENABLE_MPU == 1 )

+    mrs r2, control                     /* r2 = CONTROL. */

+    stmdb r1!, {r2}                     /* Store CONTROL value on the stack. */

+#endif /* configENABLE_MPU */

+

+    str r1, [r0]                        /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */

+    movs r1, #0                         /* r1 = securecontextNO_STACK. */

+    msr psplim, r1                      /* PSPLIM = securecontextNO_STACK. */

+    msr psp, r1                         /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */

+

+    save_ctx_therad_mode:

+        bx lr

 /*-----------------------------------------------------------*/

 

-	END

+    END

diff --git a/portable/IAR/ARM_CM33/secure/secure_heap.c b/portable/IAR/ARM_CM33/secure/secure_heap.c
index 0100ad0..099b01f 100644
--- a/portable/IAR/ARM_CM33/secure/secure_heap.c
+++ b/portable/IAR/ARM_CM33/secure/secure_heap.c
@@ -38,7 +38,9 @@
 /**

  * @brief Total heap size.

  */

-#define secureconfigTOTAL_HEAP_SIZE    ( ( ( size_t ) ( 10 * 1024 ) ) )

+#ifndef secureconfigTOTAL_HEAP_SIZE

+    #define secureconfigTOTAL_HEAP_SIZE    ( ( ( size_t ) ( 10 * 1024 ) ) )

+#endif

 

 /* No test marker by default. */

 #ifndef mtCOVERAGE_TEST_MARKER