Release v11.3.1_20261016
diff --git a/README.md b/README.md
index 09619a1..e1fcd79 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # Middleware FreeRTOS MCU Component
 
-![tag](https://img.shields.io/badge/tag-v11.2.0_20260327-brightgreen.svg)
+![tag](https://img.shields.io/badge/tag-v11.3.1_20261016-brightgreen.svg)
 
 ## Overview
 
diff --git a/Source/CMSIS_RTOS_V2/cmsis_os2.c b/Source/CMSIS_RTOS_V2/cmsis_os2.c
index 5469c12..8083c7f 100644
--- a/Source/CMSIS_RTOS_V2/cmsis_os2.c
+++ b/Source/CMSIS_RTOS_V2/cmsis_os2.c
@@ -1,5 +1,5 @@
 /* --------------------------------------------------------------------------
- * Copyright (c) 2013-2024 Arm Limited. All rights reserved.
+ * Copyright 2013-2026 Arm Limited and/or its affiliates.
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -84,8 +84,8 @@
 #define EVENT_FLAGS_INVALID_BITS  (~((1UL << MAX_BITS_EVENT_GROUPS) - 1U))
 
 /* Kernel version and identification string definition (major.minor.rev: mmnnnrrrr dec) */
-#define KERNEL_VERSION            (((uint32_t)tskKERNEL_VERSION_MAJOR * 10000000UL) | \
-                                   ((uint32_t)tskKERNEL_VERSION_MINOR *    10000UL) | \
+#define KERNEL_VERSION            (((uint32_t)tskKERNEL_VERSION_MAJOR * 10000000UL) + \
+                                   ((uint32_t)tskKERNEL_VERSION_MINOR *    10000UL) + \
                                    ((uint32_t)tskKERNEL_VERSION_BUILD *        1UL))
 
 #define KERNEL_ID                 ("FreeRTOS " tskKERNEL_VERSION_NUMBER)
@@ -127,7 +127,7 @@
     HeapRegion_t array.
   */
   #define HEAP_5_REGION_SETUP   1
-
+  
   #ifndef configHEAP_5_REGIONS
     #define configHEAP_5_REGIONS xHeapRegions
 
@@ -176,7 +176,6 @@
 #endif
 #endif /* SysTick */
 
-
 /*
   Determine if CPU executes from interrupt context or if interrupts are masked.
 */
@@ -580,9 +579,9 @@
     mem  = -1;
 
     if (attr != NULL) {
-      if (attr->name != NULL) {
-        name = attr->name;
-      }
+      /* Take the name from attributes */
+      name = attr->name;
+
       if (attr->priority != osPriorityNone) {
         prio = (UBaseType_t)attr->priority;
       }
@@ -592,6 +591,11 @@
         return (NULL);
       }
 
+      if ((attr->attr_bits & osThreadPrivileged) == osThreadPrivileged) {
+        /* Set privilege bit to create a privileged task */
+        prio |= portPRIVILEGE_BIT;
+      }
+
       if (attr->stack_size > 0U) {
         /* In FreeRTOS stack is not in bytes, but in sizeof(StackType_t) which is 4 on ARM ports.       */
         /* Stack size should be therefore 4 byte aligned in order to avoid division caused side effects */
@@ -883,9 +887,10 @@
   Terminate execution of a thread.
 */
 osStatus_t osThreadTerminate (osThreadId_t thread_id) {
-  TaskHandle_t hTask = (TaskHandle_t)thread_id;
   osStatus_t stat;
+
 #ifndef USE_FreeRTOS_HEAP_1
+  TaskHandle_t hTask = (TaskHandle_t)thread_id;
   eTaskState tstate;
 
   if (IRQ_Context() != 0U) {
@@ -905,6 +910,7 @@
     }
   }
 #else
+  (void)thread_id;
   stat = osError;
 #endif
 
@@ -1048,8 +1054,7 @@
   Clear the specified Thread Flags of current running thread.
 */
 uint32_t osThreadFlagsClear (uint32_t flags) {
-  TaskHandle_t hTask;
-  uint32_t rflags, cflags;
+  uint32_t rflags;
 
   if (IRQ_Context() != 0U) {
     rflags = (uint32_t)osErrorISR;
@@ -1058,19 +1063,7 @@
     rflags = (uint32_t)osErrorParameter;
   }
   else {
-    hTask = xTaskGetCurrentTaskHandle();
-
-    if (xTaskNotifyAndQuery (hTask, 0, eNoAction, &cflags) == pdPASS) {
-      rflags = cflags;
-      cflags &= ~flags;
-
-      if (xTaskNotify (hTask, cflags, eSetValueWithOverwrite) != pdPASS) {
-        rflags = (uint32_t)osError;
-      }
-    }
-    else {
-      rflags = (uint32_t)osError;
-    }
+    rflags = ulTaskNotifyValueClear(NULL, flags);
   }
 
   /* Return flags before clearing */
@@ -1326,9 +1319,8 @@
       name = NULL;
 
       if (attr != NULL) {
-        if (attr->name != NULL) {
-          name = attr->name;
-        }
+        /* Take the name from attributes */
+        name = attr->name;
 
         if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticTimer_t))) {
           /* The memory for control block is provided, use static object */
@@ -1477,12 +1469,13 @@
   Delete a timer.
 */
 osStatus_t osTimerDelete (osTimerId_t timer_id) {
-  TimerHandle_t hTimer = (TimerHandle_t)timer_id;
   osStatus_t stat;
+
 #ifndef USE_FreeRTOS_HEAP_1
-#if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
+  TimerHandle_t hTimer = (TimerHandle_t)timer_id;
+  #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
   TimerCallback_t *callb;
-#endif
+  #endif
 
   if (IRQ_Context() != 0U) {
     stat = osErrorISR;
@@ -1511,6 +1504,7 @@
     }
   }
 #else
+  (void)timer_id;
   stat = osError;
 #endif
 
@@ -1742,10 +1736,11 @@
   Delete an Event Flags object.
 */
 osStatus_t osEventFlagsDelete (osEventFlagsId_t ef_id) {
-  EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id;
   osStatus_t stat;
 
 #ifndef USE_FreeRTOS_HEAP_1
+  EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id;
+
   if (IRQ_Context() != 0U) {
     stat = osErrorISR;
   }
@@ -1757,6 +1752,7 @@
     vEventGroupDelete (hEventGroup);
   }
 #else
+  (void)ef_id;
   stat = osError;
 #endif
 
@@ -1973,6 +1969,7 @@
 */
 osStatus_t osMutexDelete (osMutexId_t mutex_id) {
   osStatus_t stat;
+
 #ifndef USE_FreeRTOS_HEAP_1
   SemaphoreHandle_t hMutex;
 
@@ -1992,6 +1989,7 @@
     vSemaphoreDelete (hMutex);
   }
 #else
+  (void)mutex_id;
   stat = osError;
 #endif
 
@@ -2176,10 +2174,11 @@
   Delete a Semaphore object.
 */
 osStatus_t osSemaphoreDelete (osSemaphoreId_t semaphore_id) {
-  SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)semaphore_id;
   osStatus_t stat;
 
 #ifndef USE_FreeRTOS_HEAP_1
+  SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)semaphore_id;
+
   if (IRQ_Context() != 0U) {
     stat = osErrorISR;
   }
@@ -2195,6 +2194,7 @@
     vSemaphoreDelete (hSemaphore);
   }
 #else
+  (void)semaphore_id;
   stat = osError;
 #endif
 
@@ -2432,7 +2432,7 @@
   else if (IRQ_Context() != 0U) {
     isrm = taskENTER_CRITICAL_FROM_ISR();
 
-    space = uxQueueGetQueueLength (hQueue) - uxQueueMessagesWaiting (hQueue);
+    space = uxQueueGetQueueLength (hQueue) - uxQueueMessagesWaitingFromISR (hQueue);
 
     taskEXIT_CRITICAL_FROM_ISR(isrm);
   }
@@ -2470,10 +2470,11 @@
   Delete a Message Queue object.
 */
 osStatus_t osMessageQueueDelete (osMessageQueueId_t mq_id) {
-  QueueHandle_t hQueue = (QueueHandle_t)mq_id;
   osStatus_t stat;
 
 #ifndef USE_FreeRTOS_HEAP_1
+  QueueHandle_t hQueue = (QueueHandle_t)mq_id;
+
   if (IRQ_Context() != 0U) {
     stat = osErrorISR;
   }
@@ -2489,6 +2490,7 @@
     vQueueDelete (hQueue);
   }
 #else
+  (void)mq_id;
   stat = osError;
 #endif
 
@@ -2529,9 +2531,8 @@
     mem_mp = -1;
 
     if (attr != NULL) {
-      if (attr->name != NULL) {
-        name = attr->name;
-      }
+      /* Take the name from attributes */
+      name = attr->name;
 
       if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(MemPool_t))) {
         /* Static control block is provided */
@@ -2568,10 +2569,14 @@
     if (mem_cb == 0) {
       mp = pvPortMalloc (sizeof(MemPool_t));
     } else {
-      mp = attr->cb_mem;
+      if(mem_cb == 1) {
+        mp = attr->cb_mem;
+      }
     }
 
     if (mp != NULL) {
+      mp->mem_arr = NULL;
+
       /* Create a semaphore (max count == initial count == block_count) */
       #if (configSUPPORT_STATIC_ALLOCATION == 1)
         mp->sem = xSemaphoreCreateCountingStatic (block_count, block_count, &mp->mem_sem);
@@ -2586,7 +2591,9 @@
         if (mem_mp == 0) {
           mp->mem_arr = pvPortMalloc (sz);
         } else {
-          mp->mem_arr = attr->mp_mem;
+          if(mem_mp == 1) {
+            mp->mem_arr = attr->mp_mem;
+          }
         }
       }
     }
diff --git a/Source/History.txt b/Source/History.txt
index 7df76e1..7baa62a 100644
--- a/Source/History.txt
+++ b/Source/History.txt
@@ -1,5 +1,255 @@
 Documentation and download available at https://www.FreeRTOS.org/
 
+Changes between FreeRTOS V11.3.0 and FreeRTOS V11.3.1 released August 2026
+
+    + Add Symmetric Multiprocessing (SMP) support to the Armv8-M ports for the
+      GCC, ArmClang and IAR toolchains. This adds per core critical nesting
+      state, spinlocks, inter-core yield and wakeup using SEV/WFE, primary and
+      secondary core bring up synchronization, and a core safe PendSV context
+      switch. Single core builds are unchanged. We thank @AhmedIsmail02 for
+      their contribution.
+    + Add new xTaskPeriodicDelay API for periodic tasks. It supersedes
+      xTaskDelayUntil by preventing run away of pxPreviousWakeTime, catching up
+      skipped periods immediately while returning the number of periods skipped,
+      and returning 0 when not enough ticks have elapsed. We thank @ntd for
+      their contribution.
+    + Add uxTaskCallForEachTask API, which invokes a caller supplied callback
+      for each task in the system, and refactor uxTaskGetSystemState to use it.
+      We thank @DRNadler for their contribution.
+    + Add configIDLE_AFFINITY configuration option, which pins each Idle task to
+      its corresponding core in SMP systems. It defaults to 0, which allows the
+      scheduler to run Idle tasks on any available core. We thank @rus084 for
+      their contribution.
+    + Add validation to SecureContext_AllocateContext in the ARMv8-M secure side
+      ports to ensure that the requested secure stack size plus the stack seal
+      size does not overflow before allocating. We thank Jordan Mecom (Block,
+      Inc.) for reporting this issue.
+    + Add assertions to vQueueDelete to check that no tasks are blocked on the
+      queue being deleted.
+    + Add a link to the FreeRTOS Kernel threat model in SECURITY.md.
+    + Add documentation clarifying that the MemoryRegion_t ulParameters macros
+      are port specific, so applications must use the tskMPU_REGION_* or
+      portMPU_REGION_* values that match their MPU port. We thank @Old-Ding for
+      their contribution.
+    + Add a comment documenting that a privileged task must revoke access
+      permissions before deleting a kernel object when using Access Control
+      Lists.
+    + Update the ARM_CRx_No_GIC port to declare vPortYield as a weak symbol so
+      that devices with a dedicated software interrupt register can substitute
+      their own yield trigger. The default behavior is unchanged. We thank
+      @maximdeclercq for their contribution.
+    + Update the FreeRTOSConfig.h template to use a 32-bit tick type, which
+      avoids compiler warnings on Windows where a 64-bit tick resolves to
+      unsigned long long.
+    + Update the deprecated CMake configuration warning to use INTERFACE rather
+      than PUBLIC for the freertos_config interface library. We thank @Isla-jq
+      for their contribution.
+    + Fix vPortFreeSecureContext in the ARMv8-M ports to read xSecureContext at
+      the correct offset. When the MPU is enabled, the first item in the TCB is
+      the stored context location rather than the top of stack, so
+      xSecureContext is located at a negative offset from that position.
+    + Fix SecureContext_AllocateContext in the ARMv8-M secure side ports to
+      reject a secure stack size smaller than the stack seal size.
+    + Fix SecureContext_FreeContext in the ARMv8-M secure side ports to refuse
+      to free the secure context that is currently loaded, as indicated by
+      PSPLIM. Freeing it left the running task referencing freed secure memory.
+      The task handle supplied by the non-secure side is untrusted, so it is
+      now used only as an additional ownership check.
+    + Fix the ARMv8-M ports to service the portSVC_START_SCHEDULER and
+      portSVC_FREE_SECURE_CONTEXT supervisor calls only when they are raised
+      from privileged code. When the MPU is enabled, both requests are now
+      ignored unless the calling program counter lies within the privileged
+      functions section.
+    + Fix a type confusion in xQueueAddToSet by verifying that the object
+      passed as the queue set really is a queue set, that is, that its item
+      size is sizeof( Queue_t * ). Passing an ordinary queue now returns
+      pdFAIL rather than allowing prvNotifyQueueSetContainer to copy item size
+      bytes from a single pointer on the stack.
+    + Fix xTimerGenericCommandFromTask to validate the lower bound of
+      xCommandID in addition to the existing upper bound, so that only the
+      valid task command range from tmrCOMMAND_START_DONT_TRACE to
+      tmrCOMMAND_DELETE is accepted. Rejected commands return pdFAIL, and
+      behavior for valid commands and for xTimerGenericCommandFromISR is
+      unchanged.
+    + Fix a kernel object pool entry leak by adding an MPU wrapper for the
+      xTimerDelete API, so that the pool index is freed when a timer is deleted
+      with MPU wrappers version 2.
+    + Fix the MPU wrapper macro mapping for the ARMv8-M ports.
+    + Fix silently failing critical sections in unprivileged tasks by
+      disallowing configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS with MPU wrappers
+      version 2 in the ARMv7-M MPU ports. The option now defaults to 0 under
+      version 2, and explicitly setting it to 1 raises a compile time error.
+      Behavior with MPU wrappers version 1 is unchanged.
+    + Fix a time of check to time of use race condition in vTaskListTasks, where
+      reading the volatile task count twice allowed a task to be created between
+      the reads, resulting in an undersized allocation and a possible buffer
+      overflow in uxTaskGetSystemState. We thank @srpatcha for their
+      contribution.
+    + Fix a spurious heap_5 assertion when configENABLE_HEAP_PROTECTOR is 1 and
+      an allocation cannot be satisfied. The free block search reaching the end
+      marker is a normal out of memory condition, so pvPortMalloc now returns
+      NULL and invokes the malloc failed hook instead of asserting.
+    + Fix batching stream buffers to unblock a receiver only after the buffered
+      byte count exceeds, rather than reaches, the trigger level. Previously a
+      receiver could be woken early and xStreamBufferReceive could return 0
+      bytes. Stream buffer and message buffer semantics are unchanged. We thank
+      @officialasishkumar for their contribution.
+    + Fix MISRA C 2012 Rule 20.4 violation by replacing `#define static` with a
+      STATIC macro, which also keeps the static variables in
+      vApplicationGetIdleTaskMemory and vApplicationGetPassiveIdleTaskMemory
+      static when portREMOVE_STATIC_QUALIFIER is defined. We thank @elsonwei for
+      their contribution.
+    + Fix undefined behavior in the MSVC-MingW port caused by left shifting a
+      signed int by 31 or more bits.
+    + Fix a duplicate Doxygen \defgroup identifier by giving
+      uxTaskBasePriorityGet its own group instead of reusing the
+      uxTaskPriorityGet group.
+    + Fix the incorrect #endif comment after vPortSetupTimerInterrupt in the GCC
+      and IAR RISC-V ports, which duplicated configMTIME_BASE_ADDRESS and
+      omitted configMTIMECMP_BASE_ADDRESS. We thank @cuiweixie for their
+      contribution.
+    + Fix incorrect #endif comments in croutine.c and queue.c, which reversed
+      the configUSE_CO_ROUTINES condition and named the wrong configuration
+      option for configSUPPORT_DYNAMIC_ALLOCATION. We thank @Zepp-Hanzj for
+      their contribution.
+    + Fix the configLIST_VOLATILE #endif comment and the documented parameter
+      names for uxListRemove in include/list.h. We thank @rakeshr-source for
+      their contribution.
+    + Fix the type and timeout values used in the xStreamBufferSend and
+      xMessageBufferSend documentation examples. We thank @Isla-jq for their
+      contribution.
+    + Fix copy and paste comment typos in xTaskGetApplicationTaskTag and
+      xTaskGetApplicationTaskTagFromISR, and a typo in the
+      xTaskGenericNotifyWait comment. We thank @wanghengZzz for their
+      contributions.
+    + Fix comment typos in the queue.h, list.h and task.h documentation,
+      including the xQueueReceiveFromISR and xQueueGenericSend examples, the
+      listGET_ITEM_VALUE_OF_HEAD_ENTRY \page tag, and the uxIndexToCLear typo.
+      We thank @zepp-chen for their contribution.
+    + Fix the FreeRTOSConfig.h template path referenced in README.md. We thank
+      @IClementI for their contribution.
+    + Fix the missing V prefix in the release_tag and namespace-prefix inputs of
+      the auto release workflow.
+    + Fix long path failures in the Windows kernel demo builds by enabling
+      Windows long path support in CI.
+    + Remove an unnecessary const variable from the GCC and IAR RISC-V ports. We
+      thank @IClementI for their contribution.
+
+Changes between FreeRTOS V11.2.0 and FreeRTOS V11.3.0 released March 2026
+
+    + Correct minor mistakes in code comments in event_groups.c, include/queue.h,
+      and include/task.h. We thank @wirelinker for their contribution.
+    + Add Arm China STAR-MC3 port support. We thank @cpussw01 for their
+      contribution.
+    + Add Memory Protection Unit (MPU) support to the ARM Cortex-R82 port. We
+      thank @AhmedIsmail02 for their contribution.
+    + Add ARM Cortex-M52 port support for GCC and IAR compilers. We thank
+      @Armchina_JidongMei for their contribution.
+    + Add ARM Cortex-R82 non-MPU port for ARMv8-R AArch64 with SMP support. We
+      thank @AhmedIsmail02 for their contribution.
+    + Add Floating Point Unit (FPU) context save support to the RISC-V port.
+      We thank @cubidesj for their contribution.
+    + Add Vector context save support to the RISC-V port. We thank @cubidesj
+      for their contribution.
+    + Add xPortIsInsideInterrupt API to the RP2040 port to match other ARM
+      ports. We thank @graham-sanderson for their contribution.
+    + Add catch up behavior documentation to xTaskDelayUntil API to explain
+      frequency breaks when catching up for past events.
+    + Add asserts to check for stack overflow at task creation time.
+    + Add assert to check for overflow in xStreamBufferSendFromISR API.
+    + Add assert to check for overflow of recursive mutex counter. We thank
+      @InnerSteff for their contribution.
+    + Add CFI frame unwind information in portable/IAR/RXv2/port_asm.s to
+      enable debugger callstack display beyond __interrupt_27. We thank
+      @bernd-edlinger for their contribution.
+    + Update xTaskDelayUntil to be the preferred delay function in the
+      FreeRTOSConfig.h template.
+    + Update RISC-V port to use saved mstatus for FPU/VPU state determination
+      instead of re-reading after writes, addressing specification-compliant
+      implementations where FS field may change to Dirty.
+    + Update RISC-V port to refine vector context layout on stack for proper
+      register ordering. We thank @Saiiijchan for their contribution.
+    + Update RISC-V port to refine FPU register context offset calculation. We
+      thank @Saiiijchan for their contribution.
+    + Update RISC-V port to use UBaseType_t for ullMachineTimerCompareRegisterBase
+      to resolve warnings on 32-bit platforms.
+    + Update FreeRTOS MPU to remove the assertion and runtime check enforcing
+      matching between configTOTAL_MPU_REGIONS and physical MPU regions,
+      allowing applications to manage a subset of available regions. We thank
+      @ErickReyesR for their contribution.
+    + Update ARM_CRx_No_GIC port to set Data endianness bit in SPSR register
+      for big-endian compilation. We thank @maximdeclercq00 for their
+      contribution.
+    + Update Win32 port to guard timeapi.h include for MinGW compatibility and
+      add compiler-specific headers for cross-compiler support. We thank
+      @nordync for their contribution.
+    + Update Win32 port to move Windows headers to port.c to prevent inclusion
+      of windows.h in all header files and avoid macro conflicts. We thank
+      @creiter64 for their contribution.
+    + Update POSIX port to delete thread key on process exit instead of in
+      xPortStartScheduler to ensure proper cleanup of thread-specific memory.
+    + Update POSIX port to fix race condition in vPortEndScheduler by moving
+      scheduler thread signal after FreeRTOS thread check. We thank
+      @arctic-alpaca for their contribution.
+    + Update RP2040 port to fix use of deprecated volatile semantics for C++20
+      compatibility. We thank @mathiasgredal for their contribution.
+    + Update RP2040 port to propagate PICO_SDK_VERSION_* to parent scope in
+      CMake. We thank @shengtai25 for their contribution.
+    + Update RP2040 port to remove unused code and preprocessor directives. We
+      thank @pascalr for their contribution.
+    + Update RL78 port to fix incorrect register image for pvParameters in FAR
+      data model for IAR compiler. We thank @sauleThsQuin for their
+      contribution.
+    + Update RL78 port to fix compilation failure on portasm.s file due to
+      indentation on ASM macro. We thank @5iBri for their contribution.
+    + Update ARM_CRx_MPU port to add LLVM assembler compatibility by
+      explicitly specifying section flags. We thank @malsyned for their
+      contribution.
+    + Update Cortex-M ports to rename ulStackFrameSize to
+      ulHardwareSavedExceptionFrameSize for improved readability. We thank
+      @AhmedIsmail02 for their contribution.
+    + Update MPLAB PIC32MZ-EF port to add assert to catch register overflow.
+      We thank @mrluzeiro for their contribution.
+    + Update comments related to taskYIELD in queue.h. We thank @Saiiijchan
+      for their contribution.
+    + Fix priority disinheritance in vTaskPriorityDisinheritAfterTimeout to
+      reset the correct priority when the task disinheriting timeout was the
+      only task at that priority.
+    + Fix event groups to remove direct mapping of xEventGroupClearBitsFromISR
+      and xEventGroupSetBitsFromISR to xTimerPendFunctionCallFromISR,
+      resolving redefinition warnings. We thank @AhmedIsmail02 for their
+      contribution.
+    + Fix datatype of queue item length macros from uint8_t to UBaseType_t to
+      match API parameter types.
+    + Fix possible NULL pointer dereference after configASSERT() calls in
+      queue.c and stream_buffer.c. We thank @Florian.LaRoche for their
+      contribution.
+    + Fix Win32 port to prevent SetWaitableTimer() call from being ignored
+      when configASSERT expands to nothing. We thank @kim-schwaner for their
+      contribution.
+    + Fix compiler warnings from gcc -Wconversion. We thank @Florian.LaRoche
+      for their contribution.
+    + Fix compiler warning about gcc -Wwrite-strings in POSIX port. We thank
+      @Florian.LaRoche for their contribution.
+    + Fix set but unused variable warning in pxPortInitialiseStack. We thank
+      @razrbro for their contribution.
+    + Fix missing include to resolve compile error. We thank @mike919192 for
+      their contribution.
+    + Fix missing cast to BaseType_t.
+    + Fix cast in stack allocation for task creation for negative
+      portSTACK_GROWTH. We thank @sidharthseela for their contribution.
+    + Fix missing macro guards in task.h to prevent unintended API access. We
+      thank @SoniHarsh1 for their contribution.
+    + Fix CMake build for GCC_ARM_CRx_MPU by adding to mpu_wrappers patterns.
+      We thank @malsyned for their contribution.
+    + Fix initialization of size_t-type variable by changing macro from
+      portMAX_DELAY to SIZE_MAX. We thank @duyicheng741 for their
+      contribution.
+    + Define configENABLE_PAC and configENABLE_BTI before including portable.h
+      to prevent "used before definition" warnings.
+    + Remove stray semicolon from gcc-ARM_CRx_MPU port.c. We thank
+      @Florian.LaRoche for their contribution.
+
 Changes between FreeRTOS V11.1.0 and FreeRTOS V11.2.0 released March 04, 2025
 
     + Add CC-RH port for Renesas F1Kx devices. We thank @TrongNguyenR for their
diff --git a/Source/README.md b/Source/README.md
index a6d383a..fabe522 100644
--- a/Source/README.md
+++ b/Source/README.md
@@ -1,5 +1,5 @@
 [![CMock Unit Tests](https://github.com/FreeRTOS/FreeRTOS-Kernel/actions/workflows/unit-tests.yml/badge.svg?branch=main&event=push)](https://github.com/FreeRTOS/FreeRTOS-Kernel/actions/workflows/unit-tests.yml?query=branch%3Amain+event%3Apush+workflow%3A%22CMock+Unit+Tests%22++)
-[![codecov](https://codecov.io/gh/FreeRTOS/FreeRTOS-Kernel/badge.svg?branch=main)](https://codecov.io/gh/FreeRTOS/FreeRTOS-Kernel)
+[![codecov](https://app.codecov.io/gh/FreeRTOS/FreeRTOS-Kernel/badge.svg?branch=main)](https://codecov.io/gh/FreeRTOS/FreeRTOS-Kernel)
 
 ## Getting started
 
@@ -130,7 +130,7 @@
 
 - The ```./include``` directory contains the real time kernel header files.
 
-- The ```./template_configuration``` directory contains a sample `FreeRTOSConfig.h` to help jumpstart a new project.
+- The ```./examples/template_configuration``` directory contains a sample `FreeRTOSConfig.h` to help jumpstart a new project.
 See the [FreeRTOSConfig.h](examples/template_configuration/FreeRTOSConfig.h) file for instructions.
 
 ### Code Formatting
diff --git a/Source/croutine.c b/Source/croutine.c
index 99aa0dc..397c052 100644
--- a/Source/croutine.c
+++ b/Source/croutine.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -38,24 +38,26 @@
  * than file scope.
  */
     #ifdef portREMOVE_STATIC_QUALIFIER
-        #define static
+        #define STATIC
+    #else
+        #define STATIC    static
     #endif
 
 
 /* Lists for ready and blocked co-routines. --------------------*/
-    static List_t pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /**< Prioritised ready co-routines. */
-    static List_t xDelayedCoRoutineList1;                                   /**< Delayed co-routines. */
-    static List_t xDelayedCoRoutineList2;                                   /**< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */
-    static List_t * pxDelayedCoRoutineList = NULL;                          /**< Points to the delayed co-routine list currently being used. */
-    static List_t * pxOverflowDelayedCoRoutineList = NULL;                  /**< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */
-    static List_t xPendingReadyCoRoutineList;                               /**< Holds co-routines that have been readied by an external event.  They cannot be added directly to the ready lists as the ready lists cannot be accessed by interrupts. */
+    STATIC List_t pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /**< Prioritised ready co-routines. */
+    STATIC List_t xDelayedCoRoutineList1;                                   /**< Delayed co-routines. */
+    STATIC List_t xDelayedCoRoutineList2;                                   /**< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */
+    STATIC List_t * pxDelayedCoRoutineList = NULL;                          /**< Points to the delayed co-routine list currently being used. */
+    STATIC List_t * pxOverflowDelayedCoRoutineList = NULL;                  /**< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */
+    STATIC List_t xPendingReadyCoRoutineList;                               /**< Holds co-routines that have been readied by an external event.  They cannot be added directly to the ready lists as the ready lists cannot be accessed by interrupts. */
 
 /* Other file private variables. --------------------------------*/
     CRCB_t * pxCurrentCoRoutine = NULL;
-    static UBaseType_t uxTopCoRoutineReadyPriority = ( UBaseType_t ) 0U;
-    static TickType_t xCoRoutineTickCount = ( TickType_t ) 0U;
-    static TickType_t xLastTickCount = ( TickType_t ) 0U;
-    static TickType_t xPassedTicks = ( TickType_t ) 0U;
+    STATIC UBaseType_t uxTopCoRoutineReadyPriority = ( UBaseType_t ) 0U;
+    STATIC TickType_t xCoRoutineTickCount = ( TickType_t ) 0U;
+    STATIC TickType_t xLastTickCount = ( TickType_t ) 0U;
+    STATIC TickType_t xPassedTicks = ( TickType_t ) 0U;
 
 /* The initial state of the co-routine when it is created. */
     #define corINITIAL_STATE    ( 0 )
@@ -80,7 +82,7 @@
  * Utility to ready all the lists used by the scheduler.  This is called
  * automatically upon the creation of the first co-routine.
  */
-    static void prvInitialiseCoRoutineLists( void );
+    STATIC void prvInitialiseCoRoutineLists( void );
 
 /*
  * Co-routines that are readied by an interrupt cannot be placed directly into
@@ -88,7 +90,7 @@
  * in the pending ready list in order that they can later be moved to the ready
  * list by the co-routine scheduler.
  */
-    static void prvCheckPendingReadyList( void );
+    STATIC void prvCheckPendingReadyList( void );
 
 /*
  * Macro that looks at the list of co-routines that are currently delayed to
@@ -98,7 +100,7 @@
  * meaning once one co-routine has been found whose timer has not expired
  * we need not look any further down the list.
  */
-    static void prvCheckDelayedList( void );
+    STATIC void prvCheckDelayedList( void );
 
 /*-----------------------------------------------------------*/
 
@@ -212,7 +214,7 @@
     }
 /*-----------------------------------------------------------*/
 
-    static void prvCheckPendingReadyList( void )
+    STATIC void prvCheckPendingReadyList( void )
     {
         /* Are there any co-routines waiting to get moved to the ready list?  These
          * are co-routines that have been readied by an ISR.  The ISR cannot access
@@ -235,7 +237,7 @@
     }
 /*-----------------------------------------------------------*/
 
-    static void prvCheckDelayedList( void )
+    STATIC void prvCheckDelayedList( void )
     {
         CRCB_t * pxCRCB;
 
@@ -333,7 +335,7 @@
     }
 /*-----------------------------------------------------------*/
 
-    static void prvInitialiseCoRoutineLists( void )
+    STATIC void prvInitialiseCoRoutineLists( void )
     {
         UBaseType_t uxPriority;
 
@@ -402,4 +404,4 @@
     }
 /*-----------------------------------------------------------*/
 
-#endif /* configUSE_CO_ROUTINES == 0 */
+#endif /* configUSE_CO_ROUTINES != 0 */
diff --git a/Source/event_groups.c b/Source/event_groups.c
index 09f2ec0..4714467 100644
--- a/Source/event_groups.c
+++ b/Source/event_groups.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -72,7 +72,7 @@
  * The wait condition is defined by xWaitForAllBits.  If xWaitForAllBits is
  * pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor
  * are also set in uxCurrentEventBits.  If xWaitForAllBits is pdFALSE then the
- * wait condition is met if any of the bits set in uxBitsToWait for are also set
+ * wait condition is met if any of the bits set in uxBitsToWaitFor are also set
  * in uxCurrentEventBits.
  */
     static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
@@ -501,7 +501,7 @@
     }
 /*-----------------------------------------------------------*/
 
-    #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
+    #if ( ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
 
         BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
                                                 const EventBits_t uxBitsToClear )
@@ -511,14 +511,14 @@
             traceENTER_xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear );
 
             traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );
-            xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL );
+            xReturn = xTimerPendFunctionCallFromISR( &vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL );
 
             traceRETURN_xEventGroupClearBitsFromISR( xReturn );
 
             return xReturn;
         }
 
-    #endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
+    #endif /* if ( ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
 /*-----------------------------------------------------------*/
 
     EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
@@ -812,7 +812,7 @@
     }
 /*-----------------------------------------------------------*/
 
-    #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
+    #if ( ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
 
         BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
                                               const EventBits_t uxBitsToSet,
@@ -823,14 +823,14 @@
             traceENTER_xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken );
 
             traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );
-            xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken );
+            xReturn = xTimerPendFunctionCallFromISR( &vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken );
 
             traceRETURN_xEventGroupSetBitsFromISR( xReturn );
 
             return xReturn;
         }
 
-    #endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
+    #endif /* if ( ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
 /*-----------------------------------------------------------*/
 
     #if ( configUSE_TRACE_FACILITY == 1 )
diff --git a/Source/include/FreeRTOS.h b/Source/include/FreeRTOS.h
index 75459a9..1a7e6e7 100644
--- a/Source/include/FreeRTOS.h
+++ b/Source/include/FreeRTOS.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -101,6 +101,16 @@
     #define configASSERT_DEFINED    1
 #endif
 
+/* Set configENABLE_PAC and/or configENABLE_BTI to 1 to enable PAC and/or BTI
+ * support and 0 to disable them. These are currently used in ARMv8.1-M ports. */
+#ifndef configENABLE_PAC
+    #define configENABLE_PAC    0
+#endif
+
+#ifndef configENABLE_BTI
+    #define configENABLE_BTI    0
+#endif
+
 /* Basic FreeRTOS definitions. */
 #include "projdefs.h"
 
@@ -367,6 +377,10 @@
     #define configIDLE_SHOULD_YIELD    1
 #endif
 
+#ifndef configIDLE_AFFINITY
+    #define configIDLE_AFFINITY    0
+#endif
+
 #if configMAX_TASK_NAME_LEN < 1
     #error configMAX_TASK_NAME_LEN must be set to a minimum of 1 in FreeRTOSConfig.h
 #endif
@@ -1756,6 +1770,14 @@
     #define traceRETURN_vTaskDelete()
 #endif
 
+#ifndef traceENTER_xTaskPeriodicDelay
+    #define traceENTER_xTaskPeriodicDelay( pxPreviousWakeTime, xTimeIncrement )
+#endif
+
+#ifndef traceRETURN_xTaskPeriodicDelay
+    #define traceRETURN_xTaskPeriodicDelay( xIncrements )
+#endif
+
 #ifndef traceENTER_xTaskDelayUntil
     #define traceENTER_xTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement )
 #endif
@@ -3040,16 +3062,6 @@
     #define configCONTROL_INFINITE_LOOP()
 #endif
 
-/* Set configENABLE_PAC and/or configENABLE_BTI to 1 to enable PAC and/or BTI
- * support and 0 to disable them. These are currently used in ARMv8.1-M ports. */
-#ifndef configENABLE_PAC
-    #define configENABLE_PAC    0
-#endif
-
-#ifndef configENABLE_BTI
-    #define configENABLE_BTI    0
-#endif
-
 /* Sometimes the FreeRTOSConfig.h settings only allow a task to be created using
  * dynamically allocated RAM, in which case when any task is deleted it is known
  * that both the task's stack and TCB need to be freed.  Sometimes the
diff --git a/Source/include/FreeRTOSConfig_template.h b/Source/include/FreeRTOSConfig_template.h
index 4df0001..88efedd 100644
--- a/Source/include/FreeRTOSConfig_template.h
+++ b/Source/include/FreeRTOSConfig_template.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -136,7 +136,7 @@
  *
  * Defining configTICK_TYPE_WIDTH_IN_BITS as TICK_TYPE_WIDTH_64_BITS causes
  * TickType_t to be defined (typedef'ed) as an unsigned 64-bit type. */
-#define configTICK_TYPE_WIDTH_IN_BITS              TICK_TYPE_WIDTH_64_BITS
+#define configTICK_TYPE_WIDTH_IN_BITS              TICK_TYPE_WIDTH_32_BITS
 
 /* Set configIDLE_SHOULD_YIELD to 1 to have the Idle task yield to an
  * application task if there is an Idle priority (priority 0) application task
@@ -415,6 +415,8 @@
  * number of the failing assert (for example, "vAssertCalled( __FILE__, __LINE__
  * )" or it can simple disable interrupts and sit in a loop to halt all
  * execution on the failing line for viewing in a debugger. */
+
+/* *INDENT-OFF* */
 #define configASSERT( x )         \
     if( ( x ) == 0 )              \
     {                             \
@@ -422,6 +424,7 @@
         for( ; ; )                \
         ;                         \
     }
+/* *INDENT-ON* */
 
 /******************************************************************************/
 /* FreeRTOS MPU specific definitions. *****************************************/
@@ -555,6 +558,13 @@
  * tskNO_AFFINITY if left undefined. */
 #define configTIMER_SERVICE_TASK_CORE_AFFINITY    tskNO_AFFINITY
 
+/* When using SMP (i.e. configNUMBER_OF_CORES is greater than one), set
+ * configIDLE_AFFINITY to 1 to pin each Idle task to its corresponding
+ * core. When set to 1, Idle task N will only run on core N, using an affinity
+ * mask of (1 << N).  Set to 0 to allow the scheduler to run Idle tasks on any
+ * available core.  Defaults to 0 if left undefined. */
+#define configIDLE_AFFINITY                       0
+
 /******************************************************************************/
 /* ARMv8-M secure side port related definitions. ******************************/
 /******************************************************************************/
@@ -567,7 +577,7 @@
 /* Defines the kernel provided implementation of
  * vApplicationGetIdleTaskMemory() and vApplicationGetTimerTaskMemory()
  * to provide the memory that is used by the Idle task and Timer task
- * respectively. The application can provide it's own implementation of
+ * respectively. The application can provide its own implementation of
  * vApplicationGetIdleTaskMemory() and vApplicationGetTimerTaskMemory() by
  * setting configKERNEL_PROVIDED_STATIC_MEMORY to 0 or leaving it undefined. */
 #define configKERNEL_PROVIDED_STATIC_MEMORY    1
@@ -599,10 +609,10 @@
 
 /* Set configENABLE_MVE to 1 to enable the M-Profile Vector Extension (MVE)
  * support, or 0 to leave the MVE support disabled. This option is only
- * applicable to Cortex-M55 and Cortex-M85 ports as M-Profile Vector Extension
- * (MVE) is available only on these architectures. configENABLE_MVE must be left
- * undefined, or defined to 0 for the Cortex-M23,Cortex-M33 and Cortex-M35P
- * ports. */
+ * applicable to Cortex-M52, Cortex-M55, Cortex-M85 and STAR-MC3 ports as
+ * M-Profile Vector Extension (MVE) is available only on these architectures.
+ * configENABLE_MVE must be left undefined, or defined to 0 for the
+ * Cortex-M23,Cortex-M33 and Cortex-M35P ports. */
 #define configENABLE_MVE                  1
 
 /******************************************************************************/
@@ -650,7 +660,7 @@
 #define INCLUDE_uxTaskPriorityGet              1
 #define INCLUDE_vTaskDelete                    1
 #define INCLUDE_vTaskSuspend                   1
-#define INCLUDE_vTaskDelayUntil                1
+#define INCLUDE_xTaskDelayUntil                1
 #define INCLUDE_vTaskDelay                     1
 #define INCLUDE_xTaskGetSchedulerState         1
 #define INCLUDE_xTaskGetCurrentTaskHandle      1
diff --git a/Source/include/StackMacros.h b/Source/include/StackMacros.h
index a500ccb..9acfa18 100644
--- a/Source/include/StackMacros.h
+++ b/Source/include/StackMacros.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/include/atomic.h b/Source/include/atomic.h
index 0a75b94..6bacfad 100644
--- a/Source/include/atomic.h
+++ b/Source/include/atomic.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/include/croutine.h b/Source/include/croutine.h
index b9aa577..07ca2bd 100644
--- a/Source/include/croutine.h
+++ b/Source/include/croutine.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -246,7 +246,10 @@
  * \defgroup crSTART crSTART
  * \ingroup Tasks
  */
+
+/* *INDENT-OFF* */
 #define crEND()    }
+/* *INDENT-ON* */
 
 /*
  * These macros are intended for internal use by the co-routine implementation
@@ -525,7 +528,7 @@
  * functions used by tasks.
  *
  * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to
- * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and
+ * pass data between a co-routine and ISR, whereas xQueueSendFromISR() and
  * xQueueReceiveFromISR() can only be used to pass data between a task and and
  * ISR.
  *
@@ -625,7 +628,7 @@
  * functions used by tasks.
  *
  * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to
- * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and
+ * pass data between a co-routine and ISR, whereas xQueueSendFromISR() and
  * xQueueReceiveFromISR() can only be used to pass data between a task and and
  * ISR.
  *
diff --git a/Source/include/deprecated_definitions.h b/Source/include/deprecated_definitions.h
index 1718a32..ce0d555 100644
--- a/Source/include/deprecated_definitions.h
+++ b/Source/include/deprecated_definitions.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/include/event_groups.h b/Source/include/event_groups.h
index ef14e78..1120183 100644
--- a/Source/include/event_groups.h
+++ b/Source/include/event_groups.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -452,13 +452,10 @@
  * \defgroup xEventGroupClearBitsFromISR xEventGroupClearBitsFromISR
  * \ingroup EventGroup
  */
-#if ( configUSE_TRACE_FACILITY == 1 )
+#if ( ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
     BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
                                             const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;
-#else
-    #define xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ) \
-    xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) ( xEventGroup ), ( uint32_t ) ( uxBitsToClear ), NULL )
-#endif
+#endif /* if ( ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
 
 /**
  * event_groups.h
@@ -607,14 +604,11 @@
  * \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR
  * \ingroup EventGroup
  */
-#if ( configUSE_TRACE_FACILITY == 1 )
+#if ( ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
     BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
                                           const EventBits_t uxBitsToSet,
                                           BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
-#else
-    #define xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ) \
-    xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) ( xEventGroup ), ( uint32_t ) ( uxBitsToSet ), ( pxHigherPriorityTaskWoken ) )
-#endif
+#endif /* if ( ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
 
 /**
  * event_groups.h
diff --git a/Source/include/list.h b/Source/include/list.h
index 7de4d36..769b047 100644
--- a/Source/include/list.h
+++ b/Source/include/list.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -31,7 +31,7 @@
  * heavily for the schedulers needs, it is also available for use by
  * application code.
  *
- * list_ts can only store pointers to list_item_ts.  Each ListItem_t contains a
+ * List_t can only store pointers to ListItem_t.  Each ListItem_t contains a
  * numeric value (xItemValue).  Most of the time the lists are sorted in
  * ascending item value order.
  *
@@ -42,9 +42,9 @@
  * is because the tail contains a wrap back pointer to the true head of
  * the list.
  *
- * In addition to it's value, each list item contains a pointer to the next
+ * In addition to its value, each list item contains a pointer to the next
  * item in the list (pxNext), a pointer to the list it is in (pxContainer)
- * and a pointer to back to the object that contains it.  These later two
+ * and a pointer back to the object that contains it.  These later two
  * pointers are included for efficiency of list manipulation.  There is
  * effectively a two way link between the object containing the list item and
  * the list item itself.
@@ -74,7 +74,7 @@
  * compiler's options were set for maximum optimisation has been inspected and
  * deemed to be as intended.  That said, as compiler technology advances, and
  * especially if aggressive cross module optimisation is used (a use case that
- * has not been exercised to any great extend) then it is feasible that the
+ * has not been exercised to any great extent) then it is feasible that the
  * volatile qualifier will be needed for correct optimisation.  It is expected
  * that a compiler removing essential code because, without the volatile
  * qualifier on the list structure members and with aggressive cross module
@@ -92,7 +92,7 @@
  */
 #ifndef configLIST_VOLATILE
     #define configLIST_VOLATILE
-#endif /* configSUPPORT_CROSS_MODULE_OPTIMISATION */
+#endif /* configLIST_VOLATILE */
 
 /* *INDENT-OFF* */
 #ifdef __cplusplus
@@ -191,7 +191,7 @@
  * Access macro to get the owner of a list item.  The owner of a list item
  * is the object (usually a TCB) that contains the list item.
  *
- * \page listGET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER
+ * \page listGET_LIST_ITEM_OWNER listGET_LIST_ITEM_OWNER
  * \ingroup LinkedList
  */
 #define listGET_LIST_ITEM_OWNER( pxListItem )             ( ( pxListItem )->pvOwner )
@@ -219,7 +219,7 @@
  * Access macro to retrieve the value of the list item at the head of a given
  * list.
  *
- * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
+ * \page listGET_ITEM_VALUE_OF_HEAD_ENTRY listGET_ITEM_VALUE_OF_HEAD_ENTRY
  * \ingroup LinkedList
  */
 #define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList )        ( ( ( pxList )->xListEnd ).pxNext->xItemValue )
@@ -310,7 +310,7 @@
  * Remove an item from a list.  The list item has a pointer to the list that
  * it is in, so only the list item need be passed into the function.
  *
- * @param uxListRemove The item to be removed.  The item will remove itself from
+ * @param pxItemToRemove The item to be removed.  The item will remove itself from
  * the list pointed to by it's pxContainer parameter.
  *
  * @return The number of items that remain in the list after the list item has
@@ -491,7 +491,7 @@
  * Remove an item from a list.  The list item has a pointer to the list that
  * it is in, so only the list item need be passed into the function.
  *
- * @param uxListRemove The item to be removed.  The item will remove itself from
+ * @param pxItemToRemove The item to be removed.  The item will remove itself from
  * the list pointed to by it's pxContainer parameter.
  *
  * @return The number of items that remain in the list after the list item has
diff --git a/Source/include/message_buffer.h b/Source/include/message_buffer.h
index 5c4d15b..cba18d3 100644
--- a/Source/include/message_buffer.h
+++ b/Source/include/message_buffer.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -560,14 +560,14 @@
  *
  * Example use:
  * @code{c}
- * void vAFunction( MessageBuffer_t xMessageBuffer )
+ * void vAFunction( MessageBufferHandle_t xMessageBuffer )
  * {
  * uint8_t ucRxData[ 20 ];
  * size_t xReceivedBytes;
  * const TickType_t xBlockTime = pdMS_TO_TICKS( 20 );
  *
  *  // Receive the next message from the message buffer.  Wait in the Blocked
- *  // state (so not using any CPU processing time) for a maximum of 100ms for
+ *  // state (so not using any CPU processing time) for a maximum of 20ms for
  *  // a message to become available.
  *  xReceivedBytes = xMessageBufferReceive( xMessageBuffer,
  *                                          ( void * ) ucRxData,
@@ -655,7 +655,7 @@
  * Example use:
  * @code{c}
  * // A message buffer that has already been created.
- * MessageBuffer_t xMessageBuffer;
+ * MessageBufferHandle_t xMessageBuffer;
  *
  * void vAnInterruptServiceRoutine( void )
  * {
diff --git a/Source/include/mpu_prototypes.h b/Source/include/mpu_prototypes.h
index 3a2bff5..00d8c09 100644
--- a/Source/include/mpu_prototypes.h
+++ b/Source/include/mpu_prototypes.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -369,6 +369,9 @@
                                             BaseType_t * const pxHigherPriorityTaskWoken,
                                             const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
 
+BaseType_t MPU_xTimerDelete( TimerHandle_t xTimer,
+                             TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
+
 /* MPU versions of event_group.h API functions. */
 EventBits_t MPU_xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
                                      const EventBits_t uxBitsToWaitFor,
@@ -409,13 +412,16 @@
 
 BaseType_t MPU_xEventGroupGetStaticBuffer( EventGroupHandle_t xEventGroup,
                                            StaticEventGroup_t ** ppxEventGroupBuffer ) PRIVILEGED_FUNCTION;
-BaseType_t MPU_xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
-                                            const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;
-BaseType_t MPU_xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
-                                          const EventBits_t uxBitsToSet,
-                                          BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
 EventBits_t MPU_xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
 
+#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
+    BaseType_t MPU_xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
+                                                const EventBits_t uxBitsToClear ) FREERTOS_SYSTEM_CALL;
+    BaseType_t MPU_xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
+                                              const EventBits_t uxBitsToSet,
+                                              BaseType_t * pxHigherPriorityTaskWoken ) FREERTOS_SYSTEM_CALL;
+#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
+
 /* MPU versions of message/stream_buffer.h API functions. */
 size_t MPU_xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
                               const void * pvTxData,
diff --git a/Source/include/mpu_syscall_numbers.h b/Source/include/mpu_syscall_numbers.h
index 7203a3a..4531bb2 100644
--- a/Source/include/mpu_syscall_numbers.h
+++ b/Source/include/mpu_syscall_numbers.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/include/mpu_wrappers.h b/Source/include/mpu_wrappers.h
index 1bad3a2..9779036 100644
--- a/Source/include/mpu_wrappers.h
+++ b/Source/include/mpu_wrappers.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -190,6 +190,7 @@
             #define xTimerCreateStatic             MPU_xTimerCreateStatic
             #define xTimerGetStaticBuffer          MPU_xTimerGetStaticBuffer
             #define xTimerGenericCommandFromISR    MPU_xTimerGenericCommandFromISR
+            #define xTimerDelete                   MPU_xTimerDelete
         #endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
 
 /* Map standard event_group.h API functions to the MPU equivalents. */
@@ -249,6 +250,9 @@
         #if ( ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) )
 
             #define vGrantAccessToTask( xTask, xTaskToGrantAccess )                        vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xTaskToGrantAccess ) )
+
+/* A privileged task must revoke access to the object before deletion,
+ * otherwise index reuse may result in accidental permissions. */
             #define vRevokeAccessToTask( xTask, xTaskToRevokeAccess )                      vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xTaskToRevokeAccess ) )
 
             #define vGrantAccessToSemaphore( xTask, xSemaphoreToGrantAccess )              vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xSemaphoreToGrantAccess ) )
diff --git a/Source/include/newlib-freertos.h b/Source/include/newlib-freertos.h
index 3aa344a..11435e8 100644
--- a/Source/include/newlib-freertos.h
+++ b/Source/include/newlib-freertos.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/include/picolibc-freertos.h b/Source/include/picolibc-freertos.h
index 677205d..641b55f 100644
--- a/Source/include/picolibc-freertos.h
+++ b/Source/include/picolibc-freertos.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/include/portable.h b/Source/include/portable.h
index 601062a..aa23e2d 100644
--- a/Source/include/portable.h
+++ b/Source/include/portable.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/include/projdefs.h b/Source/include/projdefs.h
index c9ac64a..ceaadf4 100644
--- a/Source/include/projdefs.h
+++ b/Source/include/projdefs.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/include/queue.h b/Source/include/queue.h
index 7c8e0de..48ea4db 100644
--- a/Source/include/queue.h
+++ b/Source/include/queue.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -44,7 +44,7 @@
 
 /**
  * Type by which queues are referenced.  For example, a call to xQueueCreate()
- * returns an QueueHandle_t variable that can then be used as a parameter to
+ * returns a QueueHandle_t variable that can then be used as a parameter to
  * xQueueSend(), xQueueReceive(), etc.
  */
 struct QueueDefinition; /* Using old naming convention so as not to break kernel aware debuggers. */
@@ -60,7 +60,7 @@
 /**
  * Queue sets can contain both queues and semaphores, so the
  * QueueSetMemberHandle_t is defined as a type to be used where a parameter or
- * return value can be either an QueueHandle_t or an SemaphoreHandle_t.
+ * return value can be either a QueueHandle_t or a SemaphoreHandle_t.
  */
 typedef struct QueueDefinition   * QueueSetMemberHandle_t;
 
@@ -185,7 +185,7 @@
  * @param pucQueueStorage If uxItemSize is not zero then
  * pucQueueStorage must point to a uint8_t array that is at least large
  * enough to hold the maximum number of items that can be in the queue at any
- * one time - which is ( uxQueueLength * uxItemsSize ) bytes.  If uxItemSize is
+ * one time - which is ( uxQueueLength * uxItemSize ) bytes.  If uxItemSize is
  * zero then pucQueueStorage can be NULL.
  *
  * @param pxQueueBuffer Must point to a variable of type StaticQueue_t, which
@@ -202,8 +202,8 @@
  *  char ucData[ 20 ];
  * };
  *
- #define QUEUE_LENGTH 10
- #define ITEM_SIZE sizeof( uint32_t )
+ * #define QUEUE_LENGTH 10
+ * #define ITEM_SIZE sizeof( uint32_t )
  *
  * // xQueueBuffer will hold the queue structure.
  * StaticQueue_t xQueueBuffer;
@@ -217,10 +217,10 @@
  *  QueueHandle_t xQueue1;
  *
  *  // Create a queue capable of containing 10 uint32_t values.
- *  xQueue1 = xQueueCreate( QUEUE_LENGTH, // The number of items the queue can hold.
- *                          ITEM_SIZE     // The size of each item in the queue
- *                          &( ucQueueStorage[ 0 ] ), // The buffer that will hold the items in the queue.
- *                          &xQueueBuffer ); // The buffer that will hold the queue structure.
+ *  xQueue1 = xQueueCreateStatic( QUEUE_LENGTH,             // The number of items the queue can hold.
+ *                                ITEM_SIZE,                // The size of each item in the queue.
+ *                                &( ucQueueStorage[ 0 ] ), // The buffer that will hold the items in the queue.
+ *                                &xQueueBuffer );          // The buffer that will hold the queue structure.
  *
  *  // The queue is guaranteed to be created successfully as no dynamic memory
  *  // allocation is used.  Therefore xQueue1 is now a handle to a valid queue.
@@ -604,7 +604,7 @@
  * BaseType_t xQueueGenericSend(
  *                                  QueueHandle_t xQueue,
  *                                  const void * pvItemToQueue,
- *                                  TickType_t xTicksToWait
+ *                                  TickType_t xTicksToWait,
  *                                  BaseType_t xCopyPosition
  *                              );
  * @endcode
@@ -1026,7 +1026,11 @@
  *  // Now the buffer is empty we can switch context if necessary.
  *  if( xHigherPriorityTaskWoken )
  *  {
- *      taskYIELD ();
+ *      // As xHigherPriorityTaskWoken is now set to pdTRUE then a context
+ *      // switch should be requested. The macro used is port specific and
+ *      // will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() -
+ *      // refer to the documentation page for the port being used.
+ *      portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
  *  }
  * }
  * @endcode
@@ -1098,7 +1102,11 @@
  *  // Now the buffer is empty we can switch context if necessary.
  *  if( xHigherPriorityTaskWoken )
  *  {
- *      taskYIELD ();
+ *      // As xHigherPriorityTaskWoken is now set to pdTRUE then a context
+ *      // switch should be requested. The macro used is port specific and
+ *      // will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() -
+ *      // refer to the documentation page for the port being used.
+ *      portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
  *  }
  * }
  * @endcode
@@ -1181,7 +1189,7 @@
  *
  *  // ...
  *
- *  if( xHigherPrioritytaskWoken == pdTRUE )
+ *  if( xHigherPriorityTaskWoken == pdTRUE )
  *  {
  *      // Writing to the queue caused a task to unblock and the unblocked task
  *      // has a priority higher than or equal to the priority of the currently
@@ -1429,23 +1437,27 @@
  * // ISR that outputs all the characters received on the queue.
  * void vISR_Routine( void )
  * {
- * BaseType_t xTaskWokenByReceive = pdFALSE;
+ * BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  * char cRxedChar;
  *
- *  while( xQueueReceiveFromISR( xQueue, ( void * ) &cRxedChar, &xTaskWokenByReceive) )
+ *  while( xQueueReceiveFromISR( xQueue, ( void * ) &cRxedChar, &xHigherPriorityTaskWoken) )
  *  {
  *      // A character was received.  Output the character now.
  *      vOutputCharacter( cRxedChar );
  *
  *      // If removing the character from the queue woke the task that was
- *      // posting onto the queue xTaskWokenByReceive will have been set to
+ *      // posting onto the queue xHigherPriorityTaskWoken will have been set to
  *      // pdTRUE.  No matter how many times this loop iterates only one
  *      // task will be woken.
  *  }
  *
- *  if( xTaskWokenByReceive != ( char ) pdFALSE;
+ *  if( xHigherPriorityTaskWoken == pdTRUE )
  *  {
- *      taskYIELD ();
+ *      // As xHigherPriorityTaskWoken is now set to pdTRUE then a context
+ *      // switch should be requested. The macro used is port specific and
+ *      // will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() -
+ *      // refer to the documentation page for the port being used.
+ *      portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
  *  }
  * }
  * @endcode
@@ -1652,7 +1664,7 @@
  * Note 2:  Blocking on a queue set that contains a mutex will not cause the
  * mutex holder to inherit the priority of the blocked task.
  *
- * Note 3:  An additional 4 bytes of RAM is required for each space in a every
+ * Note 3:  An additional 4 bytes of RAM is required for each space in every
  * queue added to a queue set.  Therefore counting semaphores that have a high
  * maximum count value should not be added to a queue set.
  *
@@ -1704,7 +1716,7 @@
  * Note 2:  Blocking on a queue set that contains a mutex will not cause the
  * mutex holder to inherit the priority of the blocked task.
  *
- * Note 3:  An additional 4 bytes of RAM is required for each space in a every
+ * Note 3:  An additional 4 bytes of RAM is required for each space in every
  * queue added to a queue set.  Therefore counting semaphores that have a high
  * maximum count value should not be added to a queue set.
  *
@@ -1755,7 +1767,7 @@
  * a call to xQueueSelectFromSet() has first returned a handle to that set member.
  *
  * @param xQueueOrSemaphore The handle of the queue or semaphore being added to
- * the queue set (cast to an QueueSetMemberHandle_t type).
+ * the queue set (cast to a QueueSetMemberHandle_t type).
  *
  * @param xQueueSet The handle of the queue set to which the queue or semaphore
  * is being added.
@@ -1778,7 +1790,7 @@
  * function.
  *
  * @param xQueueOrSemaphore The handle of the queue or semaphore being removed
- * from the queue set (cast to an QueueSetMemberHandle_t type).
+ * from the queue set (cast to a QueueSetMemberHandle_t type).
  *
  * @param xQueueSet The handle of the queue set in which the queue or semaphore
  * is included.
@@ -1824,7 +1836,7 @@
  * a QueueSetMemberHandle_t type) contained in the queue set that contains data,
  * or the handle of a semaphore (cast to a QueueSetMemberHandle_t type) contained
  * in the queue set that is available, or NULL if no such queue or semaphore
- * exists before before the specified block time expires.
+ * exists before the specified block time expires.
  */
 #if ( configUSE_QUEUE_SETS == 1 )
     QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet,
diff --git a/Source/include/semphr.h b/Source/include/semphr.h
index 4767514..7d16072 100644
--- a/Source/include/semphr.h
+++ b/Source/include/semphr.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -37,8 +37,8 @@
 
 typedef QueueHandle_t SemaphoreHandle_t;
 
-#define semBINARY_SEMAPHORE_QUEUE_LENGTH    ( ( uint8_t ) 1U )
-#define semSEMAPHORE_QUEUE_ITEM_LENGTH      ( ( uint8_t ) 0U )
+#define semBINARY_SEMAPHORE_QUEUE_LENGTH    ( ( UBaseType_t ) 1U )
+#define semSEMAPHORE_QUEUE_ITEM_LENGTH      ( ( UBaseType_t ) 0U )
 #define semGIVE_BLOCK_TIME                  ( ( TickType_t ) 0U )
 
 
diff --git a/Source/include/stack_macros.h b/Source/include/stack_macros.h
index 20acaf3..fc63278 100644
--- a/Source/include/stack_macros.h
+++ b/Source/include/stack_macros.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/include/stdint.readme b/Source/include/stdint.readme
index 517a77e..af5978f 100644
--- a/Source/include/stdint.readme
+++ b/Source/include/stdint.readme
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/include/stream_buffer.h b/Source/include/stream_buffer.h
index b257b82..321baa6 100644
--- a/Source/include/stream_buffer.h
+++ b/Source/include/stream_buffer.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -760,7 +760,7 @@
  *
  * Example use:
  * @code{c}
- * void vAFunction( StreamBuffer_t xStreamBuffer )
+ * void vAFunction( StreamBufferHandle_t xStreamBuffer )
  * {
  * uint8_t ucRxData[ 20 ];
  * size_t xReceivedBytes;
@@ -768,7 +768,7 @@
  *
  *  // Receive up to another sizeof( ucRxData ) bytes from the stream buffer.
  *  // Wait in the Blocked state (so not using any CPU processing time) for a
- *  // maximum of 100ms for the full sizeof( ucRxData ) number of bytes to be
+ *  // maximum of 20ms for the full sizeof( ucRxData ) number of bytes to be
  *  // available.
  *  xReceivedBytes = xStreamBufferReceive( xStreamBuffer,
  *                                         ( void * ) ucRxData,
@@ -840,7 +840,7 @@
  * Example use:
  * @code{c}
  * // A stream buffer that has already been created.
- * StreamBuffer_t xStreamBuffer;
+ * StreamBufferHandle_t xStreamBuffer;
  *
  * void vAnInterruptServiceRoutine( void )
  * {
@@ -1218,7 +1218,7 @@
  * stream_buffer.h
  *
  * @code{c}
- * void vStreamBufferSetStreamBufferNotificationIndex ( StreamBuffer_t xStreamBuffer, UBaseType_t uxNotificationIndex );
+ * void vStreamBufferSetStreamBufferNotificationIndex ( StreamBufferHandle_t xStreamBuffer, UBaseType_t uxNotificationIndex );
  * @endcode
  *
  * Set the task notification index used for the supplied stream buffer.
diff --git a/Source/include/task.h b/Source/include/task.h
index b910197..09f1875 100644
--- a/Source/include/task.h
+++ b/Source/include/task.h
@@ -1,6 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -53,10 +54,10 @@
  * The tskKERNEL_VERSION_MAJOR, tskKERNEL_VERSION_MINOR, tskKERNEL_VERSION_BUILD
  * values will reflect the last released version number.
  */
-#define tskKERNEL_VERSION_NUMBER                      "V11.2.0"
+#define tskKERNEL_VERSION_NUMBER                      "V11.3.1"
 #define tskKERNEL_VERSION_MAJOR                       11
-#define tskKERNEL_VERSION_MINOR                       2
-#define tskKERNEL_VERSION_BUILD                       0
+#define tskKERNEL_VERSION_MINOR                       3
+#define tskKERNEL_VERSION_BUILD                       1
 
 /* MPU region parameters passed in ulParameters
  * of MemoryRegion_t struct. */
@@ -68,24 +69,27 @@
 #if defined( portARMV8M_MINOR_VERSION ) && ( portARMV8M_MINOR_VERSION >= 1 )
     #define tskMPU_REGION_PRIVILEGED_EXECUTE_NEVER    ( 1U << 5U )
 #endif /* portARMV8M_MINOR_VERSION >= 1 */
+#define tskMPU_REGION_NON_SHAREABLE                   ( 1U << 6U )
+#define tskMPU_REGION_OUTER_SHAREABLE                 ( 1U << 7U )
+#define tskMPU_REGION_INNER_SHAREABLE                 ( 1U << 8U )
 
 /* MPU region permissions stored in MPU settings to
  * authorize access requests. */
-#define tskMPU_READ_PERMISSION        ( 1U << 0U )
-#define tskMPU_WRITE_PERMISSION       ( 1U << 1U )
+#define tskMPU_READ_PERMISSION                        ( 1U << 0U )
+#define tskMPU_WRITE_PERMISSION                       ( 1U << 1U )
 
 /* The direct to task notification feature used to have only a single notification
  * per task.  Now there is an array of notifications per task that is dimensioned by
  * configTASK_NOTIFICATION_ARRAY_ENTRIES.  For backward compatibility, any use of the
  * original direct to task notification defaults to using the first index in the
  * array. */
-#define tskDEFAULT_INDEX_TO_NOTIFY    ( 0 )
+#define tskDEFAULT_INDEX_TO_NOTIFY                    ( 0 )
 
 /**
  * task. h
  *
  * Type by which tasks are referenced.  For example, a call to xTaskCreate
- * returns (via a pointer parameter) an TaskHandle_t variable that can then
+ * returns (via a pointer parameter) a TaskHandle_t variable that can then
  * be used as a parameter to vTaskDelete to delete the task.
  *
  * \defgroup TaskHandle_t TaskHandle_t
@@ -180,6 +184,13 @@
     #endif
 } TaskStatus_t;
 
+/* Callback type used by uxTaskCallForEachTask(). The callback receives one
+ * task handle and state at a time, plus an opaque caller-supplied context
+ * pointer. The callback may call vTaskGetInfo() if it needs a TaskStatus_t. */
+typedef void (* TaskStatusCallbackFunction_t)( TaskHandle_t xTask,
+                                               eTaskState eState,
+                                               void * pvCallbackContext );
+
 /* Possible return values for eTaskConfirmSleepModeStatus(). */
 typedef enum
 {
@@ -544,6 +555,14 @@
  * The function parameters define the memory regions and associated access
  * permissions allocated to the task.
  *
+ * The parameter macros used in MemoryRegion_t.ulParameters are port specific.
+ * Some ports, including the Cortex-M3/4 MPU ports, use the portMPU_REGION_*
+ * values shown below.
+ * ARMv8-M MPU ports, such as CM23, CM33, CM52, CM55, CM85 and STAR_MC3, use
+ * the tskMPU_REGION_* values defined in this header; the port translates them
+ * into MPU register settings. Check the selected port's headers before selecting
+ * the region parameter macros.
+ *
  * See xTaskCreateRestrictedStatic() for a version that does not use any
  * dynamic memory allocation.
  *
@@ -560,7 +579,7 @@
  *
  * Example usage:
  * @code{c}
- * // Create an TaskParameters_t structure that defines the task to be created.
+ * // Create a TaskParameters_t structure that defines the task to be created.
  * static const TaskParameters_t xCheckTaskParameters =
  * {
  *  vATask,     // pvTaskCode - the function that implements the task.
@@ -602,12 +621,12 @@
  * \defgroup xTaskCreateRestricted xTaskCreateRestricted
  * \ingroup Tasks
  */
-#if ( portUSING_MPU_WRAPPERS == 1 )
+#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
     BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition,
                                       TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION;
 #endif
 
-#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
+#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
     BaseType_t xTaskCreateRestrictedAffinitySet( const TaskParameters_t * const pxTaskDefinition,
                                                  UBaseType_t uxCoreAffinityMask,
                                                  TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION;
@@ -635,6 +654,14 @@
  * xTaskCreateRestrictedStatic() therefore allows a memory protected task to be
  * created without using any dynamic memory allocation.
  *
+ * The parameter macros used in MemoryRegion_t.ulParameters are port specific.
+ * Some ports, including the Cortex-M3/4 MPU ports, use the portMPU_REGION_*
+ * values shown below.
+ * ARMv8-M MPU ports, such as CM23, CM33, CM52, CM55, CM85 and STAR_MC3, use
+ * the tskMPU_REGION_* values defined in this header; the port translates them
+ * into MPU register settings. Check the selected port's headers before selecting
+ * the region parameter macros.
+ *
  * @param pxTaskDefinition Pointer to a structure that contains a member
  * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API
  * documentation) plus an optional stack buffer and the memory region
@@ -650,7 +677,7 @@
  *
  * Example usage:
  * @code{c}
- * // Create an TaskParameters_t structure that defines the task to be created.
+ * // Create a TaskParameters_t structure that defines the task to be created.
  * // The StaticTask_t variable is only included in the structure when
  * // configSUPPORT_STATIC_ALLOCATION is set to 1.  The PRIVILEGED_DATA macro can
  * // be used to force the variable into the RTOS kernel's privileged data area.
@@ -724,6 +751,14 @@
  * @param[in] pxRegions A pointer to a MemoryRegion_t structure that contains the
  * new memory region definitions.
  *
+ * The parameter macros used in MemoryRegion_t.ulParameters are port specific.
+ * Some ports, including the Cortex-M3/4 MPU ports, use the portMPU_REGION_*
+ * values shown below.
+ * ARMv8-M MPU ports, such as CM23, CM33, CM52, CM55, CM85 and STAR_MC3, use
+ * the tskMPU_REGION_* values defined in this header; the port translates them
+ * into MPU register settings. Check the selected port's headers before selecting
+ * the region parameter macros.
+ *
  * Example usage:
  * @code{c}
  * // Define an array of MemoryRegion_t structures that configures an MPU region
@@ -861,6 +896,43 @@
 /**
  * task. h
  * @code{c}
+ * TickType_t xTaskPeriodicDelay( TickType_t *pxPreviousWakeTime, const TickType_t xTimeIncrement );
+ * @endcode
+ *
+ * INCLUDE_xTaskDelayUntil must be defined as 1 for this function to be available.
+ * See the configuration section for more information.
+ *
+ * Periodic task delay to ensure a constant execution frequency.
+ *
+ * This function is similar to xTaskDelayUntil () with a few important differences:
+ * - pxPreviousWakeTime contains the last past wake time, so it never runs away
+ * - if you suspend the task, when you resume it pxPreviousWakeTime will instantly
+ *   catch up all skipped increments
+ * - it returns the number of increments added to pxPreviosWakeTime
+ *
+ * @param pxPreviousWakeTime Pointer to a variable that holds the time at which the
+ * task was last unblocked.  The variable must be initialised with the current time
+ * prior to its first use.  Following this the variable is automatically updated.
+ *
+ * @param xTimeIncrement The cycle time period.  The task will be unblocked at
+ * time *pxPreviousWakeTime + xTimeIncrement.  Passing the same xTimeIncrement
+ * parameter value will cause the task to execute with a fixed interval.
+ *
+ * @return Number of times xTimeIncrement has been added to pxPreviousWakeTime.
+ * It is 0 on the first call or if not enough ticks have been elapsed since the
+ * last call, 1 in normal circumstances or more than 1 if some period has been
+ * skipped for some reason (e.g. when the caller task is suspended for more than
+ * xTimeIncrement ticks).
+ *
+ * \defgroup xTaskPeriodicDelay xTaskPeriodicDelay
+ * \ingroup TaskCtrl
+ */
+TickType_t xTaskPeriodicDelay( TickType_t * const pxPreviousWakeTime,
+                               const TickType_t xTimeIncrement ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ * @code{c}
  * BaseType_t xTaskDelayUntil( TickType_t *pxPreviousWakeTime, const TickType_t xTimeIncrement );
  * @endcode
  *
@@ -897,7 +969,8 @@
  *
  * @return Value which can be used to check whether the task was actually delayed.
  * Will be pdTRUE if the task way delayed and pdFALSE otherwise.  A task will not
- * be delayed if the next expected wake time is in the past.
+ * be delayed if the next expected wake time is in the past. This prevents periodic
+ * tasks from accumulating delays and allows them to resume their regular timing pattern.
  *
  * Example usage:
  * @code{c}
@@ -1002,7 +1075,7 @@
  *   // it itself.
  *   if( uxTaskPriorityGet( xHandle ) != tskIDLE_PRIORITY )
  *   {
- *       // The task has changed it's priority.
+ *       // The task has changed its priority.
  *   }
  *
  *   // ...
@@ -1045,7 +1118,7 @@
  *
  * @return The base priority of xTask.
  *
- * \defgroup uxTaskPriorityGet uxTaskBasePriorityGet
+ * \defgroup uxTaskBasePriorityGet uxTaskBasePriorityGet
  * \ingroup TaskCtrl
  */
 UBaseType_t uxTaskBasePriorityGet( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
@@ -2084,7 +2157,7 @@
  * configUSE_TRACE_FACILITY must be defined as 1 in FreeRTOSConfig.h for
  * uxTaskGetSystemState() to be available.
  *
- * uxTaskGetSystemState() populates an TaskStatus_t structure for each task in
+ * uxTaskGetSystemState() populates a TaskStatus_t structure for each task in
  * the system.  TaskStatus_t structures contain, among other things, members
  * for the task handle, task name, task priority, task state, and total amount
  * of run time consumed by the task.  See the TaskStatus_t structure
@@ -2181,7 +2254,38 @@
     UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,
                                       const UBaseType_t uxArraySize,
                                       configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION;
-#endif
+
+
+/**
+ * For each task, call pxCallbackFunction with the task's handle and state,
+ * and the provided context.
+ *
+ * NOTE: This function is intended for debugging use only as it suspends
+ * the scheduler for an extended period. The callback runs while the
+ * scheduler is suspended, so it must return quickly and must not perform
+ * blocking operations.
+ *
+ * NOTE: This API is privileged-only (it invokes a user callback from
+ * privileged context).
+ *
+ * @param pxCallbackFunction Callback to invoke once for each task (passing
+ * the task's handle, state, and the pvCallbackContext).
+ *
+ * @param pvCallbackContext Opaque caller-provided context passed through to
+ * each callback invocation.
+ *
+ * @param pulTotalRunTime If configGENERATE_RUN_TIME_STATS is set to 1 in
+ * FreeRTOSConfig.h then *pulTotalRunTime is set to the total run time since
+ * boot. pulTotalRunTime can be set to NULL to omit the total run time
+ * information.
+ *
+ * @return The number tasks provided to the callback.
+ */
+    UBaseType_t uxTaskCallForEachTask( TaskStatusCallbackFunction_t pxCallbackFunction,
+                                       void * pvCallbackContext,
+                                       configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION;
+
+#endif /* if ( configUSE_TRACE_FACILITY == 1 ) */
 
 /**
  * task. h
@@ -2612,9 +2716,8 @@
  * notification value at that index being updated.  ulValue is not used and
  * xTaskNotifyIndexed() always returns pdPASS in this case.
  *
- * pulPreviousNotificationValue -
- * Can be used to pass out the subject task's notification value before any
- * bits are modified by the notify function.
+ * @param pulPreviousNotificationValue Can be used to pass out the subject
+ * task's notification value before any bits are modified by the notify function.
  *
  * @return Dependent on the value of eAction.  See the description of the
  * eAction parameter.
@@ -2759,6 +2862,9 @@
  * updated.  ulValue is not used and xTaskNotify() always returns pdPASS in
  * this case.
  *
+ * @param pulPreviousNotificationValue Can be used to pass out the subject
+ * task's notification value before any bits are modified by the notify function.
+ *
  * @param pxHigherPriorityTaskWoken  xTaskNotifyFromISR() will set
  * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the
  * task to which the notification was sent to leave the Blocked state, and the
@@ -3201,7 +3307,7 @@
 /**
  * task. h
  * @code{c}
- * BaseType_t xTaskNotifyStateClearIndexed( TaskHandle_t xTask, UBaseType_t uxIndexToCLear );
+ * BaseType_t xTaskNotifyStateClearIndexed( TaskHandle_t xTask, UBaseType_t uxIndexToClear );
  *
  * BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask );
  * @endcode
diff --git a/Source/include/timers.h b/Source/include/timers.h
index 2e809c0..7f0c85c 100644
--- a/Source/include/timers.h
+++ b/Source/include/timers.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -667,8 +667,13 @@
  *
  * See the xTimerChangePeriod() API function example usage scenario.
  */
-#define xTimerDelete( xTimer, xTicksToWait ) \
+#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
+    BaseType_t xTimerDelete( TimerHandle_t xTimer,
+                             TickType_t xTicksToWait );
+#else
+    #define xTimerDelete( xTimer, xTicksToWait ) \
     xTimerGenericCommand( ( xTimer ), tmrCOMMAND_DELETE, 0U, NULL, ( xTicksToWait ) )
+#endif
 
 /**
  * BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait );
diff --git a/Source/list.c b/Source/list.c
index b390c5a..c6ef877 100644
--- a/Source/list.c
+++ b/Source/list.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/ARMClang/Use-the-GCC-ports.txt b/Source/portable/ARMClang/Use-the-GCC-ports.txt
new file mode 100644
index 0000000..9dd1bc7
--- /dev/null
+++ b/Source/portable/ARMClang/Use-the-GCC-ports.txt
@@ -0,0 +1,2 @@
+The FreeRTOS GCC port layer also builds and works with the ARMClang compiler.
+To use the ARMClang compiler build the port files from FreeRTOS/Source/portable/GCC.
diff --git a/Source/portable/Common/mpu_wrappers.c b/Source/portable/Common/mpu_wrappers.c
index a26021b..0778977 100644
--- a/Source/portable/Common/mpu_wrappers.c
+++ b/Source/portable/Common/mpu_wrappers.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/Common/mpu_wrappers_v2.c b/Source/portable/Common/mpu_wrappers_v2.c
index ac1159b..b81bf0f 100644
--- a/Source/portable/Common/mpu_wrappers_v2.c
+++ b/Source/portable/Common/mpu_wrappers_v2.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -1059,8 +1059,8 @@
                                                   configRUN_TIME_COUNTER_TYPE * pulTotalRunTime ) /* PRIVILEGED_FUNCTION */
         {
             UBaseType_t uxReturn = 0;
-            UBaseType_t xIsTaskStatusArrayWriteable = pdFALSE;
-            UBaseType_t xIsTotalRunTimeWriteable = pdFALSE;
+            BaseType_t xIsTaskStatusArrayWriteable = pdFALSE;
+            BaseType_t xIsTotalRunTimeWriteable = pdFALSE;
             uint32_t ulArraySize = ( uint32_t ) uxArraySize;
             uint32_t ulTaskStatusSize = ( uint32_t ) sizeof( TaskStatus_t );
 
@@ -3890,6 +3890,40 @@
     #endif /* if ( configUSE_TIMERS == 1 ) */
 /*-----------------------------------------------------------*/
 
+    #if ( configUSE_TIMERS == 1 )
+
+        BaseType_t MPU_xTimerDelete( TimerHandle_t xTimer, TickType_t xTicksToWait ) /* PRIVILEGED_FUNCTION */
+        {
+            BaseType_t xReturn = pdFALSE;
+            TimerHandle_t xInternalTimerHandle = NULL;
+            int32_t lIndex;
+
+            lIndex = ( int32_t ) xTimer;
+
+            if( IS_EXTERNAL_INDEX_VALID( lIndex ) != pdFALSE )
+            {
+                xInternalTimerHandle = MPU_GetTimerHandleAtIndex( CONVERT_TO_INTERNAL_INDEX( lIndex ) );
+
+                if( xInternalTimerHandle != NULL )
+                {
+                    xReturn = xTimerGenericCommandFromTask( xInternalTimerHandle,
+                                                            tmrCOMMAND_DELETE,
+                                                            0U, /* xOptionalValue */
+                                                            NULL, /* pxHigherPriorityTaskWoken */
+                                                            xTicksToWait );
+                    if( xReturn != pdFALSE )
+                    {
+                        MPU_SetIndexFreeInKernelObjectPool( CONVERT_TO_INTERNAL_INDEX( lIndex ) );
+                    }
+                }
+            }
+
+            return xReturn;
+        }
+
+    #endif /* if ( configUSE_TIMERS == 1 ) */
+/*-----------------------------------------------------------*/
+
 /*-----------------------------------------------------------*/
 /*           MPU wrappers for event group APIs.              */
 /*-----------------------------------------------------------*/
@@ -4282,7 +4316,7 @@
     #endif /* #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configUSE_EVENT_GROUPS == 1 ) ) */
 /*-----------------------------------------------------------*/
 
-    #if ( ( configUSE_EVENT_GROUPS == 1 ) && ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
+    #if ( ( configUSE_EVENT_GROUPS == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
 
         BaseType_t MPU_xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
                                                     const EventBits_t uxBitsToClear ) /* PRIVILEGED_FUNCTION */
@@ -4306,10 +4340,10 @@
             return xReturn;
         }
 
-    #endif /* #if ( ( configUSE_EVENT_GROUPS == 1 ) && ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
+    #endif /* #if ( ( configUSE_EVENT_GROUPS == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
 /*-----------------------------------------------------------*/
 
-    #if ( ( configUSE_EVENT_GROUPS == 1 ) && ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
+    #if ( ( configUSE_EVENT_GROUPS == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
 
         BaseType_t MPU_xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
                                                   const EventBits_t uxBitsToSet,
@@ -4334,7 +4368,7 @@
             return xReturn;
         }
 
-    #endif /* #if ( ( configUSE_EVENT_GROUPS == 1 ) && ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
+    #endif /* #if ( ( configUSE_EVENT_GROUPS == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
 /*-----------------------------------------------------------*/
 
     #if ( configUSE_EVENT_GROUPS == 1 )
diff --git a/Source/portable/GCC/ARM_CA9/port.c b/Source/portable/GCC/ARM_CA9/port.c
index cb724d0..5ac0d16 100644
--- a/Source/portable/GCC/ARM_CA9/port.c
+++ b/Source/portable/GCC/ARM_CA9/port.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CA9/portASM.S b/Source/portable/GCC/ARM_CA9/portASM.S
index 61caf27..dfdbad8 100644
--- a/Source/portable/GCC/ARM_CA9/portASM.S
+++ b/Source/portable/GCC/ARM_CA9/portASM.S
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CA9/portmacro.h b/Source/portable/GCC/ARM_CA9/portmacro.h
index 76255db..57ebf9c 100644
--- a/Source/portable/GCC/ARM_CA9/portmacro.h
+++ b/Source/portable/GCC/ARM_CA9/portmacro.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM0/mpu_wrappers_v2_asm.c b/Source/portable/GCC/ARM_CM0/mpu_wrappers_v2_asm.c
index 2a7af2e..6d7194b 100644
--- a/Source/portable/GCC/ARM_CM0/mpu_wrappers_v2_asm.c
+++ b/Source/portable/GCC/ARM_CM0/mpu_wrappers_v2_asm.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM0/port.c b/Source/portable/GCC/ARM_CM0/port.c
index e9ef847..e51ed32 100644
--- a/Source/portable/GCC/ARM_CM0/port.c
+++ b/Source/portable/GCC/ARM_CM0/port.c
@@ -1,6 +1,8 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * Copyright 2025 Arm Limited and/or its affiliates
+ * <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -687,7 +689,7 @@
         }
 
         /* Shift the code by one before returning so it can be written directly
-         * into the the correct bit position of the attribute register. */
+         * into the correct bit position of the attribute register. */
         return( ulReturnValue << 1UL );
     }
 
@@ -915,7 +917,10 @@
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulSystemCallStack;
         uint32_t ulSystemCallLocation, i;
-        const uint32_t ulStackFrameSize = 8;
+        /* Hardware Saved Stack Frame Size upon Exception entry:
+         * Basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+         */
+        const uint32_t ulHardwareSavedExceptionFrameSize = 8;
 
         #if defined( __ARMCC_VERSION )
 
@@ -955,10 +960,10 @@
             pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
 
             /* Make space on the system call stack for the stack frame. */
-            pulSystemCallStack = pulSystemCallStack - ulStackFrameSize;
+            pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulSystemCallStack[ i ] = pulTaskStack[ i ];
             }
@@ -981,7 +986,7 @@
 
             /* Remember the location where we should copy the stack frame when we exit from
              * the system call. */
-            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
+            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
 
             /* Record if the hardware used padding to force the stack pointer
              * to be double word aligned. */
@@ -1036,7 +1041,10 @@
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulTaskStack;
         uint32_t ulSystemCallLocation, i;
-        const uint32_t ulStackFrameSize = 8;
+        /* Hardware Saved Stack Frame Size upon Exception entry:
+         * Basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+         */
+        const uint32_t ulHardwareSavedExceptionFrameSize = 8;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1072,10 +1080,10 @@
             pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
 
             /* Make space on the task stack for the stack frame. */
-            pulTaskStack = pulTaskStack - ulStackFrameSize;
+            pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulTaskStack[ i ] = pulSystemCallStack[ i ];
             }
diff --git a/Source/portable/GCC/ARM_CM0/portasm.c b/Source/portable/GCC/ARM_CM0/portasm.c
index 2280ec8..ec95ddb 100644
--- a/Source/portable/GCC/ARM_CM0/portasm.c
+++ b/Source/portable/GCC/ARM_CM0/portasm.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -111,9 +111,9 @@
             " restore_general_regs_first_task:                \n"
             "    subs r1, #32                                 \n"
             "    ldmia r1!, {r4-r7}                           \n" /* r4-r7 contain half of the hardware saved context. */
-            "    stmia r2!, {r4-r7}                           \n" /* Copy half of the the hardware saved context on the task stack. */
+            "    stmia r2!, {r4-r7}                           \n" /* Copy half of the hardware saved context on the task stack. */
             "    ldmia r1!, {r4-r7}                           \n" /* r4-r7 contain rest half of the hardware saved context. */
-            "    stmia r2!, {r4-r7}                           \n" /* Copy rest half of the the hardware saved context on the task stack. */
+            "    stmia r2!, {r4-r7}                           \n" /* Copy rest half of the hardware saved context on the task stack. */
             "    subs r1, #48                                 \n"
             "    ldmia r1!, {r4-r7}                           \n" /* Restore r8-r11. */
             "    mov r8, r4                                   \n" /* r8 = r4. */
@@ -366,9 +366,9 @@
             " restore_general_regs:                           \n"
             "    subs r1, #32                                 \n"
             "    ldmia r1!, {r4-r7}                           \n" /* r4-r7 contain half of the hardware saved context. */
-            "    stmia r2!, {r4-r7}                           \n" /* Copy half of the the hardware saved context on the task stack. */
+            "    stmia r2!, {r4-r7}                           \n" /* Copy half of the hardware saved context on the task stack. */
             "    ldmia r1!, {r4-r7}                           \n" /* r4-r7 contain rest half of the hardware saved context. */
-            "    stmia r2!, {r4-r7}                           \n" /* Copy rest half of the the hardware saved context on the task stack. */
+            "    stmia r2!, {r4-r7}                           \n" /* Copy rest half of the hardware saved context on the task stack. */
             "    subs r1, #48                                 \n"
             "    ldmia r1!, {r4-r7}                           \n" /* Restore r8-r11. */
             "    mov r8, r4                                   \n" /* r8 = r4. */
diff --git a/Source/portable/GCC/ARM_CM0/portasm.h b/Source/portable/GCC/ARM_CM0/portasm.h
index ce0f3aa..da5c664 100644
--- a/Source/portable/GCC/ARM_CM0/portasm.h
+++ b/Source/portable/GCC/ARM_CM0/portasm.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM0/portmacro.h b/Source/portable/GCC/ARM_CM0/portmacro.h
index 97e8450..2599275 100644
--- a/Source/portable/GCC/ARM_CM0/portmacro.h
+++ b/Source/portable/GCC/ARM_CM0/portmacro.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM23/non_secure/mpu_wrappers_v2_asm.c b/Source/portable/GCC/ARM_CM23/non_secure/mpu_wrappers_v2_asm.c
index a195dbf..a3fc377 100644
--- a/Source/portable/GCC/ARM_CM23/non_secure/mpu_wrappers_v2_asm.c
+++ b/Source/portable/GCC/ARM_CM23/non_secure/mpu_wrappers_v2_asm.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM23/non_secure/port.c b/Source/portable/GCC/ARM_CM23/non_secure/port.c
index f16a343..007150c 100644
--- a/Source/portable/GCC/ARM_CM23/non_secure/port.c
+++ b/Source/portable/GCC/ARM_CM23/non_secure/port.c
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024-2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -145,13 +144,13 @@
 /**
  * @brief Constants required to manipulate the FPU.
  */
-#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 )              /* Coprocessor Access Control Register. */
+#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */
 #define portCPACR_CP10_VALUE    ( 3UL )
 #define portCPACR_CP11_VALUE    portCPACR_CP10_VALUE
 #define portCPACR_CP10_POS      ( 20UL )
 #define portCPACR_CP11_POS      ( 22UL )
 
-#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 )              /* Floating Point Context Control Register. */
+#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
 #define portFPCCR_ASPEN_POS     ( 31UL )
 #define portFPCCR_ASPEN_MASK    ( 1UL << portFPCCR_ASPEN_POS )
 #define portFPCCR_LSPEN_POS     ( 30UL )
@@ -188,8 +187,8 @@
 #define portMPU_MAIR0_REG                       ( *( ( volatile uint32_t * ) 0xe000edc0 ) )
 #define portMPU_MAIR1_REG                       ( *( ( volatile uint32_t * ) 0xe000edc4 ) )
 
-#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
-#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
+#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
+#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
 
 #define portMPU_RBAR_ACCESS_PERMISSIONS_MASK    ( 3UL << 1UL )
 
@@ -230,8 +229,8 @@
 
 #if ( portARMV8M_MINOR_VERSION >= 1 )
 
-/* Enable Privileged eXecute Never MPU attribute for the selected memory
- * region. */
+    /* Enable Privileged eXecute Never MPU attribute for the selected memory
+     * region. */
     #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER    ( 1UL << 4UL )
 #endif /* portARMV8M_MINOR_VERSION >= 1 */
 
@@ -241,9 +240,6 @@
 /* Enable MPU. */
 #define portMPU_ENABLE_BIT                    ( 1UL << 0UL )
 
-/* Expected value of the portMPU_TYPE register. */
-#define portEXPECTED_MPU_TYPE_VALUE           ( configTOTAL_MPU_REGIONS << 8UL )
-
 /* Extract first address of the MPU region as encoded in the
  * RBAR (Region Base Address Register) value. */
 #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@@ -291,37 +287,37 @@
 
 #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         FD
- * 1111 1111  1111 1111  1111 1111  1111 1101
- *
- * Bit[6] - 1 --> The exception was taken from the Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 1 --> The exception was taken to the Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         FD
+     * 1111 1111  1111 1111  1111 1111  1111 1101
+     *
+     * Bit[6] - 1 --> The exception was taken from the Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 1 --> The exception was taken to the Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xfffffffd )
 #else
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         BC
- * 1111 1111  1111 1111  1111 1111  1011 1100
- *
- * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         BC
+     * 1111 1111  1111 1111  1111 1111  1011 1100
+     *
+     * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xffffffbc )
 #endif /* configRUN_FREERTOS_SECURE_ONLY */
 
@@ -401,50 +397,54 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Extract MPU region's access permissions from the Region Base Address
- * Register (RBAR) value.
- *
- * @param ulRBARValue RBAR value for the MPU region.
- *
- * @return uint32_t Access permissions.
- */
+    /**
+     * @brief Extract MPU region's access permissions from the Region Base Address
+     * Register (RBAR) value.
+     *
+     * @param ulRBARValue RBAR value for the MPU region.
+     *
+     * @return uint32_t Access permissions.
+     */
     static uint32_t prvGetRegionAccessPermissions( uint32_t ulRBARValue ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU == 1 && configUSE_MPU_WRAPPERS_V1 == 0 */
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Setup the Memory Protection Unit (MPU).
- */
+    /**
+     * @brief Setup the Memory Protection Unit (MPU).
+     */
     static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU */
 
 #if ( configENABLE_FPU == 1 )
 
-/**
- * @brief Setup the Floating Point Unit (FPU).
- */
+    /**
+     * @brief Setup the Floating Point Unit (FPU).
+     */
     static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_FPU */
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
 
-/**
- * @brief Configures PACBTI features.
- *
- * This function configures the Pointer Authentication, and Branch Target
- * Identification security features as per the user configuration. It returns
- * the value of the special purpose CONTROL register accordingly, and optionally
- * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
- * architecture based) target supports PACBTI security feature.
- *
- * @param xWriteControlRegister Used to control whether the special purpose
- * CONTROL register should be updated or not.
- *
- * @return CONTROL register value according to the configured PACBTI option.
- */
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    /**
+     * @brief Configures PACBTI features.
+     *
+     * This function configures the Pointer Authentication, and Branch Target
+     * Identification security features as per the user configuration. It returns
+     * the value of the special purpose CONTROL register accordingly, and optionally
+     * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
+     * architecture based) target supports PACBTI security feature.
+     *
+     * @param xWriteControlRegister Used to control whether the special purpose
+     * CONTROL register should be updated or not.
+     *
+     * @return CONTROL register value according to the configured PACBTI option.
+     */
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -491,14 +491,14 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the system call stack so that upon returning from
- * SVC, the system call stack is used.
- *
- * @param pulTaskStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- * @param ucSystemCallNumber The system call number of the system call.
- */
+    /**
+     * @brief Sets up the system call stack so that upon returning from
+     * SVC, the system call stack is used.
+     *
+     * @param pulTaskStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     * @param ucSystemCallNumber The system call number of the system call.
+     */
     void vSystemCallEnter( uint32_t * pulTaskStack,
                            uint32_t ulLR,
                            uint8_t ucSystemCallNumber ) PRIVILEGED_FUNCTION;
@@ -507,22 +507,22 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Raise SVC for exiting from a system call.
- */
+    /**
+     * @brief Raise SVC for exiting from a system call.
+     */
     void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the task stack so that upon returning from
- * SVC, the task stack is used again.
- *
- * @param pulSystemCallStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- */
+    /**
+     * @brief Sets up the task stack so that upon returning from
+     * SVC, the task stack is used again.
+     *
+     * @param pulSystemCallStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     */
     void vSystemCallExit( uint32_t * pulSystemCallStack,
                           uint32_t ulLR ) PRIVILEGED_FUNCTION;
 
@@ -530,21 +530,38 @@
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Checks whether or not the calling task is privileged.
- *
- * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
- */
+    /**
+     * @brief Checks whether or not the calling task is privileged.
+     *
+     * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
+     */
     BaseType_t xPortIsTaskPrivileged( void ) PRIVILEGED_FUNCTION;
 
 #endif /* configENABLE_MPU == 1 */
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /**
+     * @brief Platform/Application-defined function that wakes up the secondary cores.
+     *
+     * @return pdTRUE if the secondary cores were successfully woken up.
+     *         pdFALSE otherwise.
+     */
+    extern BaseType_t configWAKE_SECONDARY_CORES( void );
+
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
+
+/**
+ * @brief Configures interrupt priorities.
+ */
+void vPortConfigureInterruptPriorities( void ) PRIVILEGED_FUNCTION;
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief This variable is set to pdTRUE when the scheduler is started.
- */
+    /**
+     * @brief This variable is set to pdTRUE when the scheduler is started.
+     */
     PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
@@ -553,14 +570,22 @@
  * @brief Each task maintains its own interrupt status in the critical nesting
  * variable.
  */
-PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
+#if ( configNUMBER_OF_CORES == 1 )
+    PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0UL;
+#else /* #if ( configNUMBER_OF_CORES == 1 ) */
+    PRIVILEGED_DATA volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ] = { 0 };
+    /* Flags to check if the secondary cores are ready. */
+    PRIVILEGED_DATA volatile uint8_t ucSecondaryCoresReadyFlags[ configNUMBER_OF_CORES - 1 ] = { 0 };
+    /* Flag to indicate that the primary core has completed its initialisation. */
+    PRIVILEGED_DATA volatile uint8_t ucPrimaryCoreInitDoneFlag = 0;
+ #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #if ( configENABLE_TRUSTZONE == 1 )
 
-/**
- * @brief Saved as part of the task context to indicate which context the
- * task is using on the secure side.
- */
+    /**
+     * @brief Saved as part of the task context to indicate which context the
+     * task is using on the secure side.
+     */
     PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
 #endif /* configENABLE_TRUSTZONE */
 
@@ -579,21 +604,21 @@
 
 #if ( configUSE_TICKLESS_IDLE == 1 )
 
-/**
- * @brief The number of SysTick increments that make up one tick period.
- */
+    /**
+     * @brief The number of SysTick increments that make up one tick period.
+     */
     PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
 
-/**
- * @brief The maximum number of tick periods that can be suppressed is
- * limited by the 24 bit resolution of the SysTick timer.
- */
+    /**
+     * @brief The maximum number of tick periods that can be suppressed is
+     * limited by the 24 bit resolution of the SysTick timer.
+     */
     PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
 
-/**
- * @brief Compensate for the CPU cycles that pass while the SysTick is
- * stopped (low power functionality only).
- */
+    /**
+     * @brief Compensate for the CPU cycles that pass while the SysTick is
+     * stopped (low power functionality only).
+     */
     PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0;
 #endif /* configUSE_TICKLESS_IDLE */
 /*-----------------------------------------------------------*/
@@ -856,7 +881,11 @@
      * should instead call vTaskDelete( NULL ). Artificially force an assert()
      * to be triggered if configASSERT() is defined, then stop here so
      * application writers can catch the error. */
-    configASSERT( ulCriticalNesting == ~0UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == ~0UL );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == ~0UL );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
     portDISABLE_INTERRUPTS();
 
     while( ulDummy == 0 )
@@ -925,64 +954,57 @@
         /* The only permitted number of regions are 8 or 16. */
         configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 16 ) );
 
-        /* Ensure that the configTOTAL_MPU_REGIONS is configured correctly. */
-        configASSERT( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE );
+        /* MAIR0 - Index 0. */
+        portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
+        /* MAIR0 - Index 1. */
+        portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
 
-        /* Check that the MPU is present. */
-        if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
-        {
-            /* MAIR0 - Index 0. */
-            portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
-            /* MAIR0 - Index 1. */
-            portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
+        /* Setup privileged flash as Read Only so that privileged tasks can
+         * read it but not modify. */
+        portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup privileged flash as Read Only so that privileged tasks can
-             * read it but not modify. */
-            portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged flash as Read Only by both privileged and
+         * unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged flash as Read Only by both privileged and
-             * unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged syscalls flash as Read Only by both privileged
+         * and unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged syscalls flash as Read Only by both privileged
-             * and unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup RAM containing kernel data for privileged access only. */
+        portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
+                           ( portMPU_REGION_EXECUTE_NEVER );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup RAM containing kernel data for privileged access only. */
-            portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
-                               ( portMPU_REGION_EXECUTE_NEVER );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Enable mem fault. */
+        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
 
-            /* Enable mem fault. */
-            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
-
-            /* Enable MPU with privileged background access i.e. unmapped
-             * regions have privileged access. */
-            portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
-        }
+        /* Enable MPU with privileged background access i.e. unmapped
+         * regions have privileged access. */
+        portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
     }
 
 #endif /* configENABLE_MPU */
@@ -1027,28 +1049,29 @@
 }
 /*-----------------------------------------------------------*/
 
-void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    portDISABLE_INTERRUPTS();
-    ulCriticalNesting++;
-
-    /* Barriers are normally not required but do ensure the code is
-     * completely within the specified behaviour for the architecture. */
-    __asm volatile ( "dsb" ::: "memory" );
-    __asm volatile ( "isb" );
-}
-/*-----------------------------------------------------------*/
-
-void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    configASSERT( ulCriticalNesting );
-    ulCriticalNesting--;
-
-    if( ulCriticalNesting == 0 )
+#if ( configNUMBER_OF_CORES == 1 )
+    void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
     {
-        portENABLE_INTERRUPTS();
+        portDISABLE_INTERRUPTS();
+        ulCriticalNesting++;
+        /* Barriers are normally not required but do ensure the code is
+        * completely within the specified behaviour for the architecture. */
+        __asm volatile ( "dsb" ::: "memory" );
+        __asm volatile ( "isb" );
     }
-}
+    /*-----------------------------------------------------------*/
+
+    void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
+    {
+        configASSERT( ulCriticalNesting );
+        ulCriticalNesting--;
+
+        if( ulCriticalNesting == 0 )
+        {
+            portENABLE_INTERRUPTS();
+        }
+    }
+#endif /* configNUMBER_OF_CORES == 1 */
 /*-----------------------------------------------------------*/
 
 void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
@@ -1056,6 +1079,10 @@
     uint32_t ulPreviousMask;
 
     ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
+    #if ( configNUMBER_OF_CORES > 1 )
+        UBaseType_t uxSavedInterruptStatus = portENTER_CRITICAL_FROM_ISR();
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     traceISR_ENTER();
     {
         /* Increment the RTOS tick. */
@@ -1070,6 +1097,10 @@
             traceISR_EXIT();
         }
     }
+    #if ( configNUMBER_OF_CORES > 1 )
+        portEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
 }
 /*-----------------------------------------------------------*/
@@ -1078,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1090,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1108,38 +1151,42 @@
 
     switch( ucSVCNumber )
     {
-        #if ( configENABLE_TRUSTZONE == 1 )
-            case portSVC_ALLOCATE_SECURE_CONTEXT:
+    #if ( configENABLE_TRUSTZONE == 1 )
+        case portSVC_ALLOCATE_SECURE_CONTEXT:
 
-                /* R0 contains the stack size passed as parameter to the
-                 * vPortAllocateSecureContext function. */
-                ulR0 = pulCallerStackAddress[ 0 ];
+            /* R0 contains the stack size passed as parameter to the
+             * vPortAllocateSecureContext function. */
+            ulR0 = pulCallerStackAddress[ 0 ];
 
-                #if ( configENABLE_MPU == 1 )
-                {
-                    /* Read the CONTROL register value. */
-                    __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
+            #if ( configENABLE_MPU == 1 )
+            {
+                /* Read the CONTROL register value. */
+                __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
 
-                    /* The task that raised the SVC is privileged if Bit[0]
-                     * in the CONTROL register is 0. */
-                    ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
+                /* The task that raised the SVC is privileged if Bit[0]
+                 * in the CONTROL register is 0. */
+                ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
 
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
-                }
-                #else /* if ( configENABLE_MPU == 1 ) */
-                {
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
-                }
-                #endif /* configENABLE_MPU */
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
+            }
+            #else /* if ( configENABLE_MPU == 1 ) */
+            {
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
+            }
+            #endif /* configENABLE_MPU */
 
-                configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
-                SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
-                break;
+            configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
+            SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
+            break;
 
-            case portSVC_FREE_SECURE_CONTEXT:
-
+        case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
                 /* R0 contains TCB being freed and R1 contains the secure
                  * context handle to be freed. */
                 ulR0 = pulCallerStackAddress[ 0 ];
@@ -1147,51 +1194,62 @@
 
                 /* Free the secure context. */
                 SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
-                break;
-        #endif /* configENABLE_TRUSTZONE */
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
+            break;
+    #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
-            #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
-                case portSVC_RAISE_PRIVILEGE:
+    #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
+        case portSVC_RAISE_PRIVILEGE:
 
-                    /* Only raise the privilege, if the svc was raised from any of
-                     * the system calls. */
-                    if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
-                        ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
-                    {
-                        vRaisePrivilege();
-                    }
-                    break;
-            #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
+            /* Only raise the privilege, if the svc was raised from any of
+             * the system calls. */
+            if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
+                ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
+            {
+                vRaisePrivilege();
+            }
+            break;
+    #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
-            #if ( configENABLE_MPU == 1 )
-                case portSVC_YIELD:
-                    vPortYield();
-                    break;
-            #endif /* configENABLE_MPU == 1 */
+    #if ( configENABLE_MPU == 1 )
+        case portSVC_YIELD:
+            vPortYield();
+            break;
+    #endif /* configENABLE_MPU == 1 */
 
         default:
             /* Incorrect SVC call. */
@@ -1210,7 +1268,7 @@
         extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulSystemCallStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1246,12 +1304,16 @@
         {
             pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1261,20 +1323,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the system call stack for the stack frame. */
-            pulSystemCallStack = pulSystemCallStack - ulStackFrameSize;
+            pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulSystemCallStack[ i ] = pulTaskStack[ i ];
             }
@@ -1310,7 +1372,7 @@
 
             /* Remember the location where we should copy the stack frame when we exit from
              * the system call. */
-            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
+            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
 
             /* Record if the hardware used padding to force the stack pointer
              * to be double word aligned. */
@@ -1360,7 +1422,7 @@
         extern TaskHandle_t pxCurrentTCB;
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulTaskStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1392,12 +1454,16 @@
         {
             pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1407,20 +1473,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the task stack for the stack frame. */
-            pulTaskStack = pulTaskStack - ulStackFrameSize;
+            pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulTaskStack[ i ] = pulSystemCallStack[ i ];
             }
@@ -1518,21 +1584,21 @@
         xMPUSettings->ulContext[ ulIndex ] = 0x11111111; /* r11. */
         ulIndex++;
 
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters;            /* r0. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters; /* r0. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x01010101;                           /* r1. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x01010101; /* r1. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x02020202;                           /* r2. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x02020202; /* r2. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x03030303;                           /* r3. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x03030303; /* r3. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x12121212;                           /* r12. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x12121212; /* r12. */
         ulIndex++;
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) portTASK_RETURN_ADDRESS; /* LR. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode;                  /* PC. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode; /* PC. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR;                     /* xPSR. */
+        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR; /* xPSR. */
         ulIndex++;
 
         #if ( configENABLE_TRUSTZONE == 1 )
@@ -1543,14 +1609,18 @@
         #endif /* configENABLE_TRUSTZONE */
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) ( pxTopOfStack - 8 ); /* PSP with the hardware saved stack. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack;         /* PSPLIM. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack; /* PSPLIM. */
         ulIndex++;
 
         #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
         {
             /* Check PACBTI security feature configuration before pushing the
              * CONTROL register's value on task's TCB. */
-            ulControl = prvConfigurePACBTI( pdFALSE );
+            #if ( configNUMBER_OF_CORES == 1 )
+                ulControl = prvConfigurePACBTI( pdFALSE );
+            #else /* configNUMBER_OF_CORES > 1 */
+                ulControl = vConfigurePACBTI( pdFALSE );
+            #endif /* configNUMBER_OF_CORES */
         }
         #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1615,15 +1685,15 @@
          * interrupt. */
         #if ( portPRELOAD_REGISTERS == 0 )
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
-            pxTopOfStack -= 5;                                       /* R12, R3, R2 and R1. */
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
-            pxTopOfStack -= 9;                                       /* R11..R4, EXC_RETURN. */
+            pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
+            pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */
             *pxTopOfStack = portINITIAL_EXC_RETURN;
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
@@ -1637,42 +1707,42 @@
         }
         #else /* portPRELOAD_REGISTERS */
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x12121212UL;            /* R12. */
+            *pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x03030303UL;            /* R3. */
+            *pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x02020202UL;            /* R2. */
+            *pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x01010101UL;            /* R1. */
+            *pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x11111111UL;            /* R11. */
+            *pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x10101010UL;            /* R10. */
+            *pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x09090909UL;            /* R09. */
+            *pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x08080808UL;            /* R08. */
+            *pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x07070707UL;            /* R07. */
+            *pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x06060606UL;            /* R06. */
+            *pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x05050505UL;            /* R05. */
+            *pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x04040404UL;            /* R04. */
+            *pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04. */
             pxTopOfStack--;
-            *pxTopOfStack = portINITIAL_EXC_RETURN;                  /* EXC_RETURN. */
+            *pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxEndOfStack;            /* Slot used to hold this task's PSPLIM value. */
+            *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
 
             #if ( configENABLE_TRUSTZONE == 1 )
             {
@@ -1739,91 +1809,17 @@
     }
     #endif /* configCHECK_HANDLER_INSTALLATION */
 
-    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
-    {
-        volatile uint32_t ulImplementedPrioBits = 0;
-        volatile uint8_t ucMaxPriorityValue;
-
-        /* Determine the maximum priority from which ISR safe FreeRTOS API
-         * functions can be called. ISR safe functions are those that end in
-         * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
-         * ensure interrupt entry is as fast and simple as possible.
-         *
-         * First, determine the number of priority bits available. Write to all
-         * possible bits in the priority setting for SVCall. */
-        portNVIC_SHPR2_REG = 0xFF000000;
-
-        /* Read the value back to see how many bits stuck. */
-        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
-
-        /* Use the same mask on the maximum system call priority. */
-        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
-
-        /* Check that the maximum system call priority is nonzero after
-         * accounting for the number of priority bits supported by the
-         * hardware. A priority of 0 is invalid because setting the BASEPRI
-         * register to 0 unmasks all interrupts, and interrupts with priority 0
-         * cannot be masked using BASEPRI.
-         * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
-        configASSERT( ucMaxSysCallPriority );
-
-        /* Check that the bits not implemented in hardware are zero in
-         * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
-        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
-
-        /* Calculate the maximum acceptable priority group value for the number
-         * of bits read back. */
-        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
-        {
-            ulImplementedPrioBits++;
-            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
-        }
-
-        if( ulImplementedPrioBits == 8 )
-        {
-            /* When the hardware implements 8 priority bits, there is no way for
-             * the software to configure PRIGROUP to not have sub-priorities. As
-             * a result, the least significant bit is always used for sub-priority
-             * and there are 128 preemption priorities and 2 sub-priorities.
-             *
-             * This may cause some confusion in some cases - for example, if
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
-             * priority interrupts will be masked in Critical Sections as those
-             * are at the same preemption priority. This may appear confusing as
-             * 4 is higher (numerically lower) priority than
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
-             * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
-             * to 4, this confusion does not happen and the behaviour remains the same.
-             *
-             * The following assert ensures that the sub-priority bit in the
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
-             * confusion. */
-            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
-            ulMaxPRIGROUPValue = 0;
-        }
-        else
-        {
-            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
-        }
-
-        /* Shift the priority group value back to its position within the AIRCR
-         * register. */
-        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
-        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
-    }
-    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
-
-    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
-     * the highest priority. */
-    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
-    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
-    portNVIC_SHPR2_REG = 0;
+    vPortConfigureInterruptPriorities();
 
     #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
     {
         /* Set the CONTROL register value based on PACBTI security feature
          * configuration before starting the first task. */
-        ( void ) prvConfigurePACBTI( pdTRUE );
+        #if ( configNUMBER_OF_CORES == 1 )
+            ( void ) prvConfigurePACBTI( pdTRUE );
+        #else /* configNUMBER_OF_CORES > 1 */
+            ( void ) vConfigurePACBTI( pdTRUE );
+        #endif /* configNUMBER_OF_CORES */
     }
     #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1834,12 +1830,47 @@
     }
     #endif /* configENABLE_MPU */
 
-    /* Start the timer that generates the tick ISR. Interrupts are disabled
-     * here already. */
-    vPortSetupTimerInterrupt();
+    #if ( configNUMBER_OF_CORES > 1 )
+        /* Start the timer that generates the tick ISR. Interrupts are disabled
+         * here already. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count for all cores. */
+        for ( uint8_t ucCoreID = 0; ucCoreID < configNUMBER_OF_CORES; ucCoreID++ )
+        {
+            ulCriticalNestings[ ucCoreID ] = 0;
+        }
+        /* Signal that primary core has done all the necessary initialisations. */
+        ucPrimaryCoreInitDoneFlag = 1;
+        /* Wake up secondary cores */
+        BaseType_t xWakeResult = configWAKE_SECONDARY_CORES();
+        configASSERT( xWakeResult == pdTRUE );
 
-    /* Initialize the critical nesting count ready for the first task. */
-    ulCriticalNesting = 0;
+        /* Hold the primary core here until all the secondary cores are ready, this would be achieved only when
+         * all elements of ucSecondaryCoresReadyFlags are set.
+         */
+        while( 1 )
+        {
+            BaseType_t xAllCoresReady = pdTRUE;
+            for( uint8_t ucCoreID = 0; ucCoreID < ( configNUMBER_OF_CORES - 1 ); ucCoreID++ )
+            {
+                if( ucSecondaryCoresReadyFlags[ ucCoreID ] != pdTRUE )
+                {
+                    xAllCoresReady = pdFALSE;
+                    break;
+                }
+                }
+
+            if ( xAllCoresReady == pdTRUE )
+            {
+                break;
+            }
+        }
+    #else /* if ( configNUMBER_OF_CORES > 1 ) */
+        /* Start the timer that generates the tick ISR. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count ready for the first task. */
+        ulCriticalNesting = 0;
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
     {
@@ -1856,7 +1887,11 @@
      * functionality by defining configTASK_RETURN_ADDRESS. Call
      * vTaskSwitchContext() so link time optimization does not remove the
      * symbol. */
-    vTaskSwitchContext();
+    #if ( configNUMBER_OF_CORES > 1 )
+        vTaskSwitchContext( portGET_CORE_ID() );
+    #else
+        vTaskSwitchContext();
+    #endif
     prvTaskExitError();
 
     /* Should not get here. */
@@ -1868,7 +1903,11 @@
 {
     /* Not implemented in ports where there is nothing to return to.
      * Artificially force an assert. */
-    configASSERT( ulCriticalNesting == 1000UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == 1000UL );
+    #else /* if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == 1000UL );
+    #endif /* if ( configNUMBER_OF_CORES == 1 ) */
 }
 /*-----------------------------------------------------------*/
 
@@ -2151,6 +2190,90 @@
 #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
 /*-----------------------------------------------------------*/
 
+void vPortConfigureInterruptPriorities( void ) /* PRIVILEGED_FUNCTION */
+{
+    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
+    {
+        volatile uint32_t ulImplementedPrioBits = 0;
+        volatile uint8_t ucMaxPriorityValue;
+
+        /* Determine the maximum priority from which ISR safe FreeRTOS API
+        * functions can be called. ISR safe functions are those that end in
+        * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
+        * ensure interrupt entry is as fast and simple as possible.
+        *
+        * First, determine the number of priority bits available. Write to all
+        * possible bits in the priority setting for SVCall. */
+        portNVIC_SHPR2_REG = 0xFF000000;
+
+        /* Read the value back to see how many bits stuck. */
+        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
+
+        /* Use the same mask on the maximum system call priority. */
+        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
+
+        /* Check that the maximum system call priority is nonzero after
+        * accounting for the number of priority bits supported by the
+        * hardware. A priority of 0 is invalid because setting the BASEPRI
+        * register to 0 unmasks all interrupts, and interrupts with priority 0
+        * cannot be masked using BASEPRI.
+        * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+        configASSERT( ucMaxSysCallPriority );
+
+        /* Check that the bits not implemented in hardware are zero in
+        * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
+        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
+
+        /* Calculate the maximum acceptable priority group value for the number
+        * of bits read back. */
+        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
+        {
+            ulImplementedPrioBits++;
+            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
+        }
+
+        if( ulImplementedPrioBits == 8 )
+        {
+            /* When the hardware implements 8 priority bits, there is no way for
+            * the software to configure PRIGROUP to not have sub-priorities. As
+            * a result, the least significant bit is always used for sub-priority
+            * and there are 128 preemption priorities and 2 sub-priorities.
+            *
+            * This may cause some confusion in some cases - for example, if
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
+            * priority interrupts will be masked in Critical Sections as those
+            * are at the same preemption priority. This may appear confusing as
+            * 4 is higher (numerically lower) priority than
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
+            * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
+            * to 4, this confusion does not happen and the behaviour remains the same.
+            *
+            * The following assert ensures that the sub-priority bit in the
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
+            * confusion. */
+            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
+            ulMaxPRIGROUPValue = 0;
+        }
+        else
+        {
+            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
+        }
+
+        /* Shift the priority group value back to its position within the AIRCR
+        * register. */
+        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
+        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
+    }
+    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
+
+    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
+    * the highest priority. */
+    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
+    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
+    portNVIC_SHPR2_REG = 0;
+}
+/*-----------------------------------------------------------*/
+
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) )
 
     void vPortGrantAccessToKernelObject( TaskHandle_t xInternalTaskHandle,
@@ -2247,36 +2370,214 @@
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
-
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
-    {
-        uint32_t ulControl = 0x0;
-
-        /* Ensure that PACBTI is implemented. */
-        configASSERT( portID_ISAR5_REG != 0x0 );
-
-        /* Enable UsageFault exception. */
-        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
-
-        #if ( configENABLE_PAC == 1 )
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #else /* configNUMBER_OF_CORES > 1 */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #endif /* configNUMBER_OF_CORES */
         {
-            ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
-        }
-        #endif
+            uint32_t ulControl = 0x0;
 
-        #if ( configENABLE_BTI == 1 )
-        {
-            ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
-        }
-        #endif
+            /* Ensure that PACBTI is implemented. */
+            configASSERT( portID_ISAR5_REG != 0x0 );
 
-        if( xWriteControlRegister == pdTRUE )
-        {
-            __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
-        }
+            /* Enable UsageFault exception. */
+            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
 
-        return ulControl;
-    }
+            #if ( configENABLE_PAC == 1 )
+            {
+                ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
+            }
+            #endif
+
+            #if ( configENABLE_BTI == 1 )
+            {
+                ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
+            }
+            #endif
+
+            if( xWriteControlRegister == pdTRUE )
+            {
+                __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
+            }
+
+            return ulControl;
+        }
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 /*-----------------------------------------------------------*/
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /* Which core owns the lock? */
+    PRIVILEGED_DATA volatile uint32_t ulOwnedByCore[ portMAX_CORE_COUNT ];
+    /* Lock count a core owns. */
+    PRIVILEGED_DATA volatile uint32_t ulRecursionCountByLock[ eLockCount ];
+    /* Index 0 is used for ISR lock and Index 1 is used for task lock. */
+    PRIVILEGED_DATA volatile uint32_t ulGateWord[ eLockCount ];
+
+    __attribute__((weak)) void vInterruptCore( uint8_t ucCoreID )
+    {
+        /* Default weak stub - platform specific implementation may override. */
+        ( void ) ucCoreID;
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline void prvSpinUnlock( volatile uint32_t * ulLock )
+    {
+        /* Conservative unlock: preserve original barriers for broad HW/FVP. */
+        __asm volatile (
+            "dmb sy         \n"
+            "mov r1, #0     \n"
+            "str r1, [%0]   \n"
+            "sev            \n"
+            "dsb            \n"
+            "isb            \n"
+            :
+            : "r" ( ulLock )
+            : "memory", "r1"
+        );
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline uint32_t prvSpinTrylock( volatile uint32_t * ulLock )
+    {
+        /*
+         * Conservative ldrex/strex trylock:
+         * - Return 1 immediately if busy, clearing exclusive state (CLREX).
+         * - Retry strex only on spurious failure when observed free.
+         * - DMB on success to preserve expected acquire semantics.
+         */
+        uint32_t ulVal;
+        uint32_t ulStatus;
+
+        __asm volatile (
+            " ldrex %0, [%1]   \n"
+            : "=r" ( ulVal )
+            : "r" ( ulLock )
+            : "memory"
+        );
+
+        if( ulVal != 0U )
+        {
+            __asm volatile ("clrex" ::: "memory");
+            return 1U;
+        }
+
+        __asm volatile (
+            " strex %0, %2, [%1]   \n"
+            : "=&r" ( ulStatus )
+            : "r" ( ulLock ), "r" (1U)
+            : "memory"
+        );
+
+        if( ulStatus != 0U )
+        {
+            return 1U;
+        }
+        __asm volatile ( "dmb" ::: "memory" );
+        return 0U;
+    }
+
+
+/*-----------------------------------------------------------*/
+
+    /* Read 32b value shared between cores. */
+    static inline uint32_t prvGet32( volatile uint32_t * x )
+    {
+        __asm( "dsb" );
+        return *x;
+    }
+
+/*-----------------------------------------------------------*/
+
+    /* Write 32b value shared between cores. */
+    static inline void prvSet32( volatile uint32_t * x,
+                                 uint32_t value )
+    {
+        *x = value;
+        __asm( "dsb" );
+    }
+
+/*-----------------------------------------------------------*/
+
+    void vPortRecursiveLock( uint8_t ucCoreID,
+                             ePortRTOSLock eLockNum,
+                             BaseType_t uxAcquire )
+    {
+        /* Validate the core ID and lock number. */
+        configASSERT( ucCoreID < portMAX_CORE_COUNT );
+        configASSERT( eLockNum < eLockCount );
+
+        uint32_t ulLockBit = 1u << eLockNum;
+
+        /* Lock acquire */
+        if( uxAcquire )
+        {
+            /* Check if spinlock is available. */
+            /* If spinlock is not available check if the core owns the lock. */
+            /* If the core owns the lock wait increment the lock count by the core. */
+            /* If core does not own the lock wait for the spinlock. */
+            if( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+            {
+                /* Check if the core owns the spinlock. */
+                if( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit )
+                {
+                    configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != portUINT32_MAX );
+                    prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) + 1 ) );
+                    return;
+                }
+
+                /* Preload the gate word into the cache. */
+                uint32_t dummy = ulGateWord[ eLockNum ];
+                dummy++;
+
+                while( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+                {
+                    __asm volatile ( "wfe" );
+                }
+            }
+
+            /* Add barrier to ensure lock is taken before we proceed. */
+            __asm volatile( "dmb sy" ::: "memory" );
+
+            /* Assert the lock count is 0 when the spinlock is free and is acquired. */
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) == 0 );
+
+            /* Set lock count as 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], 1 );
+            /* Set ulOwnedByCore. */
+            prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) | ulLockBit ) );
+        }
+        /* Lock release. */
+        else
+        {
+            /* Assert the lock is not free already. */
+            configASSERT( ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit ) != 0 );
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != 0 );
+
+            /* Reduce ulRecursionCountByLock by 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) - 1 ) );
+
+            if( !prvGet32( &ulRecursionCountByLock[ eLockNum ] ) )
+            {
+                prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ~ulLockBit ) );
+                prvSpinUnlock( &ulGateWord[ eLockNum ] );
+                /* Add barrier to ensure lock status is reflected before we proceed. */
+                __asm volatile( "dmb sy" ::: "memory" );
+            }
+        }
+    }
+
+/*-----------------------------------------------------------*/
+
+    uint8_t ucPortGetCoreID( void )
+    {
+        return *(volatile uint8_t *)(configCORE_ID_REGISTER);
+    }
+
+/*-----------------------------------------------------------*/
+
+#endif /* if( configNUMBER_OF_CORES > 1 ) */
diff --git a/Source/portable/GCC/ARM_CM23/non_secure/portasm.c b/Source/portable/GCC/ARM_CM23/non_secure/portasm.c
index bfc061e..24a8ee1 100644
--- a/Source/portable/GCC/ARM_CM23/non_secure/portasm.c
+++ b/Source/portable/GCC/ARM_CM23/non_secure/portasm.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -48,6 +48,12 @@
 #endif
 
 #if ( configENABLE_MPU == 1 )
+    #define SECURE_CONTEXT_OFFSET   -20
+#else
+    #define SECURE_CONTEXT_OFFSET   0
+#endif
+
+#if ( configENABLE_MPU == 1 )
 
     void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
     {
@@ -120,9 +126,9 @@
             " restore_general_regs_first_task:                \n"
             "    subs r2, #32                                 \n"
             "    ldmia r2!, {r4-r7}                           \n" /* r4-r7 contain half of the hardware saved context. */
-            "    stmia r3!, {r4-r7}                           \n" /* Copy half of the the hardware saved context on the task stack. */
+            "    stmia r3!, {r4-r7}                           \n" /* Copy half of the hardware saved context on the task stack. */
             "    ldmia r2!, {r4-r7}                           \n" /* r4-r7 contain rest half of the hardware saved context. */
-            "    stmia r3!, {r4-r7}                           \n" /* Copy rest half of the the hardware saved context on the task stack. */
+            "    stmia r3!, {r4-r7}                           \n" /* Copy rest half of the hardware saved context on the task stack. */
             "    subs r2, #48                                 \n"
             "    ldmia r2!, {r4-r7}                           \n" /* Restore r8-r11. */
             "    mov r8, r4                                   \n" /* r8 = r4. */
@@ -396,9 +402,9 @@
             " restore_general_regs:                           \n"
             "    subs r2, #32                                 \n"
             "    ldmia r2!, {r4-r7}                           \n" /* r4-r7 contain half of the hardware saved context. */
-            "    stmia r3!, {r4-r7}                           \n" /* Copy half of the the hardware saved context on the task stack. */
+            "    stmia r3!, {r4-r7}                           \n" /* Copy half of the hardware saved context on the task stack. */
             "    ldmia r2!, {r4-r7}                           \n" /* r4-r7 contain rest half of the hardware saved context. */
-            "    stmia r3!, {r4-r7}                           \n" /* Copy rest half of the the hardware saved context on the task stack. */
+            "    stmia r3!, {r4-r7}                           \n" /* Copy rest half of the hardware saved context on the task stack. */
             "    subs r2, #48                                 \n"
             "    ldmia r2!, {r4-r7}                           \n" /* Restore r8-r11. */
             "    mov r8, r4                                   \n" /* r8 = r4. */
@@ -590,15 +596,16 @@
     (
         "   .syntax unified                                 \n"
         "                                                   \n"
-        "   ldr r2, [r0]                                    \n" /* The first item in the TCB is the top of the stack. */
-        "   ldr r1, [r2]                                    \n" /* The first item on the stack is the task's xSecureContext. */
+        "   ldr r2, [r0]                                    \n" /* The first item in the TCB is the stored context location. */
+        "   adds r2, r2, %0                                 \n" /* r2 = r2 + SECURE_CONTEXT_OFFSET. */
+        "   ldr r1, [r2]                                    \n" /* Read xSecureContext from the task's context. */
         "   cmp r1, #0                                      \n" /* Raise svc if task's xSecureContext is not NULL. */
         "   bne free_secure_context                         \n" /* Branch if r1 != 0. */
         "   bx lr                                           \n" /* There is no secure context (xSecureContext is NULL). */
         " free_secure_context:                              \n"
-        "   svc %0                                          \n" /* Secure context is freed in the supervisor call. */
+        "   svc %1                                          \n" /* Secure context is freed in the supervisor call. */
         "   bx lr                                           \n" /* Return. */
-        ::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
+        ::"i" ( SECURE_CONTEXT_OFFSET ), "i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
     );
 }
 /*-----------------------------------------------------------*/
diff --git a/Source/portable/GCC/ARM_CM23/non_secure/portasm.h b/Source/portable/GCC/ARM_CM23/non_secure/portasm.h
index 53b4b6e..b4b545f 100644
--- a/Source/portable/GCC/ARM_CM23/non_secure/portasm.h
+++ b/Source/portable/GCC/ARM_CM23/non_secure/portasm.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM23/non_secure/portmacro.h b/Source/portable/GCC/ARM_CM23/non_secure/portmacro.h
index 728e77d..14f73a1 100644
--- a/Source/portable/GCC/ARM_CM23/non_secure/portmacro.h
+++ b/Source/portable/GCC/ARM_CM23/non_secure/portmacro.h
@@ -1,6 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * Copyright 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -52,6 +53,7 @@
 #define portHAS_ARMV8M_MAIN_EXTENSION    0
 #define portARMV8M_MINOR_VERSION         0
 #define portDONT_DISCARD                 __attribute__( ( used ) )
+#define portVALIDATED_FOR_SMP            0
 /*-----------------------------------------------------------*/
 
 /* ARMv8-M common port configurations. */
diff --git a/Source/portable/GCC/ARM_CM23/non_secure/portmacrocommon.h b/Source/portable/GCC/ARM_CM23/non_secure/portmacrocommon.h
index 2dfac6a..c34fdee 100644
--- a/Source/portable/GCC/ARM_CM23/non_secure/portmacrocommon.h
+++ b/Source/portable/GCC/ARM_CM23/non_secure/portmacrocommon.h
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -59,6 +58,19 @@
     #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h.  Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
 #endif /* configENABLE_TRUSTZONE */
 
+#if ( configNUMBER_OF_CORES > 1 )
+    #if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 )
+        #error "Multi-core SMP is currently only validated for Cortex-M33 non-TrustZone non-MPU port."
+    #endif /* if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 ) ) */
+
+    #ifndef configCORE_ID_REGISTER
+        #error "configCORE_ID_REGISTER must be defined to the address of the register used to identify the core executing the code."
+    #endif /* ifndef configCORE_ID_REGISTER */
+
+    #ifndef configWAKE_SECONDARY_CORES
+        #error "configWAKE_SECONDARY_CORES must be defined to a function that wakes the secondary cores."
+    #endif /* ifndef configWAKE_SECONDARY_CORES */
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -428,10 +440,26 @@
 /**
  * @brief Critical section management.
  */
+
+#define portSET_INTERRUPT_MASK()                  ulSetInterruptMask()
+#define portCLEAR_INTERRUPT_MASK( x )             vClearInterruptMask( x )
 #define portSET_INTERRUPT_MASK_FROM_ISR()         ulSetInterruptMask()
 #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x )    vClearInterruptMask( x )
-#define portENTER_CRITICAL()                      vPortEnterCritical()
-#define portEXIT_CRITICAL()                       vPortExitCritical()
+
+#if ( configNUMBER_OF_CORES == 1 )
+    #define portENTER_CRITICAL()                      vPortEnterCritical()
+    #define portEXIT_CRITICAL()                       vPortExitCritical()
+#else /* ( configNUMBER_OF_CORES == 1 ) */
+    extern void vTaskEnterCritical( void );
+    extern void vTaskExitCritical( void );
+    extern UBaseType_t vTaskEnterCriticalFromISR( void );
+    extern void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus );
+
+    #define portENTER_CRITICAL()                      vTaskEnterCritical()
+    #define portEXIT_CRITICAL()                       vTaskExitCritical()
+    #define portENTER_CRITICAL_FROM_ISR()             vTaskEnterCriticalFromISR()
+    #define portEXIT_CRITICAL_FROM_ISR( x )           vTaskExitCriticalFromISR( x )
+#endif /* if ( configNUMBER_OF_CORES != 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -526,7 +554,7 @@
 /* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION
  * based on whether or not Mainline extension is implemented. */
 #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
-    #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 )
+    #if ( ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) && ( configNUMBER_OF_CORES == 1 ) )
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    1
     #else
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    0
@@ -573,6 +601,44 @@
 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
 /*-----------------------------------------------------------*/
 
+
+#if ( configNUMBER_OF_CORES > 1 )
+    typedef enum
+    {
+        eIsrLock = 0,
+        eTaskLock,
+        eLockCount
+    } ePortRTOSLock;
+
+    extern volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ];
+    extern void vPortRecursiveLock( uint8_t ucCoreID,
+                                    ePortRTOSLock eLockNum,
+                                    BaseType_t uxAcquire );
+    extern uint8_t ucPortGetCoreID( void );
+    extern void vInterruptCore( uint8_t ucCoreID );
+
+    #define portGET_CORE_ID()                                  ucPortGetCoreID()
+
+    #define portGET_CRITICAL_NESTING_COUNT( xCoreID )          ( ulCriticalNestings[ ( uint8_t ) xCoreID ] )
+    #define portSET_CRITICAL_NESTING_COUNT( xCoreID, x )       ( ulCriticalNestings[ ( uint8_t ) xCoreID ] = ( x ) )
+    #define portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]++ )
+    #define portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]-- )
+
+    #define portMAX_CORE_COUNT                                 ( configNUMBER_OF_CORES )
+
+    #define portYIELD_CORE( xCoreID )                          vInterruptCore( xCoreID )
+
+    #define portRELEASE_ISR_LOCK( xCoreID )                    vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdFALSE )
+    #define portGET_ISR_LOCK( xCoreID )                        vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdTRUE )
+
+    #define portRELEASE_TASK_LOCK( xCoreID )                   vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdFALSE )
+    #define portGET_TASK_LOCK( xCoreID )                       vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdTRUE )
+
+    #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* ( configENABLE_PAC == 1 || configENABLE_BTI == 1 ) */
+#endif
+
 /* *INDENT-OFF* */
 #ifdef __cplusplus
     }
diff --git a/Source/portable/GCC/ARM_CM23/secure/secure_context.c b/Source/portable/GCC/ARM_CM23/secure/secure_context.c
index 62bcfa1..2dae022 100644
--- a/Source/portable/GCC/ARM_CM23/secure/secure_context.c
+++ b/Source/portable/GCC/ARM_CM23/secure/secure_context.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -213,8 +213,19 @@
         /* Were we able to get a free context? */
         if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS )
         {
-            /* Allocate the stack space. */
-            pucStackMemory = pvPortMalloc( ulSecureStackSize + securecontextSTACK_SEAL_SIZE );
+            /* Allocate the stack space if possible. */
+            if( ( ulSecureStackSize < securecontextSTACK_SEAL_SIZE ) ||
+                ( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) )
+            {
+                /* Reject stacks that are too small (the CONTROL word would be
+                 * written before the allocation, corrupting the secure heap)
+                 * and sizes that would overflow when the seal size is added. */
+                pucStackMemory = NULL;
+            }
+            else
+            {
+                pucStackMemory = pvPortMalloc( ulSecureStackSize + securecontextSTACK_SEAL_SIZE );
+            }
 
             if( pucStackMemory != NULL )
             {
@@ -279,9 +290,12 @@
                                                               void * pvTaskHandle )
 {
     uint32_t ulIPSR, ulSecureContextIndex;
+    uint8_t * pucStackLimit;
 
-    /* Read the Interrupt Program Status Register (IPSR) value. */
+    /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
+     * Register (PSPLIM) value. */
     secureportREAD_IPSR( ulIPSR );
+    secureportREAD_PSPLIM( pucStackLimit );
 
     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
      * when the processor is running in the Thread Mode. */
@@ -293,8 +307,14 @@
             ulSecureContextIndex = xSecureContextHandle - 1UL;
 
             /* Ensure that the secure context being deleted is associated with
-             * the task. */
-            if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
+             * the task and is NOT the currently-loaded context. Freeing a
+             * context whose stack is currently loaded in PSPLIM would leave the
+             * running task referencing freed secure memory (use-after-free).
+             * pvTaskHandle is supplied by the non-secure side and is untrusted,
+             * so it is used only as an additional ownership match, not as
+             * authority. */
+            if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) &&
+                ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) )
             {
                 /* Free the stack space. */
                 vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
@@ -342,7 +362,7 @@
 
         secureportREAD_PSPLIM( pucStackLimit );
 
-        /* Ensure that task's context is loaded and the task is saving it's own
+        /* Ensure that task's context is loaded and the task is saving its own
          * context. */
         if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) &&
             ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) )
diff --git a/Source/portable/GCC/ARM_CM23/secure/secure_context.h b/Source/portable/GCC/ARM_CM23/secure/secure_context.h
index 8b93857..51dd823 100644
--- a/Source/portable/GCC/ARM_CM23/secure/secure_context.h
+++ b/Source/portable/GCC/ARM_CM23/secure/secure_context.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM23/secure/secure_context_port.c b/Source/portable/GCC/ARM_CM23/secure/secure_context_port.c
index d10c7f3..d041d00 100644
--- a/Source/portable/GCC/ARM_CM23/secure/secure_context_port.c
+++ b/Source/portable/GCC/ARM_CM23/secure/secure_context_port.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM23/secure/secure_heap.c b/Source/portable/GCC/ARM_CM23/secure/secure_heap.c
index b0e83b4..58226bf 100644
--- a/Source/portable/GCC/ARM_CM23/secure/secure_heap.c
+++ b/Source/portable/GCC/ARM_CM23/secure/secure_heap.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM23/secure/secure_heap.h b/Source/portable/GCC/ARM_CM23/secure/secure_heap.h
index 61a96da..906fa24 100644
--- a/Source/portable/GCC/ARM_CM23/secure/secure_heap.h
+++ b/Source/portable/GCC/ARM_CM23/secure/secure_heap.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM23/secure/secure_init.c b/Source/portable/GCC/ARM_CM23/secure/secure_init.c
index f7f7e67..6996692 100644
--- a/Source/portable/GCC/ARM_CM23/secure/secure_init.c
+++ b/Source/portable/GCC/ARM_CM23/secure/secure_init.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM23/secure/secure_init.h b/Source/portable/GCC/ARM_CM23/secure/secure_init.h
index 46ffbd9..4e7bd40 100644
--- a/Source/portable/GCC/ARM_CM23/secure/secure_init.h
+++ b/Source/portable/GCC/ARM_CM23/secure/secure_init.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM23/secure/secure_port_macros.h b/Source/portable/GCC/ARM_CM23/secure/secure_port_macros.h
index 34494e1..72774eb 100644
--- a/Source/portable/GCC/ARM_CM23/secure/secure_port_macros.h
+++ b/Source/portable/GCC/ARM_CM23/secure/secure_port_macros.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM23_NTZ/non_secure/mpu_wrappers_v2_asm.c b/Source/portable/GCC/ARM_CM23_NTZ/non_secure/mpu_wrappers_v2_asm.c
index a195dbf..a3fc377 100644
--- a/Source/portable/GCC/ARM_CM23_NTZ/non_secure/mpu_wrappers_v2_asm.c
+++ b/Source/portable/GCC/ARM_CM23_NTZ/non_secure/mpu_wrappers_v2_asm.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM23_NTZ/non_secure/port.c b/Source/portable/GCC/ARM_CM23_NTZ/non_secure/port.c
index f16a343..007150c 100644
--- a/Source/portable/GCC/ARM_CM23_NTZ/non_secure/port.c
+++ b/Source/portable/GCC/ARM_CM23_NTZ/non_secure/port.c
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024-2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -145,13 +144,13 @@
 /**
  * @brief Constants required to manipulate the FPU.
  */
-#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 )              /* Coprocessor Access Control Register. */
+#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */
 #define portCPACR_CP10_VALUE    ( 3UL )
 #define portCPACR_CP11_VALUE    portCPACR_CP10_VALUE
 #define portCPACR_CP10_POS      ( 20UL )
 #define portCPACR_CP11_POS      ( 22UL )
 
-#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 )              /* Floating Point Context Control Register. */
+#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
 #define portFPCCR_ASPEN_POS     ( 31UL )
 #define portFPCCR_ASPEN_MASK    ( 1UL << portFPCCR_ASPEN_POS )
 #define portFPCCR_LSPEN_POS     ( 30UL )
@@ -188,8 +187,8 @@
 #define portMPU_MAIR0_REG                       ( *( ( volatile uint32_t * ) 0xe000edc0 ) )
 #define portMPU_MAIR1_REG                       ( *( ( volatile uint32_t * ) 0xe000edc4 ) )
 
-#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
-#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
+#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
+#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
 
 #define portMPU_RBAR_ACCESS_PERMISSIONS_MASK    ( 3UL << 1UL )
 
@@ -230,8 +229,8 @@
 
 #if ( portARMV8M_MINOR_VERSION >= 1 )
 
-/* Enable Privileged eXecute Never MPU attribute for the selected memory
- * region. */
+    /* Enable Privileged eXecute Never MPU attribute for the selected memory
+     * region. */
     #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER    ( 1UL << 4UL )
 #endif /* portARMV8M_MINOR_VERSION >= 1 */
 
@@ -241,9 +240,6 @@
 /* Enable MPU. */
 #define portMPU_ENABLE_BIT                    ( 1UL << 0UL )
 
-/* Expected value of the portMPU_TYPE register. */
-#define portEXPECTED_MPU_TYPE_VALUE           ( configTOTAL_MPU_REGIONS << 8UL )
-
 /* Extract first address of the MPU region as encoded in the
  * RBAR (Region Base Address Register) value. */
 #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@@ -291,37 +287,37 @@
 
 #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         FD
- * 1111 1111  1111 1111  1111 1111  1111 1101
- *
- * Bit[6] - 1 --> The exception was taken from the Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 1 --> The exception was taken to the Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         FD
+     * 1111 1111  1111 1111  1111 1111  1111 1101
+     *
+     * Bit[6] - 1 --> The exception was taken from the Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 1 --> The exception was taken to the Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xfffffffd )
 #else
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         BC
- * 1111 1111  1111 1111  1111 1111  1011 1100
- *
- * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         BC
+     * 1111 1111  1111 1111  1111 1111  1011 1100
+     *
+     * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xffffffbc )
 #endif /* configRUN_FREERTOS_SECURE_ONLY */
 
@@ -401,50 +397,54 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Extract MPU region's access permissions from the Region Base Address
- * Register (RBAR) value.
- *
- * @param ulRBARValue RBAR value for the MPU region.
- *
- * @return uint32_t Access permissions.
- */
+    /**
+     * @brief Extract MPU region's access permissions from the Region Base Address
+     * Register (RBAR) value.
+     *
+     * @param ulRBARValue RBAR value for the MPU region.
+     *
+     * @return uint32_t Access permissions.
+     */
     static uint32_t prvGetRegionAccessPermissions( uint32_t ulRBARValue ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU == 1 && configUSE_MPU_WRAPPERS_V1 == 0 */
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Setup the Memory Protection Unit (MPU).
- */
+    /**
+     * @brief Setup the Memory Protection Unit (MPU).
+     */
     static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU */
 
 #if ( configENABLE_FPU == 1 )
 
-/**
- * @brief Setup the Floating Point Unit (FPU).
- */
+    /**
+     * @brief Setup the Floating Point Unit (FPU).
+     */
     static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_FPU */
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
 
-/**
- * @brief Configures PACBTI features.
- *
- * This function configures the Pointer Authentication, and Branch Target
- * Identification security features as per the user configuration. It returns
- * the value of the special purpose CONTROL register accordingly, and optionally
- * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
- * architecture based) target supports PACBTI security feature.
- *
- * @param xWriteControlRegister Used to control whether the special purpose
- * CONTROL register should be updated or not.
- *
- * @return CONTROL register value according to the configured PACBTI option.
- */
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    /**
+     * @brief Configures PACBTI features.
+     *
+     * This function configures the Pointer Authentication, and Branch Target
+     * Identification security features as per the user configuration. It returns
+     * the value of the special purpose CONTROL register accordingly, and optionally
+     * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
+     * architecture based) target supports PACBTI security feature.
+     *
+     * @param xWriteControlRegister Used to control whether the special purpose
+     * CONTROL register should be updated or not.
+     *
+     * @return CONTROL register value according to the configured PACBTI option.
+     */
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -491,14 +491,14 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the system call stack so that upon returning from
- * SVC, the system call stack is used.
- *
- * @param pulTaskStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- * @param ucSystemCallNumber The system call number of the system call.
- */
+    /**
+     * @brief Sets up the system call stack so that upon returning from
+     * SVC, the system call stack is used.
+     *
+     * @param pulTaskStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     * @param ucSystemCallNumber The system call number of the system call.
+     */
     void vSystemCallEnter( uint32_t * pulTaskStack,
                            uint32_t ulLR,
                            uint8_t ucSystemCallNumber ) PRIVILEGED_FUNCTION;
@@ -507,22 +507,22 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Raise SVC for exiting from a system call.
- */
+    /**
+     * @brief Raise SVC for exiting from a system call.
+     */
     void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the task stack so that upon returning from
- * SVC, the task stack is used again.
- *
- * @param pulSystemCallStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- */
+    /**
+     * @brief Sets up the task stack so that upon returning from
+     * SVC, the task stack is used again.
+     *
+     * @param pulSystemCallStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     */
     void vSystemCallExit( uint32_t * pulSystemCallStack,
                           uint32_t ulLR ) PRIVILEGED_FUNCTION;
 
@@ -530,21 +530,38 @@
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Checks whether or not the calling task is privileged.
- *
- * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
- */
+    /**
+     * @brief Checks whether or not the calling task is privileged.
+     *
+     * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
+     */
     BaseType_t xPortIsTaskPrivileged( void ) PRIVILEGED_FUNCTION;
 
 #endif /* configENABLE_MPU == 1 */
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /**
+     * @brief Platform/Application-defined function that wakes up the secondary cores.
+     *
+     * @return pdTRUE if the secondary cores were successfully woken up.
+     *         pdFALSE otherwise.
+     */
+    extern BaseType_t configWAKE_SECONDARY_CORES( void );
+
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
+
+/**
+ * @brief Configures interrupt priorities.
+ */
+void vPortConfigureInterruptPriorities( void ) PRIVILEGED_FUNCTION;
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief This variable is set to pdTRUE when the scheduler is started.
- */
+    /**
+     * @brief This variable is set to pdTRUE when the scheduler is started.
+     */
     PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
@@ -553,14 +570,22 @@
  * @brief Each task maintains its own interrupt status in the critical nesting
  * variable.
  */
-PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
+#if ( configNUMBER_OF_CORES == 1 )
+    PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0UL;
+#else /* #if ( configNUMBER_OF_CORES == 1 ) */
+    PRIVILEGED_DATA volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ] = { 0 };
+    /* Flags to check if the secondary cores are ready. */
+    PRIVILEGED_DATA volatile uint8_t ucSecondaryCoresReadyFlags[ configNUMBER_OF_CORES - 1 ] = { 0 };
+    /* Flag to indicate that the primary core has completed its initialisation. */
+    PRIVILEGED_DATA volatile uint8_t ucPrimaryCoreInitDoneFlag = 0;
+ #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #if ( configENABLE_TRUSTZONE == 1 )
 
-/**
- * @brief Saved as part of the task context to indicate which context the
- * task is using on the secure side.
- */
+    /**
+     * @brief Saved as part of the task context to indicate which context the
+     * task is using on the secure side.
+     */
     PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
 #endif /* configENABLE_TRUSTZONE */
 
@@ -579,21 +604,21 @@
 
 #if ( configUSE_TICKLESS_IDLE == 1 )
 
-/**
- * @brief The number of SysTick increments that make up one tick period.
- */
+    /**
+     * @brief The number of SysTick increments that make up one tick period.
+     */
     PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
 
-/**
- * @brief The maximum number of tick periods that can be suppressed is
- * limited by the 24 bit resolution of the SysTick timer.
- */
+    /**
+     * @brief The maximum number of tick periods that can be suppressed is
+     * limited by the 24 bit resolution of the SysTick timer.
+     */
     PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
 
-/**
- * @brief Compensate for the CPU cycles that pass while the SysTick is
- * stopped (low power functionality only).
- */
+    /**
+     * @brief Compensate for the CPU cycles that pass while the SysTick is
+     * stopped (low power functionality only).
+     */
     PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0;
 #endif /* configUSE_TICKLESS_IDLE */
 /*-----------------------------------------------------------*/
@@ -856,7 +881,11 @@
      * should instead call vTaskDelete( NULL ). Artificially force an assert()
      * to be triggered if configASSERT() is defined, then stop here so
      * application writers can catch the error. */
-    configASSERT( ulCriticalNesting == ~0UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == ~0UL );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == ~0UL );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
     portDISABLE_INTERRUPTS();
 
     while( ulDummy == 0 )
@@ -925,64 +954,57 @@
         /* The only permitted number of regions are 8 or 16. */
         configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 16 ) );
 
-        /* Ensure that the configTOTAL_MPU_REGIONS is configured correctly. */
-        configASSERT( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE );
+        /* MAIR0 - Index 0. */
+        portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
+        /* MAIR0 - Index 1. */
+        portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
 
-        /* Check that the MPU is present. */
-        if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
-        {
-            /* MAIR0 - Index 0. */
-            portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
-            /* MAIR0 - Index 1. */
-            portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
+        /* Setup privileged flash as Read Only so that privileged tasks can
+         * read it but not modify. */
+        portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup privileged flash as Read Only so that privileged tasks can
-             * read it but not modify. */
-            portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged flash as Read Only by both privileged and
+         * unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged flash as Read Only by both privileged and
-             * unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged syscalls flash as Read Only by both privileged
+         * and unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged syscalls flash as Read Only by both privileged
-             * and unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup RAM containing kernel data for privileged access only. */
+        portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
+                           ( portMPU_REGION_EXECUTE_NEVER );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup RAM containing kernel data for privileged access only. */
-            portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
-                               ( portMPU_REGION_EXECUTE_NEVER );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Enable mem fault. */
+        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
 
-            /* Enable mem fault. */
-            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
-
-            /* Enable MPU with privileged background access i.e. unmapped
-             * regions have privileged access. */
-            portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
-        }
+        /* Enable MPU with privileged background access i.e. unmapped
+         * regions have privileged access. */
+        portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
     }
 
 #endif /* configENABLE_MPU */
@@ -1027,28 +1049,29 @@
 }
 /*-----------------------------------------------------------*/
 
-void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    portDISABLE_INTERRUPTS();
-    ulCriticalNesting++;
-
-    /* Barriers are normally not required but do ensure the code is
-     * completely within the specified behaviour for the architecture. */
-    __asm volatile ( "dsb" ::: "memory" );
-    __asm volatile ( "isb" );
-}
-/*-----------------------------------------------------------*/
-
-void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    configASSERT( ulCriticalNesting );
-    ulCriticalNesting--;
-
-    if( ulCriticalNesting == 0 )
+#if ( configNUMBER_OF_CORES == 1 )
+    void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
     {
-        portENABLE_INTERRUPTS();
+        portDISABLE_INTERRUPTS();
+        ulCriticalNesting++;
+        /* Barriers are normally not required but do ensure the code is
+        * completely within the specified behaviour for the architecture. */
+        __asm volatile ( "dsb" ::: "memory" );
+        __asm volatile ( "isb" );
     }
-}
+    /*-----------------------------------------------------------*/
+
+    void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
+    {
+        configASSERT( ulCriticalNesting );
+        ulCriticalNesting--;
+
+        if( ulCriticalNesting == 0 )
+        {
+            portENABLE_INTERRUPTS();
+        }
+    }
+#endif /* configNUMBER_OF_CORES == 1 */
 /*-----------------------------------------------------------*/
 
 void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
@@ -1056,6 +1079,10 @@
     uint32_t ulPreviousMask;
 
     ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
+    #if ( configNUMBER_OF_CORES > 1 )
+        UBaseType_t uxSavedInterruptStatus = portENTER_CRITICAL_FROM_ISR();
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     traceISR_ENTER();
     {
         /* Increment the RTOS tick. */
@@ -1070,6 +1097,10 @@
             traceISR_EXIT();
         }
     }
+    #if ( configNUMBER_OF_CORES > 1 )
+        portEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
 }
 /*-----------------------------------------------------------*/
@@ -1078,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1090,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1108,38 +1151,42 @@
 
     switch( ucSVCNumber )
     {
-        #if ( configENABLE_TRUSTZONE == 1 )
-            case portSVC_ALLOCATE_SECURE_CONTEXT:
+    #if ( configENABLE_TRUSTZONE == 1 )
+        case portSVC_ALLOCATE_SECURE_CONTEXT:
 
-                /* R0 contains the stack size passed as parameter to the
-                 * vPortAllocateSecureContext function. */
-                ulR0 = pulCallerStackAddress[ 0 ];
+            /* R0 contains the stack size passed as parameter to the
+             * vPortAllocateSecureContext function. */
+            ulR0 = pulCallerStackAddress[ 0 ];
 
-                #if ( configENABLE_MPU == 1 )
-                {
-                    /* Read the CONTROL register value. */
-                    __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
+            #if ( configENABLE_MPU == 1 )
+            {
+                /* Read the CONTROL register value. */
+                __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
 
-                    /* The task that raised the SVC is privileged if Bit[0]
-                     * in the CONTROL register is 0. */
-                    ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
+                /* The task that raised the SVC is privileged if Bit[0]
+                 * in the CONTROL register is 0. */
+                ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
 
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
-                }
-                #else /* if ( configENABLE_MPU == 1 ) */
-                {
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
-                }
-                #endif /* configENABLE_MPU */
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
+            }
+            #else /* if ( configENABLE_MPU == 1 ) */
+            {
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
+            }
+            #endif /* configENABLE_MPU */
 
-                configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
-                SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
-                break;
+            configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
+            SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
+            break;
 
-            case portSVC_FREE_SECURE_CONTEXT:
-
+        case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
                 /* R0 contains TCB being freed and R1 contains the secure
                  * context handle to be freed. */
                 ulR0 = pulCallerStackAddress[ 0 ];
@@ -1147,51 +1194,62 @@
 
                 /* Free the secure context. */
                 SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
-                break;
-        #endif /* configENABLE_TRUSTZONE */
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
+            break;
+    #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
-            #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
-                case portSVC_RAISE_PRIVILEGE:
+    #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
+        case portSVC_RAISE_PRIVILEGE:
 
-                    /* Only raise the privilege, if the svc was raised from any of
-                     * the system calls. */
-                    if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
-                        ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
-                    {
-                        vRaisePrivilege();
-                    }
-                    break;
-            #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
+            /* Only raise the privilege, if the svc was raised from any of
+             * the system calls. */
+            if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
+                ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
+            {
+                vRaisePrivilege();
+            }
+            break;
+    #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
-            #if ( configENABLE_MPU == 1 )
-                case portSVC_YIELD:
-                    vPortYield();
-                    break;
-            #endif /* configENABLE_MPU == 1 */
+    #if ( configENABLE_MPU == 1 )
+        case portSVC_YIELD:
+            vPortYield();
+            break;
+    #endif /* configENABLE_MPU == 1 */
 
         default:
             /* Incorrect SVC call. */
@@ -1210,7 +1268,7 @@
         extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulSystemCallStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1246,12 +1304,16 @@
         {
             pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1261,20 +1323,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the system call stack for the stack frame. */
-            pulSystemCallStack = pulSystemCallStack - ulStackFrameSize;
+            pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulSystemCallStack[ i ] = pulTaskStack[ i ];
             }
@@ -1310,7 +1372,7 @@
 
             /* Remember the location where we should copy the stack frame when we exit from
              * the system call. */
-            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
+            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
 
             /* Record if the hardware used padding to force the stack pointer
              * to be double word aligned. */
@@ -1360,7 +1422,7 @@
         extern TaskHandle_t pxCurrentTCB;
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulTaskStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1392,12 +1454,16 @@
         {
             pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1407,20 +1473,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the task stack for the stack frame. */
-            pulTaskStack = pulTaskStack - ulStackFrameSize;
+            pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulTaskStack[ i ] = pulSystemCallStack[ i ];
             }
@@ -1518,21 +1584,21 @@
         xMPUSettings->ulContext[ ulIndex ] = 0x11111111; /* r11. */
         ulIndex++;
 
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters;            /* r0. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters; /* r0. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x01010101;                           /* r1. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x01010101; /* r1. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x02020202;                           /* r2. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x02020202; /* r2. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x03030303;                           /* r3. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x03030303; /* r3. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x12121212;                           /* r12. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x12121212; /* r12. */
         ulIndex++;
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) portTASK_RETURN_ADDRESS; /* LR. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode;                  /* PC. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode; /* PC. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR;                     /* xPSR. */
+        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR; /* xPSR. */
         ulIndex++;
 
         #if ( configENABLE_TRUSTZONE == 1 )
@@ -1543,14 +1609,18 @@
         #endif /* configENABLE_TRUSTZONE */
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) ( pxTopOfStack - 8 ); /* PSP with the hardware saved stack. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack;         /* PSPLIM. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack; /* PSPLIM. */
         ulIndex++;
 
         #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
         {
             /* Check PACBTI security feature configuration before pushing the
              * CONTROL register's value on task's TCB. */
-            ulControl = prvConfigurePACBTI( pdFALSE );
+            #if ( configNUMBER_OF_CORES == 1 )
+                ulControl = prvConfigurePACBTI( pdFALSE );
+            #else /* configNUMBER_OF_CORES > 1 */
+                ulControl = vConfigurePACBTI( pdFALSE );
+            #endif /* configNUMBER_OF_CORES */
         }
         #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1615,15 +1685,15 @@
          * interrupt. */
         #if ( portPRELOAD_REGISTERS == 0 )
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
-            pxTopOfStack -= 5;                                       /* R12, R3, R2 and R1. */
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
-            pxTopOfStack -= 9;                                       /* R11..R4, EXC_RETURN. */
+            pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
+            pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */
             *pxTopOfStack = portINITIAL_EXC_RETURN;
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
@@ -1637,42 +1707,42 @@
         }
         #else /* portPRELOAD_REGISTERS */
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x12121212UL;            /* R12. */
+            *pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x03030303UL;            /* R3. */
+            *pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x02020202UL;            /* R2. */
+            *pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x01010101UL;            /* R1. */
+            *pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x11111111UL;            /* R11. */
+            *pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x10101010UL;            /* R10. */
+            *pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x09090909UL;            /* R09. */
+            *pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x08080808UL;            /* R08. */
+            *pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x07070707UL;            /* R07. */
+            *pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x06060606UL;            /* R06. */
+            *pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x05050505UL;            /* R05. */
+            *pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x04040404UL;            /* R04. */
+            *pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04. */
             pxTopOfStack--;
-            *pxTopOfStack = portINITIAL_EXC_RETURN;                  /* EXC_RETURN. */
+            *pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxEndOfStack;            /* Slot used to hold this task's PSPLIM value. */
+            *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
 
             #if ( configENABLE_TRUSTZONE == 1 )
             {
@@ -1739,91 +1809,17 @@
     }
     #endif /* configCHECK_HANDLER_INSTALLATION */
 
-    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
-    {
-        volatile uint32_t ulImplementedPrioBits = 0;
-        volatile uint8_t ucMaxPriorityValue;
-
-        /* Determine the maximum priority from which ISR safe FreeRTOS API
-         * functions can be called. ISR safe functions are those that end in
-         * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
-         * ensure interrupt entry is as fast and simple as possible.
-         *
-         * First, determine the number of priority bits available. Write to all
-         * possible bits in the priority setting for SVCall. */
-        portNVIC_SHPR2_REG = 0xFF000000;
-
-        /* Read the value back to see how many bits stuck. */
-        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
-
-        /* Use the same mask on the maximum system call priority. */
-        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
-
-        /* Check that the maximum system call priority is nonzero after
-         * accounting for the number of priority bits supported by the
-         * hardware. A priority of 0 is invalid because setting the BASEPRI
-         * register to 0 unmasks all interrupts, and interrupts with priority 0
-         * cannot be masked using BASEPRI.
-         * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
-        configASSERT( ucMaxSysCallPriority );
-
-        /* Check that the bits not implemented in hardware are zero in
-         * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
-        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
-
-        /* Calculate the maximum acceptable priority group value for the number
-         * of bits read back. */
-        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
-        {
-            ulImplementedPrioBits++;
-            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
-        }
-
-        if( ulImplementedPrioBits == 8 )
-        {
-            /* When the hardware implements 8 priority bits, there is no way for
-             * the software to configure PRIGROUP to not have sub-priorities. As
-             * a result, the least significant bit is always used for sub-priority
-             * and there are 128 preemption priorities and 2 sub-priorities.
-             *
-             * This may cause some confusion in some cases - for example, if
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
-             * priority interrupts will be masked in Critical Sections as those
-             * are at the same preemption priority. This may appear confusing as
-             * 4 is higher (numerically lower) priority than
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
-             * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
-             * to 4, this confusion does not happen and the behaviour remains the same.
-             *
-             * The following assert ensures that the sub-priority bit in the
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
-             * confusion. */
-            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
-            ulMaxPRIGROUPValue = 0;
-        }
-        else
-        {
-            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
-        }
-
-        /* Shift the priority group value back to its position within the AIRCR
-         * register. */
-        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
-        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
-    }
-    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
-
-    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
-     * the highest priority. */
-    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
-    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
-    portNVIC_SHPR2_REG = 0;
+    vPortConfigureInterruptPriorities();
 
     #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
     {
         /* Set the CONTROL register value based on PACBTI security feature
          * configuration before starting the first task. */
-        ( void ) prvConfigurePACBTI( pdTRUE );
+        #if ( configNUMBER_OF_CORES == 1 )
+            ( void ) prvConfigurePACBTI( pdTRUE );
+        #else /* configNUMBER_OF_CORES > 1 */
+            ( void ) vConfigurePACBTI( pdTRUE );
+        #endif /* configNUMBER_OF_CORES */
     }
     #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1834,12 +1830,47 @@
     }
     #endif /* configENABLE_MPU */
 
-    /* Start the timer that generates the tick ISR. Interrupts are disabled
-     * here already. */
-    vPortSetupTimerInterrupt();
+    #if ( configNUMBER_OF_CORES > 1 )
+        /* Start the timer that generates the tick ISR. Interrupts are disabled
+         * here already. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count for all cores. */
+        for ( uint8_t ucCoreID = 0; ucCoreID < configNUMBER_OF_CORES; ucCoreID++ )
+        {
+            ulCriticalNestings[ ucCoreID ] = 0;
+        }
+        /* Signal that primary core has done all the necessary initialisations. */
+        ucPrimaryCoreInitDoneFlag = 1;
+        /* Wake up secondary cores */
+        BaseType_t xWakeResult = configWAKE_SECONDARY_CORES();
+        configASSERT( xWakeResult == pdTRUE );
 
-    /* Initialize the critical nesting count ready for the first task. */
-    ulCriticalNesting = 0;
+        /* Hold the primary core here until all the secondary cores are ready, this would be achieved only when
+         * all elements of ucSecondaryCoresReadyFlags are set.
+         */
+        while( 1 )
+        {
+            BaseType_t xAllCoresReady = pdTRUE;
+            for( uint8_t ucCoreID = 0; ucCoreID < ( configNUMBER_OF_CORES - 1 ); ucCoreID++ )
+            {
+                if( ucSecondaryCoresReadyFlags[ ucCoreID ] != pdTRUE )
+                {
+                    xAllCoresReady = pdFALSE;
+                    break;
+                }
+                }
+
+            if ( xAllCoresReady == pdTRUE )
+            {
+                break;
+            }
+        }
+    #else /* if ( configNUMBER_OF_CORES > 1 ) */
+        /* Start the timer that generates the tick ISR. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count ready for the first task. */
+        ulCriticalNesting = 0;
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
     {
@@ -1856,7 +1887,11 @@
      * functionality by defining configTASK_RETURN_ADDRESS. Call
      * vTaskSwitchContext() so link time optimization does not remove the
      * symbol. */
-    vTaskSwitchContext();
+    #if ( configNUMBER_OF_CORES > 1 )
+        vTaskSwitchContext( portGET_CORE_ID() );
+    #else
+        vTaskSwitchContext();
+    #endif
     prvTaskExitError();
 
     /* Should not get here. */
@@ -1868,7 +1903,11 @@
 {
     /* Not implemented in ports where there is nothing to return to.
      * Artificially force an assert. */
-    configASSERT( ulCriticalNesting == 1000UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == 1000UL );
+    #else /* if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == 1000UL );
+    #endif /* if ( configNUMBER_OF_CORES == 1 ) */
 }
 /*-----------------------------------------------------------*/
 
@@ -2151,6 +2190,90 @@
 #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
 /*-----------------------------------------------------------*/
 
+void vPortConfigureInterruptPriorities( void ) /* PRIVILEGED_FUNCTION */
+{
+    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
+    {
+        volatile uint32_t ulImplementedPrioBits = 0;
+        volatile uint8_t ucMaxPriorityValue;
+
+        /* Determine the maximum priority from which ISR safe FreeRTOS API
+        * functions can be called. ISR safe functions are those that end in
+        * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
+        * ensure interrupt entry is as fast and simple as possible.
+        *
+        * First, determine the number of priority bits available. Write to all
+        * possible bits in the priority setting for SVCall. */
+        portNVIC_SHPR2_REG = 0xFF000000;
+
+        /* Read the value back to see how many bits stuck. */
+        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
+
+        /* Use the same mask on the maximum system call priority. */
+        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
+
+        /* Check that the maximum system call priority is nonzero after
+        * accounting for the number of priority bits supported by the
+        * hardware. A priority of 0 is invalid because setting the BASEPRI
+        * register to 0 unmasks all interrupts, and interrupts with priority 0
+        * cannot be masked using BASEPRI.
+        * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+        configASSERT( ucMaxSysCallPriority );
+
+        /* Check that the bits not implemented in hardware are zero in
+        * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
+        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
+
+        /* Calculate the maximum acceptable priority group value for the number
+        * of bits read back. */
+        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
+        {
+            ulImplementedPrioBits++;
+            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
+        }
+
+        if( ulImplementedPrioBits == 8 )
+        {
+            /* When the hardware implements 8 priority bits, there is no way for
+            * the software to configure PRIGROUP to not have sub-priorities. As
+            * a result, the least significant bit is always used for sub-priority
+            * and there are 128 preemption priorities and 2 sub-priorities.
+            *
+            * This may cause some confusion in some cases - for example, if
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
+            * priority interrupts will be masked in Critical Sections as those
+            * are at the same preemption priority. This may appear confusing as
+            * 4 is higher (numerically lower) priority than
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
+            * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
+            * to 4, this confusion does not happen and the behaviour remains the same.
+            *
+            * The following assert ensures that the sub-priority bit in the
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
+            * confusion. */
+            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
+            ulMaxPRIGROUPValue = 0;
+        }
+        else
+        {
+            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
+        }
+
+        /* Shift the priority group value back to its position within the AIRCR
+        * register. */
+        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
+        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
+    }
+    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
+
+    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
+    * the highest priority. */
+    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
+    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
+    portNVIC_SHPR2_REG = 0;
+}
+/*-----------------------------------------------------------*/
+
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) )
 
     void vPortGrantAccessToKernelObject( TaskHandle_t xInternalTaskHandle,
@@ -2247,36 +2370,214 @@
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
-
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
-    {
-        uint32_t ulControl = 0x0;
-
-        /* Ensure that PACBTI is implemented. */
-        configASSERT( portID_ISAR5_REG != 0x0 );
-
-        /* Enable UsageFault exception. */
-        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
-
-        #if ( configENABLE_PAC == 1 )
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #else /* configNUMBER_OF_CORES > 1 */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #endif /* configNUMBER_OF_CORES */
         {
-            ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
-        }
-        #endif
+            uint32_t ulControl = 0x0;
 
-        #if ( configENABLE_BTI == 1 )
-        {
-            ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
-        }
-        #endif
+            /* Ensure that PACBTI is implemented. */
+            configASSERT( portID_ISAR5_REG != 0x0 );
 
-        if( xWriteControlRegister == pdTRUE )
-        {
-            __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
-        }
+            /* Enable UsageFault exception. */
+            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
 
-        return ulControl;
-    }
+            #if ( configENABLE_PAC == 1 )
+            {
+                ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
+            }
+            #endif
+
+            #if ( configENABLE_BTI == 1 )
+            {
+                ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
+            }
+            #endif
+
+            if( xWriteControlRegister == pdTRUE )
+            {
+                __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
+            }
+
+            return ulControl;
+        }
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 /*-----------------------------------------------------------*/
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /* Which core owns the lock? */
+    PRIVILEGED_DATA volatile uint32_t ulOwnedByCore[ portMAX_CORE_COUNT ];
+    /* Lock count a core owns. */
+    PRIVILEGED_DATA volatile uint32_t ulRecursionCountByLock[ eLockCount ];
+    /* Index 0 is used for ISR lock and Index 1 is used for task lock. */
+    PRIVILEGED_DATA volatile uint32_t ulGateWord[ eLockCount ];
+
+    __attribute__((weak)) void vInterruptCore( uint8_t ucCoreID )
+    {
+        /* Default weak stub - platform specific implementation may override. */
+        ( void ) ucCoreID;
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline void prvSpinUnlock( volatile uint32_t * ulLock )
+    {
+        /* Conservative unlock: preserve original barriers for broad HW/FVP. */
+        __asm volatile (
+            "dmb sy         \n"
+            "mov r1, #0     \n"
+            "str r1, [%0]   \n"
+            "sev            \n"
+            "dsb            \n"
+            "isb            \n"
+            :
+            : "r" ( ulLock )
+            : "memory", "r1"
+        );
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline uint32_t prvSpinTrylock( volatile uint32_t * ulLock )
+    {
+        /*
+         * Conservative ldrex/strex trylock:
+         * - Return 1 immediately if busy, clearing exclusive state (CLREX).
+         * - Retry strex only on spurious failure when observed free.
+         * - DMB on success to preserve expected acquire semantics.
+         */
+        uint32_t ulVal;
+        uint32_t ulStatus;
+
+        __asm volatile (
+            " ldrex %0, [%1]   \n"
+            : "=r" ( ulVal )
+            : "r" ( ulLock )
+            : "memory"
+        );
+
+        if( ulVal != 0U )
+        {
+            __asm volatile ("clrex" ::: "memory");
+            return 1U;
+        }
+
+        __asm volatile (
+            " strex %0, %2, [%1]   \n"
+            : "=&r" ( ulStatus )
+            : "r" ( ulLock ), "r" (1U)
+            : "memory"
+        );
+
+        if( ulStatus != 0U )
+        {
+            return 1U;
+        }
+        __asm volatile ( "dmb" ::: "memory" );
+        return 0U;
+    }
+
+
+/*-----------------------------------------------------------*/
+
+    /* Read 32b value shared between cores. */
+    static inline uint32_t prvGet32( volatile uint32_t * x )
+    {
+        __asm( "dsb" );
+        return *x;
+    }
+
+/*-----------------------------------------------------------*/
+
+    /* Write 32b value shared between cores. */
+    static inline void prvSet32( volatile uint32_t * x,
+                                 uint32_t value )
+    {
+        *x = value;
+        __asm( "dsb" );
+    }
+
+/*-----------------------------------------------------------*/
+
+    void vPortRecursiveLock( uint8_t ucCoreID,
+                             ePortRTOSLock eLockNum,
+                             BaseType_t uxAcquire )
+    {
+        /* Validate the core ID and lock number. */
+        configASSERT( ucCoreID < portMAX_CORE_COUNT );
+        configASSERT( eLockNum < eLockCount );
+
+        uint32_t ulLockBit = 1u << eLockNum;
+
+        /* Lock acquire */
+        if( uxAcquire )
+        {
+            /* Check if spinlock is available. */
+            /* If spinlock is not available check if the core owns the lock. */
+            /* If the core owns the lock wait increment the lock count by the core. */
+            /* If core does not own the lock wait for the spinlock. */
+            if( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+            {
+                /* Check if the core owns the spinlock. */
+                if( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit )
+                {
+                    configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != portUINT32_MAX );
+                    prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) + 1 ) );
+                    return;
+                }
+
+                /* Preload the gate word into the cache. */
+                uint32_t dummy = ulGateWord[ eLockNum ];
+                dummy++;
+
+                while( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+                {
+                    __asm volatile ( "wfe" );
+                }
+            }
+
+            /* Add barrier to ensure lock is taken before we proceed. */
+            __asm volatile( "dmb sy" ::: "memory" );
+
+            /* Assert the lock count is 0 when the spinlock is free and is acquired. */
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) == 0 );
+
+            /* Set lock count as 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], 1 );
+            /* Set ulOwnedByCore. */
+            prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) | ulLockBit ) );
+        }
+        /* Lock release. */
+        else
+        {
+            /* Assert the lock is not free already. */
+            configASSERT( ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit ) != 0 );
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != 0 );
+
+            /* Reduce ulRecursionCountByLock by 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) - 1 ) );
+
+            if( !prvGet32( &ulRecursionCountByLock[ eLockNum ] ) )
+            {
+                prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ~ulLockBit ) );
+                prvSpinUnlock( &ulGateWord[ eLockNum ] );
+                /* Add barrier to ensure lock status is reflected before we proceed. */
+                __asm volatile( "dmb sy" ::: "memory" );
+            }
+        }
+    }
+
+/*-----------------------------------------------------------*/
+
+    uint8_t ucPortGetCoreID( void )
+    {
+        return *(volatile uint8_t *)(configCORE_ID_REGISTER);
+    }
+
+/*-----------------------------------------------------------*/
+
+#endif /* if( configNUMBER_OF_CORES > 1 ) */
diff --git a/Source/portable/GCC/ARM_CM23_NTZ/non_secure/portasm.c b/Source/portable/GCC/ARM_CM23_NTZ/non_secure/portasm.c
index 3bf4e27..8f2a11c 100644
--- a/Source/portable/GCC/ARM_CM23_NTZ/non_secure/portasm.c
+++ b/Source/portable/GCC/ARM_CM23_NTZ/non_secure/portasm.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -121,9 +121,9 @@
             " restore_general_regs_first_task:                \n"
             "    subs r1, #32                                 \n"
             "    ldmia r1!, {r4-r7}                           \n" /* r4-r7 contain half of the hardware saved context. */
-            "    stmia r2!, {r4-r7}                           \n" /* Copy half of the the hardware saved context on the task stack. */
+            "    stmia r2!, {r4-r7}                           \n" /* Copy half of the hardware saved context on the task stack. */
             "    ldmia r1!, {r4-r7}                           \n" /* r4-r7 contain rest half of the hardware saved context. */
-            "    stmia r2!, {r4-r7}                           \n" /* Copy rest half of the the hardware saved context on the task stack. */
+            "    stmia r2!, {r4-r7}                           \n" /* Copy rest half of the hardware saved context on the task stack. */
             "    subs r1, #48                                 \n"
             "    ldmia r1!, {r4-r7}                           \n" /* Restore r8-r11. */
             "    mov r8, r4                                   \n" /* r8 = r4. */
@@ -375,9 +375,9 @@
             " restore_general_regs:                           \n"
             "    subs r1, #32                                 \n"
             "    ldmia r1!, {r4-r7}                           \n" /* r4-r7 contain half of the hardware saved context. */
-            "    stmia r2!, {r4-r7}                           \n" /* Copy half of the the hardware saved context on the task stack. */
+            "    stmia r2!, {r4-r7}                           \n" /* Copy half of the hardware saved context on the task stack. */
             "    ldmia r1!, {r4-r7}                           \n" /* r4-r7 contain rest half of the hardware saved context. */
-            "    stmia r2!, {r4-r7}                           \n" /* Copy rest half of the the hardware saved context on the task stack. */
+            "    stmia r2!, {r4-r7}                           \n" /* Copy rest half of the hardware saved context on the task stack. */
             "    subs r1, #48                                 \n"
             "    ldmia r1!, {r4-r7}                           \n" /* Restore r8-r11. */
             "    mov r8, r4                                   \n" /* r8 = r4. */
diff --git a/Source/portable/GCC/ARM_CM23_NTZ/non_secure/portasm.h b/Source/portable/GCC/ARM_CM23_NTZ/non_secure/portasm.h
index 53b4b6e..b4b545f 100644
--- a/Source/portable/GCC/ARM_CM23_NTZ/non_secure/portasm.h
+++ b/Source/portable/GCC/ARM_CM23_NTZ/non_secure/portasm.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM23_NTZ/non_secure/portmacro.h b/Source/portable/GCC/ARM_CM23_NTZ/non_secure/portmacro.h
index 728e77d..14f73a1 100644
--- a/Source/portable/GCC/ARM_CM23_NTZ/non_secure/portmacro.h
+++ b/Source/portable/GCC/ARM_CM23_NTZ/non_secure/portmacro.h
@@ -1,6 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * Copyright 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -52,6 +53,7 @@
 #define portHAS_ARMV8M_MAIN_EXTENSION    0
 #define portARMV8M_MINOR_VERSION         0
 #define portDONT_DISCARD                 __attribute__( ( used ) )
+#define portVALIDATED_FOR_SMP            0
 /*-----------------------------------------------------------*/
 
 /* ARMv8-M common port configurations. */
diff --git a/Source/portable/GCC/ARM_CM23_NTZ/non_secure/portmacrocommon.h b/Source/portable/GCC/ARM_CM23_NTZ/non_secure/portmacrocommon.h
index 2dfac6a..c34fdee 100644
--- a/Source/portable/GCC/ARM_CM23_NTZ/non_secure/portmacrocommon.h
+++ b/Source/portable/GCC/ARM_CM23_NTZ/non_secure/portmacrocommon.h
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -59,6 +58,19 @@
     #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h.  Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
 #endif /* configENABLE_TRUSTZONE */
 
+#if ( configNUMBER_OF_CORES > 1 )
+    #if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 )
+        #error "Multi-core SMP is currently only validated for Cortex-M33 non-TrustZone non-MPU port."
+    #endif /* if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 ) ) */
+
+    #ifndef configCORE_ID_REGISTER
+        #error "configCORE_ID_REGISTER must be defined to the address of the register used to identify the core executing the code."
+    #endif /* ifndef configCORE_ID_REGISTER */
+
+    #ifndef configWAKE_SECONDARY_CORES
+        #error "configWAKE_SECONDARY_CORES must be defined to a function that wakes the secondary cores."
+    #endif /* ifndef configWAKE_SECONDARY_CORES */
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -428,10 +440,26 @@
 /**
  * @brief Critical section management.
  */
+
+#define portSET_INTERRUPT_MASK()                  ulSetInterruptMask()
+#define portCLEAR_INTERRUPT_MASK( x )             vClearInterruptMask( x )
 #define portSET_INTERRUPT_MASK_FROM_ISR()         ulSetInterruptMask()
 #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x )    vClearInterruptMask( x )
-#define portENTER_CRITICAL()                      vPortEnterCritical()
-#define portEXIT_CRITICAL()                       vPortExitCritical()
+
+#if ( configNUMBER_OF_CORES == 1 )
+    #define portENTER_CRITICAL()                      vPortEnterCritical()
+    #define portEXIT_CRITICAL()                       vPortExitCritical()
+#else /* ( configNUMBER_OF_CORES == 1 ) */
+    extern void vTaskEnterCritical( void );
+    extern void vTaskExitCritical( void );
+    extern UBaseType_t vTaskEnterCriticalFromISR( void );
+    extern void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus );
+
+    #define portENTER_CRITICAL()                      vTaskEnterCritical()
+    #define portEXIT_CRITICAL()                       vTaskExitCritical()
+    #define portENTER_CRITICAL_FROM_ISR()             vTaskEnterCriticalFromISR()
+    #define portEXIT_CRITICAL_FROM_ISR( x )           vTaskExitCriticalFromISR( x )
+#endif /* if ( configNUMBER_OF_CORES != 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -526,7 +554,7 @@
 /* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION
  * based on whether or not Mainline extension is implemented. */
 #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
-    #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 )
+    #if ( ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) && ( configNUMBER_OF_CORES == 1 ) )
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    1
     #else
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    0
@@ -573,6 +601,44 @@
 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
 /*-----------------------------------------------------------*/
 
+
+#if ( configNUMBER_OF_CORES > 1 )
+    typedef enum
+    {
+        eIsrLock = 0,
+        eTaskLock,
+        eLockCount
+    } ePortRTOSLock;
+
+    extern volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ];
+    extern void vPortRecursiveLock( uint8_t ucCoreID,
+                                    ePortRTOSLock eLockNum,
+                                    BaseType_t uxAcquire );
+    extern uint8_t ucPortGetCoreID( void );
+    extern void vInterruptCore( uint8_t ucCoreID );
+
+    #define portGET_CORE_ID()                                  ucPortGetCoreID()
+
+    #define portGET_CRITICAL_NESTING_COUNT( xCoreID )          ( ulCriticalNestings[ ( uint8_t ) xCoreID ] )
+    #define portSET_CRITICAL_NESTING_COUNT( xCoreID, x )       ( ulCriticalNestings[ ( uint8_t ) xCoreID ] = ( x ) )
+    #define portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]++ )
+    #define portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]-- )
+
+    #define portMAX_CORE_COUNT                                 ( configNUMBER_OF_CORES )
+
+    #define portYIELD_CORE( xCoreID )                          vInterruptCore( xCoreID )
+
+    #define portRELEASE_ISR_LOCK( xCoreID )                    vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdFALSE )
+    #define portGET_ISR_LOCK( xCoreID )                        vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdTRUE )
+
+    #define portRELEASE_TASK_LOCK( xCoreID )                   vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdFALSE )
+    #define portGET_TASK_LOCK( xCoreID )                       vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdTRUE )
+
+    #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* ( configENABLE_PAC == 1 || configENABLE_BTI == 1 ) */
+#endif
+
 /* *INDENT-OFF* */
 #ifdef __cplusplus
     }
diff --git a/Source/portable/GCC/ARM_CM3/port.c b/Source/portable/GCC/ARM_CM3/port.c
index fb32128..54d5567 100644
--- a/Source/portable/GCC/ARM_CM3/port.c
+++ b/Source/portable/GCC/ARM_CM3/port.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM3/portmacro.h b/Source/portable/GCC/ARM_CM3/portmacro.h
index 1d0d009..d9a19e4 100644
--- a/Source/portable/GCC/ARM_CM3/portmacro.h
+++ b/Source/portable/GCC/ARM_CM3/portmacro.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM33/non_secure/mpu_wrappers_v2_asm.c b/Source/portable/GCC/ARM_CM33/non_secure/mpu_wrappers_v2_asm.c
index 9c3e8c7..6dd2be8 100644
--- a/Source/portable/GCC/ARM_CM33/non_secure/mpu_wrappers_v2_asm.c
+++ b/Source/portable/GCC/ARM_CM33/non_secure/mpu_wrappers_v2_asm.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM33/non_secure/port.c b/Source/portable/GCC/ARM_CM33/non_secure/port.c
index f16a343..007150c 100644
--- a/Source/portable/GCC/ARM_CM33/non_secure/port.c
+++ b/Source/portable/GCC/ARM_CM33/non_secure/port.c
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024-2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -145,13 +144,13 @@
 /**
  * @brief Constants required to manipulate the FPU.
  */
-#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 )              /* Coprocessor Access Control Register. */
+#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */
 #define portCPACR_CP10_VALUE    ( 3UL )
 #define portCPACR_CP11_VALUE    portCPACR_CP10_VALUE
 #define portCPACR_CP10_POS      ( 20UL )
 #define portCPACR_CP11_POS      ( 22UL )
 
-#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 )              /* Floating Point Context Control Register. */
+#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
 #define portFPCCR_ASPEN_POS     ( 31UL )
 #define portFPCCR_ASPEN_MASK    ( 1UL << portFPCCR_ASPEN_POS )
 #define portFPCCR_LSPEN_POS     ( 30UL )
@@ -188,8 +187,8 @@
 #define portMPU_MAIR0_REG                       ( *( ( volatile uint32_t * ) 0xe000edc0 ) )
 #define portMPU_MAIR1_REG                       ( *( ( volatile uint32_t * ) 0xe000edc4 ) )
 
-#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
-#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
+#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
+#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
 
 #define portMPU_RBAR_ACCESS_PERMISSIONS_MASK    ( 3UL << 1UL )
 
@@ -230,8 +229,8 @@
 
 #if ( portARMV8M_MINOR_VERSION >= 1 )
 
-/* Enable Privileged eXecute Never MPU attribute for the selected memory
- * region. */
+    /* Enable Privileged eXecute Never MPU attribute for the selected memory
+     * region. */
     #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER    ( 1UL << 4UL )
 #endif /* portARMV8M_MINOR_VERSION >= 1 */
 
@@ -241,9 +240,6 @@
 /* Enable MPU. */
 #define portMPU_ENABLE_BIT                    ( 1UL << 0UL )
 
-/* Expected value of the portMPU_TYPE register. */
-#define portEXPECTED_MPU_TYPE_VALUE           ( configTOTAL_MPU_REGIONS << 8UL )
-
 /* Extract first address of the MPU region as encoded in the
  * RBAR (Region Base Address Register) value. */
 #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@@ -291,37 +287,37 @@
 
 #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         FD
- * 1111 1111  1111 1111  1111 1111  1111 1101
- *
- * Bit[6] - 1 --> The exception was taken from the Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 1 --> The exception was taken to the Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         FD
+     * 1111 1111  1111 1111  1111 1111  1111 1101
+     *
+     * Bit[6] - 1 --> The exception was taken from the Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 1 --> The exception was taken to the Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xfffffffd )
 #else
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         BC
- * 1111 1111  1111 1111  1111 1111  1011 1100
- *
- * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         BC
+     * 1111 1111  1111 1111  1111 1111  1011 1100
+     *
+     * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xffffffbc )
 #endif /* configRUN_FREERTOS_SECURE_ONLY */
 
@@ -401,50 +397,54 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Extract MPU region's access permissions from the Region Base Address
- * Register (RBAR) value.
- *
- * @param ulRBARValue RBAR value for the MPU region.
- *
- * @return uint32_t Access permissions.
- */
+    /**
+     * @brief Extract MPU region's access permissions from the Region Base Address
+     * Register (RBAR) value.
+     *
+     * @param ulRBARValue RBAR value for the MPU region.
+     *
+     * @return uint32_t Access permissions.
+     */
     static uint32_t prvGetRegionAccessPermissions( uint32_t ulRBARValue ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU == 1 && configUSE_MPU_WRAPPERS_V1 == 0 */
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Setup the Memory Protection Unit (MPU).
- */
+    /**
+     * @brief Setup the Memory Protection Unit (MPU).
+     */
     static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU */
 
 #if ( configENABLE_FPU == 1 )
 
-/**
- * @brief Setup the Floating Point Unit (FPU).
- */
+    /**
+     * @brief Setup the Floating Point Unit (FPU).
+     */
     static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_FPU */
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
 
-/**
- * @brief Configures PACBTI features.
- *
- * This function configures the Pointer Authentication, and Branch Target
- * Identification security features as per the user configuration. It returns
- * the value of the special purpose CONTROL register accordingly, and optionally
- * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
- * architecture based) target supports PACBTI security feature.
- *
- * @param xWriteControlRegister Used to control whether the special purpose
- * CONTROL register should be updated or not.
- *
- * @return CONTROL register value according to the configured PACBTI option.
- */
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    /**
+     * @brief Configures PACBTI features.
+     *
+     * This function configures the Pointer Authentication, and Branch Target
+     * Identification security features as per the user configuration. It returns
+     * the value of the special purpose CONTROL register accordingly, and optionally
+     * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
+     * architecture based) target supports PACBTI security feature.
+     *
+     * @param xWriteControlRegister Used to control whether the special purpose
+     * CONTROL register should be updated or not.
+     *
+     * @return CONTROL register value according to the configured PACBTI option.
+     */
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -491,14 +491,14 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the system call stack so that upon returning from
- * SVC, the system call stack is used.
- *
- * @param pulTaskStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- * @param ucSystemCallNumber The system call number of the system call.
- */
+    /**
+     * @brief Sets up the system call stack so that upon returning from
+     * SVC, the system call stack is used.
+     *
+     * @param pulTaskStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     * @param ucSystemCallNumber The system call number of the system call.
+     */
     void vSystemCallEnter( uint32_t * pulTaskStack,
                            uint32_t ulLR,
                            uint8_t ucSystemCallNumber ) PRIVILEGED_FUNCTION;
@@ -507,22 +507,22 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Raise SVC for exiting from a system call.
- */
+    /**
+     * @brief Raise SVC for exiting from a system call.
+     */
     void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the task stack so that upon returning from
- * SVC, the task stack is used again.
- *
- * @param pulSystemCallStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- */
+    /**
+     * @brief Sets up the task stack so that upon returning from
+     * SVC, the task stack is used again.
+     *
+     * @param pulSystemCallStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     */
     void vSystemCallExit( uint32_t * pulSystemCallStack,
                           uint32_t ulLR ) PRIVILEGED_FUNCTION;
 
@@ -530,21 +530,38 @@
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Checks whether or not the calling task is privileged.
- *
- * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
- */
+    /**
+     * @brief Checks whether or not the calling task is privileged.
+     *
+     * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
+     */
     BaseType_t xPortIsTaskPrivileged( void ) PRIVILEGED_FUNCTION;
 
 #endif /* configENABLE_MPU == 1 */
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /**
+     * @brief Platform/Application-defined function that wakes up the secondary cores.
+     *
+     * @return pdTRUE if the secondary cores were successfully woken up.
+     *         pdFALSE otherwise.
+     */
+    extern BaseType_t configWAKE_SECONDARY_CORES( void );
+
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
+
+/**
+ * @brief Configures interrupt priorities.
+ */
+void vPortConfigureInterruptPriorities( void ) PRIVILEGED_FUNCTION;
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief This variable is set to pdTRUE when the scheduler is started.
- */
+    /**
+     * @brief This variable is set to pdTRUE when the scheduler is started.
+     */
     PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
@@ -553,14 +570,22 @@
  * @brief Each task maintains its own interrupt status in the critical nesting
  * variable.
  */
-PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
+#if ( configNUMBER_OF_CORES == 1 )
+    PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0UL;
+#else /* #if ( configNUMBER_OF_CORES == 1 ) */
+    PRIVILEGED_DATA volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ] = { 0 };
+    /* Flags to check if the secondary cores are ready. */
+    PRIVILEGED_DATA volatile uint8_t ucSecondaryCoresReadyFlags[ configNUMBER_OF_CORES - 1 ] = { 0 };
+    /* Flag to indicate that the primary core has completed its initialisation. */
+    PRIVILEGED_DATA volatile uint8_t ucPrimaryCoreInitDoneFlag = 0;
+ #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #if ( configENABLE_TRUSTZONE == 1 )
 
-/**
- * @brief Saved as part of the task context to indicate which context the
- * task is using on the secure side.
- */
+    /**
+     * @brief Saved as part of the task context to indicate which context the
+     * task is using on the secure side.
+     */
     PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
 #endif /* configENABLE_TRUSTZONE */
 
@@ -579,21 +604,21 @@
 
 #if ( configUSE_TICKLESS_IDLE == 1 )
 
-/**
- * @brief The number of SysTick increments that make up one tick period.
- */
+    /**
+     * @brief The number of SysTick increments that make up one tick period.
+     */
     PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
 
-/**
- * @brief The maximum number of tick periods that can be suppressed is
- * limited by the 24 bit resolution of the SysTick timer.
- */
+    /**
+     * @brief The maximum number of tick periods that can be suppressed is
+     * limited by the 24 bit resolution of the SysTick timer.
+     */
     PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
 
-/**
- * @brief Compensate for the CPU cycles that pass while the SysTick is
- * stopped (low power functionality only).
- */
+    /**
+     * @brief Compensate for the CPU cycles that pass while the SysTick is
+     * stopped (low power functionality only).
+     */
     PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0;
 #endif /* configUSE_TICKLESS_IDLE */
 /*-----------------------------------------------------------*/
@@ -856,7 +881,11 @@
      * should instead call vTaskDelete( NULL ). Artificially force an assert()
      * to be triggered if configASSERT() is defined, then stop here so
      * application writers can catch the error. */
-    configASSERT( ulCriticalNesting == ~0UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == ~0UL );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == ~0UL );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
     portDISABLE_INTERRUPTS();
 
     while( ulDummy == 0 )
@@ -925,64 +954,57 @@
         /* The only permitted number of regions are 8 or 16. */
         configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 16 ) );
 
-        /* Ensure that the configTOTAL_MPU_REGIONS is configured correctly. */
-        configASSERT( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE );
+        /* MAIR0 - Index 0. */
+        portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
+        /* MAIR0 - Index 1. */
+        portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
 
-        /* Check that the MPU is present. */
-        if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
-        {
-            /* MAIR0 - Index 0. */
-            portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
-            /* MAIR0 - Index 1. */
-            portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
+        /* Setup privileged flash as Read Only so that privileged tasks can
+         * read it but not modify. */
+        portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup privileged flash as Read Only so that privileged tasks can
-             * read it but not modify. */
-            portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged flash as Read Only by both privileged and
+         * unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged flash as Read Only by both privileged and
-             * unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged syscalls flash as Read Only by both privileged
+         * and unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged syscalls flash as Read Only by both privileged
-             * and unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup RAM containing kernel data for privileged access only. */
+        portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
+                           ( portMPU_REGION_EXECUTE_NEVER );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup RAM containing kernel data for privileged access only. */
-            portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
-                               ( portMPU_REGION_EXECUTE_NEVER );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Enable mem fault. */
+        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
 
-            /* Enable mem fault. */
-            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
-
-            /* Enable MPU with privileged background access i.e. unmapped
-             * regions have privileged access. */
-            portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
-        }
+        /* Enable MPU with privileged background access i.e. unmapped
+         * regions have privileged access. */
+        portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
     }
 
 #endif /* configENABLE_MPU */
@@ -1027,28 +1049,29 @@
 }
 /*-----------------------------------------------------------*/
 
-void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    portDISABLE_INTERRUPTS();
-    ulCriticalNesting++;
-
-    /* Barriers are normally not required but do ensure the code is
-     * completely within the specified behaviour for the architecture. */
-    __asm volatile ( "dsb" ::: "memory" );
-    __asm volatile ( "isb" );
-}
-/*-----------------------------------------------------------*/
-
-void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    configASSERT( ulCriticalNesting );
-    ulCriticalNesting--;
-
-    if( ulCriticalNesting == 0 )
+#if ( configNUMBER_OF_CORES == 1 )
+    void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
     {
-        portENABLE_INTERRUPTS();
+        portDISABLE_INTERRUPTS();
+        ulCriticalNesting++;
+        /* Barriers are normally not required but do ensure the code is
+        * completely within the specified behaviour for the architecture. */
+        __asm volatile ( "dsb" ::: "memory" );
+        __asm volatile ( "isb" );
     }
-}
+    /*-----------------------------------------------------------*/
+
+    void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
+    {
+        configASSERT( ulCriticalNesting );
+        ulCriticalNesting--;
+
+        if( ulCriticalNesting == 0 )
+        {
+            portENABLE_INTERRUPTS();
+        }
+    }
+#endif /* configNUMBER_OF_CORES == 1 */
 /*-----------------------------------------------------------*/
 
 void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
@@ -1056,6 +1079,10 @@
     uint32_t ulPreviousMask;
 
     ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
+    #if ( configNUMBER_OF_CORES > 1 )
+        UBaseType_t uxSavedInterruptStatus = portENTER_CRITICAL_FROM_ISR();
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     traceISR_ENTER();
     {
         /* Increment the RTOS tick. */
@@ -1070,6 +1097,10 @@
             traceISR_EXIT();
         }
     }
+    #if ( configNUMBER_OF_CORES > 1 )
+        portEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
 }
 /*-----------------------------------------------------------*/
@@ -1078,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1090,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1108,38 +1151,42 @@
 
     switch( ucSVCNumber )
     {
-        #if ( configENABLE_TRUSTZONE == 1 )
-            case portSVC_ALLOCATE_SECURE_CONTEXT:
+    #if ( configENABLE_TRUSTZONE == 1 )
+        case portSVC_ALLOCATE_SECURE_CONTEXT:
 
-                /* R0 contains the stack size passed as parameter to the
-                 * vPortAllocateSecureContext function. */
-                ulR0 = pulCallerStackAddress[ 0 ];
+            /* R0 contains the stack size passed as parameter to the
+             * vPortAllocateSecureContext function. */
+            ulR0 = pulCallerStackAddress[ 0 ];
 
-                #if ( configENABLE_MPU == 1 )
-                {
-                    /* Read the CONTROL register value. */
-                    __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
+            #if ( configENABLE_MPU == 1 )
+            {
+                /* Read the CONTROL register value. */
+                __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
 
-                    /* The task that raised the SVC is privileged if Bit[0]
-                     * in the CONTROL register is 0. */
-                    ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
+                /* The task that raised the SVC is privileged if Bit[0]
+                 * in the CONTROL register is 0. */
+                ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
 
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
-                }
-                #else /* if ( configENABLE_MPU == 1 ) */
-                {
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
-                }
-                #endif /* configENABLE_MPU */
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
+            }
+            #else /* if ( configENABLE_MPU == 1 ) */
+            {
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
+            }
+            #endif /* configENABLE_MPU */
 
-                configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
-                SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
-                break;
+            configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
+            SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
+            break;
 
-            case portSVC_FREE_SECURE_CONTEXT:
-
+        case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
                 /* R0 contains TCB being freed and R1 contains the secure
                  * context handle to be freed. */
                 ulR0 = pulCallerStackAddress[ 0 ];
@@ -1147,51 +1194,62 @@
 
                 /* Free the secure context. */
                 SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
-                break;
-        #endif /* configENABLE_TRUSTZONE */
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
+            break;
+    #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
-            #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
-                case portSVC_RAISE_PRIVILEGE:
+    #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
+        case portSVC_RAISE_PRIVILEGE:
 
-                    /* Only raise the privilege, if the svc was raised from any of
-                     * the system calls. */
-                    if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
-                        ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
-                    {
-                        vRaisePrivilege();
-                    }
-                    break;
-            #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
+            /* Only raise the privilege, if the svc was raised from any of
+             * the system calls. */
+            if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
+                ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
+            {
+                vRaisePrivilege();
+            }
+            break;
+    #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
-            #if ( configENABLE_MPU == 1 )
-                case portSVC_YIELD:
-                    vPortYield();
-                    break;
-            #endif /* configENABLE_MPU == 1 */
+    #if ( configENABLE_MPU == 1 )
+        case portSVC_YIELD:
+            vPortYield();
+            break;
+    #endif /* configENABLE_MPU == 1 */
 
         default:
             /* Incorrect SVC call. */
@@ -1210,7 +1268,7 @@
         extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulSystemCallStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1246,12 +1304,16 @@
         {
             pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1261,20 +1323,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the system call stack for the stack frame. */
-            pulSystemCallStack = pulSystemCallStack - ulStackFrameSize;
+            pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulSystemCallStack[ i ] = pulTaskStack[ i ];
             }
@@ -1310,7 +1372,7 @@
 
             /* Remember the location where we should copy the stack frame when we exit from
              * the system call. */
-            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
+            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
 
             /* Record if the hardware used padding to force the stack pointer
              * to be double word aligned. */
@@ -1360,7 +1422,7 @@
         extern TaskHandle_t pxCurrentTCB;
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulTaskStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1392,12 +1454,16 @@
         {
             pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1407,20 +1473,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the task stack for the stack frame. */
-            pulTaskStack = pulTaskStack - ulStackFrameSize;
+            pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulTaskStack[ i ] = pulSystemCallStack[ i ];
             }
@@ -1518,21 +1584,21 @@
         xMPUSettings->ulContext[ ulIndex ] = 0x11111111; /* r11. */
         ulIndex++;
 
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters;            /* r0. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters; /* r0. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x01010101;                           /* r1. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x01010101; /* r1. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x02020202;                           /* r2. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x02020202; /* r2. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x03030303;                           /* r3. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x03030303; /* r3. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x12121212;                           /* r12. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x12121212; /* r12. */
         ulIndex++;
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) portTASK_RETURN_ADDRESS; /* LR. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode;                  /* PC. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode; /* PC. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR;                     /* xPSR. */
+        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR; /* xPSR. */
         ulIndex++;
 
         #if ( configENABLE_TRUSTZONE == 1 )
@@ -1543,14 +1609,18 @@
         #endif /* configENABLE_TRUSTZONE */
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) ( pxTopOfStack - 8 ); /* PSP with the hardware saved stack. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack;         /* PSPLIM. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack; /* PSPLIM. */
         ulIndex++;
 
         #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
         {
             /* Check PACBTI security feature configuration before pushing the
              * CONTROL register's value on task's TCB. */
-            ulControl = prvConfigurePACBTI( pdFALSE );
+            #if ( configNUMBER_OF_CORES == 1 )
+                ulControl = prvConfigurePACBTI( pdFALSE );
+            #else /* configNUMBER_OF_CORES > 1 */
+                ulControl = vConfigurePACBTI( pdFALSE );
+            #endif /* configNUMBER_OF_CORES */
         }
         #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1615,15 +1685,15 @@
          * interrupt. */
         #if ( portPRELOAD_REGISTERS == 0 )
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
-            pxTopOfStack -= 5;                                       /* R12, R3, R2 and R1. */
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
-            pxTopOfStack -= 9;                                       /* R11..R4, EXC_RETURN. */
+            pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
+            pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */
             *pxTopOfStack = portINITIAL_EXC_RETURN;
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
@@ -1637,42 +1707,42 @@
         }
         #else /* portPRELOAD_REGISTERS */
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x12121212UL;            /* R12. */
+            *pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x03030303UL;            /* R3. */
+            *pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x02020202UL;            /* R2. */
+            *pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x01010101UL;            /* R1. */
+            *pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x11111111UL;            /* R11. */
+            *pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x10101010UL;            /* R10. */
+            *pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x09090909UL;            /* R09. */
+            *pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x08080808UL;            /* R08. */
+            *pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x07070707UL;            /* R07. */
+            *pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x06060606UL;            /* R06. */
+            *pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x05050505UL;            /* R05. */
+            *pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x04040404UL;            /* R04. */
+            *pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04. */
             pxTopOfStack--;
-            *pxTopOfStack = portINITIAL_EXC_RETURN;                  /* EXC_RETURN. */
+            *pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxEndOfStack;            /* Slot used to hold this task's PSPLIM value. */
+            *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
 
             #if ( configENABLE_TRUSTZONE == 1 )
             {
@@ -1739,91 +1809,17 @@
     }
     #endif /* configCHECK_HANDLER_INSTALLATION */
 
-    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
-    {
-        volatile uint32_t ulImplementedPrioBits = 0;
-        volatile uint8_t ucMaxPriorityValue;
-
-        /* Determine the maximum priority from which ISR safe FreeRTOS API
-         * functions can be called. ISR safe functions are those that end in
-         * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
-         * ensure interrupt entry is as fast and simple as possible.
-         *
-         * First, determine the number of priority bits available. Write to all
-         * possible bits in the priority setting for SVCall. */
-        portNVIC_SHPR2_REG = 0xFF000000;
-
-        /* Read the value back to see how many bits stuck. */
-        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
-
-        /* Use the same mask on the maximum system call priority. */
-        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
-
-        /* Check that the maximum system call priority is nonzero after
-         * accounting for the number of priority bits supported by the
-         * hardware. A priority of 0 is invalid because setting the BASEPRI
-         * register to 0 unmasks all interrupts, and interrupts with priority 0
-         * cannot be masked using BASEPRI.
-         * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
-        configASSERT( ucMaxSysCallPriority );
-
-        /* Check that the bits not implemented in hardware are zero in
-         * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
-        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
-
-        /* Calculate the maximum acceptable priority group value for the number
-         * of bits read back. */
-        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
-        {
-            ulImplementedPrioBits++;
-            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
-        }
-
-        if( ulImplementedPrioBits == 8 )
-        {
-            /* When the hardware implements 8 priority bits, there is no way for
-             * the software to configure PRIGROUP to not have sub-priorities. As
-             * a result, the least significant bit is always used for sub-priority
-             * and there are 128 preemption priorities and 2 sub-priorities.
-             *
-             * This may cause some confusion in some cases - for example, if
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
-             * priority interrupts will be masked in Critical Sections as those
-             * are at the same preemption priority. This may appear confusing as
-             * 4 is higher (numerically lower) priority than
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
-             * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
-             * to 4, this confusion does not happen and the behaviour remains the same.
-             *
-             * The following assert ensures that the sub-priority bit in the
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
-             * confusion. */
-            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
-            ulMaxPRIGROUPValue = 0;
-        }
-        else
-        {
-            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
-        }
-
-        /* Shift the priority group value back to its position within the AIRCR
-         * register. */
-        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
-        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
-    }
-    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
-
-    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
-     * the highest priority. */
-    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
-    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
-    portNVIC_SHPR2_REG = 0;
+    vPortConfigureInterruptPriorities();
 
     #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
     {
         /* Set the CONTROL register value based on PACBTI security feature
          * configuration before starting the first task. */
-        ( void ) prvConfigurePACBTI( pdTRUE );
+        #if ( configNUMBER_OF_CORES == 1 )
+            ( void ) prvConfigurePACBTI( pdTRUE );
+        #else /* configNUMBER_OF_CORES > 1 */
+            ( void ) vConfigurePACBTI( pdTRUE );
+        #endif /* configNUMBER_OF_CORES */
     }
     #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1834,12 +1830,47 @@
     }
     #endif /* configENABLE_MPU */
 
-    /* Start the timer that generates the tick ISR. Interrupts are disabled
-     * here already. */
-    vPortSetupTimerInterrupt();
+    #if ( configNUMBER_OF_CORES > 1 )
+        /* Start the timer that generates the tick ISR. Interrupts are disabled
+         * here already. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count for all cores. */
+        for ( uint8_t ucCoreID = 0; ucCoreID < configNUMBER_OF_CORES; ucCoreID++ )
+        {
+            ulCriticalNestings[ ucCoreID ] = 0;
+        }
+        /* Signal that primary core has done all the necessary initialisations. */
+        ucPrimaryCoreInitDoneFlag = 1;
+        /* Wake up secondary cores */
+        BaseType_t xWakeResult = configWAKE_SECONDARY_CORES();
+        configASSERT( xWakeResult == pdTRUE );
 
-    /* Initialize the critical nesting count ready for the first task. */
-    ulCriticalNesting = 0;
+        /* Hold the primary core here until all the secondary cores are ready, this would be achieved only when
+         * all elements of ucSecondaryCoresReadyFlags are set.
+         */
+        while( 1 )
+        {
+            BaseType_t xAllCoresReady = pdTRUE;
+            for( uint8_t ucCoreID = 0; ucCoreID < ( configNUMBER_OF_CORES - 1 ); ucCoreID++ )
+            {
+                if( ucSecondaryCoresReadyFlags[ ucCoreID ] != pdTRUE )
+                {
+                    xAllCoresReady = pdFALSE;
+                    break;
+                }
+                }
+
+            if ( xAllCoresReady == pdTRUE )
+            {
+                break;
+            }
+        }
+    #else /* if ( configNUMBER_OF_CORES > 1 ) */
+        /* Start the timer that generates the tick ISR. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count ready for the first task. */
+        ulCriticalNesting = 0;
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
     {
@@ -1856,7 +1887,11 @@
      * functionality by defining configTASK_RETURN_ADDRESS. Call
      * vTaskSwitchContext() so link time optimization does not remove the
      * symbol. */
-    vTaskSwitchContext();
+    #if ( configNUMBER_OF_CORES > 1 )
+        vTaskSwitchContext( portGET_CORE_ID() );
+    #else
+        vTaskSwitchContext();
+    #endif
     prvTaskExitError();
 
     /* Should not get here. */
@@ -1868,7 +1903,11 @@
 {
     /* Not implemented in ports where there is nothing to return to.
      * Artificially force an assert. */
-    configASSERT( ulCriticalNesting == 1000UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == 1000UL );
+    #else /* if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == 1000UL );
+    #endif /* if ( configNUMBER_OF_CORES == 1 ) */
 }
 /*-----------------------------------------------------------*/
 
@@ -2151,6 +2190,90 @@
 #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
 /*-----------------------------------------------------------*/
 
+void vPortConfigureInterruptPriorities( void ) /* PRIVILEGED_FUNCTION */
+{
+    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
+    {
+        volatile uint32_t ulImplementedPrioBits = 0;
+        volatile uint8_t ucMaxPriorityValue;
+
+        /* Determine the maximum priority from which ISR safe FreeRTOS API
+        * functions can be called. ISR safe functions are those that end in
+        * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
+        * ensure interrupt entry is as fast and simple as possible.
+        *
+        * First, determine the number of priority bits available. Write to all
+        * possible bits in the priority setting for SVCall. */
+        portNVIC_SHPR2_REG = 0xFF000000;
+
+        /* Read the value back to see how many bits stuck. */
+        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
+
+        /* Use the same mask on the maximum system call priority. */
+        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
+
+        /* Check that the maximum system call priority is nonzero after
+        * accounting for the number of priority bits supported by the
+        * hardware. A priority of 0 is invalid because setting the BASEPRI
+        * register to 0 unmasks all interrupts, and interrupts with priority 0
+        * cannot be masked using BASEPRI.
+        * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+        configASSERT( ucMaxSysCallPriority );
+
+        /* Check that the bits not implemented in hardware are zero in
+        * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
+        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
+
+        /* Calculate the maximum acceptable priority group value for the number
+        * of bits read back. */
+        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
+        {
+            ulImplementedPrioBits++;
+            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
+        }
+
+        if( ulImplementedPrioBits == 8 )
+        {
+            /* When the hardware implements 8 priority bits, there is no way for
+            * the software to configure PRIGROUP to not have sub-priorities. As
+            * a result, the least significant bit is always used for sub-priority
+            * and there are 128 preemption priorities and 2 sub-priorities.
+            *
+            * This may cause some confusion in some cases - for example, if
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
+            * priority interrupts will be masked in Critical Sections as those
+            * are at the same preemption priority. This may appear confusing as
+            * 4 is higher (numerically lower) priority than
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
+            * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
+            * to 4, this confusion does not happen and the behaviour remains the same.
+            *
+            * The following assert ensures that the sub-priority bit in the
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
+            * confusion. */
+            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
+            ulMaxPRIGROUPValue = 0;
+        }
+        else
+        {
+            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
+        }
+
+        /* Shift the priority group value back to its position within the AIRCR
+        * register. */
+        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
+        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
+    }
+    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
+
+    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
+    * the highest priority. */
+    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
+    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
+    portNVIC_SHPR2_REG = 0;
+}
+/*-----------------------------------------------------------*/
+
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) )
 
     void vPortGrantAccessToKernelObject( TaskHandle_t xInternalTaskHandle,
@@ -2247,36 +2370,214 @@
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
-
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
-    {
-        uint32_t ulControl = 0x0;
-
-        /* Ensure that PACBTI is implemented. */
-        configASSERT( portID_ISAR5_REG != 0x0 );
-
-        /* Enable UsageFault exception. */
-        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
-
-        #if ( configENABLE_PAC == 1 )
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #else /* configNUMBER_OF_CORES > 1 */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #endif /* configNUMBER_OF_CORES */
         {
-            ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
-        }
-        #endif
+            uint32_t ulControl = 0x0;
 
-        #if ( configENABLE_BTI == 1 )
-        {
-            ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
-        }
-        #endif
+            /* Ensure that PACBTI is implemented. */
+            configASSERT( portID_ISAR5_REG != 0x0 );
 
-        if( xWriteControlRegister == pdTRUE )
-        {
-            __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
-        }
+            /* Enable UsageFault exception. */
+            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
 
-        return ulControl;
-    }
+            #if ( configENABLE_PAC == 1 )
+            {
+                ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
+            }
+            #endif
+
+            #if ( configENABLE_BTI == 1 )
+            {
+                ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
+            }
+            #endif
+
+            if( xWriteControlRegister == pdTRUE )
+            {
+                __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
+            }
+
+            return ulControl;
+        }
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 /*-----------------------------------------------------------*/
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /* Which core owns the lock? */
+    PRIVILEGED_DATA volatile uint32_t ulOwnedByCore[ portMAX_CORE_COUNT ];
+    /* Lock count a core owns. */
+    PRIVILEGED_DATA volatile uint32_t ulRecursionCountByLock[ eLockCount ];
+    /* Index 0 is used for ISR lock and Index 1 is used for task lock. */
+    PRIVILEGED_DATA volatile uint32_t ulGateWord[ eLockCount ];
+
+    __attribute__((weak)) void vInterruptCore( uint8_t ucCoreID )
+    {
+        /* Default weak stub - platform specific implementation may override. */
+        ( void ) ucCoreID;
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline void prvSpinUnlock( volatile uint32_t * ulLock )
+    {
+        /* Conservative unlock: preserve original barriers for broad HW/FVP. */
+        __asm volatile (
+            "dmb sy         \n"
+            "mov r1, #0     \n"
+            "str r1, [%0]   \n"
+            "sev            \n"
+            "dsb            \n"
+            "isb            \n"
+            :
+            : "r" ( ulLock )
+            : "memory", "r1"
+        );
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline uint32_t prvSpinTrylock( volatile uint32_t * ulLock )
+    {
+        /*
+         * Conservative ldrex/strex trylock:
+         * - Return 1 immediately if busy, clearing exclusive state (CLREX).
+         * - Retry strex only on spurious failure when observed free.
+         * - DMB on success to preserve expected acquire semantics.
+         */
+        uint32_t ulVal;
+        uint32_t ulStatus;
+
+        __asm volatile (
+            " ldrex %0, [%1]   \n"
+            : "=r" ( ulVal )
+            : "r" ( ulLock )
+            : "memory"
+        );
+
+        if( ulVal != 0U )
+        {
+            __asm volatile ("clrex" ::: "memory");
+            return 1U;
+        }
+
+        __asm volatile (
+            " strex %0, %2, [%1]   \n"
+            : "=&r" ( ulStatus )
+            : "r" ( ulLock ), "r" (1U)
+            : "memory"
+        );
+
+        if( ulStatus != 0U )
+        {
+            return 1U;
+        }
+        __asm volatile ( "dmb" ::: "memory" );
+        return 0U;
+    }
+
+
+/*-----------------------------------------------------------*/
+
+    /* Read 32b value shared between cores. */
+    static inline uint32_t prvGet32( volatile uint32_t * x )
+    {
+        __asm( "dsb" );
+        return *x;
+    }
+
+/*-----------------------------------------------------------*/
+
+    /* Write 32b value shared between cores. */
+    static inline void prvSet32( volatile uint32_t * x,
+                                 uint32_t value )
+    {
+        *x = value;
+        __asm( "dsb" );
+    }
+
+/*-----------------------------------------------------------*/
+
+    void vPortRecursiveLock( uint8_t ucCoreID,
+                             ePortRTOSLock eLockNum,
+                             BaseType_t uxAcquire )
+    {
+        /* Validate the core ID and lock number. */
+        configASSERT( ucCoreID < portMAX_CORE_COUNT );
+        configASSERT( eLockNum < eLockCount );
+
+        uint32_t ulLockBit = 1u << eLockNum;
+
+        /* Lock acquire */
+        if( uxAcquire )
+        {
+            /* Check if spinlock is available. */
+            /* If spinlock is not available check if the core owns the lock. */
+            /* If the core owns the lock wait increment the lock count by the core. */
+            /* If core does not own the lock wait for the spinlock. */
+            if( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+            {
+                /* Check if the core owns the spinlock. */
+                if( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit )
+                {
+                    configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != portUINT32_MAX );
+                    prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) + 1 ) );
+                    return;
+                }
+
+                /* Preload the gate word into the cache. */
+                uint32_t dummy = ulGateWord[ eLockNum ];
+                dummy++;
+
+                while( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+                {
+                    __asm volatile ( "wfe" );
+                }
+            }
+
+            /* Add barrier to ensure lock is taken before we proceed. */
+            __asm volatile( "dmb sy" ::: "memory" );
+
+            /* Assert the lock count is 0 when the spinlock is free and is acquired. */
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) == 0 );
+
+            /* Set lock count as 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], 1 );
+            /* Set ulOwnedByCore. */
+            prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) | ulLockBit ) );
+        }
+        /* Lock release. */
+        else
+        {
+            /* Assert the lock is not free already. */
+            configASSERT( ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit ) != 0 );
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != 0 );
+
+            /* Reduce ulRecursionCountByLock by 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) - 1 ) );
+
+            if( !prvGet32( &ulRecursionCountByLock[ eLockNum ] ) )
+            {
+                prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ~ulLockBit ) );
+                prvSpinUnlock( &ulGateWord[ eLockNum ] );
+                /* Add barrier to ensure lock status is reflected before we proceed. */
+                __asm volatile( "dmb sy" ::: "memory" );
+            }
+        }
+    }
+
+/*-----------------------------------------------------------*/
+
+    uint8_t ucPortGetCoreID( void )
+    {
+        return *(volatile uint8_t *)(configCORE_ID_REGISTER);
+    }
+
+/*-----------------------------------------------------------*/
+
+#endif /* if( configNUMBER_OF_CORES > 1 ) */
diff --git a/Source/portable/GCC/ARM_CM33/non_secure/portasm.c b/Source/portable/GCC/ARM_CM33/non_secure/portasm.c
index bdee088..6bc070d 100644
--- a/Source/portable/GCC/ARM_CM33/non_secure/portasm.c
+++ b/Source/portable/GCC/ARM_CM33/non_secure/portasm.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  * Copyright 2024 Arm Limited and/or its affiliates
  * <open-source-office@arm.com>
@@ -46,6 +46,16 @@
 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
 
 #if ( configENABLE_MPU == 1 )
+    #if ( configENABLE_PAC == 1 )
+        #define SECURE_CONTEXT_OFFSET   -36
+    #else
+        #define SECURE_CONTEXT_OFFSET   -20
+    #endif
+#else
+    #define SECURE_CONTEXT_OFFSET       0
+#endif
+
+#if ( configENABLE_MPU == 1 )
 
     void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
     {
@@ -609,13 +619,13 @@
     (
         "   .syntax unified                                 \n"
         "                                                   \n"
-        "   ldr r2, [r0]                                    \n" /* The first item in the TCB is the top of the stack. */
-        "   ldr r1, [r2]                                    \n" /* The first item on the stack is the task's xSecureContext. */
+        "   ldr r2, [r0]                                    \n" /* The first item in the TCB is the stored context location. */
+        "   ldr r1, [r2, %0]                                \n" /* Read xSecureContext from the task's context. */
         "   cmp r1, #0                                      \n" /* Raise svc if task's xSecureContext is not NULL. */
         "   it ne                                           \n"
-        "   svcne %0                                        \n" /* Secure context is freed in the supervisor call. */
+        "   svcne %1                                        \n" /* Secure context is freed in the supervisor call. */
         "   bx lr                                           \n" /* Return. */
-        ::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
+        ::"i" ( SECURE_CONTEXT_OFFSET ), "i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
     );
 }
 /*-----------------------------------------------------------*/
diff --git a/Source/portable/GCC/ARM_CM33/non_secure/portasm.h b/Source/portable/GCC/ARM_CM33/non_secure/portasm.h
index 53b4b6e..b4b545f 100644
--- a/Source/portable/GCC/ARM_CM33/non_secure/portasm.h
+++ b/Source/portable/GCC/ARM_CM33/non_secure/portasm.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM33/non_secure/portmacro.h b/Source/portable/GCC/ARM_CM33/non_secure/portmacro.h
index a57d2e6..931ba78 100644
--- a/Source/portable/GCC/ARM_CM33/non_secure/portmacro.h
+++ b/Source/portable/GCC/ARM_CM33/non_secure/portmacro.h
@@ -1,6 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * Copyright 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -52,6 +53,7 @@
 #define portHAS_ARMV8M_MAIN_EXTENSION    1
 #define portARMV8M_MINOR_VERSION         0
 #define portDONT_DISCARD                 __attribute__( ( used ) )
+#define portVALIDATED_FOR_SMP            0
 /*-----------------------------------------------------------*/
 
 /* ARMv8-M common port configurations. */
diff --git a/Source/portable/GCC/ARM_CM33/non_secure/portmacrocommon.h b/Source/portable/GCC/ARM_CM33/non_secure/portmacrocommon.h
index 2dfac6a..c34fdee 100644
--- a/Source/portable/GCC/ARM_CM33/non_secure/portmacrocommon.h
+++ b/Source/portable/GCC/ARM_CM33/non_secure/portmacrocommon.h
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -59,6 +58,19 @@
     #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h.  Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
 #endif /* configENABLE_TRUSTZONE */
 
+#if ( configNUMBER_OF_CORES > 1 )
+    #if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 )
+        #error "Multi-core SMP is currently only validated for Cortex-M33 non-TrustZone non-MPU port."
+    #endif /* if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 ) ) */
+
+    #ifndef configCORE_ID_REGISTER
+        #error "configCORE_ID_REGISTER must be defined to the address of the register used to identify the core executing the code."
+    #endif /* ifndef configCORE_ID_REGISTER */
+
+    #ifndef configWAKE_SECONDARY_CORES
+        #error "configWAKE_SECONDARY_CORES must be defined to a function that wakes the secondary cores."
+    #endif /* ifndef configWAKE_SECONDARY_CORES */
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -428,10 +440,26 @@
 /**
  * @brief Critical section management.
  */
+
+#define portSET_INTERRUPT_MASK()                  ulSetInterruptMask()
+#define portCLEAR_INTERRUPT_MASK( x )             vClearInterruptMask( x )
 #define portSET_INTERRUPT_MASK_FROM_ISR()         ulSetInterruptMask()
 #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x )    vClearInterruptMask( x )
-#define portENTER_CRITICAL()                      vPortEnterCritical()
-#define portEXIT_CRITICAL()                       vPortExitCritical()
+
+#if ( configNUMBER_OF_CORES == 1 )
+    #define portENTER_CRITICAL()                      vPortEnterCritical()
+    #define portEXIT_CRITICAL()                       vPortExitCritical()
+#else /* ( configNUMBER_OF_CORES == 1 ) */
+    extern void vTaskEnterCritical( void );
+    extern void vTaskExitCritical( void );
+    extern UBaseType_t vTaskEnterCriticalFromISR( void );
+    extern void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus );
+
+    #define portENTER_CRITICAL()                      vTaskEnterCritical()
+    #define portEXIT_CRITICAL()                       vTaskExitCritical()
+    #define portENTER_CRITICAL_FROM_ISR()             vTaskEnterCriticalFromISR()
+    #define portEXIT_CRITICAL_FROM_ISR( x )           vTaskExitCriticalFromISR( x )
+#endif /* if ( configNUMBER_OF_CORES != 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -526,7 +554,7 @@
 /* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION
  * based on whether or not Mainline extension is implemented. */
 #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
-    #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 )
+    #if ( ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) && ( configNUMBER_OF_CORES == 1 ) )
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    1
     #else
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    0
@@ -573,6 +601,44 @@
 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
 /*-----------------------------------------------------------*/
 
+
+#if ( configNUMBER_OF_CORES > 1 )
+    typedef enum
+    {
+        eIsrLock = 0,
+        eTaskLock,
+        eLockCount
+    } ePortRTOSLock;
+
+    extern volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ];
+    extern void vPortRecursiveLock( uint8_t ucCoreID,
+                                    ePortRTOSLock eLockNum,
+                                    BaseType_t uxAcquire );
+    extern uint8_t ucPortGetCoreID( void );
+    extern void vInterruptCore( uint8_t ucCoreID );
+
+    #define portGET_CORE_ID()                                  ucPortGetCoreID()
+
+    #define portGET_CRITICAL_NESTING_COUNT( xCoreID )          ( ulCriticalNestings[ ( uint8_t ) xCoreID ] )
+    #define portSET_CRITICAL_NESTING_COUNT( xCoreID, x )       ( ulCriticalNestings[ ( uint8_t ) xCoreID ] = ( x ) )
+    #define portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]++ )
+    #define portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]-- )
+
+    #define portMAX_CORE_COUNT                                 ( configNUMBER_OF_CORES )
+
+    #define portYIELD_CORE( xCoreID )                          vInterruptCore( xCoreID )
+
+    #define portRELEASE_ISR_LOCK( xCoreID )                    vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdFALSE )
+    #define portGET_ISR_LOCK( xCoreID )                        vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdTRUE )
+
+    #define portRELEASE_TASK_LOCK( xCoreID )                   vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdFALSE )
+    #define portGET_TASK_LOCK( xCoreID )                       vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdTRUE )
+
+    #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* ( configENABLE_PAC == 1 || configENABLE_BTI == 1 ) */
+#endif
+
 /* *INDENT-OFF* */
 #ifdef __cplusplus
     }
diff --git a/Source/portable/GCC/ARM_CM33/secure/secure_context.c b/Source/portable/GCC/ARM_CM33/secure/secure_context.c
index 62bcfa1..2dae022 100644
--- a/Source/portable/GCC/ARM_CM33/secure/secure_context.c
+++ b/Source/portable/GCC/ARM_CM33/secure/secure_context.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -213,8 +213,19 @@
         /* Were we able to get a free context? */
         if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS )
         {
-            /* Allocate the stack space. */
-            pucStackMemory = pvPortMalloc( ulSecureStackSize + securecontextSTACK_SEAL_SIZE );
+            /* Allocate the stack space if possible. */
+            if( ( ulSecureStackSize < securecontextSTACK_SEAL_SIZE ) ||
+                ( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) )
+            {
+                /* Reject stacks that are too small (the CONTROL word would be
+                 * written before the allocation, corrupting the secure heap)
+                 * and sizes that would overflow when the seal size is added. */
+                pucStackMemory = NULL;
+            }
+            else
+            {
+                pucStackMemory = pvPortMalloc( ulSecureStackSize + securecontextSTACK_SEAL_SIZE );
+            }
 
             if( pucStackMemory != NULL )
             {
@@ -279,9 +290,12 @@
                                                               void * pvTaskHandle )
 {
     uint32_t ulIPSR, ulSecureContextIndex;
+    uint8_t * pucStackLimit;
 
-    /* Read the Interrupt Program Status Register (IPSR) value. */
+    /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
+     * Register (PSPLIM) value. */
     secureportREAD_IPSR( ulIPSR );
+    secureportREAD_PSPLIM( pucStackLimit );
 
     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
      * when the processor is running in the Thread Mode. */
@@ -293,8 +307,14 @@
             ulSecureContextIndex = xSecureContextHandle - 1UL;
 
             /* Ensure that the secure context being deleted is associated with
-             * the task. */
-            if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
+             * the task and is NOT the currently-loaded context. Freeing a
+             * context whose stack is currently loaded in PSPLIM would leave the
+             * running task referencing freed secure memory (use-after-free).
+             * pvTaskHandle is supplied by the non-secure side and is untrusted,
+             * so it is used only as an additional ownership match, not as
+             * authority. */
+            if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) &&
+                ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) )
             {
                 /* Free the stack space. */
                 vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
@@ -342,7 +362,7 @@
 
         secureportREAD_PSPLIM( pucStackLimit );
 
-        /* Ensure that task's context is loaded and the task is saving it's own
+        /* Ensure that task's context is loaded and the task is saving its own
          * context. */
         if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) &&
             ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) )
diff --git a/Source/portable/GCC/ARM_CM33/secure/secure_context.h b/Source/portable/GCC/ARM_CM33/secure/secure_context.h
index 8b93857..51dd823 100644
--- a/Source/portable/GCC/ARM_CM33/secure/secure_context.h
+++ b/Source/portable/GCC/ARM_CM33/secure/secure_context.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM33/secure/secure_context_port.c b/Source/portable/GCC/ARM_CM33/secure/secure_context_port.c
index 11d8e1b..ef5cbf7 100644
--- a/Source/portable/GCC/ARM_CM33/secure/secure_context_port.c
+++ b/Source/portable/GCC/ARM_CM33/secure/secure_context_port.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM33/secure/secure_heap.c b/Source/portable/GCC/ARM_CM33/secure/secure_heap.c
index b0e83b4..58226bf 100644
--- a/Source/portable/GCC/ARM_CM33/secure/secure_heap.c
+++ b/Source/portable/GCC/ARM_CM33/secure/secure_heap.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM33/secure/secure_heap.h b/Source/portable/GCC/ARM_CM33/secure/secure_heap.h
index 61a96da..906fa24 100644
--- a/Source/portable/GCC/ARM_CM33/secure/secure_heap.h
+++ b/Source/portable/GCC/ARM_CM33/secure/secure_heap.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM33/secure/secure_init.c b/Source/portable/GCC/ARM_CM33/secure/secure_init.c
index f7f7e67..6996692 100644
--- a/Source/portable/GCC/ARM_CM33/secure/secure_init.c
+++ b/Source/portable/GCC/ARM_CM33/secure/secure_init.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM33/secure/secure_init.h b/Source/portable/GCC/ARM_CM33/secure/secure_init.h
index 46ffbd9..4e7bd40 100644
--- a/Source/portable/GCC/ARM_CM33/secure/secure_init.h
+++ b/Source/portable/GCC/ARM_CM33/secure/secure_init.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM33/secure/secure_port_macros.h b/Source/portable/GCC/ARM_CM33/secure/secure_port_macros.h
index 34494e1..72774eb 100644
--- a/Source/portable/GCC/ARM_CM33/secure/secure_port_macros.h
+++ b/Source/portable/GCC/ARM_CM33/secure/secure_port_macros.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM33_NTZ/non_secure/mpu_wrappers_v2_asm.c b/Source/portable/GCC/ARM_CM33_NTZ/non_secure/mpu_wrappers_v2_asm.c
index 8504ddd..63d1b52 100644
--- a/Source/portable/GCC/ARM_CM33_NTZ/non_secure/mpu_wrappers_v2_asm.c
+++ b/Source/portable/GCC/ARM_CM33_NTZ/non_secure/mpu_wrappers_v2_asm.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM33_NTZ/non_secure/port.c b/Source/portable/GCC/ARM_CM33_NTZ/non_secure/port.c
index f16a343..007150c 100644
--- a/Source/portable/GCC/ARM_CM33_NTZ/non_secure/port.c
+++ b/Source/portable/GCC/ARM_CM33_NTZ/non_secure/port.c
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024-2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -145,13 +144,13 @@
 /**
  * @brief Constants required to manipulate the FPU.
  */
-#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 )              /* Coprocessor Access Control Register. */
+#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */
 #define portCPACR_CP10_VALUE    ( 3UL )
 #define portCPACR_CP11_VALUE    portCPACR_CP10_VALUE
 #define portCPACR_CP10_POS      ( 20UL )
 #define portCPACR_CP11_POS      ( 22UL )
 
-#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 )              /* Floating Point Context Control Register. */
+#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
 #define portFPCCR_ASPEN_POS     ( 31UL )
 #define portFPCCR_ASPEN_MASK    ( 1UL << portFPCCR_ASPEN_POS )
 #define portFPCCR_LSPEN_POS     ( 30UL )
@@ -188,8 +187,8 @@
 #define portMPU_MAIR0_REG                       ( *( ( volatile uint32_t * ) 0xe000edc0 ) )
 #define portMPU_MAIR1_REG                       ( *( ( volatile uint32_t * ) 0xe000edc4 ) )
 
-#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
-#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
+#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
+#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
 
 #define portMPU_RBAR_ACCESS_PERMISSIONS_MASK    ( 3UL << 1UL )
 
@@ -230,8 +229,8 @@
 
 #if ( portARMV8M_MINOR_VERSION >= 1 )
 
-/* Enable Privileged eXecute Never MPU attribute for the selected memory
- * region. */
+    /* Enable Privileged eXecute Never MPU attribute for the selected memory
+     * region. */
     #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER    ( 1UL << 4UL )
 #endif /* portARMV8M_MINOR_VERSION >= 1 */
 
@@ -241,9 +240,6 @@
 /* Enable MPU. */
 #define portMPU_ENABLE_BIT                    ( 1UL << 0UL )
 
-/* Expected value of the portMPU_TYPE register. */
-#define portEXPECTED_MPU_TYPE_VALUE           ( configTOTAL_MPU_REGIONS << 8UL )
-
 /* Extract first address of the MPU region as encoded in the
  * RBAR (Region Base Address Register) value. */
 #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@@ -291,37 +287,37 @@
 
 #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         FD
- * 1111 1111  1111 1111  1111 1111  1111 1101
- *
- * Bit[6] - 1 --> The exception was taken from the Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 1 --> The exception was taken to the Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         FD
+     * 1111 1111  1111 1111  1111 1111  1111 1101
+     *
+     * Bit[6] - 1 --> The exception was taken from the Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 1 --> The exception was taken to the Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xfffffffd )
 #else
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         BC
- * 1111 1111  1111 1111  1111 1111  1011 1100
- *
- * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         BC
+     * 1111 1111  1111 1111  1111 1111  1011 1100
+     *
+     * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xffffffbc )
 #endif /* configRUN_FREERTOS_SECURE_ONLY */
 
@@ -401,50 +397,54 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Extract MPU region's access permissions from the Region Base Address
- * Register (RBAR) value.
- *
- * @param ulRBARValue RBAR value for the MPU region.
- *
- * @return uint32_t Access permissions.
- */
+    /**
+     * @brief Extract MPU region's access permissions from the Region Base Address
+     * Register (RBAR) value.
+     *
+     * @param ulRBARValue RBAR value for the MPU region.
+     *
+     * @return uint32_t Access permissions.
+     */
     static uint32_t prvGetRegionAccessPermissions( uint32_t ulRBARValue ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU == 1 && configUSE_MPU_WRAPPERS_V1 == 0 */
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Setup the Memory Protection Unit (MPU).
- */
+    /**
+     * @brief Setup the Memory Protection Unit (MPU).
+     */
     static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU */
 
 #if ( configENABLE_FPU == 1 )
 
-/**
- * @brief Setup the Floating Point Unit (FPU).
- */
+    /**
+     * @brief Setup the Floating Point Unit (FPU).
+     */
     static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_FPU */
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
 
-/**
- * @brief Configures PACBTI features.
- *
- * This function configures the Pointer Authentication, and Branch Target
- * Identification security features as per the user configuration. It returns
- * the value of the special purpose CONTROL register accordingly, and optionally
- * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
- * architecture based) target supports PACBTI security feature.
- *
- * @param xWriteControlRegister Used to control whether the special purpose
- * CONTROL register should be updated or not.
- *
- * @return CONTROL register value according to the configured PACBTI option.
- */
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    /**
+     * @brief Configures PACBTI features.
+     *
+     * This function configures the Pointer Authentication, and Branch Target
+     * Identification security features as per the user configuration. It returns
+     * the value of the special purpose CONTROL register accordingly, and optionally
+     * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
+     * architecture based) target supports PACBTI security feature.
+     *
+     * @param xWriteControlRegister Used to control whether the special purpose
+     * CONTROL register should be updated or not.
+     *
+     * @return CONTROL register value according to the configured PACBTI option.
+     */
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -491,14 +491,14 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the system call stack so that upon returning from
- * SVC, the system call stack is used.
- *
- * @param pulTaskStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- * @param ucSystemCallNumber The system call number of the system call.
- */
+    /**
+     * @brief Sets up the system call stack so that upon returning from
+     * SVC, the system call stack is used.
+     *
+     * @param pulTaskStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     * @param ucSystemCallNumber The system call number of the system call.
+     */
     void vSystemCallEnter( uint32_t * pulTaskStack,
                            uint32_t ulLR,
                            uint8_t ucSystemCallNumber ) PRIVILEGED_FUNCTION;
@@ -507,22 +507,22 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Raise SVC for exiting from a system call.
- */
+    /**
+     * @brief Raise SVC for exiting from a system call.
+     */
     void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the task stack so that upon returning from
- * SVC, the task stack is used again.
- *
- * @param pulSystemCallStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- */
+    /**
+     * @brief Sets up the task stack so that upon returning from
+     * SVC, the task stack is used again.
+     *
+     * @param pulSystemCallStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     */
     void vSystemCallExit( uint32_t * pulSystemCallStack,
                           uint32_t ulLR ) PRIVILEGED_FUNCTION;
 
@@ -530,21 +530,38 @@
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Checks whether or not the calling task is privileged.
- *
- * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
- */
+    /**
+     * @brief Checks whether or not the calling task is privileged.
+     *
+     * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
+     */
     BaseType_t xPortIsTaskPrivileged( void ) PRIVILEGED_FUNCTION;
 
 #endif /* configENABLE_MPU == 1 */
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /**
+     * @brief Platform/Application-defined function that wakes up the secondary cores.
+     *
+     * @return pdTRUE if the secondary cores were successfully woken up.
+     *         pdFALSE otherwise.
+     */
+    extern BaseType_t configWAKE_SECONDARY_CORES( void );
+
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
+
+/**
+ * @brief Configures interrupt priorities.
+ */
+void vPortConfigureInterruptPriorities( void ) PRIVILEGED_FUNCTION;
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief This variable is set to pdTRUE when the scheduler is started.
- */
+    /**
+     * @brief This variable is set to pdTRUE when the scheduler is started.
+     */
     PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
@@ -553,14 +570,22 @@
  * @brief Each task maintains its own interrupt status in the critical nesting
  * variable.
  */
-PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
+#if ( configNUMBER_OF_CORES == 1 )
+    PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0UL;
+#else /* #if ( configNUMBER_OF_CORES == 1 ) */
+    PRIVILEGED_DATA volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ] = { 0 };
+    /* Flags to check if the secondary cores are ready. */
+    PRIVILEGED_DATA volatile uint8_t ucSecondaryCoresReadyFlags[ configNUMBER_OF_CORES - 1 ] = { 0 };
+    /* Flag to indicate that the primary core has completed its initialisation. */
+    PRIVILEGED_DATA volatile uint8_t ucPrimaryCoreInitDoneFlag = 0;
+ #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #if ( configENABLE_TRUSTZONE == 1 )
 
-/**
- * @brief Saved as part of the task context to indicate which context the
- * task is using on the secure side.
- */
+    /**
+     * @brief Saved as part of the task context to indicate which context the
+     * task is using on the secure side.
+     */
     PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
 #endif /* configENABLE_TRUSTZONE */
 
@@ -579,21 +604,21 @@
 
 #if ( configUSE_TICKLESS_IDLE == 1 )
 
-/**
- * @brief The number of SysTick increments that make up one tick period.
- */
+    /**
+     * @brief The number of SysTick increments that make up one tick period.
+     */
     PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
 
-/**
- * @brief The maximum number of tick periods that can be suppressed is
- * limited by the 24 bit resolution of the SysTick timer.
- */
+    /**
+     * @brief The maximum number of tick periods that can be suppressed is
+     * limited by the 24 bit resolution of the SysTick timer.
+     */
     PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
 
-/**
- * @brief Compensate for the CPU cycles that pass while the SysTick is
- * stopped (low power functionality only).
- */
+    /**
+     * @brief Compensate for the CPU cycles that pass while the SysTick is
+     * stopped (low power functionality only).
+     */
     PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0;
 #endif /* configUSE_TICKLESS_IDLE */
 /*-----------------------------------------------------------*/
@@ -856,7 +881,11 @@
      * should instead call vTaskDelete( NULL ). Artificially force an assert()
      * to be triggered if configASSERT() is defined, then stop here so
      * application writers can catch the error. */
-    configASSERT( ulCriticalNesting == ~0UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == ~0UL );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == ~0UL );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
     portDISABLE_INTERRUPTS();
 
     while( ulDummy == 0 )
@@ -925,64 +954,57 @@
         /* The only permitted number of regions are 8 or 16. */
         configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 16 ) );
 
-        /* Ensure that the configTOTAL_MPU_REGIONS is configured correctly. */
-        configASSERT( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE );
+        /* MAIR0 - Index 0. */
+        portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
+        /* MAIR0 - Index 1. */
+        portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
 
-        /* Check that the MPU is present. */
-        if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
-        {
-            /* MAIR0 - Index 0. */
-            portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
-            /* MAIR0 - Index 1. */
-            portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
+        /* Setup privileged flash as Read Only so that privileged tasks can
+         * read it but not modify. */
+        portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup privileged flash as Read Only so that privileged tasks can
-             * read it but not modify. */
-            portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged flash as Read Only by both privileged and
+         * unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged flash as Read Only by both privileged and
-             * unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged syscalls flash as Read Only by both privileged
+         * and unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged syscalls flash as Read Only by both privileged
-             * and unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup RAM containing kernel data for privileged access only. */
+        portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
+                           ( portMPU_REGION_EXECUTE_NEVER );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup RAM containing kernel data for privileged access only. */
-            portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
-                               ( portMPU_REGION_EXECUTE_NEVER );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Enable mem fault. */
+        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
 
-            /* Enable mem fault. */
-            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
-
-            /* Enable MPU with privileged background access i.e. unmapped
-             * regions have privileged access. */
-            portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
-        }
+        /* Enable MPU with privileged background access i.e. unmapped
+         * regions have privileged access. */
+        portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
     }
 
 #endif /* configENABLE_MPU */
@@ -1027,28 +1049,29 @@
 }
 /*-----------------------------------------------------------*/
 
-void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    portDISABLE_INTERRUPTS();
-    ulCriticalNesting++;
-
-    /* Barriers are normally not required but do ensure the code is
-     * completely within the specified behaviour for the architecture. */
-    __asm volatile ( "dsb" ::: "memory" );
-    __asm volatile ( "isb" );
-}
-/*-----------------------------------------------------------*/
-
-void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    configASSERT( ulCriticalNesting );
-    ulCriticalNesting--;
-
-    if( ulCriticalNesting == 0 )
+#if ( configNUMBER_OF_CORES == 1 )
+    void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
     {
-        portENABLE_INTERRUPTS();
+        portDISABLE_INTERRUPTS();
+        ulCriticalNesting++;
+        /* Barriers are normally not required but do ensure the code is
+        * completely within the specified behaviour for the architecture. */
+        __asm volatile ( "dsb" ::: "memory" );
+        __asm volatile ( "isb" );
     }
-}
+    /*-----------------------------------------------------------*/
+
+    void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
+    {
+        configASSERT( ulCriticalNesting );
+        ulCriticalNesting--;
+
+        if( ulCriticalNesting == 0 )
+        {
+            portENABLE_INTERRUPTS();
+        }
+    }
+#endif /* configNUMBER_OF_CORES == 1 */
 /*-----------------------------------------------------------*/
 
 void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
@@ -1056,6 +1079,10 @@
     uint32_t ulPreviousMask;
 
     ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
+    #if ( configNUMBER_OF_CORES > 1 )
+        UBaseType_t uxSavedInterruptStatus = portENTER_CRITICAL_FROM_ISR();
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     traceISR_ENTER();
     {
         /* Increment the RTOS tick. */
@@ -1070,6 +1097,10 @@
             traceISR_EXIT();
         }
     }
+    #if ( configNUMBER_OF_CORES > 1 )
+        portEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
 }
 /*-----------------------------------------------------------*/
@@ -1078,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1090,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1108,38 +1151,42 @@
 
     switch( ucSVCNumber )
     {
-        #if ( configENABLE_TRUSTZONE == 1 )
-            case portSVC_ALLOCATE_SECURE_CONTEXT:
+    #if ( configENABLE_TRUSTZONE == 1 )
+        case portSVC_ALLOCATE_SECURE_CONTEXT:
 
-                /* R0 contains the stack size passed as parameter to the
-                 * vPortAllocateSecureContext function. */
-                ulR0 = pulCallerStackAddress[ 0 ];
+            /* R0 contains the stack size passed as parameter to the
+             * vPortAllocateSecureContext function. */
+            ulR0 = pulCallerStackAddress[ 0 ];
 
-                #if ( configENABLE_MPU == 1 )
-                {
-                    /* Read the CONTROL register value. */
-                    __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
+            #if ( configENABLE_MPU == 1 )
+            {
+                /* Read the CONTROL register value. */
+                __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
 
-                    /* The task that raised the SVC is privileged if Bit[0]
-                     * in the CONTROL register is 0. */
-                    ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
+                /* The task that raised the SVC is privileged if Bit[0]
+                 * in the CONTROL register is 0. */
+                ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
 
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
-                }
-                #else /* if ( configENABLE_MPU == 1 ) */
-                {
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
-                }
-                #endif /* configENABLE_MPU */
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
+            }
+            #else /* if ( configENABLE_MPU == 1 ) */
+            {
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
+            }
+            #endif /* configENABLE_MPU */
 
-                configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
-                SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
-                break;
+            configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
+            SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
+            break;
 
-            case portSVC_FREE_SECURE_CONTEXT:
-
+        case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
                 /* R0 contains TCB being freed and R1 contains the secure
                  * context handle to be freed. */
                 ulR0 = pulCallerStackAddress[ 0 ];
@@ -1147,51 +1194,62 @@
 
                 /* Free the secure context. */
                 SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
-                break;
-        #endif /* configENABLE_TRUSTZONE */
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
+            break;
+    #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
-            #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
-                case portSVC_RAISE_PRIVILEGE:
+    #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
+        case portSVC_RAISE_PRIVILEGE:
 
-                    /* Only raise the privilege, if the svc was raised from any of
-                     * the system calls. */
-                    if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
-                        ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
-                    {
-                        vRaisePrivilege();
-                    }
-                    break;
-            #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
+            /* Only raise the privilege, if the svc was raised from any of
+             * the system calls. */
+            if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
+                ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
+            {
+                vRaisePrivilege();
+            }
+            break;
+    #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
-            #if ( configENABLE_MPU == 1 )
-                case portSVC_YIELD:
-                    vPortYield();
-                    break;
-            #endif /* configENABLE_MPU == 1 */
+    #if ( configENABLE_MPU == 1 )
+        case portSVC_YIELD:
+            vPortYield();
+            break;
+    #endif /* configENABLE_MPU == 1 */
 
         default:
             /* Incorrect SVC call. */
@@ -1210,7 +1268,7 @@
         extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulSystemCallStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1246,12 +1304,16 @@
         {
             pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1261,20 +1323,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the system call stack for the stack frame. */
-            pulSystemCallStack = pulSystemCallStack - ulStackFrameSize;
+            pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulSystemCallStack[ i ] = pulTaskStack[ i ];
             }
@@ -1310,7 +1372,7 @@
 
             /* Remember the location where we should copy the stack frame when we exit from
              * the system call. */
-            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
+            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
 
             /* Record if the hardware used padding to force the stack pointer
              * to be double word aligned. */
@@ -1360,7 +1422,7 @@
         extern TaskHandle_t pxCurrentTCB;
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulTaskStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1392,12 +1454,16 @@
         {
             pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1407,20 +1473,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the task stack for the stack frame. */
-            pulTaskStack = pulTaskStack - ulStackFrameSize;
+            pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulTaskStack[ i ] = pulSystemCallStack[ i ];
             }
@@ -1518,21 +1584,21 @@
         xMPUSettings->ulContext[ ulIndex ] = 0x11111111; /* r11. */
         ulIndex++;
 
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters;            /* r0. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters; /* r0. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x01010101;                           /* r1. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x01010101; /* r1. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x02020202;                           /* r2. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x02020202; /* r2. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x03030303;                           /* r3. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x03030303; /* r3. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x12121212;                           /* r12. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x12121212; /* r12. */
         ulIndex++;
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) portTASK_RETURN_ADDRESS; /* LR. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode;                  /* PC. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode; /* PC. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR;                     /* xPSR. */
+        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR; /* xPSR. */
         ulIndex++;
 
         #if ( configENABLE_TRUSTZONE == 1 )
@@ -1543,14 +1609,18 @@
         #endif /* configENABLE_TRUSTZONE */
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) ( pxTopOfStack - 8 ); /* PSP with the hardware saved stack. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack;         /* PSPLIM. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack; /* PSPLIM. */
         ulIndex++;
 
         #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
         {
             /* Check PACBTI security feature configuration before pushing the
              * CONTROL register's value on task's TCB. */
-            ulControl = prvConfigurePACBTI( pdFALSE );
+            #if ( configNUMBER_OF_CORES == 1 )
+                ulControl = prvConfigurePACBTI( pdFALSE );
+            #else /* configNUMBER_OF_CORES > 1 */
+                ulControl = vConfigurePACBTI( pdFALSE );
+            #endif /* configNUMBER_OF_CORES */
         }
         #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1615,15 +1685,15 @@
          * interrupt. */
         #if ( portPRELOAD_REGISTERS == 0 )
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
-            pxTopOfStack -= 5;                                       /* R12, R3, R2 and R1. */
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
-            pxTopOfStack -= 9;                                       /* R11..R4, EXC_RETURN. */
+            pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
+            pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */
             *pxTopOfStack = portINITIAL_EXC_RETURN;
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
@@ -1637,42 +1707,42 @@
         }
         #else /* portPRELOAD_REGISTERS */
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x12121212UL;            /* R12. */
+            *pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x03030303UL;            /* R3. */
+            *pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x02020202UL;            /* R2. */
+            *pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x01010101UL;            /* R1. */
+            *pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x11111111UL;            /* R11. */
+            *pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x10101010UL;            /* R10. */
+            *pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x09090909UL;            /* R09. */
+            *pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x08080808UL;            /* R08. */
+            *pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x07070707UL;            /* R07. */
+            *pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x06060606UL;            /* R06. */
+            *pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x05050505UL;            /* R05. */
+            *pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x04040404UL;            /* R04. */
+            *pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04. */
             pxTopOfStack--;
-            *pxTopOfStack = portINITIAL_EXC_RETURN;                  /* EXC_RETURN. */
+            *pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxEndOfStack;            /* Slot used to hold this task's PSPLIM value. */
+            *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
 
             #if ( configENABLE_TRUSTZONE == 1 )
             {
@@ -1739,91 +1809,17 @@
     }
     #endif /* configCHECK_HANDLER_INSTALLATION */
 
-    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
-    {
-        volatile uint32_t ulImplementedPrioBits = 0;
-        volatile uint8_t ucMaxPriorityValue;
-
-        /* Determine the maximum priority from which ISR safe FreeRTOS API
-         * functions can be called. ISR safe functions are those that end in
-         * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
-         * ensure interrupt entry is as fast and simple as possible.
-         *
-         * First, determine the number of priority bits available. Write to all
-         * possible bits in the priority setting for SVCall. */
-        portNVIC_SHPR2_REG = 0xFF000000;
-
-        /* Read the value back to see how many bits stuck. */
-        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
-
-        /* Use the same mask on the maximum system call priority. */
-        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
-
-        /* Check that the maximum system call priority is nonzero after
-         * accounting for the number of priority bits supported by the
-         * hardware. A priority of 0 is invalid because setting the BASEPRI
-         * register to 0 unmasks all interrupts, and interrupts with priority 0
-         * cannot be masked using BASEPRI.
-         * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
-        configASSERT( ucMaxSysCallPriority );
-
-        /* Check that the bits not implemented in hardware are zero in
-         * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
-        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
-
-        /* Calculate the maximum acceptable priority group value for the number
-         * of bits read back. */
-        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
-        {
-            ulImplementedPrioBits++;
-            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
-        }
-
-        if( ulImplementedPrioBits == 8 )
-        {
-            /* When the hardware implements 8 priority bits, there is no way for
-             * the software to configure PRIGROUP to not have sub-priorities. As
-             * a result, the least significant bit is always used for sub-priority
-             * and there are 128 preemption priorities and 2 sub-priorities.
-             *
-             * This may cause some confusion in some cases - for example, if
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
-             * priority interrupts will be masked in Critical Sections as those
-             * are at the same preemption priority. This may appear confusing as
-             * 4 is higher (numerically lower) priority than
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
-             * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
-             * to 4, this confusion does not happen and the behaviour remains the same.
-             *
-             * The following assert ensures that the sub-priority bit in the
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
-             * confusion. */
-            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
-            ulMaxPRIGROUPValue = 0;
-        }
-        else
-        {
-            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
-        }
-
-        /* Shift the priority group value back to its position within the AIRCR
-         * register. */
-        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
-        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
-    }
-    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
-
-    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
-     * the highest priority. */
-    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
-    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
-    portNVIC_SHPR2_REG = 0;
+    vPortConfigureInterruptPriorities();
 
     #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
     {
         /* Set the CONTROL register value based on PACBTI security feature
          * configuration before starting the first task. */
-        ( void ) prvConfigurePACBTI( pdTRUE );
+        #if ( configNUMBER_OF_CORES == 1 )
+            ( void ) prvConfigurePACBTI( pdTRUE );
+        #else /* configNUMBER_OF_CORES > 1 */
+            ( void ) vConfigurePACBTI( pdTRUE );
+        #endif /* configNUMBER_OF_CORES */
     }
     #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1834,12 +1830,47 @@
     }
     #endif /* configENABLE_MPU */
 
-    /* Start the timer that generates the tick ISR. Interrupts are disabled
-     * here already. */
-    vPortSetupTimerInterrupt();
+    #if ( configNUMBER_OF_CORES > 1 )
+        /* Start the timer that generates the tick ISR. Interrupts are disabled
+         * here already. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count for all cores. */
+        for ( uint8_t ucCoreID = 0; ucCoreID < configNUMBER_OF_CORES; ucCoreID++ )
+        {
+            ulCriticalNestings[ ucCoreID ] = 0;
+        }
+        /* Signal that primary core has done all the necessary initialisations. */
+        ucPrimaryCoreInitDoneFlag = 1;
+        /* Wake up secondary cores */
+        BaseType_t xWakeResult = configWAKE_SECONDARY_CORES();
+        configASSERT( xWakeResult == pdTRUE );
 
-    /* Initialize the critical nesting count ready for the first task. */
-    ulCriticalNesting = 0;
+        /* Hold the primary core here until all the secondary cores are ready, this would be achieved only when
+         * all elements of ucSecondaryCoresReadyFlags are set.
+         */
+        while( 1 )
+        {
+            BaseType_t xAllCoresReady = pdTRUE;
+            for( uint8_t ucCoreID = 0; ucCoreID < ( configNUMBER_OF_CORES - 1 ); ucCoreID++ )
+            {
+                if( ucSecondaryCoresReadyFlags[ ucCoreID ] != pdTRUE )
+                {
+                    xAllCoresReady = pdFALSE;
+                    break;
+                }
+                }
+
+            if ( xAllCoresReady == pdTRUE )
+            {
+                break;
+            }
+        }
+    #else /* if ( configNUMBER_OF_CORES > 1 ) */
+        /* Start the timer that generates the tick ISR. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count ready for the first task. */
+        ulCriticalNesting = 0;
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
     {
@@ -1856,7 +1887,11 @@
      * functionality by defining configTASK_RETURN_ADDRESS. Call
      * vTaskSwitchContext() so link time optimization does not remove the
      * symbol. */
-    vTaskSwitchContext();
+    #if ( configNUMBER_OF_CORES > 1 )
+        vTaskSwitchContext( portGET_CORE_ID() );
+    #else
+        vTaskSwitchContext();
+    #endif
     prvTaskExitError();
 
     /* Should not get here. */
@@ -1868,7 +1903,11 @@
 {
     /* Not implemented in ports where there is nothing to return to.
      * Artificially force an assert. */
-    configASSERT( ulCriticalNesting == 1000UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == 1000UL );
+    #else /* if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == 1000UL );
+    #endif /* if ( configNUMBER_OF_CORES == 1 ) */
 }
 /*-----------------------------------------------------------*/
 
@@ -2151,6 +2190,90 @@
 #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
 /*-----------------------------------------------------------*/
 
+void vPortConfigureInterruptPriorities( void ) /* PRIVILEGED_FUNCTION */
+{
+    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
+    {
+        volatile uint32_t ulImplementedPrioBits = 0;
+        volatile uint8_t ucMaxPriorityValue;
+
+        /* Determine the maximum priority from which ISR safe FreeRTOS API
+        * functions can be called. ISR safe functions are those that end in
+        * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
+        * ensure interrupt entry is as fast and simple as possible.
+        *
+        * First, determine the number of priority bits available. Write to all
+        * possible bits in the priority setting for SVCall. */
+        portNVIC_SHPR2_REG = 0xFF000000;
+
+        /* Read the value back to see how many bits stuck. */
+        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
+
+        /* Use the same mask on the maximum system call priority. */
+        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
+
+        /* Check that the maximum system call priority is nonzero after
+        * accounting for the number of priority bits supported by the
+        * hardware. A priority of 0 is invalid because setting the BASEPRI
+        * register to 0 unmasks all interrupts, and interrupts with priority 0
+        * cannot be masked using BASEPRI.
+        * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+        configASSERT( ucMaxSysCallPriority );
+
+        /* Check that the bits not implemented in hardware are zero in
+        * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
+        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
+
+        /* Calculate the maximum acceptable priority group value for the number
+        * of bits read back. */
+        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
+        {
+            ulImplementedPrioBits++;
+            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
+        }
+
+        if( ulImplementedPrioBits == 8 )
+        {
+            /* When the hardware implements 8 priority bits, there is no way for
+            * the software to configure PRIGROUP to not have sub-priorities. As
+            * a result, the least significant bit is always used for sub-priority
+            * and there are 128 preemption priorities and 2 sub-priorities.
+            *
+            * This may cause some confusion in some cases - for example, if
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
+            * priority interrupts will be masked in Critical Sections as those
+            * are at the same preemption priority. This may appear confusing as
+            * 4 is higher (numerically lower) priority than
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
+            * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
+            * to 4, this confusion does not happen and the behaviour remains the same.
+            *
+            * The following assert ensures that the sub-priority bit in the
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
+            * confusion. */
+            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
+            ulMaxPRIGROUPValue = 0;
+        }
+        else
+        {
+            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
+        }
+
+        /* Shift the priority group value back to its position within the AIRCR
+        * register. */
+        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
+        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
+    }
+    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
+
+    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
+    * the highest priority. */
+    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
+    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
+    portNVIC_SHPR2_REG = 0;
+}
+/*-----------------------------------------------------------*/
+
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) )
 
     void vPortGrantAccessToKernelObject( TaskHandle_t xInternalTaskHandle,
@@ -2247,36 +2370,214 @@
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
-
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
-    {
-        uint32_t ulControl = 0x0;
-
-        /* Ensure that PACBTI is implemented. */
-        configASSERT( portID_ISAR5_REG != 0x0 );
-
-        /* Enable UsageFault exception. */
-        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
-
-        #if ( configENABLE_PAC == 1 )
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #else /* configNUMBER_OF_CORES > 1 */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #endif /* configNUMBER_OF_CORES */
         {
-            ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
-        }
-        #endif
+            uint32_t ulControl = 0x0;
 
-        #if ( configENABLE_BTI == 1 )
-        {
-            ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
-        }
-        #endif
+            /* Ensure that PACBTI is implemented. */
+            configASSERT( portID_ISAR5_REG != 0x0 );
 
-        if( xWriteControlRegister == pdTRUE )
-        {
-            __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
-        }
+            /* Enable UsageFault exception. */
+            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
 
-        return ulControl;
-    }
+            #if ( configENABLE_PAC == 1 )
+            {
+                ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
+            }
+            #endif
+
+            #if ( configENABLE_BTI == 1 )
+            {
+                ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
+            }
+            #endif
+
+            if( xWriteControlRegister == pdTRUE )
+            {
+                __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
+            }
+
+            return ulControl;
+        }
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 /*-----------------------------------------------------------*/
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /* Which core owns the lock? */
+    PRIVILEGED_DATA volatile uint32_t ulOwnedByCore[ portMAX_CORE_COUNT ];
+    /* Lock count a core owns. */
+    PRIVILEGED_DATA volatile uint32_t ulRecursionCountByLock[ eLockCount ];
+    /* Index 0 is used for ISR lock and Index 1 is used for task lock. */
+    PRIVILEGED_DATA volatile uint32_t ulGateWord[ eLockCount ];
+
+    __attribute__((weak)) void vInterruptCore( uint8_t ucCoreID )
+    {
+        /* Default weak stub - platform specific implementation may override. */
+        ( void ) ucCoreID;
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline void prvSpinUnlock( volatile uint32_t * ulLock )
+    {
+        /* Conservative unlock: preserve original barriers for broad HW/FVP. */
+        __asm volatile (
+            "dmb sy         \n"
+            "mov r1, #0     \n"
+            "str r1, [%0]   \n"
+            "sev            \n"
+            "dsb            \n"
+            "isb            \n"
+            :
+            : "r" ( ulLock )
+            : "memory", "r1"
+        );
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline uint32_t prvSpinTrylock( volatile uint32_t * ulLock )
+    {
+        /*
+         * Conservative ldrex/strex trylock:
+         * - Return 1 immediately if busy, clearing exclusive state (CLREX).
+         * - Retry strex only on spurious failure when observed free.
+         * - DMB on success to preserve expected acquire semantics.
+         */
+        uint32_t ulVal;
+        uint32_t ulStatus;
+
+        __asm volatile (
+            " ldrex %0, [%1]   \n"
+            : "=r" ( ulVal )
+            : "r" ( ulLock )
+            : "memory"
+        );
+
+        if( ulVal != 0U )
+        {
+            __asm volatile ("clrex" ::: "memory");
+            return 1U;
+        }
+
+        __asm volatile (
+            " strex %0, %2, [%1]   \n"
+            : "=&r" ( ulStatus )
+            : "r" ( ulLock ), "r" (1U)
+            : "memory"
+        );
+
+        if( ulStatus != 0U )
+        {
+            return 1U;
+        }
+        __asm volatile ( "dmb" ::: "memory" );
+        return 0U;
+    }
+
+
+/*-----------------------------------------------------------*/
+
+    /* Read 32b value shared between cores. */
+    static inline uint32_t prvGet32( volatile uint32_t * x )
+    {
+        __asm( "dsb" );
+        return *x;
+    }
+
+/*-----------------------------------------------------------*/
+
+    /* Write 32b value shared between cores. */
+    static inline void prvSet32( volatile uint32_t * x,
+                                 uint32_t value )
+    {
+        *x = value;
+        __asm( "dsb" );
+    }
+
+/*-----------------------------------------------------------*/
+
+    void vPortRecursiveLock( uint8_t ucCoreID,
+                             ePortRTOSLock eLockNum,
+                             BaseType_t uxAcquire )
+    {
+        /* Validate the core ID and lock number. */
+        configASSERT( ucCoreID < portMAX_CORE_COUNT );
+        configASSERT( eLockNum < eLockCount );
+
+        uint32_t ulLockBit = 1u << eLockNum;
+
+        /* Lock acquire */
+        if( uxAcquire )
+        {
+            /* Check if spinlock is available. */
+            /* If spinlock is not available check if the core owns the lock. */
+            /* If the core owns the lock wait increment the lock count by the core. */
+            /* If core does not own the lock wait for the spinlock. */
+            if( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+            {
+                /* Check if the core owns the spinlock. */
+                if( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit )
+                {
+                    configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != portUINT32_MAX );
+                    prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) + 1 ) );
+                    return;
+                }
+
+                /* Preload the gate word into the cache. */
+                uint32_t dummy = ulGateWord[ eLockNum ];
+                dummy++;
+
+                while( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+                {
+                    __asm volatile ( "wfe" );
+                }
+            }
+
+            /* Add barrier to ensure lock is taken before we proceed. */
+            __asm volatile( "dmb sy" ::: "memory" );
+
+            /* Assert the lock count is 0 when the spinlock is free and is acquired. */
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) == 0 );
+
+            /* Set lock count as 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], 1 );
+            /* Set ulOwnedByCore. */
+            prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) | ulLockBit ) );
+        }
+        /* Lock release. */
+        else
+        {
+            /* Assert the lock is not free already. */
+            configASSERT( ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit ) != 0 );
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != 0 );
+
+            /* Reduce ulRecursionCountByLock by 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) - 1 ) );
+
+            if( !prvGet32( &ulRecursionCountByLock[ eLockNum ] ) )
+            {
+                prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ~ulLockBit ) );
+                prvSpinUnlock( &ulGateWord[ eLockNum ] );
+                /* Add barrier to ensure lock status is reflected before we proceed. */
+                __asm volatile( "dmb sy" ::: "memory" );
+            }
+        }
+    }
+
+/*-----------------------------------------------------------*/
+
+    uint8_t ucPortGetCoreID( void )
+    {
+        return *(volatile uint8_t *)(configCORE_ID_REGISTER);
+    }
+
+/*-----------------------------------------------------------*/
+
+#endif /* if( configNUMBER_OF_CORES > 1 ) */
diff --git a/Source/portable/GCC/ARM_CM33_NTZ/non_secure/portasm.c b/Source/portable/GCC/ARM_CM33_NTZ/non_secure/portasm.c
index 51ec476..fbb00b1 100644
--- a/Source/portable/GCC/ARM_CM33_NTZ/non_secure/portasm.c
+++ b/Source/portable/GCC/ARM_CM33_NTZ/non_secure/portasm.c
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -134,8 +133,21 @@
         (
             "   .syntax unified                                 \n"
             "                                                   \n"
+        /*
+         * The SMP-specific logic below is derived from the Raspberry Pi
+         * implementation in the FreeRTOS-Kernel-Community-Supported-Ports project.
+         * Source: GCC/RP2350_ARM_NTZ/non_secure/portasm.c
+         * Upstream commit: 8b2955f6d97bf4cd582db9f5b62d9eb1587b76d7
+         */
+        #if ( configNUMBER_OF_CORES == 1)
             "   ldr  r2, =pxCurrentTCB                          \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
             "   ldr  r1, [r2]                                   \n" /* Read pxCurrentTCB. */
+        #else /* if ( configNUMBER_OF_CORES == 1) */
+            "   ldr r1, =ulFirstTaskLiteralPool                 \n" /* Get the location of the current TCB and the Id of the current core. */
+            "   ldmia r1!, {r2, r3}                             \n"
+            "   ldr r2, [r2]                                    \n" /* r2 = Core Id */
+            "   ldr r1, [r3, r2, LSL #2]                        \n" /* r1 = pxCurrentTCBs[CORE_ID] */
+        #endif /* if ( configNUMBER_OF_CORES == 1) */
             "   ldr  r0, [r1]                                   \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
             "                                                   \n"
         #if ( configENABLE_PAC == 1 )
@@ -158,6 +170,14 @@
             "   mov  r0, #0                                     \n"
             "   msr  basepri, r0                                \n" /* Ensure that interrupts are enabled when the first task starts. */
             "   bx   r2                                         \n" /* Finally, branch to EXC_RETURN. */
+        #if ( configNUMBER_OF_CORES > 1 )
+            "                                                   \n"
+            "     .align 4                                      \n"
+            "ulFirstTaskLiteralPool:                            \n"
+            "    .word %c0                                      \n" /* CORE_ID_REGISTER */
+            "    .word pxCurrentTCBs                            \n"
+            :: "i" (configCORE_ID_REGISTER)
+        #endif /* if ( configNUMBER_OF_CORES > 1 ) */
         );
     }
 
@@ -422,20 +442,43 @@
             "   clrm {r1-r4}                                    \n" /* Clear r1-r4. */
         #endif /* configENABLE_PAC */
             "                                                   \n"
+        /*
+         * The SMP-specific logic below is derived from the Raspberry Pi
+         * implementation in the FreeRTOS-Kernel-Community-Supported-Ports project.
+         * Source: GCC/RP2350_ARM_NTZ/non_secure/portasm.c
+         * Upstream commit: 8b2955f6d97bf4cd582db9f5b62d9eb1587b76d7
+         */
+        #if ( configNUMBER_OF_CORES == 1)
             "   ldr r2, =pxCurrentTCB                           \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
             "   ldr r1, [r2]                                    \n" /* Read pxCurrentTCB. */
+        #else /* if ( configNUMBER_OF_CORES == 1) */
+            "   ldr r1, =ulPendSVLiteralPool                    \n" /* Get the location of the current TCB and the Id of the current core. */
+            "   ldmia r1!, {r2, r3}                             \n"
+            "   ldr r2, [r2]                                    \n" /* r2 = Core Id */
+            "   ldr r1, [r3, r2, LSL #2]                        \n" /* r1 = pxCurrentTCBs[CORE_ID] */
+        #endif /* if ( configNUMBER_OF_CORES == 1) */
             "   str r0, [r1]                                    \n" /* Save the new top of stack in TCB. */
             "                                                   \n"
             "   mov r0, %0                                      \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
             "   msr basepri, r0                                 \n" /* Disable interrupts up to configMAX_SYSCALL_INTERRUPT_PRIORITY. */
             "   dsb                                             \n"
             "   isb                                             \n"
+        #if ( configNUMBER_OF_CORES > 1)
+            "   mov r0, r2                                      \n" /* r0 = ucPortGetCoreID() */
+        #endif /* if ( configNUMBER_OF_CORES == 1) */
             "   bl vTaskSwitchContext                           \n"
             "   mov r0, #0                                      \n" /* r0 = 0. */
             "   msr basepri, r0                                 \n" /* Enable interrupts. */
             "                                                   \n"
+        #if ( configNUMBER_OF_CORES == 1)
             "   ldr r2, =pxCurrentTCB                           \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
             "   ldr r1, [r2]                                    \n" /* Read pxCurrentTCB. */
+        #else /* if ( configNUMBER_OF_CORES == 1) */
+            "   ldr r1, =ulPendSVLiteralPool                    \n" /* Get the location of the current TCB and the Id of the current core. */
+            "   ldmia r1!, {r2, r3}                             \n"
+            "   ldr r2, [r2]                                    \n" /* r2 = Core Id */
+            "   ldr r1, [r3, r2, LSL #2]                        \n" /* r1 = pxCurrentTCBs[CORE_ID] */
+        #endif /* if ( configNUMBER_OF_CORES == 1) */
             "   ldr r0, [r1]                                    \n" /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
             "                                                   \n"
         #if ( configENABLE_PAC == 1 )
@@ -458,7 +501,16 @@
             "   msr psplim, r2                                  \n" /* Restore the PSPLIM register value for the task. */
             "   msr psp, r0                                     \n" /* Remember the new top of stack for the task. */
             "   bx r3                                           \n"
-            ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
+        #if ( configNUMBER_OF_CORES > 1 )
+            "   .align 4                           \n"
+            "   ulPendSVLiteralPool:               \n"
+            "   .word %c1                          \n" /* CORE_ID_REGISTER */
+            "   .word pxCurrentTCBs                \n"
+            :: "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ), "i" ( configCORE_ID_REGISTER )
+        #else /* #if ( configNUMBER_OF_CORES > 1 ) */
+            :: "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
+        #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
+
         );
     }
 
diff --git a/Source/portable/GCC/ARM_CM33_NTZ/non_secure/portasm.h b/Source/portable/GCC/ARM_CM33_NTZ/non_secure/portasm.h
index 53b4b6e..b4b545f 100644
--- a/Source/portable/GCC/ARM_CM33_NTZ/non_secure/portasm.h
+++ b/Source/portable/GCC/ARM_CM33_NTZ/non_secure/portasm.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM33_NTZ/non_secure/portmacro.h b/Source/portable/GCC/ARM_CM33_NTZ/non_secure/portmacro.h
index a57d2e6..390ec34 100644
--- a/Source/portable/GCC/ARM_CM33_NTZ/non_secure/portmacro.h
+++ b/Source/portable/GCC/ARM_CM33_NTZ/non_secure/portmacro.h
@@ -1,6 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * Copyright 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -52,6 +53,7 @@
 #define portHAS_ARMV8M_MAIN_EXTENSION    1
 #define portARMV8M_MINOR_VERSION         0
 #define portDONT_DISCARD                 __attribute__( ( used ) )
+#define portVALIDATED_FOR_SMP            1
 /*-----------------------------------------------------------*/
 
 /* ARMv8-M common port configurations. */
diff --git a/Source/portable/GCC/ARM_CM33_NTZ/non_secure/portmacrocommon.h b/Source/portable/GCC/ARM_CM33_NTZ/non_secure/portmacrocommon.h
index 2dfac6a..c34fdee 100644
--- a/Source/portable/GCC/ARM_CM33_NTZ/non_secure/portmacrocommon.h
+++ b/Source/portable/GCC/ARM_CM33_NTZ/non_secure/portmacrocommon.h
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -59,6 +58,19 @@
     #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h.  Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
 #endif /* configENABLE_TRUSTZONE */
 
+#if ( configNUMBER_OF_CORES > 1 )
+    #if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 )
+        #error "Multi-core SMP is currently only validated for Cortex-M33 non-TrustZone non-MPU port."
+    #endif /* if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 ) ) */
+
+    #ifndef configCORE_ID_REGISTER
+        #error "configCORE_ID_REGISTER must be defined to the address of the register used to identify the core executing the code."
+    #endif /* ifndef configCORE_ID_REGISTER */
+
+    #ifndef configWAKE_SECONDARY_CORES
+        #error "configWAKE_SECONDARY_CORES must be defined to a function that wakes the secondary cores."
+    #endif /* ifndef configWAKE_SECONDARY_CORES */
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -428,10 +440,26 @@
 /**
  * @brief Critical section management.
  */
+
+#define portSET_INTERRUPT_MASK()                  ulSetInterruptMask()
+#define portCLEAR_INTERRUPT_MASK( x )             vClearInterruptMask( x )
 #define portSET_INTERRUPT_MASK_FROM_ISR()         ulSetInterruptMask()
 #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x )    vClearInterruptMask( x )
-#define portENTER_CRITICAL()                      vPortEnterCritical()
-#define portEXIT_CRITICAL()                       vPortExitCritical()
+
+#if ( configNUMBER_OF_CORES == 1 )
+    #define portENTER_CRITICAL()                      vPortEnterCritical()
+    #define portEXIT_CRITICAL()                       vPortExitCritical()
+#else /* ( configNUMBER_OF_CORES == 1 ) */
+    extern void vTaskEnterCritical( void );
+    extern void vTaskExitCritical( void );
+    extern UBaseType_t vTaskEnterCriticalFromISR( void );
+    extern void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus );
+
+    #define portENTER_CRITICAL()                      vTaskEnterCritical()
+    #define portEXIT_CRITICAL()                       vTaskExitCritical()
+    #define portENTER_CRITICAL_FROM_ISR()             vTaskEnterCriticalFromISR()
+    #define portEXIT_CRITICAL_FROM_ISR( x )           vTaskExitCriticalFromISR( x )
+#endif /* if ( configNUMBER_OF_CORES != 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -526,7 +554,7 @@
 /* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION
  * based on whether or not Mainline extension is implemented. */
 #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
-    #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 )
+    #if ( ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) && ( configNUMBER_OF_CORES == 1 ) )
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    1
     #else
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    0
@@ -573,6 +601,44 @@
 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
 /*-----------------------------------------------------------*/
 
+
+#if ( configNUMBER_OF_CORES > 1 )
+    typedef enum
+    {
+        eIsrLock = 0,
+        eTaskLock,
+        eLockCount
+    } ePortRTOSLock;
+
+    extern volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ];
+    extern void vPortRecursiveLock( uint8_t ucCoreID,
+                                    ePortRTOSLock eLockNum,
+                                    BaseType_t uxAcquire );
+    extern uint8_t ucPortGetCoreID( void );
+    extern void vInterruptCore( uint8_t ucCoreID );
+
+    #define portGET_CORE_ID()                                  ucPortGetCoreID()
+
+    #define portGET_CRITICAL_NESTING_COUNT( xCoreID )          ( ulCriticalNestings[ ( uint8_t ) xCoreID ] )
+    #define portSET_CRITICAL_NESTING_COUNT( xCoreID, x )       ( ulCriticalNestings[ ( uint8_t ) xCoreID ] = ( x ) )
+    #define portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]++ )
+    #define portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]-- )
+
+    #define portMAX_CORE_COUNT                                 ( configNUMBER_OF_CORES )
+
+    #define portYIELD_CORE( xCoreID )                          vInterruptCore( xCoreID )
+
+    #define portRELEASE_ISR_LOCK( xCoreID )                    vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdFALSE )
+    #define portGET_ISR_LOCK( xCoreID )                        vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdTRUE )
+
+    #define portRELEASE_TASK_LOCK( xCoreID )                   vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdFALSE )
+    #define portGET_TASK_LOCK( xCoreID )                       vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdTRUE )
+
+    #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* ( configENABLE_PAC == 1 || configENABLE_BTI == 1 ) */
+#endif
+
 /* *INDENT-OFF* */
 #ifdef __cplusplus
     }
diff --git a/Source/portable/GCC/ARM_CM3_MPU/mpu_wrappers_v2_asm.c b/Source/portable/GCC/ARM_CM3_MPU/mpu_wrappers_v2_asm.c
index 0e0abee..6c2e8ed 100644
--- a/Source/portable/GCC/ARM_CM3_MPU/mpu_wrappers_v2_asm.c
+++ b/Source/portable/GCC/ARM_CM3_MPU/mpu_wrappers_v2_asm.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM3_MPU/port.c b/Source/portable/GCC/ARM_CM3_MPU/port.c
index af25ed6..d834fba 100644
--- a/Source/portable/GCC/ARM_CM3_MPU/port.c
+++ b/Source/portable/GCC/ARM_CM3_MPU/port.c
@@ -1,6 +1,8 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * Copyright 2025 Arm Limited and/or its affiliates
+ * <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -53,9 +55,19 @@
     #define portNVIC_SYSTICK_CLK    ( 0 )
 #endif
 
+/* Unprivileged critical sections are not supported when using MPU wrappers
+ * version 2. Default the option to 0 and reject an explicit value of 1. */
 #ifndef configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS
-    #warning "configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS is not defined. We recommend defining it to 0 in FreeRTOSConfig.h for better security."
-    #define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS    1
+    #if ( configUSE_MPU_WRAPPERS_V1 == 0 )
+        #define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS    0
+    #else
+        #warning "configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS is not defined. We recommend defining it to 0 in FreeRTOSConfig.h for better security."
+        #define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS    1
+    #endif
+#else
+    #if ( ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) )
+        #error configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS is not supported with MPU wrappers version 2 ( configUSE_MPU_WRAPPERS_V1 == 0 ).
+    #endif
 #endif
 
 /* Prototype of all Interrupt Service Routines (ISRs). */
@@ -484,7 +496,10 @@
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulSystemCallStack;
         uint32_t ulSystemCallLocation, i;
-        const uint32_t ulStackFrameSize = 8;
+        /* Hardware Saved Stack Frame Size upon Exception entry:
+         * Basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+         */
+        const uint32_t ulHardwareSavedExceptionFrameSize = 8;
 
         #if defined( __ARMCC_VERSION )
             /* Declaration when these variable are defined in code instead of being
@@ -520,10 +535,10 @@
             pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
 
             /* Make space on the system call stack for the stack frame. */
-            pulSystemCallStack = pulSystemCallStack - ulStackFrameSize;
+            pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulSystemCallStack[ i ] = pulTaskStack[ i ];
             }
@@ -541,7 +556,7 @@
 
             /* Remember the location where we should copy the stack frame when we exit from
              * the system call. */
-            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
+            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
 
             /* Store the value of the Link Register before the SVC was raised.
              * It contains the address of the caller of the System Call entry
@@ -594,7 +609,10 @@
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulTaskStack;
         uint32_t ulSystemCallLocation, i;
-        const uint32_t ulStackFrameSize = 8;
+        /* Hardware Saved Stack Frame Size upon Exception entry:
+         * Basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+         */
+        const uint32_t ulHardwareSavedExceptionFrameSize = 8;
 
         #if defined( __ARMCC_VERSION )
             /* Declaration when these variable are defined in code instead of being
@@ -626,10 +644,10 @@
             pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
 
             /* Make space on the task stack for the stack frame. */
-            pulTaskStack = pulTaskStack - ulStackFrameSize;
+            pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulTaskStack[ i ] = pulSystemCallStack[ i ];
             }
@@ -1188,7 +1206,7 @@
     }
 
     /* Shift the code by one before returning so it can be written directly
-     * into the the correct bit position of the attribute register. */
+     * into the correct bit position of the attribute register. */
     return( ulReturnValue << 1UL );
 }
 /*-----------------------------------------------------------*/
diff --git a/Source/portable/GCC/ARM_CM3_MPU/portmacro.h b/Source/portable/GCC/ARM_CM3_MPU/portmacro.h
index 3d8d604..c6ee751 100644
--- a/Source/portable/GCC/ARM_CM3_MPU/portmacro.h
+++ b/Source/portable/GCC/ARM_CM3_MPU/portmacro.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM4F/port.c b/Source/portable/GCC/ARM_CM4F/port.c
index df7027a..b321f06 100644
--- a/Source/portable/GCC/ARM_CM4F/port.c
+++ b/Source/portable/GCC/ARM_CM4F/port.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM4F/portmacro.h b/Source/portable/GCC/ARM_CM4F/portmacro.h
index f555ef8..fc2a839 100644
--- a/Source/portable/GCC/ARM_CM4F/portmacro.h
+++ b/Source/portable/GCC/ARM_CM4F/portmacro.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM4_MPU/mpu_wrappers_v2_asm.c b/Source/portable/GCC/ARM_CM4_MPU/mpu_wrappers_v2_asm.c
index 0e0abee..6c2e8ed 100644
--- a/Source/portable/GCC/ARM_CM4_MPU/mpu_wrappers_v2_asm.c
+++ b/Source/portable/GCC/ARM_CM4_MPU/mpu_wrappers_v2_asm.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM4_MPU/port.c b/Source/portable/GCC/ARM_CM4_MPU/port.c
index 9ff846e..c383c54 100644
--- a/Source/portable/GCC/ARM_CM4_MPU/port.c
+++ b/Source/portable/GCC/ARM_CM4_MPU/port.c
@@ -1,6 +1,8 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * Copyright 2025 Arm Limited and/or its affiliates
+ * <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -57,9 +59,19 @@
     #define portNVIC_SYSTICK_CLK    ( 0 )
 #endif
 
+/* Unprivileged critical sections are not supported when using MPU wrappers
+ * version 2. Default the option to 0 and reject an explicit value of 1. */
 #ifndef configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS
-    #warning "configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS is not defined. We recommend defining it to 0 in FreeRTOSConfig.h for better security."
-    #define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS    1
+    #if ( configUSE_MPU_WRAPPERS_V1 == 0 )
+        #define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS    0
+    #else
+        #warning "configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS is not defined. We recommend defining it to 0 in FreeRTOSConfig.h for better security."
+        #define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS    1
+    #endif
+#else
+    #if ( ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) )
+        #error configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS is not supported with MPU wrappers version 2 ( configUSE_MPU_WRAPPERS_V1 == 0 ).
+    #endif
 #endif
 
 /* Prototype of all Interrupt Service Routines (ISRs). */
@@ -518,7 +530,7 @@
         extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulSystemCallStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
             /* Declaration when these variable are defined in code instead of being
@@ -553,10 +565,14 @@
         {
             pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
             {
                 /* Extended frame i.e. FPU in use. */
-                ulStackFrameSize = 26;
+                ulHardwareSavedExceptionFrameSize = 26;
                 __asm volatile (
                     " vpush {s0}         \n" /* Trigger lazy stacking. */
                     " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -566,14 +582,14 @@
             else
             {
                 /* Standard frame i.e. FPU not in use. */
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
 
             /* Make space on the system call stack for the stack frame. */
-            pulSystemCallStack = pulSystemCallStack - ulStackFrameSize;
+            pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulSystemCallStack[ i ] = pulTaskStack[ i ];
             }
@@ -591,7 +607,7 @@
 
             /* Remember the location where we should copy the stack frame when we exit from
              * the system call. */
-            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
+            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
 
             /* Store the value of the Link Register before the SVC was raised.
              * It contains the address of the caller of the System Call entry
@@ -644,7 +660,7 @@
         extern TaskHandle_t pxCurrentTCB;
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulTaskStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
             /* Declaration when these variable are defined in code instead of being
@@ -675,10 +691,14 @@
         {
             pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
             {
                 /* Extended frame i.e. FPU in use. */
-                ulStackFrameSize = 26;
+                ulHardwareSavedExceptionFrameSize = 26;
                 __asm volatile (
                     " vpush {s0}         \n" /* Trigger lazy stacking. */
                     " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -688,14 +708,14 @@
             else
             {
                 /* Standard frame i.e. FPU not in use. */
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
 
             /* Make space on the task stack for the stack frame. */
-            pulTaskStack = pulTaskStack - ulStackFrameSize;
+            pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulTaskStack[ i ] = pulSystemCallStack[ i ];
             }
@@ -1330,7 +1350,7 @@
     }
 
     /* Shift the code by one before returning so it can be written directly
-     * into the the correct bit position of the attribute register. */
+     * into the correct bit position of the attribute register. */
     return( ulReturnValue << 1UL );
 }
 /*-----------------------------------------------------------*/
diff --git a/Source/portable/GCC/ARM_CM4_MPU/portmacro.h b/Source/portable/GCC/ARM_CM4_MPU/portmacro.h
index 1ba44d1..6fcc95f 100644
--- a/Source/portable/GCC/ARM_CM4_MPU/portmacro.h
+++ b/Source/portable/GCC/ARM_CM4_MPU/portmacro.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM55/non_secure/mpu_wrappers_v2_asm.c b/Source/portable/GCC/ARM_CM55/non_secure/mpu_wrappers_v2_asm.c
index 9c3e8c7..6dd2be8 100644
--- a/Source/portable/GCC/ARM_CM55/non_secure/mpu_wrappers_v2_asm.c
+++ b/Source/portable/GCC/ARM_CM55/non_secure/mpu_wrappers_v2_asm.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM55/non_secure/port.c b/Source/portable/GCC/ARM_CM55/non_secure/port.c
index f16a343..007150c 100644
--- a/Source/portable/GCC/ARM_CM55/non_secure/port.c
+++ b/Source/portable/GCC/ARM_CM55/non_secure/port.c
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024-2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -145,13 +144,13 @@
 /**
  * @brief Constants required to manipulate the FPU.
  */
-#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 )              /* Coprocessor Access Control Register. */
+#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */
 #define portCPACR_CP10_VALUE    ( 3UL )
 #define portCPACR_CP11_VALUE    portCPACR_CP10_VALUE
 #define portCPACR_CP10_POS      ( 20UL )
 #define portCPACR_CP11_POS      ( 22UL )
 
-#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 )              /* Floating Point Context Control Register. */
+#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
 #define portFPCCR_ASPEN_POS     ( 31UL )
 #define portFPCCR_ASPEN_MASK    ( 1UL << portFPCCR_ASPEN_POS )
 #define portFPCCR_LSPEN_POS     ( 30UL )
@@ -188,8 +187,8 @@
 #define portMPU_MAIR0_REG                       ( *( ( volatile uint32_t * ) 0xe000edc0 ) )
 #define portMPU_MAIR1_REG                       ( *( ( volatile uint32_t * ) 0xe000edc4 ) )
 
-#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
-#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
+#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
+#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
 
 #define portMPU_RBAR_ACCESS_PERMISSIONS_MASK    ( 3UL << 1UL )
 
@@ -230,8 +229,8 @@
 
 #if ( portARMV8M_MINOR_VERSION >= 1 )
 
-/* Enable Privileged eXecute Never MPU attribute for the selected memory
- * region. */
+    /* Enable Privileged eXecute Never MPU attribute for the selected memory
+     * region. */
     #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER    ( 1UL << 4UL )
 #endif /* portARMV8M_MINOR_VERSION >= 1 */
 
@@ -241,9 +240,6 @@
 /* Enable MPU. */
 #define portMPU_ENABLE_BIT                    ( 1UL << 0UL )
 
-/* Expected value of the portMPU_TYPE register. */
-#define portEXPECTED_MPU_TYPE_VALUE           ( configTOTAL_MPU_REGIONS << 8UL )
-
 /* Extract first address of the MPU region as encoded in the
  * RBAR (Region Base Address Register) value. */
 #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@@ -291,37 +287,37 @@
 
 #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         FD
- * 1111 1111  1111 1111  1111 1111  1111 1101
- *
- * Bit[6] - 1 --> The exception was taken from the Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 1 --> The exception was taken to the Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         FD
+     * 1111 1111  1111 1111  1111 1111  1111 1101
+     *
+     * Bit[6] - 1 --> The exception was taken from the Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 1 --> The exception was taken to the Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xfffffffd )
 #else
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         BC
- * 1111 1111  1111 1111  1111 1111  1011 1100
- *
- * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         BC
+     * 1111 1111  1111 1111  1111 1111  1011 1100
+     *
+     * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xffffffbc )
 #endif /* configRUN_FREERTOS_SECURE_ONLY */
 
@@ -401,50 +397,54 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Extract MPU region's access permissions from the Region Base Address
- * Register (RBAR) value.
- *
- * @param ulRBARValue RBAR value for the MPU region.
- *
- * @return uint32_t Access permissions.
- */
+    /**
+     * @brief Extract MPU region's access permissions from the Region Base Address
+     * Register (RBAR) value.
+     *
+     * @param ulRBARValue RBAR value for the MPU region.
+     *
+     * @return uint32_t Access permissions.
+     */
     static uint32_t prvGetRegionAccessPermissions( uint32_t ulRBARValue ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU == 1 && configUSE_MPU_WRAPPERS_V1 == 0 */
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Setup the Memory Protection Unit (MPU).
- */
+    /**
+     * @brief Setup the Memory Protection Unit (MPU).
+     */
     static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU */
 
 #if ( configENABLE_FPU == 1 )
 
-/**
- * @brief Setup the Floating Point Unit (FPU).
- */
+    /**
+     * @brief Setup the Floating Point Unit (FPU).
+     */
     static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_FPU */
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
 
-/**
- * @brief Configures PACBTI features.
- *
- * This function configures the Pointer Authentication, and Branch Target
- * Identification security features as per the user configuration. It returns
- * the value of the special purpose CONTROL register accordingly, and optionally
- * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
- * architecture based) target supports PACBTI security feature.
- *
- * @param xWriteControlRegister Used to control whether the special purpose
- * CONTROL register should be updated or not.
- *
- * @return CONTROL register value according to the configured PACBTI option.
- */
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    /**
+     * @brief Configures PACBTI features.
+     *
+     * This function configures the Pointer Authentication, and Branch Target
+     * Identification security features as per the user configuration. It returns
+     * the value of the special purpose CONTROL register accordingly, and optionally
+     * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
+     * architecture based) target supports PACBTI security feature.
+     *
+     * @param xWriteControlRegister Used to control whether the special purpose
+     * CONTROL register should be updated or not.
+     *
+     * @return CONTROL register value according to the configured PACBTI option.
+     */
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -491,14 +491,14 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the system call stack so that upon returning from
- * SVC, the system call stack is used.
- *
- * @param pulTaskStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- * @param ucSystemCallNumber The system call number of the system call.
- */
+    /**
+     * @brief Sets up the system call stack so that upon returning from
+     * SVC, the system call stack is used.
+     *
+     * @param pulTaskStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     * @param ucSystemCallNumber The system call number of the system call.
+     */
     void vSystemCallEnter( uint32_t * pulTaskStack,
                            uint32_t ulLR,
                            uint8_t ucSystemCallNumber ) PRIVILEGED_FUNCTION;
@@ -507,22 +507,22 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Raise SVC for exiting from a system call.
- */
+    /**
+     * @brief Raise SVC for exiting from a system call.
+     */
     void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the task stack so that upon returning from
- * SVC, the task stack is used again.
- *
- * @param pulSystemCallStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- */
+    /**
+     * @brief Sets up the task stack so that upon returning from
+     * SVC, the task stack is used again.
+     *
+     * @param pulSystemCallStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     */
     void vSystemCallExit( uint32_t * pulSystemCallStack,
                           uint32_t ulLR ) PRIVILEGED_FUNCTION;
 
@@ -530,21 +530,38 @@
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Checks whether or not the calling task is privileged.
- *
- * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
- */
+    /**
+     * @brief Checks whether or not the calling task is privileged.
+     *
+     * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
+     */
     BaseType_t xPortIsTaskPrivileged( void ) PRIVILEGED_FUNCTION;
 
 #endif /* configENABLE_MPU == 1 */
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /**
+     * @brief Platform/Application-defined function that wakes up the secondary cores.
+     *
+     * @return pdTRUE if the secondary cores were successfully woken up.
+     *         pdFALSE otherwise.
+     */
+    extern BaseType_t configWAKE_SECONDARY_CORES( void );
+
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
+
+/**
+ * @brief Configures interrupt priorities.
+ */
+void vPortConfigureInterruptPriorities( void ) PRIVILEGED_FUNCTION;
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief This variable is set to pdTRUE when the scheduler is started.
- */
+    /**
+     * @brief This variable is set to pdTRUE when the scheduler is started.
+     */
     PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
@@ -553,14 +570,22 @@
  * @brief Each task maintains its own interrupt status in the critical nesting
  * variable.
  */
-PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
+#if ( configNUMBER_OF_CORES == 1 )
+    PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0UL;
+#else /* #if ( configNUMBER_OF_CORES == 1 ) */
+    PRIVILEGED_DATA volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ] = { 0 };
+    /* Flags to check if the secondary cores are ready. */
+    PRIVILEGED_DATA volatile uint8_t ucSecondaryCoresReadyFlags[ configNUMBER_OF_CORES - 1 ] = { 0 };
+    /* Flag to indicate that the primary core has completed its initialisation. */
+    PRIVILEGED_DATA volatile uint8_t ucPrimaryCoreInitDoneFlag = 0;
+ #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #if ( configENABLE_TRUSTZONE == 1 )
 
-/**
- * @brief Saved as part of the task context to indicate which context the
- * task is using on the secure side.
- */
+    /**
+     * @brief Saved as part of the task context to indicate which context the
+     * task is using on the secure side.
+     */
     PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
 #endif /* configENABLE_TRUSTZONE */
 
@@ -579,21 +604,21 @@
 
 #if ( configUSE_TICKLESS_IDLE == 1 )
 
-/**
- * @brief The number of SysTick increments that make up one tick period.
- */
+    /**
+     * @brief The number of SysTick increments that make up one tick period.
+     */
     PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
 
-/**
- * @brief The maximum number of tick periods that can be suppressed is
- * limited by the 24 bit resolution of the SysTick timer.
- */
+    /**
+     * @brief The maximum number of tick periods that can be suppressed is
+     * limited by the 24 bit resolution of the SysTick timer.
+     */
     PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
 
-/**
- * @brief Compensate for the CPU cycles that pass while the SysTick is
- * stopped (low power functionality only).
- */
+    /**
+     * @brief Compensate for the CPU cycles that pass while the SysTick is
+     * stopped (low power functionality only).
+     */
     PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0;
 #endif /* configUSE_TICKLESS_IDLE */
 /*-----------------------------------------------------------*/
@@ -856,7 +881,11 @@
      * should instead call vTaskDelete( NULL ). Artificially force an assert()
      * to be triggered if configASSERT() is defined, then stop here so
      * application writers can catch the error. */
-    configASSERT( ulCriticalNesting == ~0UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == ~0UL );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == ~0UL );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
     portDISABLE_INTERRUPTS();
 
     while( ulDummy == 0 )
@@ -925,64 +954,57 @@
         /* The only permitted number of regions are 8 or 16. */
         configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 16 ) );
 
-        /* Ensure that the configTOTAL_MPU_REGIONS is configured correctly. */
-        configASSERT( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE );
+        /* MAIR0 - Index 0. */
+        portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
+        /* MAIR0 - Index 1. */
+        portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
 
-        /* Check that the MPU is present. */
-        if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
-        {
-            /* MAIR0 - Index 0. */
-            portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
-            /* MAIR0 - Index 1. */
-            portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
+        /* Setup privileged flash as Read Only so that privileged tasks can
+         * read it but not modify. */
+        portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup privileged flash as Read Only so that privileged tasks can
-             * read it but not modify. */
-            portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged flash as Read Only by both privileged and
+         * unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged flash as Read Only by both privileged and
-             * unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged syscalls flash as Read Only by both privileged
+         * and unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged syscalls flash as Read Only by both privileged
-             * and unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup RAM containing kernel data for privileged access only. */
+        portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
+                           ( portMPU_REGION_EXECUTE_NEVER );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup RAM containing kernel data for privileged access only. */
-            portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
-                               ( portMPU_REGION_EXECUTE_NEVER );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Enable mem fault. */
+        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
 
-            /* Enable mem fault. */
-            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
-
-            /* Enable MPU with privileged background access i.e. unmapped
-             * regions have privileged access. */
-            portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
-        }
+        /* Enable MPU with privileged background access i.e. unmapped
+         * regions have privileged access. */
+        portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
     }
 
 #endif /* configENABLE_MPU */
@@ -1027,28 +1049,29 @@
 }
 /*-----------------------------------------------------------*/
 
-void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    portDISABLE_INTERRUPTS();
-    ulCriticalNesting++;
-
-    /* Barriers are normally not required but do ensure the code is
-     * completely within the specified behaviour for the architecture. */
-    __asm volatile ( "dsb" ::: "memory" );
-    __asm volatile ( "isb" );
-}
-/*-----------------------------------------------------------*/
-
-void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    configASSERT( ulCriticalNesting );
-    ulCriticalNesting--;
-
-    if( ulCriticalNesting == 0 )
+#if ( configNUMBER_OF_CORES == 1 )
+    void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
     {
-        portENABLE_INTERRUPTS();
+        portDISABLE_INTERRUPTS();
+        ulCriticalNesting++;
+        /* Barriers are normally not required but do ensure the code is
+        * completely within the specified behaviour for the architecture. */
+        __asm volatile ( "dsb" ::: "memory" );
+        __asm volatile ( "isb" );
     }
-}
+    /*-----------------------------------------------------------*/
+
+    void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
+    {
+        configASSERT( ulCriticalNesting );
+        ulCriticalNesting--;
+
+        if( ulCriticalNesting == 0 )
+        {
+            portENABLE_INTERRUPTS();
+        }
+    }
+#endif /* configNUMBER_OF_CORES == 1 */
 /*-----------------------------------------------------------*/
 
 void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
@@ -1056,6 +1079,10 @@
     uint32_t ulPreviousMask;
 
     ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
+    #if ( configNUMBER_OF_CORES > 1 )
+        UBaseType_t uxSavedInterruptStatus = portENTER_CRITICAL_FROM_ISR();
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     traceISR_ENTER();
     {
         /* Increment the RTOS tick. */
@@ -1070,6 +1097,10 @@
             traceISR_EXIT();
         }
     }
+    #if ( configNUMBER_OF_CORES > 1 )
+        portEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
 }
 /*-----------------------------------------------------------*/
@@ -1078,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1090,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1108,38 +1151,42 @@
 
     switch( ucSVCNumber )
     {
-        #if ( configENABLE_TRUSTZONE == 1 )
-            case portSVC_ALLOCATE_SECURE_CONTEXT:
+    #if ( configENABLE_TRUSTZONE == 1 )
+        case portSVC_ALLOCATE_SECURE_CONTEXT:
 
-                /* R0 contains the stack size passed as parameter to the
-                 * vPortAllocateSecureContext function. */
-                ulR0 = pulCallerStackAddress[ 0 ];
+            /* R0 contains the stack size passed as parameter to the
+             * vPortAllocateSecureContext function. */
+            ulR0 = pulCallerStackAddress[ 0 ];
 
-                #if ( configENABLE_MPU == 1 )
-                {
-                    /* Read the CONTROL register value. */
-                    __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
+            #if ( configENABLE_MPU == 1 )
+            {
+                /* Read the CONTROL register value. */
+                __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
 
-                    /* The task that raised the SVC is privileged if Bit[0]
-                     * in the CONTROL register is 0. */
-                    ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
+                /* The task that raised the SVC is privileged if Bit[0]
+                 * in the CONTROL register is 0. */
+                ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
 
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
-                }
-                #else /* if ( configENABLE_MPU == 1 ) */
-                {
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
-                }
-                #endif /* configENABLE_MPU */
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
+            }
+            #else /* if ( configENABLE_MPU == 1 ) */
+            {
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
+            }
+            #endif /* configENABLE_MPU */
 
-                configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
-                SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
-                break;
+            configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
+            SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
+            break;
 
-            case portSVC_FREE_SECURE_CONTEXT:
-
+        case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
                 /* R0 contains TCB being freed and R1 contains the secure
                  * context handle to be freed. */
                 ulR0 = pulCallerStackAddress[ 0 ];
@@ -1147,51 +1194,62 @@
 
                 /* Free the secure context. */
                 SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
-                break;
-        #endif /* configENABLE_TRUSTZONE */
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
+            break;
+    #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
-            #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
-                case portSVC_RAISE_PRIVILEGE:
+    #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
+        case portSVC_RAISE_PRIVILEGE:
 
-                    /* Only raise the privilege, if the svc was raised from any of
-                     * the system calls. */
-                    if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
-                        ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
-                    {
-                        vRaisePrivilege();
-                    }
-                    break;
-            #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
+            /* Only raise the privilege, if the svc was raised from any of
+             * the system calls. */
+            if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
+                ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
+            {
+                vRaisePrivilege();
+            }
+            break;
+    #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
-            #if ( configENABLE_MPU == 1 )
-                case portSVC_YIELD:
-                    vPortYield();
-                    break;
-            #endif /* configENABLE_MPU == 1 */
+    #if ( configENABLE_MPU == 1 )
+        case portSVC_YIELD:
+            vPortYield();
+            break;
+    #endif /* configENABLE_MPU == 1 */
 
         default:
             /* Incorrect SVC call. */
@@ -1210,7 +1268,7 @@
         extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulSystemCallStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1246,12 +1304,16 @@
         {
             pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1261,20 +1323,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the system call stack for the stack frame. */
-            pulSystemCallStack = pulSystemCallStack - ulStackFrameSize;
+            pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulSystemCallStack[ i ] = pulTaskStack[ i ];
             }
@@ -1310,7 +1372,7 @@
 
             /* Remember the location where we should copy the stack frame when we exit from
              * the system call. */
-            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
+            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
 
             /* Record if the hardware used padding to force the stack pointer
              * to be double word aligned. */
@@ -1360,7 +1422,7 @@
         extern TaskHandle_t pxCurrentTCB;
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulTaskStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1392,12 +1454,16 @@
         {
             pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1407,20 +1473,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the task stack for the stack frame. */
-            pulTaskStack = pulTaskStack - ulStackFrameSize;
+            pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulTaskStack[ i ] = pulSystemCallStack[ i ];
             }
@@ -1518,21 +1584,21 @@
         xMPUSettings->ulContext[ ulIndex ] = 0x11111111; /* r11. */
         ulIndex++;
 
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters;            /* r0. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters; /* r0. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x01010101;                           /* r1. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x01010101; /* r1. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x02020202;                           /* r2. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x02020202; /* r2. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x03030303;                           /* r3. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x03030303; /* r3. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x12121212;                           /* r12. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x12121212; /* r12. */
         ulIndex++;
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) portTASK_RETURN_ADDRESS; /* LR. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode;                  /* PC. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode; /* PC. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR;                     /* xPSR. */
+        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR; /* xPSR. */
         ulIndex++;
 
         #if ( configENABLE_TRUSTZONE == 1 )
@@ -1543,14 +1609,18 @@
         #endif /* configENABLE_TRUSTZONE */
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) ( pxTopOfStack - 8 ); /* PSP with the hardware saved stack. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack;         /* PSPLIM. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack; /* PSPLIM. */
         ulIndex++;
 
         #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
         {
             /* Check PACBTI security feature configuration before pushing the
              * CONTROL register's value on task's TCB. */
-            ulControl = prvConfigurePACBTI( pdFALSE );
+            #if ( configNUMBER_OF_CORES == 1 )
+                ulControl = prvConfigurePACBTI( pdFALSE );
+            #else /* configNUMBER_OF_CORES > 1 */
+                ulControl = vConfigurePACBTI( pdFALSE );
+            #endif /* configNUMBER_OF_CORES */
         }
         #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1615,15 +1685,15 @@
          * interrupt. */
         #if ( portPRELOAD_REGISTERS == 0 )
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
-            pxTopOfStack -= 5;                                       /* R12, R3, R2 and R1. */
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
-            pxTopOfStack -= 9;                                       /* R11..R4, EXC_RETURN. */
+            pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
+            pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */
             *pxTopOfStack = portINITIAL_EXC_RETURN;
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
@@ -1637,42 +1707,42 @@
         }
         #else /* portPRELOAD_REGISTERS */
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x12121212UL;            /* R12. */
+            *pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x03030303UL;            /* R3. */
+            *pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x02020202UL;            /* R2. */
+            *pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x01010101UL;            /* R1. */
+            *pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x11111111UL;            /* R11. */
+            *pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x10101010UL;            /* R10. */
+            *pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x09090909UL;            /* R09. */
+            *pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x08080808UL;            /* R08. */
+            *pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x07070707UL;            /* R07. */
+            *pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x06060606UL;            /* R06. */
+            *pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x05050505UL;            /* R05. */
+            *pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x04040404UL;            /* R04. */
+            *pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04. */
             pxTopOfStack--;
-            *pxTopOfStack = portINITIAL_EXC_RETURN;                  /* EXC_RETURN. */
+            *pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxEndOfStack;            /* Slot used to hold this task's PSPLIM value. */
+            *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
 
             #if ( configENABLE_TRUSTZONE == 1 )
             {
@@ -1739,91 +1809,17 @@
     }
     #endif /* configCHECK_HANDLER_INSTALLATION */
 
-    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
-    {
-        volatile uint32_t ulImplementedPrioBits = 0;
-        volatile uint8_t ucMaxPriorityValue;
-
-        /* Determine the maximum priority from which ISR safe FreeRTOS API
-         * functions can be called. ISR safe functions are those that end in
-         * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
-         * ensure interrupt entry is as fast and simple as possible.
-         *
-         * First, determine the number of priority bits available. Write to all
-         * possible bits in the priority setting for SVCall. */
-        portNVIC_SHPR2_REG = 0xFF000000;
-
-        /* Read the value back to see how many bits stuck. */
-        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
-
-        /* Use the same mask on the maximum system call priority. */
-        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
-
-        /* Check that the maximum system call priority is nonzero after
-         * accounting for the number of priority bits supported by the
-         * hardware. A priority of 0 is invalid because setting the BASEPRI
-         * register to 0 unmasks all interrupts, and interrupts with priority 0
-         * cannot be masked using BASEPRI.
-         * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
-        configASSERT( ucMaxSysCallPriority );
-
-        /* Check that the bits not implemented in hardware are zero in
-         * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
-        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
-
-        /* Calculate the maximum acceptable priority group value for the number
-         * of bits read back. */
-        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
-        {
-            ulImplementedPrioBits++;
-            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
-        }
-
-        if( ulImplementedPrioBits == 8 )
-        {
-            /* When the hardware implements 8 priority bits, there is no way for
-             * the software to configure PRIGROUP to not have sub-priorities. As
-             * a result, the least significant bit is always used for sub-priority
-             * and there are 128 preemption priorities and 2 sub-priorities.
-             *
-             * This may cause some confusion in some cases - for example, if
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
-             * priority interrupts will be masked in Critical Sections as those
-             * are at the same preemption priority. This may appear confusing as
-             * 4 is higher (numerically lower) priority than
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
-             * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
-             * to 4, this confusion does not happen and the behaviour remains the same.
-             *
-             * The following assert ensures that the sub-priority bit in the
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
-             * confusion. */
-            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
-            ulMaxPRIGROUPValue = 0;
-        }
-        else
-        {
-            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
-        }
-
-        /* Shift the priority group value back to its position within the AIRCR
-         * register. */
-        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
-        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
-    }
-    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
-
-    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
-     * the highest priority. */
-    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
-    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
-    portNVIC_SHPR2_REG = 0;
+    vPortConfigureInterruptPriorities();
 
     #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
     {
         /* Set the CONTROL register value based on PACBTI security feature
          * configuration before starting the first task. */
-        ( void ) prvConfigurePACBTI( pdTRUE );
+        #if ( configNUMBER_OF_CORES == 1 )
+            ( void ) prvConfigurePACBTI( pdTRUE );
+        #else /* configNUMBER_OF_CORES > 1 */
+            ( void ) vConfigurePACBTI( pdTRUE );
+        #endif /* configNUMBER_OF_CORES */
     }
     #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1834,12 +1830,47 @@
     }
     #endif /* configENABLE_MPU */
 
-    /* Start the timer that generates the tick ISR. Interrupts are disabled
-     * here already. */
-    vPortSetupTimerInterrupt();
+    #if ( configNUMBER_OF_CORES > 1 )
+        /* Start the timer that generates the tick ISR. Interrupts are disabled
+         * here already. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count for all cores. */
+        for ( uint8_t ucCoreID = 0; ucCoreID < configNUMBER_OF_CORES; ucCoreID++ )
+        {
+            ulCriticalNestings[ ucCoreID ] = 0;
+        }
+        /* Signal that primary core has done all the necessary initialisations. */
+        ucPrimaryCoreInitDoneFlag = 1;
+        /* Wake up secondary cores */
+        BaseType_t xWakeResult = configWAKE_SECONDARY_CORES();
+        configASSERT( xWakeResult == pdTRUE );
 
-    /* Initialize the critical nesting count ready for the first task. */
-    ulCriticalNesting = 0;
+        /* Hold the primary core here until all the secondary cores are ready, this would be achieved only when
+         * all elements of ucSecondaryCoresReadyFlags are set.
+         */
+        while( 1 )
+        {
+            BaseType_t xAllCoresReady = pdTRUE;
+            for( uint8_t ucCoreID = 0; ucCoreID < ( configNUMBER_OF_CORES - 1 ); ucCoreID++ )
+            {
+                if( ucSecondaryCoresReadyFlags[ ucCoreID ] != pdTRUE )
+                {
+                    xAllCoresReady = pdFALSE;
+                    break;
+                }
+                }
+
+            if ( xAllCoresReady == pdTRUE )
+            {
+                break;
+            }
+        }
+    #else /* if ( configNUMBER_OF_CORES > 1 ) */
+        /* Start the timer that generates the tick ISR. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count ready for the first task. */
+        ulCriticalNesting = 0;
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
     {
@@ -1856,7 +1887,11 @@
      * functionality by defining configTASK_RETURN_ADDRESS. Call
      * vTaskSwitchContext() so link time optimization does not remove the
      * symbol. */
-    vTaskSwitchContext();
+    #if ( configNUMBER_OF_CORES > 1 )
+        vTaskSwitchContext( portGET_CORE_ID() );
+    #else
+        vTaskSwitchContext();
+    #endif
     prvTaskExitError();
 
     /* Should not get here. */
@@ -1868,7 +1903,11 @@
 {
     /* Not implemented in ports where there is nothing to return to.
      * Artificially force an assert. */
-    configASSERT( ulCriticalNesting == 1000UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == 1000UL );
+    #else /* if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == 1000UL );
+    #endif /* if ( configNUMBER_OF_CORES == 1 ) */
 }
 /*-----------------------------------------------------------*/
 
@@ -2151,6 +2190,90 @@
 #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
 /*-----------------------------------------------------------*/
 
+void vPortConfigureInterruptPriorities( void ) /* PRIVILEGED_FUNCTION */
+{
+    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
+    {
+        volatile uint32_t ulImplementedPrioBits = 0;
+        volatile uint8_t ucMaxPriorityValue;
+
+        /* Determine the maximum priority from which ISR safe FreeRTOS API
+        * functions can be called. ISR safe functions are those that end in
+        * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
+        * ensure interrupt entry is as fast and simple as possible.
+        *
+        * First, determine the number of priority bits available. Write to all
+        * possible bits in the priority setting for SVCall. */
+        portNVIC_SHPR2_REG = 0xFF000000;
+
+        /* Read the value back to see how many bits stuck. */
+        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
+
+        /* Use the same mask on the maximum system call priority. */
+        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
+
+        /* Check that the maximum system call priority is nonzero after
+        * accounting for the number of priority bits supported by the
+        * hardware. A priority of 0 is invalid because setting the BASEPRI
+        * register to 0 unmasks all interrupts, and interrupts with priority 0
+        * cannot be masked using BASEPRI.
+        * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+        configASSERT( ucMaxSysCallPriority );
+
+        /* Check that the bits not implemented in hardware are zero in
+        * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
+        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
+
+        /* Calculate the maximum acceptable priority group value for the number
+        * of bits read back. */
+        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
+        {
+            ulImplementedPrioBits++;
+            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
+        }
+
+        if( ulImplementedPrioBits == 8 )
+        {
+            /* When the hardware implements 8 priority bits, there is no way for
+            * the software to configure PRIGROUP to not have sub-priorities. As
+            * a result, the least significant bit is always used for sub-priority
+            * and there are 128 preemption priorities and 2 sub-priorities.
+            *
+            * This may cause some confusion in some cases - for example, if
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
+            * priority interrupts will be masked in Critical Sections as those
+            * are at the same preemption priority. This may appear confusing as
+            * 4 is higher (numerically lower) priority than
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
+            * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
+            * to 4, this confusion does not happen and the behaviour remains the same.
+            *
+            * The following assert ensures that the sub-priority bit in the
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
+            * confusion. */
+            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
+            ulMaxPRIGROUPValue = 0;
+        }
+        else
+        {
+            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
+        }
+
+        /* Shift the priority group value back to its position within the AIRCR
+        * register. */
+        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
+        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
+    }
+    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
+
+    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
+    * the highest priority. */
+    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
+    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
+    portNVIC_SHPR2_REG = 0;
+}
+/*-----------------------------------------------------------*/
+
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) )
 
     void vPortGrantAccessToKernelObject( TaskHandle_t xInternalTaskHandle,
@@ -2247,36 +2370,214 @@
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
-
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
-    {
-        uint32_t ulControl = 0x0;
-
-        /* Ensure that PACBTI is implemented. */
-        configASSERT( portID_ISAR5_REG != 0x0 );
-
-        /* Enable UsageFault exception. */
-        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
-
-        #if ( configENABLE_PAC == 1 )
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #else /* configNUMBER_OF_CORES > 1 */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #endif /* configNUMBER_OF_CORES */
         {
-            ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
-        }
-        #endif
+            uint32_t ulControl = 0x0;
 
-        #if ( configENABLE_BTI == 1 )
-        {
-            ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
-        }
-        #endif
+            /* Ensure that PACBTI is implemented. */
+            configASSERT( portID_ISAR5_REG != 0x0 );
 
-        if( xWriteControlRegister == pdTRUE )
-        {
-            __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
-        }
+            /* Enable UsageFault exception. */
+            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
 
-        return ulControl;
-    }
+            #if ( configENABLE_PAC == 1 )
+            {
+                ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
+            }
+            #endif
+
+            #if ( configENABLE_BTI == 1 )
+            {
+                ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
+            }
+            #endif
+
+            if( xWriteControlRegister == pdTRUE )
+            {
+                __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
+            }
+
+            return ulControl;
+        }
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 /*-----------------------------------------------------------*/
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /* Which core owns the lock? */
+    PRIVILEGED_DATA volatile uint32_t ulOwnedByCore[ portMAX_CORE_COUNT ];
+    /* Lock count a core owns. */
+    PRIVILEGED_DATA volatile uint32_t ulRecursionCountByLock[ eLockCount ];
+    /* Index 0 is used for ISR lock and Index 1 is used for task lock. */
+    PRIVILEGED_DATA volatile uint32_t ulGateWord[ eLockCount ];
+
+    __attribute__((weak)) void vInterruptCore( uint8_t ucCoreID )
+    {
+        /* Default weak stub - platform specific implementation may override. */
+        ( void ) ucCoreID;
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline void prvSpinUnlock( volatile uint32_t * ulLock )
+    {
+        /* Conservative unlock: preserve original barriers for broad HW/FVP. */
+        __asm volatile (
+            "dmb sy         \n"
+            "mov r1, #0     \n"
+            "str r1, [%0]   \n"
+            "sev            \n"
+            "dsb            \n"
+            "isb            \n"
+            :
+            : "r" ( ulLock )
+            : "memory", "r1"
+        );
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline uint32_t prvSpinTrylock( volatile uint32_t * ulLock )
+    {
+        /*
+         * Conservative ldrex/strex trylock:
+         * - Return 1 immediately if busy, clearing exclusive state (CLREX).
+         * - Retry strex only on spurious failure when observed free.
+         * - DMB on success to preserve expected acquire semantics.
+         */
+        uint32_t ulVal;
+        uint32_t ulStatus;
+
+        __asm volatile (
+            " ldrex %0, [%1]   \n"
+            : "=r" ( ulVal )
+            : "r" ( ulLock )
+            : "memory"
+        );
+
+        if( ulVal != 0U )
+        {
+            __asm volatile ("clrex" ::: "memory");
+            return 1U;
+        }
+
+        __asm volatile (
+            " strex %0, %2, [%1]   \n"
+            : "=&r" ( ulStatus )
+            : "r" ( ulLock ), "r" (1U)
+            : "memory"
+        );
+
+        if( ulStatus != 0U )
+        {
+            return 1U;
+        }
+        __asm volatile ( "dmb" ::: "memory" );
+        return 0U;
+    }
+
+
+/*-----------------------------------------------------------*/
+
+    /* Read 32b value shared between cores. */
+    static inline uint32_t prvGet32( volatile uint32_t * x )
+    {
+        __asm( "dsb" );
+        return *x;
+    }
+
+/*-----------------------------------------------------------*/
+
+    /* Write 32b value shared between cores. */
+    static inline void prvSet32( volatile uint32_t * x,
+                                 uint32_t value )
+    {
+        *x = value;
+        __asm( "dsb" );
+    }
+
+/*-----------------------------------------------------------*/
+
+    void vPortRecursiveLock( uint8_t ucCoreID,
+                             ePortRTOSLock eLockNum,
+                             BaseType_t uxAcquire )
+    {
+        /* Validate the core ID and lock number. */
+        configASSERT( ucCoreID < portMAX_CORE_COUNT );
+        configASSERT( eLockNum < eLockCount );
+
+        uint32_t ulLockBit = 1u << eLockNum;
+
+        /* Lock acquire */
+        if( uxAcquire )
+        {
+            /* Check if spinlock is available. */
+            /* If spinlock is not available check if the core owns the lock. */
+            /* If the core owns the lock wait increment the lock count by the core. */
+            /* If core does not own the lock wait for the spinlock. */
+            if( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+            {
+                /* Check if the core owns the spinlock. */
+                if( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit )
+                {
+                    configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != portUINT32_MAX );
+                    prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) + 1 ) );
+                    return;
+                }
+
+                /* Preload the gate word into the cache. */
+                uint32_t dummy = ulGateWord[ eLockNum ];
+                dummy++;
+
+                while( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+                {
+                    __asm volatile ( "wfe" );
+                }
+            }
+
+            /* Add barrier to ensure lock is taken before we proceed. */
+            __asm volatile( "dmb sy" ::: "memory" );
+
+            /* Assert the lock count is 0 when the spinlock is free and is acquired. */
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) == 0 );
+
+            /* Set lock count as 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], 1 );
+            /* Set ulOwnedByCore. */
+            prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) | ulLockBit ) );
+        }
+        /* Lock release. */
+        else
+        {
+            /* Assert the lock is not free already. */
+            configASSERT( ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit ) != 0 );
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != 0 );
+
+            /* Reduce ulRecursionCountByLock by 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) - 1 ) );
+
+            if( !prvGet32( &ulRecursionCountByLock[ eLockNum ] ) )
+            {
+                prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ~ulLockBit ) );
+                prvSpinUnlock( &ulGateWord[ eLockNum ] );
+                /* Add barrier to ensure lock status is reflected before we proceed. */
+                __asm volatile( "dmb sy" ::: "memory" );
+            }
+        }
+    }
+
+/*-----------------------------------------------------------*/
+
+    uint8_t ucPortGetCoreID( void )
+    {
+        return *(volatile uint8_t *)(configCORE_ID_REGISTER);
+    }
+
+/*-----------------------------------------------------------*/
+
+#endif /* if( configNUMBER_OF_CORES > 1 ) */
diff --git a/Source/portable/GCC/ARM_CM55/non_secure/portasm.c b/Source/portable/GCC/ARM_CM55/non_secure/portasm.c
index bdee088..6bc070d 100644
--- a/Source/portable/GCC/ARM_CM55/non_secure/portasm.c
+++ b/Source/portable/GCC/ARM_CM55/non_secure/portasm.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  * Copyright 2024 Arm Limited and/or its affiliates
  * <open-source-office@arm.com>
@@ -46,6 +46,16 @@
 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
 
 #if ( configENABLE_MPU == 1 )
+    #if ( configENABLE_PAC == 1 )
+        #define SECURE_CONTEXT_OFFSET   -36
+    #else
+        #define SECURE_CONTEXT_OFFSET   -20
+    #endif
+#else
+    #define SECURE_CONTEXT_OFFSET       0
+#endif
+
+#if ( configENABLE_MPU == 1 )
 
     void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
     {
@@ -609,13 +619,13 @@
     (
         "   .syntax unified                                 \n"
         "                                                   \n"
-        "   ldr r2, [r0]                                    \n" /* The first item in the TCB is the top of the stack. */
-        "   ldr r1, [r2]                                    \n" /* The first item on the stack is the task's xSecureContext. */
+        "   ldr r2, [r0]                                    \n" /* The first item in the TCB is the stored context location. */
+        "   ldr r1, [r2, %0]                                \n" /* Read xSecureContext from the task's context. */
         "   cmp r1, #0                                      \n" /* Raise svc if task's xSecureContext is not NULL. */
         "   it ne                                           \n"
-        "   svcne %0                                        \n" /* Secure context is freed in the supervisor call. */
+        "   svcne %1                                        \n" /* Secure context is freed in the supervisor call. */
         "   bx lr                                           \n" /* Return. */
-        ::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
+        ::"i" ( SECURE_CONTEXT_OFFSET ), "i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
     );
 }
 /*-----------------------------------------------------------*/
diff --git a/Source/portable/GCC/ARM_CM55/non_secure/portasm.h b/Source/portable/GCC/ARM_CM55/non_secure/portasm.h
index 53b4b6e..b4b545f 100644
--- a/Source/portable/GCC/ARM_CM55/non_secure/portasm.h
+++ b/Source/portable/GCC/ARM_CM55/non_secure/portasm.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM55/non_secure/portmacro.h b/Source/portable/GCC/ARM_CM55/non_secure/portmacro.h
index 11a2777..11d6470 100644
--- a/Source/portable/GCC/ARM_CM55/non_secure/portmacro.h
+++ b/Source/portable/GCC/ARM_CM55/non_secure/portmacro.h
@@ -1,6 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * Copyright 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -57,6 +58,7 @@
 #define portHAS_ARMV8M_MAIN_EXTENSION    1
 #define portARMV8M_MINOR_VERSION         1
 #define portDONT_DISCARD                 __attribute__( ( used ) )
+#define portVALIDATED_FOR_SMP            0
 /*-----------------------------------------------------------*/
 
 /* ARMv8-M common port configurations. */
diff --git a/Source/portable/GCC/ARM_CM55/non_secure/portmacrocommon.h b/Source/portable/GCC/ARM_CM55/non_secure/portmacrocommon.h
index 2dfac6a..c34fdee 100644
--- a/Source/portable/GCC/ARM_CM55/non_secure/portmacrocommon.h
+++ b/Source/portable/GCC/ARM_CM55/non_secure/portmacrocommon.h
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -59,6 +58,19 @@
     #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h.  Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
 #endif /* configENABLE_TRUSTZONE */
 
+#if ( configNUMBER_OF_CORES > 1 )
+    #if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 )
+        #error "Multi-core SMP is currently only validated for Cortex-M33 non-TrustZone non-MPU port."
+    #endif /* if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 ) ) */
+
+    #ifndef configCORE_ID_REGISTER
+        #error "configCORE_ID_REGISTER must be defined to the address of the register used to identify the core executing the code."
+    #endif /* ifndef configCORE_ID_REGISTER */
+
+    #ifndef configWAKE_SECONDARY_CORES
+        #error "configWAKE_SECONDARY_CORES must be defined to a function that wakes the secondary cores."
+    #endif /* ifndef configWAKE_SECONDARY_CORES */
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -428,10 +440,26 @@
 /**
  * @brief Critical section management.
  */
+
+#define portSET_INTERRUPT_MASK()                  ulSetInterruptMask()
+#define portCLEAR_INTERRUPT_MASK( x )             vClearInterruptMask( x )
 #define portSET_INTERRUPT_MASK_FROM_ISR()         ulSetInterruptMask()
 #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x )    vClearInterruptMask( x )
-#define portENTER_CRITICAL()                      vPortEnterCritical()
-#define portEXIT_CRITICAL()                       vPortExitCritical()
+
+#if ( configNUMBER_OF_CORES == 1 )
+    #define portENTER_CRITICAL()                      vPortEnterCritical()
+    #define portEXIT_CRITICAL()                       vPortExitCritical()
+#else /* ( configNUMBER_OF_CORES == 1 ) */
+    extern void vTaskEnterCritical( void );
+    extern void vTaskExitCritical( void );
+    extern UBaseType_t vTaskEnterCriticalFromISR( void );
+    extern void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus );
+
+    #define portENTER_CRITICAL()                      vTaskEnterCritical()
+    #define portEXIT_CRITICAL()                       vTaskExitCritical()
+    #define portENTER_CRITICAL_FROM_ISR()             vTaskEnterCriticalFromISR()
+    #define portEXIT_CRITICAL_FROM_ISR( x )           vTaskExitCriticalFromISR( x )
+#endif /* if ( configNUMBER_OF_CORES != 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -526,7 +554,7 @@
 /* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION
  * based on whether or not Mainline extension is implemented. */
 #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
-    #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 )
+    #if ( ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) && ( configNUMBER_OF_CORES == 1 ) )
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    1
     #else
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    0
@@ -573,6 +601,44 @@
 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
 /*-----------------------------------------------------------*/
 
+
+#if ( configNUMBER_OF_CORES > 1 )
+    typedef enum
+    {
+        eIsrLock = 0,
+        eTaskLock,
+        eLockCount
+    } ePortRTOSLock;
+
+    extern volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ];
+    extern void vPortRecursiveLock( uint8_t ucCoreID,
+                                    ePortRTOSLock eLockNum,
+                                    BaseType_t uxAcquire );
+    extern uint8_t ucPortGetCoreID( void );
+    extern void vInterruptCore( uint8_t ucCoreID );
+
+    #define portGET_CORE_ID()                                  ucPortGetCoreID()
+
+    #define portGET_CRITICAL_NESTING_COUNT( xCoreID )          ( ulCriticalNestings[ ( uint8_t ) xCoreID ] )
+    #define portSET_CRITICAL_NESTING_COUNT( xCoreID, x )       ( ulCriticalNestings[ ( uint8_t ) xCoreID ] = ( x ) )
+    #define portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]++ )
+    #define portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]-- )
+
+    #define portMAX_CORE_COUNT                                 ( configNUMBER_OF_CORES )
+
+    #define portYIELD_CORE( xCoreID )                          vInterruptCore( xCoreID )
+
+    #define portRELEASE_ISR_LOCK( xCoreID )                    vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdFALSE )
+    #define portGET_ISR_LOCK( xCoreID )                        vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdTRUE )
+
+    #define portRELEASE_TASK_LOCK( xCoreID )                   vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdFALSE )
+    #define portGET_TASK_LOCK( xCoreID )                       vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdTRUE )
+
+    #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* ( configENABLE_PAC == 1 || configENABLE_BTI == 1 ) */
+#endif
+
 /* *INDENT-OFF* */
 #ifdef __cplusplus
     }
diff --git a/Source/portable/GCC/ARM_CM55/secure/secure_context.c b/Source/portable/GCC/ARM_CM55/secure/secure_context.c
index 62bcfa1..2dae022 100644
--- a/Source/portable/GCC/ARM_CM55/secure/secure_context.c
+++ b/Source/portable/GCC/ARM_CM55/secure/secure_context.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -213,8 +213,19 @@
         /* Were we able to get a free context? */
         if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS )
         {
-            /* Allocate the stack space. */
-            pucStackMemory = pvPortMalloc( ulSecureStackSize + securecontextSTACK_SEAL_SIZE );
+            /* Allocate the stack space if possible. */
+            if( ( ulSecureStackSize < securecontextSTACK_SEAL_SIZE ) ||
+                ( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) )
+            {
+                /* Reject stacks that are too small (the CONTROL word would be
+                 * written before the allocation, corrupting the secure heap)
+                 * and sizes that would overflow when the seal size is added. */
+                pucStackMemory = NULL;
+            }
+            else
+            {
+                pucStackMemory = pvPortMalloc( ulSecureStackSize + securecontextSTACK_SEAL_SIZE );
+            }
 
             if( pucStackMemory != NULL )
             {
@@ -279,9 +290,12 @@
                                                               void * pvTaskHandle )
 {
     uint32_t ulIPSR, ulSecureContextIndex;
+    uint8_t * pucStackLimit;
 
-    /* Read the Interrupt Program Status Register (IPSR) value. */
+    /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
+     * Register (PSPLIM) value. */
     secureportREAD_IPSR( ulIPSR );
+    secureportREAD_PSPLIM( pucStackLimit );
 
     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
      * when the processor is running in the Thread Mode. */
@@ -293,8 +307,14 @@
             ulSecureContextIndex = xSecureContextHandle - 1UL;
 
             /* Ensure that the secure context being deleted is associated with
-             * the task. */
-            if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
+             * the task and is NOT the currently-loaded context. Freeing a
+             * context whose stack is currently loaded in PSPLIM would leave the
+             * running task referencing freed secure memory (use-after-free).
+             * pvTaskHandle is supplied by the non-secure side and is untrusted,
+             * so it is used only as an additional ownership match, not as
+             * authority. */
+            if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) &&
+                ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) )
             {
                 /* Free the stack space. */
                 vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
@@ -342,7 +362,7 @@
 
         secureportREAD_PSPLIM( pucStackLimit );
 
-        /* Ensure that task's context is loaded and the task is saving it's own
+        /* Ensure that task's context is loaded and the task is saving its own
          * context. */
         if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) &&
             ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) )
diff --git a/Source/portable/GCC/ARM_CM55/secure/secure_context.h b/Source/portable/GCC/ARM_CM55/secure/secure_context.h
index 8b93857..51dd823 100644
--- a/Source/portable/GCC/ARM_CM55/secure/secure_context.h
+++ b/Source/portable/GCC/ARM_CM55/secure/secure_context.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM55/secure/secure_context_port.c b/Source/portable/GCC/ARM_CM55/secure/secure_context_port.c
index 11d8e1b..ef5cbf7 100644
--- a/Source/portable/GCC/ARM_CM55/secure/secure_context_port.c
+++ b/Source/portable/GCC/ARM_CM55/secure/secure_context_port.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM55/secure/secure_heap.c b/Source/portable/GCC/ARM_CM55/secure/secure_heap.c
index b0e83b4..58226bf 100644
--- a/Source/portable/GCC/ARM_CM55/secure/secure_heap.c
+++ b/Source/portable/GCC/ARM_CM55/secure/secure_heap.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM55/secure/secure_heap.h b/Source/portable/GCC/ARM_CM55/secure/secure_heap.h
index 61a96da..906fa24 100644
--- a/Source/portable/GCC/ARM_CM55/secure/secure_heap.h
+++ b/Source/portable/GCC/ARM_CM55/secure/secure_heap.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM55/secure/secure_init.c b/Source/portable/GCC/ARM_CM55/secure/secure_init.c
index f7f7e67..6996692 100644
--- a/Source/portable/GCC/ARM_CM55/secure/secure_init.c
+++ b/Source/portable/GCC/ARM_CM55/secure/secure_init.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM55/secure/secure_init.h b/Source/portable/GCC/ARM_CM55/secure/secure_init.h
index 46ffbd9..4e7bd40 100644
--- a/Source/portable/GCC/ARM_CM55/secure/secure_init.h
+++ b/Source/portable/GCC/ARM_CM55/secure/secure_init.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM55/secure/secure_port_macros.h b/Source/portable/GCC/ARM_CM55/secure/secure_port_macros.h
index 34494e1..72774eb 100644
--- a/Source/portable/GCC/ARM_CM55/secure/secure_port_macros.h
+++ b/Source/portable/GCC/ARM_CM55/secure/secure_port_macros.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM55_NTZ/non_secure/mpu_wrappers_v2_asm.c b/Source/portable/GCC/ARM_CM55_NTZ/non_secure/mpu_wrappers_v2_asm.c
index 8504ddd..63d1b52 100644
--- a/Source/portable/GCC/ARM_CM55_NTZ/non_secure/mpu_wrappers_v2_asm.c
+++ b/Source/portable/GCC/ARM_CM55_NTZ/non_secure/mpu_wrappers_v2_asm.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM55_NTZ/non_secure/port.c b/Source/portable/GCC/ARM_CM55_NTZ/non_secure/port.c
index f16a343..007150c 100644
--- a/Source/portable/GCC/ARM_CM55_NTZ/non_secure/port.c
+++ b/Source/portable/GCC/ARM_CM55_NTZ/non_secure/port.c
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024-2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -145,13 +144,13 @@
 /**
  * @brief Constants required to manipulate the FPU.
  */
-#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 )              /* Coprocessor Access Control Register. */
+#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */
 #define portCPACR_CP10_VALUE    ( 3UL )
 #define portCPACR_CP11_VALUE    portCPACR_CP10_VALUE
 #define portCPACR_CP10_POS      ( 20UL )
 #define portCPACR_CP11_POS      ( 22UL )
 
-#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 )              /* Floating Point Context Control Register. */
+#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
 #define portFPCCR_ASPEN_POS     ( 31UL )
 #define portFPCCR_ASPEN_MASK    ( 1UL << portFPCCR_ASPEN_POS )
 #define portFPCCR_LSPEN_POS     ( 30UL )
@@ -188,8 +187,8 @@
 #define portMPU_MAIR0_REG                       ( *( ( volatile uint32_t * ) 0xe000edc0 ) )
 #define portMPU_MAIR1_REG                       ( *( ( volatile uint32_t * ) 0xe000edc4 ) )
 
-#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
-#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
+#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
+#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
 
 #define portMPU_RBAR_ACCESS_PERMISSIONS_MASK    ( 3UL << 1UL )
 
@@ -230,8 +229,8 @@
 
 #if ( portARMV8M_MINOR_VERSION >= 1 )
 
-/* Enable Privileged eXecute Never MPU attribute for the selected memory
- * region. */
+    /* Enable Privileged eXecute Never MPU attribute for the selected memory
+     * region. */
     #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER    ( 1UL << 4UL )
 #endif /* portARMV8M_MINOR_VERSION >= 1 */
 
@@ -241,9 +240,6 @@
 /* Enable MPU. */
 #define portMPU_ENABLE_BIT                    ( 1UL << 0UL )
 
-/* Expected value of the portMPU_TYPE register. */
-#define portEXPECTED_MPU_TYPE_VALUE           ( configTOTAL_MPU_REGIONS << 8UL )
-
 /* Extract first address of the MPU region as encoded in the
  * RBAR (Region Base Address Register) value. */
 #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@@ -291,37 +287,37 @@
 
 #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         FD
- * 1111 1111  1111 1111  1111 1111  1111 1101
- *
- * Bit[6] - 1 --> The exception was taken from the Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 1 --> The exception was taken to the Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         FD
+     * 1111 1111  1111 1111  1111 1111  1111 1101
+     *
+     * Bit[6] - 1 --> The exception was taken from the Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 1 --> The exception was taken to the Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xfffffffd )
 #else
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         BC
- * 1111 1111  1111 1111  1111 1111  1011 1100
- *
- * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         BC
+     * 1111 1111  1111 1111  1111 1111  1011 1100
+     *
+     * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xffffffbc )
 #endif /* configRUN_FREERTOS_SECURE_ONLY */
 
@@ -401,50 +397,54 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Extract MPU region's access permissions from the Region Base Address
- * Register (RBAR) value.
- *
- * @param ulRBARValue RBAR value for the MPU region.
- *
- * @return uint32_t Access permissions.
- */
+    /**
+     * @brief Extract MPU region's access permissions from the Region Base Address
+     * Register (RBAR) value.
+     *
+     * @param ulRBARValue RBAR value for the MPU region.
+     *
+     * @return uint32_t Access permissions.
+     */
     static uint32_t prvGetRegionAccessPermissions( uint32_t ulRBARValue ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU == 1 && configUSE_MPU_WRAPPERS_V1 == 0 */
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Setup the Memory Protection Unit (MPU).
- */
+    /**
+     * @brief Setup the Memory Protection Unit (MPU).
+     */
     static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU */
 
 #if ( configENABLE_FPU == 1 )
 
-/**
- * @brief Setup the Floating Point Unit (FPU).
- */
+    /**
+     * @brief Setup the Floating Point Unit (FPU).
+     */
     static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_FPU */
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
 
-/**
- * @brief Configures PACBTI features.
- *
- * This function configures the Pointer Authentication, and Branch Target
- * Identification security features as per the user configuration. It returns
- * the value of the special purpose CONTROL register accordingly, and optionally
- * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
- * architecture based) target supports PACBTI security feature.
- *
- * @param xWriteControlRegister Used to control whether the special purpose
- * CONTROL register should be updated or not.
- *
- * @return CONTROL register value according to the configured PACBTI option.
- */
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    /**
+     * @brief Configures PACBTI features.
+     *
+     * This function configures the Pointer Authentication, and Branch Target
+     * Identification security features as per the user configuration. It returns
+     * the value of the special purpose CONTROL register accordingly, and optionally
+     * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
+     * architecture based) target supports PACBTI security feature.
+     *
+     * @param xWriteControlRegister Used to control whether the special purpose
+     * CONTROL register should be updated or not.
+     *
+     * @return CONTROL register value according to the configured PACBTI option.
+     */
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -491,14 +491,14 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the system call stack so that upon returning from
- * SVC, the system call stack is used.
- *
- * @param pulTaskStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- * @param ucSystemCallNumber The system call number of the system call.
- */
+    /**
+     * @brief Sets up the system call stack so that upon returning from
+     * SVC, the system call stack is used.
+     *
+     * @param pulTaskStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     * @param ucSystemCallNumber The system call number of the system call.
+     */
     void vSystemCallEnter( uint32_t * pulTaskStack,
                            uint32_t ulLR,
                            uint8_t ucSystemCallNumber ) PRIVILEGED_FUNCTION;
@@ -507,22 +507,22 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Raise SVC for exiting from a system call.
- */
+    /**
+     * @brief Raise SVC for exiting from a system call.
+     */
     void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the task stack so that upon returning from
- * SVC, the task stack is used again.
- *
- * @param pulSystemCallStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- */
+    /**
+     * @brief Sets up the task stack so that upon returning from
+     * SVC, the task stack is used again.
+     *
+     * @param pulSystemCallStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     */
     void vSystemCallExit( uint32_t * pulSystemCallStack,
                           uint32_t ulLR ) PRIVILEGED_FUNCTION;
 
@@ -530,21 +530,38 @@
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Checks whether or not the calling task is privileged.
- *
- * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
- */
+    /**
+     * @brief Checks whether or not the calling task is privileged.
+     *
+     * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
+     */
     BaseType_t xPortIsTaskPrivileged( void ) PRIVILEGED_FUNCTION;
 
 #endif /* configENABLE_MPU == 1 */
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /**
+     * @brief Platform/Application-defined function that wakes up the secondary cores.
+     *
+     * @return pdTRUE if the secondary cores were successfully woken up.
+     *         pdFALSE otherwise.
+     */
+    extern BaseType_t configWAKE_SECONDARY_CORES( void );
+
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
+
+/**
+ * @brief Configures interrupt priorities.
+ */
+void vPortConfigureInterruptPriorities( void ) PRIVILEGED_FUNCTION;
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief This variable is set to pdTRUE when the scheduler is started.
- */
+    /**
+     * @brief This variable is set to pdTRUE when the scheduler is started.
+     */
     PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
@@ -553,14 +570,22 @@
  * @brief Each task maintains its own interrupt status in the critical nesting
  * variable.
  */
-PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
+#if ( configNUMBER_OF_CORES == 1 )
+    PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0UL;
+#else /* #if ( configNUMBER_OF_CORES == 1 ) */
+    PRIVILEGED_DATA volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ] = { 0 };
+    /* Flags to check if the secondary cores are ready. */
+    PRIVILEGED_DATA volatile uint8_t ucSecondaryCoresReadyFlags[ configNUMBER_OF_CORES - 1 ] = { 0 };
+    /* Flag to indicate that the primary core has completed its initialisation. */
+    PRIVILEGED_DATA volatile uint8_t ucPrimaryCoreInitDoneFlag = 0;
+ #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #if ( configENABLE_TRUSTZONE == 1 )
 
-/**
- * @brief Saved as part of the task context to indicate which context the
- * task is using on the secure side.
- */
+    /**
+     * @brief Saved as part of the task context to indicate which context the
+     * task is using on the secure side.
+     */
     PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
 #endif /* configENABLE_TRUSTZONE */
 
@@ -579,21 +604,21 @@
 
 #if ( configUSE_TICKLESS_IDLE == 1 )
 
-/**
- * @brief The number of SysTick increments that make up one tick period.
- */
+    /**
+     * @brief The number of SysTick increments that make up one tick period.
+     */
     PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
 
-/**
- * @brief The maximum number of tick periods that can be suppressed is
- * limited by the 24 bit resolution of the SysTick timer.
- */
+    /**
+     * @brief The maximum number of tick periods that can be suppressed is
+     * limited by the 24 bit resolution of the SysTick timer.
+     */
     PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
 
-/**
- * @brief Compensate for the CPU cycles that pass while the SysTick is
- * stopped (low power functionality only).
- */
+    /**
+     * @brief Compensate for the CPU cycles that pass while the SysTick is
+     * stopped (low power functionality only).
+     */
     PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0;
 #endif /* configUSE_TICKLESS_IDLE */
 /*-----------------------------------------------------------*/
@@ -856,7 +881,11 @@
      * should instead call vTaskDelete( NULL ). Artificially force an assert()
      * to be triggered if configASSERT() is defined, then stop here so
      * application writers can catch the error. */
-    configASSERT( ulCriticalNesting == ~0UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == ~0UL );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == ~0UL );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
     portDISABLE_INTERRUPTS();
 
     while( ulDummy == 0 )
@@ -925,64 +954,57 @@
         /* The only permitted number of regions are 8 or 16. */
         configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 16 ) );
 
-        /* Ensure that the configTOTAL_MPU_REGIONS is configured correctly. */
-        configASSERT( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE );
+        /* MAIR0 - Index 0. */
+        portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
+        /* MAIR0 - Index 1. */
+        portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
 
-        /* Check that the MPU is present. */
-        if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
-        {
-            /* MAIR0 - Index 0. */
-            portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
-            /* MAIR0 - Index 1. */
-            portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
+        /* Setup privileged flash as Read Only so that privileged tasks can
+         * read it but not modify. */
+        portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup privileged flash as Read Only so that privileged tasks can
-             * read it but not modify. */
-            portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged flash as Read Only by both privileged and
+         * unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged flash as Read Only by both privileged and
-             * unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged syscalls flash as Read Only by both privileged
+         * and unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged syscalls flash as Read Only by both privileged
-             * and unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup RAM containing kernel data for privileged access only. */
+        portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
+                           ( portMPU_REGION_EXECUTE_NEVER );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup RAM containing kernel data for privileged access only. */
-            portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
-                               ( portMPU_REGION_EXECUTE_NEVER );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Enable mem fault. */
+        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
 
-            /* Enable mem fault. */
-            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
-
-            /* Enable MPU with privileged background access i.e. unmapped
-             * regions have privileged access. */
-            portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
-        }
+        /* Enable MPU with privileged background access i.e. unmapped
+         * regions have privileged access. */
+        portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
     }
 
 #endif /* configENABLE_MPU */
@@ -1027,28 +1049,29 @@
 }
 /*-----------------------------------------------------------*/
 
-void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    portDISABLE_INTERRUPTS();
-    ulCriticalNesting++;
-
-    /* Barriers are normally not required but do ensure the code is
-     * completely within the specified behaviour for the architecture. */
-    __asm volatile ( "dsb" ::: "memory" );
-    __asm volatile ( "isb" );
-}
-/*-----------------------------------------------------------*/
-
-void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    configASSERT( ulCriticalNesting );
-    ulCriticalNesting--;
-
-    if( ulCriticalNesting == 0 )
+#if ( configNUMBER_OF_CORES == 1 )
+    void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
     {
-        portENABLE_INTERRUPTS();
+        portDISABLE_INTERRUPTS();
+        ulCriticalNesting++;
+        /* Barriers are normally not required but do ensure the code is
+        * completely within the specified behaviour for the architecture. */
+        __asm volatile ( "dsb" ::: "memory" );
+        __asm volatile ( "isb" );
     }
-}
+    /*-----------------------------------------------------------*/
+
+    void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
+    {
+        configASSERT( ulCriticalNesting );
+        ulCriticalNesting--;
+
+        if( ulCriticalNesting == 0 )
+        {
+            portENABLE_INTERRUPTS();
+        }
+    }
+#endif /* configNUMBER_OF_CORES == 1 */
 /*-----------------------------------------------------------*/
 
 void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
@@ -1056,6 +1079,10 @@
     uint32_t ulPreviousMask;
 
     ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
+    #if ( configNUMBER_OF_CORES > 1 )
+        UBaseType_t uxSavedInterruptStatus = portENTER_CRITICAL_FROM_ISR();
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     traceISR_ENTER();
     {
         /* Increment the RTOS tick. */
@@ -1070,6 +1097,10 @@
             traceISR_EXIT();
         }
     }
+    #if ( configNUMBER_OF_CORES > 1 )
+        portEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
 }
 /*-----------------------------------------------------------*/
@@ -1078,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1090,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1108,38 +1151,42 @@
 
     switch( ucSVCNumber )
     {
-        #if ( configENABLE_TRUSTZONE == 1 )
-            case portSVC_ALLOCATE_SECURE_CONTEXT:
+    #if ( configENABLE_TRUSTZONE == 1 )
+        case portSVC_ALLOCATE_SECURE_CONTEXT:
 
-                /* R0 contains the stack size passed as parameter to the
-                 * vPortAllocateSecureContext function. */
-                ulR0 = pulCallerStackAddress[ 0 ];
+            /* R0 contains the stack size passed as parameter to the
+             * vPortAllocateSecureContext function. */
+            ulR0 = pulCallerStackAddress[ 0 ];
 
-                #if ( configENABLE_MPU == 1 )
-                {
-                    /* Read the CONTROL register value. */
-                    __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
+            #if ( configENABLE_MPU == 1 )
+            {
+                /* Read the CONTROL register value. */
+                __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
 
-                    /* The task that raised the SVC is privileged if Bit[0]
-                     * in the CONTROL register is 0. */
-                    ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
+                /* The task that raised the SVC is privileged if Bit[0]
+                 * in the CONTROL register is 0. */
+                ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
 
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
-                }
-                #else /* if ( configENABLE_MPU == 1 ) */
-                {
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
-                }
-                #endif /* configENABLE_MPU */
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
+            }
+            #else /* if ( configENABLE_MPU == 1 ) */
+            {
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
+            }
+            #endif /* configENABLE_MPU */
 
-                configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
-                SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
-                break;
+            configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
+            SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
+            break;
 
-            case portSVC_FREE_SECURE_CONTEXT:
-
+        case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
                 /* R0 contains TCB being freed and R1 contains the secure
                  * context handle to be freed. */
                 ulR0 = pulCallerStackAddress[ 0 ];
@@ -1147,51 +1194,62 @@
 
                 /* Free the secure context. */
                 SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
-                break;
-        #endif /* configENABLE_TRUSTZONE */
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
+            break;
+    #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
-            #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
-                case portSVC_RAISE_PRIVILEGE:
+    #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
+        case portSVC_RAISE_PRIVILEGE:
 
-                    /* Only raise the privilege, if the svc was raised from any of
-                     * the system calls. */
-                    if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
-                        ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
-                    {
-                        vRaisePrivilege();
-                    }
-                    break;
-            #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
+            /* Only raise the privilege, if the svc was raised from any of
+             * the system calls. */
+            if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
+                ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
+            {
+                vRaisePrivilege();
+            }
+            break;
+    #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
-            #if ( configENABLE_MPU == 1 )
-                case portSVC_YIELD:
-                    vPortYield();
-                    break;
-            #endif /* configENABLE_MPU == 1 */
+    #if ( configENABLE_MPU == 1 )
+        case portSVC_YIELD:
+            vPortYield();
+            break;
+    #endif /* configENABLE_MPU == 1 */
 
         default:
             /* Incorrect SVC call. */
@@ -1210,7 +1268,7 @@
         extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulSystemCallStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1246,12 +1304,16 @@
         {
             pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1261,20 +1323,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the system call stack for the stack frame. */
-            pulSystemCallStack = pulSystemCallStack - ulStackFrameSize;
+            pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulSystemCallStack[ i ] = pulTaskStack[ i ];
             }
@@ -1310,7 +1372,7 @@
 
             /* Remember the location where we should copy the stack frame when we exit from
              * the system call. */
-            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
+            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
 
             /* Record if the hardware used padding to force the stack pointer
              * to be double word aligned. */
@@ -1360,7 +1422,7 @@
         extern TaskHandle_t pxCurrentTCB;
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulTaskStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1392,12 +1454,16 @@
         {
             pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1407,20 +1473,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the task stack for the stack frame. */
-            pulTaskStack = pulTaskStack - ulStackFrameSize;
+            pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulTaskStack[ i ] = pulSystemCallStack[ i ];
             }
@@ -1518,21 +1584,21 @@
         xMPUSettings->ulContext[ ulIndex ] = 0x11111111; /* r11. */
         ulIndex++;
 
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters;            /* r0. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters; /* r0. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x01010101;                           /* r1. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x01010101; /* r1. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x02020202;                           /* r2. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x02020202; /* r2. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x03030303;                           /* r3. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x03030303; /* r3. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x12121212;                           /* r12. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x12121212; /* r12. */
         ulIndex++;
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) portTASK_RETURN_ADDRESS; /* LR. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode;                  /* PC. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode; /* PC. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR;                     /* xPSR. */
+        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR; /* xPSR. */
         ulIndex++;
 
         #if ( configENABLE_TRUSTZONE == 1 )
@@ -1543,14 +1609,18 @@
         #endif /* configENABLE_TRUSTZONE */
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) ( pxTopOfStack - 8 ); /* PSP with the hardware saved stack. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack;         /* PSPLIM. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack; /* PSPLIM. */
         ulIndex++;
 
         #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
         {
             /* Check PACBTI security feature configuration before pushing the
              * CONTROL register's value on task's TCB. */
-            ulControl = prvConfigurePACBTI( pdFALSE );
+            #if ( configNUMBER_OF_CORES == 1 )
+                ulControl = prvConfigurePACBTI( pdFALSE );
+            #else /* configNUMBER_OF_CORES > 1 */
+                ulControl = vConfigurePACBTI( pdFALSE );
+            #endif /* configNUMBER_OF_CORES */
         }
         #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1615,15 +1685,15 @@
          * interrupt. */
         #if ( portPRELOAD_REGISTERS == 0 )
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
-            pxTopOfStack -= 5;                                       /* R12, R3, R2 and R1. */
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
-            pxTopOfStack -= 9;                                       /* R11..R4, EXC_RETURN. */
+            pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
+            pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */
             *pxTopOfStack = portINITIAL_EXC_RETURN;
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
@@ -1637,42 +1707,42 @@
         }
         #else /* portPRELOAD_REGISTERS */
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x12121212UL;            /* R12. */
+            *pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x03030303UL;            /* R3. */
+            *pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x02020202UL;            /* R2. */
+            *pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x01010101UL;            /* R1. */
+            *pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x11111111UL;            /* R11. */
+            *pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x10101010UL;            /* R10. */
+            *pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x09090909UL;            /* R09. */
+            *pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x08080808UL;            /* R08. */
+            *pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x07070707UL;            /* R07. */
+            *pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x06060606UL;            /* R06. */
+            *pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x05050505UL;            /* R05. */
+            *pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x04040404UL;            /* R04. */
+            *pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04. */
             pxTopOfStack--;
-            *pxTopOfStack = portINITIAL_EXC_RETURN;                  /* EXC_RETURN. */
+            *pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxEndOfStack;            /* Slot used to hold this task's PSPLIM value. */
+            *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
 
             #if ( configENABLE_TRUSTZONE == 1 )
             {
@@ -1739,91 +1809,17 @@
     }
     #endif /* configCHECK_HANDLER_INSTALLATION */
 
-    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
-    {
-        volatile uint32_t ulImplementedPrioBits = 0;
-        volatile uint8_t ucMaxPriorityValue;
-
-        /* Determine the maximum priority from which ISR safe FreeRTOS API
-         * functions can be called. ISR safe functions are those that end in
-         * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
-         * ensure interrupt entry is as fast and simple as possible.
-         *
-         * First, determine the number of priority bits available. Write to all
-         * possible bits in the priority setting for SVCall. */
-        portNVIC_SHPR2_REG = 0xFF000000;
-
-        /* Read the value back to see how many bits stuck. */
-        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
-
-        /* Use the same mask on the maximum system call priority. */
-        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
-
-        /* Check that the maximum system call priority is nonzero after
-         * accounting for the number of priority bits supported by the
-         * hardware. A priority of 0 is invalid because setting the BASEPRI
-         * register to 0 unmasks all interrupts, and interrupts with priority 0
-         * cannot be masked using BASEPRI.
-         * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
-        configASSERT( ucMaxSysCallPriority );
-
-        /* Check that the bits not implemented in hardware are zero in
-         * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
-        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
-
-        /* Calculate the maximum acceptable priority group value for the number
-         * of bits read back. */
-        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
-        {
-            ulImplementedPrioBits++;
-            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
-        }
-
-        if( ulImplementedPrioBits == 8 )
-        {
-            /* When the hardware implements 8 priority bits, there is no way for
-             * the software to configure PRIGROUP to not have sub-priorities. As
-             * a result, the least significant bit is always used for sub-priority
-             * and there are 128 preemption priorities and 2 sub-priorities.
-             *
-             * This may cause some confusion in some cases - for example, if
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
-             * priority interrupts will be masked in Critical Sections as those
-             * are at the same preemption priority. This may appear confusing as
-             * 4 is higher (numerically lower) priority than
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
-             * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
-             * to 4, this confusion does not happen and the behaviour remains the same.
-             *
-             * The following assert ensures that the sub-priority bit in the
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
-             * confusion. */
-            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
-            ulMaxPRIGROUPValue = 0;
-        }
-        else
-        {
-            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
-        }
-
-        /* Shift the priority group value back to its position within the AIRCR
-         * register. */
-        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
-        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
-    }
-    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
-
-    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
-     * the highest priority. */
-    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
-    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
-    portNVIC_SHPR2_REG = 0;
+    vPortConfigureInterruptPriorities();
 
     #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
     {
         /* Set the CONTROL register value based on PACBTI security feature
          * configuration before starting the first task. */
-        ( void ) prvConfigurePACBTI( pdTRUE );
+        #if ( configNUMBER_OF_CORES == 1 )
+            ( void ) prvConfigurePACBTI( pdTRUE );
+        #else /* configNUMBER_OF_CORES > 1 */
+            ( void ) vConfigurePACBTI( pdTRUE );
+        #endif /* configNUMBER_OF_CORES */
     }
     #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1834,12 +1830,47 @@
     }
     #endif /* configENABLE_MPU */
 
-    /* Start the timer that generates the tick ISR. Interrupts are disabled
-     * here already. */
-    vPortSetupTimerInterrupt();
+    #if ( configNUMBER_OF_CORES > 1 )
+        /* Start the timer that generates the tick ISR. Interrupts are disabled
+         * here already. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count for all cores. */
+        for ( uint8_t ucCoreID = 0; ucCoreID < configNUMBER_OF_CORES; ucCoreID++ )
+        {
+            ulCriticalNestings[ ucCoreID ] = 0;
+        }
+        /* Signal that primary core has done all the necessary initialisations. */
+        ucPrimaryCoreInitDoneFlag = 1;
+        /* Wake up secondary cores */
+        BaseType_t xWakeResult = configWAKE_SECONDARY_CORES();
+        configASSERT( xWakeResult == pdTRUE );
 
-    /* Initialize the critical nesting count ready for the first task. */
-    ulCriticalNesting = 0;
+        /* Hold the primary core here until all the secondary cores are ready, this would be achieved only when
+         * all elements of ucSecondaryCoresReadyFlags are set.
+         */
+        while( 1 )
+        {
+            BaseType_t xAllCoresReady = pdTRUE;
+            for( uint8_t ucCoreID = 0; ucCoreID < ( configNUMBER_OF_CORES - 1 ); ucCoreID++ )
+            {
+                if( ucSecondaryCoresReadyFlags[ ucCoreID ] != pdTRUE )
+                {
+                    xAllCoresReady = pdFALSE;
+                    break;
+                }
+                }
+
+            if ( xAllCoresReady == pdTRUE )
+            {
+                break;
+            }
+        }
+    #else /* if ( configNUMBER_OF_CORES > 1 ) */
+        /* Start the timer that generates the tick ISR. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count ready for the first task. */
+        ulCriticalNesting = 0;
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
     {
@@ -1856,7 +1887,11 @@
      * functionality by defining configTASK_RETURN_ADDRESS. Call
      * vTaskSwitchContext() so link time optimization does not remove the
      * symbol. */
-    vTaskSwitchContext();
+    #if ( configNUMBER_OF_CORES > 1 )
+        vTaskSwitchContext( portGET_CORE_ID() );
+    #else
+        vTaskSwitchContext();
+    #endif
     prvTaskExitError();
 
     /* Should not get here. */
@@ -1868,7 +1903,11 @@
 {
     /* Not implemented in ports where there is nothing to return to.
      * Artificially force an assert. */
-    configASSERT( ulCriticalNesting == 1000UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == 1000UL );
+    #else /* if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == 1000UL );
+    #endif /* if ( configNUMBER_OF_CORES == 1 ) */
 }
 /*-----------------------------------------------------------*/
 
@@ -2151,6 +2190,90 @@
 #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
 /*-----------------------------------------------------------*/
 
+void vPortConfigureInterruptPriorities( void ) /* PRIVILEGED_FUNCTION */
+{
+    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
+    {
+        volatile uint32_t ulImplementedPrioBits = 0;
+        volatile uint8_t ucMaxPriorityValue;
+
+        /* Determine the maximum priority from which ISR safe FreeRTOS API
+        * functions can be called. ISR safe functions are those that end in
+        * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
+        * ensure interrupt entry is as fast and simple as possible.
+        *
+        * First, determine the number of priority bits available. Write to all
+        * possible bits in the priority setting for SVCall. */
+        portNVIC_SHPR2_REG = 0xFF000000;
+
+        /* Read the value back to see how many bits stuck. */
+        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
+
+        /* Use the same mask on the maximum system call priority. */
+        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
+
+        /* Check that the maximum system call priority is nonzero after
+        * accounting for the number of priority bits supported by the
+        * hardware. A priority of 0 is invalid because setting the BASEPRI
+        * register to 0 unmasks all interrupts, and interrupts with priority 0
+        * cannot be masked using BASEPRI.
+        * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+        configASSERT( ucMaxSysCallPriority );
+
+        /* Check that the bits not implemented in hardware are zero in
+        * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
+        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
+
+        /* Calculate the maximum acceptable priority group value for the number
+        * of bits read back. */
+        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
+        {
+            ulImplementedPrioBits++;
+            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
+        }
+
+        if( ulImplementedPrioBits == 8 )
+        {
+            /* When the hardware implements 8 priority bits, there is no way for
+            * the software to configure PRIGROUP to not have sub-priorities. As
+            * a result, the least significant bit is always used for sub-priority
+            * and there are 128 preemption priorities and 2 sub-priorities.
+            *
+            * This may cause some confusion in some cases - for example, if
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
+            * priority interrupts will be masked in Critical Sections as those
+            * are at the same preemption priority. This may appear confusing as
+            * 4 is higher (numerically lower) priority than
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
+            * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
+            * to 4, this confusion does not happen and the behaviour remains the same.
+            *
+            * The following assert ensures that the sub-priority bit in the
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
+            * confusion. */
+            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
+            ulMaxPRIGROUPValue = 0;
+        }
+        else
+        {
+            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
+        }
+
+        /* Shift the priority group value back to its position within the AIRCR
+        * register. */
+        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
+        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
+    }
+    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
+
+    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
+    * the highest priority. */
+    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
+    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
+    portNVIC_SHPR2_REG = 0;
+}
+/*-----------------------------------------------------------*/
+
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) )
 
     void vPortGrantAccessToKernelObject( TaskHandle_t xInternalTaskHandle,
@@ -2247,36 +2370,214 @@
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
-
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
-    {
-        uint32_t ulControl = 0x0;
-
-        /* Ensure that PACBTI is implemented. */
-        configASSERT( portID_ISAR5_REG != 0x0 );
-
-        /* Enable UsageFault exception. */
-        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
-
-        #if ( configENABLE_PAC == 1 )
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #else /* configNUMBER_OF_CORES > 1 */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #endif /* configNUMBER_OF_CORES */
         {
-            ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
-        }
-        #endif
+            uint32_t ulControl = 0x0;
 
-        #if ( configENABLE_BTI == 1 )
-        {
-            ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
-        }
-        #endif
+            /* Ensure that PACBTI is implemented. */
+            configASSERT( portID_ISAR5_REG != 0x0 );
 
-        if( xWriteControlRegister == pdTRUE )
-        {
-            __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
-        }
+            /* Enable UsageFault exception. */
+            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
 
-        return ulControl;
-    }
+            #if ( configENABLE_PAC == 1 )
+            {
+                ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
+            }
+            #endif
+
+            #if ( configENABLE_BTI == 1 )
+            {
+                ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
+            }
+            #endif
+
+            if( xWriteControlRegister == pdTRUE )
+            {
+                __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
+            }
+
+            return ulControl;
+        }
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 /*-----------------------------------------------------------*/
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /* Which core owns the lock? */
+    PRIVILEGED_DATA volatile uint32_t ulOwnedByCore[ portMAX_CORE_COUNT ];
+    /* Lock count a core owns. */
+    PRIVILEGED_DATA volatile uint32_t ulRecursionCountByLock[ eLockCount ];
+    /* Index 0 is used for ISR lock and Index 1 is used for task lock. */
+    PRIVILEGED_DATA volatile uint32_t ulGateWord[ eLockCount ];
+
+    __attribute__((weak)) void vInterruptCore( uint8_t ucCoreID )
+    {
+        /* Default weak stub - platform specific implementation may override. */
+        ( void ) ucCoreID;
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline void prvSpinUnlock( volatile uint32_t * ulLock )
+    {
+        /* Conservative unlock: preserve original barriers for broad HW/FVP. */
+        __asm volatile (
+            "dmb sy         \n"
+            "mov r1, #0     \n"
+            "str r1, [%0]   \n"
+            "sev            \n"
+            "dsb            \n"
+            "isb            \n"
+            :
+            : "r" ( ulLock )
+            : "memory", "r1"
+        );
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline uint32_t prvSpinTrylock( volatile uint32_t * ulLock )
+    {
+        /*
+         * Conservative ldrex/strex trylock:
+         * - Return 1 immediately if busy, clearing exclusive state (CLREX).
+         * - Retry strex only on spurious failure when observed free.
+         * - DMB on success to preserve expected acquire semantics.
+         */
+        uint32_t ulVal;
+        uint32_t ulStatus;
+
+        __asm volatile (
+            " ldrex %0, [%1]   \n"
+            : "=r" ( ulVal )
+            : "r" ( ulLock )
+            : "memory"
+        );
+
+        if( ulVal != 0U )
+        {
+            __asm volatile ("clrex" ::: "memory");
+            return 1U;
+        }
+
+        __asm volatile (
+            " strex %0, %2, [%1]   \n"
+            : "=&r" ( ulStatus )
+            : "r" ( ulLock ), "r" (1U)
+            : "memory"
+        );
+
+        if( ulStatus != 0U )
+        {
+            return 1U;
+        }
+        __asm volatile ( "dmb" ::: "memory" );
+        return 0U;
+    }
+
+
+/*-----------------------------------------------------------*/
+
+    /* Read 32b value shared between cores. */
+    static inline uint32_t prvGet32( volatile uint32_t * x )
+    {
+        __asm( "dsb" );
+        return *x;
+    }
+
+/*-----------------------------------------------------------*/
+
+    /* Write 32b value shared between cores. */
+    static inline void prvSet32( volatile uint32_t * x,
+                                 uint32_t value )
+    {
+        *x = value;
+        __asm( "dsb" );
+    }
+
+/*-----------------------------------------------------------*/
+
+    void vPortRecursiveLock( uint8_t ucCoreID,
+                             ePortRTOSLock eLockNum,
+                             BaseType_t uxAcquire )
+    {
+        /* Validate the core ID and lock number. */
+        configASSERT( ucCoreID < portMAX_CORE_COUNT );
+        configASSERT( eLockNum < eLockCount );
+
+        uint32_t ulLockBit = 1u << eLockNum;
+
+        /* Lock acquire */
+        if( uxAcquire )
+        {
+            /* Check if spinlock is available. */
+            /* If spinlock is not available check if the core owns the lock. */
+            /* If the core owns the lock wait increment the lock count by the core. */
+            /* If core does not own the lock wait for the spinlock. */
+            if( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+            {
+                /* Check if the core owns the spinlock. */
+                if( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit )
+                {
+                    configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != portUINT32_MAX );
+                    prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) + 1 ) );
+                    return;
+                }
+
+                /* Preload the gate word into the cache. */
+                uint32_t dummy = ulGateWord[ eLockNum ];
+                dummy++;
+
+                while( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+                {
+                    __asm volatile ( "wfe" );
+                }
+            }
+
+            /* Add barrier to ensure lock is taken before we proceed. */
+            __asm volatile( "dmb sy" ::: "memory" );
+
+            /* Assert the lock count is 0 when the spinlock is free and is acquired. */
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) == 0 );
+
+            /* Set lock count as 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], 1 );
+            /* Set ulOwnedByCore. */
+            prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) | ulLockBit ) );
+        }
+        /* Lock release. */
+        else
+        {
+            /* Assert the lock is not free already. */
+            configASSERT( ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit ) != 0 );
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != 0 );
+
+            /* Reduce ulRecursionCountByLock by 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) - 1 ) );
+
+            if( !prvGet32( &ulRecursionCountByLock[ eLockNum ] ) )
+            {
+                prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ~ulLockBit ) );
+                prvSpinUnlock( &ulGateWord[ eLockNum ] );
+                /* Add barrier to ensure lock status is reflected before we proceed. */
+                __asm volatile( "dmb sy" ::: "memory" );
+            }
+        }
+    }
+
+/*-----------------------------------------------------------*/
+
+    uint8_t ucPortGetCoreID( void )
+    {
+        return *(volatile uint8_t *)(configCORE_ID_REGISTER);
+    }
+
+/*-----------------------------------------------------------*/
+
+#endif /* if( configNUMBER_OF_CORES > 1 ) */
diff --git a/Source/portable/GCC/ARM_CM55_NTZ/non_secure/portasm.c b/Source/portable/GCC/ARM_CM55_NTZ/non_secure/portasm.c
index 51ec476..fbb00b1 100644
--- a/Source/portable/GCC/ARM_CM55_NTZ/non_secure/portasm.c
+++ b/Source/portable/GCC/ARM_CM55_NTZ/non_secure/portasm.c
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -134,8 +133,21 @@
         (
             "   .syntax unified                                 \n"
             "                                                   \n"
+        /*
+         * The SMP-specific logic below is derived from the Raspberry Pi
+         * implementation in the FreeRTOS-Kernel-Community-Supported-Ports project.
+         * Source: GCC/RP2350_ARM_NTZ/non_secure/portasm.c
+         * Upstream commit: 8b2955f6d97bf4cd582db9f5b62d9eb1587b76d7
+         */
+        #if ( configNUMBER_OF_CORES == 1)
             "   ldr  r2, =pxCurrentTCB                          \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
             "   ldr  r1, [r2]                                   \n" /* Read pxCurrentTCB. */
+        #else /* if ( configNUMBER_OF_CORES == 1) */
+            "   ldr r1, =ulFirstTaskLiteralPool                 \n" /* Get the location of the current TCB and the Id of the current core. */
+            "   ldmia r1!, {r2, r3}                             \n"
+            "   ldr r2, [r2]                                    \n" /* r2 = Core Id */
+            "   ldr r1, [r3, r2, LSL #2]                        \n" /* r1 = pxCurrentTCBs[CORE_ID] */
+        #endif /* if ( configNUMBER_OF_CORES == 1) */
             "   ldr  r0, [r1]                                   \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
             "                                                   \n"
         #if ( configENABLE_PAC == 1 )
@@ -158,6 +170,14 @@
             "   mov  r0, #0                                     \n"
             "   msr  basepri, r0                                \n" /* Ensure that interrupts are enabled when the first task starts. */
             "   bx   r2                                         \n" /* Finally, branch to EXC_RETURN. */
+        #if ( configNUMBER_OF_CORES > 1 )
+            "                                                   \n"
+            "     .align 4                                      \n"
+            "ulFirstTaskLiteralPool:                            \n"
+            "    .word %c0                                      \n" /* CORE_ID_REGISTER */
+            "    .word pxCurrentTCBs                            \n"
+            :: "i" (configCORE_ID_REGISTER)
+        #endif /* if ( configNUMBER_OF_CORES > 1 ) */
         );
     }
 
@@ -422,20 +442,43 @@
             "   clrm {r1-r4}                                    \n" /* Clear r1-r4. */
         #endif /* configENABLE_PAC */
             "                                                   \n"
+        /*
+         * The SMP-specific logic below is derived from the Raspberry Pi
+         * implementation in the FreeRTOS-Kernel-Community-Supported-Ports project.
+         * Source: GCC/RP2350_ARM_NTZ/non_secure/portasm.c
+         * Upstream commit: 8b2955f6d97bf4cd582db9f5b62d9eb1587b76d7
+         */
+        #if ( configNUMBER_OF_CORES == 1)
             "   ldr r2, =pxCurrentTCB                           \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
             "   ldr r1, [r2]                                    \n" /* Read pxCurrentTCB. */
+        #else /* if ( configNUMBER_OF_CORES == 1) */
+            "   ldr r1, =ulPendSVLiteralPool                    \n" /* Get the location of the current TCB and the Id of the current core. */
+            "   ldmia r1!, {r2, r3}                             \n"
+            "   ldr r2, [r2]                                    \n" /* r2 = Core Id */
+            "   ldr r1, [r3, r2, LSL #2]                        \n" /* r1 = pxCurrentTCBs[CORE_ID] */
+        #endif /* if ( configNUMBER_OF_CORES == 1) */
             "   str r0, [r1]                                    \n" /* Save the new top of stack in TCB. */
             "                                                   \n"
             "   mov r0, %0                                      \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
             "   msr basepri, r0                                 \n" /* Disable interrupts up to configMAX_SYSCALL_INTERRUPT_PRIORITY. */
             "   dsb                                             \n"
             "   isb                                             \n"
+        #if ( configNUMBER_OF_CORES > 1)
+            "   mov r0, r2                                      \n" /* r0 = ucPortGetCoreID() */
+        #endif /* if ( configNUMBER_OF_CORES == 1) */
             "   bl vTaskSwitchContext                           \n"
             "   mov r0, #0                                      \n" /* r0 = 0. */
             "   msr basepri, r0                                 \n" /* Enable interrupts. */
             "                                                   \n"
+        #if ( configNUMBER_OF_CORES == 1)
             "   ldr r2, =pxCurrentTCB                           \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
             "   ldr r1, [r2]                                    \n" /* Read pxCurrentTCB. */
+        #else /* if ( configNUMBER_OF_CORES == 1) */
+            "   ldr r1, =ulPendSVLiteralPool                    \n" /* Get the location of the current TCB and the Id of the current core. */
+            "   ldmia r1!, {r2, r3}                             \n"
+            "   ldr r2, [r2]                                    \n" /* r2 = Core Id */
+            "   ldr r1, [r3, r2, LSL #2]                        \n" /* r1 = pxCurrentTCBs[CORE_ID] */
+        #endif /* if ( configNUMBER_OF_CORES == 1) */
             "   ldr r0, [r1]                                    \n" /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
             "                                                   \n"
         #if ( configENABLE_PAC == 1 )
@@ -458,7 +501,16 @@
             "   msr psplim, r2                                  \n" /* Restore the PSPLIM register value for the task. */
             "   msr psp, r0                                     \n" /* Remember the new top of stack for the task. */
             "   bx r3                                           \n"
-            ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
+        #if ( configNUMBER_OF_CORES > 1 )
+            "   .align 4                           \n"
+            "   ulPendSVLiteralPool:               \n"
+            "   .word %c1                          \n" /* CORE_ID_REGISTER */
+            "   .word pxCurrentTCBs                \n"
+            :: "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ), "i" ( configCORE_ID_REGISTER )
+        #else /* #if ( configNUMBER_OF_CORES > 1 ) */
+            :: "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
+        #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
+
         );
     }
 
diff --git a/Source/portable/GCC/ARM_CM55_NTZ/non_secure/portasm.h b/Source/portable/GCC/ARM_CM55_NTZ/non_secure/portasm.h
index 53b4b6e..b4b545f 100644
--- a/Source/portable/GCC/ARM_CM55_NTZ/non_secure/portasm.h
+++ b/Source/portable/GCC/ARM_CM55_NTZ/non_secure/portasm.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM55_NTZ/non_secure/portmacro.h b/Source/portable/GCC/ARM_CM55_NTZ/non_secure/portmacro.h
index 11a2777..11d6470 100644
--- a/Source/portable/GCC/ARM_CM55_NTZ/non_secure/portmacro.h
+++ b/Source/portable/GCC/ARM_CM55_NTZ/non_secure/portmacro.h
@@ -1,6 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * Copyright 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -57,6 +58,7 @@
 #define portHAS_ARMV8M_MAIN_EXTENSION    1
 #define portARMV8M_MINOR_VERSION         1
 #define portDONT_DISCARD                 __attribute__( ( used ) )
+#define portVALIDATED_FOR_SMP            0
 /*-----------------------------------------------------------*/
 
 /* ARMv8-M common port configurations. */
diff --git a/Source/portable/GCC/ARM_CM55_NTZ/non_secure/portmacrocommon.h b/Source/portable/GCC/ARM_CM55_NTZ/non_secure/portmacrocommon.h
index 2dfac6a..c34fdee 100644
--- a/Source/portable/GCC/ARM_CM55_NTZ/non_secure/portmacrocommon.h
+++ b/Source/portable/GCC/ARM_CM55_NTZ/non_secure/portmacrocommon.h
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -59,6 +58,19 @@
     #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h.  Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
 #endif /* configENABLE_TRUSTZONE */
 
+#if ( configNUMBER_OF_CORES > 1 )
+    #if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 )
+        #error "Multi-core SMP is currently only validated for Cortex-M33 non-TrustZone non-MPU port."
+    #endif /* if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 ) ) */
+
+    #ifndef configCORE_ID_REGISTER
+        #error "configCORE_ID_REGISTER must be defined to the address of the register used to identify the core executing the code."
+    #endif /* ifndef configCORE_ID_REGISTER */
+
+    #ifndef configWAKE_SECONDARY_CORES
+        #error "configWAKE_SECONDARY_CORES must be defined to a function that wakes the secondary cores."
+    #endif /* ifndef configWAKE_SECONDARY_CORES */
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -428,10 +440,26 @@
 /**
  * @brief Critical section management.
  */
+
+#define portSET_INTERRUPT_MASK()                  ulSetInterruptMask()
+#define portCLEAR_INTERRUPT_MASK( x )             vClearInterruptMask( x )
 #define portSET_INTERRUPT_MASK_FROM_ISR()         ulSetInterruptMask()
 #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x )    vClearInterruptMask( x )
-#define portENTER_CRITICAL()                      vPortEnterCritical()
-#define portEXIT_CRITICAL()                       vPortExitCritical()
+
+#if ( configNUMBER_OF_CORES == 1 )
+    #define portENTER_CRITICAL()                      vPortEnterCritical()
+    #define portEXIT_CRITICAL()                       vPortExitCritical()
+#else /* ( configNUMBER_OF_CORES == 1 ) */
+    extern void vTaskEnterCritical( void );
+    extern void vTaskExitCritical( void );
+    extern UBaseType_t vTaskEnterCriticalFromISR( void );
+    extern void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus );
+
+    #define portENTER_CRITICAL()                      vTaskEnterCritical()
+    #define portEXIT_CRITICAL()                       vTaskExitCritical()
+    #define portENTER_CRITICAL_FROM_ISR()             vTaskEnterCriticalFromISR()
+    #define portEXIT_CRITICAL_FROM_ISR( x )           vTaskExitCriticalFromISR( x )
+#endif /* if ( configNUMBER_OF_CORES != 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -526,7 +554,7 @@
 /* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION
  * based on whether or not Mainline extension is implemented. */
 #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
-    #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 )
+    #if ( ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) && ( configNUMBER_OF_CORES == 1 ) )
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    1
     #else
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    0
@@ -573,6 +601,44 @@
 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
 /*-----------------------------------------------------------*/
 
+
+#if ( configNUMBER_OF_CORES > 1 )
+    typedef enum
+    {
+        eIsrLock = 0,
+        eTaskLock,
+        eLockCount
+    } ePortRTOSLock;
+
+    extern volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ];
+    extern void vPortRecursiveLock( uint8_t ucCoreID,
+                                    ePortRTOSLock eLockNum,
+                                    BaseType_t uxAcquire );
+    extern uint8_t ucPortGetCoreID( void );
+    extern void vInterruptCore( uint8_t ucCoreID );
+
+    #define portGET_CORE_ID()                                  ucPortGetCoreID()
+
+    #define portGET_CRITICAL_NESTING_COUNT( xCoreID )          ( ulCriticalNestings[ ( uint8_t ) xCoreID ] )
+    #define portSET_CRITICAL_NESTING_COUNT( xCoreID, x )       ( ulCriticalNestings[ ( uint8_t ) xCoreID ] = ( x ) )
+    #define portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]++ )
+    #define portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]-- )
+
+    #define portMAX_CORE_COUNT                                 ( configNUMBER_OF_CORES )
+
+    #define portYIELD_CORE( xCoreID )                          vInterruptCore( xCoreID )
+
+    #define portRELEASE_ISR_LOCK( xCoreID )                    vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdFALSE )
+    #define portGET_ISR_LOCK( xCoreID )                        vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdTRUE )
+
+    #define portRELEASE_TASK_LOCK( xCoreID )                   vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdFALSE )
+    #define portGET_TASK_LOCK( xCoreID )                       vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdTRUE )
+
+    #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* ( configENABLE_PAC == 1 || configENABLE_BTI == 1 ) */
+#endif
+
 /* *INDENT-OFF* */
 #ifdef __cplusplus
     }
diff --git a/Source/portable/GCC/ARM_CM7/r0p1/port.c b/Source/portable/GCC/ARM_CM7/r0p1/port.c
index 7f689ba..b1287ef 100644
--- a/Source/portable/GCC/ARM_CM7/r0p1/port.c
+++ b/Source/portable/GCC/ARM_CM7/r0p1/port.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM7/r0p1/portmacro.h b/Source/portable/GCC/ARM_CM7/r0p1/portmacro.h
index eeb95a9..7827664 100644
--- a/Source/portable/GCC/ARM_CM7/r0p1/portmacro.h
+++ b/Source/portable/GCC/ARM_CM7/r0p1/portmacro.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM85/non_secure/mpu_wrappers_v2_asm.c b/Source/portable/GCC/ARM_CM85/non_secure/mpu_wrappers_v2_asm.c
index 9c3e8c7..6dd2be8 100644
--- a/Source/portable/GCC/ARM_CM85/non_secure/mpu_wrappers_v2_asm.c
+++ b/Source/portable/GCC/ARM_CM85/non_secure/mpu_wrappers_v2_asm.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM85/non_secure/port.c b/Source/portable/GCC/ARM_CM85/non_secure/port.c
index f16a343..007150c 100644
--- a/Source/portable/GCC/ARM_CM85/non_secure/port.c
+++ b/Source/portable/GCC/ARM_CM85/non_secure/port.c
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024-2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -145,13 +144,13 @@
 /**
  * @brief Constants required to manipulate the FPU.
  */
-#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 )              /* Coprocessor Access Control Register. */
+#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */
 #define portCPACR_CP10_VALUE    ( 3UL )
 #define portCPACR_CP11_VALUE    portCPACR_CP10_VALUE
 #define portCPACR_CP10_POS      ( 20UL )
 #define portCPACR_CP11_POS      ( 22UL )
 
-#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 )              /* Floating Point Context Control Register. */
+#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
 #define portFPCCR_ASPEN_POS     ( 31UL )
 #define portFPCCR_ASPEN_MASK    ( 1UL << portFPCCR_ASPEN_POS )
 #define portFPCCR_LSPEN_POS     ( 30UL )
@@ -188,8 +187,8 @@
 #define portMPU_MAIR0_REG                       ( *( ( volatile uint32_t * ) 0xe000edc0 ) )
 #define portMPU_MAIR1_REG                       ( *( ( volatile uint32_t * ) 0xe000edc4 ) )
 
-#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
-#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
+#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
+#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
 
 #define portMPU_RBAR_ACCESS_PERMISSIONS_MASK    ( 3UL << 1UL )
 
@@ -230,8 +229,8 @@
 
 #if ( portARMV8M_MINOR_VERSION >= 1 )
 
-/* Enable Privileged eXecute Never MPU attribute for the selected memory
- * region. */
+    /* Enable Privileged eXecute Never MPU attribute for the selected memory
+     * region. */
     #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER    ( 1UL << 4UL )
 #endif /* portARMV8M_MINOR_VERSION >= 1 */
 
@@ -241,9 +240,6 @@
 /* Enable MPU. */
 #define portMPU_ENABLE_BIT                    ( 1UL << 0UL )
 
-/* Expected value of the portMPU_TYPE register. */
-#define portEXPECTED_MPU_TYPE_VALUE           ( configTOTAL_MPU_REGIONS << 8UL )
-
 /* Extract first address of the MPU region as encoded in the
  * RBAR (Region Base Address Register) value. */
 #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@@ -291,37 +287,37 @@
 
 #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         FD
- * 1111 1111  1111 1111  1111 1111  1111 1101
- *
- * Bit[6] - 1 --> The exception was taken from the Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 1 --> The exception was taken to the Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         FD
+     * 1111 1111  1111 1111  1111 1111  1111 1101
+     *
+     * Bit[6] - 1 --> The exception was taken from the Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 1 --> The exception was taken to the Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xfffffffd )
 #else
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         BC
- * 1111 1111  1111 1111  1111 1111  1011 1100
- *
- * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         BC
+     * 1111 1111  1111 1111  1111 1111  1011 1100
+     *
+     * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xffffffbc )
 #endif /* configRUN_FREERTOS_SECURE_ONLY */
 
@@ -401,50 +397,54 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Extract MPU region's access permissions from the Region Base Address
- * Register (RBAR) value.
- *
- * @param ulRBARValue RBAR value for the MPU region.
- *
- * @return uint32_t Access permissions.
- */
+    /**
+     * @brief Extract MPU region's access permissions from the Region Base Address
+     * Register (RBAR) value.
+     *
+     * @param ulRBARValue RBAR value for the MPU region.
+     *
+     * @return uint32_t Access permissions.
+     */
     static uint32_t prvGetRegionAccessPermissions( uint32_t ulRBARValue ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU == 1 && configUSE_MPU_WRAPPERS_V1 == 0 */
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Setup the Memory Protection Unit (MPU).
- */
+    /**
+     * @brief Setup the Memory Protection Unit (MPU).
+     */
     static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU */
 
 #if ( configENABLE_FPU == 1 )
 
-/**
- * @brief Setup the Floating Point Unit (FPU).
- */
+    /**
+     * @brief Setup the Floating Point Unit (FPU).
+     */
     static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_FPU */
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
 
-/**
- * @brief Configures PACBTI features.
- *
- * This function configures the Pointer Authentication, and Branch Target
- * Identification security features as per the user configuration. It returns
- * the value of the special purpose CONTROL register accordingly, and optionally
- * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
- * architecture based) target supports PACBTI security feature.
- *
- * @param xWriteControlRegister Used to control whether the special purpose
- * CONTROL register should be updated or not.
- *
- * @return CONTROL register value according to the configured PACBTI option.
- */
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    /**
+     * @brief Configures PACBTI features.
+     *
+     * This function configures the Pointer Authentication, and Branch Target
+     * Identification security features as per the user configuration. It returns
+     * the value of the special purpose CONTROL register accordingly, and optionally
+     * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
+     * architecture based) target supports PACBTI security feature.
+     *
+     * @param xWriteControlRegister Used to control whether the special purpose
+     * CONTROL register should be updated or not.
+     *
+     * @return CONTROL register value according to the configured PACBTI option.
+     */
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -491,14 +491,14 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the system call stack so that upon returning from
- * SVC, the system call stack is used.
- *
- * @param pulTaskStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- * @param ucSystemCallNumber The system call number of the system call.
- */
+    /**
+     * @brief Sets up the system call stack so that upon returning from
+     * SVC, the system call stack is used.
+     *
+     * @param pulTaskStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     * @param ucSystemCallNumber The system call number of the system call.
+     */
     void vSystemCallEnter( uint32_t * pulTaskStack,
                            uint32_t ulLR,
                            uint8_t ucSystemCallNumber ) PRIVILEGED_FUNCTION;
@@ -507,22 +507,22 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Raise SVC for exiting from a system call.
- */
+    /**
+     * @brief Raise SVC for exiting from a system call.
+     */
     void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the task stack so that upon returning from
- * SVC, the task stack is used again.
- *
- * @param pulSystemCallStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- */
+    /**
+     * @brief Sets up the task stack so that upon returning from
+     * SVC, the task stack is used again.
+     *
+     * @param pulSystemCallStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     */
     void vSystemCallExit( uint32_t * pulSystemCallStack,
                           uint32_t ulLR ) PRIVILEGED_FUNCTION;
 
@@ -530,21 +530,38 @@
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Checks whether or not the calling task is privileged.
- *
- * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
- */
+    /**
+     * @brief Checks whether or not the calling task is privileged.
+     *
+     * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
+     */
     BaseType_t xPortIsTaskPrivileged( void ) PRIVILEGED_FUNCTION;
 
 #endif /* configENABLE_MPU == 1 */
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /**
+     * @brief Platform/Application-defined function that wakes up the secondary cores.
+     *
+     * @return pdTRUE if the secondary cores were successfully woken up.
+     *         pdFALSE otherwise.
+     */
+    extern BaseType_t configWAKE_SECONDARY_CORES( void );
+
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
+
+/**
+ * @brief Configures interrupt priorities.
+ */
+void vPortConfigureInterruptPriorities( void ) PRIVILEGED_FUNCTION;
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief This variable is set to pdTRUE when the scheduler is started.
- */
+    /**
+     * @brief This variable is set to pdTRUE when the scheduler is started.
+     */
     PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
@@ -553,14 +570,22 @@
  * @brief Each task maintains its own interrupt status in the critical nesting
  * variable.
  */
-PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
+#if ( configNUMBER_OF_CORES == 1 )
+    PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0UL;
+#else /* #if ( configNUMBER_OF_CORES == 1 ) */
+    PRIVILEGED_DATA volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ] = { 0 };
+    /* Flags to check if the secondary cores are ready. */
+    PRIVILEGED_DATA volatile uint8_t ucSecondaryCoresReadyFlags[ configNUMBER_OF_CORES - 1 ] = { 0 };
+    /* Flag to indicate that the primary core has completed its initialisation. */
+    PRIVILEGED_DATA volatile uint8_t ucPrimaryCoreInitDoneFlag = 0;
+ #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #if ( configENABLE_TRUSTZONE == 1 )
 
-/**
- * @brief Saved as part of the task context to indicate which context the
- * task is using on the secure side.
- */
+    /**
+     * @brief Saved as part of the task context to indicate which context the
+     * task is using on the secure side.
+     */
     PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
 #endif /* configENABLE_TRUSTZONE */
 
@@ -579,21 +604,21 @@
 
 #if ( configUSE_TICKLESS_IDLE == 1 )
 
-/**
- * @brief The number of SysTick increments that make up one tick period.
- */
+    /**
+     * @brief The number of SysTick increments that make up one tick period.
+     */
     PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
 
-/**
- * @brief The maximum number of tick periods that can be suppressed is
- * limited by the 24 bit resolution of the SysTick timer.
- */
+    /**
+     * @brief The maximum number of tick periods that can be suppressed is
+     * limited by the 24 bit resolution of the SysTick timer.
+     */
     PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
 
-/**
- * @brief Compensate for the CPU cycles that pass while the SysTick is
- * stopped (low power functionality only).
- */
+    /**
+     * @brief Compensate for the CPU cycles that pass while the SysTick is
+     * stopped (low power functionality only).
+     */
     PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0;
 #endif /* configUSE_TICKLESS_IDLE */
 /*-----------------------------------------------------------*/
@@ -856,7 +881,11 @@
      * should instead call vTaskDelete( NULL ). Artificially force an assert()
      * to be triggered if configASSERT() is defined, then stop here so
      * application writers can catch the error. */
-    configASSERT( ulCriticalNesting == ~0UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == ~0UL );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == ~0UL );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
     portDISABLE_INTERRUPTS();
 
     while( ulDummy == 0 )
@@ -925,64 +954,57 @@
         /* The only permitted number of regions are 8 or 16. */
         configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 16 ) );
 
-        /* Ensure that the configTOTAL_MPU_REGIONS is configured correctly. */
-        configASSERT( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE );
+        /* MAIR0 - Index 0. */
+        portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
+        /* MAIR0 - Index 1. */
+        portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
 
-        /* Check that the MPU is present. */
-        if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
-        {
-            /* MAIR0 - Index 0. */
-            portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
-            /* MAIR0 - Index 1. */
-            portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
+        /* Setup privileged flash as Read Only so that privileged tasks can
+         * read it but not modify. */
+        portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup privileged flash as Read Only so that privileged tasks can
-             * read it but not modify. */
-            portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged flash as Read Only by both privileged and
+         * unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged flash as Read Only by both privileged and
-             * unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged syscalls flash as Read Only by both privileged
+         * and unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged syscalls flash as Read Only by both privileged
-             * and unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup RAM containing kernel data for privileged access only. */
+        portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
+                           ( portMPU_REGION_EXECUTE_NEVER );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup RAM containing kernel data for privileged access only. */
-            portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
-                               ( portMPU_REGION_EXECUTE_NEVER );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Enable mem fault. */
+        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
 
-            /* Enable mem fault. */
-            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
-
-            /* Enable MPU with privileged background access i.e. unmapped
-             * regions have privileged access. */
-            portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
-        }
+        /* Enable MPU with privileged background access i.e. unmapped
+         * regions have privileged access. */
+        portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
     }
 
 #endif /* configENABLE_MPU */
@@ -1027,28 +1049,29 @@
 }
 /*-----------------------------------------------------------*/
 
-void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    portDISABLE_INTERRUPTS();
-    ulCriticalNesting++;
-
-    /* Barriers are normally not required but do ensure the code is
-     * completely within the specified behaviour for the architecture. */
-    __asm volatile ( "dsb" ::: "memory" );
-    __asm volatile ( "isb" );
-}
-/*-----------------------------------------------------------*/
-
-void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    configASSERT( ulCriticalNesting );
-    ulCriticalNesting--;
-
-    if( ulCriticalNesting == 0 )
+#if ( configNUMBER_OF_CORES == 1 )
+    void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
     {
-        portENABLE_INTERRUPTS();
+        portDISABLE_INTERRUPTS();
+        ulCriticalNesting++;
+        /* Barriers are normally not required but do ensure the code is
+        * completely within the specified behaviour for the architecture. */
+        __asm volatile ( "dsb" ::: "memory" );
+        __asm volatile ( "isb" );
     }
-}
+    /*-----------------------------------------------------------*/
+
+    void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
+    {
+        configASSERT( ulCriticalNesting );
+        ulCriticalNesting--;
+
+        if( ulCriticalNesting == 0 )
+        {
+            portENABLE_INTERRUPTS();
+        }
+    }
+#endif /* configNUMBER_OF_CORES == 1 */
 /*-----------------------------------------------------------*/
 
 void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
@@ -1056,6 +1079,10 @@
     uint32_t ulPreviousMask;
 
     ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
+    #if ( configNUMBER_OF_CORES > 1 )
+        UBaseType_t uxSavedInterruptStatus = portENTER_CRITICAL_FROM_ISR();
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     traceISR_ENTER();
     {
         /* Increment the RTOS tick. */
@@ -1070,6 +1097,10 @@
             traceISR_EXIT();
         }
     }
+    #if ( configNUMBER_OF_CORES > 1 )
+        portEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
 }
 /*-----------------------------------------------------------*/
@@ -1078,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1090,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1108,38 +1151,42 @@
 
     switch( ucSVCNumber )
     {
-        #if ( configENABLE_TRUSTZONE == 1 )
-            case portSVC_ALLOCATE_SECURE_CONTEXT:
+    #if ( configENABLE_TRUSTZONE == 1 )
+        case portSVC_ALLOCATE_SECURE_CONTEXT:
 
-                /* R0 contains the stack size passed as parameter to the
-                 * vPortAllocateSecureContext function. */
-                ulR0 = pulCallerStackAddress[ 0 ];
+            /* R0 contains the stack size passed as parameter to the
+             * vPortAllocateSecureContext function. */
+            ulR0 = pulCallerStackAddress[ 0 ];
 
-                #if ( configENABLE_MPU == 1 )
-                {
-                    /* Read the CONTROL register value. */
-                    __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
+            #if ( configENABLE_MPU == 1 )
+            {
+                /* Read the CONTROL register value. */
+                __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
 
-                    /* The task that raised the SVC is privileged if Bit[0]
-                     * in the CONTROL register is 0. */
-                    ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
+                /* The task that raised the SVC is privileged if Bit[0]
+                 * in the CONTROL register is 0. */
+                ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
 
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
-                }
-                #else /* if ( configENABLE_MPU == 1 ) */
-                {
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
-                }
-                #endif /* configENABLE_MPU */
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
+            }
+            #else /* if ( configENABLE_MPU == 1 ) */
+            {
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
+            }
+            #endif /* configENABLE_MPU */
 
-                configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
-                SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
-                break;
+            configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
+            SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
+            break;
 
-            case portSVC_FREE_SECURE_CONTEXT:
-
+        case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
                 /* R0 contains TCB being freed and R1 contains the secure
                  * context handle to be freed. */
                 ulR0 = pulCallerStackAddress[ 0 ];
@@ -1147,51 +1194,62 @@
 
                 /* Free the secure context. */
                 SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
-                break;
-        #endif /* configENABLE_TRUSTZONE */
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
+            break;
+    #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
-            #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
-                case portSVC_RAISE_PRIVILEGE:
+    #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
+        case portSVC_RAISE_PRIVILEGE:
 
-                    /* Only raise the privilege, if the svc was raised from any of
-                     * the system calls. */
-                    if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
-                        ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
-                    {
-                        vRaisePrivilege();
-                    }
-                    break;
-            #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
+            /* Only raise the privilege, if the svc was raised from any of
+             * the system calls. */
+            if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
+                ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
+            {
+                vRaisePrivilege();
+            }
+            break;
+    #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
-            #if ( configENABLE_MPU == 1 )
-                case portSVC_YIELD:
-                    vPortYield();
-                    break;
-            #endif /* configENABLE_MPU == 1 */
+    #if ( configENABLE_MPU == 1 )
+        case portSVC_YIELD:
+            vPortYield();
+            break;
+    #endif /* configENABLE_MPU == 1 */
 
         default:
             /* Incorrect SVC call. */
@@ -1210,7 +1268,7 @@
         extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulSystemCallStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1246,12 +1304,16 @@
         {
             pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1261,20 +1323,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the system call stack for the stack frame. */
-            pulSystemCallStack = pulSystemCallStack - ulStackFrameSize;
+            pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulSystemCallStack[ i ] = pulTaskStack[ i ];
             }
@@ -1310,7 +1372,7 @@
 
             /* Remember the location where we should copy the stack frame when we exit from
              * the system call. */
-            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
+            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
 
             /* Record if the hardware used padding to force the stack pointer
              * to be double word aligned. */
@@ -1360,7 +1422,7 @@
         extern TaskHandle_t pxCurrentTCB;
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulTaskStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1392,12 +1454,16 @@
         {
             pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1407,20 +1473,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the task stack for the stack frame. */
-            pulTaskStack = pulTaskStack - ulStackFrameSize;
+            pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulTaskStack[ i ] = pulSystemCallStack[ i ];
             }
@@ -1518,21 +1584,21 @@
         xMPUSettings->ulContext[ ulIndex ] = 0x11111111; /* r11. */
         ulIndex++;
 
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters;            /* r0. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters; /* r0. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x01010101;                           /* r1. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x01010101; /* r1. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x02020202;                           /* r2. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x02020202; /* r2. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x03030303;                           /* r3. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x03030303; /* r3. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x12121212;                           /* r12. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x12121212; /* r12. */
         ulIndex++;
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) portTASK_RETURN_ADDRESS; /* LR. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode;                  /* PC. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode; /* PC. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR;                     /* xPSR. */
+        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR; /* xPSR. */
         ulIndex++;
 
         #if ( configENABLE_TRUSTZONE == 1 )
@@ -1543,14 +1609,18 @@
         #endif /* configENABLE_TRUSTZONE */
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) ( pxTopOfStack - 8 ); /* PSP with the hardware saved stack. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack;         /* PSPLIM. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack; /* PSPLIM. */
         ulIndex++;
 
         #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
         {
             /* Check PACBTI security feature configuration before pushing the
              * CONTROL register's value on task's TCB. */
-            ulControl = prvConfigurePACBTI( pdFALSE );
+            #if ( configNUMBER_OF_CORES == 1 )
+                ulControl = prvConfigurePACBTI( pdFALSE );
+            #else /* configNUMBER_OF_CORES > 1 */
+                ulControl = vConfigurePACBTI( pdFALSE );
+            #endif /* configNUMBER_OF_CORES */
         }
         #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1615,15 +1685,15 @@
          * interrupt. */
         #if ( portPRELOAD_REGISTERS == 0 )
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
-            pxTopOfStack -= 5;                                       /* R12, R3, R2 and R1. */
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
-            pxTopOfStack -= 9;                                       /* R11..R4, EXC_RETURN. */
+            pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
+            pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */
             *pxTopOfStack = portINITIAL_EXC_RETURN;
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
@@ -1637,42 +1707,42 @@
         }
         #else /* portPRELOAD_REGISTERS */
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x12121212UL;            /* R12. */
+            *pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x03030303UL;            /* R3. */
+            *pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x02020202UL;            /* R2. */
+            *pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x01010101UL;            /* R1. */
+            *pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x11111111UL;            /* R11. */
+            *pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x10101010UL;            /* R10. */
+            *pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x09090909UL;            /* R09. */
+            *pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x08080808UL;            /* R08. */
+            *pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x07070707UL;            /* R07. */
+            *pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x06060606UL;            /* R06. */
+            *pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x05050505UL;            /* R05. */
+            *pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x04040404UL;            /* R04. */
+            *pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04. */
             pxTopOfStack--;
-            *pxTopOfStack = portINITIAL_EXC_RETURN;                  /* EXC_RETURN. */
+            *pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxEndOfStack;            /* Slot used to hold this task's PSPLIM value. */
+            *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
 
             #if ( configENABLE_TRUSTZONE == 1 )
             {
@@ -1739,91 +1809,17 @@
     }
     #endif /* configCHECK_HANDLER_INSTALLATION */
 
-    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
-    {
-        volatile uint32_t ulImplementedPrioBits = 0;
-        volatile uint8_t ucMaxPriorityValue;
-
-        /* Determine the maximum priority from which ISR safe FreeRTOS API
-         * functions can be called. ISR safe functions are those that end in
-         * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
-         * ensure interrupt entry is as fast and simple as possible.
-         *
-         * First, determine the number of priority bits available. Write to all
-         * possible bits in the priority setting for SVCall. */
-        portNVIC_SHPR2_REG = 0xFF000000;
-
-        /* Read the value back to see how many bits stuck. */
-        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
-
-        /* Use the same mask on the maximum system call priority. */
-        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
-
-        /* Check that the maximum system call priority is nonzero after
-         * accounting for the number of priority bits supported by the
-         * hardware. A priority of 0 is invalid because setting the BASEPRI
-         * register to 0 unmasks all interrupts, and interrupts with priority 0
-         * cannot be masked using BASEPRI.
-         * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
-        configASSERT( ucMaxSysCallPriority );
-
-        /* Check that the bits not implemented in hardware are zero in
-         * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
-        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
-
-        /* Calculate the maximum acceptable priority group value for the number
-         * of bits read back. */
-        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
-        {
-            ulImplementedPrioBits++;
-            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
-        }
-
-        if( ulImplementedPrioBits == 8 )
-        {
-            /* When the hardware implements 8 priority bits, there is no way for
-             * the software to configure PRIGROUP to not have sub-priorities. As
-             * a result, the least significant bit is always used for sub-priority
-             * and there are 128 preemption priorities and 2 sub-priorities.
-             *
-             * This may cause some confusion in some cases - for example, if
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
-             * priority interrupts will be masked in Critical Sections as those
-             * are at the same preemption priority. This may appear confusing as
-             * 4 is higher (numerically lower) priority than
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
-             * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
-             * to 4, this confusion does not happen and the behaviour remains the same.
-             *
-             * The following assert ensures that the sub-priority bit in the
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
-             * confusion. */
-            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
-            ulMaxPRIGROUPValue = 0;
-        }
-        else
-        {
-            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
-        }
-
-        /* Shift the priority group value back to its position within the AIRCR
-         * register. */
-        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
-        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
-    }
-    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
-
-    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
-     * the highest priority. */
-    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
-    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
-    portNVIC_SHPR2_REG = 0;
+    vPortConfigureInterruptPriorities();
 
     #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
     {
         /* Set the CONTROL register value based on PACBTI security feature
          * configuration before starting the first task. */
-        ( void ) prvConfigurePACBTI( pdTRUE );
+        #if ( configNUMBER_OF_CORES == 1 )
+            ( void ) prvConfigurePACBTI( pdTRUE );
+        #else /* configNUMBER_OF_CORES > 1 */
+            ( void ) vConfigurePACBTI( pdTRUE );
+        #endif /* configNUMBER_OF_CORES */
     }
     #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1834,12 +1830,47 @@
     }
     #endif /* configENABLE_MPU */
 
-    /* Start the timer that generates the tick ISR. Interrupts are disabled
-     * here already. */
-    vPortSetupTimerInterrupt();
+    #if ( configNUMBER_OF_CORES > 1 )
+        /* Start the timer that generates the tick ISR. Interrupts are disabled
+         * here already. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count for all cores. */
+        for ( uint8_t ucCoreID = 0; ucCoreID < configNUMBER_OF_CORES; ucCoreID++ )
+        {
+            ulCriticalNestings[ ucCoreID ] = 0;
+        }
+        /* Signal that primary core has done all the necessary initialisations. */
+        ucPrimaryCoreInitDoneFlag = 1;
+        /* Wake up secondary cores */
+        BaseType_t xWakeResult = configWAKE_SECONDARY_CORES();
+        configASSERT( xWakeResult == pdTRUE );
 
-    /* Initialize the critical nesting count ready for the first task. */
-    ulCriticalNesting = 0;
+        /* Hold the primary core here until all the secondary cores are ready, this would be achieved only when
+         * all elements of ucSecondaryCoresReadyFlags are set.
+         */
+        while( 1 )
+        {
+            BaseType_t xAllCoresReady = pdTRUE;
+            for( uint8_t ucCoreID = 0; ucCoreID < ( configNUMBER_OF_CORES - 1 ); ucCoreID++ )
+            {
+                if( ucSecondaryCoresReadyFlags[ ucCoreID ] != pdTRUE )
+                {
+                    xAllCoresReady = pdFALSE;
+                    break;
+                }
+                }
+
+            if ( xAllCoresReady == pdTRUE )
+            {
+                break;
+            }
+        }
+    #else /* if ( configNUMBER_OF_CORES > 1 ) */
+        /* Start the timer that generates the tick ISR. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count ready for the first task. */
+        ulCriticalNesting = 0;
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
     {
@@ -1856,7 +1887,11 @@
      * functionality by defining configTASK_RETURN_ADDRESS. Call
      * vTaskSwitchContext() so link time optimization does not remove the
      * symbol. */
-    vTaskSwitchContext();
+    #if ( configNUMBER_OF_CORES > 1 )
+        vTaskSwitchContext( portGET_CORE_ID() );
+    #else
+        vTaskSwitchContext();
+    #endif
     prvTaskExitError();
 
     /* Should not get here. */
@@ -1868,7 +1903,11 @@
 {
     /* Not implemented in ports where there is nothing to return to.
      * Artificially force an assert. */
-    configASSERT( ulCriticalNesting == 1000UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == 1000UL );
+    #else /* if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == 1000UL );
+    #endif /* if ( configNUMBER_OF_CORES == 1 ) */
 }
 /*-----------------------------------------------------------*/
 
@@ -2151,6 +2190,90 @@
 #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
 /*-----------------------------------------------------------*/
 
+void vPortConfigureInterruptPriorities( void ) /* PRIVILEGED_FUNCTION */
+{
+    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
+    {
+        volatile uint32_t ulImplementedPrioBits = 0;
+        volatile uint8_t ucMaxPriorityValue;
+
+        /* Determine the maximum priority from which ISR safe FreeRTOS API
+        * functions can be called. ISR safe functions are those that end in
+        * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
+        * ensure interrupt entry is as fast and simple as possible.
+        *
+        * First, determine the number of priority bits available. Write to all
+        * possible bits in the priority setting for SVCall. */
+        portNVIC_SHPR2_REG = 0xFF000000;
+
+        /* Read the value back to see how many bits stuck. */
+        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
+
+        /* Use the same mask on the maximum system call priority. */
+        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
+
+        /* Check that the maximum system call priority is nonzero after
+        * accounting for the number of priority bits supported by the
+        * hardware. A priority of 0 is invalid because setting the BASEPRI
+        * register to 0 unmasks all interrupts, and interrupts with priority 0
+        * cannot be masked using BASEPRI.
+        * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+        configASSERT( ucMaxSysCallPriority );
+
+        /* Check that the bits not implemented in hardware are zero in
+        * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
+        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
+
+        /* Calculate the maximum acceptable priority group value for the number
+        * of bits read back. */
+        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
+        {
+            ulImplementedPrioBits++;
+            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
+        }
+
+        if( ulImplementedPrioBits == 8 )
+        {
+            /* When the hardware implements 8 priority bits, there is no way for
+            * the software to configure PRIGROUP to not have sub-priorities. As
+            * a result, the least significant bit is always used for sub-priority
+            * and there are 128 preemption priorities and 2 sub-priorities.
+            *
+            * This may cause some confusion in some cases - for example, if
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
+            * priority interrupts will be masked in Critical Sections as those
+            * are at the same preemption priority. This may appear confusing as
+            * 4 is higher (numerically lower) priority than
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
+            * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
+            * to 4, this confusion does not happen and the behaviour remains the same.
+            *
+            * The following assert ensures that the sub-priority bit in the
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
+            * confusion. */
+            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
+            ulMaxPRIGROUPValue = 0;
+        }
+        else
+        {
+            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
+        }
+
+        /* Shift the priority group value back to its position within the AIRCR
+        * register. */
+        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
+        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
+    }
+    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
+
+    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
+    * the highest priority. */
+    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
+    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
+    portNVIC_SHPR2_REG = 0;
+}
+/*-----------------------------------------------------------*/
+
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) )
 
     void vPortGrantAccessToKernelObject( TaskHandle_t xInternalTaskHandle,
@@ -2247,36 +2370,214 @@
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
-
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
-    {
-        uint32_t ulControl = 0x0;
-
-        /* Ensure that PACBTI is implemented. */
-        configASSERT( portID_ISAR5_REG != 0x0 );
-
-        /* Enable UsageFault exception. */
-        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
-
-        #if ( configENABLE_PAC == 1 )
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #else /* configNUMBER_OF_CORES > 1 */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #endif /* configNUMBER_OF_CORES */
         {
-            ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
-        }
-        #endif
+            uint32_t ulControl = 0x0;
 
-        #if ( configENABLE_BTI == 1 )
-        {
-            ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
-        }
-        #endif
+            /* Ensure that PACBTI is implemented. */
+            configASSERT( portID_ISAR5_REG != 0x0 );
 
-        if( xWriteControlRegister == pdTRUE )
-        {
-            __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
-        }
+            /* Enable UsageFault exception. */
+            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
 
-        return ulControl;
-    }
+            #if ( configENABLE_PAC == 1 )
+            {
+                ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
+            }
+            #endif
+
+            #if ( configENABLE_BTI == 1 )
+            {
+                ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
+            }
+            #endif
+
+            if( xWriteControlRegister == pdTRUE )
+            {
+                __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
+            }
+
+            return ulControl;
+        }
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 /*-----------------------------------------------------------*/
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /* Which core owns the lock? */
+    PRIVILEGED_DATA volatile uint32_t ulOwnedByCore[ portMAX_CORE_COUNT ];
+    /* Lock count a core owns. */
+    PRIVILEGED_DATA volatile uint32_t ulRecursionCountByLock[ eLockCount ];
+    /* Index 0 is used for ISR lock and Index 1 is used for task lock. */
+    PRIVILEGED_DATA volatile uint32_t ulGateWord[ eLockCount ];
+
+    __attribute__((weak)) void vInterruptCore( uint8_t ucCoreID )
+    {
+        /* Default weak stub - platform specific implementation may override. */
+        ( void ) ucCoreID;
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline void prvSpinUnlock( volatile uint32_t * ulLock )
+    {
+        /* Conservative unlock: preserve original barriers for broad HW/FVP. */
+        __asm volatile (
+            "dmb sy         \n"
+            "mov r1, #0     \n"
+            "str r1, [%0]   \n"
+            "sev            \n"
+            "dsb            \n"
+            "isb            \n"
+            :
+            : "r" ( ulLock )
+            : "memory", "r1"
+        );
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline uint32_t prvSpinTrylock( volatile uint32_t * ulLock )
+    {
+        /*
+         * Conservative ldrex/strex trylock:
+         * - Return 1 immediately if busy, clearing exclusive state (CLREX).
+         * - Retry strex only on spurious failure when observed free.
+         * - DMB on success to preserve expected acquire semantics.
+         */
+        uint32_t ulVal;
+        uint32_t ulStatus;
+
+        __asm volatile (
+            " ldrex %0, [%1]   \n"
+            : "=r" ( ulVal )
+            : "r" ( ulLock )
+            : "memory"
+        );
+
+        if( ulVal != 0U )
+        {
+            __asm volatile ("clrex" ::: "memory");
+            return 1U;
+        }
+
+        __asm volatile (
+            " strex %0, %2, [%1]   \n"
+            : "=&r" ( ulStatus )
+            : "r" ( ulLock ), "r" (1U)
+            : "memory"
+        );
+
+        if( ulStatus != 0U )
+        {
+            return 1U;
+        }
+        __asm volatile ( "dmb" ::: "memory" );
+        return 0U;
+    }
+
+
+/*-----------------------------------------------------------*/
+
+    /* Read 32b value shared between cores. */
+    static inline uint32_t prvGet32( volatile uint32_t * x )
+    {
+        __asm( "dsb" );
+        return *x;
+    }
+
+/*-----------------------------------------------------------*/
+
+    /* Write 32b value shared between cores. */
+    static inline void prvSet32( volatile uint32_t * x,
+                                 uint32_t value )
+    {
+        *x = value;
+        __asm( "dsb" );
+    }
+
+/*-----------------------------------------------------------*/
+
+    void vPortRecursiveLock( uint8_t ucCoreID,
+                             ePortRTOSLock eLockNum,
+                             BaseType_t uxAcquire )
+    {
+        /* Validate the core ID and lock number. */
+        configASSERT( ucCoreID < portMAX_CORE_COUNT );
+        configASSERT( eLockNum < eLockCount );
+
+        uint32_t ulLockBit = 1u << eLockNum;
+
+        /* Lock acquire */
+        if( uxAcquire )
+        {
+            /* Check if spinlock is available. */
+            /* If spinlock is not available check if the core owns the lock. */
+            /* If the core owns the lock wait increment the lock count by the core. */
+            /* If core does not own the lock wait for the spinlock. */
+            if( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+            {
+                /* Check if the core owns the spinlock. */
+                if( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit )
+                {
+                    configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != portUINT32_MAX );
+                    prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) + 1 ) );
+                    return;
+                }
+
+                /* Preload the gate word into the cache. */
+                uint32_t dummy = ulGateWord[ eLockNum ];
+                dummy++;
+
+                while( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+                {
+                    __asm volatile ( "wfe" );
+                }
+            }
+
+            /* Add barrier to ensure lock is taken before we proceed. */
+            __asm volatile( "dmb sy" ::: "memory" );
+
+            /* Assert the lock count is 0 when the spinlock is free and is acquired. */
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) == 0 );
+
+            /* Set lock count as 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], 1 );
+            /* Set ulOwnedByCore. */
+            prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) | ulLockBit ) );
+        }
+        /* Lock release. */
+        else
+        {
+            /* Assert the lock is not free already. */
+            configASSERT( ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit ) != 0 );
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != 0 );
+
+            /* Reduce ulRecursionCountByLock by 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) - 1 ) );
+
+            if( !prvGet32( &ulRecursionCountByLock[ eLockNum ] ) )
+            {
+                prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ~ulLockBit ) );
+                prvSpinUnlock( &ulGateWord[ eLockNum ] );
+                /* Add barrier to ensure lock status is reflected before we proceed. */
+                __asm volatile( "dmb sy" ::: "memory" );
+            }
+        }
+    }
+
+/*-----------------------------------------------------------*/
+
+    uint8_t ucPortGetCoreID( void )
+    {
+        return *(volatile uint8_t *)(configCORE_ID_REGISTER);
+    }
+
+/*-----------------------------------------------------------*/
+
+#endif /* if( configNUMBER_OF_CORES > 1 ) */
diff --git a/Source/portable/GCC/ARM_CM85/non_secure/portasm.c b/Source/portable/GCC/ARM_CM85/non_secure/portasm.c
index bdee088..6bc070d 100644
--- a/Source/portable/GCC/ARM_CM85/non_secure/portasm.c
+++ b/Source/portable/GCC/ARM_CM85/non_secure/portasm.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  * Copyright 2024 Arm Limited and/or its affiliates
  * <open-source-office@arm.com>
@@ -46,6 +46,16 @@
 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
 
 #if ( configENABLE_MPU == 1 )
+    #if ( configENABLE_PAC == 1 )
+        #define SECURE_CONTEXT_OFFSET   -36
+    #else
+        #define SECURE_CONTEXT_OFFSET   -20
+    #endif
+#else
+    #define SECURE_CONTEXT_OFFSET       0
+#endif
+
+#if ( configENABLE_MPU == 1 )
 
     void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
     {
@@ -609,13 +619,13 @@
     (
         "   .syntax unified                                 \n"
         "                                                   \n"
-        "   ldr r2, [r0]                                    \n" /* The first item in the TCB is the top of the stack. */
-        "   ldr r1, [r2]                                    \n" /* The first item on the stack is the task's xSecureContext. */
+        "   ldr r2, [r0]                                    \n" /* The first item in the TCB is the stored context location. */
+        "   ldr r1, [r2, %0]                                \n" /* Read xSecureContext from the task's context. */
         "   cmp r1, #0                                      \n" /* Raise svc if task's xSecureContext is not NULL. */
         "   it ne                                           \n"
-        "   svcne %0                                        \n" /* Secure context is freed in the supervisor call. */
+        "   svcne %1                                        \n" /* Secure context is freed in the supervisor call. */
         "   bx lr                                           \n" /* Return. */
-        ::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
+        ::"i" ( SECURE_CONTEXT_OFFSET ), "i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
     );
 }
 /*-----------------------------------------------------------*/
diff --git a/Source/portable/GCC/ARM_CM85/non_secure/portasm.h b/Source/portable/GCC/ARM_CM85/non_secure/portasm.h
index 53b4b6e..b4b545f 100644
--- a/Source/portable/GCC/ARM_CM85/non_secure/portasm.h
+++ b/Source/portable/GCC/ARM_CM85/non_secure/portasm.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM85/non_secure/portmacro.h b/Source/portable/GCC/ARM_CM85/non_secure/portmacro.h
index 3386f52..892228d 100644
--- a/Source/portable/GCC/ARM_CM85/non_secure/portmacro.h
+++ b/Source/portable/GCC/ARM_CM85/non_secure/portmacro.h
@@ -1,6 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * Copyright 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -57,6 +58,7 @@
 #define portHAS_ARMV8M_MAIN_EXTENSION    1
 #define portARMV8M_MINOR_VERSION         1
 #define portDONT_DISCARD                 __attribute__( ( used ) )
+#define portVALIDATED_FOR_SMP            0
 /*-----------------------------------------------------------*/
 
 /* ARMv8-M common port configurations. */
diff --git a/Source/portable/GCC/ARM_CM85/non_secure/portmacrocommon.h b/Source/portable/GCC/ARM_CM85/non_secure/portmacrocommon.h
index 2dfac6a..c34fdee 100644
--- a/Source/portable/GCC/ARM_CM85/non_secure/portmacrocommon.h
+++ b/Source/portable/GCC/ARM_CM85/non_secure/portmacrocommon.h
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -59,6 +58,19 @@
     #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h.  Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
 #endif /* configENABLE_TRUSTZONE */
 
+#if ( configNUMBER_OF_CORES > 1 )
+    #if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 )
+        #error "Multi-core SMP is currently only validated for Cortex-M33 non-TrustZone non-MPU port."
+    #endif /* if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 ) ) */
+
+    #ifndef configCORE_ID_REGISTER
+        #error "configCORE_ID_REGISTER must be defined to the address of the register used to identify the core executing the code."
+    #endif /* ifndef configCORE_ID_REGISTER */
+
+    #ifndef configWAKE_SECONDARY_CORES
+        #error "configWAKE_SECONDARY_CORES must be defined to a function that wakes the secondary cores."
+    #endif /* ifndef configWAKE_SECONDARY_CORES */
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -428,10 +440,26 @@
 /**
  * @brief Critical section management.
  */
+
+#define portSET_INTERRUPT_MASK()                  ulSetInterruptMask()
+#define portCLEAR_INTERRUPT_MASK( x )             vClearInterruptMask( x )
 #define portSET_INTERRUPT_MASK_FROM_ISR()         ulSetInterruptMask()
 #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x )    vClearInterruptMask( x )
-#define portENTER_CRITICAL()                      vPortEnterCritical()
-#define portEXIT_CRITICAL()                       vPortExitCritical()
+
+#if ( configNUMBER_OF_CORES == 1 )
+    #define portENTER_CRITICAL()                      vPortEnterCritical()
+    #define portEXIT_CRITICAL()                       vPortExitCritical()
+#else /* ( configNUMBER_OF_CORES == 1 ) */
+    extern void vTaskEnterCritical( void );
+    extern void vTaskExitCritical( void );
+    extern UBaseType_t vTaskEnterCriticalFromISR( void );
+    extern void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus );
+
+    #define portENTER_CRITICAL()                      vTaskEnterCritical()
+    #define portEXIT_CRITICAL()                       vTaskExitCritical()
+    #define portENTER_CRITICAL_FROM_ISR()             vTaskEnterCriticalFromISR()
+    #define portEXIT_CRITICAL_FROM_ISR( x )           vTaskExitCriticalFromISR( x )
+#endif /* if ( configNUMBER_OF_CORES != 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -526,7 +554,7 @@
 /* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION
  * based on whether or not Mainline extension is implemented. */
 #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
-    #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 )
+    #if ( ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) && ( configNUMBER_OF_CORES == 1 ) )
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    1
     #else
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    0
@@ -573,6 +601,44 @@
 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
 /*-----------------------------------------------------------*/
 
+
+#if ( configNUMBER_OF_CORES > 1 )
+    typedef enum
+    {
+        eIsrLock = 0,
+        eTaskLock,
+        eLockCount
+    } ePortRTOSLock;
+
+    extern volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ];
+    extern void vPortRecursiveLock( uint8_t ucCoreID,
+                                    ePortRTOSLock eLockNum,
+                                    BaseType_t uxAcquire );
+    extern uint8_t ucPortGetCoreID( void );
+    extern void vInterruptCore( uint8_t ucCoreID );
+
+    #define portGET_CORE_ID()                                  ucPortGetCoreID()
+
+    #define portGET_CRITICAL_NESTING_COUNT( xCoreID )          ( ulCriticalNestings[ ( uint8_t ) xCoreID ] )
+    #define portSET_CRITICAL_NESTING_COUNT( xCoreID, x )       ( ulCriticalNestings[ ( uint8_t ) xCoreID ] = ( x ) )
+    #define portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]++ )
+    #define portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]-- )
+
+    #define portMAX_CORE_COUNT                                 ( configNUMBER_OF_CORES )
+
+    #define portYIELD_CORE( xCoreID )                          vInterruptCore( xCoreID )
+
+    #define portRELEASE_ISR_LOCK( xCoreID )                    vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdFALSE )
+    #define portGET_ISR_LOCK( xCoreID )                        vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdTRUE )
+
+    #define portRELEASE_TASK_LOCK( xCoreID )                   vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdFALSE )
+    #define portGET_TASK_LOCK( xCoreID )                       vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdTRUE )
+
+    #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* ( configENABLE_PAC == 1 || configENABLE_BTI == 1 ) */
+#endif
+
 /* *INDENT-OFF* */
 #ifdef __cplusplus
     }
diff --git a/Source/portable/GCC/ARM_CM85/secure/secure_context.c b/Source/portable/GCC/ARM_CM85/secure/secure_context.c
index 62bcfa1..2dae022 100644
--- a/Source/portable/GCC/ARM_CM85/secure/secure_context.c
+++ b/Source/portable/GCC/ARM_CM85/secure/secure_context.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -213,8 +213,19 @@
         /* Were we able to get a free context? */
         if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS )
         {
-            /* Allocate the stack space. */
-            pucStackMemory = pvPortMalloc( ulSecureStackSize + securecontextSTACK_SEAL_SIZE );
+            /* Allocate the stack space if possible. */
+            if( ( ulSecureStackSize < securecontextSTACK_SEAL_SIZE ) ||
+                ( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) )
+            {
+                /* Reject stacks that are too small (the CONTROL word would be
+                 * written before the allocation, corrupting the secure heap)
+                 * and sizes that would overflow when the seal size is added. */
+                pucStackMemory = NULL;
+            }
+            else
+            {
+                pucStackMemory = pvPortMalloc( ulSecureStackSize + securecontextSTACK_SEAL_SIZE );
+            }
 
             if( pucStackMemory != NULL )
             {
@@ -279,9 +290,12 @@
                                                               void * pvTaskHandle )
 {
     uint32_t ulIPSR, ulSecureContextIndex;
+    uint8_t * pucStackLimit;
 
-    /* Read the Interrupt Program Status Register (IPSR) value. */
+    /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
+     * Register (PSPLIM) value. */
     secureportREAD_IPSR( ulIPSR );
+    secureportREAD_PSPLIM( pucStackLimit );
 
     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
      * when the processor is running in the Thread Mode. */
@@ -293,8 +307,14 @@
             ulSecureContextIndex = xSecureContextHandle - 1UL;
 
             /* Ensure that the secure context being deleted is associated with
-             * the task. */
-            if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
+             * the task and is NOT the currently-loaded context. Freeing a
+             * context whose stack is currently loaded in PSPLIM would leave the
+             * running task referencing freed secure memory (use-after-free).
+             * pvTaskHandle is supplied by the non-secure side and is untrusted,
+             * so it is used only as an additional ownership match, not as
+             * authority. */
+            if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) &&
+                ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) )
             {
                 /* Free the stack space. */
                 vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
@@ -342,7 +362,7 @@
 
         secureportREAD_PSPLIM( pucStackLimit );
 
-        /* Ensure that task's context is loaded and the task is saving it's own
+        /* Ensure that task's context is loaded and the task is saving its own
          * context. */
         if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) &&
             ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) )
diff --git a/Source/portable/GCC/ARM_CM85/secure/secure_context.h b/Source/portable/GCC/ARM_CM85/secure/secure_context.h
index 8b93857..51dd823 100644
--- a/Source/portable/GCC/ARM_CM85/secure/secure_context.h
+++ b/Source/portable/GCC/ARM_CM85/secure/secure_context.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM85/secure/secure_context_port.c b/Source/portable/GCC/ARM_CM85/secure/secure_context_port.c
index 11d8e1b..ef5cbf7 100644
--- a/Source/portable/GCC/ARM_CM85/secure/secure_context_port.c
+++ b/Source/portable/GCC/ARM_CM85/secure/secure_context_port.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM85/secure/secure_heap.c b/Source/portable/GCC/ARM_CM85/secure/secure_heap.c
index b0e83b4..58226bf 100644
--- a/Source/portable/GCC/ARM_CM85/secure/secure_heap.c
+++ b/Source/portable/GCC/ARM_CM85/secure/secure_heap.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM85/secure/secure_heap.h b/Source/portable/GCC/ARM_CM85/secure/secure_heap.h
index 61a96da..906fa24 100644
--- a/Source/portable/GCC/ARM_CM85/secure/secure_heap.h
+++ b/Source/portable/GCC/ARM_CM85/secure/secure_heap.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM85/secure/secure_init.c b/Source/portable/GCC/ARM_CM85/secure/secure_init.c
index f7f7e67..6996692 100644
--- a/Source/portable/GCC/ARM_CM85/secure/secure_init.c
+++ b/Source/portable/GCC/ARM_CM85/secure/secure_init.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM85/secure/secure_init.h b/Source/portable/GCC/ARM_CM85/secure/secure_init.h
index 46ffbd9..4e7bd40 100644
--- a/Source/portable/GCC/ARM_CM85/secure/secure_init.h
+++ b/Source/portable/GCC/ARM_CM85/secure/secure_init.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM85/secure/secure_port_macros.h b/Source/portable/GCC/ARM_CM85/secure/secure_port_macros.h
index 34494e1..72774eb 100644
--- a/Source/portable/GCC/ARM_CM85/secure/secure_port_macros.h
+++ b/Source/portable/GCC/ARM_CM85/secure/secure_port_macros.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM85_NTZ/non_secure/mpu_wrappers_v2_asm.c b/Source/portable/GCC/ARM_CM85_NTZ/non_secure/mpu_wrappers_v2_asm.c
index 8504ddd..63d1b52 100644
--- a/Source/portable/GCC/ARM_CM85_NTZ/non_secure/mpu_wrappers_v2_asm.c
+++ b/Source/portable/GCC/ARM_CM85_NTZ/non_secure/mpu_wrappers_v2_asm.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM85_NTZ/non_secure/port.c b/Source/portable/GCC/ARM_CM85_NTZ/non_secure/port.c
index f16a343..007150c 100644
--- a/Source/portable/GCC/ARM_CM85_NTZ/non_secure/port.c
+++ b/Source/portable/GCC/ARM_CM85_NTZ/non_secure/port.c
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024-2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -145,13 +144,13 @@
 /**
  * @brief Constants required to manipulate the FPU.
  */
-#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 )              /* Coprocessor Access Control Register. */
+#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */
 #define portCPACR_CP10_VALUE    ( 3UL )
 #define portCPACR_CP11_VALUE    portCPACR_CP10_VALUE
 #define portCPACR_CP10_POS      ( 20UL )
 #define portCPACR_CP11_POS      ( 22UL )
 
-#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 )              /* Floating Point Context Control Register. */
+#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
 #define portFPCCR_ASPEN_POS     ( 31UL )
 #define portFPCCR_ASPEN_MASK    ( 1UL << portFPCCR_ASPEN_POS )
 #define portFPCCR_LSPEN_POS     ( 30UL )
@@ -188,8 +187,8 @@
 #define portMPU_MAIR0_REG                       ( *( ( volatile uint32_t * ) 0xe000edc0 ) )
 #define portMPU_MAIR1_REG                       ( *( ( volatile uint32_t * ) 0xe000edc4 ) )
 
-#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
-#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
+#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
+#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
 
 #define portMPU_RBAR_ACCESS_PERMISSIONS_MASK    ( 3UL << 1UL )
 
@@ -230,8 +229,8 @@
 
 #if ( portARMV8M_MINOR_VERSION >= 1 )
 
-/* Enable Privileged eXecute Never MPU attribute for the selected memory
- * region. */
+    /* Enable Privileged eXecute Never MPU attribute for the selected memory
+     * region. */
     #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER    ( 1UL << 4UL )
 #endif /* portARMV8M_MINOR_VERSION >= 1 */
 
@@ -241,9 +240,6 @@
 /* Enable MPU. */
 #define portMPU_ENABLE_BIT                    ( 1UL << 0UL )
 
-/* Expected value of the portMPU_TYPE register. */
-#define portEXPECTED_MPU_TYPE_VALUE           ( configTOTAL_MPU_REGIONS << 8UL )
-
 /* Extract first address of the MPU region as encoded in the
  * RBAR (Region Base Address Register) value. */
 #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@@ -291,37 +287,37 @@
 
 #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         FD
- * 1111 1111  1111 1111  1111 1111  1111 1101
- *
- * Bit[6] - 1 --> The exception was taken from the Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 1 --> The exception was taken to the Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         FD
+     * 1111 1111  1111 1111  1111 1111  1111 1101
+     *
+     * Bit[6] - 1 --> The exception was taken from the Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 1 --> The exception was taken to the Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xfffffffd )
 #else
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         BC
- * 1111 1111  1111 1111  1111 1111  1011 1100
- *
- * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         BC
+     * 1111 1111  1111 1111  1111 1111  1011 1100
+     *
+     * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xffffffbc )
 #endif /* configRUN_FREERTOS_SECURE_ONLY */
 
@@ -401,50 +397,54 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Extract MPU region's access permissions from the Region Base Address
- * Register (RBAR) value.
- *
- * @param ulRBARValue RBAR value for the MPU region.
- *
- * @return uint32_t Access permissions.
- */
+    /**
+     * @brief Extract MPU region's access permissions from the Region Base Address
+     * Register (RBAR) value.
+     *
+     * @param ulRBARValue RBAR value for the MPU region.
+     *
+     * @return uint32_t Access permissions.
+     */
     static uint32_t prvGetRegionAccessPermissions( uint32_t ulRBARValue ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU == 1 && configUSE_MPU_WRAPPERS_V1 == 0 */
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Setup the Memory Protection Unit (MPU).
- */
+    /**
+     * @brief Setup the Memory Protection Unit (MPU).
+     */
     static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU */
 
 #if ( configENABLE_FPU == 1 )
 
-/**
- * @brief Setup the Floating Point Unit (FPU).
- */
+    /**
+     * @brief Setup the Floating Point Unit (FPU).
+     */
     static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_FPU */
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
 
-/**
- * @brief Configures PACBTI features.
- *
- * This function configures the Pointer Authentication, and Branch Target
- * Identification security features as per the user configuration. It returns
- * the value of the special purpose CONTROL register accordingly, and optionally
- * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
- * architecture based) target supports PACBTI security feature.
- *
- * @param xWriteControlRegister Used to control whether the special purpose
- * CONTROL register should be updated or not.
- *
- * @return CONTROL register value according to the configured PACBTI option.
- */
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    /**
+     * @brief Configures PACBTI features.
+     *
+     * This function configures the Pointer Authentication, and Branch Target
+     * Identification security features as per the user configuration. It returns
+     * the value of the special purpose CONTROL register accordingly, and optionally
+     * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
+     * architecture based) target supports PACBTI security feature.
+     *
+     * @param xWriteControlRegister Used to control whether the special purpose
+     * CONTROL register should be updated or not.
+     *
+     * @return CONTROL register value according to the configured PACBTI option.
+     */
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -491,14 +491,14 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the system call stack so that upon returning from
- * SVC, the system call stack is used.
- *
- * @param pulTaskStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- * @param ucSystemCallNumber The system call number of the system call.
- */
+    /**
+     * @brief Sets up the system call stack so that upon returning from
+     * SVC, the system call stack is used.
+     *
+     * @param pulTaskStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     * @param ucSystemCallNumber The system call number of the system call.
+     */
     void vSystemCallEnter( uint32_t * pulTaskStack,
                            uint32_t ulLR,
                            uint8_t ucSystemCallNumber ) PRIVILEGED_FUNCTION;
@@ -507,22 +507,22 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Raise SVC for exiting from a system call.
- */
+    /**
+     * @brief Raise SVC for exiting from a system call.
+     */
     void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the task stack so that upon returning from
- * SVC, the task stack is used again.
- *
- * @param pulSystemCallStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- */
+    /**
+     * @brief Sets up the task stack so that upon returning from
+     * SVC, the task stack is used again.
+     *
+     * @param pulSystemCallStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     */
     void vSystemCallExit( uint32_t * pulSystemCallStack,
                           uint32_t ulLR ) PRIVILEGED_FUNCTION;
 
@@ -530,21 +530,38 @@
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Checks whether or not the calling task is privileged.
- *
- * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
- */
+    /**
+     * @brief Checks whether or not the calling task is privileged.
+     *
+     * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
+     */
     BaseType_t xPortIsTaskPrivileged( void ) PRIVILEGED_FUNCTION;
 
 #endif /* configENABLE_MPU == 1 */
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /**
+     * @brief Platform/Application-defined function that wakes up the secondary cores.
+     *
+     * @return pdTRUE if the secondary cores were successfully woken up.
+     *         pdFALSE otherwise.
+     */
+    extern BaseType_t configWAKE_SECONDARY_CORES( void );
+
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
+
+/**
+ * @brief Configures interrupt priorities.
+ */
+void vPortConfigureInterruptPriorities( void ) PRIVILEGED_FUNCTION;
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief This variable is set to pdTRUE when the scheduler is started.
- */
+    /**
+     * @brief This variable is set to pdTRUE when the scheduler is started.
+     */
     PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
@@ -553,14 +570,22 @@
  * @brief Each task maintains its own interrupt status in the critical nesting
  * variable.
  */
-PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
+#if ( configNUMBER_OF_CORES == 1 )
+    PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0UL;
+#else /* #if ( configNUMBER_OF_CORES == 1 ) */
+    PRIVILEGED_DATA volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ] = { 0 };
+    /* Flags to check if the secondary cores are ready. */
+    PRIVILEGED_DATA volatile uint8_t ucSecondaryCoresReadyFlags[ configNUMBER_OF_CORES - 1 ] = { 0 };
+    /* Flag to indicate that the primary core has completed its initialisation. */
+    PRIVILEGED_DATA volatile uint8_t ucPrimaryCoreInitDoneFlag = 0;
+ #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #if ( configENABLE_TRUSTZONE == 1 )
 
-/**
- * @brief Saved as part of the task context to indicate which context the
- * task is using on the secure side.
- */
+    /**
+     * @brief Saved as part of the task context to indicate which context the
+     * task is using on the secure side.
+     */
     PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
 #endif /* configENABLE_TRUSTZONE */
 
@@ -579,21 +604,21 @@
 
 #if ( configUSE_TICKLESS_IDLE == 1 )
 
-/**
- * @brief The number of SysTick increments that make up one tick period.
- */
+    /**
+     * @brief The number of SysTick increments that make up one tick period.
+     */
     PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
 
-/**
- * @brief The maximum number of tick periods that can be suppressed is
- * limited by the 24 bit resolution of the SysTick timer.
- */
+    /**
+     * @brief The maximum number of tick periods that can be suppressed is
+     * limited by the 24 bit resolution of the SysTick timer.
+     */
     PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
 
-/**
- * @brief Compensate for the CPU cycles that pass while the SysTick is
- * stopped (low power functionality only).
- */
+    /**
+     * @brief Compensate for the CPU cycles that pass while the SysTick is
+     * stopped (low power functionality only).
+     */
     PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0;
 #endif /* configUSE_TICKLESS_IDLE */
 /*-----------------------------------------------------------*/
@@ -856,7 +881,11 @@
      * should instead call vTaskDelete( NULL ). Artificially force an assert()
      * to be triggered if configASSERT() is defined, then stop here so
      * application writers can catch the error. */
-    configASSERT( ulCriticalNesting == ~0UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == ~0UL );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == ~0UL );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
     portDISABLE_INTERRUPTS();
 
     while( ulDummy == 0 )
@@ -925,64 +954,57 @@
         /* The only permitted number of regions are 8 or 16. */
         configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 16 ) );
 
-        /* Ensure that the configTOTAL_MPU_REGIONS is configured correctly. */
-        configASSERT( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE );
+        /* MAIR0 - Index 0. */
+        portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
+        /* MAIR0 - Index 1. */
+        portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
 
-        /* Check that the MPU is present. */
-        if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
-        {
-            /* MAIR0 - Index 0. */
-            portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
-            /* MAIR0 - Index 1. */
-            portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
+        /* Setup privileged flash as Read Only so that privileged tasks can
+         * read it but not modify. */
+        portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup privileged flash as Read Only so that privileged tasks can
-             * read it but not modify. */
-            portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged flash as Read Only by both privileged and
+         * unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged flash as Read Only by both privileged and
-             * unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged syscalls flash as Read Only by both privileged
+         * and unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged syscalls flash as Read Only by both privileged
-             * and unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup RAM containing kernel data for privileged access only. */
+        portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
+                           ( portMPU_REGION_EXECUTE_NEVER );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup RAM containing kernel data for privileged access only. */
-            portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
-                               ( portMPU_REGION_EXECUTE_NEVER );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Enable mem fault. */
+        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
 
-            /* Enable mem fault. */
-            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
-
-            /* Enable MPU with privileged background access i.e. unmapped
-             * regions have privileged access. */
-            portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
-        }
+        /* Enable MPU with privileged background access i.e. unmapped
+         * regions have privileged access. */
+        portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
     }
 
 #endif /* configENABLE_MPU */
@@ -1027,28 +1049,29 @@
 }
 /*-----------------------------------------------------------*/
 
-void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    portDISABLE_INTERRUPTS();
-    ulCriticalNesting++;
-
-    /* Barriers are normally not required but do ensure the code is
-     * completely within the specified behaviour for the architecture. */
-    __asm volatile ( "dsb" ::: "memory" );
-    __asm volatile ( "isb" );
-}
-/*-----------------------------------------------------------*/
-
-void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    configASSERT( ulCriticalNesting );
-    ulCriticalNesting--;
-
-    if( ulCriticalNesting == 0 )
+#if ( configNUMBER_OF_CORES == 1 )
+    void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
     {
-        portENABLE_INTERRUPTS();
+        portDISABLE_INTERRUPTS();
+        ulCriticalNesting++;
+        /* Barriers are normally not required but do ensure the code is
+        * completely within the specified behaviour for the architecture. */
+        __asm volatile ( "dsb" ::: "memory" );
+        __asm volatile ( "isb" );
     }
-}
+    /*-----------------------------------------------------------*/
+
+    void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
+    {
+        configASSERT( ulCriticalNesting );
+        ulCriticalNesting--;
+
+        if( ulCriticalNesting == 0 )
+        {
+            portENABLE_INTERRUPTS();
+        }
+    }
+#endif /* configNUMBER_OF_CORES == 1 */
 /*-----------------------------------------------------------*/
 
 void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
@@ -1056,6 +1079,10 @@
     uint32_t ulPreviousMask;
 
     ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
+    #if ( configNUMBER_OF_CORES > 1 )
+        UBaseType_t uxSavedInterruptStatus = portENTER_CRITICAL_FROM_ISR();
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     traceISR_ENTER();
     {
         /* Increment the RTOS tick. */
@@ -1070,6 +1097,10 @@
             traceISR_EXIT();
         }
     }
+    #if ( configNUMBER_OF_CORES > 1 )
+        portEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
 }
 /*-----------------------------------------------------------*/
@@ -1078,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1090,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1108,38 +1151,42 @@
 
     switch( ucSVCNumber )
     {
-        #if ( configENABLE_TRUSTZONE == 1 )
-            case portSVC_ALLOCATE_SECURE_CONTEXT:
+    #if ( configENABLE_TRUSTZONE == 1 )
+        case portSVC_ALLOCATE_SECURE_CONTEXT:
 
-                /* R0 contains the stack size passed as parameter to the
-                 * vPortAllocateSecureContext function. */
-                ulR0 = pulCallerStackAddress[ 0 ];
+            /* R0 contains the stack size passed as parameter to the
+             * vPortAllocateSecureContext function. */
+            ulR0 = pulCallerStackAddress[ 0 ];
 
-                #if ( configENABLE_MPU == 1 )
-                {
-                    /* Read the CONTROL register value. */
-                    __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
+            #if ( configENABLE_MPU == 1 )
+            {
+                /* Read the CONTROL register value. */
+                __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
 
-                    /* The task that raised the SVC is privileged if Bit[0]
-                     * in the CONTROL register is 0. */
-                    ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
+                /* The task that raised the SVC is privileged if Bit[0]
+                 * in the CONTROL register is 0. */
+                ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
 
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
-                }
-                #else /* if ( configENABLE_MPU == 1 ) */
-                {
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
-                }
-                #endif /* configENABLE_MPU */
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
+            }
+            #else /* if ( configENABLE_MPU == 1 ) */
+            {
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
+            }
+            #endif /* configENABLE_MPU */
 
-                configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
-                SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
-                break;
+            configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
+            SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
+            break;
 
-            case portSVC_FREE_SECURE_CONTEXT:
-
+        case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
                 /* R0 contains TCB being freed and R1 contains the secure
                  * context handle to be freed. */
                 ulR0 = pulCallerStackAddress[ 0 ];
@@ -1147,51 +1194,62 @@
 
                 /* Free the secure context. */
                 SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
-                break;
-        #endif /* configENABLE_TRUSTZONE */
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
+            break;
+    #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
-            #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
-                case portSVC_RAISE_PRIVILEGE:
+    #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
+        case portSVC_RAISE_PRIVILEGE:
 
-                    /* Only raise the privilege, if the svc was raised from any of
-                     * the system calls. */
-                    if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
-                        ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
-                    {
-                        vRaisePrivilege();
-                    }
-                    break;
-            #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
+            /* Only raise the privilege, if the svc was raised from any of
+             * the system calls. */
+            if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
+                ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
+            {
+                vRaisePrivilege();
+            }
+            break;
+    #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
-            #if ( configENABLE_MPU == 1 )
-                case portSVC_YIELD:
-                    vPortYield();
-                    break;
-            #endif /* configENABLE_MPU == 1 */
+    #if ( configENABLE_MPU == 1 )
+        case portSVC_YIELD:
+            vPortYield();
+            break;
+    #endif /* configENABLE_MPU == 1 */
 
         default:
             /* Incorrect SVC call. */
@@ -1210,7 +1268,7 @@
         extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulSystemCallStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1246,12 +1304,16 @@
         {
             pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1261,20 +1323,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the system call stack for the stack frame. */
-            pulSystemCallStack = pulSystemCallStack - ulStackFrameSize;
+            pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulSystemCallStack[ i ] = pulTaskStack[ i ];
             }
@@ -1310,7 +1372,7 @@
 
             /* Remember the location where we should copy the stack frame when we exit from
              * the system call. */
-            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
+            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
 
             /* Record if the hardware used padding to force the stack pointer
              * to be double word aligned. */
@@ -1360,7 +1422,7 @@
         extern TaskHandle_t pxCurrentTCB;
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulTaskStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1392,12 +1454,16 @@
         {
             pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1407,20 +1473,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the task stack for the stack frame. */
-            pulTaskStack = pulTaskStack - ulStackFrameSize;
+            pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulTaskStack[ i ] = pulSystemCallStack[ i ];
             }
@@ -1518,21 +1584,21 @@
         xMPUSettings->ulContext[ ulIndex ] = 0x11111111; /* r11. */
         ulIndex++;
 
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters;            /* r0. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters; /* r0. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x01010101;                           /* r1. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x01010101; /* r1. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x02020202;                           /* r2. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x02020202; /* r2. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x03030303;                           /* r3. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x03030303; /* r3. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x12121212;                           /* r12. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x12121212; /* r12. */
         ulIndex++;
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) portTASK_RETURN_ADDRESS; /* LR. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode;                  /* PC. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode; /* PC. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR;                     /* xPSR. */
+        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR; /* xPSR. */
         ulIndex++;
 
         #if ( configENABLE_TRUSTZONE == 1 )
@@ -1543,14 +1609,18 @@
         #endif /* configENABLE_TRUSTZONE */
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) ( pxTopOfStack - 8 ); /* PSP with the hardware saved stack. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack;         /* PSPLIM. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack; /* PSPLIM. */
         ulIndex++;
 
         #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
         {
             /* Check PACBTI security feature configuration before pushing the
              * CONTROL register's value on task's TCB. */
-            ulControl = prvConfigurePACBTI( pdFALSE );
+            #if ( configNUMBER_OF_CORES == 1 )
+                ulControl = prvConfigurePACBTI( pdFALSE );
+            #else /* configNUMBER_OF_CORES > 1 */
+                ulControl = vConfigurePACBTI( pdFALSE );
+            #endif /* configNUMBER_OF_CORES */
         }
         #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1615,15 +1685,15 @@
          * interrupt. */
         #if ( portPRELOAD_REGISTERS == 0 )
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
-            pxTopOfStack -= 5;                                       /* R12, R3, R2 and R1. */
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
-            pxTopOfStack -= 9;                                       /* R11..R4, EXC_RETURN. */
+            pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
+            pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */
             *pxTopOfStack = portINITIAL_EXC_RETURN;
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
@@ -1637,42 +1707,42 @@
         }
         #else /* portPRELOAD_REGISTERS */
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x12121212UL;            /* R12. */
+            *pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x03030303UL;            /* R3. */
+            *pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x02020202UL;            /* R2. */
+            *pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x01010101UL;            /* R1. */
+            *pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x11111111UL;            /* R11. */
+            *pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x10101010UL;            /* R10. */
+            *pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x09090909UL;            /* R09. */
+            *pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x08080808UL;            /* R08. */
+            *pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x07070707UL;            /* R07. */
+            *pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x06060606UL;            /* R06. */
+            *pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x05050505UL;            /* R05. */
+            *pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x04040404UL;            /* R04. */
+            *pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04. */
             pxTopOfStack--;
-            *pxTopOfStack = portINITIAL_EXC_RETURN;                  /* EXC_RETURN. */
+            *pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxEndOfStack;            /* Slot used to hold this task's PSPLIM value. */
+            *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
 
             #if ( configENABLE_TRUSTZONE == 1 )
             {
@@ -1739,91 +1809,17 @@
     }
     #endif /* configCHECK_HANDLER_INSTALLATION */
 
-    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
-    {
-        volatile uint32_t ulImplementedPrioBits = 0;
-        volatile uint8_t ucMaxPriorityValue;
-
-        /* Determine the maximum priority from which ISR safe FreeRTOS API
-         * functions can be called. ISR safe functions are those that end in
-         * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
-         * ensure interrupt entry is as fast and simple as possible.
-         *
-         * First, determine the number of priority bits available. Write to all
-         * possible bits in the priority setting for SVCall. */
-        portNVIC_SHPR2_REG = 0xFF000000;
-
-        /* Read the value back to see how many bits stuck. */
-        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
-
-        /* Use the same mask on the maximum system call priority. */
-        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
-
-        /* Check that the maximum system call priority is nonzero after
-         * accounting for the number of priority bits supported by the
-         * hardware. A priority of 0 is invalid because setting the BASEPRI
-         * register to 0 unmasks all interrupts, and interrupts with priority 0
-         * cannot be masked using BASEPRI.
-         * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
-        configASSERT( ucMaxSysCallPriority );
-
-        /* Check that the bits not implemented in hardware are zero in
-         * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
-        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
-
-        /* Calculate the maximum acceptable priority group value for the number
-         * of bits read back. */
-        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
-        {
-            ulImplementedPrioBits++;
-            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
-        }
-
-        if( ulImplementedPrioBits == 8 )
-        {
-            /* When the hardware implements 8 priority bits, there is no way for
-             * the software to configure PRIGROUP to not have sub-priorities. As
-             * a result, the least significant bit is always used for sub-priority
-             * and there are 128 preemption priorities and 2 sub-priorities.
-             *
-             * This may cause some confusion in some cases - for example, if
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
-             * priority interrupts will be masked in Critical Sections as those
-             * are at the same preemption priority. This may appear confusing as
-             * 4 is higher (numerically lower) priority than
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
-             * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
-             * to 4, this confusion does not happen and the behaviour remains the same.
-             *
-             * The following assert ensures that the sub-priority bit in the
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
-             * confusion. */
-            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
-            ulMaxPRIGROUPValue = 0;
-        }
-        else
-        {
-            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
-        }
-
-        /* Shift the priority group value back to its position within the AIRCR
-         * register. */
-        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
-        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
-    }
-    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
-
-    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
-     * the highest priority. */
-    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
-    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
-    portNVIC_SHPR2_REG = 0;
+    vPortConfigureInterruptPriorities();
 
     #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
     {
         /* Set the CONTROL register value based on PACBTI security feature
          * configuration before starting the first task. */
-        ( void ) prvConfigurePACBTI( pdTRUE );
+        #if ( configNUMBER_OF_CORES == 1 )
+            ( void ) prvConfigurePACBTI( pdTRUE );
+        #else /* configNUMBER_OF_CORES > 1 */
+            ( void ) vConfigurePACBTI( pdTRUE );
+        #endif /* configNUMBER_OF_CORES */
     }
     #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1834,12 +1830,47 @@
     }
     #endif /* configENABLE_MPU */
 
-    /* Start the timer that generates the tick ISR. Interrupts are disabled
-     * here already. */
-    vPortSetupTimerInterrupt();
+    #if ( configNUMBER_OF_CORES > 1 )
+        /* Start the timer that generates the tick ISR. Interrupts are disabled
+         * here already. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count for all cores. */
+        for ( uint8_t ucCoreID = 0; ucCoreID < configNUMBER_OF_CORES; ucCoreID++ )
+        {
+            ulCriticalNestings[ ucCoreID ] = 0;
+        }
+        /* Signal that primary core has done all the necessary initialisations. */
+        ucPrimaryCoreInitDoneFlag = 1;
+        /* Wake up secondary cores */
+        BaseType_t xWakeResult = configWAKE_SECONDARY_CORES();
+        configASSERT( xWakeResult == pdTRUE );
 
-    /* Initialize the critical nesting count ready for the first task. */
-    ulCriticalNesting = 0;
+        /* Hold the primary core here until all the secondary cores are ready, this would be achieved only when
+         * all elements of ucSecondaryCoresReadyFlags are set.
+         */
+        while( 1 )
+        {
+            BaseType_t xAllCoresReady = pdTRUE;
+            for( uint8_t ucCoreID = 0; ucCoreID < ( configNUMBER_OF_CORES - 1 ); ucCoreID++ )
+            {
+                if( ucSecondaryCoresReadyFlags[ ucCoreID ] != pdTRUE )
+                {
+                    xAllCoresReady = pdFALSE;
+                    break;
+                }
+                }
+
+            if ( xAllCoresReady == pdTRUE )
+            {
+                break;
+            }
+        }
+    #else /* if ( configNUMBER_OF_CORES > 1 ) */
+        /* Start the timer that generates the tick ISR. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count ready for the first task. */
+        ulCriticalNesting = 0;
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
     {
@@ -1856,7 +1887,11 @@
      * functionality by defining configTASK_RETURN_ADDRESS. Call
      * vTaskSwitchContext() so link time optimization does not remove the
      * symbol. */
-    vTaskSwitchContext();
+    #if ( configNUMBER_OF_CORES > 1 )
+        vTaskSwitchContext( portGET_CORE_ID() );
+    #else
+        vTaskSwitchContext();
+    #endif
     prvTaskExitError();
 
     /* Should not get here. */
@@ -1868,7 +1903,11 @@
 {
     /* Not implemented in ports where there is nothing to return to.
      * Artificially force an assert. */
-    configASSERT( ulCriticalNesting == 1000UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == 1000UL );
+    #else /* if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == 1000UL );
+    #endif /* if ( configNUMBER_OF_CORES == 1 ) */
 }
 /*-----------------------------------------------------------*/
 
@@ -2151,6 +2190,90 @@
 #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
 /*-----------------------------------------------------------*/
 
+void vPortConfigureInterruptPriorities( void ) /* PRIVILEGED_FUNCTION */
+{
+    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
+    {
+        volatile uint32_t ulImplementedPrioBits = 0;
+        volatile uint8_t ucMaxPriorityValue;
+
+        /* Determine the maximum priority from which ISR safe FreeRTOS API
+        * functions can be called. ISR safe functions are those that end in
+        * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
+        * ensure interrupt entry is as fast and simple as possible.
+        *
+        * First, determine the number of priority bits available. Write to all
+        * possible bits in the priority setting for SVCall. */
+        portNVIC_SHPR2_REG = 0xFF000000;
+
+        /* Read the value back to see how many bits stuck. */
+        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
+
+        /* Use the same mask on the maximum system call priority. */
+        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
+
+        /* Check that the maximum system call priority is nonzero after
+        * accounting for the number of priority bits supported by the
+        * hardware. A priority of 0 is invalid because setting the BASEPRI
+        * register to 0 unmasks all interrupts, and interrupts with priority 0
+        * cannot be masked using BASEPRI.
+        * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+        configASSERT( ucMaxSysCallPriority );
+
+        /* Check that the bits not implemented in hardware are zero in
+        * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
+        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
+
+        /* Calculate the maximum acceptable priority group value for the number
+        * of bits read back. */
+        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
+        {
+            ulImplementedPrioBits++;
+            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
+        }
+
+        if( ulImplementedPrioBits == 8 )
+        {
+            /* When the hardware implements 8 priority bits, there is no way for
+            * the software to configure PRIGROUP to not have sub-priorities. As
+            * a result, the least significant bit is always used for sub-priority
+            * and there are 128 preemption priorities and 2 sub-priorities.
+            *
+            * This may cause some confusion in some cases - for example, if
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
+            * priority interrupts will be masked in Critical Sections as those
+            * are at the same preemption priority. This may appear confusing as
+            * 4 is higher (numerically lower) priority than
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
+            * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
+            * to 4, this confusion does not happen and the behaviour remains the same.
+            *
+            * The following assert ensures that the sub-priority bit in the
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
+            * confusion. */
+            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
+            ulMaxPRIGROUPValue = 0;
+        }
+        else
+        {
+            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
+        }
+
+        /* Shift the priority group value back to its position within the AIRCR
+        * register. */
+        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
+        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
+    }
+    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
+
+    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
+    * the highest priority. */
+    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
+    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
+    portNVIC_SHPR2_REG = 0;
+}
+/*-----------------------------------------------------------*/
+
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) )
 
     void vPortGrantAccessToKernelObject( TaskHandle_t xInternalTaskHandle,
@@ -2247,36 +2370,214 @@
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
-
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
-    {
-        uint32_t ulControl = 0x0;
-
-        /* Ensure that PACBTI is implemented. */
-        configASSERT( portID_ISAR5_REG != 0x0 );
-
-        /* Enable UsageFault exception. */
-        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
-
-        #if ( configENABLE_PAC == 1 )
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #else /* configNUMBER_OF_CORES > 1 */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #endif /* configNUMBER_OF_CORES */
         {
-            ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
-        }
-        #endif
+            uint32_t ulControl = 0x0;
 
-        #if ( configENABLE_BTI == 1 )
-        {
-            ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
-        }
-        #endif
+            /* Ensure that PACBTI is implemented. */
+            configASSERT( portID_ISAR5_REG != 0x0 );
 
-        if( xWriteControlRegister == pdTRUE )
-        {
-            __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
-        }
+            /* Enable UsageFault exception. */
+            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
 
-        return ulControl;
-    }
+            #if ( configENABLE_PAC == 1 )
+            {
+                ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
+            }
+            #endif
+
+            #if ( configENABLE_BTI == 1 )
+            {
+                ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
+            }
+            #endif
+
+            if( xWriteControlRegister == pdTRUE )
+            {
+                __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
+            }
+
+            return ulControl;
+        }
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 /*-----------------------------------------------------------*/
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /* Which core owns the lock? */
+    PRIVILEGED_DATA volatile uint32_t ulOwnedByCore[ portMAX_CORE_COUNT ];
+    /* Lock count a core owns. */
+    PRIVILEGED_DATA volatile uint32_t ulRecursionCountByLock[ eLockCount ];
+    /* Index 0 is used for ISR lock and Index 1 is used for task lock. */
+    PRIVILEGED_DATA volatile uint32_t ulGateWord[ eLockCount ];
+
+    __attribute__((weak)) void vInterruptCore( uint8_t ucCoreID )
+    {
+        /* Default weak stub - platform specific implementation may override. */
+        ( void ) ucCoreID;
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline void prvSpinUnlock( volatile uint32_t * ulLock )
+    {
+        /* Conservative unlock: preserve original barriers for broad HW/FVP. */
+        __asm volatile (
+            "dmb sy         \n"
+            "mov r1, #0     \n"
+            "str r1, [%0]   \n"
+            "sev            \n"
+            "dsb            \n"
+            "isb            \n"
+            :
+            : "r" ( ulLock )
+            : "memory", "r1"
+        );
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline uint32_t prvSpinTrylock( volatile uint32_t * ulLock )
+    {
+        /*
+         * Conservative ldrex/strex trylock:
+         * - Return 1 immediately if busy, clearing exclusive state (CLREX).
+         * - Retry strex only on spurious failure when observed free.
+         * - DMB on success to preserve expected acquire semantics.
+         */
+        uint32_t ulVal;
+        uint32_t ulStatus;
+
+        __asm volatile (
+            " ldrex %0, [%1]   \n"
+            : "=r" ( ulVal )
+            : "r" ( ulLock )
+            : "memory"
+        );
+
+        if( ulVal != 0U )
+        {
+            __asm volatile ("clrex" ::: "memory");
+            return 1U;
+        }
+
+        __asm volatile (
+            " strex %0, %2, [%1]   \n"
+            : "=&r" ( ulStatus )
+            : "r" ( ulLock ), "r" (1U)
+            : "memory"
+        );
+
+        if( ulStatus != 0U )
+        {
+            return 1U;
+        }
+        __asm volatile ( "dmb" ::: "memory" );
+        return 0U;
+    }
+
+
+/*-----------------------------------------------------------*/
+
+    /* Read 32b value shared between cores. */
+    static inline uint32_t prvGet32( volatile uint32_t * x )
+    {
+        __asm( "dsb" );
+        return *x;
+    }
+
+/*-----------------------------------------------------------*/
+
+    /* Write 32b value shared between cores. */
+    static inline void prvSet32( volatile uint32_t * x,
+                                 uint32_t value )
+    {
+        *x = value;
+        __asm( "dsb" );
+    }
+
+/*-----------------------------------------------------------*/
+
+    void vPortRecursiveLock( uint8_t ucCoreID,
+                             ePortRTOSLock eLockNum,
+                             BaseType_t uxAcquire )
+    {
+        /* Validate the core ID and lock number. */
+        configASSERT( ucCoreID < portMAX_CORE_COUNT );
+        configASSERT( eLockNum < eLockCount );
+
+        uint32_t ulLockBit = 1u << eLockNum;
+
+        /* Lock acquire */
+        if( uxAcquire )
+        {
+            /* Check if spinlock is available. */
+            /* If spinlock is not available check if the core owns the lock. */
+            /* If the core owns the lock wait increment the lock count by the core. */
+            /* If core does not own the lock wait for the spinlock. */
+            if( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+            {
+                /* Check if the core owns the spinlock. */
+                if( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit )
+                {
+                    configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != portUINT32_MAX );
+                    prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) + 1 ) );
+                    return;
+                }
+
+                /* Preload the gate word into the cache. */
+                uint32_t dummy = ulGateWord[ eLockNum ];
+                dummy++;
+
+                while( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+                {
+                    __asm volatile ( "wfe" );
+                }
+            }
+
+            /* Add barrier to ensure lock is taken before we proceed. */
+            __asm volatile( "dmb sy" ::: "memory" );
+
+            /* Assert the lock count is 0 when the spinlock is free and is acquired. */
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) == 0 );
+
+            /* Set lock count as 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], 1 );
+            /* Set ulOwnedByCore. */
+            prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) | ulLockBit ) );
+        }
+        /* Lock release. */
+        else
+        {
+            /* Assert the lock is not free already. */
+            configASSERT( ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit ) != 0 );
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != 0 );
+
+            /* Reduce ulRecursionCountByLock by 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) - 1 ) );
+
+            if( !prvGet32( &ulRecursionCountByLock[ eLockNum ] ) )
+            {
+                prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ~ulLockBit ) );
+                prvSpinUnlock( &ulGateWord[ eLockNum ] );
+                /* Add barrier to ensure lock status is reflected before we proceed. */
+                __asm volatile( "dmb sy" ::: "memory" );
+            }
+        }
+    }
+
+/*-----------------------------------------------------------*/
+
+    uint8_t ucPortGetCoreID( void )
+    {
+        return *(volatile uint8_t *)(configCORE_ID_REGISTER);
+    }
+
+/*-----------------------------------------------------------*/
+
+#endif /* if( configNUMBER_OF_CORES > 1 ) */
diff --git a/Source/portable/GCC/ARM_CM85_NTZ/non_secure/portasm.c b/Source/portable/GCC/ARM_CM85_NTZ/non_secure/portasm.c
index 51ec476..fbb00b1 100644
--- a/Source/portable/GCC/ARM_CM85_NTZ/non_secure/portasm.c
+++ b/Source/portable/GCC/ARM_CM85_NTZ/non_secure/portasm.c
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -134,8 +133,21 @@
         (
             "   .syntax unified                                 \n"
             "                                                   \n"
+        /*
+         * The SMP-specific logic below is derived from the Raspberry Pi
+         * implementation in the FreeRTOS-Kernel-Community-Supported-Ports project.
+         * Source: GCC/RP2350_ARM_NTZ/non_secure/portasm.c
+         * Upstream commit: 8b2955f6d97bf4cd582db9f5b62d9eb1587b76d7
+         */
+        #if ( configNUMBER_OF_CORES == 1)
             "   ldr  r2, =pxCurrentTCB                          \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
             "   ldr  r1, [r2]                                   \n" /* Read pxCurrentTCB. */
+        #else /* if ( configNUMBER_OF_CORES == 1) */
+            "   ldr r1, =ulFirstTaskLiteralPool                 \n" /* Get the location of the current TCB and the Id of the current core. */
+            "   ldmia r1!, {r2, r3}                             \n"
+            "   ldr r2, [r2]                                    \n" /* r2 = Core Id */
+            "   ldr r1, [r3, r2, LSL #2]                        \n" /* r1 = pxCurrentTCBs[CORE_ID] */
+        #endif /* if ( configNUMBER_OF_CORES == 1) */
             "   ldr  r0, [r1]                                   \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
             "                                                   \n"
         #if ( configENABLE_PAC == 1 )
@@ -158,6 +170,14 @@
             "   mov  r0, #0                                     \n"
             "   msr  basepri, r0                                \n" /* Ensure that interrupts are enabled when the first task starts. */
             "   bx   r2                                         \n" /* Finally, branch to EXC_RETURN. */
+        #if ( configNUMBER_OF_CORES > 1 )
+            "                                                   \n"
+            "     .align 4                                      \n"
+            "ulFirstTaskLiteralPool:                            \n"
+            "    .word %c0                                      \n" /* CORE_ID_REGISTER */
+            "    .word pxCurrentTCBs                            \n"
+            :: "i" (configCORE_ID_REGISTER)
+        #endif /* if ( configNUMBER_OF_CORES > 1 ) */
         );
     }
 
@@ -422,20 +442,43 @@
             "   clrm {r1-r4}                                    \n" /* Clear r1-r4. */
         #endif /* configENABLE_PAC */
             "                                                   \n"
+        /*
+         * The SMP-specific logic below is derived from the Raspberry Pi
+         * implementation in the FreeRTOS-Kernel-Community-Supported-Ports project.
+         * Source: GCC/RP2350_ARM_NTZ/non_secure/portasm.c
+         * Upstream commit: 8b2955f6d97bf4cd582db9f5b62d9eb1587b76d7
+         */
+        #if ( configNUMBER_OF_CORES == 1)
             "   ldr r2, =pxCurrentTCB                           \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
             "   ldr r1, [r2]                                    \n" /* Read pxCurrentTCB. */
+        #else /* if ( configNUMBER_OF_CORES == 1) */
+            "   ldr r1, =ulPendSVLiteralPool                    \n" /* Get the location of the current TCB and the Id of the current core. */
+            "   ldmia r1!, {r2, r3}                             \n"
+            "   ldr r2, [r2]                                    \n" /* r2 = Core Id */
+            "   ldr r1, [r3, r2, LSL #2]                        \n" /* r1 = pxCurrentTCBs[CORE_ID] */
+        #endif /* if ( configNUMBER_OF_CORES == 1) */
             "   str r0, [r1]                                    \n" /* Save the new top of stack in TCB. */
             "                                                   \n"
             "   mov r0, %0                                      \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
             "   msr basepri, r0                                 \n" /* Disable interrupts up to configMAX_SYSCALL_INTERRUPT_PRIORITY. */
             "   dsb                                             \n"
             "   isb                                             \n"
+        #if ( configNUMBER_OF_CORES > 1)
+            "   mov r0, r2                                      \n" /* r0 = ucPortGetCoreID() */
+        #endif /* if ( configNUMBER_OF_CORES == 1) */
             "   bl vTaskSwitchContext                           \n"
             "   mov r0, #0                                      \n" /* r0 = 0. */
             "   msr basepri, r0                                 \n" /* Enable interrupts. */
             "                                                   \n"
+        #if ( configNUMBER_OF_CORES == 1)
             "   ldr r2, =pxCurrentTCB                           \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
             "   ldr r1, [r2]                                    \n" /* Read pxCurrentTCB. */
+        #else /* if ( configNUMBER_OF_CORES == 1) */
+            "   ldr r1, =ulPendSVLiteralPool                    \n" /* Get the location of the current TCB and the Id of the current core. */
+            "   ldmia r1!, {r2, r3}                             \n"
+            "   ldr r2, [r2]                                    \n" /* r2 = Core Id */
+            "   ldr r1, [r3, r2, LSL #2]                        \n" /* r1 = pxCurrentTCBs[CORE_ID] */
+        #endif /* if ( configNUMBER_OF_CORES == 1) */
             "   ldr r0, [r1]                                    \n" /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
             "                                                   \n"
         #if ( configENABLE_PAC == 1 )
@@ -458,7 +501,16 @@
             "   msr psplim, r2                                  \n" /* Restore the PSPLIM register value for the task. */
             "   msr psp, r0                                     \n" /* Remember the new top of stack for the task. */
             "   bx r3                                           \n"
-            ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
+        #if ( configNUMBER_OF_CORES > 1 )
+            "   .align 4                           \n"
+            "   ulPendSVLiteralPool:               \n"
+            "   .word %c1                          \n" /* CORE_ID_REGISTER */
+            "   .word pxCurrentTCBs                \n"
+            :: "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ), "i" ( configCORE_ID_REGISTER )
+        #else /* #if ( configNUMBER_OF_CORES > 1 ) */
+            :: "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
+        #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
+
         );
     }
 
diff --git a/Source/portable/GCC/ARM_CM85_NTZ/non_secure/portasm.h b/Source/portable/GCC/ARM_CM85_NTZ/non_secure/portasm.h
index 53b4b6e..b4b545f 100644
--- a/Source/portable/GCC/ARM_CM85_NTZ/non_secure/portasm.h
+++ b/Source/portable/GCC/ARM_CM85_NTZ/non_secure/portasm.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/GCC/ARM_CM85_NTZ/non_secure/portmacro.h b/Source/portable/GCC/ARM_CM85_NTZ/non_secure/portmacro.h
index 3386f52..892228d 100644
--- a/Source/portable/GCC/ARM_CM85_NTZ/non_secure/portmacro.h
+++ b/Source/portable/GCC/ARM_CM85_NTZ/non_secure/portmacro.h
@@ -1,6 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * Copyright 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -57,6 +58,7 @@
 #define portHAS_ARMV8M_MAIN_EXTENSION    1
 #define portARMV8M_MINOR_VERSION         1
 #define portDONT_DISCARD                 __attribute__( ( used ) )
+#define portVALIDATED_FOR_SMP            0
 /*-----------------------------------------------------------*/
 
 /* ARMv8-M common port configurations. */
diff --git a/Source/portable/GCC/ARM_CM85_NTZ/non_secure/portmacrocommon.h b/Source/portable/GCC/ARM_CM85_NTZ/non_secure/portmacrocommon.h
index 2dfac6a..c34fdee 100644
--- a/Source/portable/GCC/ARM_CM85_NTZ/non_secure/portmacrocommon.h
+++ b/Source/portable/GCC/ARM_CM85_NTZ/non_secure/portmacrocommon.h
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -59,6 +58,19 @@
     #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h.  Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
 #endif /* configENABLE_TRUSTZONE */
 
+#if ( configNUMBER_OF_CORES > 1 )
+    #if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 )
+        #error "Multi-core SMP is currently only validated for Cortex-M33 non-TrustZone non-MPU port."
+    #endif /* if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 ) ) */
+
+    #ifndef configCORE_ID_REGISTER
+        #error "configCORE_ID_REGISTER must be defined to the address of the register used to identify the core executing the code."
+    #endif /* ifndef configCORE_ID_REGISTER */
+
+    #ifndef configWAKE_SECONDARY_CORES
+        #error "configWAKE_SECONDARY_CORES must be defined to a function that wakes the secondary cores."
+    #endif /* ifndef configWAKE_SECONDARY_CORES */
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -428,10 +440,26 @@
 /**
  * @brief Critical section management.
  */
+
+#define portSET_INTERRUPT_MASK()                  ulSetInterruptMask()
+#define portCLEAR_INTERRUPT_MASK( x )             vClearInterruptMask( x )
 #define portSET_INTERRUPT_MASK_FROM_ISR()         ulSetInterruptMask()
 #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x )    vClearInterruptMask( x )
-#define portENTER_CRITICAL()                      vPortEnterCritical()
-#define portEXIT_CRITICAL()                       vPortExitCritical()
+
+#if ( configNUMBER_OF_CORES == 1 )
+    #define portENTER_CRITICAL()                      vPortEnterCritical()
+    #define portEXIT_CRITICAL()                       vPortExitCritical()
+#else /* ( configNUMBER_OF_CORES == 1 ) */
+    extern void vTaskEnterCritical( void );
+    extern void vTaskExitCritical( void );
+    extern UBaseType_t vTaskEnterCriticalFromISR( void );
+    extern void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus );
+
+    #define portENTER_CRITICAL()                      vTaskEnterCritical()
+    #define portEXIT_CRITICAL()                       vTaskExitCritical()
+    #define portENTER_CRITICAL_FROM_ISR()             vTaskEnterCriticalFromISR()
+    #define portEXIT_CRITICAL_FROM_ISR( x )           vTaskExitCriticalFromISR( x )
+#endif /* if ( configNUMBER_OF_CORES != 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -526,7 +554,7 @@
 /* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION
  * based on whether or not Mainline extension is implemented. */
 #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
-    #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 )
+    #if ( ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) && ( configNUMBER_OF_CORES == 1 ) )
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    1
     #else
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    0
@@ -573,6 +601,44 @@
 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
 /*-----------------------------------------------------------*/
 
+
+#if ( configNUMBER_OF_CORES > 1 )
+    typedef enum
+    {
+        eIsrLock = 0,
+        eTaskLock,
+        eLockCount
+    } ePortRTOSLock;
+
+    extern volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ];
+    extern void vPortRecursiveLock( uint8_t ucCoreID,
+                                    ePortRTOSLock eLockNum,
+                                    BaseType_t uxAcquire );
+    extern uint8_t ucPortGetCoreID( void );
+    extern void vInterruptCore( uint8_t ucCoreID );
+
+    #define portGET_CORE_ID()                                  ucPortGetCoreID()
+
+    #define portGET_CRITICAL_NESTING_COUNT( xCoreID )          ( ulCriticalNestings[ ( uint8_t ) xCoreID ] )
+    #define portSET_CRITICAL_NESTING_COUNT( xCoreID, x )       ( ulCriticalNestings[ ( uint8_t ) xCoreID ] = ( x ) )
+    #define portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]++ )
+    #define portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]-- )
+
+    #define portMAX_CORE_COUNT                                 ( configNUMBER_OF_CORES )
+
+    #define portYIELD_CORE( xCoreID )                          vInterruptCore( xCoreID )
+
+    #define portRELEASE_ISR_LOCK( xCoreID )                    vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdFALSE )
+    #define portGET_ISR_LOCK( xCoreID )                        vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdTRUE )
+
+    #define portRELEASE_TASK_LOCK( xCoreID )                   vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdFALSE )
+    #define portGET_TASK_LOCK( xCoreID )                       vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdTRUE )
+
+    #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* ( configENABLE_PAC == 1 || configENABLE_BTI == 1 ) */
+#endif
+
 /* *INDENT-OFF* */
 #ifdef __cplusplus
     }
diff --git a/Source/portable/IAR/ARM_CA9/port.c b/Source/portable/IAR/ARM_CA9/port.c
index 9940833..762aab7 100644
--- a/Source/portable/IAR/ARM_CA9/port.c
+++ b/Source/portable/IAR/ARM_CA9/port.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CA9/portASM.h b/Source/portable/IAR/ARM_CA9/portASM.h
index 2855a0c..9902404 100644
--- a/Source/portable/IAR/ARM_CA9/portASM.h
+++ b/Source/portable/IAR/ARM_CA9/portASM.h
@@ -1,5 +1,5 @@
 ;/*
-; * FreeRTOS Kernel V11.2.0
+; * FreeRTOS Kernel V11.3.1
 ; * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 ; *
 ; * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CA9/portASM.s b/Source/portable/IAR/ARM_CA9/portASM.s
index ebb86e9..95ca33b 100644
--- a/Source/portable/IAR/ARM_CA9/portASM.s
+++ b/Source/portable/IAR/ARM_CA9/portASM.s
@@ -1,5 +1,5 @@
 ;/*
-; * FreeRTOS Kernel V11.2.0
+; * FreeRTOS Kernel V11.3.1
 ; * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 ; *
 ; * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CA9/portmacro.h b/Source/portable/IAR/ARM_CA9/portmacro.h
index f218e60..a12fa9a 100644
--- a/Source/portable/IAR/ARM_CA9/portmacro.h
+++ b/Source/portable/IAR/ARM_CA9/portmacro.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM0/port.c b/Source/portable/IAR/ARM_CM0/port.c
index 6f7c899..06d0968 100644
--- a/Source/portable/IAR/ARM_CM0/port.c
+++ b/Source/portable/IAR/ARM_CM0/port.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM0/portasm.s b/Source/portable/IAR/ARM_CM0/portasm.s
index bc33363..afba1f4 100644
--- a/Source/portable/IAR/ARM_CM0/portasm.s
+++ b/Source/portable/IAR/ARM_CM0/portasm.s
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM0/portmacro.h b/Source/portable/IAR/ARM_CM0/portmacro.h
index e384e59..82ec004 100644
--- a/Source/portable/IAR/ARM_CM0/portmacro.h
+++ b/Source/portable/IAR/ARM_CM0/portmacro.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM23/non_secure/mpu_wrappers_v2_asm.S b/Source/portable/IAR/ARM_CM23/non_secure/mpu_wrappers_v2_asm.S
index eaafcee..39695d6 100644
--- a/Source/portable/IAR/ARM_CM23/non_secure/mpu_wrappers_v2_asm.S
+++ b/Source/portable/IAR/ARM_CM23/non_secure/mpu_wrappers_v2_asm.S
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM23/non_secure/port.c b/Source/portable/IAR/ARM_CM23/non_secure/port.c
index f16a343..007150c 100644
--- a/Source/portable/IAR/ARM_CM23/non_secure/port.c
+++ b/Source/portable/IAR/ARM_CM23/non_secure/port.c
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024-2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -145,13 +144,13 @@
 /**
  * @brief Constants required to manipulate the FPU.
  */
-#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 )              /* Coprocessor Access Control Register. */
+#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */
 #define portCPACR_CP10_VALUE    ( 3UL )
 #define portCPACR_CP11_VALUE    portCPACR_CP10_VALUE
 #define portCPACR_CP10_POS      ( 20UL )
 #define portCPACR_CP11_POS      ( 22UL )
 
-#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 )              /* Floating Point Context Control Register. */
+#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
 #define portFPCCR_ASPEN_POS     ( 31UL )
 #define portFPCCR_ASPEN_MASK    ( 1UL << portFPCCR_ASPEN_POS )
 #define portFPCCR_LSPEN_POS     ( 30UL )
@@ -188,8 +187,8 @@
 #define portMPU_MAIR0_REG                       ( *( ( volatile uint32_t * ) 0xe000edc0 ) )
 #define portMPU_MAIR1_REG                       ( *( ( volatile uint32_t * ) 0xe000edc4 ) )
 
-#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
-#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
+#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
+#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
 
 #define portMPU_RBAR_ACCESS_PERMISSIONS_MASK    ( 3UL << 1UL )
 
@@ -230,8 +229,8 @@
 
 #if ( portARMV8M_MINOR_VERSION >= 1 )
 
-/* Enable Privileged eXecute Never MPU attribute for the selected memory
- * region. */
+    /* Enable Privileged eXecute Never MPU attribute for the selected memory
+     * region. */
     #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER    ( 1UL << 4UL )
 #endif /* portARMV8M_MINOR_VERSION >= 1 */
 
@@ -241,9 +240,6 @@
 /* Enable MPU. */
 #define portMPU_ENABLE_BIT                    ( 1UL << 0UL )
 
-/* Expected value of the portMPU_TYPE register. */
-#define portEXPECTED_MPU_TYPE_VALUE           ( configTOTAL_MPU_REGIONS << 8UL )
-
 /* Extract first address of the MPU region as encoded in the
  * RBAR (Region Base Address Register) value. */
 #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@@ -291,37 +287,37 @@
 
 #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         FD
- * 1111 1111  1111 1111  1111 1111  1111 1101
- *
- * Bit[6] - 1 --> The exception was taken from the Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 1 --> The exception was taken to the Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         FD
+     * 1111 1111  1111 1111  1111 1111  1111 1101
+     *
+     * Bit[6] - 1 --> The exception was taken from the Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 1 --> The exception was taken to the Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xfffffffd )
 #else
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         BC
- * 1111 1111  1111 1111  1111 1111  1011 1100
- *
- * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         BC
+     * 1111 1111  1111 1111  1111 1111  1011 1100
+     *
+     * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xffffffbc )
 #endif /* configRUN_FREERTOS_SECURE_ONLY */
 
@@ -401,50 +397,54 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Extract MPU region's access permissions from the Region Base Address
- * Register (RBAR) value.
- *
- * @param ulRBARValue RBAR value for the MPU region.
- *
- * @return uint32_t Access permissions.
- */
+    /**
+     * @brief Extract MPU region's access permissions from the Region Base Address
+     * Register (RBAR) value.
+     *
+     * @param ulRBARValue RBAR value for the MPU region.
+     *
+     * @return uint32_t Access permissions.
+     */
     static uint32_t prvGetRegionAccessPermissions( uint32_t ulRBARValue ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU == 1 && configUSE_MPU_WRAPPERS_V1 == 0 */
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Setup the Memory Protection Unit (MPU).
- */
+    /**
+     * @brief Setup the Memory Protection Unit (MPU).
+     */
     static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU */
 
 #if ( configENABLE_FPU == 1 )
 
-/**
- * @brief Setup the Floating Point Unit (FPU).
- */
+    /**
+     * @brief Setup the Floating Point Unit (FPU).
+     */
     static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_FPU */
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
 
-/**
- * @brief Configures PACBTI features.
- *
- * This function configures the Pointer Authentication, and Branch Target
- * Identification security features as per the user configuration. It returns
- * the value of the special purpose CONTROL register accordingly, and optionally
- * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
- * architecture based) target supports PACBTI security feature.
- *
- * @param xWriteControlRegister Used to control whether the special purpose
- * CONTROL register should be updated or not.
- *
- * @return CONTROL register value according to the configured PACBTI option.
- */
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    /**
+     * @brief Configures PACBTI features.
+     *
+     * This function configures the Pointer Authentication, and Branch Target
+     * Identification security features as per the user configuration. It returns
+     * the value of the special purpose CONTROL register accordingly, and optionally
+     * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
+     * architecture based) target supports PACBTI security feature.
+     *
+     * @param xWriteControlRegister Used to control whether the special purpose
+     * CONTROL register should be updated or not.
+     *
+     * @return CONTROL register value according to the configured PACBTI option.
+     */
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -491,14 +491,14 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the system call stack so that upon returning from
- * SVC, the system call stack is used.
- *
- * @param pulTaskStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- * @param ucSystemCallNumber The system call number of the system call.
- */
+    /**
+     * @brief Sets up the system call stack so that upon returning from
+     * SVC, the system call stack is used.
+     *
+     * @param pulTaskStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     * @param ucSystemCallNumber The system call number of the system call.
+     */
     void vSystemCallEnter( uint32_t * pulTaskStack,
                            uint32_t ulLR,
                            uint8_t ucSystemCallNumber ) PRIVILEGED_FUNCTION;
@@ -507,22 +507,22 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Raise SVC for exiting from a system call.
- */
+    /**
+     * @brief Raise SVC for exiting from a system call.
+     */
     void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the task stack so that upon returning from
- * SVC, the task stack is used again.
- *
- * @param pulSystemCallStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- */
+    /**
+     * @brief Sets up the task stack so that upon returning from
+     * SVC, the task stack is used again.
+     *
+     * @param pulSystemCallStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     */
     void vSystemCallExit( uint32_t * pulSystemCallStack,
                           uint32_t ulLR ) PRIVILEGED_FUNCTION;
 
@@ -530,21 +530,38 @@
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Checks whether or not the calling task is privileged.
- *
- * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
- */
+    /**
+     * @brief Checks whether or not the calling task is privileged.
+     *
+     * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
+     */
     BaseType_t xPortIsTaskPrivileged( void ) PRIVILEGED_FUNCTION;
 
 #endif /* configENABLE_MPU == 1 */
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /**
+     * @brief Platform/Application-defined function that wakes up the secondary cores.
+     *
+     * @return pdTRUE if the secondary cores were successfully woken up.
+     *         pdFALSE otherwise.
+     */
+    extern BaseType_t configWAKE_SECONDARY_CORES( void );
+
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
+
+/**
+ * @brief Configures interrupt priorities.
+ */
+void vPortConfigureInterruptPriorities( void ) PRIVILEGED_FUNCTION;
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief This variable is set to pdTRUE when the scheduler is started.
- */
+    /**
+     * @brief This variable is set to pdTRUE when the scheduler is started.
+     */
     PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
@@ -553,14 +570,22 @@
  * @brief Each task maintains its own interrupt status in the critical nesting
  * variable.
  */
-PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
+#if ( configNUMBER_OF_CORES == 1 )
+    PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0UL;
+#else /* #if ( configNUMBER_OF_CORES == 1 ) */
+    PRIVILEGED_DATA volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ] = { 0 };
+    /* Flags to check if the secondary cores are ready. */
+    PRIVILEGED_DATA volatile uint8_t ucSecondaryCoresReadyFlags[ configNUMBER_OF_CORES - 1 ] = { 0 };
+    /* Flag to indicate that the primary core has completed its initialisation. */
+    PRIVILEGED_DATA volatile uint8_t ucPrimaryCoreInitDoneFlag = 0;
+ #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #if ( configENABLE_TRUSTZONE == 1 )
 
-/**
- * @brief Saved as part of the task context to indicate which context the
- * task is using on the secure side.
- */
+    /**
+     * @brief Saved as part of the task context to indicate which context the
+     * task is using on the secure side.
+     */
     PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
 #endif /* configENABLE_TRUSTZONE */
 
@@ -579,21 +604,21 @@
 
 #if ( configUSE_TICKLESS_IDLE == 1 )
 
-/**
- * @brief The number of SysTick increments that make up one tick period.
- */
+    /**
+     * @brief The number of SysTick increments that make up one tick period.
+     */
     PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
 
-/**
- * @brief The maximum number of tick periods that can be suppressed is
- * limited by the 24 bit resolution of the SysTick timer.
- */
+    /**
+     * @brief The maximum number of tick periods that can be suppressed is
+     * limited by the 24 bit resolution of the SysTick timer.
+     */
     PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
 
-/**
- * @brief Compensate for the CPU cycles that pass while the SysTick is
- * stopped (low power functionality only).
- */
+    /**
+     * @brief Compensate for the CPU cycles that pass while the SysTick is
+     * stopped (low power functionality only).
+     */
     PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0;
 #endif /* configUSE_TICKLESS_IDLE */
 /*-----------------------------------------------------------*/
@@ -856,7 +881,11 @@
      * should instead call vTaskDelete( NULL ). Artificially force an assert()
      * to be triggered if configASSERT() is defined, then stop here so
      * application writers can catch the error. */
-    configASSERT( ulCriticalNesting == ~0UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == ~0UL );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == ~0UL );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
     portDISABLE_INTERRUPTS();
 
     while( ulDummy == 0 )
@@ -925,64 +954,57 @@
         /* The only permitted number of regions are 8 or 16. */
         configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 16 ) );
 
-        /* Ensure that the configTOTAL_MPU_REGIONS is configured correctly. */
-        configASSERT( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE );
+        /* MAIR0 - Index 0. */
+        portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
+        /* MAIR0 - Index 1. */
+        portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
 
-        /* Check that the MPU is present. */
-        if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
-        {
-            /* MAIR0 - Index 0. */
-            portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
-            /* MAIR0 - Index 1. */
-            portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
+        /* Setup privileged flash as Read Only so that privileged tasks can
+         * read it but not modify. */
+        portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup privileged flash as Read Only so that privileged tasks can
-             * read it but not modify. */
-            portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged flash as Read Only by both privileged and
+         * unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged flash as Read Only by both privileged and
-             * unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged syscalls flash as Read Only by both privileged
+         * and unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged syscalls flash as Read Only by both privileged
-             * and unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup RAM containing kernel data for privileged access only. */
+        portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
+                           ( portMPU_REGION_EXECUTE_NEVER );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup RAM containing kernel data for privileged access only. */
-            portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
-                               ( portMPU_REGION_EXECUTE_NEVER );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Enable mem fault. */
+        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
 
-            /* Enable mem fault. */
-            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
-
-            /* Enable MPU with privileged background access i.e. unmapped
-             * regions have privileged access. */
-            portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
-        }
+        /* Enable MPU with privileged background access i.e. unmapped
+         * regions have privileged access. */
+        portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
     }
 
 #endif /* configENABLE_MPU */
@@ -1027,28 +1049,29 @@
 }
 /*-----------------------------------------------------------*/
 
-void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    portDISABLE_INTERRUPTS();
-    ulCriticalNesting++;
-
-    /* Barriers are normally not required but do ensure the code is
-     * completely within the specified behaviour for the architecture. */
-    __asm volatile ( "dsb" ::: "memory" );
-    __asm volatile ( "isb" );
-}
-/*-----------------------------------------------------------*/
-
-void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    configASSERT( ulCriticalNesting );
-    ulCriticalNesting--;
-
-    if( ulCriticalNesting == 0 )
+#if ( configNUMBER_OF_CORES == 1 )
+    void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
     {
-        portENABLE_INTERRUPTS();
+        portDISABLE_INTERRUPTS();
+        ulCriticalNesting++;
+        /* Barriers are normally not required but do ensure the code is
+        * completely within the specified behaviour for the architecture. */
+        __asm volatile ( "dsb" ::: "memory" );
+        __asm volatile ( "isb" );
     }
-}
+    /*-----------------------------------------------------------*/
+
+    void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
+    {
+        configASSERT( ulCriticalNesting );
+        ulCriticalNesting--;
+
+        if( ulCriticalNesting == 0 )
+        {
+            portENABLE_INTERRUPTS();
+        }
+    }
+#endif /* configNUMBER_OF_CORES == 1 */
 /*-----------------------------------------------------------*/
 
 void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
@@ -1056,6 +1079,10 @@
     uint32_t ulPreviousMask;
 
     ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
+    #if ( configNUMBER_OF_CORES > 1 )
+        UBaseType_t uxSavedInterruptStatus = portENTER_CRITICAL_FROM_ISR();
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     traceISR_ENTER();
     {
         /* Increment the RTOS tick. */
@@ -1070,6 +1097,10 @@
             traceISR_EXIT();
         }
     }
+    #if ( configNUMBER_OF_CORES > 1 )
+        portEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
 }
 /*-----------------------------------------------------------*/
@@ -1078,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1090,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1108,38 +1151,42 @@
 
     switch( ucSVCNumber )
     {
-        #if ( configENABLE_TRUSTZONE == 1 )
-            case portSVC_ALLOCATE_SECURE_CONTEXT:
+    #if ( configENABLE_TRUSTZONE == 1 )
+        case portSVC_ALLOCATE_SECURE_CONTEXT:
 
-                /* R0 contains the stack size passed as parameter to the
-                 * vPortAllocateSecureContext function. */
-                ulR0 = pulCallerStackAddress[ 0 ];
+            /* R0 contains the stack size passed as parameter to the
+             * vPortAllocateSecureContext function. */
+            ulR0 = pulCallerStackAddress[ 0 ];
 
-                #if ( configENABLE_MPU == 1 )
-                {
-                    /* Read the CONTROL register value. */
-                    __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
+            #if ( configENABLE_MPU == 1 )
+            {
+                /* Read the CONTROL register value. */
+                __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
 
-                    /* The task that raised the SVC is privileged if Bit[0]
-                     * in the CONTROL register is 0. */
-                    ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
+                /* The task that raised the SVC is privileged if Bit[0]
+                 * in the CONTROL register is 0. */
+                ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
 
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
-                }
-                #else /* if ( configENABLE_MPU == 1 ) */
-                {
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
-                }
-                #endif /* configENABLE_MPU */
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
+            }
+            #else /* if ( configENABLE_MPU == 1 ) */
+            {
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
+            }
+            #endif /* configENABLE_MPU */
 
-                configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
-                SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
-                break;
+            configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
+            SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
+            break;
 
-            case portSVC_FREE_SECURE_CONTEXT:
-
+        case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
                 /* R0 contains TCB being freed and R1 contains the secure
                  * context handle to be freed. */
                 ulR0 = pulCallerStackAddress[ 0 ];
@@ -1147,51 +1194,62 @@
 
                 /* Free the secure context. */
                 SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
-                break;
-        #endif /* configENABLE_TRUSTZONE */
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
+            break;
+    #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
-            #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
-                case portSVC_RAISE_PRIVILEGE:
+    #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
+        case portSVC_RAISE_PRIVILEGE:
 
-                    /* Only raise the privilege, if the svc was raised from any of
-                     * the system calls. */
-                    if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
-                        ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
-                    {
-                        vRaisePrivilege();
-                    }
-                    break;
-            #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
+            /* Only raise the privilege, if the svc was raised from any of
+             * the system calls. */
+            if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
+                ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
+            {
+                vRaisePrivilege();
+            }
+            break;
+    #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
-            #if ( configENABLE_MPU == 1 )
-                case portSVC_YIELD:
-                    vPortYield();
-                    break;
-            #endif /* configENABLE_MPU == 1 */
+    #if ( configENABLE_MPU == 1 )
+        case portSVC_YIELD:
+            vPortYield();
+            break;
+    #endif /* configENABLE_MPU == 1 */
 
         default:
             /* Incorrect SVC call. */
@@ -1210,7 +1268,7 @@
         extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulSystemCallStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1246,12 +1304,16 @@
         {
             pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1261,20 +1323,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the system call stack for the stack frame. */
-            pulSystemCallStack = pulSystemCallStack - ulStackFrameSize;
+            pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulSystemCallStack[ i ] = pulTaskStack[ i ];
             }
@@ -1310,7 +1372,7 @@
 
             /* Remember the location where we should copy the stack frame when we exit from
              * the system call. */
-            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
+            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
 
             /* Record if the hardware used padding to force the stack pointer
              * to be double word aligned. */
@@ -1360,7 +1422,7 @@
         extern TaskHandle_t pxCurrentTCB;
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulTaskStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1392,12 +1454,16 @@
         {
             pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1407,20 +1473,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the task stack for the stack frame. */
-            pulTaskStack = pulTaskStack - ulStackFrameSize;
+            pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulTaskStack[ i ] = pulSystemCallStack[ i ];
             }
@@ -1518,21 +1584,21 @@
         xMPUSettings->ulContext[ ulIndex ] = 0x11111111; /* r11. */
         ulIndex++;
 
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters;            /* r0. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters; /* r0. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x01010101;                           /* r1. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x01010101; /* r1. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x02020202;                           /* r2. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x02020202; /* r2. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x03030303;                           /* r3. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x03030303; /* r3. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x12121212;                           /* r12. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x12121212; /* r12. */
         ulIndex++;
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) portTASK_RETURN_ADDRESS; /* LR. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode;                  /* PC. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode; /* PC. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR;                     /* xPSR. */
+        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR; /* xPSR. */
         ulIndex++;
 
         #if ( configENABLE_TRUSTZONE == 1 )
@@ -1543,14 +1609,18 @@
         #endif /* configENABLE_TRUSTZONE */
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) ( pxTopOfStack - 8 ); /* PSP with the hardware saved stack. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack;         /* PSPLIM. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack; /* PSPLIM. */
         ulIndex++;
 
         #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
         {
             /* Check PACBTI security feature configuration before pushing the
              * CONTROL register's value on task's TCB. */
-            ulControl = prvConfigurePACBTI( pdFALSE );
+            #if ( configNUMBER_OF_CORES == 1 )
+                ulControl = prvConfigurePACBTI( pdFALSE );
+            #else /* configNUMBER_OF_CORES > 1 */
+                ulControl = vConfigurePACBTI( pdFALSE );
+            #endif /* configNUMBER_OF_CORES */
         }
         #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1615,15 +1685,15 @@
          * interrupt. */
         #if ( portPRELOAD_REGISTERS == 0 )
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
-            pxTopOfStack -= 5;                                       /* R12, R3, R2 and R1. */
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
-            pxTopOfStack -= 9;                                       /* R11..R4, EXC_RETURN. */
+            pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
+            pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */
             *pxTopOfStack = portINITIAL_EXC_RETURN;
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
@@ -1637,42 +1707,42 @@
         }
         #else /* portPRELOAD_REGISTERS */
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x12121212UL;            /* R12. */
+            *pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x03030303UL;            /* R3. */
+            *pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x02020202UL;            /* R2. */
+            *pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x01010101UL;            /* R1. */
+            *pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x11111111UL;            /* R11. */
+            *pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x10101010UL;            /* R10. */
+            *pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x09090909UL;            /* R09. */
+            *pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x08080808UL;            /* R08. */
+            *pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x07070707UL;            /* R07. */
+            *pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x06060606UL;            /* R06. */
+            *pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x05050505UL;            /* R05. */
+            *pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x04040404UL;            /* R04. */
+            *pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04. */
             pxTopOfStack--;
-            *pxTopOfStack = portINITIAL_EXC_RETURN;                  /* EXC_RETURN. */
+            *pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxEndOfStack;            /* Slot used to hold this task's PSPLIM value. */
+            *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
 
             #if ( configENABLE_TRUSTZONE == 1 )
             {
@@ -1739,91 +1809,17 @@
     }
     #endif /* configCHECK_HANDLER_INSTALLATION */
 
-    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
-    {
-        volatile uint32_t ulImplementedPrioBits = 0;
-        volatile uint8_t ucMaxPriorityValue;
-
-        /* Determine the maximum priority from which ISR safe FreeRTOS API
-         * functions can be called. ISR safe functions are those that end in
-         * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
-         * ensure interrupt entry is as fast and simple as possible.
-         *
-         * First, determine the number of priority bits available. Write to all
-         * possible bits in the priority setting for SVCall. */
-        portNVIC_SHPR2_REG = 0xFF000000;
-
-        /* Read the value back to see how many bits stuck. */
-        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
-
-        /* Use the same mask on the maximum system call priority. */
-        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
-
-        /* Check that the maximum system call priority is nonzero after
-         * accounting for the number of priority bits supported by the
-         * hardware. A priority of 0 is invalid because setting the BASEPRI
-         * register to 0 unmasks all interrupts, and interrupts with priority 0
-         * cannot be masked using BASEPRI.
-         * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
-        configASSERT( ucMaxSysCallPriority );
-
-        /* Check that the bits not implemented in hardware are zero in
-         * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
-        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
-
-        /* Calculate the maximum acceptable priority group value for the number
-         * of bits read back. */
-        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
-        {
-            ulImplementedPrioBits++;
-            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
-        }
-
-        if( ulImplementedPrioBits == 8 )
-        {
-            /* When the hardware implements 8 priority bits, there is no way for
-             * the software to configure PRIGROUP to not have sub-priorities. As
-             * a result, the least significant bit is always used for sub-priority
-             * and there are 128 preemption priorities and 2 sub-priorities.
-             *
-             * This may cause some confusion in some cases - for example, if
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
-             * priority interrupts will be masked in Critical Sections as those
-             * are at the same preemption priority. This may appear confusing as
-             * 4 is higher (numerically lower) priority than
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
-             * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
-             * to 4, this confusion does not happen and the behaviour remains the same.
-             *
-             * The following assert ensures that the sub-priority bit in the
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
-             * confusion. */
-            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
-            ulMaxPRIGROUPValue = 0;
-        }
-        else
-        {
-            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
-        }
-
-        /* Shift the priority group value back to its position within the AIRCR
-         * register. */
-        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
-        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
-    }
-    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
-
-    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
-     * the highest priority. */
-    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
-    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
-    portNVIC_SHPR2_REG = 0;
+    vPortConfigureInterruptPriorities();
 
     #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
     {
         /* Set the CONTROL register value based on PACBTI security feature
          * configuration before starting the first task. */
-        ( void ) prvConfigurePACBTI( pdTRUE );
+        #if ( configNUMBER_OF_CORES == 1 )
+            ( void ) prvConfigurePACBTI( pdTRUE );
+        #else /* configNUMBER_OF_CORES > 1 */
+            ( void ) vConfigurePACBTI( pdTRUE );
+        #endif /* configNUMBER_OF_CORES */
     }
     #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1834,12 +1830,47 @@
     }
     #endif /* configENABLE_MPU */
 
-    /* Start the timer that generates the tick ISR. Interrupts are disabled
-     * here already. */
-    vPortSetupTimerInterrupt();
+    #if ( configNUMBER_OF_CORES > 1 )
+        /* Start the timer that generates the tick ISR. Interrupts are disabled
+         * here already. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count for all cores. */
+        for ( uint8_t ucCoreID = 0; ucCoreID < configNUMBER_OF_CORES; ucCoreID++ )
+        {
+            ulCriticalNestings[ ucCoreID ] = 0;
+        }
+        /* Signal that primary core has done all the necessary initialisations. */
+        ucPrimaryCoreInitDoneFlag = 1;
+        /* Wake up secondary cores */
+        BaseType_t xWakeResult = configWAKE_SECONDARY_CORES();
+        configASSERT( xWakeResult == pdTRUE );
 
-    /* Initialize the critical nesting count ready for the first task. */
-    ulCriticalNesting = 0;
+        /* Hold the primary core here until all the secondary cores are ready, this would be achieved only when
+         * all elements of ucSecondaryCoresReadyFlags are set.
+         */
+        while( 1 )
+        {
+            BaseType_t xAllCoresReady = pdTRUE;
+            for( uint8_t ucCoreID = 0; ucCoreID < ( configNUMBER_OF_CORES - 1 ); ucCoreID++ )
+            {
+                if( ucSecondaryCoresReadyFlags[ ucCoreID ] != pdTRUE )
+                {
+                    xAllCoresReady = pdFALSE;
+                    break;
+                }
+                }
+
+            if ( xAllCoresReady == pdTRUE )
+            {
+                break;
+            }
+        }
+    #else /* if ( configNUMBER_OF_CORES > 1 ) */
+        /* Start the timer that generates the tick ISR. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count ready for the first task. */
+        ulCriticalNesting = 0;
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
     {
@@ -1856,7 +1887,11 @@
      * functionality by defining configTASK_RETURN_ADDRESS. Call
      * vTaskSwitchContext() so link time optimization does not remove the
      * symbol. */
-    vTaskSwitchContext();
+    #if ( configNUMBER_OF_CORES > 1 )
+        vTaskSwitchContext( portGET_CORE_ID() );
+    #else
+        vTaskSwitchContext();
+    #endif
     prvTaskExitError();
 
     /* Should not get here. */
@@ -1868,7 +1903,11 @@
 {
     /* Not implemented in ports where there is nothing to return to.
      * Artificially force an assert. */
-    configASSERT( ulCriticalNesting == 1000UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == 1000UL );
+    #else /* if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == 1000UL );
+    #endif /* if ( configNUMBER_OF_CORES == 1 ) */
 }
 /*-----------------------------------------------------------*/
 
@@ -2151,6 +2190,90 @@
 #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
 /*-----------------------------------------------------------*/
 
+void vPortConfigureInterruptPriorities( void ) /* PRIVILEGED_FUNCTION */
+{
+    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
+    {
+        volatile uint32_t ulImplementedPrioBits = 0;
+        volatile uint8_t ucMaxPriorityValue;
+
+        /* Determine the maximum priority from which ISR safe FreeRTOS API
+        * functions can be called. ISR safe functions are those that end in
+        * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
+        * ensure interrupt entry is as fast and simple as possible.
+        *
+        * First, determine the number of priority bits available. Write to all
+        * possible bits in the priority setting for SVCall. */
+        portNVIC_SHPR2_REG = 0xFF000000;
+
+        /* Read the value back to see how many bits stuck. */
+        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
+
+        /* Use the same mask on the maximum system call priority. */
+        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
+
+        /* Check that the maximum system call priority is nonzero after
+        * accounting for the number of priority bits supported by the
+        * hardware. A priority of 0 is invalid because setting the BASEPRI
+        * register to 0 unmasks all interrupts, and interrupts with priority 0
+        * cannot be masked using BASEPRI.
+        * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+        configASSERT( ucMaxSysCallPriority );
+
+        /* Check that the bits not implemented in hardware are zero in
+        * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
+        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
+
+        /* Calculate the maximum acceptable priority group value for the number
+        * of bits read back. */
+        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
+        {
+            ulImplementedPrioBits++;
+            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
+        }
+
+        if( ulImplementedPrioBits == 8 )
+        {
+            /* When the hardware implements 8 priority bits, there is no way for
+            * the software to configure PRIGROUP to not have sub-priorities. As
+            * a result, the least significant bit is always used for sub-priority
+            * and there are 128 preemption priorities and 2 sub-priorities.
+            *
+            * This may cause some confusion in some cases - for example, if
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
+            * priority interrupts will be masked in Critical Sections as those
+            * are at the same preemption priority. This may appear confusing as
+            * 4 is higher (numerically lower) priority than
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
+            * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
+            * to 4, this confusion does not happen and the behaviour remains the same.
+            *
+            * The following assert ensures that the sub-priority bit in the
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
+            * confusion. */
+            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
+            ulMaxPRIGROUPValue = 0;
+        }
+        else
+        {
+            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
+        }
+
+        /* Shift the priority group value back to its position within the AIRCR
+        * register. */
+        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
+        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
+    }
+    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
+
+    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
+    * the highest priority. */
+    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
+    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
+    portNVIC_SHPR2_REG = 0;
+}
+/*-----------------------------------------------------------*/
+
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) )
 
     void vPortGrantAccessToKernelObject( TaskHandle_t xInternalTaskHandle,
@@ -2247,36 +2370,214 @@
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
-
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
-    {
-        uint32_t ulControl = 0x0;
-
-        /* Ensure that PACBTI is implemented. */
-        configASSERT( portID_ISAR5_REG != 0x0 );
-
-        /* Enable UsageFault exception. */
-        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
-
-        #if ( configENABLE_PAC == 1 )
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #else /* configNUMBER_OF_CORES > 1 */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #endif /* configNUMBER_OF_CORES */
         {
-            ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
-        }
-        #endif
+            uint32_t ulControl = 0x0;
 
-        #if ( configENABLE_BTI == 1 )
-        {
-            ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
-        }
-        #endif
+            /* Ensure that PACBTI is implemented. */
+            configASSERT( portID_ISAR5_REG != 0x0 );
 
-        if( xWriteControlRegister == pdTRUE )
-        {
-            __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
-        }
+            /* Enable UsageFault exception. */
+            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
 
-        return ulControl;
-    }
+            #if ( configENABLE_PAC == 1 )
+            {
+                ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
+            }
+            #endif
+
+            #if ( configENABLE_BTI == 1 )
+            {
+                ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
+            }
+            #endif
+
+            if( xWriteControlRegister == pdTRUE )
+            {
+                __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
+            }
+
+            return ulControl;
+        }
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 /*-----------------------------------------------------------*/
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /* Which core owns the lock? */
+    PRIVILEGED_DATA volatile uint32_t ulOwnedByCore[ portMAX_CORE_COUNT ];
+    /* Lock count a core owns. */
+    PRIVILEGED_DATA volatile uint32_t ulRecursionCountByLock[ eLockCount ];
+    /* Index 0 is used for ISR lock and Index 1 is used for task lock. */
+    PRIVILEGED_DATA volatile uint32_t ulGateWord[ eLockCount ];
+
+    __attribute__((weak)) void vInterruptCore( uint8_t ucCoreID )
+    {
+        /* Default weak stub - platform specific implementation may override. */
+        ( void ) ucCoreID;
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline void prvSpinUnlock( volatile uint32_t * ulLock )
+    {
+        /* Conservative unlock: preserve original barriers for broad HW/FVP. */
+        __asm volatile (
+            "dmb sy         \n"
+            "mov r1, #0     \n"
+            "str r1, [%0]   \n"
+            "sev            \n"
+            "dsb            \n"
+            "isb            \n"
+            :
+            : "r" ( ulLock )
+            : "memory", "r1"
+        );
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline uint32_t prvSpinTrylock( volatile uint32_t * ulLock )
+    {
+        /*
+         * Conservative ldrex/strex trylock:
+         * - Return 1 immediately if busy, clearing exclusive state (CLREX).
+         * - Retry strex only on spurious failure when observed free.
+         * - DMB on success to preserve expected acquire semantics.
+         */
+        uint32_t ulVal;
+        uint32_t ulStatus;
+
+        __asm volatile (
+            " ldrex %0, [%1]   \n"
+            : "=r" ( ulVal )
+            : "r" ( ulLock )
+            : "memory"
+        );
+
+        if( ulVal != 0U )
+        {
+            __asm volatile ("clrex" ::: "memory");
+            return 1U;
+        }
+
+        __asm volatile (
+            " strex %0, %2, [%1]   \n"
+            : "=&r" ( ulStatus )
+            : "r" ( ulLock ), "r" (1U)
+            : "memory"
+        );
+
+        if( ulStatus != 0U )
+        {
+            return 1U;
+        }
+        __asm volatile ( "dmb" ::: "memory" );
+        return 0U;
+    }
+
+
+/*-----------------------------------------------------------*/
+
+    /* Read 32b value shared between cores. */
+    static inline uint32_t prvGet32( volatile uint32_t * x )
+    {
+        __asm( "dsb" );
+        return *x;
+    }
+
+/*-----------------------------------------------------------*/
+
+    /* Write 32b value shared between cores. */
+    static inline void prvSet32( volatile uint32_t * x,
+                                 uint32_t value )
+    {
+        *x = value;
+        __asm( "dsb" );
+    }
+
+/*-----------------------------------------------------------*/
+
+    void vPortRecursiveLock( uint8_t ucCoreID,
+                             ePortRTOSLock eLockNum,
+                             BaseType_t uxAcquire )
+    {
+        /* Validate the core ID and lock number. */
+        configASSERT( ucCoreID < portMAX_CORE_COUNT );
+        configASSERT( eLockNum < eLockCount );
+
+        uint32_t ulLockBit = 1u << eLockNum;
+
+        /* Lock acquire */
+        if( uxAcquire )
+        {
+            /* Check if spinlock is available. */
+            /* If spinlock is not available check if the core owns the lock. */
+            /* If the core owns the lock wait increment the lock count by the core. */
+            /* If core does not own the lock wait for the spinlock. */
+            if( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+            {
+                /* Check if the core owns the spinlock. */
+                if( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit )
+                {
+                    configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != portUINT32_MAX );
+                    prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) + 1 ) );
+                    return;
+                }
+
+                /* Preload the gate word into the cache. */
+                uint32_t dummy = ulGateWord[ eLockNum ];
+                dummy++;
+
+                while( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+                {
+                    __asm volatile ( "wfe" );
+                }
+            }
+
+            /* Add barrier to ensure lock is taken before we proceed. */
+            __asm volatile( "dmb sy" ::: "memory" );
+
+            /* Assert the lock count is 0 when the spinlock is free and is acquired. */
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) == 0 );
+
+            /* Set lock count as 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], 1 );
+            /* Set ulOwnedByCore. */
+            prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) | ulLockBit ) );
+        }
+        /* Lock release. */
+        else
+        {
+            /* Assert the lock is not free already. */
+            configASSERT( ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit ) != 0 );
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != 0 );
+
+            /* Reduce ulRecursionCountByLock by 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) - 1 ) );
+
+            if( !prvGet32( &ulRecursionCountByLock[ eLockNum ] ) )
+            {
+                prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ~ulLockBit ) );
+                prvSpinUnlock( &ulGateWord[ eLockNum ] );
+                /* Add barrier to ensure lock status is reflected before we proceed. */
+                __asm volatile( "dmb sy" ::: "memory" );
+            }
+        }
+    }
+
+/*-----------------------------------------------------------*/
+
+    uint8_t ucPortGetCoreID( void )
+    {
+        return *(volatile uint8_t *)(configCORE_ID_REGISTER);
+    }
+
+/*-----------------------------------------------------------*/
+
+#endif /* if( configNUMBER_OF_CORES > 1 ) */
diff --git a/Source/portable/IAR/ARM_CM23/non_secure/portasm.h b/Source/portable/IAR/ARM_CM23/non_secure/portasm.h
index 53b4b6e..b4b545f 100644
--- a/Source/portable/IAR/ARM_CM23/non_secure/portasm.h
+++ b/Source/portable/IAR/ARM_CM23/non_secure/portasm.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM23/non_secure/portasm.s b/Source/portable/IAR/ARM_CM23/non_secure/portasm.s
index 6b25588..137d464 100644
--- a/Source/portable/IAR/ARM_CM23/non_secure/portasm.s
+++ b/Source/portable/IAR/ARM_CM23/non_secure/portasm.s
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -40,6 +40,12 @@
     #define configUSE_MPU_WRAPPERS_V1 0
 #endif
 
+#if ( configENABLE_MPU == 1 )
+    #define SECURE_CONTEXT_OFFSET   -20
+#else
+    #define SECURE_CONTEXT_OFFSET   0
+#endif
+
 
     EXTERN pxCurrentTCB
     EXTERN xSecureContext
@@ -512,8 +518,9 @@
 /*-----------------------------------------------------------*/
 
 vPortFreeSecureContext:
-    ldr r2, [r0]                            /* The first item in the TCB is the top of the stack. */
-    ldr r1, [r2]                            /* The first item on the stack is the task's xSecureContext. */
+    ldr r2, [r0]                            /* The first item in the TCB is the stored context location. */
+    adds r2, r2, #SECURE_CONTEXT_OFFSET     /* r2 = r2 + SECURE_CONTEXT_OFFSET. */
+    ldr r1, [r2]                            /* Read xSecureContext from the task's context. */
     cmp r1, #0                              /* Raise svc if task's xSecureContext is not NULL. */
     bne free_secure_context                 /* Branch if r1 != 0. */
     bx lr                                   /* There is no secure context (xSecureContext is NULL). */
diff --git a/Source/portable/IAR/ARM_CM23/non_secure/portmacro.h b/Source/portable/IAR/ARM_CM23/non_secure/portmacro.h
index 6cf50c5..4fb83e0 100644
--- a/Source/portable/IAR/ARM_CM23/non_secure/portmacro.h
+++ b/Source/portable/IAR/ARM_CM23/non_secure/portmacro.h
@@ -1,6 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * Copyright 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -52,6 +53,7 @@
 #define portHAS_ARMV8M_MAIN_EXTENSION    0
 #define portARMV8M_MINOR_VERSION         0
 #define portDONT_DISCARD                 __root
+#define portVALIDATED_FOR_SMP            0
 /*-----------------------------------------------------------*/
 
 /* ARMv8-M common port configurations. */
diff --git a/Source/portable/IAR/ARM_CM23/non_secure/portmacrocommon.h b/Source/portable/IAR/ARM_CM23/non_secure/portmacrocommon.h
index 2dfac6a..c34fdee 100644
--- a/Source/portable/IAR/ARM_CM23/non_secure/portmacrocommon.h
+++ b/Source/portable/IAR/ARM_CM23/non_secure/portmacrocommon.h
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -59,6 +58,19 @@
     #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h.  Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
 #endif /* configENABLE_TRUSTZONE */
 
+#if ( configNUMBER_OF_CORES > 1 )
+    #if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 )
+        #error "Multi-core SMP is currently only validated for Cortex-M33 non-TrustZone non-MPU port."
+    #endif /* if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 ) ) */
+
+    #ifndef configCORE_ID_REGISTER
+        #error "configCORE_ID_REGISTER must be defined to the address of the register used to identify the core executing the code."
+    #endif /* ifndef configCORE_ID_REGISTER */
+
+    #ifndef configWAKE_SECONDARY_CORES
+        #error "configWAKE_SECONDARY_CORES must be defined to a function that wakes the secondary cores."
+    #endif /* ifndef configWAKE_SECONDARY_CORES */
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -428,10 +440,26 @@
 /**
  * @brief Critical section management.
  */
+
+#define portSET_INTERRUPT_MASK()                  ulSetInterruptMask()
+#define portCLEAR_INTERRUPT_MASK( x )             vClearInterruptMask( x )
 #define portSET_INTERRUPT_MASK_FROM_ISR()         ulSetInterruptMask()
 #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x )    vClearInterruptMask( x )
-#define portENTER_CRITICAL()                      vPortEnterCritical()
-#define portEXIT_CRITICAL()                       vPortExitCritical()
+
+#if ( configNUMBER_OF_CORES == 1 )
+    #define portENTER_CRITICAL()                      vPortEnterCritical()
+    #define portEXIT_CRITICAL()                       vPortExitCritical()
+#else /* ( configNUMBER_OF_CORES == 1 ) */
+    extern void vTaskEnterCritical( void );
+    extern void vTaskExitCritical( void );
+    extern UBaseType_t vTaskEnterCriticalFromISR( void );
+    extern void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus );
+
+    #define portENTER_CRITICAL()                      vTaskEnterCritical()
+    #define portEXIT_CRITICAL()                       vTaskExitCritical()
+    #define portENTER_CRITICAL_FROM_ISR()             vTaskEnterCriticalFromISR()
+    #define portEXIT_CRITICAL_FROM_ISR( x )           vTaskExitCriticalFromISR( x )
+#endif /* if ( configNUMBER_OF_CORES != 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -526,7 +554,7 @@
 /* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION
  * based on whether or not Mainline extension is implemented. */
 #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
-    #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 )
+    #if ( ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) && ( configNUMBER_OF_CORES == 1 ) )
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    1
     #else
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    0
@@ -573,6 +601,44 @@
 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
 /*-----------------------------------------------------------*/
 
+
+#if ( configNUMBER_OF_CORES > 1 )
+    typedef enum
+    {
+        eIsrLock = 0,
+        eTaskLock,
+        eLockCount
+    } ePortRTOSLock;
+
+    extern volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ];
+    extern void vPortRecursiveLock( uint8_t ucCoreID,
+                                    ePortRTOSLock eLockNum,
+                                    BaseType_t uxAcquire );
+    extern uint8_t ucPortGetCoreID( void );
+    extern void vInterruptCore( uint8_t ucCoreID );
+
+    #define portGET_CORE_ID()                                  ucPortGetCoreID()
+
+    #define portGET_CRITICAL_NESTING_COUNT( xCoreID )          ( ulCriticalNestings[ ( uint8_t ) xCoreID ] )
+    #define portSET_CRITICAL_NESTING_COUNT( xCoreID, x )       ( ulCriticalNestings[ ( uint8_t ) xCoreID ] = ( x ) )
+    #define portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]++ )
+    #define portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]-- )
+
+    #define portMAX_CORE_COUNT                                 ( configNUMBER_OF_CORES )
+
+    #define portYIELD_CORE( xCoreID )                          vInterruptCore( xCoreID )
+
+    #define portRELEASE_ISR_LOCK( xCoreID )                    vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdFALSE )
+    #define portGET_ISR_LOCK( xCoreID )                        vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdTRUE )
+
+    #define portRELEASE_TASK_LOCK( xCoreID )                   vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdFALSE )
+    #define portGET_TASK_LOCK( xCoreID )                       vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdTRUE )
+
+    #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* ( configENABLE_PAC == 1 || configENABLE_BTI == 1 ) */
+#endif
+
 /* *INDENT-OFF* */
 #ifdef __cplusplus
     }
diff --git a/Source/portable/IAR/ARM_CM23/secure/secure_context.c b/Source/portable/IAR/ARM_CM23/secure/secure_context.c
index 62bcfa1..2dae022 100644
--- a/Source/portable/IAR/ARM_CM23/secure/secure_context.c
+++ b/Source/portable/IAR/ARM_CM23/secure/secure_context.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -213,8 +213,19 @@
         /* Were we able to get a free context? */
         if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS )
         {
-            /* Allocate the stack space. */
-            pucStackMemory = pvPortMalloc( ulSecureStackSize + securecontextSTACK_SEAL_SIZE );
+            /* Allocate the stack space if possible. */
+            if( ( ulSecureStackSize < securecontextSTACK_SEAL_SIZE ) ||
+                ( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) )
+            {
+                /* Reject stacks that are too small (the CONTROL word would be
+                 * written before the allocation, corrupting the secure heap)
+                 * and sizes that would overflow when the seal size is added. */
+                pucStackMemory = NULL;
+            }
+            else
+            {
+                pucStackMemory = pvPortMalloc( ulSecureStackSize + securecontextSTACK_SEAL_SIZE );
+            }
 
             if( pucStackMemory != NULL )
             {
@@ -279,9 +290,12 @@
                                                               void * pvTaskHandle )
 {
     uint32_t ulIPSR, ulSecureContextIndex;
+    uint8_t * pucStackLimit;
 
-    /* Read the Interrupt Program Status Register (IPSR) value. */
+    /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
+     * Register (PSPLIM) value. */
     secureportREAD_IPSR( ulIPSR );
+    secureportREAD_PSPLIM( pucStackLimit );
 
     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
      * when the processor is running in the Thread Mode. */
@@ -293,8 +307,14 @@
             ulSecureContextIndex = xSecureContextHandle - 1UL;
 
             /* Ensure that the secure context being deleted is associated with
-             * the task. */
-            if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
+             * the task and is NOT the currently-loaded context. Freeing a
+             * context whose stack is currently loaded in PSPLIM would leave the
+             * running task referencing freed secure memory (use-after-free).
+             * pvTaskHandle is supplied by the non-secure side and is untrusted,
+             * so it is used only as an additional ownership match, not as
+             * authority. */
+            if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) &&
+                ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) )
             {
                 /* Free the stack space. */
                 vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
@@ -342,7 +362,7 @@
 
         secureportREAD_PSPLIM( pucStackLimit );
 
-        /* Ensure that task's context is loaded and the task is saving it's own
+        /* Ensure that task's context is loaded and the task is saving its own
          * context. */
         if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) &&
             ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) )
diff --git a/Source/portable/IAR/ARM_CM23/secure/secure_context.h b/Source/portable/IAR/ARM_CM23/secure/secure_context.h
index 8b93857..51dd823 100644
--- a/Source/portable/IAR/ARM_CM23/secure/secure_context.h
+++ b/Source/portable/IAR/ARM_CM23/secure/secure_context.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM23/secure/secure_context_port_asm.s b/Source/portable/IAR/ARM_CM23/secure/secure_context_port_asm.s
index e3ff975..0a52ad1 100644
--- a/Source/portable/IAR/ARM_CM23/secure/secure_context_port_asm.s
+++ b/Source/portable/IAR/ARM_CM23/secure/secure_context_port_asm.s
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM23/secure/secure_heap.c b/Source/portable/IAR/ARM_CM23/secure/secure_heap.c
index b0e83b4..58226bf 100644
--- a/Source/portable/IAR/ARM_CM23/secure/secure_heap.c
+++ b/Source/portable/IAR/ARM_CM23/secure/secure_heap.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM23/secure/secure_heap.h b/Source/portable/IAR/ARM_CM23/secure/secure_heap.h
index 61a96da..906fa24 100644
--- a/Source/portable/IAR/ARM_CM23/secure/secure_heap.h
+++ b/Source/portable/IAR/ARM_CM23/secure/secure_heap.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM23/secure/secure_init.c b/Source/portable/IAR/ARM_CM23/secure/secure_init.c
index f7f7e67..6996692 100644
--- a/Source/portable/IAR/ARM_CM23/secure/secure_init.c
+++ b/Source/portable/IAR/ARM_CM23/secure/secure_init.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM23/secure/secure_init.h b/Source/portable/IAR/ARM_CM23/secure/secure_init.h
index 46ffbd9..4e7bd40 100644
--- a/Source/portable/IAR/ARM_CM23/secure/secure_init.h
+++ b/Source/portable/IAR/ARM_CM23/secure/secure_init.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM23/secure/secure_port_macros.h b/Source/portable/IAR/ARM_CM23/secure/secure_port_macros.h
index 34494e1..72774eb 100644
--- a/Source/portable/IAR/ARM_CM23/secure/secure_port_macros.h
+++ b/Source/portable/IAR/ARM_CM23/secure/secure_port_macros.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM23_NTZ/non_secure/mpu_wrappers_v2_asm.S b/Source/portable/IAR/ARM_CM23_NTZ/non_secure/mpu_wrappers_v2_asm.S
index eaafcee..39695d6 100644
--- a/Source/portable/IAR/ARM_CM23_NTZ/non_secure/mpu_wrappers_v2_asm.S
+++ b/Source/portable/IAR/ARM_CM23_NTZ/non_secure/mpu_wrappers_v2_asm.S
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM23_NTZ/non_secure/port.c b/Source/portable/IAR/ARM_CM23_NTZ/non_secure/port.c
index f16a343..007150c 100644
--- a/Source/portable/IAR/ARM_CM23_NTZ/non_secure/port.c
+++ b/Source/portable/IAR/ARM_CM23_NTZ/non_secure/port.c
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024-2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -145,13 +144,13 @@
 /**
  * @brief Constants required to manipulate the FPU.
  */
-#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 )              /* Coprocessor Access Control Register. */
+#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */
 #define portCPACR_CP10_VALUE    ( 3UL )
 #define portCPACR_CP11_VALUE    portCPACR_CP10_VALUE
 #define portCPACR_CP10_POS      ( 20UL )
 #define portCPACR_CP11_POS      ( 22UL )
 
-#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 )              /* Floating Point Context Control Register. */
+#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
 #define portFPCCR_ASPEN_POS     ( 31UL )
 #define portFPCCR_ASPEN_MASK    ( 1UL << portFPCCR_ASPEN_POS )
 #define portFPCCR_LSPEN_POS     ( 30UL )
@@ -188,8 +187,8 @@
 #define portMPU_MAIR0_REG                       ( *( ( volatile uint32_t * ) 0xe000edc0 ) )
 #define portMPU_MAIR1_REG                       ( *( ( volatile uint32_t * ) 0xe000edc4 ) )
 
-#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
-#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
+#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
+#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
 
 #define portMPU_RBAR_ACCESS_PERMISSIONS_MASK    ( 3UL << 1UL )
 
@@ -230,8 +229,8 @@
 
 #if ( portARMV8M_MINOR_VERSION >= 1 )
 
-/* Enable Privileged eXecute Never MPU attribute for the selected memory
- * region. */
+    /* Enable Privileged eXecute Never MPU attribute for the selected memory
+     * region. */
     #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER    ( 1UL << 4UL )
 #endif /* portARMV8M_MINOR_VERSION >= 1 */
 
@@ -241,9 +240,6 @@
 /* Enable MPU. */
 #define portMPU_ENABLE_BIT                    ( 1UL << 0UL )
 
-/* Expected value of the portMPU_TYPE register. */
-#define portEXPECTED_MPU_TYPE_VALUE           ( configTOTAL_MPU_REGIONS << 8UL )
-
 /* Extract first address of the MPU region as encoded in the
  * RBAR (Region Base Address Register) value. */
 #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@@ -291,37 +287,37 @@
 
 #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         FD
- * 1111 1111  1111 1111  1111 1111  1111 1101
- *
- * Bit[6] - 1 --> The exception was taken from the Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 1 --> The exception was taken to the Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         FD
+     * 1111 1111  1111 1111  1111 1111  1111 1101
+     *
+     * Bit[6] - 1 --> The exception was taken from the Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 1 --> The exception was taken to the Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xfffffffd )
 #else
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         BC
- * 1111 1111  1111 1111  1111 1111  1011 1100
- *
- * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         BC
+     * 1111 1111  1111 1111  1111 1111  1011 1100
+     *
+     * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xffffffbc )
 #endif /* configRUN_FREERTOS_SECURE_ONLY */
 
@@ -401,50 +397,54 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Extract MPU region's access permissions from the Region Base Address
- * Register (RBAR) value.
- *
- * @param ulRBARValue RBAR value for the MPU region.
- *
- * @return uint32_t Access permissions.
- */
+    /**
+     * @brief Extract MPU region's access permissions from the Region Base Address
+     * Register (RBAR) value.
+     *
+     * @param ulRBARValue RBAR value for the MPU region.
+     *
+     * @return uint32_t Access permissions.
+     */
     static uint32_t prvGetRegionAccessPermissions( uint32_t ulRBARValue ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU == 1 && configUSE_MPU_WRAPPERS_V1 == 0 */
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Setup the Memory Protection Unit (MPU).
- */
+    /**
+     * @brief Setup the Memory Protection Unit (MPU).
+     */
     static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU */
 
 #if ( configENABLE_FPU == 1 )
 
-/**
- * @brief Setup the Floating Point Unit (FPU).
- */
+    /**
+     * @brief Setup the Floating Point Unit (FPU).
+     */
     static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_FPU */
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
 
-/**
- * @brief Configures PACBTI features.
- *
- * This function configures the Pointer Authentication, and Branch Target
- * Identification security features as per the user configuration. It returns
- * the value of the special purpose CONTROL register accordingly, and optionally
- * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
- * architecture based) target supports PACBTI security feature.
- *
- * @param xWriteControlRegister Used to control whether the special purpose
- * CONTROL register should be updated or not.
- *
- * @return CONTROL register value according to the configured PACBTI option.
- */
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    /**
+     * @brief Configures PACBTI features.
+     *
+     * This function configures the Pointer Authentication, and Branch Target
+     * Identification security features as per the user configuration. It returns
+     * the value of the special purpose CONTROL register accordingly, and optionally
+     * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
+     * architecture based) target supports PACBTI security feature.
+     *
+     * @param xWriteControlRegister Used to control whether the special purpose
+     * CONTROL register should be updated or not.
+     *
+     * @return CONTROL register value according to the configured PACBTI option.
+     */
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -491,14 +491,14 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the system call stack so that upon returning from
- * SVC, the system call stack is used.
- *
- * @param pulTaskStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- * @param ucSystemCallNumber The system call number of the system call.
- */
+    /**
+     * @brief Sets up the system call stack so that upon returning from
+     * SVC, the system call stack is used.
+     *
+     * @param pulTaskStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     * @param ucSystemCallNumber The system call number of the system call.
+     */
     void vSystemCallEnter( uint32_t * pulTaskStack,
                            uint32_t ulLR,
                            uint8_t ucSystemCallNumber ) PRIVILEGED_FUNCTION;
@@ -507,22 +507,22 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Raise SVC for exiting from a system call.
- */
+    /**
+     * @brief Raise SVC for exiting from a system call.
+     */
     void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the task stack so that upon returning from
- * SVC, the task stack is used again.
- *
- * @param pulSystemCallStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- */
+    /**
+     * @brief Sets up the task stack so that upon returning from
+     * SVC, the task stack is used again.
+     *
+     * @param pulSystemCallStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     */
     void vSystemCallExit( uint32_t * pulSystemCallStack,
                           uint32_t ulLR ) PRIVILEGED_FUNCTION;
 
@@ -530,21 +530,38 @@
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Checks whether or not the calling task is privileged.
- *
- * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
- */
+    /**
+     * @brief Checks whether or not the calling task is privileged.
+     *
+     * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
+     */
     BaseType_t xPortIsTaskPrivileged( void ) PRIVILEGED_FUNCTION;
 
 #endif /* configENABLE_MPU == 1 */
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /**
+     * @brief Platform/Application-defined function that wakes up the secondary cores.
+     *
+     * @return pdTRUE if the secondary cores were successfully woken up.
+     *         pdFALSE otherwise.
+     */
+    extern BaseType_t configWAKE_SECONDARY_CORES( void );
+
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
+
+/**
+ * @brief Configures interrupt priorities.
+ */
+void vPortConfigureInterruptPriorities( void ) PRIVILEGED_FUNCTION;
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief This variable is set to pdTRUE when the scheduler is started.
- */
+    /**
+     * @brief This variable is set to pdTRUE when the scheduler is started.
+     */
     PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
@@ -553,14 +570,22 @@
  * @brief Each task maintains its own interrupt status in the critical nesting
  * variable.
  */
-PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
+#if ( configNUMBER_OF_CORES == 1 )
+    PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0UL;
+#else /* #if ( configNUMBER_OF_CORES == 1 ) */
+    PRIVILEGED_DATA volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ] = { 0 };
+    /* Flags to check if the secondary cores are ready. */
+    PRIVILEGED_DATA volatile uint8_t ucSecondaryCoresReadyFlags[ configNUMBER_OF_CORES - 1 ] = { 0 };
+    /* Flag to indicate that the primary core has completed its initialisation. */
+    PRIVILEGED_DATA volatile uint8_t ucPrimaryCoreInitDoneFlag = 0;
+ #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #if ( configENABLE_TRUSTZONE == 1 )
 
-/**
- * @brief Saved as part of the task context to indicate which context the
- * task is using on the secure side.
- */
+    /**
+     * @brief Saved as part of the task context to indicate which context the
+     * task is using on the secure side.
+     */
     PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
 #endif /* configENABLE_TRUSTZONE */
 
@@ -579,21 +604,21 @@
 
 #if ( configUSE_TICKLESS_IDLE == 1 )
 
-/**
- * @brief The number of SysTick increments that make up one tick period.
- */
+    /**
+     * @brief The number of SysTick increments that make up one tick period.
+     */
     PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
 
-/**
- * @brief The maximum number of tick periods that can be suppressed is
- * limited by the 24 bit resolution of the SysTick timer.
- */
+    /**
+     * @brief The maximum number of tick periods that can be suppressed is
+     * limited by the 24 bit resolution of the SysTick timer.
+     */
     PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
 
-/**
- * @brief Compensate for the CPU cycles that pass while the SysTick is
- * stopped (low power functionality only).
- */
+    /**
+     * @brief Compensate for the CPU cycles that pass while the SysTick is
+     * stopped (low power functionality only).
+     */
     PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0;
 #endif /* configUSE_TICKLESS_IDLE */
 /*-----------------------------------------------------------*/
@@ -856,7 +881,11 @@
      * should instead call vTaskDelete( NULL ). Artificially force an assert()
      * to be triggered if configASSERT() is defined, then stop here so
      * application writers can catch the error. */
-    configASSERT( ulCriticalNesting == ~0UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == ~0UL );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == ~0UL );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
     portDISABLE_INTERRUPTS();
 
     while( ulDummy == 0 )
@@ -925,64 +954,57 @@
         /* The only permitted number of regions are 8 or 16. */
         configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 16 ) );
 
-        /* Ensure that the configTOTAL_MPU_REGIONS is configured correctly. */
-        configASSERT( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE );
+        /* MAIR0 - Index 0. */
+        portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
+        /* MAIR0 - Index 1. */
+        portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
 
-        /* Check that the MPU is present. */
-        if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
-        {
-            /* MAIR0 - Index 0. */
-            portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
-            /* MAIR0 - Index 1. */
-            portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
+        /* Setup privileged flash as Read Only so that privileged tasks can
+         * read it but not modify. */
+        portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup privileged flash as Read Only so that privileged tasks can
-             * read it but not modify. */
-            portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged flash as Read Only by both privileged and
+         * unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged flash as Read Only by both privileged and
-             * unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged syscalls flash as Read Only by both privileged
+         * and unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged syscalls flash as Read Only by both privileged
-             * and unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup RAM containing kernel data for privileged access only. */
+        portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
+                           ( portMPU_REGION_EXECUTE_NEVER );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup RAM containing kernel data for privileged access only. */
-            portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
-                               ( portMPU_REGION_EXECUTE_NEVER );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Enable mem fault. */
+        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
 
-            /* Enable mem fault. */
-            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
-
-            /* Enable MPU with privileged background access i.e. unmapped
-             * regions have privileged access. */
-            portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
-        }
+        /* Enable MPU with privileged background access i.e. unmapped
+         * regions have privileged access. */
+        portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
     }
 
 #endif /* configENABLE_MPU */
@@ -1027,28 +1049,29 @@
 }
 /*-----------------------------------------------------------*/
 
-void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    portDISABLE_INTERRUPTS();
-    ulCriticalNesting++;
-
-    /* Barriers are normally not required but do ensure the code is
-     * completely within the specified behaviour for the architecture. */
-    __asm volatile ( "dsb" ::: "memory" );
-    __asm volatile ( "isb" );
-}
-/*-----------------------------------------------------------*/
-
-void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    configASSERT( ulCriticalNesting );
-    ulCriticalNesting--;
-
-    if( ulCriticalNesting == 0 )
+#if ( configNUMBER_OF_CORES == 1 )
+    void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
     {
-        portENABLE_INTERRUPTS();
+        portDISABLE_INTERRUPTS();
+        ulCriticalNesting++;
+        /* Barriers are normally not required but do ensure the code is
+        * completely within the specified behaviour for the architecture. */
+        __asm volatile ( "dsb" ::: "memory" );
+        __asm volatile ( "isb" );
     }
-}
+    /*-----------------------------------------------------------*/
+
+    void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
+    {
+        configASSERT( ulCriticalNesting );
+        ulCriticalNesting--;
+
+        if( ulCriticalNesting == 0 )
+        {
+            portENABLE_INTERRUPTS();
+        }
+    }
+#endif /* configNUMBER_OF_CORES == 1 */
 /*-----------------------------------------------------------*/
 
 void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
@@ -1056,6 +1079,10 @@
     uint32_t ulPreviousMask;
 
     ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
+    #if ( configNUMBER_OF_CORES > 1 )
+        UBaseType_t uxSavedInterruptStatus = portENTER_CRITICAL_FROM_ISR();
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     traceISR_ENTER();
     {
         /* Increment the RTOS tick. */
@@ -1070,6 +1097,10 @@
             traceISR_EXIT();
         }
     }
+    #if ( configNUMBER_OF_CORES > 1 )
+        portEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
 }
 /*-----------------------------------------------------------*/
@@ -1078,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1090,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1108,38 +1151,42 @@
 
     switch( ucSVCNumber )
     {
-        #if ( configENABLE_TRUSTZONE == 1 )
-            case portSVC_ALLOCATE_SECURE_CONTEXT:
+    #if ( configENABLE_TRUSTZONE == 1 )
+        case portSVC_ALLOCATE_SECURE_CONTEXT:
 
-                /* R0 contains the stack size passed as parameter to the
-                 * vPortAllocateSecureContext function. */
-                ulR0 = pulCallerStackAddress[ 0 ];
+            /* R0 contains the stack size passed as parameter to the
+             * vPortAllocateSecureContext function. */
+            ulR0 = pulCallerStackAddress[ 0 ];
 
-                #if ( configENABLE_MPU == 1 )
-                {
-                    /* Read the CONTROL register value. */
-                    __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
+            #if ( configENABLE_MPU == 1 )
+            {
+                /* Read the CONTROL register value. */
+                __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
 
-                    /* The task that raised the SVC is privileged if Bit[0]
-                     * in the CONTROL register is 0. */
-                    ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
+                /* The task that raised the SVC is privileged if Bit[0]
+                 * in the CONTROL register is 0. */
+                ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
 
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
-                }
-                #else /* if ( configENABLE_MPU == 1 ) */
-                {
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
-                }
-                #endif /* configENABLE_MPU */
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
+            }
+            #else /* if ( configENABLE_MPU == 1 ) */
+            {
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
+            }
+            #endif /* configENABLE_MPU */
 
-                configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
-                SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
-                break;
+            configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
+            SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
+            break;
 
-            case portSVC_FREE_SECURE_CONTEXT:
-
+        case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
                 /* R0 contains TCB being freed and R1 contains the secure
                  * context handle to be freed. */
                 ulR0 = pulCallerStackAddress[ 0 ];
@@ -1147,51 +1194,62 @@
 
                 /* Free the secure context. */
                 SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
-                break;
-        #endif /* configENABLE_TRUSTZONE */
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
+            break;
+    #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
-            #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
-                case portSVC_RAISE_PRIVILEGE:
+    #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
+        case portSVC_RAISE_PRIVILEGE:
 
-                    /* Only raise the privilege, if the svc was raised from any of
-                     * the system calls. */
-                    if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
-                        ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
-                    {
-                        vRaisePrivilege();
-                    }
-                    break;
-            #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
+            /* Only raise the privilege, if the svc was raised from any of
+             * the system calls. */
+            if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
+                ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
+            {
+                vRaisePrivilege();
+            }
+            break;
+    #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
-            #if ( configENABLE_MPU == 1 )
-                case portSVC_YIELD:
-                    vPortYield();
-                    break;
-            #endif /* configENABLE_MPU == 1 */
+    #if ( configENABLE_MPU == 1 )
+        case portSVC_YIELD:
+            vPortYield();
+            break;
+    #endif /* configENABLE_MPU == 1 */
 
         default:
             /* Incorrect SVC call. */
@@ -1210,7 +1268,7 @@
         extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulSystemCallStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1246,12 +1304,16 @@
         {
             pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1261,20 +1323,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the system call stack for the stack frame. */
-            pulSystemCallStack = pulSystemCallStack - ulStackFrameSize;
+            pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulSystemCallStack[ i ] = pulTaskStack[ i ];
             }
@@ -1310,7 +1372,7 @@
 
             /* Remember the location where we should copy the stack frame when we exit from
              * the system call. */
-            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
+            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
 
             /* Record if the hardware used padding to force the stack pointer
              * to be double word aligned. */
@@ -1360,7 +1422,7 @@
         extern TaskHandle_t pxCurrentTCB;
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulTaskStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1392,12 +1454,16 @@
         {
             pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1407,20 +1473,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the task stack for the stack frame. */
-            pulTaskStack = pulTaskStack - ulStackFrameSize;
+            pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulTaskStack[ i ] = pulSystemCallStack[ i ];
             }
@@ -1518,21 +1584,21 @@
         xMPUSettings->ulContext[ ulIndex ] = 0x11111111; /* r11. */
         ulIndex++;
 
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters;            /* r0. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters; /* r0. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x01010101;                           /* r1. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x01010101; /* r1. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x02020202;                           /* r2. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x02020202; /* r2. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x03030303;                           /* r3. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x03030303; /* r3. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x12121212;                           /* r12. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x12121212; /* r12. */
         ulIndex++;
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) portTASK_RETURN_ADDRESS; /* LR. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode;                  /* PC. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode; /* PC. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR;                     /* xPSR. */
+        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR; /* xPSR. */
         ulIndex++;
 
         #if ( configENABLE_TRUSTZONE == 1 )
@@ -1543,14 +1609,18 @@
         #endif /* configENABLE_TRUSTZONE */
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) ( pxTopOfStack - 8 ); /* PSP with the hardware saved stack. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack;         /* PSPLIM. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack; /* PSPLIM. */
         ulIndex++;
 
         #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
         {
             /* Check PACBTI security feature configuration before pushing the
              * CONTROL register's value on task's TCB. */
-            ulControl = prvConfigurePACBTI( pdFALSE );
+            #if ( configNUMBER_OF_CORES == 1 )
+                ulControl = prvConfigurePACBTI( pdFALSE );
+            #else /* configNUMBER_OF_CORES > 1 */
+                ulControl = vConfigurePACBTI( pdFALSE );
+            #endif /* configNUMBER_OF_CORES */
         }
         #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1615,15 +1685,15 @@
          * interrupt. */
         #if ( portPRELOAD_REGISTERS == 0 )
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
-            pxTopOfStack -= 5;                                       /* R12, R3, R2 and R1. */
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
-            pxTopOfStack -= 9;                                       /* R11..R4, EXC_RETURN. */
+            pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
+            pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */
             *pxTopOfStack = portINITIAL_EXC_RETURN;
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
@@ -1637,42 +1707,42 @@
         }
         #else /* portPRELOAD_REGISTERS */
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x12121212UL;            /* R12. */
+            *pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x03030303UL;            /* R3. */
+            *pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x02020202UL;            /* R2. */
+            *pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x01010101UL;            /* R1. */
+            *pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x11111111UL;            /* R11. */
+            *pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x10101010UL;            /* R10. */
+            *pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x09090909UL;            /* R09. */
+            *pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x08080808UL;            /* R08. */
+            *pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x07070707UL;            /* R07. */
+            *pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x06060606UL;            /* R06. */
+            *pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x05050505UL;            /* R05. */
+            *pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x04040404UL;            /* R04. */
+            *pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04. */
             pxTopOfStack--;
-            *pxTopOfStack = portINITIAL_EXC_RETURN;                  /* EXC_RETURN. */
+            *pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxEndOfStack;            /* Slot used to hold this task's PSPLIM value. */
+            *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
 
             #if ( configENABLE_TRUSTZONE == 1 )
             {
@@ -1739,91 +1809,17 @@
     }
     #endif /* configCHECK_HANDLER_INSTALLATION */
 
-    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
-    {
-        volatile uint32_t ulImplementedPrioBits = 0;
-        volatile uint8_t ucMaxPriorityValue;
-
-        /* Determine the maximum priority from which ISR safe FreeRTOS API
-         * functions can be called. ISR safe functions are those that end in
-         * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
-         * ensure interrupt entry is as fast and simple as possible.
-         *
-         * First, determine the number of priority bits available. Write to all
-         * possible bits in the priority setting for SVCall. */
-        portNVIC_SHPR2_REG = 0xFF000000;
-
-        /* Read the value back to see how many bits stuck. */
-        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
-
-        /* Use the same mask on the maximum system call priority. */
-        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
-
-        /* Check that the maximum system call priority is nonzero after
-         * accounting for the number of priority bits supported by the
-         * hardware. A priority of 0 is invalid because setting the BASEPRI
-         * register to 0 unmasks all interrupts, and interrupts with priority 0
-         * cannot be masked using BASEPRI.
-         * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
-        configASSERT( ucMaxSysCallPriority );
-
-        /* Check that the bits not implemented in hardware are zero in
-         * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
-        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
-
-        /* Calculate the maximum acceptable priority group value for the number
-         * of bits read back. */
-        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
-        {
-            ulImplementedPrioBits++;
-            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
-        }
-
-        if( ulImplementedPrioBits == 8 )
-        {
-            /* When the hardware implements 8 priority bits, there is no way for
-             * the software to configure PRIGROUP to not have sub-priorities. As
-             * a result, the least significant bit is always used for sub-priority
-             * and there are 128 preemption priorities and 2 sub-priorities.
-             *
-             * This may cause some confusion in some cases - for example, if
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
-             * priority interrupts will be masked in Critical Sections as those
-             * are at the same preemption priority. This may appear confusing as
-             * 4 is higher (numerically lower) priority than
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
-             * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
-             * to 4, this confusion does not happen and the behaviour remains the same.
-             *
-             * The following assert ensures that the sub-priority bit in the
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
-             * confusion. */
-            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
-            ulMaxPRIGROUPValue = 0;
-        }
-        else
-        {
-            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
-        }
-
-        /* Shift the priority group value back to its position within the AIRCR
-         * register. */
-        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
-        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
-    }
-    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
-
-    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
-     * the highest priority. */
-    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
-    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
-    portNVIC_SHPR2_REG = 0;
+    vPortConfigureInterruptPriorities();
 
     #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
     {
         /* Set the CONTROL register value based on PACBTI security feature
          * configuration before starting the first task. */
-        ( void ) prvConfigurePACBTI( pdTRUE );
+        #if ( configNUMBER_OF_CORES == 1 )
+            ( void ) prvConfigurePACBTI( pdTRUE );
+        #else /* configNUMBER_OF_CORES > 1 */
+            ( void ) vConfigurePACBTI( pdTRUE );
+        #endif /* configNUMBER_OF_CORES */
     }
     #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1834,12 +1830,47 @@
     }
     #endif /* configENABLE_MPU */
 
-    /* Start the timer that generates the tick ISR. Interrupts are disabled
-     * here already. */
-    vPortSetupTimerInterrupt();
+    #if ( configNUMBER_OF_CORES > 1 )
+        /* Start the timer that generates the tick ISR. Interrupts are disabled
+         * here already. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count for all cores. */
+        for ( uint8_t ucCoreID = 0; ucCoreID < configNUMBER_OF_CORES; ucCoreID++ )
+        {
+            ulCriticalNestings[ ucCoreID ] = 0;
+        }
+        /* Signal that primary core has done all the necessary initialisations. */
+        ucPrimaryCoreInitDoneFlag = 1;
+        /* Wake up secondary cores */
+        BaseType_t xWakeResult = configWAKE_SECONDARY_CORES();
+        configASSERT( xWakeResult == pdTRUE );
 
-    /* Initialize the critical nesting count ready for the first task. */
-    ulCriticalNesting = 0;
+        /* Hold the primary core here until all the secondary cores are ready, this would be achieved only when
+         * all elements of ucSecondaryCoresReadyFlags are set.
+         */
+        while( 1 )
+        {
+            BaseType_t xAllCoresReady = pdTRUE;
+            for( uint8_t ucCoreID = 0; ucCoreID < ( configNUMBER_OF_CORES - 1 ); ucCoreID++ )
+            {
+                if( ucSecondaryCoresReadyFlags[ ucCoreID ] != pdTRUE )
+                {
+                    xAllCoresReady = pdFALSE;
+                    break;
+                }
+                }
+
+            if ( xAllCoresReady == pdTRUE )
+            {
+                break;
+            }
+        }
+    #else /* if ( configNUMBER_OF_CORES > 1 ) */
+        /* Start the timer that generates the tick ISR. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count ready for the first task. */
+        ulCriticalNesting = 0;
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
     {
@@ -1856,7 +1887,11 @@
      * functionality by defining configTASK_RETURN_ADDRESS. Call
      * vTaskSwitchContext() so link time optimization does not remove the
      * symbol. */
-    vTaskSwitchContext();
+    #if ( configNUMBER_OF_CORES > 1 )
+        vTaskSwitchContext( portGET_CORE_ID() );
+    #else
+        vTaskSwitchContext();
+    #endif
     prvTaskExitError();
 
     /* Should not get here. */
@@ -1868,7 +1903,11 @@
 {
     /* Not implemented in ports where there is nothing to return to.
      * Artificially force an assert. */
-    configASSERT( ulCriticalNesting == 1000UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == 1000UL );
+    #else /* if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == 1000UL );
+    #endif /* if ( configNUMBER_OF_CORES == 1 ) */
 }
 /*-----------------------------------------------------------*/
 
@@ -2151,6 +2190,90 @@
 #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
 /*-----------------------------------------------------------*/
 
+void vPortConfigureInterruptPriorities( void ) /* PRIVILEGED_FUNCTION */
+{
+    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
+    {
+        volatile uint32_t ulImplementedPrioBits = 0;
+        volatile uint8_t ucMaxPriorityValue;
+
+        /* Determine the maximum priority from which ISR safe FreeRTOS API
+        * functions can be called. ISR safe functions are those that end in
+        * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
+        * ensure interrupt entry is as fast and simple as possible.
+        *
+        * First, determine the number of priority bits available. Write to all
+        * possible bits in the priority setting for SVCall. */
+        portNVIC_SHPR2_REG = 0xFF000000;
+
+        /* Read the value back to see how many bits stuck. */
+        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
+
+        /* Use the same mask on the maximum system call priority. */
+        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
+
+        /* Check that the maximum system call priority is nonzero after
+        * accounting for the number of priority bits supported by the
+        * hardware. A priority of 0 is invalid because setting the BASEPRI
+        * register to 0 unmasks all interrupts, and interrupts with priority 0
+        * cannot be masked using BASEPRI.
+        * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+        configASSERT( ucMaxSysCallPriority );
+
+        /* Check that the bits not implemented in hardware are zero in
+        * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
+        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
+
+        /* Calculate the maximum acceptable priority group value for the number
+        * of bits read back. */
+        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
+        {
+            ulImplementedPrioBits++;
+            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
+        }
+
+        if( ulImplementedPrioBits == 8 )
+        {
+            /* When the hardware implements 8 priority bits, there is no way for
+            * the software to configure PRIGROUP to not have sub-priorities. As
+            * a result, the least significant bit is always used for sub-priority
+            * and there are 128 preemption priorities and 2 sub-priorities.
+            *
+            * This may cause some confusion in some cases - for example, if
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
+            * priority interrupts will be masked in Critical Sections as those
+            * are at the same preemption priority. This may appear confusing as
+            * 4 is higher (numerically lower) priority than
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
+            * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
+            * to 4, this confusion does not happen and the behaviour remains the same.
+            *
+            * The following assert ensures that the sub-priority bit in the
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
+            * confusion. */
+            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
+            ulMaxPRIGROUPValue = 0;
+        }
+        else
+        {
+            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
+        }
+
+        /* Shift the priority group value back to its position within the AIRCR
+        * register. */
+        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
+        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
+    }
+    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
+
+    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
+    * the highest priority. */
+    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
+    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
+    portNVIC_SHPR2_REG = 0;
+}
+/*-----------------------------------------------------------*/
+
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) )
 
     void vPortGrantAccessToKernelObject( TaskHandle_t xInternalTaskHandle,
@@ -2247,36 +2370,214 @@
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
-
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
-    {
-        uint32_t ulControl = 0x0;
-
-        /* Ensure that PACBTI is implemented. */
-        configASSERT( portID_ISAR5_REG != 0x0 );
-
-        /* Enable UsageFault exception. */
-        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
-
-        #if ( configENABLE_PAC == 1 )
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #else /* configNUMBER_OF_CORES > 1 */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #endif /* configNUMBER_OF_CORES */
         {
-            ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
-        }
-        #endif
+            uint32_t ulControl = 0x0;
 
-        #if ( configENABLE_BTI == 1 )
-        {
-            ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
-        }
-        #endif
+            /* Ensure that PACBTI is implemented. */
+            configASSERT( portID_ISAR5_REG != 0x0 );
 
-        if( xWriteControlRegister == pdTRUE )
-        {
-            __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
-        }
+            /* Enable UsageFault exception. */
+            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
 
-        return ulControl;
-    }
+            #if ( configENABLE_PAC == 1 )
+            {
+                ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
+            }
+            #endif
+
+            #if ( configENABLE_BTI == 1 )
+            {
+                ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
+            }
+            #endif
+
+            if( xWriteControlRegister == pdTRUE )
+            {
+                __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
+            }
+
+            return ulControl;
+        }
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 /*-----------------------------------------------------------*/
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /* Which core owns the lock? */
+    PRIVILEGED_DATA volatile uint32_t ulOwnedByCore[ portMAX_CORE_COUNT ];
+    /* Lock count a core owns. */
+    PRIVILEGED_DATA volatile uint32_t ulRecursionCountByLock[ eLockCount ];
+    /* Index 0 is used for ISR lock and Index 1 is used for task lock. */
+    PRIVILEGED_DATA volatile uint32_t ulGateWord[ eLockCount ];
+
+    __attribute__((weak)) void vInterruptCore( uint8_t ucCoreID )
+    {
+        /* Default weak stub - platform specific implementation may override. */
+        ( void ) ucCoreID;
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline void prvSpinUnlock( volatile uint32_t * ulLock )
+    {
+        /* Conservative unlock: preserve original barriers for broad HW/FVP. */
+        __asm volatile (
+            "dmb sy         \n"
+            "mov r1, #0     \n"
+            "str r1, [%0]   \n"
+            "sev            \n"
+            "dsb            \n"
+            "isb            \n"
+            :
+            : "r" ( ulLock )
+            : "memory", "r1"
+        );
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline uint32_t prvSpinTrylock( volatile uint32_t * ulLock )
+    {
+        /*
+         * Conservative ldrex/strex trylock:
+         * - Return 1 immediately if busy, clearing exclusive state (CLREX).
+         * - Retry strex only on spurious failure when observed free.
+         * - DMB on success to preserve expected acquire semantics.
+         */
+        uint32_t ulVal;
+        uint32_t ulStatus;
+
+        __asm volatile (
+            " ldrex %0, [%1]   \n"
+            : "=r" ( ulVal )
+            : "r" ( ulLock )
+            : "memory"
+        );
+
+        if( ulVal != 0U )
+        {
+            __asm volatile ("clrex" ::: "memory");
+            return 1U;
+        }
+
+        __asm volatile (
+            " strex %0, %2, [%1]   \n"
+            : "=&r" ( ulStatus )
+            : "r" ( ulLock ), "r" (1U)
+            : "memory"
+        );
+
+        if( ulStatus != 0U )
+        {
+            return 1U;
+        }
+        __asm volatile ( "dmb" ::: "memory" );
+        return 0U;
+    }
+
+
+/*-----------------------------------------------------------*/
+
+    /* Read 32b value shared between cores. */
+    static inline uint32_t prvGet32( volatile uint32_t * x )
+    {
+        __asm( "dsb" );
+        return *x;
+    }
+
+/*-----------------------------------------------------------*/
+
+    /* Write 32b value shared between cores. */
+    static inline void prvSet32( volatile uint32_t * x,
+                                 uint32_t value )
+    {
+        *x = value;
+        __asm( "dsb" );
+    }
+
+/*-----------------------------------------------------------*/
+
+    void vPortRecursiveLock( uint8_t ucCoreID,
+                             ePortRTOSLock eLockNum,
+                             BaseType_t uxAcquire )
+    {
+        /* Validate the core ID and lock number. */
+        configASSERT( ucCoreID < portMAX_CORE_COUNT );
+        configASSERT( eLockNum < eLockCount );
+
+        uint32_t ulLockBit = 1u << eLockNum;
+
+        /* Lock acquire */
+        if( uxAcquire )
+        {
+            /* Check if spinlock is available. */
+            /* If spinlock is not available check if the core owns the lock. */
+            /* If the core owns the lock wait increment the lock count by the core. */
+            /* If core does not own the lock wait for the spinlock. */
+            if( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+            {
+                /* Check if the core owns the spinlock. */
+                if( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit )
+                {
+                    configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != portUINT32_MAX );
+                    prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) + 1 ) );
+                    return;
+                }
+
+                /* Preload the gate word into the cache. */
+                uint32_t dummy = ulGateWord[ eLockNum ];
+                dummy++;
+
+                while( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+                {
+                    __asm volatile ( "wfe" );
+                }
+            }
+
+            /* Add barrier to ensure lock is taken before we proceed. */
+            __asm volatile( "dmb sy" ::: "memory" );
+
+            /* Assert the lock count is 0 when the spinlock is free and is acquired. */
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) == 0 );
+
+            /* Set lock count as 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], 1 );
+            /* Set ulOwnedByCore. */
+            prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) | ulLockBit ) );
+        }
+        /* Lock release. */
+        else
+        {
+            /* Assert the lock is not free already. */
+            configASSERT( ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit ) != 0 );
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != 0 );
+
+            /* Reduce ulRecursionCountByLock by 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) - 1 ) );
+
+            if( !prvGet32( &ulRecursionCountByLock[ eLockNum ] ) )
+            {
+                prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ~ulLockBit ) );
+                prvSpinUnlock( &ulGateWord[ eLockNum ] );
+                /* Add barrier to ensure lock status is reflected before we proceed. */
+                __asm volatile( "dmb sy" ::: "memory" );
+            }
+        }
+    }
+
+/*-----------------------------------------------------------*/
+
+    uint8_t ucPortGetCoreID( void )
+    {
+        return *(volatile uint8_t *)(configCORE_ID_REGISTER);
+    }
+
+/*-----------------------------------------------------------*/
+
+#endif /* if( configNUMBER_OF_CORES > 1 ) */
diff --git a/Source/portable/IAR/ARM_CM23_NTZ/non_secure/portasm.h b/Source/portable/IAR/ARM_CM23_NTZ/non_secure/portasm.h
index 53b4b6e..b4b545f 100644
--- a/Source/portable/IAR/ARM_CM23_NTZ/non_secure/portasm.h
+++ b/Source/portable/IAR/ARM_CM23_NTZ/non_secure/portasm.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM23_NTZ/non_secure/portasm.s b/Source/portable/IAR/ARM_CM23_NTZ/non_secure/portasm.s
index 200751b..03e8a71 100644
--- a/Source/portable/IAR/ARM_CM23_NTZ/non_secure/portasm.s
+++ b/Source/portable/IAR/ARM_CM23_NTZ/non_secure/portasm.s
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM23_NTZ/non_secure/portmacro.h b/Source/portable/IAR/ARM_CM23_NTZ/non_secure/portmacro.h
index 6cf50c5..4fb83e0 100644
--- a/Source/portable/IAR/ARM_CM23_NTZ/non_secure/portmacro.h
+++ b/Source/portable/IAR/ARM_CM23_NTZ/non_secure/portmacro.h
@@ -1,6 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * Copyright 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -52,6 +53,7 @@
 #define portHAS_ARMV8M_MAIN_EXTENSION    0
 #define portARMV8M_MINOR_VERSION         0
 #define portDONT_DISCARD                 __root
+#define portVALIDATED_FOR_SMP            0
 /*-----------------------------------------------------------*/
 
 /* ARMv8-M common port configurations. */
diff --git a/Source/portable/IAR/ARM_CM23_NTZ/non_secure/portmacrocommon.h b/Source/portable/IAR/ARM_CM23_NTZ/non_secure/portmacrocommon.h
index 2dfac6a..c34fdee 100644
--- a/Source/portable/IAR/ARM_CM23_NTZ/non_secure/portmacrocommon.h
+++ b/Source/portable/IAR/ARM_CM23_NTZ/non_secure/portmacrocommon.h
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -59,6 +58,19 @@
     #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h.  Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
 #endif /* configENABLE_TRUSTZONE */
 
+#if ( configNUMBER_OF_CORES > 1 )
+    #if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 )
+        #error "Multi-core SMP is currently only validated for Cortex-M33 non-TrustZone non-MPU port."
+    #endif /* if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 ) ) */
+
+    #ifndef configCORE_ID_REGISTER
+        #error "configCORE_ID_REGISTER must be defined to the address of the register used to identify the core executing the code."
+    #endif /* ifndef configCORE_ID_REGISTER */
+
+    #ifndef configWAKE_SECONDARY_CORES
+        #error "configWAKE_SECONDARY_CORES must be defined to a function that wakes the secondary cores."
+    #endif /* ifndef configWAKE_SECONDARY_CORES */
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -428,10 +440,26 @@
 /**
  * @brief Critical section management.
  */
+
+#define portSET_INTERRUPT_MASK()                  ulSetInterruptMask()
+#define portCLEAR_INTERRUPT_MASK( x )             vClearInterruptMask( x )
 #define portSET_INTERRUPT_MASK_FROM_ISR()         ulSetInterruptMask()
 #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x )    vClearInterruptMask( x )
-#define portENTER_CRITICAL()                      vPortEnterCritical()
-#define portEXIT_CRITICAL()                       vPortExitCritical()
+
+#if ( configNUMBER_OF_CORES == 1 )
+    #define portENTER_CRITICAL()                      vPortEnterCritical()
+    #define portEXIT_CRITICAL()                       vPortExitCritical()
+#else /* ( configNUMBER_OF_CORES == 1 ) */
+    extern void vTaskEnterCritical( void );
+    extern void vTaskExitCritical( void );
+    extern UBaseType_t vTaskEnterCriticalFromISR( void );
+    extern void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus );
+
+    #define portENTER_CRITICAL()                      vTaskEnterCritical()
+    #define portEXIT_CRITICAL()                       vTaskExitCritical()
+    #define portENTER_CRITICAL_FROM_ISR()             vTaskEnterCriticalFromISR()
+    #define portEXIT_CRITICAL_FROM_ISR( x )           vTaskExitCriticalFromISR( x )
+#endif /* if ( configNUMBER_OF_CORES != 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -526,7 +554,7 @@
 /* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION
  * based on whether or not Mainline extension is implemented. */
 #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
-    #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 )
+    #if ( ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) && ( configNUMBER_OF_CORES == 1 ) )
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    1
     #else
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    0
@@ -573,6 +601,44 @@
 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
 /*-----------------------------------------------------------*/
 
+
+#if ( configNUMBER_OF_CORES > 1 )
+    typedef enum
+    {
+        eIsrLock = 0,
+        eTaskLock,
+        eLockCount
+    } ePortRTOSLock;
+
+    extern volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ];
+    extern void vPortRecursiveLock( uint8_t ucCoreID,
+                                    ePortRTOSLock eLockNum,
+                                    BaseType_t uxAcquire );
+    extern uint8_t ucPortGetCoreID( void );
+    extern void vInterruptCore( uint8_t ucCoreID );
+
+    #define portGET_CORE_ID()                                  ucPortGetCoreID()
+
+    #define portGET_CRITICAL_NESTING_COUNT( xCoreID )          ( ulCriticalNestings[ ( uint8_t ) xCoreID ] )
+    #define portSET_CRITICAL_NESTING_COUNT( xCoreID, x )       ( ulCriticalNestings[ ( uint8_t ) xCoreID ] = ( x ) )
+    #define portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]++ )
+    #define portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]-- )
+
+    #define portMAX_CORE_COUNT                                 ( configNUMBER_OF_CORES )
+
+    #define portYIELD_CORE( xCoreID )                          vInterruptCore( xCoreID )
+
+    #define portRELEASE_ISR_LOCK( xCoreID )                    vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdFALSE )
+    #define portGET_ISR_LOCK( xCoreID )                        vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdTRUE )
+
+    #define portRELEASE_TASK_LOCK( xCoreID )                   vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdFALSE )
+    #define portGET_TASK_LOCK( xCoreID )                       vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdTRUE )
+
+    #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* ( configENABLE_PAC == 1 || configENABLE_BTI == 1 ) */
+#endif
+
 /* *INDENT-OFF* */
 #ifdef __cplusplus
     }
diff --git a/Source/portable/IAR/ARM_CM3/port.c b/Source/portable/IAR/ARM_CM3/port.c
index e706a6d..efd4e53 100644
--- a/Source/portable/IAR/ARM_CM3/port.c
+++ b/Source/portable/IAR/ARM_CM3/port.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM3/portasm.s b/Source/portable/IAR/ARM_CM3/portasm.s
index 0344b9c..948da86 100644
--- a/Source/portable/IAR/ARM_CM3/portasm.s
+++ b/Source/portable/IAR/ARM_CM3/portasm.s
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM3/portmacro.h b/Source/portable/IAR/ARM_CM3/portmacro.h
index 26b976a..c4a076e 100644
--- a/Source/portable/IAR/ARM_CM3/portmacro.h
+++ b/Source/portable/IAR/ARM_CM3/portmacro.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM33/non_secure/mpu_wrappers_v2_asm.S b/Source/portable/IAR/ARM_CM33/non_secure/mpu_wrappers_v2_asm.S
index 68192e4..c8df7ec 100644
--- a/Source/portable/IAR/ARM_CM33/non_secure/mpu_wrappers_v2_asm.S
+++ b/Source/portable/IAR/ARM_CM33/non_secure/mpu_wrappers_v2_asm.S
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM33/non_secure/port.c b/Source/portable/IAR/ARM_CM33/non_secure/port.c
index f16a343..007150c 100644
--- a/Source/portable/IAR/ARM_CM33/non_secure/port.c
+++ b/Source/portable/IAR/ARM_CM33/non_secure/port.c
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024-2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -145,13 +144,13 @@
 /**
  * @brief Constants required to manipulate the FPU.
  */
-#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 )              /* Coprocessor Access Control Register. */
+#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */
 #define portCPACR_CP10_VALUE    ( 3UL )
 #define portCPACR_CP11_VALUE    portCPACR_CP10_VALUE
 #define portCPACR_CP10_POS      ( 20UL )
 #define portCPACR_CP11_POS      ( 22UL )
 
-#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 )              /* Floating Point Context Control Register. */
+#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
 #define portFPCCR_ASPEN_POS     ( 31UL )
 #define portFPCCR_ASPEN_MASK    ( 1UL << portFPCCR_ASPEN_POS )
 #define portFPCCR_LSPEN_POS     ( 30UL )
@@ -188,8 +187,8 @@
 #define portMPU_MAIR0_REG                       ( *( ( volatile uint32_t * ) 0xe000edc0 ) )
 #define portMPU_MAIR1_REG                       ( *( ( volatile uint32_t * ) 0xe000edc4 ) )
 
-#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
-#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
+#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
+#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
 
 #define portMPU_RBAR_ACCESS_PERMISSIONS_MASK    ( 3UL << 1UL )
 
@@ -230,8 +229,8 @@
 
 #if ( portARMV8M_MINOR_VERSION >= 1 )
 
-/* Enable Privileged eXecute Never MPU attribute for the selected memory
- * region. */
+    /* Enable Privileged eXecute Never MPU attribute for the selected memory
+     * region. */
     #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER    ( 1UL << 4UL )
 #endif /* portARMV8M_MINOR_VERSION >= 1 */
 
@@ -241,9 +240,6 @@
 /* Enable MPU. */
 #define portMPU_ENABLE_BIT                    ( 1UL << 0UL )
 
-/* Expected value of the portMPU_TYPE register. */
-#define portEXPECTED_MPU_TYPE_VALUE           ( configTOTAL_MPU_REGIONS << 8UL )
-
 /* Extract first address of the MPU region as encoded in the
  * RBAR (Region Base Address Register) value. */
 #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@@ -291,37 +287,37 @@
 
 #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         FD
- * 1111 1111  1111 1111  1111 1111  1111 1101
- *
- * Bit[6] - 1 --> The exception was taken from the Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 1 --> The exception was taken to the Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         FD
+     * 1111 1111  1111 1111  1111 1111  1111 1101
+     *
+     * Bit[6] - 1 --> The exception was taken from the Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 1 --> The exception was taken to the Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xfffffffd )
 #else
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         BC
- * 1111 1111  1111 1111  1111 1111  1011 1100
- *
- * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         BC
+     * 1111 1111  1111 1111  1111 1111  1011 1100
+     *
+     * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xffffffbc )
 #endif /* configRUN_FREERTOS_SECURE_ONLY */
 
@@ -401,50 +397,54 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Extract MPU region's access permissions from the Region Base Address
- * Register (RBAR) value.
- *
- * @param ulRBARValue RBAR value for the MPU region.
- *
- * @return uint32_t Access permissions.
- */
+    /**
+     * @brief Extract MPU region's access permissions from the Region Base Address
+     * Register (RBAR) value.
+     *
+     * @param ulRBARValue RBAR value for the MPU region.
+     *
+     * @return uint32_t Access permissions.
+     */
     static uint32_t prvGetRegionAccessPermissions( uint32_t ulRBARValue ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU == 1 && configUSE_MPU_WRAPPERS_V1 == 0 */
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Setup the Memory Protection Unit (MPU).
- */
+    /**
+     * @brief Setup the Memory Protection Unit (MPU).
+     */
     static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU */
 
 #if ( configENABLE_FPU == 1 )
 
-/**
- * @brief Setup the Floating Point Unit (FPU).
- */
+    /**
+     * @brief Setup the Floating Point Unit (FPU).
+     */
     static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_FPU */
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
 
-/**
- * @brief Configures PACBTI features.
- *
- * This function configures the Pointer Authentication, and Branch Target
- * Identification security features as per the user configuration. It returns
- * the value of the special purpose CONTROL register accordingly, and optionally
- * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
- * architecture based) target supports PACBTI security feature.
- *
- * @param xWriteControlRegister Used to control whether the special purpose
- * CONTROL register should be updated or not.
- *
- * @return CONTROL register value according to the configured PACBTI option.
- */
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    /**
+     * @brief Configures PACBTI features.
+     *
+     * This function configures the Pointer Authentication, and Branch Target
+     * Identification security features as per the user configuration. It returns
+     * the value of the special purpose CONTROL register accordingly, and optionally
+     * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
+     * architecture based) target supports PACBTI security feature.
+     *
+     * @param xWriteControlRegister Used to control whether the special purpose
+     * CONTROL register should be updated or not.
+     *
+     * @return CONTROL register value according to the configured PACBTI option.
+     */
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -491,14 +491,14 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the system call stack so that upon returning from
- * SVC, the system call stack is used.
- *
- * @param pulTaskStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- * @param ucSystemCallNumber The system call number of the system call.
- */
+    /**
+     * @brief Sets up the system call stack so that upon returning from
+     * SVC, the system call stack is used.
+     *
+     * @param pulTaskStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     * @param ucSystemCallNumber The system call number of the system call.
+     */
     void vSystemCallEnter( uint32_t * pulTaskStack,
                            uint32_t ulLR,
                            uint8_t ucSystemCallNumber ) PRIVILEGED_FUNCTION;
@@ -507,22 +507,22 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Raise SVC for exiting from a system call.
- */
+    /**
+     * @brief Raise SVC for exiting from a system call.
+     */
     void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the task stack so that upon returning from
- * SVC, the task stack is used again.
- *
- * @param pulSystemCallStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- */
+    /**
+     * @brief Sets up the task stack so that upon returning from
+     * SVC, the task stack is used again.
+     *
+     * @param pulSystemCallStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     */
     void vSystemCallExit( uint32_t * pulSystemCallStack,
                           uint32_t ulLR ) PRIVILEGED_FUNCTION;
 
@@ -530,21 +530,38 @@
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Checks whether or not the calling task is privileged.
- *
- * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
- */
+    /**
+     * @brief Checks whether or not the calling task is privileged.
+     *
+     * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
+     */
     BaseType_t xPortIsTaskPrivileged( void ) PRIVILEGED_FUNCTION;
 
 #endif /* configENABLE_MPU == 1 */
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /**
+     * @brief Platform/Application-defined function that wakes up the secondary cores.
+     *
+     * @return pdTRUE if the secondary cores were successfully woken up.
+     *         pdFALSE otherwise.
+     */
+    extern BaseType_t configWAKE_SECONDARY_CORES( void );
+
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
+
+/**
+ * @brief Configures interrupt priorities.
+ */
+void vPortConfigureInterruptPriorities( void ) PRIVILEGED_FUNCTION;
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief This variable is set to pdTRUE when the scheduler is started.
- */
+    /**
+     * @brief This variable is set to pdTRUE when the scheduler is started.
+     */
     PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
@@ -553,14 +570,22 @@
  * @brief Each task maintains its own interrupt status in the critical nesting
  * variable.
  */
-PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
+#if ( configNUMBER_OF_CORES == 1 )
+    PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0UL;
+#else /* #if ( configNUMBER_OF_CORES == 1 ) */
+    PRIVILEGED_DATA volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ] = { 0 };
+    /* Flags to check if the secondary cores are ready. */
+    PRIVILEGED_DATA volatile uint8_t ucSecondaryCoresReadyFlags[ configNUMBER_OF_CORES - 1 ] = { 0 };
+    /* Flag to indicate that the primary core has completed its initialisation. */
+    PRIVILEGED_DATA volatile uint8_t ucPrimaryCoreInitDoneFlag = 0;
+ #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #if ( configENABLE_TRUSTZONE == 1 )
 
-/**
- * @brief Saved as part of the task context to indicate which context the
- * task is using on the secure side.
- */
+    /**
+     * @brief Saved as part of the task context to indicate which context the
+     * task is using on the secure side.
+     */
     PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
 #endif /* configENABLE_TRUSTZONE */
 
@@ -579,21 +604,21 @@
 
 #if ( configUSE_TICKLESS_IDLE == 1 )
 
-/**
- * @brief The number of SysTick increments that make up one tick period.
- */
+    /**
+     * @brief The number of SysTick increments that make up one tick period.
+     */
     PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
 
-/**
- * @brief The maximum number of tick periods that can be suppressed is
- * limited by the 24 bit resolution of the SysTick timer.
- */
+    /**
+     * @brief The maximum number of tick periods that can be suppressed is
+     * limited by the 24 bit resolution of the SysTick timer.
+     */
     PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
 
-/**
- * @brief Compensate for the CPU cycles that pass while the SysTick is
- * stopped (low power functionality only).
- */
+    /**
+     * @brief Compensate for the CPU cycles that pass while the SysTick is
+     * stopped (low power functionality only).
+     */
     PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0;
 #endif /* configUSE_TICKLESS_IDLE */
 /*-----------------------------------------------------------*/
@@ -856,7 +881,11 @@
      * should instead call vTaskDelete( NULL ). Artificially force an assert()
      * to be triggered if configASSERT() is defined, then stop here so
      * application writers can catch the error. */
-    configASSERT( ulCriticalNesting == ~0UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == ~0UL );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == ~0UL );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
     portDISABLE_INTERRUPTS();
 
     while( ulDummy == 0 )
@@ -925,64 +954,57 @@
         /* The only permitted number of regions are 8 or 16. */
         configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 16 ) );
 
-        /* Ensure that the configTOTAL_MPU_REGIONS is configured correctly. */
-        configASSERT( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE );
+        /* MAIR0 - Index 0. */
+        portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
+        /* MAIR0 - Index 1. */
+        portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
 
-        /* Check that the MPU is present. */
-        if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
-        {
-            /* MAIR0 - Index 0. */
-            portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
-            /* MAIR0 - Index 1. */
-            portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
+        /* Setup privileged flash as Read Only so that privileged tasks can
+         * read it but not modify. */
+        portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup privileged flash as Read Only so that privileged tasks can
-             * read it but not modify. */
-            portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged flash as Read Only by both privileged and
+         * unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged flash as Read Only by both privileged and
-             * unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged syscalls flash as Read Only by both privileged
+         * and unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged syscalls flash as Read Only by both privileged
-             * and unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup RAM containing kernel data for privileged access only. */
+        portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
+                           ( portMPU_REGION_EXECUTE_NEVER );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup RAM containing kernel data for privileged access only. */
-            portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
-                               ( portMPU_REGION_EXECUTE_NEVER );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Enable mem fault. */
+        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
 
-            /* Enable mem fault. */
-            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
-
-            /* Enable MPU with privileged background access i.e. unmapped
-             * regions have privileged access. */
-            portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
-        }
+        /* Enable MPU with privileged background access i.e. unmapped
+         * regions have privileged access. */
+        portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
     }
 
 #endif /* configENABLE_MPU */
@@ -1027,28 +1049,29 @@
 }
 /*-----------------------------------------------------------*/
 
-void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    portDISABLE_INTERRUPTS();
-    ulCriticalNesting++;
-
-    /* Barriers are normally not required but do ensure the code is
-     * completely within the specified behaviour for the architecture. */
-    __asm volatile ( "dsb" ::: "memory" );
-    __asm volatile ( "isb" );
-}
-/*-----------------------------------------------------------*/
-
-void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    configASSERT( ulCriticalNesting );
-    ulCriticalNesting--;
-
-    if( ulCriticalNesting == 0 )
+#if ( configNUMBER_OF_CORES == 1 )
+    void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
     {
-        portENABLE_INTERRUPTS();
+        portDISABLE_INTERRUPTS();
+        ulCriticalNesting++;
+        /* Barriers are normally not required but do ensure the code is
+        * completely within the specified behaviour for the architecture. */
+        __asm volatile ( "dsb" ::: "memory" );
+        __asm volatile ( "isb" );
     }
-}
+    /*-----------------------------------------------------------*/
+
+    void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
+    {
+        configASSERT( ulCriticalNesting );
+        ulCriticalNesting--;
+
+        if( ulCriticalNesting == 0 )
+        {
+            portENABLE_INTERRUPTS();
+        }
+    }
+#endif /* configNUMBER_OF_CORES == 1 */
 /*-----------------------------------------------------------*/
 
 void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
@@ -1056,6 +1079,10 @@
     uint32_t ulPreviousMask;
 
     ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
+    #if ( configNUMBER_OF_CORES > 1 )
+        UBaseType_t uxSavedInterruptStatus = portENTER_CRITICAL_FROM_ISR();
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     traceISR_ENTER();
     {
         /* Increment the RTOS tick. */
@@ -1070,6 +1097,10 @@
             traceISR_EXIT();
         }
     }
+    #if ( configNUMBER_OF_CORES > 1 )
+        portEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
 }
 /*-----------------------------------------------------------*/
@@ -1078,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1090,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1108,38 +1151,42 @@
 
     switch( ucSVCNumber )
     {
-        #if ( configENABLE_TRUSTZONE == 1 )
-            case portSVC_ALLOCATE_SECURE_CONTEXT:
+    #if ( configENABLE_TRUSTZONE == 1 )
+        case portSVC_ALLOCATE_SECURE_CONTEXT:
 
-                /* R0 contains the stack size passed as parameter to the
-                 * vPortAllocateSecureContext function. */
-                ulR0 = pulCallerStackAddress[ 0 ];
+            /* R0 contains the stack size passed as parameter to the
+             * vPortAllocateSecureContext function. */
+            ulR0 = pulCallerStackAddress[ 0 ];
 
-                #if ( configENABLE_MPU == 1 )
-                {
-                    /* Read the CONTROL register value. */
-                    __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
+            #if ( configENABLE_MPU == 1 )
+            {
+                /* Read the CONTROL register value. */
+                __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
 
-                    /* The task that raised the SVC is privileged if Bit[0]
-                     * in the CONTROL register is 0. */
-                    ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
+                /* The task that raised the SVC is privileged if Bit[0]
+                 * in the CONTROL register is 0. */
+                ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
 
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
-                }
-                #else /* if ( configENABLE_MPU == 1 ) */
-                {
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
-                }
-                #endif /* configENABLE_MPU */
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
+            }
+            #else /* if ( configENABLE_MPU == 1 ) */
+            {
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
+            }
+            #endif /* configENABLE_MPU */
 
-                configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
-                SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
-                break;
+            configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
+            SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
+            break;
 
-            case portSVC_FREE_SECURE_CONTEXT:
-
+        case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
                 /* R0 contains TCB being freed and R1 contains the secure
                  * context handle to be freed. */
                 ulR0 = pulCallerStackAddress[ 0 ];
@@ -1147,51 +1194,62 @@
 
                 /* Free the secure context. */
                 SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
-                break;
-        #endif /* configENABLE_TRUSTZONE */
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
+            break;
+    #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
-            #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
-                case portSVC_RAISE_PRIVILEGE:
+    #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
+        case portSVC_RAISE_PRIVILEGE:
 
-                    /* Only raise the privilege, if the svc was raised from any of
-                     * the system calls. */
-                    if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
-                        ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
-                    {
-                        vRaisePrivilege();
-                    }
-                    break;
-            #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
+            /* Only raise the privilege, if the svc was raised from any of
+             * the system calls. */
+            if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
+                ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
+            {
+                vRaisePrivilege();
+            }
+            break;
+    #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
-            #if ( configENABLE_MPU == 1 )
-                case portSVC_YIELD:
-                    vPortYield();
-                    break;
-            #endif /* configENABLE_MPU == 1 */
+    #if ( configENABLE_MPU == 1 )
+        case portSVC_YIELD:
+            vPortYield();
+            break;
+    #endif /* configENABLE_MPU == 1 */
 
         default:
             /* Incorrect SVC call. */
@@ -1210,7 +1268,7 @@
         extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulSystemCallStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1246,12 +1304,16 @@
         {
             pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1261,20 +1323,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the system call stack for the stack frame. */
-            pulSystemCallStack = pulSystemCallStack - ulStackFrameSize;
+            pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulSystemCallStack[ i ] = pulTaskStack[ i ];
             }
@@ -1310,7 +1372,7 @@
 
             /* Remember the location where we should copy the stack frame when we exit from
              * the system call. */
-            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
+            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
 
             /* Record if the hardware used padding to force the stack pointer
              * to be double word aligned. */
@@ -1360,7 +1422,7 @@
         extern TaskHandle_t pxCurrentTCB;
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulTaskStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1392,12 +1454,16 @@
         {
             pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1407,20 +1473,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the task stack for the stack frame. */
-            pulTaskStack = pulTaskStack - ulStackFrameSize;
+            pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulTaskStack[ i ] = pulSystemCallStack[ i ];
             }
@@ -1518,21 +1584,21 @@
         xMPUSettings->ulContext[ ulIndex ] = 0x11111111; /* r11. */
         ulIndex++;
 
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters;            /* r0. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters; /* r0. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x01010101;                           /* r1. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x01010101; /* r1. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x02020202;                           /* r2. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x02020202; /* r2. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x03030303;                           /* r3. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x03030303; /* r3. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x12121212;                           /* r12. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x12121212; /* r12. */
         ulIndex++;
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) portTASK_RETURN_ADDRESS; /* LR. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode;                  /* PC. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode; /* PC. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR;                     /* xPSR. */
+        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR; /* xPSR. */
         ulIndex++;
 
         #if ( configENABLE_TRUSTZONE == 1 )
@@ -1543,14 +1609,18 @@
         #endif /* configENABLE_TRUSTZONE */
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) ( pxTopOfStack - 8 ); /* PSP with the hardware saved stack. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack;         /* PSPLIM. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack; /* PSPLIM. */
         ulIndex++;
 
         #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
         {
             /* Check PACBTI security feature configuration before pushing the
              * CONTROL register's value on task's TCB. */
-            ulControl = prvConfigurePACBTI( pdFALSE );
+            #if ( configNUMBER_OF_CORES == 1 )
+                ulControl = prvConfigurePACBTI( pdFALSE );
+            #else /* configNUMBER_OF_CORES > 1 */
+                ulControl = vConfigurePACBTI( pdFALSE );
+            #endif /* configNUMBER_OF_CORES */
         }
         #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1615,15 +1685,15 @@
          * interrupt. */
         #if ( portPRELOAD_REGISTERS == 0 )
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
-            pxTopOfStack -= 5;                                       /* R12, R3, R2 and R1. */
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
-            pxTopOfStack -= 9;                                       /* R11..R4, EXC_RETURN. */
+            pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
+            pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */
             *pxTopOfStack = portINITIAL_EXC_RETURN;
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
@@ -1637,42 +1707,42 @@
         }
         #else /* portPRELOAD_REGISTERS */
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x12121212UL;            /* R12. */
+            *pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x03030303UL;            /* R3. */
+            *pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x02020202UL;            /* R2. */
+            *pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x01010101UL;            /* R1. */
+            *pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x11111111UL;            /* R11. */
+            *pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x10101010UL;            /* R10. */
+            *pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x09090909UL;            /* R09. */
+            *pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x08080808UL;            /* R08. */
+            *pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x07070707UL;            /* R07. */
+            *pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x06060606UL;            /* R06. */
+            *pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x05050505UL;            /* R05. */
+            *pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x04040404UL;            /* R04. */
+            *pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04. */
             pxTopOfStack--;
-            *pxTopOfStack = portINITIAL_EXC_RETURN;                  /* EXC_RETURN. */
+            *pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxEndOfStack;            /* Slot used to hold this task's PSPLIM value. */
+            *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
 
             #if ( configENABLE_TRUSTZONE == 1 )
             {
@@ -1739,91 +1809,17 @@
     }
     #endif /* configCHECK_HANDLER_INSTALLATION */
 
-    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
-    {
-        volatile uint32_t ulImplementedPrioBits = 0;
-        volatile uint8_t ucMaxPriorityValue;
-
-        /* Determine the maximum priority from which ISR safe FreeRTOS API
-         * functions can be called. ISR safe functions are those that end in
-         * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
-         * ensure interrupt entry is as fast and simple as possible.
-         *
-         * First, determine the number of priority bits available. Write to all
-         * possible bits in the priority setting for SVCall. */
-        portNVIC_SHPR2_REG = 0xFF000000;
-
-        /* Read the value back to see how many bits stuck. */
-        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
-
-        /* Use the same mask on the maximum system call priority. */
-        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
-
-        /* Check that the maximum system call priority is nonzero after
-         * accounting for the number of priority bits supported by the
-         * hardware. A priority of 0 is invalid because setting the BASEPRI
-         * register to 0 unmasks all interrupts, and interrupts with priority 0
-         * cannot be masked using BASEPRI.
-         * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
-        configASSERT( ucMaxSysCallPriority );
-
-        /* Check that the bits not implemented in hardware are zero in
-         * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
-        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
-
-        /* Calculate the maximum acceptable priority group value for the number
-         * of bits read back. */
-        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
-        {
-            ulImplementedPrioBits++;
-            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
-        }
-
-        if( ulImplementedPrioBits == 8 )
-        {
-            /* When the hardware implements 8 priority bits, there is no way for
-             * the software to configure PRIGROUP to not have sub-priorities. As
-             * a result, the least significant bit is always used for sub-priority
-             * and there are 128 preemption priorities and 2 sub-priorities.
-             *
-             * This may cause some confusion in some cases - for example, if
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
-             * priority interrupts will be masked in Critical Sections as those
-             * are at the same preemption priority. This may appear confusing as
-             * 4 is higher (numerically lower) priority than
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
-             * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
-             * to 4, this confusion does not happen and the behaviour remains the same.
-             *
-             * The following assert ensures that the sub-priority bit in the
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
-             * confusion. */
-            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
-            ulMaxPRIGROUPValue = 0;
-        }
-        else
-        {
-            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
-        }
-
-        /* Shift the priority group value back to its position within the AIRCR
-         * register. */
-        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
-        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
-    }
-    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
-
-    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
-     * the highest priority. */
-    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
-    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
-    portNVIC_SHPR2_REG = 0;
+    vPortConfigureInterruptPriorities();
 
     #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
     {
         /* Set the CONTROL register value based on PACBTI security feature
          * configuration before starting the first task. */
-        ( void ) prvConfigurePACBTI( pdTRUE );
+        #if ( configNUMBER_OF_CORES == 1 )
+            ( void ) prvConfigurePACBTI( pdTRUE );
+        #else /* configNUMBER_OF_CORES > 1 */
+            ( void ) vConfigurePACBTI( pdTRUE );
+        #endif /* configNUMBER_OF_CORES */
     }
     #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1834,12 +1830,47 @@
     }
     #endif /* configENABLE_MPU */
 
-    /* Start the timer that generates the tick ISR. Interrupts are disabled
-     * here already. */
-    vPortSetupTimerInterrupt();
+    #if ( configNUMBER_OF_CORES > 1 )
+        /* Start the timer that generates the tick ISR. Interrupts are disabled
+         * here already. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count for all cores. */
+        for ( uint8_t ucCoreID = 0; ucCoreID < configNUMBER_OF_CORES; ucCoreID++ )
+        {
+            ulCriticalNestings[ ucCoreID ] = 0;
+        }
+        /* Signal that primary core has done all the necessary initialisations. */
+        ucPrimaryCoreInitDoneFlag = 1;
+        /* Wake up secondary cores */
+        BaseType_t xWakeResult = configWAKE_SECONDARY_CORES();
+        configASSERT( xWakeResult == pdTRUE );
 
-    /* Initialize the critical nesting count ready for the first task. */
-    ulCriticalNesting = 0;
+        /* Hold the primary core here until all the secondary cores are ready, this would be achieved only when
+         * all elements of ucSecondaryCoresReadyFlags are set.
+         */
+        while( 1 )
+        {
+            BaseType_t xAllCoresReady = pdTRUE;
+            for( uint8_t ucCoreID = 0; ucCoreID < ( configNUMBER_OF_CORES - 1 ); ucCoreID++ )
+            {
+                if( ucSecondaryCoresReadyFlags[ ucCoreID ] != pdTRUE )
+                {
+                    xAllCoresReady = pdFALSE;
+                    break;
+                }
+                }
+
+            if ( xAllCoresReady == pdTRUE )
+            {
+                break;
+            }
+        }
+    #else /* if ( configNUMBER_OF_CORES > 1 ) */
+        /* Start the timer that generates the tick ISR. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count ready for the first task. */
+        ulCriticalNesting = 0;
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
     {
@@ -1856,7 +1887,11 @@
      * functionality by defining configTASK_RETURN_ADDRESS. Call
      * vTaskSwitchContext() so link time optimization does not remove the
      * symbol. */
-    vTaskSwitchContext();
+    #if ( configNUMBER_OF_CORES > 1 )
+        vTaskSwitchContext( portGET_CORE_ID() );
+    #else
+        vTaskSwitchContext();
+    #endif
     prvTaskExitError();
 
     /* Should not get here. */
@@ -1868,7 +1903,11 @@
 {
     /* Not implemented in ports where there is nothing to return to.
      * Artificially force an assert. */
-    configASSERT( ulCriticalNesting == 1000UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == 1000UL );
+    #else /* if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == 1000UL );
+    #endif /* if ( configNUMBER_OF_CORES == 1 ) */
 }
 /*-----------------------------------------------------------*/
 
@@ -2151,6 +2190,90 @@
 #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
 /*-----------------------------------------------------------*/
 
+void vPortConfigureInterruptPriorities( void ) /* PRIVILEGED_FUNCTION */
+{
+    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
+    {
+        volatile uint32_t ulImplementedPrioBits = 0;
+        volatile uint8_t ucMaxPriorityValue;
+
+        /* Determine the maximum priority from which ISR safe FreeRTOS API
+        * functions can be called. ISR safe functions are those that end in
+        * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
+        * ensure interrupt entry is as fast and simple as possible.
+        *
+        * First, determine the number of priority bits available. Write to all
+        * possible bits in the priority setting for SVCall. */
+        portNVIC_SHPR2_REG = 0xFF000000;
+
+        /* Read the value back to see how many bits stuck. */
+        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
+
+        /* Use the same mask on the maximum system call priority. */
+        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
+
+        /* Check that the maximum system call priority is nonzero after
+        * accounting for the number of priority bits supported by the
+        * hardware. A priority of 0 is invalid because setting the BASEPRI
+        * register to 0 unmasks all interrupts, and interrupts with priority 0
+        * cannot be masked using BASEPRI.
+        * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+        configASSERT( ucMaxSysCallPriority );
+
+        /* Check that the bits not implemented in hardware are zero in
+        * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
+        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
+
+        /* Calculate the maximum acceptable priority group value for the number
+        * of bits read back. */
+        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
+        {
+            ulImplementedPrioBits++;
+            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
+        }
+
+        if( ulImplementedPrioBits == 8 )
+        {
+            /* When the hardware implements 8 priority bits, there is no way for
+            * the software to configure PRIGROUP to not have sub-priorities. As
+            * a result, the least significant bit is always used for sub-priority
+            * and there are 128 preemption priorities and 2 sub-priorities.
+            *
+            * This may cause some confusion in some cases - for example, if
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
+            * priority interrupts will be masked in Critical Sections as those
+            * are at the same preemption priority. This may appear confusing as
+            * 4 is higher (numerically lower) priority than
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
+            * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
+            * to 4, this confusion does not happen and the behaviour remains the same.
+            *
+            * The following assert ensures that the sub-priority bit in the
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
+            * confusion. */
+            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
+            ulMaxPRIGROUPValue = 0;
+        }
+        else
+        {
+            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
+        }
+
+        /* Shift the priority group value back to its position within the AIRCR
+        * register. */
+        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
+        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
+    }
+    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
+
+    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
+    * the highest priority. */
+    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
+    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
+    portNVIC_SHPR2_REG = 0;
+}
+/*-----------------------------------------------------------*/
+
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) )
 
     void vPortGrantAccessToKernelObject( TaskHandle_t xInternalTaskHandle,
@@ -2247,36 +2370,214 @@
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
-
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
-    {
-        uint32_t ulControl = 0x0;
-
-        /* Ensure that PACBTI is implemented. */
-        configASSERT( portID_ISAR5_REG != 0x0 );
-
-        /* Enable UsageFault exception. */
-        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
-
-        #if ( configENABLE_PAC == 1 )
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #else /* configNUMBER_OF_CORES > 1 */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #endif /* configNUMBER_OF_CORES */
         {
-            ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
-        }
-        #endif
+            uint32_t ulControl = 0x0;
 
-        #if ( configENABLE_BTI == 1 )
-        {
-            ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
-        }
-        #endif
+            /* Ensure that PACBTI is implemented. */
+            configASSERT( portID_ISAR5_REG != 0x0 );
 
-        if( xWriteControlRegister == pdTRUE )
-        {
-            __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
-        }
+            /* Enable UsageFault exception. */
+            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
 
-        return ulControl;
-    }
+            #if ( configENABLE_PAC == 1 )
+            {
+                ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
+            }
+            #endif
+
+            #if ( configENABLE_BTI == 1 )
+            {
+                ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
+            }
+            #endif
+
+            if( xWriteControlRegister == pdTRUE )
+            {
+                __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
+            }
+
+            return ulControl;
+        }
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 /*-----------------------------------------------------------*/
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /* Which core owns the lock? */
+    PRIVILEGED_DATA volatile uint32_t ulOwnedByCore[ portMAX_CORE_COUNT ];
+    /* Lock count a core owns. */
+    PRIVILEGED_DATA volatile uint32_t ulRecursionCountByLock[ eLockCount ];
+    /* Index 0 is used for ISR lock and Index 1 is used for task lock. */
+    PRIVILEGED_DATA volatile uint32_t ulGateWord[ eLockCount ];
+
+    __attribute__((weak)) void vInterruptCore( uint8_t ucCoreID )
+    {
+        /* Default weak stub - platform specific implementation may override. */
+        ( void ) ucCoreID;
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline void prvSpinUnlock( volatile uint32_t * ulLock )
+    {
+        /* Conservative unlock: preserve original barriers for broad HW/FVP. */
+        __asm volatile (
+            "dmb sy         \n"
+            "mov r1, #0     \n"
+            "str r1, [%0]   \n"
+            "sev            \n"
+            "dsb            \n"
+            "isb            \n"
+            :
+            : "r" ( ulLock )
+            : "memory", "r1"
+        );
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline uint32_t prvSpinTrylock( volatile uint32_t * ulLock )
+    {
+        /*
+         * Conservative ldrex/strex trylock:
+         * - Return 1 immediately if busy, clearing exclusive state (CLREX).
+         * - Retry strex only on spurious failure when observed free.
+         * - DMB on success to preserve expected acquire semantics.
+         */
+        uint32_t ulVal;
+        uint32_t ulStatus;
+
+        __asm volatile (
+            " ldrex %0, [%1]   \n"
+            : "=r" ( ulVal )
+            : "r" ( ulLock )
+            : "memory"
+        );
+
+        if( ulVal != 0U )
+        {
+            __asm volatile ("clrex" ::: "memory");
+            return 1U;
+        }
+
+        __asm volatile (
+            " strex %0, %2, [%1]   \n"
+            : "=&r" ( ulStatus )
+            : "r" ( ulLock ), "r" (1U)
+            : "memory"
+        );
+
+        if( ulStatus != 0U )
+        {
+            return 1U;
+        }
+        __asm volatile ( "dmb" ::: "memory" );
+        return 0U;
+    }
+
+
+/*-----------------------------------------------------------*/
+
+    /* Read 32b value shared between cores. */
+    static inline uint32_t prvGet32( volatile uint32_t * x )
+    {
+        __asm( "dsb" );
+        return *x;
+    }
+
+/*-----------------------------------------------------------*/
+
+    /* Write 32b value shared between cores. */
+    static inline void prvSet32( volatile uint32_t * x,
+                                 uint32_t value )
+    {
+        *x = value;
+        __asm( "dsb" );
+    }
+
+/*-----------------------------------------------------------*/
+
+    void vPortRecursiveLock( uint8_t ucCoreID,
+                             ePortRTOSLock eLockNum,
+                             BaseType_t uxAcquire )
+    {
+        /* Validate the core ID and lock number. */
+        configASSERT( ucCoreID < portMAX_CORE_COUNT );
+        configASSERT( eLockNum < eLockCount );
+
+        uint32_t ulLockBit = 1u << eLockNum;
+
+        /* Lock acquire */
+        if( uxAcquire )
+        {
+            /* Check if spinlock is available. */
+            /* If spinlock is not available check if the core owns the lock. */
+            /* If the core owns the lock wait increment the lock count by the core. */
+            /* If core does not own the lock wait for the spinlock. */
+            if( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+            {
+                /* Check if the core owns the spinlock. */
+                if( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit )
+                {
+                    configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != portUINT32_MAX );
+                    prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) + 1 ) );
+                    return;
+                }
+
+                /* Preload the gate word into the cache. */
+                uint32_t dummy = ulGateWord[ eLockNum ];
+                dummy++;
+
+                while( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+                {
+                    __asm volatile ( "wfe" );
+                }
+            }
+
+            /* Add barrier to ensure lock is taken before we proceed. */
+            __asm volatile( "dmb sy" ::: "memory" );
+
+            /* Assert the lock count is 0 when the spinlock is free and is acquired. */
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) == 0 );
+
+            /* Set lock count as 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], 1 );
+            /* Set ulOwnedByCore. */
+            prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) | ulLockBit ) );
+        }
+        /* Lock release. */
+        else
+        {
+            /* Assert the lock is not free already. */
+            configASSERT( ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit ) != 0 );
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != 0 );
+
+            /* Reduce ulRecursionCountByLock by 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) - 1 ) );
+
+            if( !prvGet32( &ulRecursionCountByLock[ eLockNum ] ) )
+            {
+                prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ~ulLockBit ) );
+                prvSpinUnlock( &ulGateWord[ eLockNum ] );
+                /* Add barrier to ensure lock status is reflected before we proceed. */
+                __asm volatile( "dmb sy" ::: "memory" );
+            }
+        }
+    }
+
+/*-----------------------------------------------------------*/
+
+    uint8_t ucPortGetCoreID( void )
+    {
+        return *(volatile uint8_t *)(configCORE_ID_REGISTER);
+    }
+
+/*-----------------------------------------------------------*/
+
+#endif /* if( configNUMBER_OF_CORES > 1 ) */
diff --git a/Source/portable/IAR/ARM_CM33/non_secure/portasm.h b/Source/portable/IAR/ARM_CM33/non_secure/portasm.h
index 53b4b6e..b4b545f 100644
--- a/Source/portable/IAR/ARM_CM33/non_secure/portasm.h
+++ b/Source/portable/IAR/ARM_CM33/non_secure/portasm.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM33/non_secure/portasm.s b/Source/portable/IAR/ARM_CM33/non_secure/portasm.s
index b5c91e5..c31d9ed 100644
--- a/Source/portable/IAR/ARM_CM33/non_secure/portasm.s
+++ b/Source/portable/IAR/ARM_CM33/non_secure/portasm.s
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  * Copyright 2024 Arm Limited and/or its affiliates
  * <open-source-office@arm.com>
@@ -41,6 +41,16 @@
     #define configUSE_MPU_WRAPPERS_V1 0
 #endif
 
+#if ( configENABLE_MPU == 1 )
+    #if ( configENABLE_PAC == 1 )
+        #define SECURE_CONTEXT_OFFSET   -36
+    #else
+        #define SECURE_CONTEXT_OFFSET   -20
+    #endif
+#else
+    #define SECURE_CONTEXT_OFFSET       0
+#endif
+
     EXTERN pxCurrentTCB
     EXTERN xSecureContext
     EXTERN vTaskSwitchContext
@@ -532,8 +542,8 @@
 
 vPortFreeSecureContext:
     /* r0 = uint32_t *pulTCB. */
-    ldr r2, [r0]                            /* The first item in the TCB is the top of the stack. */
-    ldr r1, [r2]                            /* The first item on the stack is the task's xSecureContext. */
+    ldr r2, [r0]                            /* The first item in the TCB is the stored context location. */
+    ldr r1, [r2, #SECURE_CONTEXT_OFFSET]    /* Read xSecureContext from the task's context. */
     cmp r1, #0                              /* Raise svc if task's xSecureContext is not NULL. */
     it ne
     svcne 101                               /* Secure context is freed in the supervisor call. portSVC_FREE_SECURE_CONTEXT = 101. */
diff --git a/Source/portable/IAR/ARM_CM33/non_secure/portmacro.h b/Source/portable/IAR/ARM_CM33/non_secure/portmacro.h
index df7888d..89a3243 100644
--- a/Source/portable/IAR/ARM_CM33/non_secure/portmacro.h
+++ b/Source/portable/IAR/ARM_CM33/non_secure/portmacro.h
@@ -1,6 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * Copyright 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -52,6 +53,7 @@
 #define portHAS_ARMV8M_MAIN_EXTENSION    1
 #define portARMV8M_MINOR_VERSION         0
 #define portDONT_DISCARD                 __root
+#define portVALIDATED_FOR_SMP            0
 /*-----------------------------------------------------------*/
 
 /* ARMv8-M common port configurations. */
diff --git a/Source/portable/IAR/ARM_CM33/non_secure/portmacrocommon.h b/Source/portable/IAR/ARM_CM33/non_secure/portmacrocommon.h
index 2dfac6a..c34fdee 100644
--- a/Source/portable/IAR/ARM_CM33/non_secure/portmacrocommon.h
+++ b/Source/portable/IAR/ARM_CM33/non_secure/portmacrocommon.h
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -59,6 +58,19 @@
     #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h.  Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
 #endif /* configENABLE_TRUSTZONE */
 
+#if ( configNUMBER_OF_CORES > 1 )
+    #if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 )
+        #error "Multi-core SMP is currently only validated for Cortex-M33 non-TrustZone non-MPU port."
+    #endif /* if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 ) ) */
+
+    #ifndef configCORE_ID_REGISTER
+        #error "configCORE_ID_REGISTER must be defined to the address of the register used to identify the core executing the code."
+    #endif /* ifndef configCORE_ID_REGISTER */
+
+    #ifndef configWAKE_SECONDARY_CORES
+        #error "configWAKE_SECONDARY_CORES must be defined to a function that wakes the secondary cores."
+    #endif /* ifndef configWAKE_SECONDARY_CORES */
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -428,10 +440,26 @@
 /**
  * @brief Critical section management.
  */
+
+#define portSET_INTERRUPT_MASK()                  ulSetInterruptMask()
+#define portCLEAR_INTERRUPT_MASK( x )             vClearInterruptMask( x )
 #define portSET_INTERRUPT_MASK_FROM_ISR()         ulSetInterruptMask()
 #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x )    vClearInterruptMask( x )
-#define portENTER_CRITICAL()                      vPortEnterCritical()
-#define portEXIT_CRITICAL()                       vPortExitCritical()
+
+#if ( configNUMBER_OF_CORES == 1 )
+    #define portENTER_CRITICAL()                      vPortEnterCritical()
+    #define portEXIT_CRITICAL()                       vPortExitCritical()
+#else /* ( configNUMBER_OF_CORES == 1 ) */
+    extern void vTaskEnterCritical( void );
+    extern void vTaskExitCritical( void );
+    extern UBaseType_t vTaskEnterCriticalFromISR( void );
+    extern void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus );
+
+    #define portENTER_CRITICAL()                      vTaskEnterCritical()
+    #define portEXIT_CRITICAL()                       vTaskExitCritical()
+    #define portENTER_CRITICAL_FROM_ISR()             vTaskEnterCriticalFromISR()
+    #define portEXIT_CRITICAL_FROM_ISR( x )           vTaskExitCriticalFromISR( x )
+#endif /* if ( configNUMBER_OF_CORES != 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -526,7 +554,7 @@
 /* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION
  * based on whether or not Mainline extension is implemented. */
 #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
-    #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 )
+    #if ( ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) && ( configNUMBER_OF_CORES == 1 ) )
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    1
     #else
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    0
@@ -573,6 +601,44 @@
 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
 /*-----------------------------------------------------------*/
 
+
+#if ( configNUMBER_OF_CORES > 1 )
+    typedef enum
+    {
+        eIsrLock = 0,
+        eTaskLock,
+        eLockCount
+    } ePortRTOSLock;
+
+    extern volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ];
+    extern void vPortRecursiveLock( uint8_t ucCoreID,
+                                    ePortRTOSLock eLockNum,
+                                    BaseType_t uxAcquire );
+    extern uint8_t ucPortGetCoreID( void );
+    extern void vInterruptCore( uint8_t ucCoreID );
+
+    #define portGET_CORE_ID()                                  ucPortGetCoreID()
+
+    #define portGET_CRITICAL_NESTING_COUNT( xCoreID )          ( ulCriticalNestings[ ( uint8_t ) xCoreID ] )
+    #define portSET_CRITICAL_NESTING_COUNT( xCoreID, x )       ( ulCriticalNestings[ ( uint8_t ) xCoreID ] = ( x ) )
+    #define portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]++ )
+    #define portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]-- )
+
+    #define portMAX_CORE_COUNT                                 ( configNUMBER_OF_CORES )
+
+    #define portYIELD_CORE( xCoreID )                          vInterruptCore( xCoreID )
+
+    #define portRELEASE_ISR_LOCK( xCoreID )                    vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdFALSE )
+    #define portGET_ISR_LOCK( xCoreID )                        vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdTRUE )
+
+    #define portRELEASE_TASK_LOCK( xCoreID )                   vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdFALSE )
+    #define portGET_TASK_LOCK( xCoreID )                       vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdTRUE )
+
+    #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* ( configENABLE_PAC == 1 || configENABLE_BTI == 1 ) */
+#endif
+
 /* *INDENT-OFF* */
 #ifdef __cplusplus
     }
diff --git a/Source/portable/IAR/ARM_CM33/secure/secure_context.c b/Source/portable/IAR/ARM_CM33/secure/secure_context.c
index 62bcfa1..2dae022 100644
--- a/Source/portable/IAR/ARM_CM33/secure/secure_context.c
+++ b/Source/portable/IAR/ARM_CM33/secure/secure_context.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -213,8 +213,19 @@
         /* Were we able to get a free context? */
         if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS )
         {
-            /* Allocate the stack space. */
-            pucStackMemory = pvPortMalloc( ulSecureStackSize + securecontextSTACK_SEAL_SIZE );
+            /* Allocate the stack space if possible. */
+            if( ( ulSecureStackSize < securecontextSTACK_SEAL_SIZE ) ||
+                ( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) )
+            {
+                /* Reject stacks that are too small (the CONTROL word would be
+                 * written before the allocation, corrupting the secure heap)
+                 * and sizes that would overflow when the seal size is added. */
+                pucStackMemory = NULL;
+            }
+            else
+            {
+                pucStackMemory = pvPortMalloc( ulSecureStackSize + securecontextSTACK_SEAL_SIZE );
+            }
 
             if( pucStackMemory != NULL )
             {
@@ -279,9 +290,12 @@
                                                               void * pvTaskHandle )
 {
     uint32_t ulIPSR, ulSecureContextIndex;
+    uint8_t * pucStackLimit;
 
-    /* Read the Interrupt Program Status Register (IPSR) value. */
+    /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
+     * Register (PSPLIM) value. */
     secureportREAD_IPSR( ulIPSR );
+    secureportREAD_PSPLIM( pucStackLimit );
 
     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
      * when the processor is running in the Thread Mode. */
@@ -293,8 +307,14 @@
             ulSecureContextIndex = xSecureContextHandle - 1UL;
 
             /* Ensure that the secure context being deleted is associated with
-             * the task. */
-            if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
+             * the task and is NOT the currently-loaded context. Freeing a
+             * context whose stack is currently loaded in PSPLIM would leave the
+             * running task referencing freed secure memory (use-after-free).
+             * pvTaskHandle is supplied by the non-secure side and is untrusted,
+             * so it is used only as an additional ownership match, not as
+             * authority. */
+            if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) &&
+                ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) )
             {
                 /* Free the stack space. */
                 vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
@@ -342,7 +362,7 @@
 
         secureportREAD_PSPLIM( pucStackLimit );
 
-        /* Ensure that task's context is loaded and the task is saving it's own
+        /* Ensure that task's context is loaded and the task is saving its own
          * context. */
         if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) &&
             ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) )
diff --git a/Source/portable/IAR/ARM_CM33/secure/secure_context.h b/Source/portable/IAR/ARM_CM33/secure/secure_context.h
index 8b93857..51dd823 100644
--- a/Source/portable/IAR/ARM_CM33/secure/secure_context.h
+++ b/Source/portable/IAR/ARM_CM33/secure/secure_context.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM33/secure/secure_context_port_asm.s b/Source/portable/IAR/ARM_CM33/secure/secure_context_port_asm.s
index 5cc070e..519c64b 100644
--- a/Source/portable/IAR/ARM_CM33/secure/secure_context_port_asm.s
+++ b/Source/portable/IAR/ARM_CM33/secure/secure_context_port_asm.s
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM33/secure/secure_heap.c b/Source/portable/IAR/ARM_CM33/secure/secure_heap.c
index b0e83b4..58226bf 100644
--- a/Source/portable/IAR/ARM_CM33/secure/secure_heap.c
+++ b/Source/portable/IAR/ARM_CM33/secure/secure_heap.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM33/secure/secure_heap.h b/Source/portable/IAR/ARM_CM33/secure/secure_heap.h
index 61a96da..906fa24 100644
--- a/Source/portable/IAR/ARM_CM33/secure/secure_heap.h
+++ b/Source/portable/IAR/ARM_CM33/secure/secure_heap.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM33/secure/secure_init.c b/Source/portable/IAR/ARM_CM33/secure/secure_init.c
index f7f7e67..6996692 100644
--- a/Source/portable/IAR/ARM_CM33/secure/secure_init.c
+++ b/Source/portable/IAR/ARM_CM33/secure/secure_init.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM33/secure/secure_init.h b/Source/portable/IAR/ARM_CM33/secure/secure_init.h
index 46ffbd9..4e7bd40 100644
--- a/Source/portable/IAR/ARM_CM33/secure/secure_init.h
+++ b/Source/portable/IAR/ARM_CM33/secure/secure_init.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM33/secure/secure_port_macros.h b/Source/portable/IAR/ARM_CM33/secure/secure_port_macros.h
index 34494e1..72774eb 100644
--- a/Source/portable/IAR/ARM_CM33/secure/secure_port_macros.h
+++ b/Source/portable/IAR/ARM_CM33/secure/secure_port_macros.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM33_NTZ/non_secure/mpu_wrappers_v2_asm.S b/Source/portable/IAR/ARM_CM33_NTZ/non_secure/mpu_wrappers_v2_asm.S
index 68192e4..c8df7ec 100644
--- a/Source/portable/IAR/ARM_CM33_NTZ/non_secure/mpu_wrappers_v2_asm.S
+++ b/Source/portable/IAR/ARM_CM33_NTZ/non_secure/mpu_wrappers_v2_asm.S
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM33_NTZ/non_secure/port.c b/Source/portable/IAR/ARM_CM33_NTZ/non_secure/port.c
index f16a343..007150c 100644
--- a/Source/portable/IAR/ARM_CM33_NTZ/non_secure/port.c
+++ b/Source/portable/IAR/ARM_CM33_NTZ/non_secure/port.c
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024-2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -145,13 +144,13 @@
 /**
  * @brief Constants required to manipulate the FPU.
  */
-#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 )              /* Coprocessor Access Control Register. */
+#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */
 #define portCPACR_CP10_VALUE    ( 3UL )
 #define portCPACR_CP11_VALUE    portCPACR_CP10_VALUE
 #define portCPACR_CP10_POS      ( 20UL )
 #define portCPACR_CP11_POS      ( 22UL )
 
-#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 )              /* Floating Point Context Control Register. */
+#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
 #define portFPCCR_ASPEN_POS     ( 31UL )
 #define portFPCCR_ASPEN_MASK    ( 1UL << portFPCCR_ASPEN_POS )
 #define portFPCCR_LSPEN_POS     ( 30UL )
@@ -188,8 +187,8 @@
 #define portMPU_MAIR0_REG                       ( *( ( volatile uint32_t * ) 0xe000edc0 ) )
 #define portMPU_MAIR1_REG                       ( *( ( volatile uint32_t * ) 0xe000edc4 ) )
 
-#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
-#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
+#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
+#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
 
 #define portMPU_RBAR_ACCESS_PERMISSIONS_MASK    ( 3UL << 1UL )
 
@@ -230,8 +229,8 @@
 
 #if ( portARMV8M_MINOR_VERSION >= 1 )
 
-/* Enable Privileged eXecute Never MPU attribute for the selected memory
- * region. */
+    /* Enable Privileged eXecute Never MPU attribute for the selected memory
+     * region. */
     #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER    ( 1UL << 4UL )
 #endif /* portARMV8M_MINOR_VERSION >= 1 */
 
@@ -241,9 +240,6 @@
 /* Enable MPU. */
 #define portMPU_ENABLE_BIT                    ( 1UL << 0UL )
 
-/* Expected value of the portMPU_TYPE register. */
-#define portEXPECTED_MPU_TYPE_VALUE           ( configTOTAL_MPU_REGIONS << 8UL )
-
 /* Extract first address of the MPU region as encoded in the
  * RBAR (Region Base Address Register) value. */
 #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@@ -291,37 +287,37 @@
 
 #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         FD
- * 1111 1111  1111 1111  1111 1111  1111 1101
- *
- * Bit[6] - 1 --> The exception was taken from the Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 1 --> The exception was taken to the Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         FD
+     * 1111 1111  1111 1111  1111 1111  1111 1101
+     *
+     * Bit[6] - 1 --> The exception was taken from the Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 1 --> The exception was taken to the Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xfffffffd )
 #else
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         BC
- * 1111 1111  1111 1111  1111 1111  1011 1100
- *
- * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         BC
+     * 1111 1111  1111 1111  1111 1111  1011 1100
+     *
+     * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xffffffbc )
 #endif /* configRUN_FREERTOS_SECURE_ONLY */
 
@@ -401,50 +397,54 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Extract MPU region's access permissions from the Region Base Address
- * Register (RBAR) value.
- *
- * @param ulRBARValue RBAR value for the MPU region.
- *
- * @return uint32_t Access permissions.
- */
+    /**
+     * @brief Extract MPU region's access permissions from the Region Base Address
+     * Register (RBAR) value.
+     *
+     * @param ulRBARValue RBAR value for the MPU region.
+     *
+     * @return uint32_t Access permissions.
+     */
     static uint32_t prvGetRegionAccessPermissions( uint32_t ulRBARValue ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU == 1 && configUSE_MPU_WRAPPERS_V1 == 0 */
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Setup the Memory Protection Unit (MPU).
- */
+    /**
+     * @brief Setup the Memory Protection Unit (MPU).
+     */
     static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU */
 
 #if ( configENABLE_FPU == 1 )
 
-/**
- * @brief Setup the Floating Point Unit (FPU).
- */
+    /**
+     * @brief Setup the Floating Point Unit (FPU).
+     */
     static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_FPU */
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
 
-/**
- * @brief Configures PACBTI features.
- *
- * This function configures the Pointer Authentication, and Branch Target
- * Identification security features as per the user configuration. It returns
- * the value of the special purpose CONTROL register accordingly, and optionally
- * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
- * architecture based) target supports PACBTI security feature.
- *
- * @param xWriteControlRegister Used to control whether the special purpose
- * CONTROL register should be updated or not.
- *
- * @return CONTROL register value according to the configured PACBTI option.
- */
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    /**
+     * @brief Configures PACBTI features.
+     *
+     * This function configures the Pointer Authentication, and Branch Target
+     * Identification security features as per the user configuration. It returns
+     * the value of the special purpose CONTROL register accordingly, and optionally
+     * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
+     * architecture based) target supports PACBTI security feature.
+     *
+     * @param xWriteControlRegister Used to control whether the special purpose
+     * CONTROL register should be updated or not.
+     *
+     * @return CONTROL register value according to the configured PACBTI option.
+     */
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -491,14 +491,14 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the system call stack so that upon returning from
- * SVC, the system call stack is used.
- *
- * @param pulTaskStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- * @param ucSystemCallNumber The system call number of the system call.
- */
+    /**
+     * @brief Sets up the system call stack so that upon returning from
+     * SVC, the system call stack is used.
+     *
+     * @param pulTaskStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     * @param ucSystemCallNumber The system call number of the system call.
+     */
     void vSystemCallEnter( uint32_t * pulTaskStack,
                            uint32_t ulLR,
                            uint8_t ucSystemCallNumber ) PRIVILEGED_FUNCTION;
@@ -507,22 +507,22 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Raise SVC for exiting from a system call.
- */
+    /**
+     * @brief Raise SVC for exiting from a system call.
+     */
     void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the task stack so that upon returning from
- * SVC, the task stack is used again.
- *
- * @param pulSystemCallStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- */
+    /**
+     * @brief Sets up the task stack so that upon returning from
+     * SVC, the task stack is used again.
+     *
+     * @param pulSystemCallStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     */
     void vSystemCallExit( uint32_t * pulSystemCallStack,
                           uint32_t ulLR ) PRIVILEGED_FUNCTION;
 
@@ -530,21 +530,38 @@
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Checks whether or not the calling task is privileged.
- *
- * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
- */
+    /**
+     * @brief Checks whether or not the calling task is privileged.
+     *
+     * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
+     */
     BaseType_t xPortIsTaskPrivileged( void ) PRIVILEGED_FUNCTION;
 
 #endif /* configENABLE_MPU == 1 */
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /**
+     * @brief Platform/Application-defined function that wakes up the secondary cores.
+     *
+     * @return pdTRUE if the secondary cores were successfully woken up.
+     *         pdFALSE otherwise.
+     */
+    extern BaseType_t configWAKE_SECONDARY_CORES( void );
+
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
+
+/**
+ * @brief Configures interrupt priorities.
+ */
+void vPortConfigureInterruptPriorities( void ) PRIVILEGED_FUNCTION;
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief This variable is set to pdTRUE when the scheduler is started.
- */
+    /**
+     * @brief This variable is set to pdTRUE when the scheduler is started.
+     */
     PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
@@ -553,14 +570,22 @@
  * @brief Each task maintains its own interrupt status in the critical nesting
  * variable.
  */
-PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
+#if ( configNUMBER_OF_CORES == 1 )
+    PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0UL;
+#else /* #if ( configNUMBER_OF_CORES == 1 ) */
+    PRIVILEGED_DATA volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ] = { 0 };
+    /* Flags to check if the secondary cores are ready. */
+    PRIVILEGED_DATA volatile uint8_t ucSecondaryCoresReadyFlags[ configNUMBER_OF_CORES - 1 ] = { 0 };
+    /* Flag to indicate that the primary core has completed its initialisation. */
+    PRIVILEGED_DATA volatile uint8_t ucPrimaryCoreInitDoneFlag = 0;
+ #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #if ( configENABLE_TRUSTZONE == 1 )
 
-/**
- * @brief Saved as part of the task context to indicate which context the
- * task is using on the secure side.
- */
+    /**
+     * @brief Saved as part of the task context to indicate which context the
+     * task is using on the secure side.
+     */
     PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
 #endif /* configENABLE_TRUSTZONE */
 
@@ -579,21 +604,21 @@
 
 #if ( configUSE_TICKLESS_IDLE == 1 )
 
-/**
- * @brief The number of SysTick increments that make up one tick period.
- */
+    /**
+     * @brief The number of SysTick increments that make up one tick period.
+     */
     PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
 
-/**
- * @brief The maximum number of tick periods that can be suppressed is
- * limited by the 24 bit resolution of the SysTick timer.
- */
+    /**
+     * @brief The maximum number of tick periods that can be suppressed is
+     * limited by the 24 bit resolution of the SysTick timer.
+     */
     PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
 
-/**
- * @brief Compensate for the CPU cycles that pass while the SysTick is
- * stopped (low power functionality only).
- */
+    /**
+     * @brief Compensate for the CPU cycles that pass while the SysTick is
+     * stopped (low power functionality only).
+     */
     PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0;
 #endif /* configUSE_TICKLESS_IDLE */
 /*-----------------------------------------------------------*/
@@ -856,7 +881,11 @@
      * should instead call vTaskDelete( NULL ). Artificially force an assert()
      * to be triggered if configASSERT() is defined, then stop here so
      * application writers can catch the error. */
-    configASSERT( ulCriticalNesting == ~0UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == ~0UL );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == ~0UL );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
     portDISABLE_INTERRUPTS();
 
     while( ulDummy == 0 )
@@ -925,64 +954,57 @@
         /* The only permitted number of regions are 8 or 16. */
         configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 16 ) );
 
-        /* Ensure that the configTOTAL_MPU_REGIONS is configured correctly. */
-        configASSERT( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE );
+        /* MAIR0 - Index 0. */
+        portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
+        /* MAIR0 - Index 1. */
+        portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
 
-        /* Check that the MPU is present. */
-        if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
-        {
-            /* MAIR0 - Index 0. */
-            portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
-            /* MAIR0 - Index 1. */
-            portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
+        /* Setup privileged flash as Read Only so that privileged tasks can
+         * read it but not modify. */
+        portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup privileged flash as Read Only so that privileged tasks can
-             * read it but not modify. */
-            portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged flash as Read Only by both privileged and
+         * unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged flash as Read Only by both privileged and
-             * unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged syscalls flash as Read Only by both privileged
+         * and unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged syscalls flash as Read Only by both privileged
-             * and unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup RAM containing kernel data for privileged access only. */
+        portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
+                           ( portMPU_REGION_EXECUTE_NEVER );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup RAM containing kernel data for privileged access only. */
-            portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
-                               ( portMPU_REGION_EXECUTE_NEVER );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Enable mem fault. */
+        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
 
-            /* Enable mem fault. */
-            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
-
-            /* Enable MPU with privileged background access i.e. unmapped
-             * regions have privileged access. */
-            portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
-        }
+        /* Enable MPU with privileged background access i.e. unmapped
+         * regions have privileged access. */
+        portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
     }
 
 #endif /* configENABLE_MPU */
@@ -1027,28 +1049,29 @@
 }
 /*-----------------------------------------------------------*/
 
-void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    portDISABLE_INTERRUPTS();
-    ulCriticalNesting++;
-
-    /* Barriers are normally not required but do ensure the code is
-     * completely within the specified behaviour for the architecture. */
-    __asm volatile ( "dsb" ::: "memory" );
-    __asm volatile ( "isb" );
-}
-/*-----------------------------------------------------------*/
-
-void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    configASSERT( ulCriticalNesting );
-    ulCriticalNesting--;
-
-    if( ulCriticalNesting == 0 )
+#if ( configNUMBER_OF_CORES == 1 )
+    void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
     {
-        portENABLE_INTERRUPTS();
+        portDISABLE_INTERRUPTS();
+        ulCriticalNesting++;
+        /* Barriers are normally not required but do ensure the code is
+        * completely within the specified behaviour for the architecture. */
+        __asm volatile ( "dsb" ::: "memory" );
+        __asm volatile ( "isb" );
     }
-}
+    /*-----------------------------------------------------------*/
+
+    void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
+    {
+        configASSERT( ulCriticalNesting );
+        ulCriticalNesting--;
+
+        if( ulCriticalNesting == 0 )
+        {
+            portENABLE_INTERRUPTS();
+        }
+    }
+#endif /* configNUMBER_OF_CORES == 1 */
 /*-----------------------------------------------------------*/
 
 void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
@@ -1056,6 +1079,10 @@
     uint32_t ulPreviousMask;
 
     ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
+    #if ( configNUMBER_OF_CORES > 1 )
+        UBaseType_t uxSavedInterruptStatus = portENTER_CRITICAL_FROM_ISR();
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     traceISR_ENTER();
     {
         /* Increment the RTOS tick. */
@@ -1070,6 +1097,10 @@
             traceISR_EXIT();
         }
     }
+    #if ( configNUMBER_OF_CORES > 1 )
+        portEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
 }
 /*-----------------------------------------------------------*/
@@ -1078,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1090,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1108,38 +1151,42 @@
 
     switch( ucSVCNumber )
     {
-        #if ( configENABLE_TRUSTZONE == 1 )
-            case portSVC_ALLOCATE_SECURE_CONTEXT:
+    #if ( configENABLE_TRUSTZONE == 1 )
+        case portSVC_ALLOCATE_SECURE_CONTEXT:
 
-                /* R0 contains the stack size passed as parameter to the
-                 * vPortAllocateSecureContext function. */
-                ulR0 = pulCallerStackAddress[ 0 ];
+            /* R0 contains the stack size passed as parameter to the
+             * vPortAllocateSecureContext function. */
+            ulR0 = pulCallerStackAddress[ 0 ];
 
-                #if ( configENABLE_MPU == 1 )
-                {
-                    /* Read the CONTROL register value. */
-                    __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
+            #if ( configENABLE_MPU == 1 )
+            {
+                /* Read the CONTROL register value. */
+                __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
 
-                    /* The task that raised the SVC is privileged if Bit[0]
-                     * in the CONTROL register is 0. */
-                    ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
+                /* The task that raised the SVC is privileged if Bit[0]
+                 * in the CONTROL register is 0. */
+                ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
 
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
-                }
-                #else /* if ( configENABLE_MPU == 1 ) */
-                {
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
-                }
-                #endif /* configENABLE_MPU */
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
+            }
+            #else /* if ( configENABLE_MPU == 1 ) */
+            {
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
+            }
+            #endif /* configENABLE_MPU */
 
-                configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
-                SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
-                break;
+            configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
+            SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
+            break;
 
-            case portSVC_FREE_SECURE_CONTEXT:
-
+        case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
                 /* R0 contains TCB being freed and R1 contains the secure
                  * context handle to be freed. */
                 ulR0 = pulCallerStackAddress[ 0 ];
@@ -1147,51 +1194,62 @@
 
                 /* Free the secure context. */
                 SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
-                break;
-        #endif /* configENABLE_TRUSTZONE */
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
+            break;
+    #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
-            #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
-                case portSVC_RAISE_PRIVILEGE:
+    #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
+        case portSVC_RAISE_PRIVILEGE:
 
-                    /* Only raise the privilege, if the svc was raised from any of
-                     * the system calls. */
-                    if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
-                        ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
-                    {
-                        vRaisePrivilege();
-                    }
-                    break;
-            #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
+            /* Only raise the privilege, if the svc was raised from any of
+             * the system calls. */
+            if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
+                ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
+            {
+                vRaisePrivilege();
+            }
+            break;
+    #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
-            #if ( configENABLE_MPU == 1 )
-                case portSVC_YIELD:
-                    vPortYield();
-                    break;
-            #endif /* configENABLE_MPU == 1 */
+    #if ( configENABLE_MPU == 1 )
+        case portSVC_YIELD:
+            vPortYield();
+            break;
+    #endif /* configENABLE_MPU == 1 */
 
         default:
             /* Incorrect SVC call. */
@@ -1210,7 +1268,7 @@
         extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulSystemCallStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1246,12 +1304,16 @@
         {
             pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1261,20 +1323,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the system call stack for the stack frame. */
-            pulSystemCallStack = pulSystemCallStack - ulStackFrameSize;
+            pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulSystemCallStack[ i ] = pulTaskStack[ i ];
             }
@@ -1310,7 +1372,7 @@
 
             /* Remember the location where we should copy the stack frame when we exit from
              * the system call. */
-            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
+            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
 
             /* Record if the hardware used padding to force the stack pointer
              * to be double word aligned. */
@@ -1360,7 +1422,7 @@
         extern TaskHandle_t pxCurrentTCB;
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulTaskStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1392,12 +1454,16 @@
         {
             pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1407,20 +1473,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the task stack for the stack frame. */
-            pulTaskStack = pulTaskStack - ulStackFrameSize;
+            pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulTaskStack[ i ] = pulSystemCallStack[ i ];
             }
@@ -1518,21 +1584,21 @@
         xMPUSettings->ulContext[ ulIndex ] = 0x11111111; /* r11. */
         ulIndex++;
 
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters;            /* r0. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters; /* r0. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x01010101;                           /* r1. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x01010101; /* r1. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x02020202;                           /* r2. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x02020202; /* r2. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x03030303;                           /* r3. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x03030303; /* r3. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x12121212;                           /* r12. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x12121212; /* r12. */
         ulIndex++;
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) portTASK_RETURN_ADDRESS; /* LR. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode;                  /* PC. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode; /* PC. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR;                     /* xPSR. */
+        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR; /* xPSR. */
         ulIndex++;
 
         #if ( configENABLE_TRUSTZONE == 1 )
@@ -1543,14 +1609,18 @@
         #endif /* configENABLE_TRUSTZONE */
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) ( pxTopOfStack - 8 ); /* PSP with the hardware saved stack. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack;         /* PSPLIM. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack; /* PSPLIM. */
         ulIndex++;
 
         #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
         {
             /* Check PACBTI security feature configuration before pushing the
              * CONTROL register's value on task's TCB. */
-            ulControl = prvConfigurePACBTI( pdFALSE );
+            #if ( configNUMBER_OF_CORES == 1 )
+                ulControl = prvConfigurePACBTI( pdFALSE );
+            #else /* configNUMBER_OF_CORES > 1 */
+                ulControl = vConfigurePACBTI( pdFALSE );
+            #endif /* configNUMBER_OF_CORES */
         }
         #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1615,15 +1685,15 @@
          * interrupt. */
         #if ( portPRELOAD_REGISTERS == 0 )
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
-            pxTopOfStack -= 5;                                       /* R12, R3, R2 and R1. */
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
-            pxTopOfStack -= 9;                                       /* R11..R4, EXC_RETURN. */
+            pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
+            pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */
             *pxTopOfStack = portINITIAL_EXC_RETURN;
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
@@ -1637,42 +1707,42 @@
         }
         #else /* portPRELOAD_REGISTERS */
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x12121212UL;            /* R12. */
+            *pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x03030303UL;            /* R3. */
+            *pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x02020202UL;            /* R2. */
+            *pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x01010101UL;            /* R1. */
+            *pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x11111111UL;            /* R11. */
+            *pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x10101010UL;            /* R10. */
+            *pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x09090909UL;            /* R09. */
+            *pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x08080808UL;            /* R08. */
+            *pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x07070707UL;            /* R07. */
+            *pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x06060606UL;            /* R06. */
+            *pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x05050505UL;            /* R05. */
+            *pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x04040404UL;            /* R04. */
+            *pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04. */
             pxTopOfStack--;
-            *pxTopOfStack = portINITIAL_EXC_RETURN;                  /* EXC_RETURN. */
+            *pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxEndOfStack;            /* Slot used to hold this task's PSPLIM value. */
+            *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
 
             #if ( configENABLE_TRUSTZONE == 1 )
             {
@@ -1739,91 +1809,17 @@
     }
     #endif /* configCHECK_HANDLER_INSTALLATION */
 
-    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
-    {
-        volatile uint32_t ulImplementedPrioBits = 0;
-        volatile uint8_t ucMaxPriorityValue;
-
-        /* Determine the maximum priority from which ISR safe FreeRTOS API
-         * functions can be called. ISR safe functions are those that end in
-         * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
-         * ensure interrupt entry is as fast and simple as possible.
-         *
-         * First, determine the number of priority bits available. Write to all
-         * possible bits in the priority setting for SVCall. */
-        portNVIC_SHPR2_REG = 0xFF000000;
-
-        /* Read the value back to see how many bits stuck. */
-        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
-
-        /* Use the same mask on the maximum system call priority. */
-        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
-
-        /* Check that the maximum system call priority is nonzero after
-         * accounting for the number of priority bits supported by the
-         * hardware. A priority of 0 is invalid because setting the BASEPRI
-         * register to 0 unmasks all interrupts, and interrupts with priority 0
-         * cannot be masked using BASEPRI.
-         * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
-        configASSERT( ucMaxSysCallPriority );
-
-        /* Check that the bits not implemented in hardware are zero in
-         * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
-        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
-
-        /* Calculate the maximum acceptable priority group value for the number
-         * of bits read back. */
-        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
-        {
-            ulImplementedPrioBits++;
-            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
-        }
-
-        if( ulImplementedPrioBits == 8 )
-        {
-            /* When the hardware implements 8 priority bits, there is no way for
-             * the software to configure PRIGROUP to not have sub-priorities. As
-             * a result, the least significant bit is always used for sub-priority
-             * and there are 128 preemption priorities and 2 sub-priorities.
-             *
-             * This may cause some confusion in some cases - for example, if
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
-             * priority interrupts will be masked in Critical Sections as those
-             * are at the same preemption priority. This may appear confusing as
-             * 4 is higher (numerically lower) priority than
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
-             * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
-             * to 4, this confusion does not happen and the behaviour remains the same.
-             *
-             * The following assert ensures that the sub-priority bit in the
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
-             * confusion. */
-            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
-            ulMaxPRIGROUPValue = 0;
-        }
-        else
-        {
-            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
-        }
-
-        /* Shift the priority group value back to its position within the AIRCR
-         * register. */
-        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
-        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
-    }
-    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
-
-    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
-     * the highest priority. */
-    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
-    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
-    portNVIC_SHPR2_REG = 0;
+    vPortConfigureInterruptPriorities();
 
     #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
     {
         /* Set the CONTROL register value based on PACBTI security feature
          * configuration before starting the first task. */
-        ( void ) prvConfigurePACBTI( pdTRUE );
+        #if ( configNUMBER_OF_CORES == 1 )
+            ( void ) prvConfigurePACBTI( pdTRUE );
+        #else /* configNUMBER_OF_CORES > 1 */
+            ( void ) vConfigurePACBTI( pdTRUE );
+        #endif /* configNUMBER_OF_CORES */
     }
     #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1834,12 +1830,47 @@
     }
     #endif /* configENABLE_MPU */
 
-    /* Start the timer that generates the tick ISR. Interrupts are disabled
-     * here already. */
-    vPortSetupTimerInterrupt();
+    #if ( configNUMBER_OF_CORES > 1 )
+        /* Start the timer that generates the tick ISR. Interrupts are disabled
+         * here already. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count for all cores. */
+        for ( uint8_t ucCoreID = 0; ucCoreID < configNUMBER_OF_CORES; ucCoreID++ )
+        {
+            ulCriticalNestings[ ucCoreID ] = 0;
+        }
+        /* Signal that primary core has done all the necessary initialisations. */
+        ucPrimaryCoreInitDoneFlag = 1;
+        /* Wake up secondary cores */
+        BaseType_t xWakeResult = configWAKE_SECONDARY_CORES();
+        configASSERT( xWakeResult == pdTRUE );
 
-    /* Initialize the critical nesting count ready for the first task. */
-    ulCriticalNesting = 0;
+        /* Hold the primary core here until all the secondary cores are ready, this would be achieved only when
+         * all elements of ucSecondaryCoresReadyFlags are set.
+         */
+        while( 1 )
+        {
+            BaseType_t xAllCoresReady = pdTRUE;
+            for( uint8_t ucCoreID = 0; ucCoreID < ( configNUMBER_OF_CORES - 1 ); ucCoreID++ )
+            {
+                if( ucSecondaryCoresReadyFlags[ ucCoreID ] != pdTRUE )
+                {
+                    xAllCoresReady = pdFALSE;
+                    break;
+                }
+                }
+
+            if ( xAllCoresReady == pdTRUE )
+            {
+                break;
+            }
+        }
+    #else /* if ( configNUMBER_OF_CORES > 1 ) */
+        /* Start the timer that generates the tick ISR. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count ready for the first task. */
+        ulCriticalNesting = 0;
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
     {
@@ -1856,7 +1887,11 @@
      * functionality by defining configTASK_RETURN_ADDRESS. Call
      * vTaskSwitchContext() so link time optimization does not remove the
      * symbol. */
-    vTaskSwitchContext();
+    #if ( configNUMBER_OF_CORES > 1 )
+        vTaskSwitchContext( portGET_CORE_ID() );
+    #else
+        vTaskSwitchContext();
+    #endif
     prvTaskExitError();
 
     /* Should not get here. */
@@ -1868,7 +1903,11 @@
 {
     /* Not implemented in ports where there is nothing to return to.
      * Artificially force an assert. */
-    configASSERT( ulCriticalNesting == 1000UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == 1000UL );
+    #else /* if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == 1000UL );
+    #endif /* if ( configNUMBER_OF_CORES == 1 ) */
 }
 /*-----------------------------------------------------------*/
 
@@ -2151,6 +2190,90 @@
 #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
 /*-----------------------------------------------------------*/
 
+void vPortConfigureInterruptPriorities( void ) /* PRIVILEGED_FUNCTION */
+{
+    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
+    {
+        volatile uint32_t ulImplementedPrioBits = 0;
+        volatile uint8_t ucMaxPriorityValue;
+
+        /* Determine the maximum priority from which ISR safe FreeRTOS API
+        * functions can be called. ISR safe functions are those that end in
+        * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
+        * ensure interrupt entry is as fast and simple as possible.
+        *
+        * First, determine the number of priority bits available. Write to all
+        * possible bits in the priority setting for SVCall. */
+        portNVIC_SHPR2_REG = 0xFF000000;
+
+        /* Read the value back to see how many bits stuck. */
+        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
+
+        /* Use the same mask on the maximum system call priority. */
+        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
+
+        /* Check that the maximum system call priority is nonzero after
+        * accounting for the number of priority bits supported by the
+        * hardware. A priority of 0 is invalid because setting the BASEPRI
+        * register to 0 unmasks all interrupts, and interrupts with priority 0
+        * cannot be masked using BASEPRI.
+        * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+        configASSERT( ucMaxSysCallPriority );
+
+        /* Check that the bits not implemented in hardware are zero in
+        * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
+        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
+
+        /* Calculate the maximum acceptable priority group value for the number
+        * of bits read back. */
+        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
+        {
+            ulImplementedPrioBits++;
+            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
+        }
+
+        if( ulImplementedPrioBits == 8 )
+        {
+            /* When the hardware implements 8 priority bits, there is no way for
+            * the software to configure PRIGROUP to not have sub-priorities. As
+            * a result, the least significant bit is always used for sub-priority
+            * and there are 128 preemption priorities and 2 sub-priorities.
+            *
+            * This may cause some confusion in some cases - for example, if
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
+            * priority interrupts will be masked in Critical Sections as those
+            * are at the same preemption priority. This may appear confusing as
+            * 4 is higher (numerically lower) priority than
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
+            * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
+            * to 4, this confusion does not happen and the behaviour remains the same.
+            *
+            * The following assert ensures that the sub-priority bit in the
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
+            * confusion. */
+            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
+            ulMaxPRIGROUPValue = 0;
+        }
+        else
+        {
+            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
+        }
+
+        /* Shift the priority group value back to its position within the AIRCR
+        * register. */
+        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
+        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
+    }
+    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
+
+    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
+    * the highest priority. */
+    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
+    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
+    portNVIC_SHPR2_REG = 0;
+}
+/*-----------------------------------------------------------*/
+
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) )
 
     void vPortGrantAccessToKernelObject( TaskHandle_t xInternalTaskHandle,
@@ -2247,36 +2370,214 @@
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
-
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
-    {
-        uint32_t ulControl = 0x0;
-
-        /* Ensure that PACBTI is implemented. */
-        configASSERT( portID_ISAR5_REG != 0x0 );
-
-        /* Enable UsageFault exception. */
-        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
-
-        #if ( configENABLE_PAC == 1 )
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #else /* configNUMBER_OF_CORES > 1 */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #endif /* configNUMBER_OF_CORES */
         {
-            ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
-        }
-        #endif
+            uint32_t ulControl = 0x0;
 
-        #if ( configENABLE_BTI == 1 )
-        {
-            ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
-        }
-        #endif
+            /* Ensure that PACBTI is implemented. */
+            configASSERT( portID_ISAR5_REG != 0x0 );
 
-        if( xWriteControlRegister == pdTRUE )
-        {
-            __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
-        }
+            /* Enable UsageFault exception. */
+            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
 
-        return ulControl;
-    }
+            #if ( configENABLE_PAC == 1 )
+            {
+                ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
+            }
+            #endif
+
+            #if ( configENABLE_BTI == 1 )
+            {
+                ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
+            }
+            #endif
+
+            if( xWriteControlRegister == pdTRUE )
+            {
+                __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
+            }
+
+            return ulControl;
+        }
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 /*-----------------------------------------------------------*/
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /* Which core owns the lock? */
+    PRIVILEGED_DATA volatile uint32_t ulOwnedByCore[ portMAX_CORE_COUNT ];
+    /* Lock count a core owns. */
+    PRIVILEGED_DATA volatile uint32_t ulRecursionCountByLock[ eLockCount ];
+    /* Index 0 is used for ISR lock and Index 1 is used for task lock. */
+    PRIVILEGED_DATA volatile uint32_t ulGateWord[ eLockCount ];
+
+    __attribute__((weak)) void vInterruptCore( uint8_t ucCoreID )
+    {
+        /* Default weak stub - platform specific implementation may override. */
+        ( void ) ucCoreID;
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline void prvSpinUnlock( volatile uint32_t * ulLock )
+    {
+        /* Conservative unlock: preserve original barriers for broad HW/FVP. */
+        __asm volatile (
+            "dmb sy         \n"
+            "mov r1, #0     \n"
+            "str r1, [%0]   \n"
+            "sev            \n"
+            "dsb            \n"
+            "isb            \n"
+            :
+            : "r" ( ulLock )
+            : "memory", "r1"
+        );
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline uint32_t prvSpinTrylock( volatile uint32_t * ulLock )
+    {
+        /*
+         * Conservative ldrex/strex trylock:
+         * - Return 1 immediately if busy, clearing exclusive state (CLREX).
+         * - Retry strex only on spurious failure when observed free.
+         * - DMB on success to preserve expected acquire semantics.
+         */
+        uint32_t ulVal;
+        uint32_t ulStatus;
+
+        __asm volatile (
+            " ldrex %0, [%1]   \n"
+            : "=r" ( ulVal )
+            : "r" ( ulLock )
+            : "memory"
+        );
+
+        if( ulVal != 0U )
+        {
+            __asm volatile ("clrex" ::: "memory");
+            return 1U;
+        }
+
+        __asm volatile (
+            " strex %0, %2, [%1]   \n"
+            : "=&r" ( ulStatus )
+            : "r" ( ulLock ), "r" (1U)
+            : "memory"
+        );
+
+        if( ulStatus != 0U )
+        {
+            return 1U;
+        }
+        __asm volatile ( "dmb" ::: "memory" );
+        return 0U;
+    }
+
+
+/*-----------------------------------------------------------*/
+
+    /* Read 32b value shared between cores. */
+    static inline uint32_t prvGet32( volatile uint32_t * x )
+    {
+        __asm( "dsb" );
+        return *x;
+    }
+
+/*-----------------------------------------------------------*/
+
+    /* Write 32b value shared between cores. */
+    static inline void prvSet32( volatile uint32_t * x,
+                                 uint32_t value )
+    {
+        *x = value;
+        __asm( "dsb" );
+    }
+
+/*-----------------------------------------------------------*/
+
+    void vPortRecursiveLock( uint8_t ucCoreID,
+                             ePortRTOSLock eLockNum,
+                             BaseType_t uxAcquire )
+    {
+        /* Validate the core ID and lock number. */
+        configASSERT( ucCoreID < portMAX_CORE_COUNT );
+        configASSERT( eLockNum < eLockCount );
+
+        uint32_t ulLockBit = 1u << eLockNum;
+
+        /* Lock acquire */
+        if( uxAcquire )
+        {
+            /* Check if spinlock is available. */
+            /* If spinlock is not available check if the core owns the lock. */
+            /* If the core owns the lock wait increment the lock count by the core. */
+            /* If core does not own the lock wait for the spinlock. */
+            if( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+            {
+                /* Check if the core owns the spinlock. */
+                if( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit )
+                {
+                    configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != portUINT32_MAX );
+                    prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) + 1 ) );
+                    return;
+                }
+
+                /* Preload the gate word into the cache. */
+                uint32_t dummy = ulGateWord[ eLockNum ];
+                dummy++;
+
+                while( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+                {
+                    __asm volatile ( "wfe" );
+                }
+            }
+
+            /* Add barrier to ensure lock is taken before we proceed. */
+            __asm volatile( "dmb sy" ::: "memory" );
+
+            /* Assert the lock count is 0 when the spinlock is free and is acquired. */
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) == 0 );
+
+            /* Set lock count as 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], 1 );
+            /* Set ulOwnedByCore. */
+            prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) | ulLockBit ) );
+        }
+        /* Lock release. */
+        else
+        {
+            /* Assert the lock is not free already. */
+            configASSERT( ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit ) != 0 );
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != 0 );
+
+            /* Reduce ulRecursionCountByLock by 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) - 1 ) );
+
+            if( !prvGet32( &ulRecursionCountByLock[ eLockNum ] ) )
+            {
+                prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ~ulLockBit ) );
+                prvSpinUnlock( &ulGateWord[ eLockNum ] );
+                /* Add barrier to ensure lock status is reflected before we proceed. */
+                __asm volatile( "dmb sy" ::: "memory" );
+            }
+        }
+    }
+
+/*-----------------------------------------------------------*/
+
+    uint8_t ucPortGetCoreID( void )
+    {
+        return *(volatile uint8_t *)(configCORE_ID_REGISTER);
+    }
+
+/*-----------------------------------------------------------*/
+
+#endif /* if( configNUMBER_OF_CORES > 1 ) */
diff --git a/Source/portable/IAR/ARM_CM33_NTZ/non_secure/portasm.h b/Source/portable/IAR/ARM_CM33_NTZ/non_secure/portasm.h
index 53b4b6e..b4b545f 100644
--- a/Source/portable/IAR/ARM_CM33_NTZ/non_secure/portasm.h
+++ b/Source/portable/IAR/ARM_CM33_NTZ/non_secure/portasm.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM33_NTZ/non_secure/portasm.s b/Source/portable/IAR/ARM_CM33_NTZ/non_secure/portasm.s
index 8092255..8de575d 100644
--- a/Source/portable/IAR/ARM_CM33_NTZ/non_secure/portasm.s
+++ b/Source/portable/IAR/ARM_CM33_NTZ/non_secure/portasm.s
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -41,7 +40,15 @@
     #define configUSE_MPU_WRAPPERS_V1 0
 #endif
 
+#ifndef configNUMBER_OF_CORES
+    #define configNUMBER_OF_CORES 1
+#endif
+
+#if ( configNUMBER_OF_CORES == 1)
     EXTERN pxCurrentTCB
+#else /* if ( configNUMBER_OF_CORES == 1) */
+    EXTERN pxCurrentTCBs
+#endif
     EXTERN vTaskSwitchContext
     EXTERN vPortSVCHandler_C
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
@@ -169,8 +176,15 @@
 #else /* configENABLE_MPU */
 
 vRestoreContextOfFirstTask:
+#if ( configNUMBER_OF_CORES == 1)
     ldr  r2, =pxCurrentTCB                  /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
     ldr  r1, [r2]                           /* Read pxCurrentTCB. */
+#else /* if ( configNUMBER_OF_CORES == 1) */
+    ldr r1, =ulFirstTaskLiteralPool         /* Get the location of the current TCB and the Id of the current core. */
+    ldmia r1!, {r2, r3}
+    ldr r2, [r2]                            /* r2 = Core Id */
+    ldr r1, [r3, r2, LSL #2]                /* r1 = pxCurrentTCBs[CORE_ID] */
+#endif /* if ( configNUMBER_OF_CORES == 1) */
     ldr  r0, [r1]                           /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
 
 #if ( configENABLE_PAC == 1 )
@@ -193,6 +207,13 @@
     mov  r0, #0
     msr  basepri, r0                        /* Ensure that interrupts are enabled when the first task starts. */
     bx   r2                                 /* Finally, branch to EXC_RETURN. */
+#if ( configNUMBER_OF_CORES > 1 )
+    /* Align to 4 bytes in ROM/code area (2^2 alignment, 0 fill). */
+    ALIGNROM 2, 0
+    ulFirstTaskLiteralPool:
+        DC32 configCORE_ID_REGISTER         /* CORE_ID_REGISTER */
+        DC32 pxCurrentTCBs
+#endif /* if ( configNUMBER_OF_CORES > 1 ) */
 
 #endif /* configENABLE_MPU */
 /*-----------------------------------------------------------*/
@@ -377,20 +398,37 @@
     clrm {r1-r4}                            /* Clear r1-r4. */
 #endif /* configENABLE_PAC */
 
+#if ( configNUMBER_OF_CORES == 1)
     ldr r2, =pxCurrentTCB                   /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
     ldr r1, [r2]                            /* Read pxCurrentTCB. */
+#else /* if ( configNUMBER_OF_CORES == 1) */
+    ldr r1, =ulPendSVLiteralPool            /* Get the location of the current TCB and the Id of the current core. */
+    ldmia r1!, {r2, r3}
+    ldr r2, [r2]                            /* r2 = Core Id */
+    ldr r1, [r3, r2, LSL #2]                /* r1 = pxCurrentTCBs[CORE_ID] */
+#endif /* if ( configNUMBER_OF_CORES == 1) */
     str r0, [r1]                            /* Save the new top of stack in TCB. */
 
     mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
     msr basepri, r0                         /* Disable interrupts up to configMAX_SYSCALL_INTERRUPT_PRIORITY. */
     dsb
     isb
+    #if ( configNUMBER_OF_CORES > 1)
+        mov r0, r2                          /* r0 = ucPortGetCoreID() */
+    #endif /* if ( configNUMBER_OF_CORES == 1) */
     bl vTaskSwitchContext
     mov r0, #0                              /* r0 = 0. */
     msr basepri, r0                         /* Enable interrupts. */
 
+#if ( configNUMBER_OF_CORES == 1)
     ldr r2, =pxCurrentTCB                   /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
     ldr r1, [r2]                            /* Read pxCurrentTCB. */
+#else /* if ( configNUMBER_OF_CORES == 1) */
+    ldr r1, =ulPendSVLiteralPool            /* Get the location of the current TCB and the Id of the current core. */
+    ldmia r1!, {r2, r3}
+    ldr r2, [r2]                            /* r2 = Core Id */
+    ldr r1, [r3, r2, LSL #2]                /* r1 = pxCurrentTCBs[CORE_ID] */
+#endif /* if ( configNUMBER_OF_CORES == 1) */
     ldr r0, [r1]                            /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
 
 #if ( configENABLE_PAC == 1 )
@@ -413,6 +451,13 @@
     msr psplim, r2                          /* Restore the PSPLIM register value for the task. */
     msr psp, r0                             /* Remember the new top of stack for the task. */
     bx r3
+#if ( configNUMBER_OF_CORES > 1 )
+    /* Align to 4 bytes in ROM/code area (2^2 alignment, 0 fill). */
+    ALIGNROM 2, 0
+    ulPendSVLiteralPool:
+    DC32 configCORE_ID_REGISTER         /* CORE_ID_REGISTER */
+    DC32 pxCurrentTCBs
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
 
 #endif /* configENABLE_MPU */
 /*-----------------------------------------------------------*/
diff --git a/Source/portable/IAR/ARM_CM33_NTZ/non_secure/portmacro.h b/Source/portable/IAR/ARM_CM33_NTZ/non_secure/portmacro.h
index df7888d..db025b5 100644
--- a/Source/portable/IAR/ARM_CM33_NTZ/non_secure/portmacro.h
+++ b/Source/portable/IAR/ARM_CM33_NTZ/non_secure/portmacro.h
@@ -1,6 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * Copyright 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -52,6 +53,7 @@
 #define portHAS_ARMV8M_MAIN_EXTENSION    1
 #define portARMV8M_MINOR_VERSION         0
 #define portDONT_DISCARD                 __root
+#define portVALIDATED_FOR_SMP            1
 /*-----------------------------------------------------------*/
 
 /* ARMv8-M common port configurations. */
diff --git a/Source/portable/IAR/ARM_CM33_NTZ/non_secure/portmacrocommon.h b/Source/portable/IAR/ARM_CM33_NTZ/non_secure/portmacrocommon.h
index 2dfac6a..c34fdee 100644
--- a/Source/portable/IAR/ARM_CM33_NTZ/non_secure/portmacrocommon.h
+++ b/Source/portable/IAR/ARM_CM33_NTZ/non_secure/portmacrocommon.h
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -59,6 +58,19 @@
     #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h.  Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
 #endif /* configENABLE_TRUSTZONE */
 
+#if ( configNUMBER_OF_CORES > 1 )
+    #if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 )
+        #error "Multi-core SMP is currently only validated for Cortex-M33 non-TrustZone non-MPU port."
+    #endif /* if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 ) ) */
+
+    #ifndef configCORE_ID_REGISTER
+        #error "configCORE_ID_REGISTER must be defined to the address of the register used to identify the core executing the code."
+    #endif /* ifndef configCORE_ID_REGISTER */
+
+    #ifndef configWAKE_SECONDARY_CORES
+        #error "configWAKE_SECONDARY_CORES must be defined to a function that wakes the secondary cores."
+    #endif /* ifndef configWAKE_SECONDARY_CORES */
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -428,10 +440,26 @@
 /**
  * @brief Critical section management.
  */
+
+#define portSET_INTERRUPT_MASK()                  ulSetInterruptMask()
+#define portCLEAR_INTERRUPT_MASK( x )             vClearInterruptMask( x )
 #define portSET_INTERRUPT_MASK_FROM_ISR()         ulSetInterruptMask()
 #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x )    vClearInterruptMask( x )
-#define portENTER_CRITICAL()                      vPortEnterCritical()
-#define portEXIT_CRITICAL()                       vPortExitCritical()
+
+#if ( configNUMBER_OF_CORES == 1 )
+    #define portENTER_CRITICAL()                      vPortEnterCritical()
+    #define portEXIT_CRITICAL()                       vPortExitCritical()
+#else /* ( configNUMBER_OF_CORES == 1 ) */
+    extern void vTaskEnterCritical( void );
+    extern void vTaskExitCritical( void );
+    extern UBaseType_t vTaskEnterCriticalFromISR( void );
+    extern void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus );
+
+    #define portENTER_CRITICAL()                      vTaskEnterCritical()
+    #define portEXIT_CRITICAL()                       vTaskExitCritical()
+    #define portENTER_CRITICAL_FROM_ISR()             vTaskEnterCriticalFromISR()
+    #define portEXIT_CRITICAL_FROM_ISR( x )           vTaskExitCriticalFromISR( x )
+#endif /* if ( configNUMBER_OF_CORES != 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -526,7 +554,7 @@
 /* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION
  * based on whether or not Mainline extension is implemented. */
 #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
-    #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 )
+    #if ( ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) && ( configNUMBER_OF_CORES == 1 ) )
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    1
     #else
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    0
@@ -573,6 +601,44 @@
 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
 /*-----------------------------------------------------------*/
 
+
+#if ( configNUMBER_OF_CORES > 1 )
+    typedef enum
+    {
+        eIsrLock = 0,
+        eTaskLock,
+        eLockCount
+    } ePortRTOSLock;
+
+    extern volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ];
+    extern void vPortRecursiveLock( uint8_t ucCoreID,
+                                    ePortRTOSLock eLockNum,
+                                    BaseType_t uxAcquire );
+    extern uint8_t ucPortGetCoreID( void );
+    extern void vInterruptCore( uint8_t ucCoreID );
+
+    #define portGET_CORE_ID()                                  ucPortGetCoreID()
+
+    #define portGET_CRITICAL_NESTING_COUNT( xCoreID )          ( ulCriticalNestings[ ( uint8_t ) xCoreID ] )
+    #define portSET_CRITICAL_NESTING_COUNT( xCoreID, x )       ( ulCriticalNestings[ ( uint8_t ) xCoreID ] = ( x ) )
+    #define portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]++ )
+    #define portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]-- )
+
+    #define portMAX_CORE_COUNT                                 ( configNUMBER_OF_CORES )
+
+    #define portYIELD_CORE( xCoreID )                          vInterruptCore( xCoreID )
+
+    #define portRELEASE_ISR_LOCK( xCoreID )                    vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdFALSE )
+    #define portGET_ISR_LOCK( xCoreID )                        vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdTRUE )
+
+    #define portRELEASE_TASK_LOCK( xCoreID )                   vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdFALSE )
+    #define portGET_TASK_LOCK( xCoreID )                       vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdTRUE )
+
+    #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* ( configENABLE_PAC == 1 || configENABLE_BTI == 1 ) */
+#endif
+
 /* *INDENT-OFF* */
 #ifdef __cplusplus
     }
diff --git a/Source/portable/IAR/ARM_CM4F/port.c b/Source/portable/IAR/ARM_CM4F/port.c
index a863cac..dfeed7a 100644
--- a/Source/portable/IAR/ARM_CM4F/port.c
+++ b/Source/portable/IAR/ARM_CM4F/port.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM4F/portasm.s b/Source/portable/IAR/ARM_CM4F/portasm.s
index 627b1bf..cb10f41 100644
--- a/Source/portable/IAR/ARM_CM4F/portasm.s
+++ b/Source/portable/IAR/ARM_CM4F/portasm.s
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM4F/portmacro.h b/Source/portable/IAR/ARM_CM4F/portmacro.h
index 2bc2281..9ad246e 100644
--- a/Source/portable/IAR/ARM_CM4F/portmacro.h
+++ b/Source/portable/IAR/ARM_CM4F/portmacro.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM4_MPU/mpu_wrappers_v2_asm.S b/Source/portable/IAR/ARM_CM4_MPU/mpu_wrappers_v2_asm.S
index 310636b..5fae1d3 100644
--- a/Source/portable/IAR/ARM_CM4_MPU/mpu_wrappers_v2_asm.S
+++ b/Source/portable/IAR/ARM_CM4_MPU/mpu_wrappers_v2_asm.S
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM4_MPU/port.c b/Source/portable/IAR/ARM_CM4_MPU/port.c
index 08125a2..ac761c4 100644
--- a/Source/portable/IAR/ARM_CM4_MPU/port.c
+++ b/Source/portable/IAR/ARM_CM4_MPU/port.c
@@ -1,6 +1,8 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * Copyright 2025 Arm Limited and/or its affiliates
+ * <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -64,9 +66,19 @@
     #define portNVIC_SYSTICK_CLK_BIT    ( 0 )
 #endif
 
+/* Unprivileged critical sections are not supported when using MPU wrappers
+ * version 2. Default the option to 0 and reject an explicit value of 1. */
 #ifndef configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS
-    #warning "configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS is not defined. We recommend defining it to 0 in FreeRTOSConfig.h for better security."
-    #define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS    1
+    #if ( configUSE_MPU_WRAPPERS_V1 == 0 )
+        #define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS    0
+    #else
+        #warning "configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS is not defined. We recommend defining it to 0 in FreeRTOSConfig.h for better security."
+        #define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS    1
+    #endif
+#else
+    #if ( ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) )
+        #error configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS is not supported with MPU wrappers version 2 ( configUSE_MPU_WRAPPERS_V1 == 0 ).
+    #endif
 #endif
 
 /* Prototype of all Interrupt Service Routines (ISRs). */
@@ -459,7 +471,7 @@
         extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulSystemCallStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
             /* Declaration when these variable are defined in code instead of being
@@ -494,10 +506,14 @@
         {
             pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
             {
                 /* Extended frame i.e. FPU in use. */
-                ulStackFrameSize = 26;
+                ulHardwareSavedExceptionFrameSize = 26;
                 __asm volatile (
                     " vpush {s0}         \n" /* Trigger lazy stacking. */
                     " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -507,14 +523,14 @@
             else
             {
                 /* Standard frame i.e. FPU not in use. */
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
 
             /* Make space on the system call stack for the stack frame. */
-            pulSystemCallStack = pulSystemCallStack - ulStackFrameSize;
+            pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulSystemCallStack[ i ] = pulTaskStack[ i ];
             }
@@ -532,7 +548,7 @@
 
             /* Remember the location where we should copy the stack frame when we exit from
              * the system call. */
-            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
+            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
 
             /* Store the value of the Link Register before the SVC was raised.
              * It contains the address of the caller of the System Call entry
@@ -586,7 +602,7 @@
         extern TaskHandle_t pxCurrentTCB;
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulTaskStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
             /* Declaration when these variable are defined in code instead of being
@@ -617,10 +633,14 @@
         {
             pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
             {
                 /* Extended frame i.e. FPU in use. */
-                ulStackFrameSize = 26;
+                ulHardwareSavedExceptionFrameSize = 26;
                 __asm volatile (
                     " vpush {s0}         \n" /* Trigger lazy stacking. */
                     " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -630,14 +650,14 @@
             else
             {
                 /* Standard frame i.e. FPU not in use. */
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
 
             /* Make space on the task stack for the stack frame. */
-            pulTaskStack = pulTaskStack - ulStackFrameSize;
+            pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulTaskStack[ i ] = pulSystemCallStack[ i ];
             }
@@ -1119,7 +1139,7 @@
     }
 
     /* Shift the code by one before returning so it can be written directly
-     * into the the correct bit position of the attribute register. */
+     * into the correct bit position of the attribute register. */
     return( ulReturnValue << 1UL );
 }
 /*-----------------------------------------------------------*/
diff --git a/Source/portable/IAR/ARM_CM4_MPU/portasm.s b/Source/portable/IAR/ARM_CM4_MPU/portasm.s
index 523422a..6fb8545 100644
--- a/Source/portable/IAR/ARM_CM4_MPU/portasm.s
+++ b/Source/portable/IAR/ARM_CM4_MPU/portasm.s
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM4_MPU/portmacro.h b/Source/portable/IAR/ARM_CM4_MPU/portmacro.h
index 12e35b6..dd77194 100644
--- a/Source/portable/IAR/ARM_CM4_MPU/portmacro.h
+++ b/Source/portable/IAR/ARM_CM4_MPU/portmacro.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM55/non_secure/mpu_wrappers_v2_asm.S b/Source/portable/IAR/ARM_CM55/non_secure/mpu_wrappers_v2_asm.S
index 68192e4..c8df7ec 100644
--- a/Source/portable/IAR/ARM_CM55/non_secure/mpu_wrappers_v2_asm.S
+++ b/Source/portable/IAR/ARM_CM55/non_secure/mpu_wrappers_v2_asm.S
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM55/non_secure/port.c b/Source/portable/IAR/ARM_CM55/non_secure/port.c
index f16a343..007150c 100644
--- a/Source/portable/IAR/ARM_CM55/non_secure/port.c
+++ b/Source/portable/IAR/ARM_CM55/non_secure/port.c
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024-2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -145,13 +144,13 @@
 /**
  * @brief Constants required to manipulate the FPU.
  */
-#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 )              /* Coprocessor Access Control Register. */
+#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */
 #define portCPACR_CP10_VALUE    ( 3UL )
 #define portCPACR_CP11_VALUE    portCPACR_CP10_VALUE
 #define portCPACR_CP10_POS      ( 20UL )
 #define portCPACR_CP11_POS      ( 22UL )
 
-#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 )              /* Floating Point Context Control Register. */
+#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
 #define portFPCCR_ASPEN_POS     ( 31UL )
 #define portFPCCR_ASPEN_MASK    ( 1UL << portFPCCR_ASPEN_POS )
 #define portFPCCR_LSPEN_POS     ( 30UL )
@@ -188,8 +187,8 @@
 #define portMPU_MAIR0_REG                       ( *( ( volatile uint32_t * ) 0xe000edc0 ) )
 #define portMPU_MAIR1_REG                       ( *( ( volatile uint32_t * ) 0xe000edc4 ) )
 
-#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
-#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
+#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
+#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
 
 #define portMPU_RBAR_ACCESS_PERMISSIONS_MASK    ( 3UL << 1UL )
 
@@ -230,8 +229,8 @@
 
 #if ( portARMV8M_MINOR_VERSION >= 1 )
 
-/* Enable Privileged eXecute Never MPU attribute for the selected memory
- * region. */
+    /* Enable Privileged eXecute Never MPU attribute for the selected memory
+     * region. */
     #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER    ( 1UL << 4UL )
 #endif /* portARMV8M_MINOR_VERSION >= 1 */
 
@@ -241,9 +240,6 @@
 /* Enable MPU. */
 #define portMPU_ENABLE_BIT                    ( 1UL << 0UL )
 
-/* Expected value of the portMPU_TYPE register. */
-#define portEXPECTED_MPU_TYPE_VALUE           ( configTOTAL_MPU_REGIONS << 8UL )
-
 /* Extract first address of the MPU region as encoded in the
  * RBAR (Region Base Address Register) value. */
 #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@@ -291,37 +287,37 @@
 
 #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         FD
- * 1111 1111  1111 1111  1111 1111  1111 1101
- *
- * Bit[6] - 1 --> The exception was taken from the Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 1 --> The exception was taken to the Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         FD
+     * 1111 1111  1111 1111  1111 1111  1111 1101
+     *
+     * Bit[6] - 1 --> The exception was taken from the Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 1 --> The exception was taken to the Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xfffffffd )
 #else
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         BC
- * 1111 1111  1111 1111  1111 1111  1011 1100
- *
- * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         BC
+     * 1111 1111  1111 1111  1111 1111  1011 1100
+     *
+     * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xffffffbc )
 #endif /* configRUN_FREERTOS_SECURE_ONLY */
 
@@ -401,50 +397,54 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Extract MPU region's access permissions from the Region Base Address
- * Register (RBAR) value.
- *
- * @param ulRBARValue RBAR value for the MPU region.
- *
- * @return uint32_t Access permissions.
- */
+    /**
+     * @brief Extract MPU region's access permissions from the Region Base Address
+     * Register (RBAR) value.
+     *
+     * @param ulRBARValue RBAR value for the MPU region.
+     *
+     * @return uint32_t Access permissions.
+     */
     static uint32_t prvGetRegionAccessPermissions( uint32_t ulRBARValue ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU == 1 && configUSE_MPU_WRAPPERS_V1 == 0 */
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Setup the Memory Protection Unit (MPU).
- */
+    /**
+     * @brief Setup the Memory Protection Unit (MPU).
+     */
     static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU */
 
 #if ( configENABLE_FPU == 1 )
 
-/**
- * @brief Setup the Floating Point Unit (FPU).
- */
+    /**
+     * @brief Setup the Floating Point Unit (FPU).
+     */
     static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_FPU */
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
 
-/**
- * @brief Configures PACBTI features.
- *
- * This function configures the Pointer Authentication, and Branch Target
- * Identification security features as per the user configuration. It returns
- * the value of the special purpose CONTROL register accordingly, and optionally
- * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
- * architecture based) target supports PACBTI security feature.
- *
- * @param xWriteControlRegister Used to control whether the special purpose
- * CONTROL register should be updated or not.
- *
- * @return CONTROL register value according to the configured PACBTI option.
- */
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    /**
+     * @brief Configures PACBTI features.
+     *
+     * This function configures the Pointer Authentication, and Branch Target
+     * Identification security features as per the user configuration. It returns
+     * the value of the special purpose CONTROL register accordingly, and optionally
+     * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
+     * architecture based) target supports PACBTI security feature.
+     *
+     * @param xWriteControlRegister Used to control whether the special purpose
+     * CONTROL register should be updated or not.
+     *
+     * @return CONTROL register value according to the configured PACBTI option.
+     */
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -491,14 +491,14 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the system call stack so that upon returning from
- * SVC, the system call stack is used.
- *
- * @param pulTaskStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- * @param ucSystemCallNumber The system call number of the system call.
- */
+    /**
+     * @brief Sets up the system call stack so that upon returning from
+     * SVC, the system call stack is used.
+     *
+     * @param pulTaskStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     * @param ucSystemCallNumber The system call number of the system call.
+     */
     void vSystemCallEnter( uint32_t * pulTaskStack,
                            uint32_t ulLR,
                            uint8_t ucSystemCallNumber ) PRIVILEGED_FUNCTION;
@@ -507,22 +507,22 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Raise SVC for exiting from a system call.
- */
+    /**
+     * @brief Raise SVC for exiting from a system call.
+     */
     void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the task stack so that upon returning from
- * SVC, the task stack is used again.
- *
- * @param pulSystemCallStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- */
+    /**
+     * @brief Sets up the task stack so that upon returning from
+     * SVC, the task stack is used again.
+     *
+     * @param pulSystemCallStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     */
     void vSystemCallExit( uint32_t * pulSystemCallStack,
                           uint32_t ulLR ) PRIVILEGED_FUNCTION;
 
@@ -530,21 +530,38 @@
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Checks whether or not the calling task is privileged.
- *
- * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
- */
+    /**
+     * @brief Checks whether or not the calling task is privileged.
+     *
+     * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
+     */
     BaseType_t xPortIsTaskPrivileged( void ) PRIVILEGED_FUNCTION;
 
 #endif /* configENABLE_MPU == 1 */
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /**
+     * @brief Platform/Application-defined function that wakes up the secondary cores.
+     *
+     * @return pdTRUE if the secondary cores were successfully woken up.
+     *         pdFALSE otherwise.
+     */
+    extern BaseType_t configWAKE_SECONDARY_CORES( void );
+
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
+
+/**
+ * @brief Configures interrupt priorities.
+ */
+void vPortConfigureInterruptPriorities( void ) PRIVILEGED_FUNCTION;
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief This variable is set to pdTRUE when the scheduler is started.
- */
+    /**
+     * @brief This variable is set to pdTRUE when the scheduler is started.
+     */
     PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
@@ -553,14 +570,22 @@
  * @brief Each task maintains its own interrupt status in the critical nesting
  * variable.
  */
-PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
+#if ( configNUMBER_OF_CORES == 1 )
+    PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0UL;
+#else /* #if ( configNUMBER_OF_CORES == 1 ) */
+    PRIVILEGED_DATA volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ] = { 0 };
+    /* Flags to check if the secondary cores are ready. */
+    PRIVILEGED_DATA volatile uint8_t ucSecondaryCoresReadyFlags[ configNUMBER_OF_CORES - 1 ] = { 0 };
+    /* Flag to indicate that the primary core has completed its initialisation. */
+    PRIVILEGED_DATA volatile uint8_t ucPrimaryCoreInitDoneFlag = 0;
+ #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #if ( configENABLE_TRUSTZONE == 1 )
 
-/**
- * @brief Saved as part of the task context to indicate which context the
- * task is using on the secure side.
- */
+    /**
+     * @brief Saved as part of the task context to indicate which context the
+     * task is using on the secure side.
+     */
     PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
 #endif /* configENABLE_TRUSTZONE */
 
@@ -579,21 +604,21 @@
 
 #if ( configUSE_TICKLESS_IDLE == 1 )
 
-/**
- * @brief The number of SysTick increments that make up one tick period.
- */
+    /**
+     * @brief The number of SysTick increments that make up one tick period.
+     */
     PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
 
-/**
- * @brief The maximum number of tick periods that can be suppressed is
- * limited by the 24 bit resolution of the SysTick timer.
- */
+    /**
+     * @brief The maximum number of tick periods that can be suppressed is
+     * limited by the 24 bit resolution of the SysTick timer.
+     */
     PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
 
-/**
- * @brief Compensate for the CPU cycles that pass while the SysTick is
- * stopped (low power functionality only).
- */
+    /**
+     * @brief Compensate for the CPU cycles that pass while the SysTick is
+     * stopped (low power functionality only).
+     */
     PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0;
 #endif /* configUSE_TICKLESS_IDLE */
 /*-----------------------------------------------------------*/
@@ -856,7 +881,11 @@
      * should instead call vTaskDelete( NULL ). Artificially force an assert()
      * to be triggered if configASSERT() is defined, then stop here so
      * application writers can catch the error. */
-    configASSERT( ulCriticalNesting == ~0UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == ~0UL );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == ~0UL );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
     portDISABLE_INTERRUPTS();
 
     while( ulDummy == 0 )
@@ -925,64 +954,57 @@
         /* The only permitted number of regions are 8 or 16. */
         configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 16 ) );
 
-        /* Ensure that the configTOTAL_MPU_REGIONS is configured correctly. */
-        configASSERT( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE );
+        /* MAIR0 - Index 0. */
+        portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
+        /* MAIR0 - Index 1. */
+        portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
 
-        /* Check that the MPU is present. */
-        if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
-        {
-            /* MAIR0 - Index 0. */
-            portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
-            /* MAIR0 - Index 1. */
-            portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
+        /* Setup privileged flash as Read Only so that privileged tasks can
+         * read it but not modify. */
+        portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup privileged flash as Read Only so that privileged tasks can
-             * read it but not modify. */
-            portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged flash as Read Only by both privileged and
+         * unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged flash as Read Only by both privileged and
-             * unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged syscalls flash as Read Only by both privileged
+         * and unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged syscalls flash as Read Only by both privileged
-             * and unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup RAM containing kernel data for privileged access only. */
+        portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
+                           ( portMPU_REGION_EXECUTE_NEVER );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup RAM containing kernel data for privileged access only. */
-            portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
-                               ( portMPU_REGION_EXECUTE_NEVER );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Enable mem fault. */
+        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
 
-            /* Enable mem fault. */
-            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
-
-            /* Enable MPU with privileged background access i.e. unmapped
-             * regions have privileged access. */
-            portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
-        }
+        /* Enable MPU with privileged background access i.e. unmapped
+         * regions have privileged access. */
+        portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
     }
 
 #endif /* configENABLE_MPU */
@@ -1027,28 +1049,29 @@
 }
 /*-----------------------------------------------------------*/
 
-void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    portDISABLE_INTERRUPTS();
-    ulCriticalNesting++;
-
-    /* Barriers are normally not required but do ensure the code is
-     * completely within the specified behaviour for the architecture. */
-    __asm volatile ( "dsb" ::: "memory" );
-    __asm volatile ( "isb" );
-}
-/*-----------------------------------------------------------*/
-
-void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    configASSERT( ulCriticalNesting );
-    ulCriticalNesting--;
-
-    if( ulCriticalNesting == 0 )
+#if ( configNUMBER_OF_CORES == 1 )
+    void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
     {
-        portENABLE_INTERRUPTS();
+        portDISABLE_INTERRUPTS();
+        ulCriticalNesting++;
+        /* Barriers are normally not required but do ensure the code is
+        * completely within the specified behaviour for the architecture. */
+        __asm volatile ( "dsb" ::: "memory" );
+        __asm volatile ( "isb" );
     }
-}
+    /*-----------------------------------------------------------*/
+
+    void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
+    {
+        configASSERT( ulCriticalNesting );
+        ulCriticalNesting--;
+
+        if( ulCriticalNesting == 0 )
+        {
+            portENABLE_INTERRUPTS();
+        }
+    }
+#endif /* configNUMBER_OF_CORES == 1 */
 /*-----------------------------------------------------------*/
 
 void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
@@ -1056,6 +1079,10 @@
     uint32_t ulPreviousMask;
 
     ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
+    #if ( configNUMBER_OF_CORES > 1 )
+        UBaseType_t uxSavedInterruptStatus = portENTER_CRITICAL_FROM_ISR();
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     traceISR_ENTER();
     {
         /* Increment the RTOS tick. */
@@ -1070,6 +1097,10 @@
             traceISR_EXIT();
         }
     }
+    #if ( configNUMBER_OF_CORES > 1 )
+        portEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
 }
 /*-----------------------------------------------------------*/
@@ -1078,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1090,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1108,38 +1151,42 @@
 
     switch( ucSVCNumber )
     {
-        #if ( configENABLE_TRUSTZONE == 1 )
-            case portSVC_ALLOCATE_SECURE_CONTEXT:
+    #if ( configENABLE_TRUSTZONE == 1 )
+        case portSVC_ALLOCATE_SECURE_CONTEXT:
 
-                /* R0 contains the stack size passed as parameter to the
-                 * vPortAllocateSecureContext function. */
-                ulR0 = pulCallerStackAddress[ 0 ];
+            /* R0 contains the stack size passed as parameter to the
+             * vPortAllocateSecureContext function. */
+            ulR0 = pulCallerStackAddress[ 0 ];
 
-                #if ( configENABLE_MPU == 1 )
-                {
-                    /* Read the CONTROL register value. */
-                    __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
+            #if ( configENABLE_MPU == 1 )
+            {
+                /* Read the CONTROL register value. */
+                __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
 
-                    /* The task that raised the SVC is privileged if Bit[0]
-                     * in the CONTROL register is 0. */
-                    ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
+                /* The task that raised the SVC is privileged if Bit[0]
+                 * in the CONTROL register is 0. */
+                ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
 
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
-                }
-                #else /* if ( configENABLE_MPU == 1 ) */
-                {
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
-                }
-                #endif /* configENABLE_MPU */
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
+            }
+            #else /* if ( configENABLE_MPU == 1 ) */
+            {
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
+            }
+            #endif /* configENABLE_MPU */
 
-                configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
-                SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
-                break;
+            configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
+            SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
+            break;
 
-            case portSVC_FREE_SECURE_CONTEXT:
-
+        case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
                 /* R0 contains TCB being freed and R1 contains the secure
                  * context handle to be freed. */
                 ulR0 = pulCallerStackAddress[ 0 ];
@@ -1147,51 +1194,62 @@
 
                 /* Free the secure context. */
                 SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
-                break;
-        #endif /* configENABLE_TRUSTZONE */
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
+            break;
+    #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
-            #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
-                case portSVC_RAISE_PRIVILEGE:
+    #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
+        case portSVC_RAISE_PRIVILEGE:
 
-                    /* Only raise the privilege, if the svc was raised from any of
-                     * the system calls. */
-                    if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
-                        ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
-                    {
-                        vRaisePrivilege();
-                    }
-                    break;
-            #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
+            /* Only raise the privilege, if the svc was raised from any of
+             * the system calls. */
+            if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
+                ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
+            {
+                vRaisePrivilege();
+            }
+            break;
+    #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
-            #if ( configENABLE_MPU == 1 )
-                case portSVC_YIELD:
-                    vPortYield();
-                    break;
-            #endif /* configENABLE_MPU == 1 */
+    #if ( configENABLE_MPU == 1 )
+        case portSVC_YIELD:
+            vPortYield();
+            break;
+    #endif /* configENABLE_MPU == 1 */
 
         default:
             /* Incorrect SVC call. */
@@ -1210,7 +1268,7 @@
         extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulSystemCallStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1246,12 +1304,16 @@
         {
             pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1261,20 +1323,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the system call stack for the stack frame. */
-            pulSystemCallStack = pulSystemCallStack - ulStackFrameSize;
+            pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulSystemCallStack[ i ] = pulTaskStack[ i ];
             }
@@ -1310,7 +1372,7 @@
 
             /* Remember the location where we should copy the stack frame when we exit from
              * the system call. */
-            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
+            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
 
             /* Record if the hardware used padding to force the stack pointer
              * to be double word aligned. */
@@ -1360,7 +1422,7 @@
         extern TaskHandle_t pxCurrentTCB;
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulTaskStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1392,12 +1454,16 @@
         {
             pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1407,20 +1473,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the task stack for the stack frame. */
-            pulTaskStack = pulTaskStack - ulStackFrameSize;
+            pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulTaskStack[ i ] = pulSystemCallStack[ i ];
             }
@@ -1518,21 +1584,21 @@
         xMPUSettings->ulContext[ ulIndex ] = 0x11111111; /* r11. */
         ulIndex++;
 
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters;            /* r0. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters; /* r0. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x01010101;                           /* r1. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x01010101; /* r1. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x02020202;                           /* r2. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x02020202; /* r2. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x03030303;                           /* r3. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x03030303; /* r3. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x12121212;                           /* r12. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x12121212; /* r12. */
         ulIndex++;
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) portTASK_RETURN_ADDRESS; /* LR. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode;                  /* PC. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode; /* PC. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR;                     /* xPSR. */
+        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR; /* xPSR. */
         ulIndex++;
 
         #if ( configENABLE_TRUSTZONE == 1 )
@@ -1543,14 +1609,18 @@
         #endif /* configENABLE_TRUSTZONE */
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) ( pxTopOfStack - 8 ); /* PSP with the hardware saved stack. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack;         /* PSPLIM. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack; /* PSPLIM. */
         ulIndex++;
 
         #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
         {
             /* Check PACBTI security feature configuration before pushing the
              * CONTROL register's value on task's TCB. */
-            ulControl = prvConfigurePACBTI( pdFALSE );
+            #if ( configNUMBER_OF_CORES == 1 )
+                ulControl = prvConfigurePACBTI( pdFALSE );
+            #else /* configNUMBER_OF_CORES > 1 */
+                ulControl = vConfigurePACBTI( pdFALSE );
+            #endif /* configNUMBER_OF_CORES */
         }
         #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1615,15 +1685,15 @@
          * interrupt. */
         #if ( portPRELOAD_REGISTERS == 0 )
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
-            pxTopOfStack -= 5;                                       /* R12, R3, R2 and R1. */
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
-            pxTopOfStack -= 9;                                       /* R11..R4, EXC_RETURN. */
+            pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
+            pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */
             *pxTopOfStack = portINITIAL_EXC_RETURN;
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
@@ -1637,42 +1707,42 @@
         }
         #else /* portPRELOAD_REGISTERS */
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x12121212UL;            /* R12. */
+            *pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x03030303UL;            /* R3. */
+            *pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x02020202UL;            /* R2. */
+            *pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x01010101UL;            /* R1. */
+            *pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x11111111UL;            /* R11. */
+            *pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x10101010UL;            /* R10. */
+            *pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x09090909UL;            /* R09. */
+            *pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x08080808UL;            /* R08. */
+            *pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x07070707UL;            /* R07. */
+            *pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x06060606UL;            /* R06. */
+            *pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x05050505UL;            /* R05. */
+            *pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x04040404UL;            /* R04. */
+            *pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04. */
             pxTopOfStack--;
-            *pxTopOfStack = portINITIAL_EXC_RETURN;                  /* EXC_RETURN. */
+            *pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxEndOfStack;            /* Slot used to hold this task's PSPLIM value. */
+            *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
 
             #if ( configENABLE_TRUSTZONE == 1 )
             {
@@ -1739,91 +1809,17 @@
     }
     #endif /* configCHECK_HANDLER_INSTALLATION */
 
-    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
-    {
-        volatile uint32_t ulImplementedPrioBits = 0;
-        volatile uint8_t ucMaxPriorityValue;
-
-        /* Determine the maximum priority from which ISR safe FreeRTOS API
-         * functions can be called. ISR safe functions are those that end in
-         * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
-         * ensure interrupt entry is as fast and simple as possible.
-         *
-         * First, determine the number of priority bits available. Write to all
-         * possible bits in the priority setting for SVCall. */
-        portNVIC_SHPR2_REG = 0xFF000000;
-
-        /* Read the value back to see how many bits stuck. */
-        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
-
-        /* Use the same mask on the maximum system call priority. */
-        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
-
-        /* Check that the maximum system call priority is nonzero after
-         * accounting for the number of priority bits supported by the
-         * hardware. A priority of 0 is invalid because setting the BASEPRI
-         * register to 0 unmasks all interrupts, and interrupts with priority 0
-         * cannot be masked using BASEPRI.
-         * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
-        configASSERT( ucMaxSysCallPriority );
-
-        /* Check that the bits not implemented in hardware are zero in
-         * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
-        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
-
-        /* Calculate the maximum acceptable priority group value for the number
-         * of bits read back. */
-        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
-        {
-            ulImplementedPrioBits++;
-            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
-        }
-
-        if( ulImplementedPrioBits == 8 )
-        {
-            /* When the hardware implements 8 priority bits, there is no way for
-             * the software to configure PRIGROUP to not have sub-priorities. As
-             * a result, the least significant bit is always used for sub-priority
-             * and there are 128 preemption priorities and 2 sub-priorities.
-             *
-             * This may cause some confusion in some cases - for example, if
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
-             * priority interrupts will be masked in Critical Sections as those
-             * are at the same preemption priority. This may appear confusing as
-             * 4 is higher (numerically lower) priority than
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
-             * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
-             * to 4, this confusion does not happen and the behaviour remains the same.
-             *
-             * The following assert ensures that the sub-priority bit in the
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
-             * confusion. */
-            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
-            ulMaxPRIGROUPValue = 0;
-        }
-        else
-        {
-            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
-        }
-
-        /* Shift the priority group value back to its position within the AIRCR
-         * register. */
-        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
-        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
-    }
-    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
-
-    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
-     * the highest priority. */
-    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
-    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
-    portNVIC_SHPR2_REG = 0;
+    vPortConfigureInterruptPriorities();
 
     #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
     {
         /* Set the CONTROL register value based on PACBTI security feature
          * configuration before starting the first task. */
-        ( void ) prvConfigurePACBTI( pdTRUE );
+        #if ( configNUMBER_OF_CORES == 1 )
+            ( void ) prvConfigurePACBTI( pdTRUE );
+        #else /* configNUMBER_OF_CORES > 1 */
+            ( void ) vConfigurePACBTI( pdTRUE );
+        #endif /* configNUMBER_OF_CORES */
     }
     #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1834,12 +1830,47 @@
     }
     #endif /* configENABLE_MPU */
 
-    /* Start the timer that generates the tick ISR. Interrupts are disabled
-     * here already. */
-    vPortSetupTimerInterrupt();
+    #if ( configNUMBER_OF_CORES > 1 )
+        /* Start the timer that generates the tick ISR. Interrupts are disabled
+         * here already. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count for all cores. */
+        for ( uint8_t ucCoreID = 0; ucCoreID < configNUMBER_OF_CORES; ucCoreID++ )
+        {
+            ulCriticalNestings[ ucCoreID ] = 0;
+        }
+        /* Signal that primary core has done all the necessary initialisations. */
+        ucPrimaryCoreInitDoneFlag = 1;
+        /* Wake up secondary cores */
+        BaseType_t xWakeResult = configWAKE_SECONDARY_CORES();
+        configASSERT( xWakeResult == pdTRUE );
 
-    /* Initialize the critical nesting count ready for the first task. */
-    ulCriticalNesting = 0;
+        /* Hold the primary core here until all the secondary cores are ready, this would be achieved only when
+         * all elements of ucSecondaryCoresReadyFlags are set.
+         */
+        while( 1 )
+        {
+            BaseType_t xAllCoresReady = pdTRUE;
+            for( uint8_t ucCoreID = 0; ucCoreID < ( configNUMBER_OF_CORES - 1 ); ucCoreID++ )
+            {
+                if( ucSecondaryCoresReadyFlags[ ucCoreID ] != pdTRUE )
+                {
+                    xAllCoresReady = pdFALSE;
+                    break;
+                }
+                }
+
+            if ( xAllCoresReady == pdTRUE )
+            {
+                break;
+            }
+        }
+    #else /* if ( configNUMBER_OF_CORES > 1 ) */
+        /* Start the timer that generates the tick ISR. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count ready for the first task. */
+        ulCriticalNesting = 0;
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
     {
@@ -1856,7 +1887,11 @@
      * functionality by defining configTASK_RETURN_ADDRESS. Call
      * vTaskSwitchContext() so link time optimization does not remove the
      * symbol. */
-    vTaskSwitchContext();
+    #if ( configNUMBER_OF_CORES > 1 )
+        vTaskSwitchContext( portGET_CORE_ID() );
+    #else
+        vTaskSwitchContext();
+    #endif
     prvTaskExitError();
 
     /* Should not get here. */
@@ -1868,7 +1903,11 @@
 {
     /* Not implemented in ports where there is nothing to return to.
      * Artificially force an assert. */
-    configASSERT( ulCriticalNesting == 1000UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == 1000UL );
+    #else /* if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == 1000UL );
+    #endif /* if ( configNUMBER_OF_CORES == 1 ) */
 }
 /*-----------------------------------------------------------*/
 
@@ -2151,6 +2190,90 @@
 #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
 /*-----------------------------------------------------------*/
 
+void vPortConfigureInterruptPriorities( void ) /* PRIVILEGED_FUNCTION */
+{
+    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
+    {
+        volatile uint32_t ulImplementedPrioBits = 0;
+        volatile uint8_t ucMaxPriorityValue;
+
+        /* Determine the maximum priority from which ISR safe FreeRTOS API
+        * functions can be called. ISR safe functions are those that end in
+        * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
+        * ensure interrupt entry is as fast and simple as possible.
+        *
+        * First, determine the number of priority bits available. Write to all
+        * possible bits in the priority setting for SVCall. */
+        portNVIC_SHPR2_REG = 0xFF000000;
+
+        /* Read the value back to see how many bits stuck. */
+        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
+
+        /* Use the same mask on the maximum system call priority. */
+        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
+
+        /* Check that the maximum system call priority is nonzero after
+        * accounting for the number of priority bits supported by the
+        * hardware. A priority of 0 is invalid because setting the BASEPRI
+        * register to 0 unmasks all interrupts, and interrupts with priority 0
+        * cannot be masked using BASEPRI.
+        * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+        configASSERT( ucMaxSysCallPriority );
+
+        /* Check that the bits not implemented in hardware are zero in
+        * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
+        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
+
+        /* Calculate the maximum acceptable priority group value for the number
+        * of bits read back. */
+        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
+        {
+            ulImplementedPrioBits++;
+            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
+        }
+
+        if( ulImplementedPrioBits == 8 )
+        {
+            /* When the hardware implements 8 priority bits, there is no way for
+            * the software to configure PRIGROUP to not have sub-priorities. As
+            * a result, the least significant bit is always used for sub-priority
+            * and there are 128 preemption priorities and 2 sub-priorities.
+            *
+            * This may cause some confusion in some cases - for example, if
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
+            * priority interrupts will be masked in Critical Sections as those
+            * are at the same preemption priority. This may appear confusing as
+            * 4 is higher (numerically lower) priority than
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
+            * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
+            * to 4, this confusion does not happen and the behaviour remains the same.
+            *
+            * The following assert ensures that the sub-priority bit in the
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
+            * confusion. */
+            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
+            ulMaxPRIGROUPValue = 0;
+        }
+        else
+        {
+            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
+        }
+
+        /* Shift the priority group value back to its position within the AIRCR
+        * register. */
+        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
+        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
+    }
+    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
+
+    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
+    * the highest priority. */
+    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
+    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
+    portNVIC_SHPR2_REG = 0;
+}
+/*-----------------------------------------------------------*/
+
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) )
 
     void vPortGrantAccessToKernelObject( TaskHandle_t xInternalTaskHandle,
@@ -2247,36 +2370,214 @@
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
-
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
-    {
-        uint32_t ulControl = 0x0;
-
-        /* Ensure that PACBTI is implemented. */
-        configASSERT( portID_ISAR5_REG != 0x0 );
-
-        /* Enable UsageFault exception. */
-        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
-
-        #if ( configENABLE_PAC == 1 )
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #else /* configNUMBER_OF_CORES > 1 */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #endif /* configNUMBER_OF_CORES */
         {
-            ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
-        }
-        #endif
+            uint32_t ulControl = 0x0;
 
-        #if ( configENABLE_BTI == 1 )
-        {
-            ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
-        }
-        #endif
+            /* Ensure that PACBTI is implemented. */
+            configASSERT( portID_ISAR5_REG != 0x0 );
 
-        if( xWriteControlRegister == pdTRUE )
-        {
-            __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
-        }
+            /* Enable UsageFault exception. */
+            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
 
-        return ulControl;
-    }
+            #if ( configENABLE_PAC == 1 )
+            {
+                ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
+            }
+            #endif
+
+            #if ( configENABLE_BTI == 1 )
+            {
+                ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
+            }
+            #endif
+
+            if( xWriteControlRegister == pdTRUE )
+            {
+                __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
+            }
+
+            return ulControl;
+        }
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 /*-----------------------------------------------------------*/
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /* Which core owns the lock? */
+    PRIVILEGED_DATA volatile uint32_t ulOwnedByCore[ portMAX_CORE_COUNT ];
+    /* Lock count a core owns. */
+    PRIVILEGED_DATA volatile uint32_t ulRecursionCountByLock[ eLockCount ];
+    /* Index 0 is used for ISR lock and Index 1 is used for task lock. */
+    PRIVILEGED_DATA volatile uint32_t ulGateWord[ eLockCount ];
+
+    __attribute__((weak)) void vInterruptCore( uint8_t ucCoreID )
+    {
+        /* Default weak stub - platform specific implementation may override. */
+        ( void ) ucCoreID;
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline void prvSpinUnlock( volatile uint32_t * ulLock )
+    {
+        /* Conservative unlock: preserve original barriers for broad HW/FVP. */
+        __asm volatile (
+            "dmb sy         \n"
+            "mov r1, #0     \n"
+            "str r1, [%0]   \n"
+            "sev            \n"
+            "dsb            \n"
+            "isb            \n"
+            :
+            : "r" ( ulLock )
+            : "memory", "r1"
+        );
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline uint32_t prvSpinTrylock( volatile uint32_t * ulLock )
+    {
+        /*
+         * Conservative ldrex/strex trylock:
+         * - Return 1 immediately if busy, clearing exclusive state (CLREX).
+         * - Retry strex only on spurious failure when observed free.
+         * - DMB on success to preserve expected acquire semantics.
+         */
+        uint32_t ulVal;
+        uint32_t ulStatus;
+
+        __asm volatile (
+            " ldrex %0, [%1]   \n"
+            : "=r" ( ulVal )
+            : "r" ( ulLock )
+            : "memory"
+        );
+
+        if( ulVal != 0U )
+        {
+            __asm volatile ("clrex" ::: "memory");
+            return 1U;
+        }
+
+        __asm volatile (
+            " strex %0, %2, [%1]   \n"
+            : "=&r" ( ulStatus )
+            : "r" ( ulLock ), "r" (1U)
+            : "memory"
+        );
+
+        if( ulStatus != 0U )
+        {
+            return 1U;
+        }
+        __asm volatile ( "dmb" ::: "memory" );
+        return 0U;
+    }
+
+
+/*-----------------------------------------------------------*/
+
+    /* Read 32b value shared between cores. */
+    static inline uint32_t prvGet32( volatile uint32_t * x )
+    {
+        __asm( "dsb" );
+        return *x;
+    }
+
+/*-----------------------------------------------------------*/
+
+    /* Write 32b value shared between cores. */
+    static inline void prvSet32( volatile uint32_t * x,
+                                 uint32_t value )
+    {
+        *x = value;
+        __asm( "dsb" );
+    }
+
+/*-----------------------------------------------------------*/
+
+    void vPortRecursiveLock( uint8_t ucCoreID,
+                             ePortRTOSLock eLockNum,
+                             BaseType_t uxAcquire )
+    {
+        /* Validate the core ID and lock number. */
+        configASSERT( ucCoreID < portMAX_CORE_COUNT );
+        configASSERT( eLockNum < eLockCount );
+
+        uint32_t ulLockBit = 1u << eLockNum;
+
+        /* Lock acquire */
+        if( uxAcquire )
+        {
+            /* Check if spinlock is available. */
+            /* If spinlock is not available check if the core owns the lock. */
+            /* If the core owns the lock wait increment the lock count by the core. */
+            /* If core does not own the lock wait for the spinlock. */
+            if( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+            {
+                /* Check if the core owns the spinlock. */
+                if( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit )
+                {
+                    configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != portUINT32_MAX );
+                    prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) + 1 ) );
+                    return;
+                }
+
+                /* Preload the gate word into the cache. */
+                uint32_t dummy = ulGateWord[ eLockNum ];
+                dummy++;
+
+                while( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+                {
+                    __asm volatile ( "wfe" );
+                }
+            }
+
+            /* Add barrier to ensure lock is taken before we proceed. */
+            __asm volatile( "dmb sy" ::: "memory" );
+
+            /* Assert the lock count is 0 when the spinlock is free and is acquired. */
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) == 0 );
+
+            /* Set lock count as 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], 1 );
+            /* Set ulOwnedByCore. */
+            prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) | ulLockBit ) );
+        }
+        /* Lock release. */
+        else
+        {
+            /* Assert the lock is not free already. */
+            configASSERT( ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit ) != 0 );
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != 0 );
+
+            /* Reduce ulRecursionCountByLock by 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) - 1 ) );
+
+            if( !prvGet32( &ulRecursionCountByLock[ eLockNum ] ) )
+            {
+                prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ~ulLockBit ) );
+                prvSpinUnlock( &ulGateWord[ eLockNum ] );
+                /* Add barrier to ensure lock status is reflected before we proceed. */
+                __asm volatile( "dmb sy" ::: "memory" );
+            }
+        }
+    }
+
+/*-----------------------------------------------------------*/
+
+    uint8_t ucPortGetCoreID( void )
+    {
+        return *(volatile uint8_t *)(configCORE_ID_REGISTER);
+    }
+
+/*-----------------------------------------------------------*/
+
+#endif /* if( configNUMBER_OF_CORES > 1 ) */
diff --git a/Source/portable/IAR/ARM_CM55/non_secure/portasm.h b/Source/portable/IAR/ARM_CM55/non_secure/portasm.h
index 53b4b6e..b4b545f 100644
--- a/Source/portable/IAR/ARM_CM55/non_secure/portasm.h
+++ b/Source/portable/IAR/ARM_CM55/non_secure/portasm.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM55/non_secure/portasm.s b/Source/portable/IAR/ARM_CM55/non_secure/portasm.s
index b5c91e5..c31d9ed 100644
--- a/Source/portable/IAR/ARM_CM55/non_secure/portasm.s
+++ b/Source/portable/IAR/ARM_CM55/non_secure/portasm.s
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  * Copyright 2024 Arm Limited and/or its affiliates
  * <open-source-office@arm.com>
@@ -41,6 +41,16 @@
     #define configUSE_MPU_WRAPPERS_V1 0
 #endif
 
+#if ( configENABLE_MPU == 1 )
+    #if ( configENABLE_PAC == 1 )
+        #define SECURE_CONTEXT_OFFSET   -36
+    #else
+        #define SECURE_CONTEXT_OFFSET   -20
+    #endif
+#else
+    #define SECURE_CONTEXT_OFFSET       0
+#endif
+
     EXTERN pxCurrentTCB
     EXTERN xSecureContext
     EXTERN vTaskSwitchContext
@@ -532,8 +542,8 @@
 
 vPortFreeSecureContext:
     /* r0 = uint32_t *pulTCB. */
-    ldr r2, [r0]                            /* The first item in the TCB is the top of the stack. */
-    ldr r1, [r2]                            /* The first item on the stack is the task's xSecureContext. */
+    ldr r2, [r0]                            /* The first item in the TCB is the stored context location. */
+    ldr r1, [r2, #SECURE_CONTEXT_OFFSET]    /* Read xSecureContext from the task's context. */
     cmp r1, #0                              /* Raise svc if task's xSecureContext is not NULL. */
     it ne
     svcne 101                               /* Secure context is freed in the supervisor call. portSVC_FREE_SECURE_CONTEXT = 101. */
diff --git a/Source/portable/IAR/ARM_CM55/non_secure/portmacro.h b/Source/portable/IAR/ARM_CM55/non_secure/portmacro.h
index 0526455..0a4d223 100644
--- a/Source/portable/IAR/ARM_CM55/non_secure/portmacro.h
+++ b/Source/portable/IAR/ARM_CM55/non_secure/portmacro.h
@@ -1,6 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * Copyright 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -57,6 +58,7 @@
 #define portHAS_ARMV8M_MAIN_EXTENSION    1
 #define portARMV8M_MINOR_VERSION         1
 #define portDONT_DISCARD                 __root
+#define portVALIDATED_FOR_SMP            0
 /*-----------------------------------------------------------*/
 
 /* ARMv8-M common port configurations. */
diff --git a/Source/portable/IAR/ARM_CM55/non_secure/portmacrocommon.h b/Source/portable/IAR/ARM_CM55/non_secure/portmacrocommon.h
index 2dfac6a..c34fdee 100644
--- a/Source/portable/IAR/ARM_CM55/non_secure/portmacrocommon.h
+++ b/Source/portable/IAR/ARM_CM55/non_secure/portmacrocommon.h
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -59,6 +58,19 @@
     #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h.  Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
 #endif /* configENABLE_TRUSTZONE */
 
+#if ( configNUMBER_OF_CORES > 1 )
+    #if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 )
+        #error "Multi-core SMP is currently only validated for Cortex-M33 non-TrustZone non-MPU port."
+    #endif /* if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 ) ) */
+
+    #ifndef configCORE_ID_REGISTER
+        #error "configCORE_ID_REGISTER must be defined to the address of the register used to identify the core executing the code."
+    #endif /* ifndef configCORE_ID_REGISTER */
+
+    #ifndef configWAKE_SECONDARY_CORES
+        #error "configWAKE_SECONDARY_CORES must be defined to a function that wakes the secondary cores."
+    #endif /* ifndef configWAKE_SECONDARY_CORES */
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -428,10 +440,26 @@
 /**
  * @brief Critical section management.
  */
+
+#define portSET_INTERRUPT_MASK()                  ulSetInterruptMask()
+#define portCLEAR_INTERRUPT_MASK( x )             vClearInterruptMask( x )
 #define portSET_INTERRUPT_MASK_FROM_ISR()         ulSetInterruptMask()
 #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x )    vClearInterruptMask( x )
-#define portENTER_CRITICAL()                      vPortEnterCritical()
-#define portEXIT_CRITICAL()                       vPortExitCritical()
+
+#if ( configNUMBER_OF_CORES == 1 )
+    #define portENTER_CRITICAL()                      vPortEnterCritical()
+    #define portEXIT_CRITICAL()                       vPortExitCritical()
+#else /* ( configNUMBER_OF_CORES == 1 ) */
+    extern void vTaskEnterCritical( void );
+    extern void vTaskExitCritical( void );
+    extern UBaseType_t vTaskEnterCriticalFromISR( void );
+    extern void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus );
+
+    #define portENTER_CRITICAL()                      vTaskEnterCritical()
+    #define portEXIT_CRITICAL()                       vTaskExitCritical()
+    #define portENTER_CRITICAL_FROM_ISR()             vTaskEnterCriticalFromISR()
+    #define portEXIT_CRITICAL_FROM_ISR( x )           vTaskExitCriticalFromISR( x )
+#endif /* if ( configNUMBER_OF_CORES != 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -526,7 +554,7 @@
 /* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION
  * based on whether or not Mainline extension is implemented. */
 #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
-    #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 )
+    #if ( ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) && ( configNUMBER_OF_CORES == 1 ) )
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    1
     #else
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    0
@@ -573,6 +601,44 @@
 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
 /*-----------------------------------------------------------*/
 
+
+#if ( configNUMBER_OF_CORES > 1 )
+    typedef enum
+    {
+        eIsrLock = 0,
+        eTaskLock,
+        eLockCount
+    } ePortRTOSLock;
+
+    extern volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ];
+    extern void vPortRecursiveLock( uint8_t ucCoreID,
+                                    ePortRTOSLock eLockNum,
+                                    BaseType_t uxAcquire );
+    extern uint8_t ucPortGetCoreID( void );
+    extern void vInterruptCore( uint8_t ucCoreID );
+
+    #define portGET_CORE_ID()                                  ucPortGetCoreID()
+
+    #define portGET_CRITICAL_NESTING_COUNT( xCoreID )          ( ulCriticalNestings[ ( uint8_t ) xCoreID ] )
+    #define portSET_CRITICAL_NESTING_COUNT( xCoreID, x )       ( ulCriticalNestings[ ( uint8_t ) xCoreID ] = ( x ) )
+    #define portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]++ )
+    #define portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]-- )
+
+    #define portMAX_CORE_COUNT                                 ( configNUMBER_OF_CORES )
+
+    #define portYIELD_CORE( xCoreID )                          vInterruptCore( xCoreID )
+
+    #define portRELEASE_ISR_LOCK( xCoreID )                    vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdFALSE )
+    #define portGET_ISR_LOCK( xCoreID )                        vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdTRUE )
+
+    #define portRELEASE_TASK_LOCK( xCoreID )                   vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdFALSE )
+    #define portGET_TASK_LOCK( xCoreID )                       vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdTRUE )
+
+    #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* ( configENABLE_PAC == 1 || configENABLE_BTI == 1 ) */
+#endif
+
 /* *INDENT-OFF* */
 #ifdef __cplusplus
     }
diff --git a/Source/portable/IAR/ARM_CM55/secure/secure_context.c b/Source/portable/IAR/ARM_CM55/secure/secure_context.c
index 62bcfa1..2dae022 100644
--- a/Source/portable/IAR/ARM_CM55/secure/secure_context.c
+++ b/Source/portable/IAR/ARM_CM55/secure/secure_context.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -213,8 +213,19 @@
         /* Were we able to get a free context? */
         if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS )
         {
-            /* Allocate the stack space. */
-            pucStackMemory = pvPortMalloc( ulSecureStackSize + securecontextSTACK_SEAL_SIZE );
+            /* Allocate the stack space if possible. */
+            if( ( ulSecureStackSize < securecontextSTACK_SEAL_SIZE ) ||
+                ( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) )
+            {
+                /* Reject stacks that are too small (the CONTROL word would be
+                 * written before the allocation, corrupting the secure heap)
+                 * and sizes that would overflow when the seal size is added. */
+                pucStackMemory = NULL;
+            }
+            else
+            {
+                pucStackMemory = pvPortMalloc( ulSecureStackSize + securecontextSTACK_SEAL_SIZE );
+            }
 
             if( pucStackMemory != NULL )
             {
@@ -279,9 +290,12 @@
                                                               void * pvTaskHandle )
 {
     uint32_t ulIPSR, ulSecureContextIndex;
+    uint8_t * pucStackLimit;
 
-    /* Read the Interrupt Program Status Register (IPSR) value. */
+    /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
+     * Register (PSPLIM) value. */
     secureportREAD_IPSR( ulIPSR );
+    secureportREAD_PSPLIM( pucStackLimit );
 
     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
      * when the processor is running in the Thread Mode. */
@@ -293,8 +307,14 @@
             ulSecureContextIndex = xSecureContextHandle - 1UL;
 
             /* Ensure that the secure context being deleted is associated with
-             * the task. */
-            if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
+             * the task and is NOT the currently-loaded context. Freeing a
+             * context whose stack is currently loaded in PSPLIM would leave the
+             * running task referencing freed secure memory (use-after-free).
+             * pvTaskHandle is supplied by the non-secure side and is untrusted,
+             * so it is used only as an additional ownership match, not as
+             * authority. */
+            if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) &&
+                ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) )
             {
                 /* Free the stack space. */
                 vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
@@ -342,7 +362,7 @@
 
         secureportREAD_PSPLIM( pucStackLimit );
 
-        /* Ensure that task's context is loaded and the task is saving it's own
+        /* Ensure that task's context is loaded and the task is saving its own
          * context. */
         if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) &&
             ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) )
diff --git a/Source/portable/IAR/ARM_CM55/secure/secure_context.h b/Source/portable/IAR/ARM_CM55/secure/secure_context.h
index 8b93857..51dd823 100644
--- a/Source/portable/IAR/ARM_CM55/secure/secure_context.h
+++ b/Source/portable/IAR/ARM_CM55/secure/secure_context.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM55/secure/secure_context_port_asm.s b/Source/portable/IAR/ARM_CM55/secure/secure_context_port_asm.s
index 5cc070e..519c64b 100644
--- a/Source/portable/IAR/ARM_CM55/secure/secure_context_port_asm.s
+++ b/Source/portable/IAR/ARM_CM55/secure/secure_context_port_asm.s
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM55/secure/secure_heap.c b/Source/portable/IAR/ARM_CM55/secure/secure_heap.c
index b0e83b4..58226bf 100644
--- a/Source/portable/IAR/ARM_CM55/secure/secure_heap.c
+++ b/Source/portable/IAR/ARM_CM55/secure/secure_heap.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM55/secure/secure_heap.h b/Source/portable/IAR/ARM_CM55/secure/secure_heap.h
index 61a96da..906fa24 100644
--- a/Source/portable/IAR/ARM_CM55/secure/secure_heap.h
+++ b/Source/portable/IAR/ARM_CM55/secure/secure_heap.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM55/secure/secure_init.c b/Source/portable/IAR/ARM_CM55/secure/secure_init.c
index f7f7e67..6996692 100644
--- a/Source/portable/IAR/ARM_CM55/secure/secure_init.c
+++ b/Source/portable/IAR/ARM_CM55/secure/secure_init.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM55/secure/secure_init.h b/Source/portable/IAR/ARM_CM55/secure/secure_init.h
index 46ffbd9..4e7bd40 100644
--- a/Source/portable/IAR/ARM_CM55/secure/secure_init.h
+++ b/Source/portable/IAR/ARM_CM55/secure/secure_init.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM55/secure/secure_port_macros.h b/Source/portable/IAR/ARM_CM55/secure/secure_port_macros.h
index 34494e1..72774eb 100644
--- a/Source/portable/IAR/ARM_CM55/secure/secure_port_macros.h
+++ b/Source/portable/IAR/ARM_CM55/secure/secure_port_macros.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM55_NTZ/non_secure/mpu_wrappers_v2_asm.S b/Source/portable/IAR/ARM_CM55_NTZ/non_secure/mpu_wrappers_v2_asm.S
index 68192e4..c8df7ec 100644
--- a/Source/portable/IAR/ARM_CM55_NTZ/non_secure/mpu_wrappers_v2_asm.S
+++ b/Source/portable/IAR/ARM_CM55_NTZ/non_secure/mpu_wrappers_v2_asm.S
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM55_NTZ/non_secure/port.c b/Source/portable/IAR/ARM_CM55_NTZ/non_secure/port.c
index f16a343..007150c 100644
--- a/Source/portable/IAR/ARM_CM55_NTZ/non_secure/port.c
+++ b/Source/portable/IAR/ARM_CM55_NTZ/non_secure/port.c
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024-2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -145,13 +144,13 @@
 /**
  * @brief Constants required to manipulate the FPU.
  */
-#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 )              /* Coprocessor Access Control Register. */
+#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */
 #define portCPACR_CP10_VALUE    ( 3UL )
 #define portCPACR_CP11_VALUE    portCPACR_CP10_VALUE
 #define portCPACR_CP10_POS      ( 20UL )
 #define portCPACR_CP11_POS      ( 22UL )
 
-#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 )              /* Floating Point Context Control Register. */
+#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
 #define portFPCCR_ASPEN_POS     ( 31UL )
 #define portFPCCR_ASPEN_MASK    ( 1UL << portFPCCR_ASPEN_POS )
 #define portFPCCR_LSPEN_POS     ( 30UL )
@@ -188,8 +187,8 @@
 #define portMPU_MAIR0_REG                       ( *( ( volatile uint32_t * ) 0xe000edc0 ) )
 #define portMPU_MAIR1_REG                       ( *( ( volatile uint32_t * ) 0xe000edc4 ) )
 
-#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
-#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
+#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
+#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
 
 #define portMPU_RBAR_ACCESS_PERMISSIONS_MASK    ( 3UL << 1UL )
 
@@ -230,8 +229,8 @@
 
 #if ( portARMV8M_MINOR_VERSION >= 1 )
 
-/* Enable Privileged eXecute Never MPU attribute for the selected memory
- * region. */
+    /* Enable Privileged eXecute Never MPU attribute for the selected memory
+     * region. */
     #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER    ( 1UL << 4UL )
 #endif /* portARMV8M_MINOR_VERSION >= 1 */
 
@@ -241,9 +240,6 @@
 /* Enable MPU. */
 #define portMPU_ENABLE_BIT                    ( 1UL << 0UL )
 
-/* Expected value of the portMPU_TYPE register. */
-#define portEXPECTED_MPU_TYPE_VALUE           ( configTOTAL_MPU_REGIONS << 8UL )
-
 /* Extract first address of the MPU region as encoded in the
  * RBAR (Region Base Address Register) value. */
 #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@@ -291,37 +287,37 @@
 
 #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         FD
- * 1111 1111  1111 1111  1111 1111  1111 1101
- *
- * Bit[6] - 1 --> The exception was taken from the Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 1 --> The exception was taken to the Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         FD
+     * 1111 1111  1111 1111  1111 1111  1111 1101
+     *
+     * Bit[6] - 1 --> The exception was taken from the Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 1 --> The exception was taken to the Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xfffffffd )
 #else
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         BC
- * 1111 1111  1111 1111  1111 1111  1011 1100
- *
- * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         BC
+     * 1111 1111  1111 1111  1111 1111  1011 1100
+     *
+     * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xffffffbc )
 #endif /* configRUN_FREERTOS_SECURE_ONLY */
 
@@ -401,50 +397,54 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Extract MPU region's access permissions from the Region Base Address
- * Register (RBAR) value.
- *
- * @param ulRBARValue RBAR value for the MPU region.
- *
- * @return uint32_t Access permissions.
- */
+    /**
+     * @brief Extract MPU region's access permissions from the Region Base Address
+     * Register (RBAR) value.
+     *
+     * @param ulRBARValue RBAR value for the MPU region.
+     *
+     * @return uint32_t Access permissions.
+     */
     static uint32_t prvGetRegionAccessPermissions( uint32_t ulRBARValue ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU == 1 && configUSE_MPU_WRAPPERS_V1 == 0 */
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Setup the Memory Protection Unit (MPU).
- */
+    /**
+     * @brief Setup the Memory Protection Unit (MPU).
+     */
     static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU */
 
 #if ( configENABLE_FPU == 1 )
 
-/**
- * @brief Setup the Floating Point Unit (FPU).
- */
+    /**
+     * @brief Setup the Floating Point Unit (FPU).
+     */
     static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_FPU */
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
 
-/**
- * @brief Configures PACBTI features.
- *
- * This function configures the Pointer Authentication, and Branch Target
- * Identification security features as per the user configuration. It returns
- * the value of the special purpose CONTROL register accordingly, and optionally
- * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
- * architecture based) target supports PACBTI security feature.
- *
- * @param xWriteControlRegister Used to control whether the special purpose
- * CONTROL register should be updated or not.
- *
- * @return CONTROL register value according to the configured PACBTI option.
- */
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    /**
+     * @brief Configures PACBTI features.
+     *
+     * This function configures the Pointer Authentication, and Branch Target
+     * Identification security features as per the user configuration. It returns
+     * the value of the special purpose CONTROL register accordingly, and optionally
+     * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
+     * architecture based) target supports PACBTI security feature.
+     *
+     * @param xWriteControlRegister Used to control whether the special purpose
+     * CONTROL register should be updated or not.
+     *
+     * @return CONTROL register value according to the configured PACBTI option.
+     */
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -491,14 +491,14 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the system call stack so that upon returning from
- * SVC, the system call stack is used.
- *
- * @param pulTaskStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- * @param ucSystemCallNumber The system call number of the system call.
- */
+    /**
+     * @brief Sets up the system call stack so that upon returning from
+     * SVC, the system call stack is used.
+     *
+     * @param pulTaskStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     * @param ucSystemCallNumber The system call number of the system call.
+     */
     void vSystemCallEnter( uint32_t * pulTaskStack,
                            uint32_t ulLR,
                            uint8_t ucSystemCallNumber ) PRIVILEGED_FUNCTION;
@@ -507,22 +507,22 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Raise SVC for exiting from a system call.
- */
+    /**
+     * @brief Raise SVC for exiting from a system call.
+     */
     void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the task stack so that upon returning from
- * SVC, the task stack is used again.
- *
- * @param pulSystemCallStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- */
+    /**
+     * @brief Sets up the task stack so that upon returning from
+     * SVC, the task stack is used again.
+     *
+     * @param pulSystemCallStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     */
     void vSystemCallExit( uint32_t * pulSystemCallStack,
                           uint32_t ulLR ) PRIVILEGED_FUNCTION;
 
@@ -530,21 +530,38 @@
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Checks whether or not the calling task is privileged.
- *
- * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
- */
+    /**
+     * @brief Checks whether or not the calling task is privileged.
+     *
+     * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
+     */
     BaseType_t xPortIsTaskPrivileged( void ) PRIVILEGED_FUNCTION;
 
 #endif /* configENABLE_MPU == 1 */
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /**
+     * @brief Platform/Application-defined function that wakes up the secondary cores.
+     *
+     * @return pdTRUE if the secondary cores were successfully woken up.
+     *         pdFALSE otherwise.
+     */
+    extern BaseType_t configWAKE_SECONDARY_CORES( void );
+
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
+
+/**
+ * @brief Configures interrupt priorities.
+ */
+void vPortConfigureInterruptPriorities( void ) PRIVILEGED_FUNCTION;
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief This variable is set to pdTRUE when the scheduler is started.
- */
+    /**
+     * @brief This variable is set to pdTRUE when the scheduler is started.
+     */
     PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
@@ -553,14 +570,22 @@
  * @brief Each task maintains its own interrupt status in the critical nesting
  * variable.
  */
-PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
+#if ( configNUMBER_OF_CORES == 1 )
+    PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0UL;
+#else /* #if ( configNUMBER_OF_CORES == 1 ) */
+    PRIVILEGED_DATA volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ] = { 0 };
+    /* Flags to check if the secondary cores are ready. */
+    PRIVILEGED_DATA volatile uint8_t ucSecondaryCoresReadyFlags[ configNUMBER_OF_CORES - 1 ] = { 0 };
+    /* Flag to indicate that the primary core has completed its initialisation. */
+    PRIVILEGED_DATA volatile uint8_t ucPrimaryCoreInitDoneFlag = 0;
+ #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #if ( configENABLE_TRUSTZONE == 1 )
 
-/**
- * @brief Saved as part of the task context to indicate which context the
- * task is using on the secure side.
- */
+    /**
+     * @brief Saved as part of the task context to indicate which context the
+     * task is using on the secure side.
+     */
     PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
 #endif /* configENABLE_TRUSTZONE */
 
@@ -579,21 +604,21 @@
 
 #if ( configUSE_TICKLESS_IDLE == 1 )
 
-/**
- * @brief The number of SysTick increments that make up one tick period.
- */
+    /**
+     * @brief The number of SysTick increments that make up one tick period.
+     */
     PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
 
-/**
- * @brief The maximum number of tick periods that can be suppressed is
- * limited by the 24 bit resolution of the SysTick timer.
- */
+    /**
+     * @brief The maximum number of tick periods that can be suppressed is
+     * limited by the 24 bit resolution of the SysTick timer.
+     */
     PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
 
-/**
- * @brief Compensate for the CPU cycles that pass while the SysTick is
- * stopped (low power functionality only).
- */
+    /**
+     * @brief Compensate for the CPU cycles that pass while the SysTick is
+     * stopped (low power functionality only).
+     */
     PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0;
 #endif /* configUSE_TICKLESS_IDLE */
 /*-----------------------------------------------------------*/
@@ -856,7 +881,11 @@
      * should instead call vTaskDelete( NULL ). Artificially force an assert()
      * to be triggered if configASSERT() is defined, then stop here so
      * application writers can catch the error. */
-    configASSERT( ulCriticalNesting == ~0UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == ~0UL );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == ~0UL );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
     portDISABLE_INTERRUPTS();
 
     while( ulDummy == 0 )
@@ -925,64 +954,57 @@
         /* The only permitted number of regions are 8 or 16. */
         configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 16 ) );
 
-        /* Ensure that the configTOTAL_MPU_REGIONS is configured correctly. */
-        configASSERT( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE );
+        /* MAIR0 - Index 0. */
+        portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
+        /* MAIR0 - Index 1. */
+        portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
 
-        /* Check that the MPU is present. */
-        if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
-        {
-            /* MAIR0 - Index 0. */
-            portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
-            /* MAIR0 - Index 1. */
-            portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
+        /* Setup privileged flash as Read Only so that privileged tasks can
+         * read it but not modify. */
+        portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup privileged flash as Read Only so that privileged tasks can
-             * read it but not modify. */
-            portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged flash as Read Only by both privileged and
+         * unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged flash as Read Only by both privileged and
-             * unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged syscalls flash as Read Only by both privileged
+         * and unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged syscalls flash as Read Only by both privileged
-             * and unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup RAM containing kernel data for privileged access only. */
+        portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
+                           ( portMPU_REGION_EXECUTE_NEVER );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup RAM containing kernel data for privileged access only. */
-            portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
-                               ( portMPU_REGION_EXECUTE_NEVER );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Enable mem fault. */
+        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
 
-            /* Enable mem fault. */
-            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
-
-            /* Enable MPU with privileged background access i.e. unmapped
-             * regions have privileged access. */
-            portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
-        }
+        /* Enable MPU with privileged background access i.e. unmapped
+         * regions have privileged access. */
+        portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
     }
 
 #endif /* configENABLE_MPU */
@@ -1027,28 +1049,29 @@
 }
 /*-----------------------------------------------------------*/
 
-void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    portDISABLE_INTERRUPTS();
-    ulCriticalNesting++;
-
-    /* Barriers are normally not required but do ensure the code is
-     * completely within the specified behaviour for the architecture. */
-    __asm volatile ( "dsb" ::: "memory" );
-    __asm volatile ( "isb" );
-}
-/*-----------------------------------------------------------*/
-
-void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    configASSERT( ulCriticalNesting );
-    ulCriticalNesting--;
-
-    if( ulCriticalNesting == 0 )
+#if ( configNUMBER_OF_CORES == 1 )
+    void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
     {
-        portENABLE_INTERRUPTS();
+        portDISABLE_INTERRUPTS();
+        ulCriticalNesting++;
+        /* Barriers are normally not required but do ensure the code is
+        * completely within the specified behaviour for the architecture. */
+        __asm volatile ( "dsb" ::: "memory" );
+        __asm volatile ( "isb" );
     }
-}
+    /*-----------------------------------------------------------*/
+
+    void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
+    {
+        configASSERT( ulCriticalNesting );
+        ulCriticalNesting--;
+
+        if( ulCriticalNesting == 0 )
+        {
+            portENABLE_INTERRUPTS();
+        }
+    }
+#endif /* configNUMBER_OF_CORES == 1 */
 /*-----------------------------------------------------------*/
 
 void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
@@ -1056,6 +1079,10 @@
     uint32_t ulPreviousMask;
 
     ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
+    #if ( configNUMBER_OF_CORES > 1 )
+        UBaseType_t uxSavedInterruptStatus = portENTER_CRITICAL_FROM_ISR();
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     traceISR_ENTER();
     {
         /* Increment the RTOS tick. */
@@ -1070,6 +1097,10 @@
             traceISR_EXIT();
         }
     }
+    #if ( configNUMBER_OF_CORES > 1 )
+        portEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
 }
 /*-----------------------------------------------------------*/
@@ -1078,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1090,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1108,38 +1151,42 @@
 
     switch( ucSVCNumber )
     {
-        #if ( configENABLE_TRUSTZONE == 1 )
-            case portSVC_ALLOCATE_SECURE_CONTEXT:
+    #if ( configENABLE_TRUSTZONE == 1 )
+        case portSVC_ALLOCATE_SECURE_CONTEXT:
 
-                /* R0 contains the stack size passed as parameter to the
-                 * vPortAllocateSecureContext function. */
-                ulR0 = pulCallerStackAddress[ 0 ];
+            /* R0 contains the stack size passed as parameter to the
+             * vPortAllocateSecureContext function. */
+            ulR0 = pulCallerStackAddress[ 0 ];
 
-                #if ( configENABLE_MPU == 1 )
-                {
-                    /* Read the CONTROL register value. */
-                    __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
+            #if ( configENABLE_MPU == 1 )
+            {
+                /* Read the CONTROL register value. */
+                __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
 
-                    /* The task that raised the SVC is privileged if Bit[0]
-                     * in the CONTROL register is 0. */
-                    ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
+                /* The task that raised the SVC is privileged if Bit[0]
+                 * in the CONTROL register is 0. */
+                ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
 
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
-                }
-                #else /* if ( configENABLE_MPU == 1 ) */
-                {
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
-                }
-                #endif /* configENABLE_MPU */
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
+            }
+            #else /* if ( configENABLE_MPU == 1 ) */
+            {
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
+            }
+            #endif /* configENABLE_MPU */
 
-                configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
-                SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
-                break;
+            configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
+            SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
+            break;
 
-            case portSVC_FREE_SECURE_CONTEXT:
-
+        case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
                 /* R0 contains TCB being freed and R1 contains the secure
                  * context handle to be freed. */
                 ulR0 = pulCallerStackAddress[ 0 ];
@@ -1147,51 +1194,62 @@
 
                 /* Free the secure context. */
                 SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
-                break;
-        #endif /* configENABLE_TRUSTZONE */
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
+            break;
+    #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
-            #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
-                case portSVC_RAISE_PRIVILEGE:
+    #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
+        case portSVC_RAISE_PRIVILEGE:
 
-                    /* Only raise the privilege, if the svc was raised from any of
-                     * the system calls. */
-                    if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
-                        ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
-                    {
-                        vRaisePrivilege();
-                    }
-                    break;
-            #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
+            /* Only raise the privilege, if the svc was raised from any of
+             * the system calls. */
+            if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
+                ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
+            {
+                vRaisePrivilege();
+            }
+            break;
+    #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
-            #if ( configENABLE_MPU == 1 )
-                case portSVC_YIELD:
-                    vPortYield();
-                    break;
-            #endif /* configENABLE_MPU == 1 */
+    #if ( configENABLE_MPU == 1 )
+        case portSVC_YIELD:
+            vPortYield();
+            break;
+    #endif /* configENABLE_MPU == 1 */
 
         default:
             /* Incorrect SVC call. */
@@ -1210,7 +1268,7 @@
         extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulSystemCallStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1246,12 +1304,16 @@
         {
             pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1261,20 +1323,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the system call stack for the stack frame. */
-            pulSystemCallStack = pulSystemCallStack - ulStackFrameSize;
+            pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulSystemCallStack[ i ] = pulTaskStack[ i ];
             }
@@ -1310,7 +1372,7 @@
 
             /* Remember the location where we should copy the stack frame when we exit from
              * the system call. */
-            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
+            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
 
             /* Record if the hardware used padding to force the stack pointer
              * to be double word aligned. */
@@ -1360,7 +1422,7 @@
         extern TaskHandle_t pxCurrentTCB;
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulTaskStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1392,12 +1454,16 @@
         {
             pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1407,20 +1473,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the task stack for the stack frame. */
-            pulTaskStack = pulTaskStack - ulStackFrameSize;
+            pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulTaskStack[ i ] = pulSystemCallStack[ i ];
             }
@@ -1518,21 +1584,21 @@
         xMPUSettings->ulContext[ ulIndex ] = 0x11111111; /* r11. */
         ulIndex++;
 
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters;            /* r0. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters; /* r0. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x01010101;                           /* r1. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x01010101; /* r1. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x02020202;                           /* r2. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x02020202; /* r2. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x03030303;                           /* r3. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x03030303; /* r3. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x12121212;                           /* r12. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x12121212; /* r12. */
         ulIndex++;
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) portTASK_RETURN_ADDRESS; /* LR. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode;                  /* PC. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode; /* PC. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR;                     /* xPSR. */
+        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR; /* xPSR. */
         ulIndex++;
 
         #if ( configENABLE_TRUSTZONE == 1 )
@@ -1543,14 +1609,18 @@
         #endif /* configENABLE_TRUSTZONE */
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) ( pxTopOfStack - 8 ); /* PSP with the hardware saved stack. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack;         /* PSPLIM. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack; /* PSPLIM. */
         ulIndex++;
 
         #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
         {
             /* Check PACBTI security feature configuration before pushing the
              * CONTROL register's value on task's TCB. */
-            ulControl = prvConfigurePACBTI( pdFALSE );
+            #if ( configNUMBER_OF_CORES == 1 )
+                ulControl = prvConfigurePACBTI( pdFALSE );
+            #else /* configNUMBER_OF_CORES > 1 */
+                ulControl = vConfigurePACBTI( pdFALSE );
+            #endif /* configNUMBER_OF_CORES */
         }
         #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1615,15 +1685,15 @@
          * interrupt. */
         #if ( portPRELOAD_REGISTERS == 0 )
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
-            pxTopOfStack -= 5;                                       /* R12, R3, R2 and R1. */
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
-            pxTopOfStack -= 9;                                       /* R11..R4, EXC_RETURN. */
+            pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
+            pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */
             *pxTopOfStack = portINITIAL_EXC_RETURN;
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
@@ -1637,42 +1707,42 @@
         }
         #else /* portPRELOAD_REGISTERS */
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x12121212UL;            /* R12. */
+            *pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x03030303UL;            /* R3. */
+            *pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x02020202UL;            /* R2. */
+            *pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x01010101UL;            /* R1. */
+            *pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x11111111UL;            /* R11. */
+            *pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x10101010UL;            /* R10. */
+            *pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x09090909UL;            /* R09. */
+            *pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x08080808UL;            /* R08. */
+            *pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x07070707UL;            /* R07. */
+            *pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x06060606UL;            /* R06. */
+            *pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x05050505UL;            /* R05. */
+            *pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x04040404UL;            /* R04. */
+            *pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04. */
             pxTopOfStack--;
-            *pxTopOfStack = portINITIAL_EXC_RETURN;                  /* EXC_RETURN. */
+            *pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxEndOfStack;            /* Slot used to hold this task's PSPLIM value. */
+            *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
 
             #if ( configENABLE_TRUSTZONE == 1 )
             {
@@ -1739,91 +1809,17 @@
     }
     #endif /* configCHECK_HANDLER_INSTALLATION */
 
-    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
-    {
-        volatile uint32_t ulImplementedPrioBits = 0;
-        volatile uint8_t ucMaxPriorityValue;
-
-        /* Determine the maximum priority from which ISR safe FreeRTOS API
-         * functions can be called. ISR safe functions are those that end in
-         * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
-         * ensure interrupt entry is as fast and simple as possible.
-         *
-         * First, determine the number of priority bits available. Write to all
-         * possible bits in the priority setting for SVCall. */
-        portNVIC_SHPR2_REG = 0xFF000000;
-
-        /* Read the value back to see how many bits stuck. */
-        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
-
-        /* Use the same mask on the maximum system call priority. */
-        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
-
-        /* Check that the maximum system call priority is nonzero after
-         * accounting for the number of priority bits supported by the
-         * hardware. A priority of 0 is invalid because setting the BASEPRI
-         * register to 0 unmasks all interrupts, and interrupts with priority 0
-         * cannot be masked using BASEPRI.
-         * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
-        configASSERT( ucMaxSysCallPriority );
-
-        /* Check that the bits not implemented in hardware are zero in
-         * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
-        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
-
-        /* Calculate the maximum acceptable priority group value for the number
-         * of bits read back. */
-        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
-        {
-            ulImplementedPrioBits++;
-            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
-        }
-
-        if( ulImplementedPrioBits == 8 )
-        {
-            /* When the hardware implements 8 priority bits, there is no way for
-             * the software to configure PRIGROUP to not have sub-priorities. As
-             * a result, the least significant bit is always used for sub-priority
-             * and there are 128 preemption priorities and 2 sub-priorities.
-             *
-             * This may cause some confusion in some cases - for example, if
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
-             * priority interrupts will be masked in Critical Sections as those
-             * are at the same preemption priority. This may appear confusing as
-             * 4 is higher (numerically lower) priority than
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
-             * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
-             * to 4, this confusion does not happen and the behaviour remains the same.
-             *
-             * The following assert ensures that the sub-priority bit in the
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
-             * confusion. */
-            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
-            ulMaxPRIGROUPValue = 0;
-        }
-        else
-        {
-            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
-        }
-
-        /* Shift the priority group value back to its position within the AIRCR
-         * register. */
-        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
-        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
-    }
-    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
-
-    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
-     * the highest priority. */
-    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
-    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
-    portNVIC_SHPR2_REG = 0;
+    vPortConfigureInterruptPriorities();
 
     #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
     {
         /* Set the CONTROL register value based on PACBTI security feature
          * configuration before starting the first task. */
-        ( void ) prvConfigurePACBTI( pdTRUE );
+        #if ( configNUMBER_OF_CORES == 1 )
+            ( void ) prvConfigurePACBTI( pdTRUE );
+        #else /* configNUMBER_OF_CORES > 1 */
+            ( void ) vConfigurePACBTI( pdTRUE );
+        #endif /* configNUMBER_OF_CORES */
     }
     #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1834,12 +1830,47 @@
     }
     #endif /* configENABLE_MPU */
 
-    /* Start the timer that generates the tick ISR. Interrupts are disabled
-     * here already. */
-    vPortSetupTimerInterrupt();
+    #if ( configNUMBER_OF_CORES > 1 )
+        /* Start the timer that generates the tick ISR. Interrupts are disabled
+         * here already. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count for all cores. */
+        for ( uint8_t ucCoreID = 0; ucCoreID < configNUMBER_OF_CORES; ucCoreID++ )
+        {
+            ulCriticalNestings[ ucCoreID ] = 0;
+        }
+        /* Signal that primary core has done all the necessary initialisations. */
+        ucPrimaryCoreInitDoneFlag = 1;
+        /* Wake up secondary cores */
+        BaseType_t xWakeResult = configWAKE_SECONDARY_CORES();
+        configASSERT( xWakeResult == pdTRUE );
 
-    /* Initialize the critical nesting count ready for the first task. */
-    ulCriticalNesting = 0;
+        /* Hold the primary core here until all the secondary cores are ready, this would be achieved only when
+         * all elements of ucSecondaryCoresReadyFlags are set.
+         */
+        while( 1 )
+        {
+            BaseType_t xAllCoresReady = pdTRUE;
+            for( uint8_t ucCoreID = 0; ucCoreID < ( configNUMBER_OF_CORES - 1 ); ucCoreID++ )
+            {
+                if( ucSecondaryCoresReadyFlags[ ucCoreID ] != pdTRUE )
+                {
+                    xAllCoresReady = pdFALSE;
+                    break;
+                }
+                }
+
+            if ( xAllCoresReady == pdTRUE )
+            {
+                break;
+            }
+        }
+    #else /* if ( configNUMBER_OF_CORES > 1 ) */
+        /* Start the timer that generates the tick ISR. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count ready for the first task. */
+        ulCriticalNesting = 0;
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
     {
@@ -1856,7 +1887,11 @@
      * functionality by defining configTASK_RETURN_ADDRESS. Call
      * vTaskSwitchContext() so link time optimization does not remove the
      * symbol. */
-    vTaskSwitchContext();
+    #if ( configNUMBER_OF_CORES > 1 )
+        vTaskSwitchContext( portGET_CORE_ID() );
+    #else
+        vTaskSwitchContext();
+    #endif
     prvTaskExitError();
 
     /* Should not get here. */
@@ -1868,7 +1903,11 @@
 {
     /* Not implemented in ports where there is nothing to return to.
      * Artificially force an assert. */
-    configASSERT( ulCriticalNesting == 1000UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == 1000UL );
+    #else /* if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == 1000UL );
+    #endif /* if ( configNUMBER_OF_CORES == 1 ) */
 }
 /*-----------------------------------------------------------*/
 
@@ -2151,6 +2190,90 @@
 #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
 /*-----------------------------------------------------------*/
 
+void vPortConfigureInterruptPriorities( void ) /* PRIVILEGED_FUNCTION */
+{
+    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
+    {
+        volatile uint32_t ulImplementedPrioBits = 0;
+        volatile uint8_t ucMaxPriorityValue;
+
+        /* Determine the maximum priority from which ISR safe FreeRTOS API
+        * functions can be called. ISR safe functions are those that end in
+        * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
+        * ensure interrupt entry is as fast and simple as possible.
+        *
+        * First, determine the number of priority bits available. Write to all
+        * possible bits in the priority setting for SVCall. */
+        portNVIC_SHPR2_REG = 0xFF000000;
+
+        /* Read the value back to see how many bits stuck. */
+        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
+
+        /* Use the same mask on the maximum system call priority. */
+        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
+
+        /* Check that the maximum system call priority is nonzero after
+        * accounting for the number of priority bits supported by the
+        * hardware. A priority of 0 is invalid because setting the BASEPRI
+        * register to 0 unmasks all interrupts, and interrupts with priority 0
+        * cannot be masked using BASEPRI.
+        * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+        configASSERT( ucMaxSysCallPriority );
+
+        /* Check that the bits not implemented in hardware are zero in
+        * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
+        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
+
+        /* Calculate the maximum acceptable priority group value for the number
+        * of bits read back. */
+        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
+        {
+            ulImplementedPrioBits++;
+            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
+        }
+
+        if( ulImplementedPrioBits == 8 )
+        {
+            /* When the hardware implements 8 priority bits, there is no way for
+            * the software to configure PRIGROUP to not have sub-priorities. As
+            * a result, the least significant bit is always used for sub-priority
+            * and there are 128 preemption priorities and 2 sub-priorities.
+            *
+            * This may cause some confusion in some cases - for example, if
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
+            * priority interrupts will be masked in Critical Sections as those
+            * are at the same preemption priority. This may appear confusing as
+            * 4 is higher (numerically lower) priority than
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
+            * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
+            * to 4, this confusion does not happen and the behaviour remains the same.
+            *
+            * The following assert ensures that the sub-priority bit in the
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
+            * confusion. */
+            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
+            ulMaxPRIGROUPValue = 0;
+        }
+        else
+        {
+            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
+        }
+
+        /* Shift the priority group value back to its position within the AIRCR
+        * register. */
+        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
+        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
+    }
+    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
+
+    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
+    * the highest priority. */
+    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
+    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
+    portNVIC_SHPR2_REG = 0;
+}
+/*-----------------------------------------------------------*/
+
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) )
 
     void vPortGrantAccessToKernelObject( TaskHandle_t xInternalTaskHandle,
@@ -2247,36 +2370,214 @@
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
-
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
-    {
-        uint32_t ulControl = 0x0;
-
-        /* Ensure that PACBTI is implemented. */
-        configASSERT( portID_ISAR5_REG != 0x0 );
-
-        /* Enable UsageFault exception. */
-        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
-
-        #if ( configENABLE_PAC == 1 )
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #else /* configNUMBER_OF_CORES > 1 */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #endif /* configNUMBER_OF_CORES */
         {
-            ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
-        }
-        #endif
+            uint32_t ulControl = 0x0;
 
-        #if ( configENABLE_BTI == 1 )
-        {
-            ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
-        }
-        #endif
+            /* Ensure that PACBTI is implemented. */
+            configASSERT( portID_ISAR5_REG != 0x0 );
 
-        if( xWriteControlRegister == pdTRUE )
-        {
-            __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
-        }
+            /* Enable UsageFault exception. */
+            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
 
-        return ulControl;
-    }
+            #if ( configENABLE_PAC == 1 )
+            {
+                ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
+            }
+            #endif
+
+            #if ( configENABLE_BTI == 1 )
+            {
+                ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
+            }
+            #endif
+
+            if( xWriteControlRegister == pdTRUE )
+            {
+                __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
+            }
+
+            return ulControl;
+        }
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 /*-----------------------------------------------------------*/
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /* Which core owns the lock? */
+    PRIVILEGED_DATA volatile uint32_t ulOwnedByCore[ portMAX_CORE_COUNT ];
+    /* Lock count a core owns. */
+    PRIVILEGED_DATA volatile uint32_t ulRecursionCountByLock[ eLockCount ];
+    /* Index 0 is used for ISR lock and Index 1 is used for task lock. */
+    PRIVILEGED_DATA volatile uint32_t ulGateWord[ eLockCount ];
+
+    __attribute__((weak)) void vInterruptCore( uint8_t ucCoreID )
+    {
+        /* Default weak stub - platform specific implementation may override. */
+        ( void ) ucCoreID;
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline void prvSpinUnlock( volatile uint32_t * ulLock )
+    {
+        /* Conservative unlock: preserve original barriers for broad HW/FVP. */
+        __asm volatile (
+            "dmb sy         \n"
+            "mov r1, #0     \n"
+            "str r1, [%0]   \n"
+            "sev            \n"
+            "dsb            \n"
+            "isb            \n"
+            :
+            : "r" ( ulLock )
+            : "memory", "r1"
+        );
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline uint32_t prvSpinTrylock( volatile uint32_t * ulLock )
+    {
+        /*
+         * Conservative ldrex/strex trylock:
+         * - Return 1 immediately if busy, clearing exclusive state (CLREX).
+         * - Retry strex only on spurious failure when observed free.
+         * - DMB on success to preserve expected acquire semantics.
+         */
+        uint32_t ulVal;
+        uint32_t ulStatus;
+
+        __asm volatile (
+            " ldrex %0, [%1]   \n"
+            : "=r" ( ulVal )
+            : "r" ( ulLock )
+            : "memory"
+        );
+
+        if( ulVal != 0U )
+        {
+            __asm volatile ("clrex" ::: "memory");
+            return 1U;
+        }
+
+        __asm volatile (
+            " strex %0, %2, [%1]   \n"
+            : "=&r" ( ulStatus )
+            : "r" ( ulLock ), "r" (1U)
+            : "memory"
+        );
+
+        if( ulStatus != 0U )
+        {
+            return 1U;
+        }
+        __asm volatile ( "dmb" ::: "memory" );
+        return 0U;
+    }
+
+
+/*-----------------------------------------------------------*/
+
+    /* Read 32b value shared between cores. */
+    static inline uint32_t prvGet32( volatile uint32_t * x )
+    {
+        __asm( "dsb" );
+        return *x;
+    }
+
+/*-----------------------------------------------------------*/
+
+    /* Write 32b value shared between cores. */
+    static inline void prvSet32( volatile uint32_t * x,
+                                 uint32_t value )
+    {
+        *x = value;
+        __asm( "dsb" );
+    }
+
+/*-----------------------------------------------------------*/
+
+    void vPortRecursiveLock( uint8_t ucCoreID,
+                             ePortRTOSLock eLockNum,
+                             BaseType_t uxAcquire )
+    {
+        /* Validate the core ID and lock number. */
+        configASSERT( ucCoreID < portMAX_CORE_COUNT );
+        configASSERT( eLockNum < eLockCount );
+
+        uint32_t ulLockBit = 1u << eLockNum;
+
+        /* Lock acquire */
+        if( uxAcquire )
+        {
+            /* Check if spinlock is available. */
+            /* If spinlock is not available check if the core owns the lock. */
+            /* If the core owns the lock wait increment the lock count by the core. */
+            /* If core does not own the lock wait for the spinlock. */
+            if( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+            {
+                /* Check if the core owns the spinlock. */
+                if( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit )
+                {
+                    configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != portUINT32_MAX );
+                    prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) + 1 ) );
+                    return;
+                }
+
+                /* Preload the gate word into the cache. */
+                uint32_t dummy = ulGateWord[ eLockNum ];
+                dummy++;
+
+                while( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+                {
+                    __asm volatile ( "wfe" );
+                }
+            }
+
+            /* Add barrier to ensure lock is taken before we proceed. */
+            __asm volatile( "dmb sy" ::: "memory" );
+
+            /* Assert the lock count is 0 when the spinlock is free and is acquired. */
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) == 0 );
+
+            /* Set lock count as 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], 1 );
+            /* Set ulOwnedByCore. */
+            prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) | ulLockBit ) );
+        }
+        /* Lock release. */
+        else
+        {
+            /* Assert the lock is not free already. */
+            configASSERT( ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit ) != 0 );
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != 0 );
+
+            /* Reduce ulRecursionCountByLock by 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) - 1 ) );
+
+            if( !prvGet32( &ulRecursionCountByLock[ eLockNum ] ) )
+            {
+                prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ~ulLockBit ) );
+                prvSpinUnlock( &ulGateWord[ eLockNum ] );
+                /* Add barrier to ensure lock status is reflected before we proceed. */
+                __asm volatile( "dmb sy" ::: "memory" );
+            }
+        }
+    }
+
+/*-----------------------------------------------------------*/
+
+    uint8_t ucPortGetCoreID( void )
+    {
+        return *(volatile uint8_t *)(configCORE_ID_REGISTER);
+    }
+
+/*-----------------------------------------------------------*/
+
+#endif /* if( configNUMBER_OF_CORES > 1 ) */
diff --git a/Source/portable/IAR/ARM_CM55_NTZ/non_secure/portasm.h b/Source/portable/IAR/ARM_CM55_NTZ/non_secure/portasm.h
index 53b4b6e..b4b545f 100644
--- a/Source/portable/IAR/ARM_CM55_NTZ/non_secure/portasm.h
+++ b/Source/portable/IAR/ARM_CM55_NTZ/non_secure/portasm.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM55_NTZ/non_secure/portasm.s b/Source/portable/IAR/ARM_CM55_NTZ/non_secure/portasm.s
index 8092255..8de575d 100644
--- a/Source/portable/IAR/ARM_CM55_NTZ/non_secure/portasm.s
+++ b/Source/portable/IAR/ARM_CM55_NTZ/non_secure/portasm.s
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -41,7 +40,15 @@
     #define configUSE_MPU_WRAPPERS_V1 0
 #endif
 
+#ifndef configNUMBER_OF_CORES
+    #define configNUMBER_OF_CORES 1
+#endif
+
+#if ( configNUMBER_OF_CORES == 1)
     EXTERN pxCurrentTCB
+#else /* if ( configNUMBER_OF_CORES == 1) */
+    EXTERN pxCurrentTCBs
+#endif
     EXTERN vTaskSwitchContext
     EXTERN vPortSVCHandler_C
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
@@ -169,8 +176,15 @@
 #else /* configENABLE_MPU */
 
 vRestoreContextOfFirstTask:
+#if ( configNUMBER_OF_CORES == 1)
     ldr  r2, =pxCurrentTCB                  /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
     ldr  r1, [r2]                           /* Read pxCurrentTCB. */
+#else /* if ( configNUMBER_OF_CORES == 1) */
+    ldr r1, =ulFirstTaskLiteralPool         /* Get the location of the current TCB and the Id of the current core. */
+    ldmia r1!, {r2, r3}
+    ldr r2, [r2]                            /* r2 = Core Id */
+    ldr r1, [r3, r2, LSL #2]                /* r1 = pxCurrentTCBs[CORE_ID] */
+#endif /* if ( configNUMBER_OF_CORES == 1) */
     ldr  r0, [r1]                           /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
 
 #if ( configENABLE_PAC == 1 )
@@ -193,6 +207,13 @@
     mov  r0, #0
     msr  basepri, r0                        /* Ensure that interrupts are enabled when the first task starts. */
     bx   r2                                 /* Finally, branch to EXC_RETURN. */
+#if ( configNUMBER_OF_CORES > 1 )
+    /* Align to 4 bytes in ROM/code area (2^2 alignment, 0 fill). */
+    ALIGNROM 2, 0
+    ulFirstTaskLiteralPool:
+        DC32 configCORE_ID_REGISTER         /* CORE_ID_REGISTER */
+        DC32 pxCurrentTCBs
+#endif /* if ( configNUMBER_OF_CORES > 1 ) */
 
 #endif /* configENABLE_MPU */
 /*-----------------------------------------------------------*/
@@ -377,20 +398,37 @@
     clrm {r1-r4}                            /* Clear r1-r4. */
 #endif /* configENABLE_PAC */
 
+#if ( configNUMBER_OF_CORES == 1)
     ldr r2, =pxCurrentTCB                   /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
     ldr r1, [r2]                            /* Read pxCurrentTCB. */
+#else /* if ( configNUMBER_OF_CORES == 1) */
+    ldr r1, =ulPendSVLiteralPool            /* Get the location of the current TCB and the Id of the current core. */
+    ldmia r1!, {r2, r3}
+    ldr r2, [r2]                            /* r2 = Core Id */
+    ldr r1, [r3, r2, LSL #2]                /* r1 = pxCurrentTCBs[CORE_ID] */
+#endif /* if ( configNUMBER_OF_CORES == 1) */
     str r0, [r1]                            /* Save the new top of stack in TCB. */
 
     mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
     msr basepri, r0                         /* Disable interrupts up to configMAX_SYSCALL_INTERRUPT_PRIORITY. */
     dsb
     isb
+    #if ( configNUMBER_OF_CORES > 1)
+        mov r0, r2                          /* r0 = ucPortGetCoreID() */
+    #endif /* if ( configNUMBER_OF_CORES == 1) */
     bl vTaskSwitchContext
     mov r0, #0                              /* r0 = 0. */
     msr basepri, r0                         /* Enable interrupts. */
 
+#if ( configNUMBER_OF_CORES == 1)
     ldr r2, =pxCurrentTCB                   /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
     ldr r1, [r2]                            /* Read pxCurrentTCB. */
+#else /* if ( configNUMBER_OF_CORES == 1) */
+    ldr r1, =ulPendSVLiteralPool            /* Get the location of the current TCB and the Id of the current core. */
+    ldmia r1!, {r2, r3}
+    ldr r2, [r2]                            /* r2 = Core Id */
+    ldr r1, [r3, r2, LSL #2]                /* r1 = pxCurrentTCBs[CORE_ID] */
+#endif /* if ( configNUMBER_OF_CORES == 1) */
     ldr r0, [r1]                            /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
 
 #if ( configENABLE_PAC == 1 )
@@ -413,6 +451,13 @@
     msr psplim, r2                          /* Restore the PSPLIM register value for the task. */
     msr psp, r0                             /* Remember the new top of stack for the task. */
     bx r3
+#if ( configNUMBER_OF_CORES > 1 )
+    /* Align to 4 bytes in ROM/code area (2^2 alignment, 0 fill). */
+    ALIGNROM 2, 0
+    ulPendSVLiteralPool:
+    DC32 configCORE_ID_REGISTER         /* CORE_ID_REGISTER */
+    DC32 pxCurrentTCBs
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
 
 #endif /* configENABLE_MPU */
 /*-----------------------------------------------------------*/
diff --git a/Source/portable/IAR/ARM_CM55_NTZ/non_secure/portmacro.h b/Source/portable/IAR/ARM_CM55_NTZ/non_secure/portmacro.h
index 0526455..0a4d223 100644
--- a/Source/portable/IAR/ARM_CM55_NTZ/non_secure/portmacro.h
+++ b/Source/portable/IAR/ARM_CM55_NTZ/non_secure/portmacro.h
@@ -1,6 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * Copyright 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -57,6 +58,7 @@
 #define portHAS_ARMV8M_MAIN_EXTENSION    1
 #define portARMV8M_MINOR_VERSION         1
 #define portDONT_DISCARD                 __root
+#define portVALIDATED_FOR_SMP            0
 /*-----------------------------------------------------------*/
 
 /* ARMv8-M common port configurations. */
diff --git a/Source/portable/IAR/ARM_CM55_NTZ/non_secure/portmacrocommon.h b/Source/portable/IAR/ARM_CM55_NTZ/non_secure/portmacrocommon.h
index 2dfac6a..c34fdee 100644
--- a/Source/portable/IAR/ARM_CM55_NTZ/non_secure/portmacrocommon.h
+++ b/Source/portable/IAR/ARM_CM55_NTZ/non_secure/portmacrocommon.h
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -59,6 +58,19 @@
     #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h.  Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
 #endif /* configENABLE_TRUSTZONE */
 
+#if ( configNUMBER_OF_CORES > 1 )
+    #if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 )
+        #error "Multi-core SMP is currently only validated for Cortex-M33 non-TrustZone non-MPU port."
+    #endif /* if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 ) ) */
+
+    #ifndef configCORE_ID_REGISTER
+        #error "configCORE_ID_REGISTER must be defined to the address of the register used to identify the core executing the code."
+    #endif /* ifndef configCORE_ID_REGISTER */
+
+    #ifndef configWAKE_SECONDARY_CORES
+        #error "configWAKE_SECONDARY_CORES must be defined to a function that wakes the secondary cores."
+    #endif /* ifndef configWAKE_SECONDARY_CORES */
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -428,10 +440,26 @@
 /**
  * @brief Critical section management.
  */
+
+#define portSET_INTERRUPT_MASK()                  ulSetInterruptMask()
+#define portCLEAR_INTERRUPT_MASK( x )             vClearInterruptMask( x )
 #define portSET_INTERRUPT_MASK_FROM_ISR()         ulSetInterruptMask()
 #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x )    vClearInterruptMask( x )
-#define portENTER_CRITICAL()                      vPortEnterCritical()
-#define portEXIT_CRITICAL()                       vPortExitCritical()
+
+#if ( configNUMBER_OF_CORES == 1 )
+    #define portENTER_CRITICAL()                      vPortEnterCritical()
+    #define portEXIT_CRITICAL()                       vPortExitCritical()
+#else /* ( configNUMBER_OF_CORES == 1 ) */
+    extern void vTaskEnterCritical( void );
+    extern void vTaskExitCritical( void );
+    extern UBaseType_t vTaskEnterCriticalFromISR( void );
+    extern void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus );
+
+    #define portENTER_CRITICAL()                      vTaskEnterCritical()
+    #define portEXIT_CRITICAL()                       vTaskExitCritical()
+    #define portENTER_CRITICAL_FROM_ISR()             vTaskEnterCriticalFromISR()
+    #define portEXIT_CRITICAL_FROM_ISR( x )           vTaskExitCriticalFromISR( x )
+#endif /* if ( configNUMBER_OF_CORES != 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -526,7 +554,7 @@
 /* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION
  * based on whether or not Mainline extension is implemented. */
 #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
-    #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 )
+    #if ( ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) && ( configNUMBER_OF_CORES == 1 ) )
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    1
     #else
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    0
@@ -573,6 +601,44 @@
 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
 /*-----------------------------------------------------------*/
 
+
+#if ( configNUMBER_OF_CORES > 1 )
+    typedef enum
+    {
+        eIsrLock = 0,
+        eTaskLock,
+        eLockCount
+    } ePortRTOSLock;
+
+    extern volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ];
+    extern void vPortRecursiveLock( uint8_t ucCoreID,
+                                    ePortRTOSLock eLockNum,
+                                    BaseType_t uxAcquire );
+    extern uint8_t ucPortGetCoreID( void );
+    extern void vInterruptCore( uint8_t ucCoreID );
+
+    #define portGET_CORE_ID()                                  ucPortGetCoreID()
+
+    #define portGET_CRITICAL_NESTING_COUNT( xCoreID )          ( ulCriticalNestings[ ( uint8_t ) xCoreID ] )
+    #define portSET_CRITICAL_NESTING_COUNT( xCoreID, x )       ( ulCriticalNestings[ ( uint8_t ) xCoreID ] = ( x ) )
+    #define portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]++ )
+    #define portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]-- )
+
+    #define portMAX_CORE_COUNT                                 ( configNUMBER_OF_CORES )
+
+    #define portYIELD_CORE( xCoreID )                          vInterruptCore( xCoreID )
+
+    #define portRELEASE_ISR_LOCK( xCoreID )                    vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdFALSE )
+    #define portGET_ISR_LOCK( xCoreID )                        vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdTRUE )
+
+    #define portRELEASE_TASK_LOCK( xCoreID )                   vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdFALSE )
+    #define portGET_TASK_LOCK( xCoreID )                       vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdTRUE )
+
+    #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* ( configENABLE_PAC == 1 || configENABLE_BTI == 1 ) */
+#endif
+
 /* *INDENT-OFF* */
 #ifdef __cplusplus
     }
diff --git a/Source/portable/IAR/ARM_CM7/r0p1/port.c b/Source/portable/IAR/ARM_CM7/r0p1/port.c
index 924e27e..3b2e734 100644
--- a/Source/portable/IAR/ARM_CM7/r0p1/port.c
+++ b/Source/portable/IAR/ARM_CM7/r0p1/port.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM7/r0p1/portasm.s b/Source/portable/IAR/ARM_CM7/r0p1/portasm.s
index 4d4ffaf..32a3fd9 100644
--- a/Source/portable/IAR/ARM_CM7/r0p1/portasm.s
+++ b/Source/portable/IAR/ARM_CM7/r0p1/portasm.s
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM7/r0p1/portmacro.h b/Source/portable/IAR/ARM_CM7/r0p1/portmacro.h
index 4fa219e..507cc8b 100644
--- a/Source/portable/IAR/ARM_CM7/r0p1/portmacro.h
+++ b/Source/portable/IAR/ARM_CM7/r0p1/portmacro.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM85/non_secure/mpu_wrappers_v2_asm.S b/Source/portable/IAR/ARM_CM85/non_secure/mpu_wrappers_v2_asm.S
index 68192e4..c8df7ec 100644
--- a/Source/portable/IAR/ARM_CM85/non_secure/mpu_wrappers_v2_asm.S
+++ b/Source/portable/IAR/ARM_CM85/non_secure/mpu_wrappers_v2_asm.S
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM85/non_secure/port.c b/Source/portable/IAR/ARM_CM85/non_secure/port.c
index f16a343..007150c 100644
--- a/Source/portable/IAR/ARM_CM85/non_secure/port.c
+++ b/Source/portable/IAR/ARM_CM85/non_secure/port.c
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024-2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -145,13 +144,13 @@
 /**
  * @brief Constants required to manipulate the FPU.
  */
-#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 )              /* Coprocessor Access Control Register. */
+#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */
 #define portCPACR_CP10_VALUE    ( 3UL )
 #define portCPACR_CP11_VALUE    portCPACR_CP10_VALUE
 #define portCPACR_CP10_POS      ( 20UL )
 #define portCPACR_CP11_POS      ( 22UL )
 
-#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 )              /* Floating Point Context Control Register. */
+#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
 #define portFPCCR_ASPEN_POS     ( 31UL )
 #define portFPCCR_ASPEN_MASK    ( 1UL << portFPCCR_ASPEN_POS )
 #define portFPCCR_LSPEN_POS     ( 30UL )
@@ -188,8 +187,8 @@
 #define portMPU_MAIR0_REG                       ( *( ( volatile uint32_t * ) 0xe000edc0 ) )
 #define portMPU_MAIR1_REG                       ( *( ( volatile uint32_t * ) 0xe000edc4 ) )
 
-#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
-#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
+#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
+#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
 
 #define portMPU_RBAR_ACCESS_PERMISSIONS_MASK    ( 3UL << 1UL )
 
@@ -230,8 +229,8 @@
 
 #if ( portARMV8M_MINOR_VERSION >= 1 )
 
-/* Enable Privileged eXecute Never MPU attribute for the selected memory
- * region. */
+    /* Enable Privileged eXecute Never MPU attribute for the selected memory
+     * region. */
     #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER    ( 1UL << 4UL )
 #endif /* portARMV8M_MINOR_VERSION >= 1 */
 
@@ -241,9 +240,6 @@
 /* Enable MPU. */
 #define portMPU_ENABLE_BIT                    ( 1UL << 0UL )
 
-/* Expected value of the portMPU_TYPE register. */
-#define portEXPECTED_MPU_TYPE_VALUE           ( configTOTAL_MPU_REGIONS << 8UL )
-
 /* Extract first address of the MPU region as encoded in the
  * RBAR (Region Base Address Register) value. */
 #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@@ -291,37 +287,37 @@
 
 #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         FD
- * 1111 1111  1111 1111  1111 1111  1111 1101
- *
- * Bit[6] - 1 --> The exception was taken from the Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 1 --> The exception was taken to the Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         FD
+     * 1111 1111  1111 1111  1111 1111  1111 1101
+     *
+     * Bit[6] - 1 --> The exception was taken from the Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 1 --> The exception was taken to the Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xfffffffd )
 #else
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         BC
- * 1111 1111  1111 1111  1111 1111  1011 1100
- *
- * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         BC
+     * 1111 1111  1111 1111  1111 1111  1011 1100
+     *
+     * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xffffffbc )
 #endif /* configRUN_FREERTOS_SECURE_ONLY */
 
@@ -401,50 +397,54 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Extract MPU region's access permissions from the Region Base Address
- * Register (RBAR) value.
- *
- * @param ulRBARValue RBAR value for the MPU region.
- *
- * @return uint32_t Access permissions.
- */
+    /**
+     * @brief Extract MPU region's access permissions from the Region Base Address
+     * Register (RBAR) value.
+     *
+     * @param ulRBARValue RBAR value for the MPU region.
+     *
+     * @return uint32_t Access permissions.
+     */
     static uint32_t prvGetRegionAccessPermissions( uint32_t ulRBARValue ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU == 1 && configUSE_MPU_WRAPPERS_V1 == 0 */
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Setup the Memory Protection Unit (MPU).
- */
+    /**
+     * @brief Setup the Memory Protection Unit (MPU).
+     */
     static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU */
 
 #if ( configENABLE_FPU == 1 )
 
-/**
- * @brief Setup the Floating Point Unit (FPU).
- */
+    /**
+     * @brief Setup the Floating Point Unit (FPU).
+     */
     static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_FPU */
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
 
-/**
- * @brief Configures PACBTI features.
- *
- * This function configures the Pointer Authentication, and Branch Target
- * Identification security features as per the user configuration. It returns
- * the value of the special purpose CONTROL register accordingly, and optionally
- * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
- * architecture based) target supports PACBTI security feature.
- *
- * @param xWriteControlRegister Used to control whether the special purpose
- * CONTROL register should be updated or not.
- *
- * @return CONTROL register value according to the configured PACBTI option.
- */
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    /**
+     * @brief Configures PACBTI features.
+     *
+     * This function configures the Pointer Authentication, and Branch Target
+     * Identification security features as per the user configuration. It returns
+     * the value of the special purpose CONTROL register accordingly, and optionally
+     * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
+     * architecture based) target supports PACBTI security feature.
+     *
+     * @param xWriteControlRegister Used to control whether the special purpose
+     * CONTROL register should be updated or not.
+     *
+     * @return CONTROL register value according to the configured PACBTI option.
+     */
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -491,14 +491,14 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the system call stack so that upon returning from
- * SVC, the system call stack is used.
- *
- * @param pulTaskStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- * @param ucSystemCallNumber The system call number of the system call.
- */
+    /**
+     * @brief Sets up the system call stack so that upon returning from
+     * SVC, the system call stack is used.
+     *
+     * @param pulTaskStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     * @param ucSystemCallNumber The system call number of the system call.
+     */
     void vSystemCallEnter( uint32_t * pulTaskStack,
                            uint32_t ulLR,
                            uint8_t ucSystemCallNumber ) PRIVILEGED_FUNCTION;
@@ -507,22 +507,22 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Raise SVC for exiting from a system call.
- */
+    /**
+     * @brief Raise SVC for exiting from a system call.
+     */
     void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the task stack so that upon returning from
- * SVC, the task stack is used again.
- *
- * @param pulSystemCallStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- */
+    /**
+     * @brief Sets up the task stack so that upon returning from
+     * SVC, the task stack is used again.
+     *
+     * @param pulSystemCallStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     */
     void vSystemCallExit( uint32_t * pulSystemCallStack,
                           uint32_t ulLR ) PRIVILEGED_FUNCTION;
 
@@ -530,21 +530,38 @@
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Checks whether or not the calling task is privileged.
- *
- * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
- */
+    /**
+     * @brief Checks whether or not the calling task is privileged.
+     *
+     * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
+     */
     BaseType_t xPortIsTaskPrivileged( void ) PRIVILEGED_FUNCTION;
 
 #endif /* configENABLE_MPU == 1 */
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /**
+     * @brief Platform/Application-defined function that wakes up the secondary cores.
+     *
+     * @return pdTRUE if the secondary cores were successfully woken up.
+     *         pdFALSE otherwise.
+     */
+    extern BaseType_t configWAKE_SECONDARY_CORES( void );
+
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
+
+/**
+ * @brief Configures interrupt priorities.
+ */
+void vPortConfigureInterruptPriorities( void ) PRIVILEGED_FUNCTION;
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief This variable is set to pdTRUE when the scheduler is started.
- */
+    /**
+     * @brief This variable is set to pdTRUE when the scheduler is started.
+     */
     PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
@@ -553,14 +570,22 @@
  * @brief Each task maintains its own interrupt status in the critical nesting
  * variable.
  */
-PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
+#if ( configNUMBER_OF_CORES == 1 )
+    PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0UL;
+#else /* #if ( configNUMBER_OF_CORES == 1 ) */
+    PRIVILEGED_DATA volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ] = { 0 };
+    /* Flags to check if the secondary cores are ready. */
+    PRIVILEGED_DATA volatile uint8_t ucSecondaryCoresReadyFlags[ configNUMBER_OF_CORES - 1 ] = { 0 };
+    /* Flag to indicate that the primary core has completed its initialisation. */
+    PRIVILEGED_DATA volatile uint8_t ucPrimaryCoreInitDoneFlag = 0;
+ #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #if ( configENABLE_TRUSTZONE == 1 )
 
-/**
- * @brief Saved as part of the task context to indicate which context the
- * task is using on the secure side.
- */
+    /**
+     * @brief Saved as part of the task context to indicate which context the
+     * task is using on the secure side.
+     */
     PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
 #endif /* configENABLE_TRUSTZONE */
 
@@ -579,21 +604,21 @@
 
 #if ( configUSE_TICKLESS_IDLE == 1 )
 
-/**
- * @brief The number of SysTick increments that make up one tick period.
- */
+    /**
+     * @brief The number of SysTick increments that make up one tick period.
+     */
     PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
 
-/**
- * @brief The maximum number of tick periods that can be suppressed is
- * limited by the 24 bit resolution of the SysTick timer.
- */
+    /**
+     * @brief The maximum number of tick periods that can be suppressed is
+     * limited by the 24 bit resolution of the SysTick timer.
+     */
     PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
 
-/**
- * @brief Compensate for the CPU cycles that pass while the SysTick is
- * stopped (low power functionality only).
- */
+    /**
+     * @brief Compensate for the CPU cycles that pass while the SysTick is
+     * stopped (low power functionality only).
+     */
     PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0;
 #endif /* configUSE_TICKLESS_IDLE */
 /*-----------------------------------------------------------*/
@@ -856,7 +881,11 @@
      * should instead call vTaskDelete( NULL ). Artificially force an assert()
      * to be triggered if configASSERT() is defined, then stop here so
      * application writers can catch the error. */
-    configASSERT( ulCriticalNesting == ~0UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == ~0UL );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == ~0UL );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
     portDISABLE_INTERRUPTS();
 
     while( ulDummy == 0 )
@@ -925,64 +954,57 @@
         /* The only permitted number of regions are 8 or 16. */
         configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 16 ) );
 
-        /* Ensure that the configTOTAL_MPU_REGIONS is configured correctly. */
-        configASSERT( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE );
+        /* MAIR0 - Index 0. */
+        portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
+        /* MAIR0 - Index 1. */
+        portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
 
-        /* Check that the MPU is present. */
-        if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
-        {
-            /* MAIR0 - Index 0. */
-            portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
-            /* MAIR0 - Index 1. */
-            portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
+        /* Setup privileged flash as Read Only so that privileged tasks can
+         * read it but not modify. */
+        portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup privileged flash as Read Only so that privileged tasks can
-             * read it but not modify. */
-            portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged flash as Read Only by both privileged and
+         * unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged flash as Read Only by both privileged and
-             * unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged syscalls flash as Read Only by both privileged
+         * and unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged syscalls flash as Read Only by both privileged
-             * and unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup RAM containing kernel data for privileged access only. */
+        portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
+                           ( portMPU_REGION_EXECUTE_NEVER );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup RAM containing kernel data for privileged access only. */
-            portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
-                               ( portMPU_REGION_EXECUTE_NEVER );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Enable mem fault. */
+        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
 
-            /* Enable mem fault. */
-            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
-
-            /* Enable MPU with privileged background access i.e. unmapped
-             * regions have privileged access. */
-            portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
-        }
+        /* Enable MPU with privileged background access i.e. unmapped
+         * regions have privileged access. */
+        portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
     }
 
 #endif /* configENABLE_MPU */
@@ -1027,28 +1049,29 @@
 }
 /*-----------------------------------------------------------*/
 
-void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    portDISABLE_INTERRUPTS();
-    ulCriticalNesting++;
-
-    /* Barriers are normally not required but do ensure the code is
-     * completely within the specified behaviour for the architecture. */
-    __asm volatile ( "dsb" ::: "memory" );
-    __asm volatile ( "isb" );
-}
-/*-----------------------------------------------------------*/
-
-void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    configASSERT( ulCriticalNesting );
-    ulCriticalNesting--;
-
-    if( ulCriticalNesting == 0 )
+#if ( configNUMBER_OF_CORES == 1 )
+    void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
     {
-        portENABLE_INTERRUPTS();
+        portDISABLE_INTERRUPTS();
+        ulCriticalNesting++;
+        /* Barriers are normally not required but do ensure the code is
+        * completely within the specified behaviour for the architecture. */
+        __asm volatile ( "dsb" ::: "memory" );
+        __asm volatile ( "isb" );
     }
-}
+    /*-----------------------------------------------------------*/
+
+    void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
+    {
+        configASSERT( ulCriticalNesting );
+        ulCriticalNesting--;
+
+        if( ulCriticalNesting == 0 )
+        {
+            portENABLE_INTERRUPTS();
+        }
+    }
+#endif /* configNUMBER_OF_CORES == 1 */
 /*-----------------------------------------------------------*/
 
 void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
@@ -1056,6 +1079,10 @@
     uint32_t ulPreviousMask;
 
     ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
+    #if ( configNUMBER_OF_CORES > 1 )
+        UBaseType_t uxSavedInterruptStatus = portENTER_CRITICAL_FROM_ISR();
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     traceISR_ENTER();
     {
         /* Increment the RTOS tick. */
@@ -1070,6 +1097,10 @@
             traceISR_EXIT();
         }
     }
+    #if ( configNUMBER_OF_CORES > 1 )
+        portEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
 }
 /*-----------------------------------------------------------*/
@@ -1078,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1090,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1108,38 +1151,42 @@
 
     switch( ucSVCNumber )
     {
-        #if ( configENABLE_TRUSTZONE == 1 )
-            case portSVC_ALLOCATE_SECURE_CONTEXT:
+    #if ( configENABLE_TRUSTZONE == 1 )
+        case portSVC_ALLOCATE_SECURE_CONTEXT:
 
-                /* R0 contains the stack size passed as parameter to the
-                 * vPortAllocateSecureContext function. */
-                ulR0 = pulCallerStackAddress[ 0 ];
+            /* R0 contains the stack size passed as parameter to the
+             * vPortAllocateSecureContext function. */
+            ulR0 = pulCallerStackAddress[ 0 ];
 
-                #if ( configENABLE_MPU == 1 )
-                {
-                    /* Read the CONTROL register value. */
-                    __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
+            #if ( configENABLE_MPU == 1 )
+            {
+                /* Read the CONTROL register value. */
+                __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
 
-                    /* The task that raised the SVC is privileged if Bit[0]
-                     * in the CONTROL register is 0. */
-                    ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
+                /* The task that raised the SVC is privileged if Bit[0]
+                 * in the CONTROL register is 0. */
+                ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
 
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
-                }
-                #else /* if ( configENABLE_MPU == 1 ) */
-                {
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
-                }
-                #endif /* configENABLE_MPU */
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
+            }
+            #else /* if ( configENABLE_MPU == 1 ) */
+            {
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
+            }
+            #endif /* configENABLE_MPU */
 
-                configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
-                SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
-                break;
+            configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
+            SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
+            break;
 
-            case portSVC_FREE_SECURE_CONTEXT:
-
+        case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
                 /* R0 contains TCB being freed and R1 contains the secure
                  * context handle to be freed. */
                 ulR0 = pulCallerStackAddress[ 0 ];
@@ -1147,51 +1194,62 @@
 
                 /* Free the secure context. */
                 SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
-                break;
-        #endif /* configENABLE_TRUSTZONE */
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
+            break;
+    #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
-            #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
-                case portSVC_RAISE_PRIVILEGE:
+    #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
+        case portSVC_RAISE_PRIVILEGE:
 
-                    /* Only raise the privilege, if the svc was raised from any of
-                     * the system calls. */
-                    if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
-                        ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
-                    {
-                        vRaisePrivilege();
-                    }
-                    break;
-            #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
+            /* Only raise the privilege, if the svc was raised from any of
+             * the system calls. */
+            if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
+                ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
+            {
+                vRaisePrivilege();
+            }
+            break;
+    #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
-            #if ( configENABLE_MPU == 1 )
-                case portSVC_YIELD:
-                    vPortYield();
-                    break;
-            #endif /* configENABLE_MPU == 1 */
+    #if ( configENABLE_MPU == 1 )
+        case portSVC_YIELD:
+            vPortYield();
+            break;
+    #endif /* configENABLE_MPU == 1 */
 
         default:
             /* Incorrect SVC call. */
@@ -1210,7 +1268,7 @@
         extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulSystemCallStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1246,12 +1304,16 @@
         {
             pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1261,20 +1323,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the system call stack for the stack frame. */
-            pulSystemCallStack = pulSystemCallStack - ulStackFrameSize;
+            pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulSystemCallStack[ i ] = pulTaskStack[ i ];
             }
@@ -1310,7 +1372,7 @@
 
             /* Remember the location where we should copy the stack frame when we exit from
              * the system call. */
-            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
+            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
 
             /* Record if the hardware used padding to force the stack pointer
              * to be double word aligned. */
@@ -1360,7 +1422,7 @@
         extern TaskHandle_t pxCurrentTCB;
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulTaskStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1392,12 +1454,16 @@
         {
             pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1407,20 +1473,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the task stack for the stack frame. */
-            pulTaskStack = pulTaskStack - ulStackFrameSize;
+            pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulTaskStack[ i ] = pulSystemCallStack[ i ];
             }
@@ -1518,21 +1584,21 @@
         xMPUSettings->ulContext[ ulIndex ] = 0x11111111; /* r11. */
         ulIndex++;
 
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters;            /* r0. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters; /* r0. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x01010101;                           /* r1. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x01010101; /* r1. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x02020202;                           /* r2. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x02020202; /* r2. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x03030303;                           /* r3. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x03030303; /* r3. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x12121212;                           /* r12. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x12121212; /* r12. */
         ulIndex++;
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) portTASK_RETURN_ADDRESS; /* LR. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode;                  /* PC. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode; /* PC. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR;                     /* xPSR. */
+        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR; /* xPSR. */
         ulIndex++;
 
         #if ( configENABLE_TRUSTZONE == 1 )
@@ -1543,14 +1609,18 @@
         #endif /* configENABLE_TRUSTZONE */
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) ( pxTopOfStack - 8 ); /* PSP with the hardware saved stack. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack;         /* PSPLIM. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack; /* PSPLIM. */
         ulIndex++;
 
         #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
         {
             /* Check PACBTI security feature configuration before pushing the
              * CONTROL register's value on task's TCB. */
-            ulControl = prvConfigurePACBTI( pdFALSE );
+            #if ( configNUMBER_OF_CORES == 1 )
+                ulControl = prvConfigurePACBTI( pdFALSE );
+            #else /* configNUMBER_OF_CORES > 1 */
+                ulControl = vConfigurePACBTI( pdFALSE );
+            #endif /* configNUMBER_OF_CORES */
         }
         #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1615,15 +1685,15 @@
          * interrupt. */
         #if ( portPRELOAD_REGISTERS == 0 )
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
-            pxTopOfStack -= 5;                                       /* R12, R3, R2 and R1. */
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
-            pxTopOfStack -= 9;                                       /* R11..R4, EXC_RETURN. */
+            pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
+            pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */
             *pxTopOfStack = portINITIAL_EXC_RETURN;
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
@@ -1637,42 +1707,42 @@
         }
         #else /* portPRELOAD_REGISTERS */
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x12121212UL;            /* R12. */
+            *pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x03030303UL;            /* R3. */
+            *pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x02020202UL;            /* R2. */
+            *pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x01010101UL;            /* R1. */
+            *pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x11111111UL;            /* R11. */
+            *pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x10101010UL;            /* R10. */
+            *pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x09090909UL;            /* R09. */
+            *pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x08080808UL;            /* R08. */
+            *pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x07070707UL;            /* R07. */
+            *pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x06060606UL;            /* R06. */
+            *pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x05050505UL;            /* R05. */
+            *pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x04040404UL;            /* R04. */
+            *pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04. */
             pxTopOfStack--;
-            *pxTopOfStack = portINITIAL_EXC_RETURN;                  /* EXC_RETURN. */
+            *pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxEndOfStack;            /* Slot used to hold this task's PSPLIM value. */
+            *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
 
             #if ( configENABLE_TRUSTZONE == 1 )
             {
@@ -1739,91 +1809,17 @@
     }
     #endif /* configCHECK_HANDLER_INSTALLATION */
 
-    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
-    {
-        volatile uint32_t ulImplementedPrioBits = 0;
-        volatile uint8_t ucMaxPriorityValue;
-
-        /* Determine the maximum priority from which ISR safe FreeRTOS API
-         * functions can be called. ISR safe functions are those that end in
-         * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
-         * ensure interrupt entry is as fast and simple as possible.
-         *
-         * First, determine the number of priority bits available. Write to all
-         * possible bits in the priority setting for SVCall. */
-        portNVIC_SHPR2_REG = 0xFF000000;
-
-        /* Read the value back to see how many bits stuck. */
-        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
-
-        /* Use the same mask on the maximum system call priority. */
-        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
-
-        /* Check that the maximum system call priority is nonzero after
-         * accounting for the number of priority bits supported by the
-         * hardware. A priority of 0 is invalid because setting the BASEPRI
-         * register to 0 unmasks all interrupts, and interrupts with priority 0
-         * cannot be masked using BASEPRI.
-         * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
-        configASSERT( ucMaxSysCallPriority );
-
-        /* Check that the bits not implemented in hardware are zero in
-         * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
-        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
-
-        /* Calculate the maximum acceptable priority group value for the number
-         * of bits read back. */
-        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
-        {
-            ulImplementedPrioBits++;
-            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
-        }
-
-        if( ulImplementedPrioBits == 8 )
-        {
-            /* When the hardware implements 8 priority bits, there is no way for
-             * the software to configure PRIGROUP to not have sub-priorities. As
-             * a result, the least significant bit is always used for sub-priority
-             * and there are 128 preemption priorities and 2 sub-priorities.
-             *
-             * This may cause some confusion in some cases - for example, if
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
-             * priority interrupts will be masked in Critical Sections as those
-             * are at the same preemption priority. This may appear confusing as
-             * 4 is higher (numerically lower) priority than
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
-             * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
-             * to 4, this confusion does not happen and the behaviour remains the same.
-             *
-             * The following assert ensures that the sub-priority bit in the
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
-             * confusion. */
-            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
-            ulMaxPRIGROUPValue = 0;
-        }
-        else
-        {
-            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
-        }
-
-        /* Shift the priority group value back to its position within the AIRCR
-         * register. */
-        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
-        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
-    }
-    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
-
-    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
-     * the highest priority. */
-    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
-    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
-    portNVIC_SHPR2_REG = 0;
+    vPortConfigureInterruptPriorities();
 
     #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
     {
         /* Set the CONTROL register value based on PACBTI security feature
          * configuration before starting the first task. */
-        ( void ) prvConfigurePACBTI( pdTRUE );
+        #if ( configNUMBER_OF_CORES == 1 )
+            ( void ) prvConfigurePACBTI( pdTRUE );
+        #else /* configNUMBER_OF_CORES > 1 */
+            ( void ) vConfigurePACBTI( pdTRUE );
+        #endif /* configNUMBER_OF_CORES */
     }
     #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1834,12 +1830,47 @@
     }
     #endif /* configENABLE_MPU */
 
-    /* Start the timer that generates the tick ISR. Interrupts are disabled
-     * here already. */
-    vPortSetupTimerInterrupt();
+    #if ( configNUMBER_OF_CORES > 1 )
+        /* Start the timer that generates the tick ISR. Interrupts are disabled
+         * here already. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count for all cores. */
+        for ( uint8_t ucCoreID = 0; ucCoreID < configNUMBER_OF_CORES; ucCoreID++ )
+        {
+            ulCriticalNestings[ ucCoreID ] = 0;
+        }
+        /* Signal that primary core has done all the necessary initialisations. */
+        ucPrimaryCoreInitDoneFlag = 1;
+        /* Wake up secondary cores */
+        BaseType_t xWakeResult = configWAKE_SECONDARY_CORES();
+        configASSERT( xWakeResult == pdTRUE );
 
-    /* Initialize the critical nesting count ready for the first task. */
-    ulCriticalNesting = 0;
+        /* Hold the primary core here until all the secondary cores are ready, this would be achieved only when
+         * all elements of ucSecondaryCoresReadyFlags are set.
+         */
+        while( 1 )
+        {
+            BaseType_t xAllCoresReady = pdTRUE;
+            for( uint8_t ucCoreID = 0; ucCoreID < ( configNUMBER_OF_CORES - 1 ); ucCoreID++ )
+            {
+                if( ucSecondaryCoresReadyFlags[ ucCoreID ] != pdTRUE )
+                {
+                    xAllCoresReady = pdFALSE;
+                    break;
+                }
+                }
+
+            if ( xAllCoresReady == pdTRUE )
+            {
+                break;
+            }
+        }
+    #else /* if ( configNUMBER_OF_CORES > 1 ) */
+        /* Start the timer that generates the tick ISR. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count ready for the first task. */
+        ulCriticalNesting = 0;
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
     {
@@ -1856,7 +1887,11 @@
      * functionality by defining configTASK_RETURN_ADDRESS. Call
      * vTaskSwitchContext() so link time optimization does not remove the
      * symbol. */
-    vTaskSwitchContext();
+    #if ( configNUMBER_OF_CORES > 1 )
+        vTaskSwitchContext( portGET_CORE_ID() );
+    #else
+        vTaskSwitchContext();
+    #endif
     prvTaskExitError();
 
     /* Should not get here. */
@@ -1868,7 +1903,11 @@
 {
     /* Not implemented in ports where there is nothing to return to.
      * Artificially force an assert. */
-    configASSERT( ulCriticalNesting == 1000UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == 1000UL );
+    #else /* if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == 1000UL );
+    #endif /* if ( configNUMBER_OF_CORES == 1 ) */
 }
 /*-----------------------------------------------------------*/
 
@@ -2151,6 +2190,90 @@
 #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
 /*-----------------------------------------------------------*/
 
+void vPortConfigureInterruptPriorities( void ) /* PRIVILEGED_FUNCTION */
+{
+    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
+    {
+        volatile uint32_t ulImplementedPrioBits = 0;
+        volatile uint8_t ucMaxPriorityValue;
+
+        /* Determine the maximum priority from which ISR safe FreeRTOS API
+        * functions can be called. ISR safe functions are those that end in
+        * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
+        * ensure interrupt entry is as fast and simple as possible.
+        *
+        * First, determine the number of priority bits available. Write to all
+        * possible bits in the priority setting for SVCall. */
+        portNVIC_SHPR2_REG = 0xFF000000;
+
+        /* Read the value back to see how many bits stuck. */
+        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
+
+        /* Use the same mask on the maximum system call priority. */
+        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
+
+        /* Check that the maximum system call priority is nonzero after
+        * accounting for the number of priority bits supported by the
+        * hardware. A priority of 0 is invalid because setting the BASEPRI
+        * register to 0 unmasks all interrupts, and interrupts with priority 0
+        * cannot be masked using BASEPRI.
+        * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+        configASSERT( ucMaxSysCallPriority );
+
+        /* Check that the bits not implemented in hardware are zero in
+        * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
+        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
+
+        /* Calculate the maximum acceptable priority group value for the number
+        * of bits read back. */
+        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
+        {
+            ulImplementedPrioBits++;
+            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
+        }
+
+        if( ulImplementedPrioBits == 8 )
+        {
+            /* When the hardware implements 8 priority bits, there is no way for
+            * the software to configure PRIGROUP to not have sub-priorities. As
+            * a result, the least significant bit is always used for sub-priority
+            * and there are 128 preemption priorities and 2 sub-priorities.
+            *
+            * This may cause some confusion in some cases - for example, if
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
+            * priority interrupts will be masked in Critical Sections as those
+            * are at the same preemption priority. This may appear confusing as
+            * 4 is higher (numerically lower) priority than
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
+            * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
+            * to 4, this confusion does not happen and the behaviour remains the same.
+            *
+            * The following assert ensures that the sub-priority bit in the
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
+            * confusion. */
+            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
+            ulMaxPRIGROUPValue = 0;
+        }
+        else
+        {
+            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
+        }
+
+        /* Shift the priority group value back to its position within the AIRCR
+        * register. */
+        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
+        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
+    }
+    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
+
+    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
+    * the highest priority. */
+    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
+    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
+    portNVIC_SHPR2_REG = 0;
+}
+/*-----------------------------------------------------------*/
+
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) )
 
     void vPortGrantAccessToKernelObject( TaskHandle_t xInternalTaskHandle,
@@ -2247,36 +2370,214 @@
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
-
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
-    {
-        uint32_t ulControl = 0x0;
-
-        /* Ensure that PACBTI is implemented. */
-        configASSERT( portID_ISAR5_REG != 0x0 );
-
-        /* Enable UsageFault exception. */
-        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
-
-        #if ( configENABLE_PAC == 1 )
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #else /* configNUMBER_OF_CORES > 1 */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #endif /* configNUMBER_OF_CORES */
         {
-            ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
-        }
-        #endif
+            uint32_t ulControl = 0x0;
 
-        #if ( configENABLE_BTI == 1 )
-        {
-            ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
-        }
-        #endif
+            /* Ensure that PACBTI is implemented. */
+            configASSERT( portID_ISAR5_REG != 0x0 );
 
-        if( xWriteControlRegister == pdTRUE )
-        {
-            __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
-        }
+            /* Enable UsageFault exception. */
+            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
 
-        return ulControl;
-    }
+            #if ( configENABLE_PAC == 1 )
+            {
+                ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
+            }
+            #endif
+
+            #if ( configENABLE_BTI == 1 )
+            {
+                ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
+            }
+            #endif
+
+            if( xWriteControlRegister == pdTRUE )
+            {
+                __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
+            }
+
+            return ulControl;
+        }
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 /*-----------------------------------------------------------*/
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /* Which core owns the lock? */
+    PRIVILEGED_DATA volatile uint32_t ulOwnedByCore[ portMAX_CORE_COUNT ];
+    /* Lock count a core owns. */
+    PRIVILEGED_DATA volatile uint32_t ulRecursionCountByLock[ eLockCount ];
+    /* Index 0 is used for ISR lock and Index 1 is used for task lock. */
+    PRIVILEGED_DATA volatile uint32_t ulGateWord[ eLockCount ];
+
+    __attribute__((weak)) void vInterruptCore( uint8_t ucCoreID )
+    {
+        /* Default weak stub - platform specific implementation may override. */
+        ( void ) ucCoreID;
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline void prvSpinUnlock( volatile uint32_t * ulLock )
+    {
+        /* Conservative unlock: preserve original barriers for broad HW/FVP. */
+        __asm volatile (
+            "dmb sy         \n"
+            "mov r1, #0     \n"
+            "str r1, [%0]   \n"
+            "sev            \n"
+            "dsb            \n"
+            "isb            \n"
+            :
+            : "r" ( ulLock )
+            : "memory", "r1"
+        );
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline uint32_t prvSpinTrylock( volatile uint32_t * ulLock )
+    {
+        /*
+         * Conservative ldrex/strex trylock:
+         * - Return 1 immediately if busy, clearing exclusive state (CLREX).
+         * - Retry strex only on spurious failure when observed free.
+         * - DMB on success to preserve expected acquire semantics.
+         */
+        uint32_t ulVal;
+        uint32_t ulStatus;
+
+        __asm volatile (
+            " ldrex %0, [%1]   \n"
+            : "=r" ( ulVal )
+            : "r" ( ulLock )
+            : "memory"
+        );
+
+        if( ulVal != 0U )
+        {
+            __asm volatile ("clrex" ::: "memory");
+            return 1U;
+        }
+
+        __asm volatile (
+            " strex %0, %2, [%1]   \n"
+            : "=&r" ( ulStatus )
+            : "r" ( ulLock ), "r" (1U)
+            : "memory"
+        );
+
+        if( ulStatus != 0U )
+        {
+            return 1U;
+        }
+        __asm volatile ( "dmb" ::: "memory" );
+        return 0U;
+    }
+
+
+/*-----------------------------------------------------------*/
+
+    /* Read 32b value shared between cores. */
+    static inline uint32_t prvGet32( volatile uint32_t * x )
+    {
+        __asm( "dsb" );
+        return *x;
+    }
+
+/*-----------------------------------------------------------*/
+
+    /* Write 32b value shared between cores. */
+    static inline void prvSet32( volatile uint32_t * x,
+                                 uint32_t value )
+    {
+        *x = value;
+        __asm( "dsb" );
+    }
+
+/*-----------------------------------------------------------*/
+
+    void vPortRecursiveLock( uint8_t ucCoreID,
+                             ePortRTOSLock eLockNum,
+                             BaseType_t uxAcquire )
+    {
+        /* Validate the core ID and lock number. */
+        configASSERT( ucCoreID < portMAX_CORE_COUNT );
+        configASSERT( eLockNum < eLockCount );
+
+        uint32_t ulLockBit = 1u << eLockNum;
+
+        /* Lock acquire */
+        if( uxAcquire )
+        {
+            /* Check if spinlock is available. */
+            /* If spinlock is not available check if the core owns the lock. */
+            /* If the core owns the lock wait increment the lock count by the core. */
+            /* If core does not own the lock wait for the spinlock. */
+            if( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+            {
+                /* Check if the core owns the spinlock. */
+                if( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit )
+                {
+                    configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != portUINT32_MAX );
+                    prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) + 1 ) );
+                    return;
+                }
+
+                /* Preload the gate word into the cache. */
+                uint32_t dummy = ulGateWord[ eLockNum ];
+                dummy++;
+
+                while( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+                {
+                    __asm volatile ( "wfe" );
+                }
+            }
+
+            /* Add barrier to ensure lock is taken before we proceed. */
+            __asm volatile( "dmb sy" ::: "memory" );
+
+            /* Assert the lock count is 0 when the spinlock is free and is acquired. */
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) == 0 );
+
+            /* Set lock count as 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], 1 );
+            /* Set ulOwnedByCore. */
+            prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) | ulLockBit ) );
+        }
+        /* Lock release. */
+        else
+        {
+            /* Assert the lock is not free already. */
+            configASSERT( ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit ) != 0 );
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != 0 );
+
+            /* Reduce ulRecursionCountByLock by 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) - 1 ) );
+
+            if( !prvGet32( &ulRecursionCountByLock[ eLockNum ] ) )
+            {
+                prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ~ulLockBit ) );
+                prvSpinUnlock( &ulGateWord[ eLockNum ] );
+                /* Add barrier to ensure lock status is reflected before we proceed. */
+                __asm volatile( "dmb sy" ::: "memory" );
+            }
+        }
+    }
+
+/*-----------------------------------------------------------*/
+
+    uint8_t ucPortGetCoreID( void )
+    {
+        return *(volatile uint8_t *)(configCORE_ID_REGISTER);
+    }
+
+/*-----------------------------------------------------------*/
+
+#endif /* if( configNUMBER_OF_CORES > 1 ) */
diff --git a/Source/portable/IAR/ARM_CM85/non_secure/portasm.h b/Source/portable/IAR/ARM_CM85/non_secure/portasm.h
index 53b4b6e..b4b545f 100644
--- a/Source/portable/IAR/ARM_CM85/non_secure/portasm.h
+++ b/Source/portable/IAR/ARM_CM85/non_secure/portasm.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM85/non_secure/portasm.s b/Source/portable/IAR/ARM_CM85/non_secure/portasm.s
index b5c91e5..c31d9ed 100644
--- a/Source/portable/IAR/ARM_CM85/non_secure/portasm.s
+++ b/Source/portable/IAR/ARM_CM85/non_secure/portasm.s
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  * Copyright 2024 Arm Limited and/or its affiliates
  * <open-source-office@arm.com>
@@ -41,6 +41,16 @@
     #define configUSE_MPU_WRAPPERS_V1 0
 #endif
 
+#if ( configENABLE_MPU == 1 )
+    #if ( configENABLE_PAC == 1 )
+        #define SECURE_CONTEXT_OFFSET   -36
+    #else
+        #define SECURE_CONTEXT_OFFSET   -20
+    #endif
+#else
+    #define SECURE_CONTEXT_OFFSET       0
+#endif
+
     EXTERN pxCurrentTCB
     EXTERN xSecureContext
     EXTERN vTaskSwitchContext
@@ -532,8 +542,8 @@
 
 vPortFreeSecureContext:
     /* r0 = uint32_t *pulTCB. */
-    ldr r2, [r0]                            /* The first item in the TCB is the top of the stack. */
-    ldr r1, [r2]                            /* The first item on the stack is the task's xSecureContext. */
+    ldr r2, [r0]                            /* The first item in the TCB is the stored context location. */
+    ldr r1, [r2, #SECURE_CONTEXT_OFFSET]    /* Read xSecureContext from the task's context. */
     cmp r1, #0                              /* Raise svc if task's xSecureContext is not NULL. */
     it ne
     svcne 101                               /* Secure context is freed in the supervisor call. portSVC_FREE_SECURE_CONTEXT = 101. */
diff --git a/Source/portable/IAR/ARM_CM85/non_secure/portmacro.h b/Source/portable/IAR/ARM_CM85/non_secure/portmacro.h
index 2f1676c..4b2faaf 100644
--- a/Source/portable/IAR/ARM_CM85/non_secure/portmacro.h
+++ b/Source/portable/IAR/ARM_CM85/non_secure/portmacro.h
@@ -1,6 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * Copyright 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -57,6 +58,7 @@
 #define portHAS_ARMV8M_MAIN_EXTENSION    1
 #define portARMV8M_MINOR_VERSION         1
 #define portDONT_DISCARD                 __root
+#define portVALIDATED_FOR_SMP            0
 /*-----------------------------------------------------------*/
 
 /* ARMv8-M common port configurations. */
diff --git a/Source/portable/IAR/ARM_CM85/non_secure/portmacrocommon.h b/Source/portable/IAR/ARM_CM85/non_secure/portmacrocommon.h
index 2dfac6a..c34fdee 100644
--- a/Source/portable/IAR/ARM_CM85/non_secure/portmacrocommon.h
+++ b/Source/portable/IAR/ARM_CM85/non_secure/portmacrocommon.h
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -59,6 +58,19 @@
     #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h.  Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
 #endif /* configENABLE_TRUSTZONE */
 
+#if ( configNUMBER_OF_CORES > 1 )
+    #if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 )
+        #error "Multi-core SMP is currently only validated for Cortex-M33 non-TrustZone non-MPU port."
+    #endif /* if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 ) ) */
+
+    #ifndef configCORE_ID_REGISTER
+        #error "configCORE_ID_REGISTER must be defined to the address of the register used to identify the core executing the code."
+    #endif /* ifndef configCORE_ID_REGISTER */
+
+    #ifndef configWAKE_SECONDARY_CORES
+        #error "configWAKE_SECONDARY_CORES must be defined to a function that wakes the secondary cores."
+    #endif /* ifndef configWAKE_SECONDARY_CORES */
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -428,10 +440,26 @@
 /**
  * @brief Critical section management.
  */
+
+#define portSET_INTERRUPT_MASK()                  ulSetInterruptMask()
+#define portCLEAR_INTERRUPT_MASK( x )             vClearInterruptMask( x )
 #define portSET_INTERRUPT_MASK_FROM_ISR()         ulSetInterruptMask()
 #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x )    vClearInterruptMask( x )
-#define portENTER_CRITICAL()                      vPortEnterCritical()
-#define portEXIT_CRITICAL()                       vPortExitCritical()
+
+#if ( configNUMBER_OF_CORES == 1 )
+    #define portENTER_CRITICAL()                      vPortEnterCritical()
+    #define portEXIT_CRITICAL()                       vPortExitCritical()
+#else /* ( configNUMBER_OF_CORES == 1 ) */
+    extern void vTaskEnterCritical( void );
+    extern void vTaskExitCritical( void );
+    extern UBaseType_t vTaskEnterCriticalFromISR( void );
+    extern void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus );
+
+    #define portENTER_CRITICAL()                      vTaskEnterCritical()
+    #define portEXIT_CRITICAL()                       vTaskExitCritical()
+    #define portENTER_CRITICAL_FROM_ISR()             vTaskEnterCriticalFromISR()
+    #define portEXIT_CRITICAL_FROM_ISR( x )           vTaskExitCriticalFromISR( x )
+#endif /* if ( configNUMBER_OF_CORES != 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -526,7 +554,7 @@
 /* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION
  * based on whether or not Mainline extension is implemented. */
 #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
-    #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 )
+    #if ( ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) && ( configNUMBER_OF_CORES == 1 ) )
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    1
     #else
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    0
@@ -573,6 +601,44 @@
 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
 /*-----------------------------------------------------------*/
 
+
+#if ( configNUMBER_OF_CORES > 1 )
+    typedef enum
+    {
+        eIsrLock = 0,
+        eTaskLock,
+        eLockCount
+    } ePortRTOSLock;
+
+    extern volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ];
+    extern void vPortRecursiveLock( uint8_t ucCoreID,
+                                    ePortRTOSLock eLockNum,
+                                    BaseType_t uxAcquire );
+    extern uint8_t ucPortGetCoreID( void );
+    extern void vInterruptCore( uint8_t ucCoreID );
+
+    #define portGET_CORE_ID()                                  ucPortGetCoreID()
+
+    #define portGET_CRITICAL_NESTING_COUNT( xCoreID )          ( ulCriticalNestings[ ( uint8_t ) xCoreID ] )
+    #define portSET_CRITICAL_NESTING_COUNT( xCoreID, x )       ( ulCriticalNestings[ ( uint8_t ) xCoreID ] = ( x ) )
+    #define portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]++ )
+    #define portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]-- )
+
+    #define portMAX_CORE_COUNT                                 ( configNUMBER_OF_CORES )
+
+    #define portYIELD_CORE( xCoreID )                          vInterruptCore( xCoreID )
+
+    #define portRELEASE_ISR_LOCK( xCoreID )                    vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdFALSE )
+    #define portGET_ISR_LOCK( xCoreID )                        vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdTRUE )
+
+    #define portRELEASE_TASK_LOCK( xCoreID )                   vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdFALSE )
+    #define portGET_TASK_LOCK( xCoreID )                       vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdTRUE )
+
+    #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* ( configENABLE_PAC == 1 || configENABLE_BTI == 1 ) */
+#endif
+
 /* *INDENT-OFF* */
 #ifdef __cplusplus
     }
diff --git a/Source/portable/IAR/ARM_CM85/secure/secure_context.c b/Source/portable/IAR/ARM_CM85/secure/secure_context.c
index 62bcfa1..2dae022 100644
--- a/Source/portable/IAR/ARM_CM85/secure/secure_context.c
+++ b/Source/portable/IAR/ARM_CM85/secure/secure_context.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -213,8 +213,19 @@
         /* Were we able to get a free context? */
         if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS )
         {
-            /* Allocate the stack space. */
-            pucStackMemory = pvPortMalloc( ulSecureStackSize + securecontextSTACK_SEAL_SIZE );
+            /* Allocate the stack space if possible. */
+            if( ( ulSecureStackSize < securecontextSTACK_SEAL_SIZE ) ||
+                ( ulSecureStackSize > ( UINT32_MAX - securecontextSTACK_SEAL_SIZE ) ) )
+            {
+                /* Reject stacks that are too small (the CONTROL word would be
+                 * written before the allocation, corrupting the secure heap)
+                 * and sizes that would overflow when the seal size is added. */
+                pucStackMemory = NULL;
+            }
+            else
+            {
+                pucStackMemory = pvPortMalloc( ulSecureStackSize + securecontextSTACK_SEAL_SIZE );
+            }
 
             if( pucStackMemory != NULL )
             {
@@ -279,9 +290,12 @@
                                                               void * pvTaskHandle )
 {
     uint32_t ulIPSR, ulSecureContextIndex;
+    uint8_t * pucStackLimit;
 
-    /* Read the Interrupt Program Status Register (IPSR) value. */
+    /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
+     * Register (PSPLIM) value. */
     secureportREAD_IPSR( ulIPSR );
+    secureportREAD_PSPLIM( pucStackLimit );
 
     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
      * when the processor is running in the Thread Mode. */
@@ -293,8 +307,14 @@
             ulSecureContextIndex = xSecureContextHandle - 1UL;
 
             /* Ensure that the secure context being deleted is associated with
-             * the task. */
-            if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
+             * the task and is NOT the currently-loaded context. Freeing a
+             * context whose stack is currently loaded in PSPLIM would leave the
+             * running task referencing freed secure memory (use-after-free).
+             * pvTaskHandle is supplied by the non-secure side and is untrusted,
+             * so it is used only as an additional ownership match, not as
+             * authority. */
+            if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) &&
+                ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) )
             {
                 /* Free the stack space. */
                 vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
@@ -342,7 +362,7 @@
 
         secureportREAD_PSPLIM( pucStackLimit );
 
-        /* Ensure that task's context is loaded and the task is saving it's own
+        /* Ensure that task's context is loaded and the task is saving its own
          * context. */
         if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) &&
             ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) )
diff --git a/Source/portable/IAR/ARM_CM85/secure/secure_context.h b/Source/portable/IAR/ARM_CM85/secure/secure_context.h
index 8b93857..51dd823 100644
--- a/Source/portable/IAR/ARM_CM85/secure/secure_context.h
+++ b/Source/portable/IAR/ARM_CM85/secure/secure_context.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM85/secure/secure_context_port_asm.s b/Source/portable/IAR/ARM_CM85/secure/secure_context_port_asm.s
index 5cc070e..519c64b 100644
--- a/Source/portable/IAR/ARM_CM85/secure/secure_context_port_asm.s
+++ b/Source/portable/IAR/ARM_CM85/secure/secure_context_port_asm.s
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM85/secure/secure_heap.c b/Source/portable/IAR/ARM_CM85/secure/secure_heap.c
index b0e83b4..58226bf 100644
--- a/Source/portable/IAR/ARM_CM85/secure/secure_heap.c
+++ b/Source/portable/IAR/ARM_CM85/secure/secure_heap.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM85/secure/secure_heap.h b/Source/portable/IAR/ARM_CM85/secure/secure_heap.h
index 61a96da..906fa24 100644
--- a/Source/portable/IAR/ARM_CM85/secure/secure_heap.h
+++ b/Source/portable/IAR/ARM_CM85/secure/secure_heap.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM85/secure/secure_init.c b/Source/portable/IAR/ARM_CM85/secure/secure_init.c
index f7f7e67..6996692 100644
--- a/Source/portable/IAR/ARM_CM85/secure/secure_init.c
+++ b/Source/portable/IAR/ARM_CM85/secure/secure_init.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM85/secure/secure_init.h b/Source/portable/IAR/ARM_CM85/secure/secure_init.h
index 46ffbd9..4e7bd40 100644
--- a/Source/portable/IAR/ARM_CM85/secure/secure_init.h
+++ b/Source/portable/IAR/ARM_CM85/secure/secure_init.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM85/secure/secure_port_macros.h b/Source/portable/IAR/ARM_CM85/secure/secure_port_macros.h
index 34494e1..72774eb 100644
--- a/Source/portable/IAR/ARM_CM85/secure/secure_port_macros.h
+++ b/Source/portable/IAR/ARM_CM85/secure/secure_port_macros.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM85_NTZ/non_secure/mpu_wrappers_v2_asm.S b/Source/portable/IAR/ARM_CM85_NTZ/non_secure/mpu_wrappers_v2_asm.S
index 68192e4..c8df7ec 100644
--- a/Source/portable/IAR/ARM_CM85_NTZ/non_secure/mpu_wrappers_v2_asm.S
+++ b/Source/portable/IAR/ARM_CM85_NTZ/non_secure/mpu_wrappers_v2_asm.S
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM85_NTZ/non_secure/port.c b/Source/portable/IAR/ARM_CM85_NTZ/non_secure/port.c
index f16a343..007150c 100644
--- a/Source/portable/IAR/ARM_CM85_NTZ/non_secure/port.c
+++ b/Source/portable/IAR/ARM_CM85_NTZ/non_secure/port.c
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024-2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -145,13 +144,13 @@
 /**
  * @brief Constants required to manipulate the FPU.
  */
-#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 )              /* Coprocessor Access Control Register. */
+#define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */
 #define portCPACR_CP10_VALUE    ( 3UL )
 #define portCPACR_CP11_VALUE    portCPACR_CP10_VALUE
 #define portCPACR_CP10_POS      ( 20UL )
 #define portCPACR_CP11_POS      ( 22UL )
 
-#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 )              /* Floating Point Context Control Register. */
+#define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
 #define portFPCCR_ASPEN_POS     ( 31UL )
 #define portFPCCR_ASPEN_MASK    ( 1UL << portFPCCR_ASPEN_POS )
 #define portFPCCR_LSPEN_POS     ( 30UL )
@@ -188,8 +187,8 @@
 #define portMPU_MAIR0_REG                       ( *( ( volatile uint32_t * ) 0xe000edc0 ) )
 #define portMPU_MAIR1_REG                       ( *( ( volatile uint32_t * ) 0xe000edc4 ) )
 
-#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
-#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 )     /* Must be 32-byte aligned. */
+#define portMPU_RBAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
+#define portMPU_RLAR_ADDRESS_MASK               ( 0xffffffe0 ) /* Must be 32-byte aligned. */
 
 #define portMPU_RBAR_ACCESS_PERMISSIONS_MASK    ( 3UL << 1UL )
 
@@ -230,8 +229,8 @@
 
 #if ( portARMV8M_MINOR_VERSION >= 1 )
 
-/* Enable Privileged eXecute Never MPU attribute for the selected memory
- * region. */
+    /* Enable Privileged eXecute Never MPU attribute for the selected memory
+     * region. */
     #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER    ( 1UL << 4UL )
 #endif /* portARMV8M_MINOR_VERSION >= 1 */
 
@@ -241,9 +240,6 @@
 /* Enable MPU. */
 #define portMPU_ENABLE_BIT                    ( 1UL << 0UL )
 
-/* Expected value of the portMPU_TYPE register. */
-#define portEXPECTED_MPU_TYPE_VALUE           ( configTOTAL_MPU_REGIONS << 8UL )
-
 /* Extract first address of the MPU region as encoded in the
  * RBAR (Region Base Address Register) value. */
 #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@@ -291,37 +287,37 @@
 
 #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         FD
- * 1111 1111  1111 1111  1111 1111  1111 1101
- *
- * Bit[6] - 1 --> The exception was taken from the Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 1 --> The exception was taken to the Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         FD
+     * 1111 1111  1111 1111  1111 1111  1111 1101
+     *
+     * Bit[6] - 1 --> The exception was taken from the Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 1 --> The exception was taken to the Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xfffffffd )
 #else
 
-/**
- * @brief Initial EXC_RETURN value.
- *
- *     FF         FF         FF         BC
- * 1111 1111  1111 1111  1111 1111  1011 1100
- *
- * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
- * Bit[5] - 1 --> Do not skip stacking of additional state context.
- * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
- * Bit[3] - 1 --> Return to the Thread mode.
- * Bit[2] - 1 --> Restore registers from the process stack.
- * Bit[1] - 0 --> Reserved, 0.
- * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
- */
+    /**
+     * @brief Initial EXC_RETURN value.
+     *
+     *     FF         FF         FF         BC
+     * 1111 1111  1111 1111  1111 1111  1011 1100
+     *
+     * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
+     * Bit[5] - 1 --> Do not skip stacking of additional state context.
+     * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
+     * Bit[3] - 1 --> Return to the Thread mode.
+     * Bit[2] - 1 --> Restore registers from the process stack.
+     * Bit[1] - 0 --> Reserved, 0.
+     * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
+     */
     #define portINITIAL_EXC_RETURN    ( 0xffffffbc )
 #endif /* configRUN_FREERTOS_SECURE_ONLY */
 
@@ -401,50 +397,54 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Extract MPU region's access permissions from the Region Base Address
- * Register (RBAR) value.
- *
- * @param ulRBARValue RBAR value for the MPU region.
- *
- * @return uint32_t Access permissions.
- */
+    /**
+     * @brief Extract MPU region's access permissions from the Region Base Address
+     * Register (RBAR) value.
+     *
+     * @param ulRBARValue RBAR value for the MPU region.
+     *
+     * @return uint32_t Access permissions.
+     */
     static uint32_t prvGetRegionAccessPermissions( uint32_t ulRBARValue ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU == 1 && configUSE_MPU_WRAPPERS_V1 == 0 */
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Setup the Memory Protection Unit (MPU).
- */
+    /**
+     * @brief Setup the Memory Protection Unit (MPU).
+     */
     static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_MPU */
 
 #if ( configENABLE_FPU == 1 )
 
-/**
- * @brief Setup the Floating Point Unit (FPU).
- */
+    /**
+     * @brief Setup the Floating Point Unit (FPU).
+     */
     static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
 #endif /* configENABLE_FPU */
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
 
-/**
- * @brief Configures PACBTI features.
- *
- * This function configures the Pointer Authentication, and Branch Target
- * Identification security features as per the user configuration. It returns
- * the value of the special purpose CONTROL register accordingly, and optionally
- * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
- * architecture based) target supports PACBTI security feature.
- *
- * @param xWriteControlRegister Used to control whether the special purpose
- * CONTROL register should be updated or not.
- *
- * @return CONTROL register value according to the configured PACBTI option.
- */
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    /**
+     * @brief Configures PACBTI features.
+     *
+     * This function configures the Pointer Authentication, and Branch Target
+     * Identification security features as per the user configuration. It returns
+     * the value of the special purpose CONTROL register accordingly, and optionally
+     * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
+     * architecture based) target supports PACBTI security feature.
+     *
+     * @param xWriteControlRegister Used to control whether the special purpose
+     * CONTROL register should be updated or not.
+     *
+     * @return CONTROL register value according to the configured PACBTI option.
+     */
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -491,14 +491,14 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the system call stack so that upon returning from
- * SVC, the system call stack is used.
- *
- * @param pulTaskStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- * @param ucSystemCallNumber The system call number of the system call.
- */
+    /**
+     * @brief Sets up the system call stack so that upon returning from
+     * SVC, the system call stack is used.
+     *
+     * @param pulTaskStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     * @param ucSystemCallNumber The system call number of the system call.
+     */
     void vSystemCallEnter( uint32_t * pulTaskStack,
                            uint32_t ulLR,
                            uint8_t ucSystemCallNumber ) PRIVILEGED_FUNCTION;
@@ -507,22 +507,22 @@
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Raise SVC for exiting from a system call.
- */
+    /**
+     * @brief Raise SVC for exiting from a system call.
+     */
     void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief Sets up the task stack so that upon returning from
- * SVC, the task stack is used again.
- *
- * @param pulSystemCallStack The current SP when the SVC was raised.
- * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
- */
+    /**
+     * @brief Sets up the task stack so that upon returning from
+     * SVC, the task stack is used again.
+     *
+     * @param pulSystemCallStack The current SP when the SVC was raised.
+     * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
+     */
     void vSystemCallExit( uint32_t * pulSystemCallStack,
                           uint32_t ulLR ) PRIVILEGED_FUNCTION;
 
@@ -530,21 +530,38 @@
 
 #if ( configENABLE_MPU == 1 )
 
-/**
- * @brief Checks whether or not the calling task is privileged.
- *
- * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
- */
+    /**
+     * @brief Checks whether or not the calling task is privileged.
+     *
+     * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
+     */
     BaseType_t xPortIsTaskPrivileged( void ) PRIVILEGED_FUNCTION;
 
 #endif /* configENABLE_MPU == 1 */
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /**
+     * @brief Platform/Application-defined function that wakes up the secondary cores.
+     *
+     * @return pdTRUE if the secondary cores were successfully woken up.
+     *         pdFALSE otherwise.
+     */
+    extern BaseType_t configWAKE_SECONDARY_CORES( void );
+
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
+
+/**
+ * @brief Configures interrupt priorities.
+ */
+void vPortConfigureInterruptPriorities( void ) PRIVILEGED_FUNCTION;
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
 
-/**
- * @brief This variable is set to pdTRUE when the scheduler is started.
- */
+    /**
+     * @brief This variable is set to pdTRUE when the scheduler is started.
+     */
     PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
 
 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
@@ -553,14 +570,22 @@
  * @brief Each task maintains its own interrupt status in the critical nesting
  * variable.
  */
-PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
+#if ( configNUMBER_OF_CORES == 1 )
+    PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0UL;
+#else /* #if ( configNUMBER_OF_CORES == 1 ) */
+    PRIVILEGED_DATA volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ] = { 0 };
+    /* Flags to check if the secondary cores are ready. */
+    PRIVILEGED_DATA volatile uint8_t ucSecondaryCoresReadyFlags[ configNUMBER_OF_CORES - 1 ] = { 0 };
+    /* Flag to indicate that the primary core has completed its initialisation. */
+    PRIVILEGED_DATA volatile uint8_t ucPrimaryCoreInitDoneFlag = 0;
+ #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
 
 #if ( configENABLE_TRUSTZONE == 1 )
 
-/**
- * @brief Saved as part of the task context to indicate which context the
- * task is using on the secure side.
- */
+    /**
+     * @brief Saved as part of the task context to indicate which context the
+     * task is using on the secure side.
+     */
     PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
 #endif /* configENABLE_TRUSTZONE */
 
@@ -579,21 +604,21 @@
 
 #if ( configUSE_TICKLESS_IDLE == 1 )
 
-/**
- * @brief The number of SysTick increments that make up one tick period.
- */
+    /**
+     * @brief The number of SysTick increments that make up one tick period.
+     */
     PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
 
-/**
- * @brief The maximum number of tick periods that can be suppressed is
- * limited by the 24 bit resolution of the SysTick timer.
- */
+    /**
+     * @brief The maximum number of tick periods that can be suppressed is
+     * limited by the 24 bit resolution of the SysTick timer.
+     */
     PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
 
-/**
- * @brief Compensate for the CPU cycles that pass while the SysTick is
- * stopped (low power functionality only).
- */
+    /**
+     * @brief Compensate for the CPU cycles that pass while the SysTick is
+     * stopped (low power functionality only).
+     */
     PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0;
 #endif /* configUSE_TICKLESS_IDLE */
 /*-----------------------------------------------------------*/
@@ -856,7 +881,11 @@
      * should instead call vTaskDelete( NULL ). Artificially force an assert()
      * to be triggered if configASSERT() is defined, then stop here so
      * application writers can catch the error. */
-    configASSERT( ulCriticalNesting == ~0UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == ~0UL );
+    #else /* #if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == ~0UL );
+    #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
     portDISABLE_INTERRUPTS();
 
     while( ulDummy == 0 )
@@ -925,64 +954,57 @@
         /* The only permitted number of regions are 8 or 16. */
         configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 16 ) );
 
-        /* Ensure that the configTOTAL_MPU_REGIONS is configured correctly. */
-        configASSERT( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE );
+        /* MAIR0 - Index 0. */
+        portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
+        /* MAIR0 - Index 1. */
+        portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
 
-        /* Check that the MPU is present. */
-        if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
-        {
-            /* MAIR0 - Index 0. */
-            portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
-            /* MAIR0 - Index 1. */
-            portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
+        /* Setup privileged flash as Read Only so that privileged tasks can
+         * read it but not modify. */
+        portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup privileged flash as Read Only so that privileged tasks can
-             * read it but not modify. */
-            portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged flash as Read Only by both privileged and
+         * unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged flash as Read Only by both privileged and
-             * unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup unprivileged syscalls flash as Read Only by both privileged
+         * and unprivileged tasks. All tasks can read it but no-one can modify. */
+        portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_READ_ONLY );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup unprivileged syscalls flash as Read Only by both privileged
-             * and unprivileged tasks. All tasks can read it but no-one can modify. */
-            portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_READ_ONLY );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Setup RAM containing kernel data for privileged access only. */
+        portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
+        portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
+                           ( portMPU_REGION_NON_SHAREABLE ) |
+                           ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
+                           ( portMPU_REGION_EXECUTE_NEVER );
+        portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
+                           ( portMPU_RLAR_ATTR_INDEX0 ) |
+                           ( portMPU_RLAR_REGION_ENABLE );
 
-            /* Setup RAM containing kernel data for privileged access only. */
-            portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
-            portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
-                               ( portMPU_REGION_NON_SHAREABLE ) |
-                               ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
-                               ( portMPU_REGION_EXECUTE_NEVER );
-            portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
-                               ( portMPU_RLAR_ATTR_INDEX0 ) |
-                               ( portMPU_RLAR_REGION_ENABLE );
+        /* Enable mem fault. */
+        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
 
-            /* Enable mem fault. */
-            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
-
-            /* Enable MPU with privileged background access i.e. unmapped
-             * regions have privileged access. */
-            portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
-        }
+        /* Enable MPU with privileged background access i.e. unmapped
+         * regions have privileged access. */
+        portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
     }
 
 #endif /* configENABLE_MPU */
@@ -1027,28 +1049,29 @@
 }
 /*-----------------------------------------------------------*/
 
-void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    portDISABLE_INTERRUPTS();
-    ulCriticalNesting++;
-
-    /* Barriers are normally not required but do ensure the code is
-     * completely within the specified behaviour for the architecture. */
-    __asm volatile ( "dsb" ::: "memory" );
-    __asm volatile ( "isb" );
-}
-/*-----------------------------------------------------------*/
-
-void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
-{
-    configASSERT( ulCriticalNesting );
-    ulCriticalNesting--;
-
-    if( ulCriticalNesting == 0 )
+#if ( configNUMBER_OF_CORES == 1 )
+    void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
     {
-        portENABLE_INTERRUPTS();
+        portDISABLE_INTERRUPTS();
+        ulCriticalNesting++;
+        /* Barriers are normally not required but do ensure the code is
+        * completely within the specified behaviour for the architecture. */
+        __asm volatile ( "dsb" ::: "memory" );
+        __asm volatile ( "isb" );
     }
-}
+    /*-----------------------------------------------------------*/
+
+    void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
+    {
+        configASSERT( ulCriticalNesting );
+        ulCriticalNesting--;
+
+        if( ulCriticalNesting == 0 )
+        {
+            portENABLE_INTERRUPTS();
+        }
+    }
+#endif /* configNUMBER_OF_CORES == 1 */
 /*-----------------------------------------------------------*/
 
 void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
@@ -1056,6 +1079,10 @@
     uint32_t ulPreviousMask;
 
     ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
+    #if ( configNUMBER_OF_CORES > 1 )
+        UBaseType_t uxSavedInterruptStatus = portENTER_CRITICAL_FROM_ISR();
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     traceISR_ENTER();
     {
         /* Increment the RTOS tick. */
@@ -1070,6 +1097,10 @@
             traceISR_EXIT();
         }
     }
+    #if ( configNUMBER_OF_CORES > 1 )
+        portEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
+
     portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
 }
 /*-----------------------------------------------------------*/
@@ -1078,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1090,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1108,38 +1151,42 @@
 
     switch( ucSVCNumber )
     {
-        #if ( configENABLE_TRUSTZONE == 1 )
-            case portSVC_ALLOCATE_SECURE_CONTEXT:
+    #if ( configENABLE_TRUSTZONE == 1 )
+        case portSVC_ALLOCATE_SECURE_CONTEXT:
 
-                /* R0 contains the stack size passed as parameter to the
-                 * vPortAllocateSecureContext function. */
-                ulR0 = pulCallerStackAddress[ 0 ];
+            /* R0 contains the stack size passed as parameter to the
+             * vPortAllocateSecureContext function. */
+            ulR0 = pulCallerStackAddress[ 0 ];
 
-                #if ( configENABLE_MPU == 1 )
-                {
-                    /* Read the CONTROL register value. */
-                    __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
+            #if ( configENABLE_MPU == 1 )
+            {
+                /* Read the CONTROL register value. */
+                __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
 
-                    /* The task that raised the SVC is privileged if Bit[0]
-                     * in the CONTROL register is 0. */
-                    ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
+                /* The task that raised the SVC is privileged if Bit[0]
+                 * in the CONTROL register is 0. */
+                ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
 
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
-                }
-                #else /* if ( configENABLE_MPU == 1 ) */
-                {
-                    /* Allocate and load a context for the secure task. */
-                    xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
-                }
-                #endif /* configENABLE_MPU */
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
+            }
+            #else /* if ( configENABLE_MPU == 1 ) */
+            {
+                /* Allocate and load a context for the secure task. */
+                xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
+            }
+            #endif /* configENABLE_MPU */
 
-                configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
-                SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
-                break;
+            configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
+            SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
+            break;
 
-            case portSVC_FREE_SECURE_CONTEXT:
-
+        case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
                 /* R0 contains TCB being freed and R1 contains the secure
                  * context handle to be freed. */
                 ulR0 = pulCallerStackAddress[ 0 ];
@@ -1147,51 +1194,62 @@
 
                 /* Free the secure context. */
                 SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
-                break;
-        #endif /* configENABLE_TRUSTZONE */
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
+            break;
+    #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
-            #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
-                case portSVC_RAISE_PRIVILEGE:
+    #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
+        case portSVC_RAISE_PRIVILEGE:
 
-                    /* Only raise the privilege, if the svc was raised from any of
-                     * the system calls. */
-                    if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
-                        ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
-                    {
-                        vRaisePrivilege();
-                    }
-                    break;
-            #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
+            /* Only raise the privilege, if the svc was raised from any of
+             * the system calls. */
+            if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
+                ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
+            {
+                vRaisePrivilege();
+            }
+            break;
+    #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
-            #if ( configENABLE_MPU == 1 )
-                case portSVC_YIELD:
-                    vPortYield();
-                    break;
-            #endif /* configENABLE_MPU == 1 */
+    #if ( configENABLE_MPU == 1 )
+        case portSVC_YIELD:
+            vPortYield();
+            break;
+    #endif /* configENABLE_MPU == 1 */
 
         default:
             /* Incorrect SVC call. */
@@ -1210,7 +1268,7 @@
         extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulSystemCallStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1246,12 +1304,16 @@
         {
             pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1261,20 +1323,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the system call stack for the stack frame. */
-            pulSystemCallStack = pulSystemCallStack - ulStackFrameSize;
+            pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulSystemCallStack[ i ] = pulTaskStack[ i ];
             }
@@ -1310,7 +1372,7 @@
 
             /* Remember the location where we should copy the stack frame when we exit from
              * the system call. */
-            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
+            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
 
             /* Record if the hardware used padding to force the stack pointer
              * to be double word aligned. */
@@ -1360,7 +1422,7 @@
         extern TaskHandle_t pxCurrentTCB;
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulTaskStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
 
         #if defined( __ARMCC_VERSION )
 
@@ -1392,12 +1454,16 @@
         {
             pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
             {
                 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
                 {
                     /* Extended frame i.e. FPU in use. */
-                    ulStackFrameSize = 26;
+                    ulHardwareSavedExceptionFrameSize = 26;
                     __asm volatile (
                         " vpush {s0}         \n" /* Trigger lazy stacking. */
                         " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
@@ -1407,20 +1473,20 @@
                 else
                 {
                     /* Standard frame i.e. FPU not in use. */
-                    ulStackFrameSize = 8;
+                    ulHardwareSavedExceptionFrameSize = 8;
                 }
             }
             #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
             {
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
             #endif /* configENABLE_FPU || configENABLE_MVE */
 
             /* Make space on the task stack for the stack frame. */
-            pulTaskStack = pulTaskStack - ulStackFrameSize;
+            pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulTaskStack[ i ] = pulSystemCallStack[ i ];
             }
@@ -1518,21 +1584,21 @@
         xMPUSettings->ulContext[ ulIndex ] = 0x11111111; /* r11. */
         ulIndex++;
 
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters;            /* r0. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters; /* r0. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x01010101;                           /* r1. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x01010101; /* r1. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x02020202;                           /* r2. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x02020202; /* r2. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x03030303;                           /* r3. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x03030303; /* r3. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = 0x12121212;                           /* r12. */
+        xMPUSettings->ulContext[ ulIndex ] = 0x12121212; /* r12. */
         ulIndex++;
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) portTASK_RETURN_ADDRESS; /* LR. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode;                  /* PC. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode; /* PC. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR;                     /* xPSR. */
+        xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR; /* xPSR. */
         ulIndex++;
 
         #if ( configENABLE_TRUSTZONE == 1 )
@@ -1543,14 +1609,18 @@
         #endif /* configENABLE_TRUSTZONE */
         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) ( pxTopOfStack - 8 ); /* PSP with the hardware saved stack. */
         ulIndex++;
-        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack;         /* PSPLIM. */
+        xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack; /* PSPLIM. */
         ulIndex++;
 
         #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
         {
             /* Check PACBTI security feature configuration before pushing the
              * CONTROL register's value on task's TCB. */
-            ulControl = prvConfigurePACBTI( pdFALSE );
+            #if ( configNUMBER_OF_CORES == 1 )
+                ulControl = prvConfigurePACBTI( pdFALSE );
+            #else /* configNUMBER_OF_CORES > 1 */
+                ulControl = vConfigurePACBTI( pdFALSE );
+            #endif /* configNUMBER_OF_CORES */
         }
         #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1615,15 +1685,15 @@
          * interrupt. */
         #if ( portPRELOAD_REGISTERS == 0 )
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
-            pxTopOfStack -= 5;                                       /* R12, R3, R2 and R1. */
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
-            pxTopOfStack -= 9;                                       /* R11..R4, EXC_RETURN. */
+            pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
+            pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */
             *pxTopOfStack = portINITIAL_EXC_RETURN;
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
@@ -1637,42 +1707,42 @@
         }
         #else /* portPRELOAD_REGISTERS */
         {
-            pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
-            *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
+            pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+            *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
+            *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
             pxTopOfStack--;
             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x12121212UL;            /* R12. */
+            *pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x03030303UL;            /* R3. */
+            *pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x02020202UL;            /* R2. */
+            *pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x01010101UL;            /* R1. */
+            *pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
+            *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x11111111UL;            /* R11. */
+            *pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x10101010UL;            /* R10. */
+            *pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x09090909UL;            /* R09. */
+            *pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x08080808UL;            /* R08. */
+            *pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x07070707UL;            /* R07. */
+            *pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x06060606UL;            /* R06. */
+            *pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x05050505UL;            /* R05. */
+            *pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) 0x04040404UL;            /* R04. */
+            *pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04. */
             pxTopOfStack--;
-            *pxTopOfStack = portINITIAL_EXC_RETURN;                  /* EXC_RETURN. */
+            *pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN. */
             pxTopOfStack--;
-            *pxTopOfStack = ( StackType_t ) pxEndOfStack;            /* Slot used to hold this task's PSPLIM value. */
+            *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
 
             #if ( configENABLE_TRUSTZONE == 1 )
             {
@@ -1739,91 +1809,17 @@
     }
     #endif /* configCHECK_HANDLER_INSTALLATION */
 
-    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
-    {
-        volatile uint32_t ulImplementedPrioBits = 0;
-        volatile uint8_t ucMaxPriorityValue;
-
-        /* Determine the maximum priority from which ISR safe FreeRTOS API
-         * functions can be called. ISR safe functions are those that end in
-         * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
-         * ensure interrupt entry is as fast and simple as possible.
-         *
-         * First, determine the number of priority bits available. Write to all
-         * possible bits in the priority setting for SVCall. */
-        portNVIC_SHPR2_REG = 0xFF000000;
-
-        /* Read the value back to see how many bits stuck. */
-        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
-
-        /* Use the same mask on the maximum system call priority. */
-        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
-
-        /* Check that the maximum system call priority is nonzero after
-         * accounting for the number of priority bits supported by the
-         * hardware. A priority of 0 is invalid because setting the BASEPRI
-         * register to 0 unmasks all interrupts, and interrupts with priority 0
-         * cannot be masked using BASEPRI.
-         * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
-        configASSERT( ucMaxSysCallPriority );
-
-        /* Check that the bits not implemented in hardware are zero in
-         * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
-        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
-
-        /* Calculate the maximum acceptable priority group value for the number
-         * of bits read back. */
-        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
-        {
-            ulImplementedPrioBits++;
-            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
-        }
-
-        if( ulImplementedPrioBits == 8 )
-        {
-            /* When the hardware implements 8 priority bits, there is no way for
-             * the software to configure PRIGROUP to not have sub-priorities. As
-             * a result, the least significant bit is always used for sub-priority
-             * and there are 128 preemption priorities and 2 sub-priorities.
-             *
-             * This may cause some confusion in some cases - for example, if
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
-             * priority interrupts will be masked in Critical Sections as those
-             * are at the same preemption priority. This may appear confusing as
-             * 4 is higher (numerically lower) priority than
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
-             * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
-             * to 4, this confusion does not happen and the behaviour remains the same.
-             *
-             * The following assert ensures that the sub-priority bit in the
-             * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
-             * confusion. */
-            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
-            ulMaxPRIGROUPValue = 0;
-        }
-        else
-        {
-            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
-        }
-
-        /* Shift the priority group value back to its position within the AIRCR
-         * register. */
-        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
-        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
-    }
-    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
-
-    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
-     * the highest priority. */
-    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
-    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
-    portNVIC_SHPR2_REG = 0;
+    vPortConfigureInterruptPriorities();
 
     #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
     {
         /* Set the CONTROL register value based on PACBTI security feature
          * configuration before starting the first task. */
-        ( void ) prvConfigurePACBTI( pdTRUE );
+        #if ( configNUMBER_OF_CORES == 1 )
+            ( void ) prvConfigurePACBTI( pdTRUE );
+        #else /* configNUMBER_OF_CORES > 1 */
+            ( void ) vConfigurePACBTI( pdTRUE );
+        #endif /* configNUMBER_OF_CORES */
     }
     #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 
@@ -1834,12 +1830,47 @@
     }
     #endif /* configENABLE_MPU */
 
-    /* Start the timer that generates the tick ISR. Interrupts are disabled
-     * here already. */
-    vPortSetupTimerInterrupt();
+    #if ( configNUMBER_OF_CORES > 1 )
+        /* Start the timer that generates the tick ISR. Interrupts are disabled
+         * here already. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count for all cores. */
+        for ( uint8_t ucCoreID = 0; ucCoreID < configNUMBER_OF_CORES; ucCoreID++ )
+        {
+            ulCriticalNestings[ ucCoreID ] = 0;
+        }
+        /* Signal that primary core has done all the necessary initialisations. */
+        ucPrimaryCoreInitDoneFlag = 1;
+        /* Wake up secondary cores */
+        BaseType_t xWakeResult = configWAKE_SECONDARY_CORES();
+        configASSERT( xWakeResult == pdTRUE );
 
-    /* Initialize the critical nesting count ready for the first task. */
-    ulCriticalNesting = 0;
+        /* Hold the primary core here until all the secondary cores are ready, this would be achieved only when
+         * all elements of ucSecondaryCoresReadyFlags are set.
+         */
+        while( 1 )
+        {
+            BaseType_t xAllCoresReady = pdTRUE;
+            for( uint8_t ucCoreID = 0; ucCoreID < ( configNUMBER_OF_CORES - 1 ); ucCoreID++ )
+            {
+                if( ucSecondaryCoresReadyFlags[ ucCoreID ] != pdTRUE )
+                {
+                    xAllCoresReady = pdFALSE;
+                    break;
+                }
+                }
+
+            if ( xAllCoresReady == pdTRUE )
+            {
+                break;
+            }
+        }
+    #else /* if ( configNUMBER_OF_CORES > 1 ) */
+        /* Start the timer that generates the tick ISR. */
+        vPortSetupTimerInterrupt();
+        /* Initialize the critical nesting count ready for the first task. */
+        ulCriticalNesting = 0;
+    #endif /* if ( configNUMBER_OF_CORES > 1 ) */
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
     {
@@ -1856,7 +1887,11 @@
      * functionality by defining configTASK_RETURN_ADDRESS. Call
      * vTaskSwitchContext() so link time optimization does not remove the
      * symbol. */
-    vTaskSwitchContext();
+    #if ( configNUMBER_OF_CORES > 1 )
+        vTaskSwitchContext( portGET_CORE_ID() );
+    #else
+        vTaskSwitchContext();
+    #endif
     prvTaskExitError();
 
     /* Should not get here. */
@@ -1868,7 +1903,11 @@
 {
     /* Not implemented in ports where there is nothing to return to.
      * Artificially force an assert. */
-    configASSERT( ulCriticalNesting == 1000UL );
+    #if ( configNUMBER_OF_CORES == 1 )
+        configASSERT( ulCriticalNesting == 1000UL );
+    #else /* if ( configNUMBER_OF_CORES == 1 ) */
+        configASSERT( ulCriticalNestings[ portGET_CORE_ID() ] == 1000UL );
+    #endif /* if ( configNUMBER_OF_CORES == 1 ) */
 }
 /*-----------------------------------------------------------*/
 
@@ -2151,6 +2190,90 @@
 #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
 /*-----------------------------------------------------------*/
 
+void vPortConfigureInterruptPriorities( void ) /* PRIVILEGED_FUNCTION */
+{
+    #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
+    {
+        volatile uint32_t ulImplementedPrioBits = 0;
+        volatile uint8_t ucMaxPriorityValue;
+
+        /* Determine the maximum priority from which ISR safe FreeRTOS API
+        * functions can be called. ISR safe functions are those that end in
+        * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
+        * ensure interrupt entry is as fast and simple as possible.
+        *
+        * First, determine the number of priority bits available. Write to all
+        * possible bits in the priority setting for SVCall. */
+        portNVIC_SHPR2_REG = 0xFF000000;
+
+        /* Read the value back to see how many bits stuck. */
+        ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
+
+        /* Use the same mask on the maximum system call priority. */
+        ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
+
+        /* Check that the maximum system call priority is nonzero after
+        * accounting for the number of priority bits supported by the
+        * hardware. A priority of 0 is invalid because setting the BASEPRI
+        * register to 0 unmasks all interrupts, and interrupts with priority 0
+        * cannot be masked using BASEPRI.
+        * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+        configASSERT( ucMaxSysCallPriority );
+
+        /* Check that the bits not implemented in hardware are zero in
+        * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
+        configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
+
+        /* Calculate the maximum acceptable priority group value for the number
+        * of bits read back. */
+        while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
+        {
+            ulImplementedPrioBits++;
+            ucMaxPriorityValue <<= ( uint8_t ) 0x01;
+        }
+
+        if( ulImplementedPrioBits == 8 )
+        {
+            /* When the hardware implements 8 priority bits, there is no way for
+            * the software to configure PRIGROUP to not have sub-priorities. As
+            * a result, the least significant bit is always used for sub-priority
+            * and there are 128 preemption priorities and 2 sub-priorities.
+            *
+            * This may cause some confusion in some cases - for example, if
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
+            * priority interrupts will be masked in Critical Sections as those
+            * are at the same preemption priority. This may appear confusing as
+            * 4 is higher (numerically lower) priority than
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
+            * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
+            * to 4, this confusion does not happen and the behaviour remains the same.
+            *
+            * The following assert ensures that the sub-priority bit in the
+            * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
+            * confusion. */
+            configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
+            ulMaxPRIGROUPValue = 0;
+        }
+        else
+        {
+            ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
+        }
+
+        /* Shift the priority group value back to its position within the AIRCR
+        * register. */
+        ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
+        ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
+    }
+    #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
+
+    /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
+    * the highest priority. */
+    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
+    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
+    portNVIC_SHPR2_REG = 0;
+}
+/*-----------------------------------------------------------*/
+
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) )
 
     void vPortGrantAccessToKernelObject( TaskHandle_t xInternalTaskHandle,
@@ -2247,36 +2370,214 @@
 /*-----------------------------------------------------------*/
 
 #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
-
-    static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
-    {
-        uint32_t ulControl = 0x0;
-
-        /* Ensure that PACBTI is implemented. */
-        configASSERT( portID_ISAR5_REG != 0x0 );
-
-        /* Enable UsageFault exception. */
-        portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
-
-        #if ( configENABLE_PAC == 1 )
+    #if ( configNUMBER_OF_CORES == 1 )
+        static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #else /* configNUMBER_OF_CORES > 1 */
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister )
+    #endif /* configNUMBER_OF_CORES */
         {
-            ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
-        }
-        #endif
+            uint32_t ulControl = 0x0;
 
-        #if ( configENABLE_BTI == 1 )
-        {
-            ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
-        }
-        #endif
+            /* Ensure that PACBTI is implemented. */
+            configASSERT( portID_ISAR5_REG != 0x0 );
 
-        if( xWriteControlRegister == pdTRUE )
-        {
-            __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
-        }
+            /* Enable UsageFault exception. */
+            portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
 
-        return ulControl;
-    }
+            #if ( configENABLE_PAC == 1 )
+            {
+                ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
+            }
+            #endif
+
+            #if ( configENABLE_BTI == 1 )
+            {
+                ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
+            }
+            #endif
+
+            if( xWriteControlRegister == pdTRUE )
+            {
+                __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
+            }
+
+            return ulControl;
+        }
 
 #endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
 /*-----------------------------------------------------------*/
+
+#if ( configNUMBER_OF_CORES > 1 )
+
+    /* Which core owns the lock? */
+    PRIVILEGED_DATA volatile uint32_t ulOwnedByCore[ portMAX_CORE_COUNT ];
+    /* Lock count a core owns. */
+    PRIVILEGED_DATA volatile uint32_t ulRecursionCountByLock[ eLockCount ];
+    /* Index 0 is used for ISR lock and Index 1 is used for task lock. */
+    PRIVILEGED_DATA volatile uint32_t ulGateWord[ eLockCount ];
+
+    __attribute__((weak)) void vInterruptCore( uint8_t ucCoreID )
+    {
+        /* Default weak stub - platform specific implementation may override. */
+        ( void ) ucCoreID;
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline void prvSpinUnlock( volatile uint32_t * ulLock )
+    {
+        /* Conservative unlock: preserve original barriers for broad HW/FVP. */
+        __asm volatile (
+            "dmb sy         \n"
+            "mov r1, #0     \n"
+            "str r1, [%0]   \n"
+            "sev            \n"
+            "dsb            \n"
+            "isb            \n"
+            :
+            : "r" ( ulLock )
+            : "memory", "r1"
+        );
+    }
+
+/*-----------------------------------------------------------*/
+
+    static inline uint32_t prvSpinTrylock( volatile uint32_t * ulLock )
+    {
+        /*
+         * Conservative ldrex/strex trylock:
+         * - Return 1 immediately if busy, clearing exclusive state (CLREX).
+         * - Retry strex only on spurious failure when observed free.
+         * - DMB on success to preserve expected acquire semantics.
+         */
+        uint32_t ulVal;
+        uint32_t ulStatus;
+
+        __asm volatile (
+            " ldrex %0, [%1]   \n"
+            : "=r" ( ulVal )
+            : "r" ( ulLock )
+            : "memory"
+        );
+
+        if( ulVal != 0U )
+        {
+            __asm volatile ("clrex" ::: "memory");
+            return 1U;
+        }
+
+        __asm volatile (
+            " strex %0, %2, [%1]   \n"
+            : "=&r" ( ulStatus )
+            : "r" ( ulLock ), "r" (1U)
+            : "memory"
+        );
+
+        if( ulStatus != 0U )
+        {
+            return 1U;
+        }
+        __asm volatile ( "dmb" ::: "memory" );
+        return 0U;
+    }
+
+
+/*-----------------------------------------------------------*/
+
+    /* Read 32b value shared between cores. */
+    static inline uint32_t prvGet32( volatile uint32_t * x )
+    {
+        __asm( "dsb" );
+        return *x;
+    }
+
+/*-----------------------------------------------------------*/
+
+    /* Write 32b value shared between cores. */
+    static inline void prvSet32( volatile uint32_t * x,
+                                 uint32_t value )
+    {
+        *x = value;
+        __asm( "dsb" );
+    }
+
+/*-----------------------------------------------------------*/
+
+    void vPortRecursiveLock( uint8_t ucCoreID,
+                             ePortRTOSLock eLockNum,
+                             BaseType_t uxAcquire )
+    {
+        /* Validate the core ID and lock number. */
+        configASSERT( ucCoreID < portMAX_CORE_COUNT );
+        configASSERT( eLockNum < eLockCount );
+
+        uint32_t ulLockBit = 1u << eLockNum;
+
+        /* Lock acquire */
+        if( uxAcquire )
+        {
+            /* Check if spinlock is available. */
+            /* If spinlock is not available check if the core owns the lock. */
+            /* If the core owns the lock wait increment the lock count by the core. */
+            /* If core does not own the lock wait for the spinlock. */
+            if( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+            {
+                /* Check if the core owns the spinlock. */
+                if( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit )
+                {
+                    configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != portUINT32_MAX );
+                    prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) + 1 ) );
+                    return;
+                }
+
+                /* Preload the gate word into the cache. */
+                uint32_t dummy = ulGateWord[ eLockNum ];
+                dummy++;
+
+                while( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
+                {
+                    __asm volatile ( "wfe" );
+                }
+            }
+
+            /* Add barrier to ensure lock is taken before we proceed. */
+            __asm volatile( "dmb sy" ::: "memory" );
+
+            /* Assert the lock count is 0 when the spinlock is free and is acquired. */
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) == 0 );
+
+            /* Set lock count as 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], 1 );
+            /* Set ulOwnedByCore. */
+            prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) | ulLockBit ) );
+        }
+        /* Lock release. */
+        else
+        {
+            /* Assert the lock is not free already. */
+            configASSERT( ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ulLockBit ) != 0 );
+            configASSERT( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) != 0 );
+
+            /* Reduce ulRecursionCountByLock by 1. */
+            prvSet32( &ulRecursionCountByLock[ eLockNum ], ( prvGet32( &ulRecursionCountByLock[ eLockNum ] ) - 1 ) );
+
+            if( !prvGet32( &ulRecursionCountByLock[ eLockNum ] ) )
+            {
+                prvSet32( &ulOwnedByCore[ ucCoreID ], ( prvGet32( &ulOwnedByCore[ ucCoreID ] ) & ~ulLockBit ) );
+                prvSpinUnlock( &ulGateWord[ eLockNum ] );
+                /* Add barrier to ensure lock status is reflected before we proceed. */
+                __asm volatile( "dmb sy" ::: "memory" );
+            }
+        }
+    }
+
+/*-----------------------------------------------------------*/
+
+    uint8_t ucPortGetCoreID( void )
+    {
+        return *(volatile uint8_t *)(configCORE_ID_REGISTER);
+    }
+
+/*-----------------------------------------------------------*/
+
+#endif /* if( configNUMBER_OF_CORES > 1 ) */
diff --git a/Source/portable/IAR/ARM_CM85_NTZ/non_secure/portasm.h b/Source/portable/IAR/ARM_CM85_NTZ/non_secure/portasm.h
index 53b4b6e..b4b545f 100644
--- a/Source/portable/IAR/ARM_CM85_NTZ/non_secure/portasm.h
+++ b/Source/portable/IAR/ARM_CM85_NTZ/non_secure/portasm.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/IAR/ARM_CM85_NTZ/non_secure/portasm.s b/Source/portable/IAR/ARM_CM85_NTZ/non_secure/portasm.s
index 8092255..8de575d 100644
--- a/Source/portable/IAR/ARM_CM85_NTZ/non_secure/portasm.s
+++ b/Source/portable/IAR/ARM_CM85_NTZ/non_secure/portasm.s
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -41,7 +40,15 @@
     #define configUSE_MPU_WRAPPERS_V1 0
 #endif
 
+#ifndef configNUMBER_OF_CORES
+    #define configNUMBER_OF_CORES 1
+#endif
+
+#if ( configNUMBER_OF_CORES == 1)
     EXTERN pxCurrentTCB
+#else /* if ( configNUMBER_OF_CORES == 1) */
+    EXTERN pxCurrentTCBs
+#endif
     EXTERN vTaskSwitchContext
     EXTERN vPortSVCHandler_C
 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
@@ -169,8 +176,15 @@
 #else /* configENABLE_MPU */
 
 vRestoreContextOfFirstTask:
+#if ( configNUMBER_OF_CORES == 1)
     ldr  r2, =pxCurrentTCB                  /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
     ldr  r1, [r2]                           /* Read pxCurrentTCB. */
+#else /* if ( configNUMBER_OF_CORES == 1) */
+    ldr r1, =ulFirstTaskLiteralPool         /* Get the location of the current TCB and the Id of the current core. */
+    ldmia r1!, {r2, r3}
+    ldr r2, [r2]                            /* r2 = Core Id */
+    ldr r1, [r3, r2, LSL #2]                /* r1 = pxCurrentTCBs[CORE_ID] */
+#endif /* if ( configNUMBER_OF_CORES == 1) */
     ldr  r0, [r1]                           /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
 
 #if ( configENABLE_PAC == 1 )
@@ -193,6 +207,13 @@
     mov  r0, #0
     msr  basepri, r0                        /* Ensure that interrupts are enabled when the first task starts. */
     bx   r2                                 /* Finally, branch to EXC_RETURN. */
+#if ( configNUMBER_OF_CORES > 1 )
+    /* Align to 4 bytes in ROM/code area (2^2 alignment, 0 fill). */
+    ALIGNROM 2, 0
+    ulFirstTaskLiteralPool:
+        DC32 configCORE_ID_REGISTER         /* CORE_ID_REGISTER */
+        DC32 pxCurrentTCBs
+#endif /* if ( configNUMBER_OF_CORES > 1 ) */
 
 #endif /* configENABLE_MPU */
 /*-----------------------------------------------------------*/
@@ -377,20 +398,37 @@
     clrm {r1-r4}                            /* Clear r1-r4. */
 #endif /* configENABLE_PAC */
 
+#if ( configNUMBER_OF_CORES == 1)
     ldr r2, =pxCurrentTCB                   /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
     ldr r1, [r2]                            /* Read pxCurrentTCB. */
+#else /* if ( configNUMBER_OF_CORES == 1) */
+    ldr r1, =ulPendSVLiteralPool            /* Get the location of the current TCB and the Id of the current core. */
+    ldmia r1!, {r2, r3}
+    ldr r2, [r2]                            /* r2 = Core Id */
+    ldr r1, [r3, r2, LSL #2]                /* r1 = pxCurrentTCBs[CORE_ID] */
+#endif /* if ( configNUMBER_OF_CORES == 1) */
     str r0, [r1]                            /* Save the new top of stack in TCB. */
 
     mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
     msr basepri, r0                         /* Disable interrupts up to configMAX_SYSCALL_INTERRUPT_PRIORITY. */
     dsb
     isb
+    #if ( configNUMBER_OF_CORES > 1)
+        mov r0, r2                          /* r0 = ucPortGetCoreID() */
+    #endif /* if ( configNUMBER_OF_CORES == 1) */
     bl vTaskSwitchContext
     mov r0, #0                              /* r0 = 0. */
     msr basepri, r0                         /* Enable interrupts. */
 
+#if ( configNUMBER_OF_CORES == 1)
     ldr r2, =pxCurrentTCB                   /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
     ldr r1, [r2]                            /* Read pxCurrentTCB. */
+#else /* if ( configNUMBER_OF_CORES == 1) */
+    ldr r1, =ulPendSVLiteralPool            /* Get the location of the current TCB and the Id of the current core. */
+    ldmia r1!, {r2, r3}
+    ldr r2, [r2]                            /* r2 = Core Id */
+    ldr r1, [r3, r2, LSL #2]                /* r1 = pxCurrentTCBs[CORE_ID] */
+#endif /* if ( configNUMBER_OF_CORES == 1) */
     ldr r0, [r1]                            /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
 
 #if ( configENABLE_PAC == 1 )
@@ -413,6 +451,13 @@
     msr psplim, r2                          /* Restore the PSPLIM register value for the task. */
     msr psp, r0                             /* Remember the new top of stack for the task. */
     bx r3
+#if ( configNUMBER_OF_CORES > 1 )
+    /* Align to 4 bytes in ROM/code area (2^2 alignment, 0 fill). */
+    ALIGNROM 2, 0
+    ulPendSVLiteralPool:
+    DC32 configCORE_ID_REGISTER         /* CORE_ID_REGISTER */
+    DC32 pxCurrentTCBs
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
 
 #endif /* configENABLE_MPU */
 /*-----------------------------------------------------------*/
diff --git a/Source/portable/IAR/ARM_CM85_NTZ/non_secure/portmacro.h b/Source/portable/IAR/ARM_CM85_NTZ/non_secure/portmacro.h
index 2f1676c..4b2faaf 100644
--- a/Source/portable/IAR/ARM_CM85_NTZ/non_secure/portmacro.h
+++ b/Source/portable/IAR/ARM_CM85_NTZ/non_secure/portmacro.h
@@ -1,6 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * Copyright 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -57,6 +58,7 @@
 #define portHAS_ARMV8M_MAIN_EXTENSION    1
 #define portARMV8M_MINOR_VERSION         1
 #define portDONT_DISCARD                 __root
+#define portVALIDATED_FOR_SMP            0
 /*-----------------------------------------------------------*/
 
 /* ARMv8-M common port configurations. */
diff --git a/Source/portable/IAR/ARM_CM85_NTZ/non_secure/portmacrocommon.h b/Source/portable/IAR/ARM_CM85_NTZ/non_secure/portmacrocommon.h
index 2dfac6a..c34fdee 100644
--- a/Source/portable/IAR/ARM_CM85_NTZ/non_secure/portmacrocommon.h
+++ b/Source/portable/IAR/ARM_CM85_NTZ/non_secure/portmacrocommon.h
@@ -1,8 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * Copyright 2024 Arm Limited and/or its affiliates
- * <open-source-office@arm.com>
+ * Copyright 2024, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -59,6 +58,19 @@
     #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h.  Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
 #endif /* configENABLE_TRUSTZONE */
 
+#if ( configNUMBER_OF_CORES > 1 )
+    #if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 )
+        #error "Multi-core SMP is currently only validated for Cortex-M33 non-TrustZone non-MPU port."
+    #endif /* if ( portVALIDATED_FOR_SMP != 1 ) || ( configENABLE_MPU == 1 ) || ( configENABLE_TRUSTZONE == 1 ) ) */
+
+    #ifndef configCORE_ID_REGISTER
+        #error "configCORE_ID_REGISTER must be defined to the address of the register used to identify the core executing the code."
+    #endif /* ifndef configCORE_ID_REGISTER */
+
+    #ifndef configWAKE_SECONDARY_CORES
+        #error "configWAKE_SECONDARY_CORES must be defined to a function that wakes the secondary cores."
+    #endif /* ifndef configWAKE_SECONDARY_CORES */
+#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -428,10 +440,26 @@
 /**
  * @brief Critical section management.
  */
+
+#define portSET_INTERRUPT_MASK()                  ulSetInterruptMask()
+#define portCLEAR_INTERRUPT_MASK( x )             vClearInterruptMask( x )
 #define portSET_INTERRUPT_MASK_FROM_ISR()         ulSetInterruptMask()
 #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x )    vClearInterruptMask( x )
-#define portENTER_CRITICAL()                      vPortEnterCritical()
-#define portEXIT_CRITICAL()                       vPortExitCritical()
+
+#if ( configNUMBER_OF_CORES == 1 )
+    #define portENTER_CRITICAL()                      vPortEnterCritical()
+    #define portEXIT_CRITICAL()                       vPortExitCritical()
+#else /* ( configNUMBER_OF_CORES == 1 ) */
+    extern void vTaskEnterCritical( void );
+    extern void vTaskExitCritical( void );
+    extern UBaseType_t vTaskEnterCriticalFromISR( void );
+    extern void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus );
+
+    #define portENTER_CRITICAL()                      vTaskEnterCritical()
+    #define portEXIT_CRITICAL()                       vTaskExitCritical()
+    #define portENTER_CRITICAL_FROM_ISR()             vTaskEnterCriticalFromISR()
+    #define portEXIT_CRITICAL_FROM_ISR( x )           vTaskExitCriticalFromISR( x )
+#endif /* if ( configNUMBER_OF_CORES != 1 ) */
 /*-----------------------------------------------------------*/
 
 /**
@@ -526,7 +554,7 @@
 /* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION
  * based on whether or not Mainline extension is implemented. */
 #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
-    #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 )
+    #if ( ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) && ( configNUMBER_OF_CORES == 1 ) )
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    1
     #else
         #define configUSE_PORT_OPTIMISED_TASK_SELECTION    0
@@ -573,6 +601,44 @@
 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
 /*-----------------------------------------------------------*/
 
+
+#if ( configNUMBER_OF_CORES > 1 )
+    typedef enum
+    {
+        eIsrLock = 0,
+        eTaskLock,
+        eLockCount
+    } ePortRTOSLock;
+
+    extern volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ];
+    extern void vPortRecursiveLock( uint8_t ucCoreID,
+                                    ePortRTOSLock eLockNum,
+                                    BaseType_t uxAcquire );
+    extern uint8_t ucPortGetCoreID( void );
+    extern void vInterruptCore( uint8_t ucCoreID );
+
+    #define portGET_CORE_ID()                                  ucPortGetCoreID()
+
+    #define portGET_CRITICAL_NESTING_COUNT( xCoreID )          ( ulCriticalNestings[ ( uint8_t ) xCoreID ] )
+    #define portSET_CRITICAL_NESTING_COUNT( xCoreID, x )       ( ulCriticalNestings[ ( uint8_t ) xCoreID ] = ( x ) )
+    #define portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]++ )
+    #define portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID )    ( ulCriticalNestings[ ( uint8_t ) xCoreID ]-- )
+
+    #define portMAX_CORE_COUNT                                 ( configNUMBER_OF_CORES )
+
+    #define portYIELD_CORE( xCoreID )                          vInterruptCore( xCoreID )
+
+    #define portRELEASE_ISR_LOCK( xCoreID )                    vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdFALSE )
+    #define portGET_ISR_LOCK( xCoreID )                        vPortRecursiveLock( ( uint8_t ) xCoreID, eIsrLock, pdTRUE )
+
+    #define portRELEASE_TASK_LOCK( xCoreID )                   vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdFALSE )
+    #define portGET_TASK_LOCK( xCoreID )                       vPortRecursiveLock( ( uint8_t ) xCoreID, eTaskLock, pdTRUE )
+
+    #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
+        uint32_t vConfigurePACBTI( BaseType_t xWriteControlRegister );
+    #endif /* ( configENABLE_PAC == 1 || configENABLE_BTI == 1 ) */
+#endif
+
 /* *INDENT-OFF* */
 #ifdef __cplusplus
     }
diff --git a/Source/portable/MemMang/heap_1.c b/Source/portable/MemMang/heap_1.c
index 30f3e13..08a3ec1 100644
--- a/Source/portable/MemMang/heap_1.c
+++ b/Source/portable/MemMang/heap_1.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/MemMang/heap_2.c b/Source/portable/MemMang/heap_2.c
index 0c6f3c2..5832a7d 100644
--- a/Source/portable/MemMang/heap_2.c
+++ b/Source/portable/MemMang/heap_2.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/MemMang/heap_3.c b/Source/portable/MemMang/heap_3.c
index e64c89c..89ca036 100644
--- a/Source/portable/MemMang/heap_3.c
+++ b/Source/portable/MemMang/heap_3.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/MemMang/heap_4.c b/Source/portable/MemMang/heap_4.c
index ef2db1c..cb47359 100644
--- a/Source/portable/MemMang/heap_4.c
+++ b/Source/portable/MemMang/heap_4.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -572,7 +572,7 @@
 void vPortGetHeapStats( HeapStats_t * pxHeapStats )
 {
     BlockLink_t * pxBlock;
-    size_t xBlocks = 0, xMaxSize = 0, xMinSize = portMAX_DELAY; /* portMAX_DELAY used as a portable way of getting the maximum value. */
+    size_t xBlocks = 0, xMaxSize = 0, xMinSize = SIZE_MAX;
 
     vTaskSuspendAll();
     {
diff --git a/Source/portable/MemMang/heap_5.c b/Source/portable/MemMang/heap_5.c
index dcfcca7..b5fdad2 100644
--- a/Source/portable/MemMang/heap_5.c
+++ b/Source/portable/MemMang/heap_5.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -284,7 +284,14 @@
                 {
                     pxPreviousBlock = pxBlock;
                     pxBlock = heapPROTECT_BLOCK_POINTER( pxBlock->pxNextFreeBlock );
-                    heapVALIDATE_BLOCK_POINTER( pxBlock );
+
+                    /* pxEnd is the end marker of the free list. It is located at
+                     * pucHeapHighAddress and is not part of the usable heap, so it
+                     * must be excluded from the heap block pointer validation. */
+                    if( pxBlock != pxEnd )
+                    {
+                        heapVALIDATE_BLOCK_POINTER( pxBlock );
+                    }
                 }
 
                 /* If the end marker was reached then a block of adequate size
@@ -672,7 +679,7 @@
 void vPortGetHeapStats( HeapStats_t * pxHeapStats )
 {
     BlockLink_t * pxBlock;
-    size_t xBlocks = 0, xMaxSize = 0, xMinSize = portMAX_DELAY; /* portMAX_DELAY used as a portable way of getting the maximum value. */
+    size_t xBlocks = 0, xMaxSize = 0, xMinSize = SIZE_MAX;
 
     vTaskSuspendAll();
     {
diff --git a/Source/portable/RVDS/ARM_CA9/port.c b/Source/portable/RVDS/ARM_CA9/port.c
index 9fe6e4a..4b62e98 100644
--- a/Source/portable/RVDS/ARM_CA9/port.c
+++ b/Source/portable/RVDS/ARM_CA9/port.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/RVDS/ARM_CA9/portASM.s b/Source/portable/RVDS/ARM_CA9/portASM.s
index 7184d22..2f934fd 100644
--- a/Source/portable/RVDS/ARM_CA9/portASM.s
+++ b/Source/portable/RVDS/ARM_CA9/portASM.s
@@ -1,5 +1,5 @@
 ;/*
-; * FreeRTOS Kernel V11.2.0
+; * FreeRTOS Kernel V11.3.1
 ; * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 ; *
 ; * SPDX-License-Identifier: MIT
diff --git a/Source/portable/RVDS/ARM_CA9/portmacro.h b/Source/portable/RVDS/ARM_CA9/portmacro.h
index d59527d..37055dc 100644
--- a/Source/portable/RVDS/ARM_CA9/portmacro.h
+++ b/Source/portable/RVDS/ARM_CA9/portmacro.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/RVDS/ARM_CA9/portmacro.inc b/Source/portable/RVDS/ARM_CA9/portmacro.inc
index 574069d..c921cac 100644
--- a/Source/portable/RVDS/ARM_CA9/portmacro.inc
+++ b/Source/portable/RVDS/ARM_CA9/portmacro.inc
@@ -1,5 +1,5 @@
 ;/*
-; * FreeRTOS Kernel V11.2.0
+; * FreeRTOS Kernel V11.3.1
 ; * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 ; *
 ; * SPDX-License-Identifier: MIT
diff --git a/Source/portable/RVDS/ARM_CM0/port.c b/Source/portable/RVDS/ARM_CM0/port.c
index 378a850..a8a1d8b 100644
--- a/Source/portable/RVDS/ARM_CM0/port.c
+++ b/Source/portable/RVDS/ARM_CM0/port.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/RVDS/ARM_CM0/portmacro.h b/Source/portable/RVDS/ARM_CM0/portmacro.h
index 5fad46d..650fe66 100644
--- a/Source/portable/RVDS/ARM_CM0/portmacro.h
+++ b/Source/portable/RVDS/ARM_CM0/portmacro.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/RVDS/ARM_CM3/port.c b/Source/portable/RVDS/ARM_CM3/port.c
index 9f95488..e38c162 100644
--- a/Source/portable/RVDS/ARM_CM3/port.c
+++ b/Source/portable/RVDS/ARM_CM3/port.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/RVDS/ARM_CM3/portmacro.h b/Source/portable/RVDS/ARM_CM3/portmacro.h
index 71e4983..1ba54e1 100644
--- a/Source/portable/RVDS/ARM_CM3/portmacro.h
+++ b/Source/portable/RVDS/ARM_CM3/portmacro.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/RVDS/ARM_CM4F/port.c b/Source/portable/RVDS/ARM_CM4F/port.c
index 54c53ce..61055e2 100644
--- a/Source/portable/RVDS/ARM_CM4F/port.c
+++ b/Source/portable/RVDS/ARM_CM4F/port.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/RVDS/ARM_CM4F/portmacro.h b/Source/portable/RVDS/ARM_CM4F/portmacro.h
index 1ed12dd..fc0b9c4 100644
--- a/Source/portable/RVDS/ARM_CM4F/portmacro.h
+++ b/Source/portable/RVDS/ARM_CM4F/portmacro.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/RVDS/ARM_CM4_MPU/mpu_wrappers_v2_asm.c b/Source/portable/RVDS/ARM_CM4_MPU/mpu_wrappers_v2_asm.c
index 76a50bb..c46c9e3 100644
--- a/Source/portable/RVDS/ARM_CM4_MPU/mpu_wrappers_v2_asm.c
+++ b/Source/portable/RVDS/ARM_CM4_MPU/mpu_wrappers_v2_asm.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/RVDS/ARM_CM4_MPU/port.c b/Source/portable/RVDS/ARM_CM4_MPU/port.c
index a491d4b..824c225 100644
--- a/Source/portable/RVDS/ARM_CM4_MPU/port.c
+++ b/Source/portable/RVDS/ARM_CM4_MPU/port.c
@@ -1,6 +1,8 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * Copyright 2025 Arm Limited and/or its affiliates
+ * <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -46,9 +48,19 @@
 
 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
 
+/* Unprivileged critical sections are not supported when using MPU wrappers
+ * version 2. Default the option to 0 and reject an explicit value of 1. */
 #ifndef configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS
-    #warning "configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS is not defined. We recommend defining it to 0 in FreeRTOSConfig.h for better security."
-    #define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS    1
+    #if ( configUSE_MPU_WRAPPERS_V1 == 0 )
+        #define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS    0
+    #else
+        #warning "configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS is not defined. We recommend defining it to 0 in FreeRTOSConfig.h for better security."
+        #define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS    1
+    #endif
+#else
+    #if ( ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) )
+        #error configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS is not supported with MPU wrappers version 2 ( configUSE_MPU_WRAPPERS_V1 == 0 ).
+    #endif
 #endif
 
 /* Prototype of all Interrupt Service Routines (ISRs). */
@@ -474,7 +486,7 @@
         extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulSystemCallStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i, r1;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i, r1;
         extern uint32_t __syscalls_flash_start__;
         extern uint32_t __syscalls_flash_end__;
 
@@ -500,23 +512,27 @@
         {
             pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
             {
                 /* Extended frame i.e. FPU in use. */
-                ulStackFrameSize = 26;
+                ulHardwareSavedExceptionFrameSize = 26;
                 prvTriggerLazyStacking();
             }
             else
             {
                 /* Standard frame i.e. FPU not in use. */
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
 
             /* Make space on the system call stack for the stack frame. */
-            pulSystemCallStack = pulSystemCallStack - ulStackFrameSize;
+            pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulSystemCallStack[ i ] = pulTaskStack[ i ];
             }
@@ -537,7 +553,7 @@
 
             /* Remember the location where we should copy the stack frame when we exit from
              * the system call. */
-            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
+            pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
 
             /* Store the value of the Link Register before the SVC was raised.
              * It contains the address of the caller of the System Call entry
@@ -592,7 +608,7 @@
         extern TaskHandle_t pxCurrentTCB;
         xMPU_SETTINGS * pxMpuSettings;
         uint32_t * pulTaskStack;
-        uint32_t ulStackFrameSize, ulSystemCallLocation, i, r1;
+        uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i, r1;
         extern uint32_t __privileged_functions_start__;
         extern uint32_t __privileged_functions_end__;
 
@@ -614,23 +630,27 @@
         {
             pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
 
+            /* Hardware Saved Stack Frame Size upon Exception entry:
+             * - No FPU: basic frame (R0-R3, R12, LR, PC, and xPSR) = 8 words.
+             * - With FPU (lazy stacking): basic frame + S0–S15 + FPSCR + reserved word = 26 words.
+             */
             if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
             {
                 /* Extended frame i.e. FPU in use. */
-                ulStackFrameSize = 26;
+                ulHardwareSavedExceptionFrameSize = 26;
                 prvTriggerLazyStacking();
             }
             else
             {
                 /* Standard frame i.e. FPU not in use. */
-                ulStackFrameSize = 8;
+                ulHardwareSavedExceptionFrameSize = 8;
             }
 
             /* Make space on the task stack for the stack frame. */
-            pulTaskStack = pulTaskStack - ulStackFrameSize;
+            pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
 
             /* Copy the stack frame. */
-            for( i = 0; i < ulStackFrameSize; i++ )
+            for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
             {
                 pulTaskStack[ i ] = pulSystemCallStack[ i ];
             }
@@ -1331,7 +1351,7 @@
     }
 
     /* Shift the code by one before returning so it can be written directly
-     * into the the correct bit position of the attribute register. */
+     * into the correct bit position of the attribute register. */
     return( ulReturnValue << 1UL );
 }
 /*-----------------------------------------------------------*/
diff --git a/Source/portable/RVDS/ARM_CM4_MPU/portmacro.h b/Source/portable/RVDS/ARM_CM4_MPU/portmacro.h
index 9a6e37d..e2741ab 100644
--- a/Source/portable/RVDS/ARM_CM4_MPU/portmacro.h
+++ b/Source/portable/RVDS/ARM_CM4_MPU/portmacro.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/RVDS/ARM_CM7/r0p1/port.c b/Source/portable/RVDS/ARM_CM7/r0p1/port.c
index 1d0e460..7294dec 100644
--- a/Source/portable/RVDS/ARM_CM7/r0p1/port.c
+++ b/Source/portable/RVDS/ARM_CM7/r0p1/port.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/RVDS/ARM_CM7/r0p1/portmacro.h b/Source/portable/RVDS/ARM_CM7/r0p1/portmacro.h
index ef1389a..9cb7a51 100644
--- a/Source/portable/RVDS/ARM_CM7/r0p1/portmacro.h
+++ b/Source/portable/RVDS/ARM_CM7/r0p1/portmacro.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/Tasking/ARM_CM4F/port.c b/Source/portable/Tasking/ARM_CM4F/port.c
index 577bbb8..bf0466b 100644
--- a/Source/portable/Tasking/ARM_CM4F/port.c
+++ b/Source/portable/Tasking/ARM_CM4F/port.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/Tasking/ARM_CM4F/port_asm.asm b/Source/portable/Tasking/ARM_CM4F/port_asm.asm
index 3022668..15308ae 100644
--- a/Source/portable/Tasking/ARM_CM4F/port_asm.asm
+++ b/Source/portable/Tasking/ARM_CM4F/port_asm.asm
@@ -1,5 +1,5 @@
 ;/*
-; * FreeRTOS Kernel V11.2.0
+; * FreeRTOS Kernel V11.3.1
 ; * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 ; *
 ; * SPDX-License-Identifier: MIT
diff --git a/Source/portable/Tasking/ARM_CM4F/portmacro.h b/Source/portable/Tasking/ARM_CM4F/portmacro.h
index 0f2e3be..02907d5 100644
--- a/Source/portable/Tasking/ARM_CM4F/portmacro.h
+++ b/Source/portable/Tasking/ARM_CM4F/portmacro.h
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
diff --git a/Source/portable/ThirdParty/GCC/ARM_TFM/README.md b/Source/portable/ThirdParty/GCC/ARM_TFM/README.md
new file mode 100644
index 0000000..c419a01
--- /dev/null
+++ b/Source/portable/ThirdParty/GCC/ARM_TFM/README.md
@@ -0,0 +1,80 @@
+# Target of this port
+
+This port adds the support that FreeRTOS applications can call the secure
+services in Trusted Firmware M(TF-M) through Platform Security Architecture
+(PSA) API based on the ARM Cortex-M23, Cortex-M33, Cortex-M52, Cortex-M55,
+Cortex-M85 and Arm China STAR-MC3 platform.
+
+The Platform Security Architecture (PSA) makes it quicker, easier and cheaper
+to design security into a device from the ground up. PSA is made up of four key
+stages: analyze, architect, implement, and certify. See [PSA Resource Page](https://www.arm.com/architecture/security-features/platform-security).
+
+TF-M is an open source project. It provides a reference implementation of PSA
+for Arm M-profile architecture. Please get the details from this [link](https://www.trustedfirmware.org/projects/tf-m/).
+
+# Derivation of the source code
+
+* `os_wrapper_freertos.c`
+  The implementation of APIs which are defined in `/interface/include/os_wrapper/mutex.h`
+  in trusted-firmware-m (tag: TF-Mv2.0.0). The implementation is based on
+  FreeRTOS mutex type semaphore.
+
+# Usage notes
+
+To build a project based on this port:
+* Step 1: build the secure image. Please follow the **Build the Secure Side** section for details.
+* Step 2: build the nonsecure image. Please follow the **Build the Non-Secure Side** for details.
+
+## Build the Secure Side
+
+### Get the TF-M source code
+
+See the [link](https://git.trustedfirmware.org/TF-M/trusted-firmware-m.git/) to get the source code. This port is supported by TF-M version **tag: TF-Mv2.0.0**.
+
+### Build TF-M
+
+Please refer to this [link](https://trustedfirmware-m.readthedocs.io/en/latest/getting_started/) to build the secure side.
+_**Note:** `TFM_NS_MANAGE_NSID` must be configured as "OFF" when building TF-M_.
+
+## Build the Non-Secure Side
+
+Please copy all the files in `freertos_kernel/portable/GCC/ARM_[CM23|CM33|CM52|CM55|CM85|STAR_MC3]_NTZ` into the `freertos_kernel/portable/ThirdParty/GCC/ARM_TFM` folder before using this port. Note that TrustZone is enabled in this port. The TF-M runs in the Secure Side.
+
+Please call the API `tfm_ns_interface_init()` which is defined in `/interface/src/os_wrapper/tfm_ns_interface_rtos.c` by trusted-firmware-m (tag: TF-Mv2.0.0) at the very beginning of your application. Otherwise, it will always fail when calling a TF-M service in the Nonsecure Side.
+
+### Configuration in FreeRTOS kernel
+
+* `configRUN_FREERTOS_SECURE_ONLY`
+This macro should be configured as 0. In this port, TF-M runs in the Secure Side while FreeRTOS
+Kernel runs in the Non-Secure Side.
+
+* `configENABLE_FPU`
+The setting of this macro is decided by the setting in Secure Side which is platform-specific.
+If the Secure Side enables Non-Secure access to FPU, then this macro can be configured as 0 or 1. Otherwise, this macro can only be configured as 0.
+Please note that Cortex-M23 does not support FPU.
+Please refer to [TF-M documentation](https://trustedfirmware-m.readthedocs.io/en/latest/integration_guide/tfm_fpu_support.html) for FPU usage on the Non-Secure side.
+
+* `configENABLE_MVE`
+The setting of this macro is decided by the setting in Secure Side which is platform-specific.
+If the Secure Side enables Non-Secure access to MVE, then this macro can be configured as 0 or 1. Otherwise, this macro can only be configured as 0.
+Please note that only Cortex-M52, Cortex-M55, Cortex-M85 and STAR-MC3 support MVE.
+Please refer to [TF-M documentation](https://trustedfirmware-m.readthedocs.io/en/latest/integration_guide/tfm_fpu_support.html) for MVE usage on the Non-Secure side.
+
+* `configENABLE_TRUSTZONE`
+This macro should be configured as 0 because TF-M doesn't use the secure context management function of FreeRTOS. New secure context management might be introduced when TF-M supports multiple secure context.
+
+
+### Integrate TF-M Non-Secure interface with FreeRTOS project
+
+To enable calling TF-M services by the Non-Secure Side, the files below should be included in the FreeRTOS project and built together.
+* files in `trusted-firmware-m/build/api_ns/interface/src`
+  These files contain the implementation of PSA Functional Developer APIs which can be called by Non-Secure Side directly and PSA Firmware Framework APIs in the IPC model. These files should be taken as part of the Non-Secure source code.
+* files in `trusted-firmware-m/build/api_ns/interface/include`
+  These files are the necessary header files to call TF-M services.
+* `trusted-firmware-m/build/api_ns/interface/lib/s_veneers.o`
+  This object file contains all the Non-Secure callable functions exported by
+  TF-M and it should be linked when generating the Non-Secure image.
+
+
+
+*Copyright (c) 2020-2024, Arm Limited. All rights reserved.*
diff --git a/Source/portable/ThirdParty/GCC/ARM_TFM/os_wrapper_freertos.c b/Source/portable/ThirdParty/GCC/ARM_TFM/os_wrapper_freertos.c
new file mode 100644
index 0000000..35add2b
--- /dev/null
+++ b/Source/portable/ThirdParty/GCC/ARM_TFM/os_wrapper_freertos.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2019-2024, Arm Limited. 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.
+ *
+ */
+
+/*
+ * This file contains the implementation of APIs which are defined in
+ * \interface/include/os_wrapper/mutex.h by TF-M(tag: TF-Mv2.0.0).
+ * The implementation is based on FreeRTOS mutex type semaphore.
+ */
+
+#include "os_wrapper/mutex.h"
+
+#include "FreeRTOS.h"
+#include "semphr.h"
+#include "mpu_wrappers.h"
+
+#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+
+/*
+ * In the static allocation, the RAM is required to hold the semaphore's
+ * state.
+ */
+    StaticSemaphore_t xSecureMutexBuffer;
+#endif
+
+void * os_wrapper_mutex_create( void )
+{
+    SemaphoreHandle_t xMutexHandle = NULL;
+
+    #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+        xMutexHandle = xSemaphoreCreateMutex();
+    #elif ( configSUPPORT_STATIC_ALLOCATION == 1 )
+        xMutexHandle = xSemaphoreCreateMutexStatic( &xSecureMutexBuffer );
+    #endif
+    return ( void * ) xMutexHandle;
+}
+/*-----------------------------------------------------------*/
+
+uint32_t os_wrapper_mutex_acquire( void * handle,
+                                   uint32_t timeout )
+{
+    BaseType_t xRet;
+
+    if( !handle )
+    {
+        return OS_WRAPPER_ERROR;
+    }
+
+    xRet = xSemaphoreTake( ( SemaphoreHandle_t ) handle,
+                           ( timeout == OS_WRAPPER_WAIT_FOREVER ) ?
+                           portMAX_DELAY : ( TickType_t ) timeout );
+
+    if( xRet != pdPASS )
+    {
+        return OS_WRAPPER_ERROR;
+    }
+    else
+    {
+        return OS_WRAPPER_SUCCESS;
+    }
+}
+/*-----------------------------------------------------------*/
+
+uint32_t os_wrapper_mutex_release( void * handle )
+{
+    BaseType_t xRet;
+
+    if( !handle )
+    {
+        return OS_WRAPPER_ERROR;
+    }
+
+    xRet = xSemaphoreGive( ( SemaphoreHandle_t ) handle );
+
+    if( xRet != pdPASS )
+    {
+        return OS_WRAPPER_ERROR;
+    }
+    else
+    {
+        return OS_WRAPPER_SUCCESS;
+    }
+}
+/*-----------------------------------------------------------*/
+
+uint32_t os_wrapper_mutex_delete( void * handle )
+{
+    vSemaphoreDelete( ( SemaphoreHandle_t ) handle );
+
+    return OS_WRAPPER_SUCCESS;
+}
+/*-----------------------------------------------------------*/
diff --git a/Source/queue.c b/Source/queue.c
index 48156f4..00d1a41 100644
--- a/Source/queue.c
+++ b/Source/queue.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -563,7 +563,7 @@
         return pxNewQueue;
     }
 
-#endif /* configSUPPORT_STATIC_ALLOCATION */
+#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
 /*-----------------------------------------------------------*/
 
 static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength,
@@ -833,6 +833,10 @@
         if( pxMutex->u.xSemaphore.xMutexHolder == xTaskGetCurrentTaskHandle() )
         {
             ( pxMutex->u.xSemaphore.uxRecursiveCallCount )++;
+
+            /* Check if an overflow occurred. */
+            configASSERT( pxMutex->u.xSemaphore.uxRecursiveCallCount );
+
             xReturn = pdPASS;
         }
         else
@@ -845,6 +849,9 @@
             if( xReturn != pdFAIL )
             {
                 ( pxMutex->u.xSemaphore.uxRecursiveCallCount )++;
+
+                /* Check if an overflow occurred. */
+                configASSERT( pxMutex->u.xSemaphore.uxRecursiveCallCount );
             }
             else
             {
@@ -1168,9 +1175,8 @@
 
     traceENTER_xQueueGenericSendFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken, xCopyPosition );
 
-    configASSERT( pxQueue );
-    configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
-    configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
+    configASSERT( ( pxQueue != NULL ) && !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
+    configASSERT( ( pxQueue != NULL ) && !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
 
     /* RTOS ports that support interrupt nesting have the concept of a maximum
      * system call (or maximum API call) interrupt priority.  Interrupts that are
@@ -1344,16 +1350,14 @@
      * not (i.e. has a task with a higher priority than us been woken by this
      * post). */
 
-    configASSERT( pxQueue );
-
     /* xQueueGenericSendFromISR() should be used instead of xQueueGiveFromISR()
      * if the item size is not 0. */
-    configASSERT( pxQueue->uxItemSize == 0 );
+    configASSERT( ( pxQueue != NULL ) && ( pxQueue->uxItemSize == 0 ) );
 
     /* Normally a mutex would not be given from an interrupt, especially if
      * there is a mutex holder, as priority inheritance makes no sense for an
-     * interrupts, only tasks. */
-    configASSERT( !( ( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) && ( pxQueue->u.xSemaphore.xMutexHolder != NULL ) ) );
+     * interrupt, only tasks. */
+    configASSERT( ( pxQueue != NULL ) && !( ( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) && ( pxQueue->u.xSemaphore.xMutexHolder != NULL ) ) );
 
     /* RTOS ports that support interrupt nesting have the concept of a maximum
      * system call (or maximum API call) interrupt priority.  Interrupts that are
@@ -1888,12 +1892,9 @@
 
     traceENTER_xQueuePeek( xQueue, pvBuffer, xTicksToWait );
 
-    /* Check the pointer is not NULL. */
-    configASSERT( ( pxQueue ) );
-
     /* The buffer into which data is received can only be NULL if the data size
      * is zero (so no data is copied into the buffer. */
-    configASSERT( !( ( ( pvBuffer ) == NULL ) && ( ( pxQueue )->uxItemSize != ( UBaseType_t ) 0U ) ) );
+    configASSERT( ( pxQueue != NULL ) && !( ( ( pvBuffer ) == NULL ) && ( ( pxQueue )->uxItemSize != ( UBaseType_t ) 0U ) ) );
 
     /* Cannot block if the scheduler is suspended. */
     #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
@@ -2145,9 +2146,8 @@
 
     traceENTER_xQueuePeekFromISR( xQueue, pvBuffer );
 
-    configASSERT( pxQueue );
-    configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
-    configASSERT( pxQueue->uxItemSize != 0 ); /* Can't peek a semaphore. */
+    configASSERT( ( pxQueue != NULL ) && !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
+    configASSERT( ( pxQueue != NULL ) && ( pxQueue->uxItemSize != 0 ) ); /* Can't peek a semaphore. */
 
     /* RTOS ports that support interrupt nesting have the concept of a maximum
      * system call (or maximum API call) interrupt priority.  Interrupts that are
@@ -2261,6 +2261,8 @@
     traceENTER_vQueueDelete( xQueue );
 
     configASSERT( pxQueue );
+    configASSERT( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) );
+    configASSERT( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) );
     traceQUEUE_DELETE( pxQueue );
 
     #if ( configQUEUE_REGISTRY_SIZE > 0 )
@@ -3223,7 +3225,16 @@
 
         taskENTER_CRITICAL();
         {
-            if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL )
+            if( ( ( Queue_t * ) xQueueSet )->uxItemSize != ( UBaseType_t ) sizeof( Queue_t * ) )
+            {
+                /* The object passed as the queue set is not a queue set. A queue
+                 * set always has an item size of sizeof( Queue_t * ). Reject any
+                 * other object to prevent a type confusion in which
+                 * prvNotifyQueueSetContainer() would later copy uxItemSize bytes
+                 * from a single pointer on the stack. */
+                xReturn = pdFAIL;
+            }
+            else if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL )
             {
                 /* Cannot add a queue/semaphore to more than one queue set. */
                 xReturn = pdFAIL;
@@ -3343,6 +3354,8 @@
         configASSERT( pxQueueSetContainer ); /* LCOV_EXCL_BR_LINE */
         configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength );
 
+        /* pxQueue->pxQueueSetContainer is verified to be non-null by caller. */
+        /* coverity[dereference] */
         if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength )
         {
             const int8_t cTxLock = pxQueueSetContainer->cTxLock;
diff --git a/Source/st_readme.txt b/Source/st_readme.txt
index 6915e1b..dc30fbf 100644
--- a/Source/st_readme.txt
+++ b/Source/st_readme.txt
@@ -31,6 +31,16 @@
   @endverbatim
 
 =======
+### 16-October-2026 ###
+=========================
++ FreeRTOS: Update to FreeRTOS v11.3.1
+
++ Add folder ARMClang
+
++ CMSIS_RTOS_V2 update against the latest CMSIS-FreeRTOS v11.3.1 release
+    - CMSIS_RTOS_V2/cmsis_os2.c
+    - CMSIS_RTOS_V2/freertos_os2.h
+
 ### 27-March-2026 ###
 =========================
   + Add SW_Security_Level.md file
diff --git a/Source/stream_buffer.c b/Source/stream_buffer.c
index 66a7d07..2736156 100644
--- a/Source/stream_buffer.c
+++ b/Source/stream_buffer.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -257,13 +257,22 @@
 static size_t prvBytesInBuffer( const StreamBuffer_t * const pxStreamBuffer ) PRIVILEGED_FUNCTION;
 
 /*
+ * Returns pdTRUE when the amount of buffered data should unblock a task that
+ * is waiting to receive data. Stream batching buffers require the buffered
+ * data to exceed the trigger level, whereas stream and message buffers unblock
+ * when the trigger level is reached.
+ */
+static BaseType_t prvBytesInBufferMeetTriggerLevel( const StreamBuffer_t * const pxStreamBuffer,
+                                                    size_t xBytesInBuffer ) PRIVILEGED_FUNCTION;
+
+/*
  * Add xCount bytes from pucData into the pxStreamBuffer's data storage area.
  * This function does not update the buffer's xHead pointer, so multiple writes
  * may be chained together "atomically". This is useful for Message Buffers where
  * the length and data bytes are written in two separate chunks, and we don't want
  * the reader to see the buffer as having grown until after all data is copied over.
  * This function takes a custom xHead value to indicate where to write to (necessary
- * for chaining) and returns the the resulting xHead position.
+ * for chaining) and returns the resulting xHead position.
  * To mark the write as complete, manually set the buffer's xHead field with the
  * returned xHead from this function.
  */
@@ -305,7 +314,7 @@
  * the writer to see the buffer as having more free space until after all data is
  * copied over, especially if we have to abort the read due to insufficient receiving space.
  * This function takes a custom xTail value to indicate where to read from (necessary
- * for chaining) and returns the the resulting xTail position.
+ * for chaining) and returns the resulting xTail position.
  * To mark the read as complete, manually set the buffer's xTail field with the
  * returned xTail from this function.
  */
@@ -919,7 +928,7 @@
         traceSTREAM_BUFFER_SEND( xStreamBuffer, xReturn );
 
         /* Was a task waiting for the data? */
-        if( prvBytesInBuffer( pxStreamBuffer ) >= pxStreamBuffer->xTriggerLevelBytes )
+        if( prvBytesInBufferMeetTriggerLevel( pxStreamBuffer, prvBytesInBuffer( pxStreamBuffer ) ) != pdFALSE )
         {
             prvSEND_COMPLETED( pxStreamBuffer );
         }
@@ -961,6 +970,9 @@
     if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
     {
         xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH;
+
+        /* Overflow? */
+        configASSERT( xRequiredSpace > xDataLengthBytes );
     }
     else
     {
@@ -973,7 +985,7 @@
     if( xReturn > ( size_t ) 0 )
     {
         /* Was a task waiting for the data? */
-        if( prvBytesInBuffer( pxStreamBuffer ) >= pxStreamBuffer->xTriggerLevelBytes )
+        if( prvBytesInBufferMeetTriggerLevel( pxStreamBuffer, prvBytesInBuffer( pxStreamBuffer ) ) != pdFALSE )
         {
             /* MISRA Ref 4.7.1 [Return value shall be checked] */
             /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#dir-47 */
@@ -1584,6 +1596,35 @@
 }
 /*-----------------------------------------------------------*/
 
+static BaseType_t prvBytesInBufferMeetTriggerLevel( const StreamBuffer_t * const pxStreamBuffer,
+                                                    size_t xBytesInBuffer )
+{
+    BaseType_t xReturn = pdFALSE;
+
+    if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_BATCHING_BUFFER ) != ( uint8_t ) 0 )
+    {
+        if( xBytesInBuffer > pxStreamBuffer->xTriggerLevelBytes )
+        {
+            xReturn = pdTRUE;
+        }
+        else
+        {
+            mtCOVERAGE_TEST_MARKER();
+        }
+    }
+    else if( xBytesInBuffer >= pxStreamBuffer->xTriggerLevelBytes )
+    {
+        xReturn = pdTRUE;
+    }
+    else
+    {
+        mtCOVERAGE_TEST_MARKER();
+    }
+
+    return xReturn;
+}
+/*-----------------------------------------------------------*/
+
 static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
                                           uint8_t * const pucBuffer,
                                           size_t xBufferSizeBytes,
@@ -1653,11 +1694,9 @@
 
     traceENTER_vStreamBufferSetStreamBufferNotificationIndex( xStreamBuffer, uxNotificationIndex );
 
-    configASSERT( pxStreamBuffer );
-
     /* There should be no task waiting otherwise we'd never resume them. */
-    configASSERT( pxStreamBuffer->xTaskWaitingToReceive == NULL );
-    configASSERT( pxStreamBuffer->xTaskWaitingToSend == NULL );
+    configASSERT( ( pxStreamBuffer != NULL ) && ( pxStreamBuffer->xTaskWaitingToReceive == NULL ) );
+    configASSERT( ( pxStreamBuffer != NULL ) && ( pxStreamBuffer->xTaskWaitingToSend == NULL ) );
 
     /* Check that the task notification index is valid. */
     configASSERT( uxNotificationIndex < configTASK_NOTIFICATION_ARRAY_ENTRIES );
diff --git a/Source/tasks.c b/Source/tasks.c
index b4c9ba0..c2c01db 100644
--- a/Source/tasks.c
+++ b/Source/tasks.c
@@ -1,6 +1,7 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * Copyright 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: MIT
  *
@@ -147,7 +148,9 @@
  * global, rather than file scope.
  */
 #ifdef portREMOVE_STATIC_QUALIFIER
-    #define static
+    #define STATIC
+#else
+    #define STATIC    static
 #endif
 
 /* The name allocated to the Idle task.  This can be overridden by defining
@@ -472,23 +475,23 @@
  * xDelayedTaskList1 and xDelayedTaskList2 could be moved to function scope but
  * doing so breaks some kernel aware debuggers and debuggers that rely on removing
  * the static qualifier. */
-PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ]; /**< Prioritised ready tasks. */
-PRIVILEGED_DATA static List_t xDelayedTaskList1;                         /**< Delayed tasks. */
-PRIVILEGED_DATA static List_t xDelayedTaskList2;                         /**< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
-PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList;              /**< Points to the delayed task list currently being used. */
-PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList;      /**< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */
-PRIVILEGED_DATA static List_t xPendingReadyList;                         /**< Tasks that have been readied while the scheduler was suspended.  They will be moved to the ready list when the scheduler is resumed. */
+PRIVILEGED_DATA STATIC List_t pxReadyTasksLists[ configMAX_PRIORITIES ]; /**< Prioritised ready tasks. */
+PRIVILEGED_DATA STATIC List_t xDelayedTaskList1;                         /**< Delayed tasks. */
+PRIVILEGED_DATA STATIC List_t xDelayedTaskList2;                         /**< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
+PRIVILEGED_DATA STATIC List_t * volatile pxDelayedTaskList;              /**< Points to the delayed task list currently being used. */
+PRIVILEGED_DATA STATIC List_t * volatile pxOverflowDelayedTaskList;      /**< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */
+PRIVILEGED_DATA STATIC List_t xPendingReadyList;                         /**< Tasks that have been readied while the scheduler was suspended.  They will be moved to the ready list when the scheduler is resumed. */
 
 #if ( INCLUDE_vTaskDelete == 1 )
 
-    PRIVILEGED_DATA static List_t xTasksWaitingTermination; /**< Tasks that have been deleted - but their memory not yet freed. */
-    PRIVILEGED_DATA static volatile UBaseType_t uxDeletedTasksWaitingCleanUp = ( UBaseType_t ) 0U;
+    PRIVILEGED_DATA STATIC List_t xTasksWaitingTermination; /**< Tasks that have been deleted - but their memory not yet freed. */
+    PRIVILEGED_DATA STATIC volatile UBaseType_t uxDeletedTasksWaitingCleanUp = ( UBaseType_t ) 0U;
 
 #endif
 
 #if ( INCLUDE_vTaskSuspend == 1 )
 
-    PRIVILEGED_DATA static List_t xSuspendedTaskList; /**< Tasks that are currently suspended. */
+    PRIVILEGED_DATA STATIC List_t xSuspendedTaskList; /**< Tasks that are currently suspended. */
 
 #endif
 
@@ -499,21 +502,21 @@
 #endif
 
 /* Other file private variables. --------------------------------*/
-PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U;
-PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;
-PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY;
-PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE;
-PRIVILEGED_DATA static volatile TickType_t xPendedTicks = ( TickType_t ) 0U;
-PRIVILEGED_DATA static volatile BaseType_t xYieldPendings[ configNUMBER_OF_CORES ] = { pdFALSE };
-PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0;
-PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U;
-PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = ( TickType_t ) 0U; /* Initialised to portMAX_DELAY before the scheduler starts. */
-PRIVILEGED_DATA static TaskHandle_t xIdleTaskHandles[ configNUMBER_OF_CORES ];       /**< Holds the handles of the idle tasks.  The idle tasks are created automatically when the scheduler is started. */
+PRIVILEGED_DATA STATIC volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U;
+PRIVILEGED_DATA STATIC volatile TickType_t xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;
+PRIVILEGED_DATA STATIC volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY;
+PRIVILEGED_DATA STATIC volatile BaseType_t xSchedulerRunning = pdFALSE;
+PRIVILEGED_DATA STATIC volatile TickType_t xPendedTicks = ( TickType_t ) 0U;
+PRIVILEGED_DATA STATIC volatile BaseType_t xYieldPendings[ configNUMBER_OF_CORES ] = { pdFALSE };
+PRIVILEGED_DATA STATIC volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0;
+PRIVILEGED_DATA STATIC UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U;
+PRIVILEGED_DATA STATIC volatile TickType_t xNextTaskUnblockTime = ( TickType_t ) 0U; /* Initialised to portMAX_DELAY before the scheduler starts. */
+PRIVILEGED_DATA STATIC TaskHandle_t xIdleTaskHandles[ configNUMBER_OF_CORES ];       /**< Holds the handles of the idle tasks.  The idle tasks are created automatically when the scheduler is started. */
 
 /* Improve support for OpenOCD. The kernel tracks Ready tasks via priority lists.
  * For tracking the state of remote threads, OpenOCD uses uxTopUsedPriority
  * to determine the number of priority lists to read back from the remote target. */
-static const volatile UBaseType_t uxTopUsedPriority = configMAX_PRIORITIES - 1U;
+STATIC const volatile UBaseType_t uxTopUsedPriority = configMAX_PRIORITIES - 1U;
 
 /* Context switches are held pending while the scheduler is suspended.  Also,
  * interrupts must not manipulate the xStateListItem of a TCB, or any of the
@@ -527,14 +530,14 @@
  * Updates to uxSchedulerSuspended must be protected by both the task lock and the ISR lock
  * and must not be done from an ISR. Reads must be protected by either lock and may be done
  * from either an ISR or a task. */
-PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) 0U;
+PRIVILEGED_DATA STATIC volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) 0U;
 
 #if ( configGENERATE_RUN_TIME_STATS == 1 )
 
 /* Do not move these variables to function scope as doing so prevents the
  * code working with debuggers that need to remove the static qualifier. */
-PRIVILEGED_DATA static configRUN_TIME_COUNTER_TYPE ulTaskSwitchedInTime[ configNUMBER_OF_CORES ] = { 0U };    /**< Holds the value of a timer/counter the last time a task was switched in. */
-PRIVILEGED_DATA static volatile configRUN_TIME_COUNTER_TYPE ulTotalRunTime[ configNUMBER_OF_CORES ] = { 0U }; /**< Holds the total amount of execution time as defined by the run time counter clock. */
+PRIVILEGED_DATA STATIC configRUN_TIME_COUNTER_TYPE ulTaskSwitchedInTime[ configNUMBER_OF_CORES ] = { 0U };    /**< Holds the value of a timer/counter the last time a task was switched in. */
+PRIVILEGED_DATA STATIC volatile configRUN_TIME_COUNTER_TYPE ulTotalRunTime[ configNUMBER_OF_CORES ] = { 0U }; /**< Holds the total amount of execution time as defined by the run time counter clock. */
 
 #endif
 
@@ -545,7 +548,7 @@
 /*
  * Creates the idle tasks during scheduler start.
  */
-static BaseType_t prvCreateIdleTasks( void );
+STATIC BaseType_t prvCreateIdleTasks( void );
 
 #if ( configNUMBER_OF_CORES > 1 )
 
@@ -553,7 +556,7 @@
  * Checks to see if another task moved the current task out of the ready
  * list while it was waiting to enter a critical section and yields, if so.
  */
-    static void prvCheckForRunStateChange( void );
+    STATIC void prvCheckForRunStateChange( void );
 #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
 
 #if ( configNUMBER_OF_CORES > 1 )
@@ -562,7 +565,7 @@
  * Yields a core, or cores if multiple priorities are not allowed to run
  * simultaneously, to allow the task pxTCB to run.
  */
-    static void prvYieldForTask( const TCB_t * pxTCB );
+    STATIC void prvYieldForTask( const TCB_t * pxTCB );
 #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
 
 #if ( configNUMBER_OF_CORES > 1 )
@@ -570,7 +573,7 @@
 /*
  * Selects the highest priority available task for the given core.
  */
-    static void prvSelectHighestPriorityTask( BaseType_t xCoreID );
+    STATIC void prvSelectHighestPriorityTask( BaseType_t xCoreID );
 #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
 
 /**
@@ -580,7 +583,7 @@
  */
 #if ( INCLUDE_vTaskSuspend == 1 )
 
-    static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
+    STATIC BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
 
 #endif /* INCLUDE_vTaskSuspend */
 
@@ -588,7 +591,7 @@
  * Utility to ready all the lists used by the scheduler.  This is called
  * automatically upon the creation of the first task.
  */
-static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION;
+STATIC void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION;
 
 /*
  * The idle task, which as all tasks is implemented as a never ending loop.
@@ -606,9 +609,11 @@
  * void prvPassiveIdleTask( void *pvParameters );
  *
  */
-static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters ) PRIVILEGED_FUNCTION;
+STATIC portTASK_FUNCTION_PROTO( prvIdleTask,
+                                pvParameters ) PRIVILEGED_FUNCTION;
 #if ( configNUMBER_OF_CORES > 1 )
-    static portTASK_FUNCTION_PROTO( prvPassiveIdleTask, pvParameters ) PRIVILEGED_FUNCTION;
+    STATIC portTASK_FUNCTION_PROTO( prvPassiveIdleTask,
+                                    pvParameters ) PRIVILEGED_FUNCTION;
 #endif
 
 /*
@@ -620,7 +625,7 @@
  */
 #if ( INCLUDE_vTaskDelete == 1 )
 
-    static void prvDeleteTCB( TCB_t * pxTCB ) PRIVILEGED_FUNCTION;
+    STATIC void prvDeleteTCB( TCB_t * pxTCB ) PRIVILEGED_FUNCTION;
 
 #endif
 
@@ -629,38 +634,22 @@
  * in the list of tasks waiting to be deleted.  If so the task is cleaned up
  * and its TCB deleted.
  */
-static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
+STATIC void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
 
 /*
  * The currently executing task is entering the Blocked state.  Add the task to
  * either the current or the overflow delayed task list.
  */
-static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait,
+STATIC void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait,
                                             const BaseType_t xCanBlockIndefinitely ) PRIVILEGED_FUNCTION;
 
 /*
- * Fills an TaskStatus_t structure with information on each task that is
- * referenced from the pxList list (which may be a ready list, a delayed list,
- * a suspended list, etc.).
- *
- * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM
- * NORMAL APPLICATION CODE.
- */
-#if ( configUSE_TRACE_FACILITY == 1 )
-
-    static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t * pxTaskStatusArray,
-                                                     List_t * pxList,
-                                                     eTaskState eState ) PRIVILEGED_FUNCTION;
-
-#endif
-
-/*
  * Searches pxList for a task with name pcNameToQuery - returning a handle to
  * the task if it is found, or NULL if the task is not found.
  */
 #if ( INCLUDE_xTaskGetHandle == 1 )
 
-    static TCB_t * prvSearchForNameWithinSingleList( List_t * pxList,
+    STATIC TCB_t * prvSearchForNameWithinSingleList( List_t * pxList,
                                                      const char pcNameToQuery[] ) PRIVILEGED_FUNCTION;
 
 #endif
@@ -672,7 +661,7 @@
  */
 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) )
 
-    static configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION;
+    STATIC configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION;
 
 #endif
 
@@ -688,7 +677,7 @@
  */
 #if ( configUSE_TICKLESS_IDLE != 0 )
 
-    static TickType_t prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION;
+    STATIC TickType_t prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION;
 
 #endif
 
@@ -696,7 +685,7 @@
  * Set xNextTaskUnblockTime to the time at which the next Blocked state task
  * will exit the Blocked state.
  */
-static void prvResetNextTaskUnblockTime( void ) PRIVILEGED_FUNCTION;
+STATIC void prvResetNextTaskUnblockTime( void ) PRIVILEGED_FUNCTION;
 
 #if ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 )
 
@@ -713,7 +702,7 @@
  * Called after a Task_t structure has been allocated either statically or
  * dynamically to fill in the structure's members.
  */
-static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
+STATIC void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
                                   const char * const pcName,
                                   const configSTACK_DEPTH_TYPE uxStackDepth,
                                   void * const pvParameters,
@@ -726,14 +715,14 @@
  * Called after a new task has been created and initialised to place the task
  * under the control of the scheduler.
  */
-static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
+STATIC void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
 
 /*
  * Create a task with static buffer for both TCB and stack. Returns a handle to
  * the task if it is created successfully. Otherwise, returns NULL.
  */
 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
-    static TCB_t * prvCreateStaticTask( TaskFunction_t pxTaskCode,
+    STATIC TCB_t * prvCreateStaticTask( TaskFunction_t pxTaskCode,
                                         const char * const pcName,
                                         const configSTACK_DEPTH_TYPE uxStackDepth,
                                         void * const pvParameters,
@@ -748,7 +737,7 @@
  * a handle to the task if it is created successfully. Otherwise, returns NULL.
  */
 #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
-    static TCB_t * prvCreateRestrictedStaticTask( const TaskParameters_t * const pxTaskDefinition,
+    STATIC TCB_t * prvCreateRestrictedStaticTask( const TaskParameters_t * const pxTaskDefinition,
                                                   TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION;
 #endif /* #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) */
 
@@ -758,7 +747,7 @@
  * returns NULL.
  */
 #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
-    static TCB_t * prvCreateRestrictedTask( const TaskParameters_t * const pxTaskDefinition,
+    STATIC TCB_t * prvCreateRestrictedTask( const TaskParameters_t * const pxTaskDefinition,
                                             TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION;
 #endif /* #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */
 
@@ -767,7 +756,7 @@
  * the task if it is created successfully. Otherwise, returns NULL.
  */
 #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
-    static TCB_t * prvCreateTask( TaskFunction_t pxTaskCode,
+    STATIC TCB_t * prvCreateTask( TaskFunction_t pxTaskCode,
                                   const char * const pcName,
                                   const configSTACK_DEPTH_TYPE uxStackDepth,
                                   void * const pvParameters,
@@ -782,7 +771,7 @@
  */
 #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
 
-    static void freertos_tasks_c_additions_init( void ) PRIVILEGED_FUNCTION;
+    STATIC void freertos_tasks_c_additions_init( void ) PRIVILEGED_FUNCTION;
 
 #endif
 
@@ -812,14 +801,14 @@
  * and less than the supplied buffer length, the string has been
  * completely written.
  */
-    static size_t prvSnprintfReturnValueToCharsWritten( int iSnprintfReturnValue,
+    STATIC size_t prvSnprintfReturnValueToCharsWritten( int iSnprintfReturnValue,
                                                         size_t n );
 
 #endif /* #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
 /*-----------------------------------------------------------*/
 
 #if ( configNUMBER_OF_CORES > 1 )
-    static void prvCheckForRunStateChange( void )
+    STATIC void prvCheckForRunStateChange( void )
     {
         UBaseType_t uxPrevCriticalNesting;
         const TCB_t * pxThisTCB;
@@ -887,13 +876,13 @@
 /*-----------------------------------------------------------*/
 
 #if ( configNUMBER_OF_CORES > 1 )
-    static void prvYieldForTask( const TCB_t * pxTCB )
+    STATIC void prvYieldForTask( const TCB_t * pxTCB )
     {
         BaseType_t xLowestPriorityToPreempt;
         BaseType_t xCurrentCoreTaskPriority;
         BaseType_t xLowestPriorityCore = ( BaseType_t ) -1;
         BaseType_t xCoreID;
-        const BaseType_t xCurrentCoreID = portGET_CORE_ID();
+        const BaseType_t xCurrentCoreID = ( BaseType_t ) portGET_CORE_ID();
 
         #if ( configRUN_MULTIPLE_PRIORITIES == 0 )
             BaseType_t xYieldCount = 0;
@@ -1002,7 +991,7 @@
 /*-----------------------------------------------------------*/
 
 #if ( configNUMBER_OF_CORES > 1 )
-    static void prvSelectHighestPriorityTask( BaseType_t xCoreID )
+    STATIC void prvSelectHighestPriorityTask( BaseType_t xCoreID )
     {
         UBaseType_t uxCurrentPriority = uxTopReadyPriority;
         BaseType_t xTaskScheduled = pdFALSE;
@@ -1273,7 +1262,7 @@
 
 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
 
-    static TCB_t * prvCreateStaticTask( TaskFunction_t pxTaskCode,
+    STATIC TCB_t * prvCreateStaticTask( TaskFunction_t pxTaskCode,
                                         const char * const pcName,
                                         const configSTACK_DEPTH_TYPE uxStackDepth,
                                         void * const pvParameters,
@@ -1404,7 +1393,7 @@
 /*-----------------------------------------------------------*/
 
 #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
-    static TCB_t * prvCreateRestrictedStaticTask( const TaskParameters_t * const pxTaskDefinition,
+    STATIC TCB_t * prvCreateRestrictedStaticTask( const TaskParameters_t * const pxTaskDefinition,
                                                   TaskHandle_t * const pxCreatedTask )
     {
         TCB_t * pxNewTCB;
@@ -1520,7 +1509,7 @@
 /*-----------------------------------------------------------*/
 
 #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
-    static TCB_t * prvCreateRestrictedTask( const TaskParameters_t * const pxTaskDefinition,
+    STATIC TCB_t * prvCreateRestrictedTask( const TaskParameters_t * const pxTaskDefinition,
                                             TaskHandle_t * const pxCreatedTask )
     {
         TCB_t * pxNewTCB;
@@ -1639,7 +1628,7 @@
 /*-----------------------------------------------------------*/
 
 #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
-    static TCB_t * prvCreateTask( TaskFunction_t pxTaskCode,
+    STATIC TCB_t * prvCreateTask( TaskFunction_t pxTaskCode,
                                   const char * const pcName,
                                   const configSTACK_DEPTH_TYPE uxStackDepth,
                                   void * const pvParameters,
@@ -1689,7 +1678,7 @@
             /* MISRA Ref 11.5.1 [Malloc memory assignment] */
             /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
             /* coverity[misra_c_2012_rule_11_5_violation] */
-            pxStack = pvPortMallocStack( ( ( ( size_t ) uxStackDepth ) * sizeof( StackType_t ) ) );
+            pxStack = ( StackType_t * ) pvPortMallocStack( ( ( ( size_t ) uxStackDepth ) * sizeof( StackType_t ) ) );
 
             if( pxStack != NULL )
             {
@@ -1812,7 +1801,7 @@
 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
 /*-----------------------------------------------------------*/
 
-static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
+STATIC void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
                                   const char * const pcName,
                                   const configSTACK_DEPTH_TYPE uxStackDepth,
                                   void * const pvParameters,
@@ -2007,6 +1996,16 @@
             pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
         }
         #endif /* portHAS_STACK_OVERFLOW_CHECKING */
+
+        #if ( portSTACK_GROWTH < 0 )
+        {
+            configASSERT( ( ( portPOINTER_SIZE_TYPE ) ( pxTopOfStack - pxNewTCB->pxTopOfStack ) ) < ( ( portPOINTER_SIZE_TYPE ) uxStackDepth ) );
+        }
+        #else /* portSTACK_GROWTH */
+        {
+            configASSERT( ( ( portPOINTER_SIZE_TYPE ) ( pxNewTCB->pxTopOfStack - pxTopOfStack ) ) < ( ( portPOINTER_SIZE_TYPE ) uxStackDepth ) );
+        }
+        #endif /* portSTACK_GROWTH */
     }
     #endif /* portUSING_MPU_WRAPPERS */
 
@@ -2038,7 +2037,7 @@
 
 #if ( configNUMBER_OF_CORES == 1 )
 
-    static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
+    STATIC void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
     {
         /* Ensure interrupts don't access the task lists while the lists are being
          * updated. */
@@ -2116,7 +2115,7 @@
 
 #else /* #if ( configNUMBER_OF_CORES == 1 ) */
 
-    static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
+    STATIC void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
     {
         /* Ensure interrupts don't access the task lists while the lists are being
          * updated. */
@@ -2177,7 +2176,7 @@
 
 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
 
-    static size_t prvSnprintfReturnValueToCharsWritten( int iSnprintfReturnValue,
+    STATIC size_t prvSnprintfReturnValueToCharsWritten( int iSnprintfReturnValue,
                                                         size_t n )
     {
         size_t uxCharsWritten;
@@ -2363,6 +2362,55 @@
 
 #if ( INCLUDE_xTaskDelayUntil == 1 )
 
+    TickType_t xTaskPeriodicDelay( TickType_t * const pxPreviousWakeTime,
+                                   const TickType_t xTimeIncrement )
+    {
+        TickType_t xIncrements, xTicksIncrements, xTicksToWait;
+
+        traceENTER_xTaskPeriodicDelay( pxPreviousWakeTime, xTimeIncrement );
+
+        configASSERT( pxPreviousWakeTime );
+        configASSERT( ( xTimeIncrement > 0U ) );
+
+        vTaskSuspendAll();
+        {
+            /* As long as everything is the same type, this plays well with overflows */
+            const TickType_t xTicksElapsed = xTickCount - *pxPreviousWakeTime;
+
+            configASSERT( uxSchedulerSuspended == 1U );
+
+            /* Number of increments to catch up: it could be 0 if
+             * not enough ticks have elapsed, 1 in the common case or
+             * more than 1 if the task has not been resumed in time */
+            xIncrements = xTicksElapsed / xTimeIncrement;
+            xTicksIncrements = xIncrements * xTimeIncrement;
+
+            /* Update to the last wake time */
+            *pxPreviousWakeTime += xTicksIncrements;
+
+            /* Ticks to the next wake time */
+            xTicksToWait = xTimeIncrement - ( xTicksElapsed - xTicksIncrements );
+
+            prvAddCurrentTaskToDelayedList( xTicksToWait, pdFALSE );
+        }
+
+        /* Force a reschedule if xTaskResumeAll has not already done so, we may
+         * have put ourselves to sleep. */
+        if( xTaskResumeAll() == pdFALSE )
+        {
+            taskYIELD_WITHIN_API();
+        }
+        else
+        {
+            mtCOVERAGE_TEST_MARKER();
+        }
+
+        traceRETURN_xTaskPeriodicDelay( xIncrements );
+
+        return xIncrements;
+    }
+
+
     BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
                                 const TickType_t xTimeIncrement )
     {
@@ -3309,7 +3357,7 @@
 
 #if ( INCLUDE_vTaskSuspend == 1 )
 
-    static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask )
+    STATIC BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask )
     {
         BaseType_t xReturn = pdFALSE;
         const TCB_t * const pxTCB = xTask;
@@ -3537,7 +3585,7 @@
 #endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */
 /*-----------------------------------------------------------*/
 
-static BaseType_t prvCreateIdleTasks( void )
+STATIC BaseType_t prvCreateIdleTasks( void )
 {
     BaseType_t xReturn = pdPASS;
     BaseType_t xCoreID;
@@ -3676,8 +3724,13 @@
                 /* Assign idle task to each core before SMP scheduler is running. */
                 xIdleTaskHandles[ xCoreID ]->xTaskRunState = xCoreID;
                 pxCurrentTCBs[ xCoreID ] = xIdleTaskHandles[ xCoreID ];
+                #if ( ( configIDLE_AFFINITY == 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
+                {
+                    xIdleTaskHandles[ xCoreID ]->uxCoreAffinityMask = ( ( UBaseType_t ) 1U << ( UBaseType_t ) xCoreID );
+                }
+                #endif /* #if ( ( configIDLE_AFFINITY == 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */
             }
-            #endif
+            #endif /* if ( configNUMBER_OF_CORES == 1 ) */
         }
     }
 
@@ -3946,7 +3999,7 @@
 
 #if ( configUSE_TICKLESS_IDLE != 0 )
 
-    static TickType_t prvGetExpectedIdleTime( void )
+    STATIC TickType_t prvGetExpectedIdleTime( void )
     {
         TickType_t xReturn;
         BaseType_t xHigherPriorityReadyTasks = pdFALSE;
@@ -4241,7 +4294,7 @@
 /*-----------------------------------------------------------*/
 
 #if ( INCLUDE_xTaskGetHandle == 1 )
-    static TCB_t * prvSearchForNameWithinSingleList( List_t * pxList,
+    STATIC TCB_t * prvSearchForNameWithinSingleList( List_t * pxList,
                                                      const char pcNameToQuery[] )
     {
         TCB_t * pxReturn = NULL;
@@ -4437,11 +4490,107 @@
 
 #if ( configUSE_TRACE_FACILITY == 1 )
 
+    STATIC UBaseType_t prvForEachTaskInList( List_t * pxList,
+                                             eTaskState eState,
+                                             TaskStatusCallbackFunction_t pxCallbackFunction,
+                                             void * pvCallbackContext );
+
+/* for uxTaskGetSystemState callback context: current write position into TaskStatusArray */
+    typedef struct xTASK_STATUS_ARRAY_WRITER_CONTEXT
+    {
+        TaskStatus_t * pxTaskStatusArray;
+        UBaseType_t uxIndex;
+    } TaskStatusArrayWriterContext_t;
+
+/* callback for uxTaskGetSystemState: write one task's status into TaskStatusArray */
+    STATIC void prvTaskStatusArrayWriter( TaskHandle_t xTask,
+                                          eTaskState eState,
+                                          void * pvCallbackContext )
+    {
+        TaskStatusArrayWriterContext_t * pxContext = ( TaskStatusArrayWriterContext_t * ) pvCallbackContext;
+
+        vTaskGetInfo( xTask, &( pxContext->pxTaskStatusArray[ pxContext->uxIndex++ ] ), pdTRUE, eState );
+    }
+
+    STATIC void prvGetTotalRunTime( configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime )
+    {
+        if( pulTotalRunTime != NULL )
+        {
+            #if ( configGENERATE_RUN_TIME_STATS == 1 )
+                #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
+                    portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) );
+                #else
+                    *pulTotalRunTime = ( configRUN_TIME_COUNTER_TYPE ) portGET_RUN_TIME_COUNTER_VALUE();
+                #endif
+            #else
+                *pulTotalRunTime = 0;
+            #endif /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
+        }
+    }
+
+/* For each task, call the provided callback function (passing the provided context). */
+/* Caller must suspend the scheduler around use of this function. */
+    STATIC UBaseType_t prvCallForEachTask( TaskStatusCallbackFunction_t pxCallbackFunction,
+                                           void * pvCallbackContext )
+    {
+        UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES;
+
+        /* Visit each task in the Ready state. */
+        do
+        {
+            uxQueue--;
+            uxTask = ( UBaseType_t ) ( uxTask + prvForEachTaskInList( &( pxReadyTasksLists[ uxQueue ] ), eReady, pxCallbackFunction, pvCallbackContext ) );
+        } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY );
+
+        /* Visit each task in the Blocked state. */
+        uxTask = ( UBaseType_t ) ( uxTask + prvForEachTaskInList( ( List_t * ) pxDelayedTaskList, eBlocked, pxCallbackFunction, pvCallbackContext ) );
+        uxTask = ( UBaseType_t ) ( uxTask + prvForEachTaskInList( ( List_t * ) pxOverflowDelayedTaskList, eBlocked, pxCallbackFunction, pvCallbackContext ) );
+
+        #if ( INCLUDE_vTaskDelete == 1 )
+        {
+            /* Visit each task that has been deleted but not yet cleaned up. */
+            uxTask = ( UBaseType_t ) ( uxTask + prvForEachTaskInList( &xTasksWaitingTermination, eDeleted, pxCallbackFunction, pvCallbackContext ) );
+        }
+        #endif
+
+        #if ( INCLUDE_vTaskSuspend == 1 )
+        {
+            /* Visit each task in the Suspended state. */
+            uxTask = ( UBaseType_t ) ( uxTask + prvForEachTaskInList( &xSuspendedTaskList, eSuspended, pxCallbackFunction, pvCallbackContext ) );
+        }
+        #endif
+
+        return uxTask;
+    }
+
+    UBaseType_t uxTaskCallForEachTask( TaskStatusCallbackFunction_t pxCallbackFunction,
+                                       void * pvCallbackContext,
+                                       configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime )
+    {
+        UBaseType_t uxTask;
+
+        configASSERT( pxCallbackFunction != NULL );
+
+        if( pxCallbackFunction == NULL )
+        {
+            return 0;
+        }
+
+        vTaskSuspendAll();
+        {
+            uxTask = prvCallForEachTask( pxCallbackFunction, pvCallbackContext );
+            prvGetTotalRunTime( pulTotalRunTime );
+        }
+        ( void ) xTaskResumeAll();
+
+        return uxTask;
+    }
+
     UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,
                                       const UBaseType_t uxArraySize,
                                       configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime )
     {
-        UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES;
+        UBaseType_t uxTask = 0;
 
         traceENTER_uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, pulTotalRunTime );
 
@@ -4450,54 +4599,11 @@
             /* Is there a space in the array for each task in the system? */
             if( uxArraySize >= uxCurrentNumberOfTasks )
             {
-                /* Fill in an TaskStatus_t structure with information on each
-                 * task in the Ready state. */
-                do
-                {
-                    uxQueue--;
-                    uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady ) );
-                } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY );
-
-                /* Fill in an TaskStatus_t structure with information on each
-                 * task in the Blocked state. */
-                uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked ) );
-                uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked ) );
-
-                #if ( INCLUDE_vTaskDelete == 1 )
-                {
-                    /* Fill in an TaskStatus_t structure with information on
-                     * each task that has been deleted but not yet cleaned up. */
-                    uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted ) );
-                }
-                #endif
-
-                #if ( INCLUDE_vTaskSuspend == 1 )
-                {
-                    /* Fill in an TaskStatus_t structure with information on
-                     * each task in the Suspended state. */
-                    uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended ) );
-                }
-                #endif
-
-                #if ( configGENERATE_RUN_TIME_STATS == 1 )
-                {
-                    if( pulTotalRunTime != NULL )
-                    {
-                        #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
-                            portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) );
-                        #else
-                            *pulTotalRunTime = ( configRUN_TIME_COUNTER_TYPE ) portGET_RUN_TIME_COUNTER_VALUE();
-                        #endif
-                    }
-                }
-                #else /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
-                {
-                    if( pulTotalRunTime != NULL )
-                    {
-                        *pulTotalRunTime = 0;
-                    }
-                }
-                #endif /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
+                TaskStatusArrayWriterContext_t xContext;
+                xContext.pxTaskStatusArray = pxTaskStatusArray;
+                xContext.uxIndex = 0;
+                uxTask = prvCallForEachTask( prvTaskStatusArrayWriter, &xContext );
+                prvGetTotalRunTime( pulTotalRunTime );
             }
             else
             {
@@ -5015,11 +5121,11 @@
 
         traceENTER_xTaskGetApplicationTaskTag( xTask );
 
-        /* If xTask is NULL then set the calling task's hook. */
+        /* If xTask is NULL then get the calling task's hook. */
         pxTCB = prvGetTCBFromHandle( xTask );
         configASSERT( pxTCB != NULL );
 
-        /* Save the hook function in the TCB.  A critical section is required as
+        /* Access the hook function in the TCB.  A critical section is required as
          * the value can be accessed from an interrupt. */
         taskENTER_CRITICAL();
         {
@@ -5045,11 +5151,11 @@
 
         traceENTER_xTaskGetApplicationTaskTagFromISR( xTask );
 
-        /* If xTask is NULL then set the calling task's hook. */
+        /* If xTask is NULL then get the calling task's hook. */
         pxTCB = prvGetTCBFromHandle( xTask );
         configASSERT( pxTCB != NULL );
 
-        /* Save the hook function in the TCB.  A critical section is required as
+        /* Access the hook function in the TCB.  A critical section is required as
          * the value can be accessed from an interrupt. */
         /* MISRA Ref 4.7.1 [Return value shall be checked] */
         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#dir-47 */
@@ -5728,7 +5834,8 @@
  */
 
 #if ( configNUMBER_OF_CORES > 1 )
-    static portTASK_FUNCTION( prvPassiveIdleTask, pvParameters )
+    STATIC portTASK_FUNCTION( prvPassiveIdleTask,
+                              pvParameters )
     {
         ( void ) pvParameters;
 
@@ -5798,7 +5905,8 @@
  *
  */
 
-static portTASK_FUNCTION( prvIdleTask, pvParameters )
+STATIC portTASK_FUNCTION( prvIdleTask,
+                          pvParameters )
 {
     /* Stop warnings. */
     ( void ) pvParameters;
@@ -6064,7 +6172,7 @@
 #endif /* portUSING_MPU_WRAPPERS */
 /*-----------------------------------------------------------*/
 
-static void prvInitialiseTaskLists( void )
+STATIC void prvInitialiseTaskLists( void )
 {
     UBaseType_t uxPriority;
 
@@ -6096,7 +6204,7 @@
 }
 /*-----------------------------------------------------------*/
 
-static void prvCheckTasksWaitingTermination( void )
+STATIC void prvCheckTasksWaitingTermination( void )
 {
     /** THIS FUNCTION IS CALLED FROM THE RTOS IDLE TASK **/
 
@@ -6322,9 +6430,10 @@
 
 #if ( configUSE_TRACE_FACILITY == 1 )
 
-    static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t * pxTaskStatusArray,
-                                                     List_t * pxList,
-                                                     eTaskState eState )
+    STATIC UBaseType_t prvForEachTaskInList( List_t * pxList,
+                                             eTaskState eState,
+                                             TaskStatusCallbackFunction_t pxCallbackFunction,
+                                             void * pvCallbackContext )
     {
         UBaseType_t uxTask = 0;
         const ListItem_t * pxEndMarker = listGET_END_MARKER( pxList );
@@ -6333,10 +6442,7 @@
 
         if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
         {
-            /* Populate an TaskStatus_t structure within the
-             * pxTaskStatusArray array for each task that is referenced from
-             * pxList.  See the definition of TaskStatus_t in task.h for the
-             * meaning of each TaskStatus_t structure member. */
+            /* Hand the callback each task handle referenced from pxList. */
             for( pxIterator = listGET_HEAD_ENTRY( pxList ); pxIterator != pxEndMarker; pxIterator = listGET_NEXT( pxIterator ) )
             {
                 /* MISRA Ref 11.5.3 [Void pointer assignment] */
@@ -6344,7 +6450,7 @@
                 /* coverity[misra_c_2012_rule_11_5_violation] */
                 pxTCB = listGET_LIST_ITEM_OWNER( pxIterator );
 
-                vTaskGetInfo( ( TaskHandle_t ) pxTCB, &( pxTaskStatusArray[ uxTask ] ), pdTRUE, eState );
+                pxCallbackFunction( ( TaskHandle_t ) pxTCB, eState, pvCallbackContext );
                 uxTask++;
             }
         }
@@ -6361,7 +6467,7 @@
 
 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) )
 
-    static configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte )
+    STATIC configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte )
     {
         configSTACK_DEPTH_TYPE uxCount = 0U;
 
@@ -6459,7 +6565,7 @@
 
 #if ( INCLUDE_vTaskDelete == 1 )
 
-    static void prvDeleteTCB( TCB_t * pxTCB )
+    STATIC void prvDeleteTCB( TCB_t * pxTCB )
     {
         /* This call is required specifically for the TriCore port.  It must be
          * above the vPortFree() calls.  The call is also used by ports/demos that
@@ -6512,7 +6618,7 @@
 #endif /* INCLUDE_vTaskDelete */
 /*-----------------------------------------------------------*/
 
-static void prvResetNextTaskUnblockTime( void )
+STATIC void prvResetNextTaskUnblockTime( void )
 {
     if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
     {
@@ -6906,7 +7012,7 @@
                             /* It is known that the task is in its ready list so
                              * there is no need to check again and the port level
                              * reset macro can be called directly. */
-                            portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority );
+                            portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );
                         }
                         else
                         {
@@ -7260,7 +7366,7 @@
 
 #if ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 )
 
-    static char * prvWriteNameToBuffer( char * pcBuffer,
+    STATIC char * prvWriteNameToBuffer( char * pcBuffer,
                                         const char * pcTaskName )
     {
         size_t x;
@@ -7340,7 +7446,7 @@
         /* MISRA Ref 11.5.1 [Malloc memory assignment] */
         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
         /* coverity[misra_c_2012_rule_11_5_violation] */
-        pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
+        pxTaskStatusArray = pvPortMalloc( uxArraySize * sizeof( TaskStatus_t ) );
 
         if( pxTaskStatusArray != NULL )
         {
@@ -7509,7 +7615,7 @@
         /* MISRA Ref 11.5.1 [Malloc memory assignment] */
         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
         /* coverity[misra_c_2012_rule_11_5_violation] */
-        pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
+        pxTaskStatusArray = pvPortMalloc( uxArraySize * sizeof( TaskStatus_t ) );
 
         if( pxTaskStatusArray != NULL )
         {
@@ -7873,7 +7979,7 @@
                 *pulNotificationValue = pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ];
             }
 
-            /* If ucNotifyValue is set then either the task never entered the
+            /* If ucNotifyState is set then either the task never entered the
              * blocked state (because a notification was already pending) or the
              * task unblocked because of a notification.  Otherwise the task
              * unblocked because of a timeout. */
@@ -8576,7 +8682,7 @@
 #endif /* if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) */
 /*-----------------------------------------------------------*/
 
-static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait,
+STATIC void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait,
                                             const BaseType_t xCanBlockIndefinitely )
 {
     TickType_t xTimeToWake;
@@ -8728,7 +8834,7 @@
     #include "freertos_tasks_c_additions.h"
 
     #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
-        static void freertos_tasks_c_additions_init( void )
+        STATIC void freertos_tasks_c_additions_init( void )
         {
             FREERTOS_TASKS_C_ADDITIONS_INIT();
         }
@@ -8743,7 +8849,7 @@
  * This is the kernel provided implementation of vApplicationGetIdleTaskMemory()
  * to provide the memory that is used by the Idle task. It is used when
  * configKERNEL_PROVIDED_STATIC_MEMORY is set to 1. The application can provide
- * it's own implementation of vApplicationGetIdleTaskMemory by setting
+ * its own implementation of vApplicationGetIdleTaskMemory by setting
  * configKERNEL_PROVIDED_STATIC_MEMORY to 0 or leaving it undefined.
  */
     void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
@@ -8784,7 +8890,7 @@
  * This is the kernel provided implementation of vApplicationGetTimerTaskMemory()
  * to provide the memory that is used by the Timer service task. It is used when
  * configKERNEL_PROVIDED_STATIC_MEMORY is set to 1. The application can provide
- * it's own implementation of vApplicationGetTimerTaskMemory by setting
+ * its own implementation of vApplicationGetTimerTaskMemory by setting
  * configKERNEL_PROVIDED_STATIC_MEMORY to 0 or leaving it undefined.
  */
     void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
diff --git a/Source/timers.c b/Source/timers.c
index 454be0a..b7e22b1 100644
--- a/Source/timers.c
+++ b/Source/timers.c
@@ -1,5 +1,5 @@
 /*
- * FreeRTOS Kernel V11.2.0
+ * FreeRTOS Kernel V11.3.1
  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * SPDX-License-Identifier: MIT
@@ -467,9 +467,11 @@
             xMessage.u.xTimerParameters.xMessageValue = xOptionalValue;
             xMessage.u.xTimerParameters.pxTimer = xTimer;
 
-            configASSERT( xCommandID < tmrFIRST_FROM_ISR_COMMAND );
+            /* Enforce a lower bound as well as an upper bound so that only
+             * valid task-issued commands are accepted here. */
+            configASSERT( ( xCommandID >= tmrCOMMAND_START_DONT_TRACE ) && ( xCommandID < tmrFIRST_FROM_ISR_COMMAND ) );
 
-            if( xCommandID < tmrFIRST_FROM_ISR_COMMAND )
+            if( ( xCommandID >= tmrCOMMAND_START_DONT_TRACE ) && ( xCommandID < tmrFIRST_FROM_ISR_COMMAND ) )
             {
                 if( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING )
                 {