Compare commits

...

41 commits

Author SHA1 Message Date
Saiiijchan
fed39c5ea7
Refine comments related to taskYIELD in queue.h (#1333)
Replace taskYIELD with portYIELD_FROM_ISR

Signed-off-by: wangfei_chen <wangfei_chen@realsil.com.cn>
Co-authored-by: wangfei_chen <wangfei_chen@realsil.com.cn>
2025-11-12 13:51:08 +05:30
Saiiijchan
439af33c52
riscv: refine vector context layout on stack (#1329)
Vector general register layout:

Before:
+--------------+  <-- High Address
|      v7      |
+--------------+
|      v6      |
+--------------+
|      ...     |
+--------------+
|      v0      |
+--------------+  <-- v0 - v7
|      v15     |
+--------------+
|      v14     |
+--------------+
|      ...     |
+--------------+
|      v8      |
+--------------+  <-- v8 - v15
|      ...     |
+--------------+
|      v24     |
+--------------+  <-- Low address

After:
+--------------+  <-- High Address
|      v31     |
+--------------+
|      v30     |
+--------------+
|      ...     |
+--------------+
|      v1      |
+--------------+
|      v0      |
+--------------+ <-- Low Address

Signed-off-by: wangfei_chen <wangfei_chen@realsil.com.cn>
Co-authored-by: wangfei_chen <wangfei_chen@realsil.com.cn>
Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com>
2025-11-04 08:44:16 -08:00
Gaurav-Aggarwal-AWS
c8d31ddcff
Use saved mstatus for FPU/VPU state determination (#1330)
According to the RISC-V Privileged Architecture Specification (20211203),
writing Initial or Clean to the FS field of mstatus may result in the FS
value getting set to Dirty in some implementations. This means we cannot
rely on reading back the same FS value after writing to mstatus.

Previously, the context restore code would:
1. Write an FS value to mstatus
2. Read mstatus again at a later point
3. Use the read FS value to determine FPU status

This change updates the context restore code to use the mstatus value
from the saved context instead of re-reading mstatus after writing to
it. This required chaning the location of the mstatus slot in the
context.

Fixes: https://github.com/FreeRTOS/FreeRTOS-Kernel/issues/1327

Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>
2025-11-03 12:32:08 +05:30
Sheng Tai
8b63f94d8d
Fix: Propagate PICO_SDK_VERSION_* to parent scope in RP2040 port (#1326) 2025-10-29 14:35:00 -07:00
Kody Stribrny
13074875c2 Prefer xTaskDelayUntil in config template
xTaskDelayUntil is more featured and should
be preferred by new users. This change was inspired by
https://forums.freertos.org/t/include-xtaskdelayuntil-vs-include-vtaskdelayuntil/24656.
2025-10-27 20:27:19 -07:00
Pascal Reich
e5987bbdb2
Remove Unused Code and Preprocessor Directives in RP2040 Port (#1324)
* Remove redundant code and preprocessor directives

* Remove more redundant code and directives
2025-10-08 18:06:45 +05:30
Ths.quiniou
a1f6e1f64f
fix[RL78 Port] incorrect register image for pvParameters in FAR model (#1316) (#1317)
In the RL78 FAR data model, pxPortInitialiseStack() did not initialize
the register image for the task parameter (pvParameters) correctly.
A:DE registers were saved with dummy values instead of the actual pointer.

Effect: on first context restore the function prologue read a corrupted
parameter. NEAR builds were not affected.

This patch aligns the FAR path with the calling convention and compiler
version:
 - IAR V2: pass pvParameters via registers → DE = low 16 bits, A = high 8
 - IAR V1 (fallback): keep legacy stack write
Also keeps the original stack-frame layout and updates the comment to
reflect that pointer sizes depend on __DATA_MODEL__.

Result: tasks in FAR receive the correct parameter at entry; NEAR remains
unchanged.

Co-authored-by: Thomas Quiniou <tquiniou@fdi-access.com>
2025-10-06 18:37:11 +05:30
Ahmed Ismail
a8ae21c88e
armv8-r: Add Arm Cortex-R82 non-MPU port (#1289)
The goal of this commit is to add the GCC/ARMClang non-MPU
port variant for ARM Cortex-R82 processor which is
ARMv8-R AArch64 based.
The work done is inspired by the GCC ARM_AARCH64 FreeRTOS port.

This port has the following features:
* Uses single security state (non TrustZone).
* Supports SMP (Symmetric multi-processing).
* Doesn't support Hypervisor (EL2).
* Doesn't support neither PMSA (MPU) nor VMSA (MMU).

Signed-off-by: Ahmed Ismail <Ahmed.Ismail@arm.com>
2025-09-29 20:10:22 +05:30
mathiasgredal
3d44975181
RP2040: Fix use of deprecated volatile semantics for C++20 (#1318) (#1319)
Co-authored-by: Mathias Gredal <matg@universal-robots.com>
Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com>
2025-09-17 12:44:14 +05:30
razrbro
692c4b070f
Fix: avoid set but unused variable warning in pxPortInitialiseStack (#1320) 2025-09-17 11:19:04 +05:30
Ahmed Ismail
44ae6cf61a
cortex-M ports: Clarify hardware-saved exception frame size variable (#1314)
* cortex-M ports: Clarify hardware-saved exception frame size variable

- Rename ulStackFrameSize to ulHardwareSavedExceptionFrameSize to
reflect the hardware-saved exception frame (8 or 26 words based
on FPU/lazy stacking).
- Add comments explaining standard vs extended frames.
- Apply across Cortex-M ports.
- No functional change, improves readability.

Signed-off-by: Ahmed Ismail <Ahmed.Ismail@arm.com>
Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>

* kernel-checker-script: Modify Arm copyright header regex

Arm's copyright header regex is modified with the following:

* Accept both single year copyright headers (e.g., "2024")
and year range copyright headers (e.g., "2024-2025").

* Accept both single-line copyright header and also
multi-line header.

* Add the escape backslash to accept only literal dot
not any character.

Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>
Signed-off-by: Ahmed Ismail <Ahmed.Ismail@arm.com>

---------

Signed-off-by: Ahmed Ismail <Ahmed.Ismail@arm.com>
Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>
2025-09-09 14:25:42 +08:00
Kim Lindberg Schwaner
ccabdec2f8
Fix risk of Win32 timer setup call getting ignored (#1311)
If a user configures the configASSERT macro to expand to nothing,
a call to the Win32 API SetWaitableTimer() doesn't get compiled.

This can happen if, for example, configASSERT(x) set defined as
assert(x) (from assert.h) which expands to nothing when NDEBUG is
set (common for "release" builds).
2025-08-15 11:09:28 -07:00
DuYicheng
386c1bca66
Change the macro from portMAX_DELAY to SIZE_MAX in order to initialize size_t-type variable correctly (#1310) 2025-08-15 12:37:23 +05:30
Ahmed Ismail
43947413b9
event-groups: Fix multiple definitions (#1307)
This commit does the following:
* Remove xEventGroupClearBitsFromISR and
xEventGroupSetBitsFromISR functions direct mapping
to xTimerPendFunctionCallFromISR in case the trace
facility is feature not set. This should match the
current implementation in which the application calling
xEventGroupClearBitsFromISR
without defining the trace macros
(i.e. traceENTER_xEventGroupClearBitsFromISR is
a blank function in this case) will end up calling
xTimerPendFunctionCallFromISR function directly.
This enhances the readability of the code by not
guarding the xEventGroup<Set/Clear>BitsFromISR
functions' declaration and definition based on
the trace facility macro (i.e. configUSE_TRACE_FACILITY).

* Refactor the guarding macros for MPU_xEventGroupClearBitsFromISR
and MPU_xEventGroupSetBitsFromISR functions to match the
change above.

The current implementation leads to redefinition warnings
as `event_groups.h`redefines xEventGroupClearBitsFromISR
and xEventGroupSetBitsFromISR based on
`configUSE_TRACE_FACILITY' after they have been defined based
on configUSE_MPU_WRAPPERS_V1 in `mpu_wrappers.h`. The
implemented changes should resolve these warnings.

Signed-off-by: Ahmed Ismail <Ahmed.Ismail@arm.com>
2025-08-14 10:40:59 -07:00
Dennis Lambe Jr.
c91ee8d724
Fix CMake build for GCC_ARM_CRx_MPU (#1308) (#1309)
Add GCC_ARM_CRX_MPU to the set of FREERTOS_PORT patterns that trigger
adding mpu_wrappers.c and mpu_wrappers_v2.c to freertos_kernel_port
target_sources.
2025-08-14 10:35:53 +05:30
creiter64
e9440d4079
Move windows headers to port.c (#1302)
* [MSVC-MingW] Move windows headers to port.c

This prevents the inclusion of windows.h. into all header files using
FreeRTOS.h and thus defining several macros conflicting with common
definitions.

* [MSVC-MingW] Include correct header for compiler intrinsics

---------

Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com>
2025-08-05 19:11:54 +08:00
Dennis Lambe Jr.
c5bec0e4b2
LLVM assembler compatibility for ARM_CRx_MPU (#1303)
GNU as makes unrecognized sections loadable and writable by default, but
LLVM's assembler requires specifying flags explicitly. Without them, the
linker generates "has non-ABS relocation" errors when trying to link the
resulting object files.
2025-08-05 16:02:03 +05:30
Gaurav-Aggarwal-AWS
2da35debfd
Add missing cast to BaseType_t (#1301)
Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>
2025-07-31 10:32:23 +08:00
Gaurav-Aggarwal-AWS
32e581636f
Delete thread key on process exit (#1297)
Previously, the shared thread key was deleted in xPortStartScheduler
after scheduler was ended. This created a race condition where
prvThreadKeyDestructor (responsible for freeing thread-specific heap
memory) would not be called if xPortStartScheduler deleted the key
before the last task deletion, as destructors are not invoked after key
deletion (see https://github.com/walac/glibc/blob/master/nptl/pthread_create.c#L145-L150).

Move thread key deletion to process exit to ensure all thread-specific
memory is properly freed.

Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>
2025-07-24 11:07:27 +05:30
Gaurav-Aggarwal-AWS
684b34ca8d
Define security extension configs before portable.h (#1294)
Define configENABLE_PAC and configENABLE_BTI before including portable.h
to prevent "used before definition" warnings when these macros are not
set in FreeRTOSConfig.h.

Fixes: https://github.com/FreeRTOS/FreeRTOS-Kernel/issues/1293

Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>
2025-07-14 16:20:18 +05:30
Aniruddha Kanhere
f5e6151b14
Update artifact path in the backup action (#1292)
* Add artifact backup action

* Fix artifact path
2025-07-09 09:53:13 -07:00
Florian La Roche
48a4939c9f
Fix compiler warning (#1291)
- In list.h fix a typo in comments.
- In portable/ThirdParty/GCC/Posix/port.c fix compiler warning about
  "gcc -Wwrite-strings".

Signed-off-by: Florian La Roche <Florian.LaRoche@gmail.com>
Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com>
2025-07-09 11:16:00 +05:30
Aniruddha Kanhere
e3a362b1d1
Add artifact backup action (#1290) 2025-07-07 18:15:46 +05:30
Gaurav-Aggarwal-AWS
7225fbcbb9
Fix datatype of queue item length macros (#1286)
The uxItemSize parameter in xQueueGenericCreate and
xQueueGeneenericCreateStatic APIs expects a UBaseType_t type.
Previously, the semSEMAPHORE_QUEUE_ITEM_LENGTH macro incorrectly cast
the value to uint8_t, causing type mismatch warnings. This change
resolves the issue by properly casting the value to UBaseType_t.

This issue was reported here: https://github.com/FreeRTOS/FreeRTOS-Kernel/issues/1285.

Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>
2025-06-30 18:11:30 +05:30
Florian La Roche
a882b10526
fix possible NULL pointer dereference after call to configASSERT() (#1284)
Compiling with clang static code analysis, possible NULL pointer
dereference are found. Since configASSERT() can possibly return
and continue "normal" operation, the code in queue.c and
stream_buffer.c can be adjusted to avoid NULL pointer exceptions.

Signed-off-by: Florian La Roche <Florian.LaRoche@gmail.com>
2025-06-30 12:05:46 +05:30
Dakshit Babbar
0ae0715ac9
Update codecov badge url (#1283) 2025-06-16 20:39:05 +05:30
Rahul Kar
62bd622ffc
Update download locations to outside repository content (#1280)
Update curl command to download in a non user accessible folder
2025-06-05 23:23:47 +05:30
Simon Brizard
2615dcde13
fix[IAR/RL78 Port] Compilation fails on portasm.s file (#1278)
The indentation on ASM macro is not authorized by IAR compiler
2025-05-12 21:20:46 +05:30
Archit Gupta
03dc002c9b
Remove formatting bot workflow (#1274) 2025-05-09 14:09:08 -07:00
Gaurav-Aggarwal-AWS
e3a0e3e86a
Revert "FreeRTOS SMP: direct access to current TCB inside stack macros (#1270)" (#1272)
This reverts commit 4162ca49d6.
2025-05-05 15:45:15 +05:30
Matth9814
4162ca49d6
FreeRTOS SMP: direct access to current TCB inside stack macros (#1270)
FreeRTOS SMP: direct access to current TCB inside stack macros
2025-04-30 13:12:08 +05:30
Florian La Roche
d03233f209
fix warnings from "gcc -Wconversion" (#1271)
fix warnings from "gcc -Wconversion"

Signed-off-by: Florian La Roche <Florian.LaRoche@gmail.com>
2025-04-28 09:51:58 +05:30
Mario Luzeiro
4ee6a1f22f
MPLAB PIC32MZ-EF - Adds an assert to catch register overflow (#1265) (#1267)
Add an assert to catch register overflow (#1265)
2025-04-25 17:05:15 +05:30
arctic-alpaca
03db672b8f
Fix race in POSIX port vPortEndScheduler (#1262)
* Fix race in POSIX port `vPortEndScheduler`

The `vPortEndScheduler` checks whether it's a FreeRTOS thread after signalling the scheduler thread to stop. This creates a race between the check and the destruction of the thread key. By moving the signal to the scheduler thread after the check, the race is prevented.

* Code review suggestions

Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>

---------

Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>
Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com>
2025-04-03 14:32:44 +05:30
Jonathan Cubides
0030d609a4
Add support for Vector context save support on RISC-V (#1260)
port: riscv: Add vector context save support
2025-03-27 15:22:22 +05:30
ErickReyesR
b9aa064591
FreeRTOS MPU: Remove MPU region number check (#1261)
FreeRTOS MPU: Remove MPU region number check

This change removes the assertion and runtime check that enforces
matching between configTOTAL_MPU_REGIONS and physical MPU
regions,. This allows applications running on devices with 16 MPU
regions to manage 8 MPU regions while leaving the remaining 8
for the kernel.

Signed-off-by: Erick Reyes <erickreyes@google.com>
2025-03-19 15:01:22 +05:30
Gaurav-Aggarwal-AWS
dacce186cf
Use UBaseType_t for ullMachineTimerCompareRegisterBase (#1258)
Use architecture-dependent UBaseType_t instead of fixed type for
ullMachineTimerCompareRegisterBase. This type is defined to uint32_t or
uint64_t based on XLEN, resolving warnings on 32-bit platforms.

Reported by landretk@ on the PR FreeRTOS/FreeRTOS-Kernel#1176.

Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>
2025-03-17 16:41:11 +05:30
Saiiijchan
64fd9291ef
RISC-V: refine fpu reg context offset (#1257)
RISC-V: refine fpu reg context offset

pxCode and mstatus stored at index 0 and 1 are based on XLEN.
Therefore, the correct formula to calculate the FPU register index
should be ( ( 2 * portWORD_SIZE ) + ( regIndex * portFPU_REG_SIZE ) ).

Signed-off-by: wangfei_chen <wangfei_chen@realsil.com.cn>
2025-03-13 21:10:51 +05:30
Saiiijchan
bb47bc02f2
RISC-V: refine fpu offset according to portFPU_REG_SIZE (#1256)
Signed-off-by: wangfei_chen <wangfei_chen@realsil.com.cn>
Co-authored-by: wangfei_chen <wangfei_chen@realsil.com.cn>
2025-03-13 11:22:38 +05:30
Jonathan Cubides
4d9cd906d3
RISCV Add FPU context save (#1250)
* port: riscv: Split the number of registers and the size of the context

* port: riscv: Create some macros for the FPU context

* port: riscv: Add a couple of macros that store fpu context

* port: riscv: Update the stack init function to include the fpu context size

* port: riscv: Add a chip_specific_extensions file that includes the F extension

* Update dictionary to include some risc-v instructions

* port: riscv: Fix a few typos

* port: riscv: Apply @aggarg's sugestions
2025-03-06 10:34:48 -08:00
Stefan Innerhofer
742729ed29
Add an assert o catch overflow of recursive mutex counter (#1254)
Add an assert o catch overflow of recursive mutex counter.
2025-03-04 15:25:19 +05:30
73 changed files with 7948 additions and 5695 deletions

View file

@ -23,6 +23,7 @@ AIRCR
ALMIEN ALMIEN
ALMV ALMV
ANDC ANDC
andi
ANDCCR ANDCCR
APIC APIC
APROCFREQ APROCFREQ
@ -47,6 +48,7 @@ bcpc
BCPC BCPC
beevt beevt
BEEVT BEEVT
beqz
BERR BERR
bfextu bfextu
Biagioni Biagioni
@ -298,6 +300,7 @@ FADD
FCMD FCMD
fcolor fcolor
FCSE FCSE
fcsr
fdiagnostics fdiagnostics
fdiv fdiv
FDIV FDIV
@ -427,6 +430,7 @@ ldrbs
LDRBS LDRBS
LDRNE LDRNE
ldsr ldsr
ldxr
lidt lidt
LINKR LINKR
LJMP LJMP
@ -502,6 +506,7 @@ movs
movw movw
MOVWF MOVWF
movx movx
MPIDR
MPLAB MPLAB
MPUCTRL MPUCTRL
MQTT MQTT
@ -776,6 +781,7 @@ SETINTENA
SETPSW SETPSW
SETR SETR
setvect setvect
sevl
SFRC SFRC
SHLL SHLL
SHLR SHLR
@ -783,6 +789,7 @@ SHPR
SHTIM SHTIM
SIFIVE SIFIVE
sinclude sinclude
slli
SODR SODR
SOFTIRQ SOFTIRQ
SPCK SPCK
@ -805,6 +812,7 @@ STTBRK
STTDLY STTDLY
STTOUT STTOUT
STTTO STTTO
stxr
SVACC SVACC
svcne svcne
SVDIS SVDIS
@ -934,6 +942,7 @@ USRIO
utest utest
utilises utilises
utilising utilising
vcsr
VDDCORE VDDCORE
vect vect
Vect Vect
@ -944,6 +953,7 @@ visualisation
vldmdbeq vldmdbeq
vldmia vldmia
vldmiaeq vldmiaeq
vlenb
VMSRNE VMSRNE
vpop vpop
VPOPNE VPOPNE
@ -951,6 +961,7 @@ vpush
VPUSHNE VPUSHNE
VRPM VRPM
Vrtc Vrtc
vsetvl
vstmdbeq vstmdbeq
vstmiaeq vstmiaeq
VTOR VTOR

View file

@ -114,6 +114,11 @@ KERNEL_ARM_COLLAB_FILES_PATTERNS = [
r'.*portable/.*/ARM_CM35*', r'.*portable/.*/ARM_CM35*',
r'.*portable/.*/ARM_CM55*', r'.*portable/.*/ARM_CM55*',
r'.*portable/.*/ARM_CM85*', r'.*portable/.*/ARM_CM85*',
r'.*portable/.*/ARM_CM0*',
r'.*portable/.*/ARM_CM3_MPU*',
r'.*portable/.*/ARM_CM4_MPU*',
r'.*portable/.*/ARM_CM4F_MPU*',
r'.*portable/.*/ARM_CR82*',
] ]
KERNEL_HEADER = [ KERNEL_HEADER = [
@ -150,8 +155,8 @@ KERNEL_HEADER = [
FREERTOS_COPYRIGHT_REGEX = r"^(;|#)?( *(\/\*|\*|#|\/\/))? Copyright \(C\) 20\d\d Amazon.com, Inc. or its affiliates. All Rights Reserved\.( \*\/)?$" FREERTOS_COPYRIGHT_REGEX = r"^(;|#)?( *(\/\*|\*|#|\/\/))? Copyright \(C\) 20\d\d Amazon.com, Inc. or its affiliates. All Rights Reserved\.( \*\/)?$"
FREERTOS_ARM_COLLAB_COPYRIGHT_REGEX = r"(^(;|#)?( *(\/\*|\*|#|\/\/))? Copyright \(C\) 20\d\d Amazon.com, Inc. or its affiliates. All Rights Reserved\.( \*\/)?$)|" + \ FREERTOS_ARM_COLLAB_COPYRIGHT_REGEX = r"(^(;|#)?( *(\/\*|\*|#|\/\/))? Copyright \(C\) 20\d\d Amazon.com, Inc. or its affiliates. All Rights Reserved\.( \*\/)?$)|" + \
r"(^(;|#)?( *(\/\*|\*|#|\/\/))? Copyright 20\d\d Arm Limited and/or its affiliates( \*\/)?$)|" + \ r"(^(;|#)?( *(\/\*|\*|#|\/\/))? Copyright 20\d\d(-20\d\d)? Arm Limited and/or its affiliates( +<open-source-office@arm\.com>)?( \*\/)?$)|" + \
r"(^(;|#)?( *(\/\*|\*|#|\/\/))? <open-source-office@arm.com>( \*\/)?$)" r"(^(;|#)?( *(\/\*|\*|#|\/\/))? <open-source-office@arm\.com>( \*\/)?$)"
class KernelHeaderChecker(HeaderChecker): class KernelHeaderChecker(HeaderChecker):

View file

@ -18,6 +18,8 @@ on:
jobs: jobs:
release-packager: release-packager:
permissions:
id-token: write
name: Release Packager name: Release Packager
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@ -117,6 +119,14 @@ jobs:
./tools/.github/scripts/release.py "$REPO_OWNER" --kernel-repo-path=local_kernel --kernel-commit="$COMMIT_SHA_2" --new-kernel-version="$VERSION_NUMBER" --new-kernel-main-br-version="$MAIN_BR_VERSION_NUMBER" ./tools/.github/scripts/release.py "$REPO_OWNER" --kernel-repo-path=local_kernel --kernel-commit="$COMMIT_SHA_2" --new-kernel-version="$VERSION_NUMBER" --new-kernel-main-br-version="$MAIN_BR_VERSION_NUMBER"
exit $? exit $?
- name: Backup Release Asset
uses: FreeRTOS/CI-CD-Github-Actions/artifact-backup@main
with:
# This is dependent on the release script putting this zip file
# in this exact location.
artifact_path: ./FreeRTOS-KernelV${{ github.event.inputs.version_number }}.zip
release_tag: ${{ github.event.inputs.version_number }}
- name: Cleanup - name: Cleanup
env: env:
VERSION_NUMBER: ${{ github.event.inputs.version_number }} VERSION_NUMBER: ${{ github.event.inputs.version_number }}

View file

@ -7,7 +7,7 @@ on:
workflow_dispatch: workflow_dispatch:
jobs: jobs:
formatting: formatting:
runs-on: ubuntu-20.04 runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4.1.1 - uses: actions/checkout@v4.1.1
- name: Check Formatting of FreeRTOS-Kernel Files - name: Check Formatting of FreeRTOS-Kernel Files

View file

@ -42,11 +42,22 @@ jobs:
# ${{ env.stepName }} # ${{ env.stepName }}
echo -e "::group::${{ env.bashInfo }} ${{ env.stepName }} ${{ env.bashEnd }}" echo -e "::group::${{ env.bashInfo }} ${{ env.stepName }} ${{ env.bashEnd }}"
wget -nv -qO- https://scan.coverity.com/download/linux64 --post-data "token=${COVERITY_TOKEN}&project=FreeRTOS-Kernel" | tar -zx --one-top-level=cov_scan --strip-components 1 wget -nv -q -O "$HOME/cov-analysis.tar.gz" https://scan.coverity.com/download/linux64 --post-data="token=${COVERITY_TOKEN}&project=FreeRTOS-Kernel"
echo "cov_scan_path=$(pwd)/cov_scan/bin" >> $GITHUB_ENV
EXPECTED_MD5="e4418004b073140d67390cffba79c3b2"
GENERATED_MD5=$(md5sum "$HOME/cov-analysis.tar.gz" | awk '{print $1}')
if [ "$GENERATED_MD5" = "$EXPECTED_MD5" ]; then
tar -zxf "$HOME/cov-analysis.tar.gz" --one-top-level=cov_scan -C "$HOME"
echo "cov_scan_path=$HOME/cov_scan/bin" >> $GITHUB_ENV
sudo rm -f "$HOME/cov-analysis.tar.gz"
echo "::endgroup::" echo "::endgroup::"
echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }} " echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }} "
else
echo -e "${{ env.bashFail }} MD5 checksum verification failed for cov-analysis.tar.gz ${{ env.bashEnd }}"
echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}"
exit -1
fi
- env: - env:
stepName: Coverity Build stepName: Coverity Build

View file

@ -1,25 +0,0 @@
name: Format Pull Request Files
on:
issue_comment:
types: [created]
env:
bashPass: \033[32;1mPASSED -
bashInfo: \033[33;1mINFO -
bashFail: \033[31;1mFAILED -
bashEnd: \033[0m
jobs:
Formatting:
name: Run Formatting Check
if: ${{ github.event.issue.pull_request &&
( ( github.event.comment.body == '/bot run uncrustify' ) ||
( github.event.comment.body == '/bot run formatting' ) ) }}
runs-on: ubuntu-20.04
steps:
- name: Apply Formatting Fix
id: check-formatting
uses: FreeRTOS/CI-CD-Github-Actions/formatting-bot@main
with:
exclude-dirs: portable

View file

@ -5,7 +5,7 @@ on: [push, pull_request]
jobs: jobs:
kernel-checker: kernel-checker:
name: FreeRTOS Kernel Header Checks name: FreeRTOS Kernel Header Checks
runs-on: ubuntu-20.04 runs-on: ubuntu-latest
steps: steps:
# Install python 3 # Install python 3
- name: Tool Setup - name: Tool Setup

View file

@ -156,14 +156,27 @@ jobs:
run: | run: |
# ${{ env.stepName }} # ${{ env.stepName }}
echo -e "::group::${{ env.bashInfo }} ${{ env.stepName }} ${{ env.bashEnd }}" echo -e "::group::${{ env.bashInfo }} ${{ env.stepName }} ${{ env.bashEnd }}"
curl -L -O https://dr-download.ti.com/software-development/ide-configuration-compiler-or-debugger/MD-LlCjWuAbzH/9.3.1.2/msp430-gcc-full-linux-x64-installer-9.3.1.2.7z
sudo apt update -y sudo apt update -y
sudo apt install -y p7zip-full sudo apt install -y p7zip-full
pushd $HOME
curl -L -o msp430-gcc-full-linux-x64-installer-9.3.1.2.7z https://dr-download.ti.com/software-development/ide-configuration-compiler-or-debugger/MD-LlCjWuAbzH/9.3.1.2/msp430-gcc-full-linux-x64-installer-9.3.1.2.7z
EXPECTED_MD5="2db2f99b4cd5c541ca0389ee20c67527"
GENERATED_MD5=$(md5sum msp430-gcc-full-linux-x64-installer-9.3.1.2.7z | awk '{print $1}')
if [ "$GENERATED_MD5" = "$EXPECTED_MD5" ]; then
7z x ./msp430-gcc-full-linux-x64-installer-9.3.1.2.7z 7z x ./msp430-gcc-full-linux-x64-installer-9.3.1.2.7z
chmod +x ./msp430-gcc-full-linux-x64-installer-9.3.1.2.run chmod +x ./msp430-gcc-full-linux-x64-installer-9.3.1.2.run
sudo ./msp430-gcc-full-linux-x64-installer-9.3.1.2.run --prefix /usr/bin/msp430-gcc --mode unattended sudo ./msp430-gcc-full-linux-x64-installer-9.3.1.2.run --prefix /usr/bin/msp430-gcc --mode unattended
echo "::endgroup::" echo "::endgroup::"
popd
echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}" echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}"
else
popd
echo -e "${{ env.bashFail }} MD5 checksum verification failed for msp430-gcc-full-linux-x64-installer-9.3.1.2.7z ${{ env.bashEnd }}"
echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}"
exit -1
fi
- name: Build msp430_GCC Demo - name: Build msp430_GCC Demo
shell: bash shell: bash
@ -211,21 +224,23 @@ jobs:
sudo apt install -y autogen gawk libgmp-dev libmpc-dev libmpfr-dev sudo apt install -y autogen gawk libgmp-dev libmpc-dev libmpfr-dev
sudo apt install -y patchutils sharutils zlib1g-dev autoconf2.64 sudo apt install -y patchutils sharutils zlib1g-dev autoconf2.64
pushd $HOME
# Download the mb-gcc toolchain from github # Download the mb-gcc toolchain from github
curl -L -O https://github.com/mdednev/mb-gcc/releases/download/2021-0623%2B2/binutils-microblaze_2.35-2021-0623+1_amd64.deb; curl -L -o binutils-microblaze.deb https://github.com/mdednev/mb-gcc/releases/download/2021-0623%2B2/binutils-microblaze_2.35-2021-0623+1_amd64.deb;
curl -L -O https://github.com/mdednev/mb-gcc/releases/download/2021-0623%2B2/gcc-microblaze_10.2.0-2021-0623+2_amd64.deb; curl -L -o gcc-microblaze.deb https://github.com/mdednev/mb-gcc/releases/download/2021-0623%2B2/gcc-microblaze_10.2.0-2021-0623+2_amd64.deb;
curl -L -O https://github.com/mdednev/mb-gcc/releases/download/2021-0623%2B2/libnewlib-microblaze-dev_3.3.0-2021-0623+3_all.deb; curl -L -o libnewlib-microblaze-dev.deb https://github.com/mdednev/mb-gcc/releases/download/2021-0623%2B2/libnewlib-microblaze-dev_3.3.0-2021-0623+3_all.deb;
curl -L -O https://github.com/mdednev/mb-gcc/releases/download/2021-0623%2B2/libnewlib-microblaze-doc_3.3.0-2021-0623+3_all.deb; curl -L -o libnewlib-microblaze-doc.deb https://github.com/mdednev/mb-gcc/releases/download/2021-0623%2B2/libnewlib-microblaze-doc_3.3.0-2021-0623+3_all.deb;
curl -L -O https://github.com/mdednev/mb-gcc/releases/download/2021-0623%2B2/libnewlib-microblaze_3.3.0-2021-0623+3_all.deb; curl -L -o libnewlib-microblaze.deb https://github.com/mdednev/mb-gcc/releases/download/2021-0623%2B2/libnewlib-microblaze_3.3.0-2021-0623+3_all.deb;
curl -L -O https://github.com/mdednev/mb-gcc/releases/download/2021-0623%2B2/newlib-source_3.3.0-2021-0623+3_all.deb; curl -L -o newlib-source.deb https://github.com/mdednev/mb-gcc/releases/download/2021-0623%2B2/newlib-source_3.3.0-2021-0623+3_all.deb;
popd
# Install the packages for the toolchain # Install the packages for the toolchain
sudo apt install -y ./binutils-microblaze*.deb; sudo apt install -y $HOME/binutils-microblaze.deb;
sudo apt install -y ./gcc-microblaze*.deb; sudo apt install -y $HOME/gcc-microblaze.deb;
sudo apt install -y ./libnewlib-microblaze-dev*.deb; sudo apt install -y $HOME/libnewlib-microblaze-dev.deb;
sudo apt install -y ./libnewlib-microblaze-doc*.deb; sudo apt install -y $HOME/libnewlib-microblaze-doc.deb;
sudo apt install -y ./libnewlib-microblaze*.deb; sudo apt install -y $HOME/libnewlib-microblaze.deb;
sudo apt install -y ./newlib-source*.deb; sudo apt install -y $HOME/newlib-source.deb;
# Validate that the toolchain is in the path and can be called # Validate that the toolchain is in the path and can be called
which mb-gcc which mb-gcc

View file

@ -3,7 +3,7 @@ on: [push, pull_request]
jobs: jobs:
run: run:
runs-on: ubuntu-20.04 runs-on: ubuntu-latest
steps: steps:
- name: Checkout Parent Repository - name: Checkout Parent Repository
uses: actions/checkout@v4.1.1 uses: actions/checkout@v4.1.1

View file

@ -87,6 +87,7 @@ if(NOT FREERTOS_PORT)
" GCC_ARM_CR5 - Compiler: GCC Target: ARM Cortex-R5\n" " GCC_ARM_CR5 - Compiler: GCC Target: ARM Cortex-R5\n"
" GCC_ARM_CRX_MPU - Compiler: GCC Target: ARM Cortex-Rx with MPU\n" " GCC_ARM_CRX_MPU - Compiler: GCC Target: ARM Cortex-Rx with MPU\n"
" GCC_ARM_CRX_NOGIC - Compiler: GCC Target: ARM Cortex-Rx no GIC\n" " GCC_ARM_CRX_NOGIC - Compiler: GCC Target: ARM Cortex-Rx no GIC\n"
" GCC_ARM_CR82 - Compiler: GCC Target: ARM Cortex-R82\n"
" GCC_ARM7_AT91FR40008 - Compiler: GCC Target: ARM7 Atmel AT91R40008\n" " GCC_ARM7_AT91FR40008 - Compiler: GCC Target: ARM7 Atmel AT91R40008\n"
" GCC_ARM7_AT91SAM7S - Compiler: GCC Target: ARM7 Atmel AT91SAM7S\n" " GCC_ARM7_AT91SAM7S - Compiler: GCC Target: ARM7 Atmel AT91SAM7S\n"
" GCC_ARM7_LPC2000 - Compiler: GCC Target: ARM7 LPC2000\n" " GCC_ARM7_LPC2000 - Compiler: GCC Target: ARM7 LPC2000\n"

View file

@ -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++) [![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 ## Getting started

View file

@ -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, BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToClear ) const EventBits_t uxBitsToClear )
@ -518,7 +518,7 @@
return 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 ) 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, BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet, const EventBits_t uxBitsToSet,
@ -830,7 +830,7 @@
return 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 ) #if ( configUSE_TRACE_FACILITY == 1 )

View file

@ -415,6 +415,8 @@
* number of the failing assert (for example, "vAssertCalled( __FILE__, __LINE__ * number of the failing assert (for example, "vAssertCalled( __FILE__, __LINE__
* )" or it can simple disable interrupts and sit in a loop to halt all * )" or it can simple disable interrupts and sit in a loop to halt all
* execution on the failing line for viewing in a debugger. */ * execution on the failing line for viewing in a debugger. */
/* *INDENT-OFF* */
#define configASSERT( x ) \ #define configASSERT( x ) \
if( ( x ) == 0 ) \ if( ( x ) == 0 ) \
{ \ { \
@ -422,6 +424,7 @@
for( ; ; ) \ for( ; ; ) \
; \ ; \
} }
/* *INDENT-ON* */
/******************************************************************************/ /******************************************************************************/
/* FreeRTOS MPU specific definitions. *****************************************/ /* FreeRTOS MPU specific definitions. *****************************************/
@ -650,7 +653,7 @@
#define INCLUDE_uxTaskPriorityGet 1 #define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1 #define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskSuspend 1 #define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1 #define INCLUDE_xTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1 #define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 1 #define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_xTaskGetCurrentTaskHandle 1 #define INCLUDE_xTaskGetCurrentTaskHandle 1

View file

@ -101,6 +101,16 @@
#define configASSERT_DEFINED 1 #define configASSERT_DEFINED 1
#endif #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. */ /* Basic FreeRTOS definitions. */
#include "projdefs.h" #include "projdefs.h"
@ -3040,16 +3050,6 @@
#define configCONTROL_INFINITE_LOOP() #define configCONTROL_INFINITE_LOOP()
#endif #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 /* 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 * 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 * that both the task's stack and TCB need to be freed. Sometimes the

View file

@ -246,7 +246,10 @@ void vCoRoutineSchedule( void );
* \defgroup crSTART crSTART * \defgroup crSTART crSTART
* \ingroup Tasks * \ingroup Tasks
*/ */
/* *INDENT-OFF* */
#define crEND() } #define crEND() }
/* *INDENT-ON* */
/* /*
* These macros are intended for internal use by the co-routine implementation * These macros are intended for internal use by the co-routine implementation

View file

@ -452,13 +452,10 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
* \defgroup xEventGroupClearBitsFromISR xEventGroupClearBitsFromISR * \defgroup xEventGroupClearBitsFromISR xEventGroupClearBitsFromISR
* \ingroup EventGroup * \ingroup EventGroup
*/ */
#if ( configUSE_TRACE_FACILITY == 1 ) #if ( ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION; const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;
#else #endif /* if ( ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
#define xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ) \
xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) ( xEventGroup ), ( uint32_t ) ( uxBitsToClear ), NULL )
#endif
/** /**
* event_groups.h * event_groups.h
@ -607,14 +604,11 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
* \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR * \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR
* \ingroup EventGroup * \ingroup EventGroup
*/ */
#if ( configUSE_TRACE_FACILITY == 1 ) #if ( ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet, const EventBits_t uxBitsToSet,
BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
#else #endif /* if ( ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
#define xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ) \
xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) ( xEventGroup ), ( uint32_t ) ( uxBitsToSet ), ( pxHigherPriorityTaskWoken ) )
#endif
/** /**
* event_groups.h * event_groups.h

View file

@ -44,7 +44,7 @@
* *
* In addition to it's value, each list item contains a pointer to the next * In addition to it's value, each list item contains a pointer to the next
* item in the list (pxNext), a pointer to the list it is in (pxContainer) * 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 * pointers are included for efficiency of list manipulation. There is
* effectively a two way link between the object containing the list item and * effectively a two way link between the object containing the list item and
* the list item itself. * the list item itself.

View file

@ -409,13 +409,16 @@ EventBits_t MPU_xEventGroupSync( EventGroupHandle_t xEventGroup,
BaseType_t MPU_xEventGroupGetStaticBuffer( EventGroupHandle_t xEventGroup, BaseType_t MPU_xEventGroupGetStaticBuffer( EventGroupHandle_t xEventGroup,
StaticEventGroup_t ** ppxEventGroupBuffer ) PRIVILEGED_FUNCTION; 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; 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. */ /* MPU versions of message/stream_buffer.h API functions. */
size_t MPU_xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, size_t MPU_xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
const void * pvTxData, const void * pvTxData,

View file

@ -1026,7 +1026,11 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
* // Now the buffer is empty we can switch context if necessary. * // Now the buffer is empty we can switch context if necessary.
* if( xHigherPriorityTaskWoken ) * 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 * @endcode
@ -1098,7 +1102,11 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
* // Now the buffer is empty we can switch context if necessary. * // Now the buffer is empty we can switch context if necessary.
* if( xHigherPriorityTaskWoken ) * 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 * @endcode
@ -1429,23 +1437,27 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue,
* // ISR that outputs all the characters received on the queue. * // ISR that outputs all the characters received on the queue.
* void vISR_Routine( void ) * void vISR_Routine( void )
* { * {
* BaseType_t xTaskWokenByReceive = pdFALSE; * BaseType_t xHigherPriorityTaskWoken = pdFALSE;
* char cRxedChar; * char cRxedChar;
* *
* while( xQueueReceiveFromISR( xQueue, ( void * ) &cRxedChar, &xTaskWokenByReceive) ) * while( xQueueReceiveFromISR( xQueue, ( void * ) &cRxedChar, &xHigherPriorityTaskWoken) )
* { * {
* // A character was received. Output the character now. * // A character was received. Output the character now.
* vOutputCharacter( cRxedChar ); * vOutputCharacter( cRxedChar );
* *
* // If removing the character from the queue woke the task that was * // 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 * // pdTRUE. No matter how many times this loop iterates only one
* // task will be woken. * // 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 * @endcode

View file

@ -37,8 +37,8 @@
typedef QueueHandle_t SemaphoreHandle_t; typedef QueueHandle_t SemaphoreHandle_t;
#define semBINARY_SEMAPHORE_QUEUE_LENGTH ( ( uint8_t ) 1U ) #define semBINARY_SEMAPHORE_QUEUE_LENGTH ( ( UBaseType_t ) 1U )
#define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( uint8_t ) 0U ) #define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( UBaseType_t ) 0U )
#define semGIVE_BLOCK_TIME ( ( TickType_t ) 0U ) #define semGIVE_BLOCK_TIME ( ( TickType_t ) 0U )

View file

@ -1,7 +1,7 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates * Copyright 2024-2025 Arm Limited and/or its affiliates
* <open-source-office@arm.com> * <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
@ -230,7 +230,7 @@ typedef void ( * portISR_t )( void );
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
#endif /* portARMV8M_MINOR_VERSION >= 1 */ #endif /* portARMV8M_MINOR_VERSION >= 1 */
@ -241,9 +241,6 @@ typedef void ( * portISR_t )( void );
/* Enable MPU. */ /* Enable MPU. */
#define portMPU_ENABLE_BIT ( 1UL << 0UL ) #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 /* Extract first address of the MPU region as encoded in the
* RBAR (Region Base Address Register) value. */ * RBAR (Region Base Address Register) value. */
#define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \ #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@ -291,7 +288,7 @@ typedef void ( * portISR_t )( void );
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 ) #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF FD * FF FF FF FD
@ -308,7 +305,7 @@ typedef void ( * portISR_t )( void );
#define portINITIAL_EXC_RETURN ( 0xfffffffd ) #define portINITIAL_EXC_RETURN ( 0xfffffffd )
#else #else
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF BC * FF FF FF BC
@ -401,7 +398,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Extract MPU region's access permissions from the Region Base Address * @brief Extract MPU region's access permissions from the Region Base Address
* Register (RBAR) value. * Register (RBAR) value.
* *
@ -414,7 +411,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Setup the Memory Protection Unit (MPU). * @brief Setup the Memory Protection Unit (MPU).
*/ */
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
@ -422,7 +419,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
/** /**
* @brief Setup the Floating Point Unit (FPU). * @brief Setup the Floating Point Unit (FPU).
*/ */
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
@ -430,7 +427,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) ) #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
/** /**
* @brief Configures PACBTI features. * @brief Configures PACBTI features.
* *
* This function configures the Pointer Authentication, and Branch Target * This function configures the Pointer Authentication, and Branch Target
@ -491,7 +488,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Sets up the system call stack so that upon returning from * @brief Sets up the system call stack so that upon returning from
* SVC, the system call stack is used. * SVC, the system call stack is used.
* *
@ -507,7 +504,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
@ -516,7 +513,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( 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 * @brief Sets up the task stack so that upon returning from
* SVC, the task stack is used again. * SVC, the task stack is used again.
* *
@ -530,7 +527,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Checks whether or not the calling task is privileged. * @brief Checks whether or not the calling task is privileged.
* *
* @return pdTRUE if the calling task is privileged, pdFALSE otherwise. * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
@ -542,7 +539,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
@ -557,7 +554,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/** /**
* @brief Saved as part of the task context to indicate which context the * @brief Saved as part of the task context to indicate which context the
* task is using on the secure side. * task is using on the secure side.
*/ */
@ -579,18 +576,18 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configUSE_TICKLESS_IDLE == 1 ) #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; PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
/** /**
* @brief The maximum number of tick periods that can be suppressed is * @brief The maximum number of tick periods that can be suppressed is
* limited by the 24 bit resolution of the SysTick timer. * limited by the 24 bit resolution of the SysTick timer.
*/ */
PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
/** /**
* @brief Compensate for the CPU cycles that pass while the SysTick is * @brief Compensate for the CPU cycles that pass while the SysTick is
* stopped (low power functionality only). * stopped (low power functionality only).
*/ */
@ -925,12 +922,6 @@ static void prvTaskExitError( void )
/* The only permitted number of regions are 8 or 16. */ /* The only permitted number of regions are 8 or 16. */
configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 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 );
/* Check that the MPU is present. */
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
{
/* MAIR0 - Index 0. */ /* MAIR0 - Index 0. */
portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
/* MAIR0 - Index 1. */ /* MAIR0 - Index 1. */
@ -983,7 +974,6 @@ static void prvTaskExitError( void )
* regions have privileged access. */ * regions have privileged access. */
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
} }
}
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -1210,7 +1200,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ]; extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulSystemCallStack; uint32_t * pulSystemCallStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1246,12 +1236,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1261,20 +1255,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the system call stack for the stack frame. */ /* Make space on the system call stack for the stack frame. */
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize; pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulSystemCallStack[ i ] = pulTaskStack[ i ]; pulSystemCallStack[ i ] = pulTaskStack[ i ];
} }
@ -1310,7 +1304,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Remember the location where we should copy the stack frame when we exit from /* Remember the location where we should copy the stack frame when we exit from
* the system call. */ * the system call. */
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize; pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
/* Record if the hardware used padding to force the stack pointer /* Record if the hardware used padding to force the stack pointer
* to be double word aligned. */ * to be double word aligned. */
@ -1360,7 +1354,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern TaskHandle_t pxCurrentTCB; extern TaskHandle_t pxCurrentTCB;
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulTaskStack; uint32_t * pulTaskStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1392,12 +1386,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1407,20 +1405,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the task stack for the stack frame. */ /* Make space on the task stack for the stack frame. */
pulTaskStack = pulTaskStack - ulStackFrameSize; pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulTaskStack[ i ] = pulSystemCallStack[ i ]; pulTaskStack[ i ] = pulSystemCallStack[ i ];
} }

View file

@ -218,6 +218,11 @@ add_library(freertos_kernel_port OBJECT
GCC/ARM_CRx_No_GIC/port.c GCC/ARM_CRx_No_GIC/port.c
GCC/ARM_CRx_No_GIC/portASM.S> GCC/ARM_CRx_No_GIC/portASM.S>
# ARMv8-R ports for GCC
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CR82>:
GCC/ARM_CR82/port.c
GCC/ARM_CR82/portASM.S>
# ARMv4T ARM7TDMI ports for GCC # ARMv4T ARM7TDMI ports for GCC
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM7_AT91FR40008>: $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM7_AT91FR40008>:
GCC/ARM7_AT91FR40008/port.c GCC/ARM7_AT91FR40008/port.c
@ -769,6 +774,7 @@ add_library(freertos_kernel_port OBJECT
if( FREERTOS_PORT MATCHES "GCC_ARM_CM(3|4)_MPU" OR if( FREERTOS_PORT MATCHES "GCC_ARM_CM(3|4)_MPU" OR
FREERTOS_PORT STREQUAL "IAR_ARM_CM4F_MPU" OR FREERTOS_PORT STREQUAL "IAR_ARM_CM4F_MPU" OR
FREERTOS_PORT STREQUAL "RVDS_ARM_CM4_MPU" OR FREERTOS_PORT STREQUAL "RVDS_ARM_CM4_MPU" OR
FREERTOS_PORT STREQUAL "GCC_ARM_CRX_MPU" OR
FREERTOS_PORT MATCHES "GCC_ARM_CM(23|33|55|85)_NTZ_NONSECURE" OR FREERTOS_PORT MATCHES "GCC_ARM_CM(23|33|55|85)_NTZ_NONSECURE" OR
FREERTOS_PORT MATCHES "GCC_ARM_CM(23|33|55|85)_NONSECURE" OR FREERTOS_PORT MATCHES "GCC_ARM_CM(23|33|55|85)_NONSECURE" OR
FREERTOS_PORT MATCHES "GCC_ARM_CM(33|55|85)_TFM" OR FREERTOS_PORT MATCHES "GCC_ARM_CM(33|55|85)_TFM" OR
@ -963,6 +969,9 @@ target_include_directories(freertos_kernel_port_headers INTERFACE
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CRX_MPU>:${CMAKE_CURRENT_LIST_DIR}/GCC/ARM_CRx_MPU> $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CRX_MPU>:${CMAKE_CURRENT_LIST_DIR}/GCC/ARM_CRx_MPU>
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CRX_NOGIC>:${CMAKE_CURRENT_LIST_DIR}/GCC/ARM_CRx_No_GIC> $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CRX_NOGIC>:${CMAKE_CURRENT_LIST_DIR}/GCC/ARM_CRx_No_GIC>
# ARMv8-R ports for GCC
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CR82>:${CMAKE_CURRENT_LIST_DIR}/GCC/ARM_CR82>
# ARMv4T ARM7TDMI ports for GCC # ARMv4T ARM7TDMI ports for GCC
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM7_AT91FR40008>:${CMAKE_CURRENT_LIST_DIR}/GCC/ARM7_AT91FR40008> $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM7_AT91FR40008>:${CMAKE_CURRENT_LIST_DIR}/GCC/ARM7_AT91FR40008>
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM7_AT91SAM7S>:${CMAKE_CURRENT_LIST_DIR}/GCC/ARM7_AT91SAM7S> $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM7_AT91SAM7S>:${CMAKE_CURRENT_LIST_DIR}/GCC/ARM7_AT91SAM7S>

View file

@ -1059,8 +1059,8 @@
configRUN_TIME_COUNTER_TYPE * pulTotalRunTime ) /* PRIVILEGED_FUNCTION */ configRUN_TIME_COUNTER_TYPE * pulTotalRunTime ) /* PRIVILEGED_FUNCTION */
{ {
UBaseType_t uxReturn = 0; UBaseType_t uxReturn = 0;
UBaseType_t xIsTaskStatusArrayWriteable = pdFALSE; BaseType_t xIsTaskStatusArrayWriteable = pdFALSE;
UBaseType_t xIsTotalRunTimeWriteable = pdFALSE; BaseType_t xIsTotalRunTimeWriteable = pdFALSE;
uint32_t ulArraySize = ( uint32_t ) uxArraySize; uint32_t ulArraySize = ( uint32_t ) uxArraySize;
uint32_t ulTaskStatusSize = ( uint32_t ) sizeof( TaskStatus_t ); uint32_t ulTaskStatusSize = ( uint32_t ) sizeof( TaskStatus_t );
@ -4282,7 +4282,7 @@
#endif /* #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configUSE_EVENT_GROUPS == 1 ) ) */ #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, BaseType_t MPU_xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToClear ) /* PRIVILEGED_FUNCTION */ const EventBits_t uxBitsToClear ) /* PRIVILEGED_FUNCTION */
@ -4306,10 +4306,10 @@
return xReturn; 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, BaseType_t MPU_xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet, const EventBits_t uxBitsToSet,
@ -4334,7 +4334,7 @@
return xReturn; 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 ) #if ( configUSE_EVENT_GROUPS == 1 )

View file

@ -1,6 +1,8 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * 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 * SPDX-License-Identifier: MIT
* *
@ -915,7 +917,10 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulSystemCallStack; uint32_t * pulSystemCallStack;
uint32_t ulSystemCallLocation, i; 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 ) #if defined( __ARMCC_VERSION )
@ -955,10 +960,10 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack; pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
/* Make space on the system call stack for the stack frame. */ /* Make space on the system call stack for the stack frame. */
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize; pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulSystemCallStack[ i ] = pulTaskStack[ i ]; pulSystemCallStack[ i ] = pulTaskStack[ i ];
} }
@ -981,7 +986,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Remember the location where we should copy the stack frame when we exit from /* Remember the location where we should copy the stack frame when we exit from
* the system call. */ * the system call. */
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize; pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
/* Record if the hardware used padding to force the stack pointer /* Record if the hardware used padding to force the stack pointer
* to be double word aligned. */ * to be double word aligned. */
@ -1036,7 +1041,10 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulTaskStack; uint32_t * pulTaskStack;
uint32_t ulSystemCallLocation, i; 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 ) #if defined( __ARMCC_VERSION )
@ -1072,10 +1080,10 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack; pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
/* Make space on the task stack for the stack frame. */ /* Make space on the task stack for the stack frame. */
pulTaskStack = pulTaskStack - ulStackFrameSize; pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulTaskStack[ i ] = pulSystemCallStack[ i ]; pulTaskStack[ i ] = pulSystemCallStack[ i ];
} }

View file

@ -1,7 +1,7 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates * Copyright 2024-2025 Arm Limited and/or its affiliates
* <open-source-office@arm.com> * <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
@ -230,7 +230,7 @@ typedef void ( * portISR_t )( void );
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
#endif /* portARMV8M_MINOR_VERSION >= 1 */ #endif /* portARMV8M_MINOR_VERSION >= 1 */
@ -241,9 +241,6 @@ typedef void ( * portISR_t )( void );
/* Enable MPU. */ /* Enable MPU. */
#define portMPU_ENABLE_BIT ( 1UL << 0UL ) #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 /* Extract first address of the MPU region as encoded in the
* RBAR (Region Base Address Register) value. */ * RBAR (Region Base Address Register) value. */
#define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \ #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@ -291,7 +288,7 @@ typedef void ( * portISR_t )( void );
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 ) #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF FD * FF FF FF FD
@ -308,7 +305,7 @@ typedef void ( * portISR_t )( void );
#define portINITIAL_EXC_RETURN ( 0xfffffffd ) #define portINITIAL_EXC_RETURN ( 0xfffffffd )
#else #else
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF BC * FF FF FF BC
@ -401,7 +398,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Extract MPU region's access permissions from the Region Base Address * @brief Extract MPU region's access permissions from the Region Base Address
* Register (RBAR) value. * Register (RBAR) value.
* *
@ -414,7 +411,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Setup the Memory Protection Unit (MPU). * @brief Setup the Memory Protection Unit (MPU).
*/ */
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
@ -422,7 +419,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
/** /**
* @brief Setup the Floating Point Unit (FPU). * @brief Setup the Floating Point Unit (FPU).
*/ */
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
@ -430,7 +427,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) ) #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
/** /**
* @brief Configures PACBTI features. * @brief Configures PACBTI features.
* *
* This function configures the Pointer Authentication, and Branch Target * This function configures the Pointer Authentication, and Branch Target
@ -491,7 +488,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Sets up the system call stack so that upon returning from * @brief Sets up the system call stack so that upon returning from
* SVC, the system call stack is used. * SVC, the system call stack is used.
* *
@ -507,7 +504,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
@ -516,7 +513,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( 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 * @brief Sets up the task stack so that upon returning from
* SVC, the task stack is used again. * SVC, the task stack is used again.
* *
@ -530,7 +527,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Checks whether or not the calling task is privileged. * @brief Checks whether or not the calling task is privileged.
* *
* @return pdTRUE if the calling task is privileged, pdFALSE otherwise. * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
@ -542,7 +539,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
@ -557,7 +554,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/** /**
* @brief Saved as part of the task context to indicate which context the * @brief Saved as part of the task context to indicate which context the
* task is using on the secure side. * task is using on the secure side.
*/ */
@ -579,18 +576,18 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configUSE_TICKLESS_IDLE == 1 ) #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; PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
/** /**
* @brief The maximum number of tick periods that can be suppressed is * @brief The maximum number of tick periods that can be suppressed is
* limited by the 24 bit resolution of the SysTick timer. * limited by the 24 bit resolution of the SysTick timer.
*/ */
PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
/** /**
* @brief Compensate for the CPU cycles that pass while the SysTick is * @brief Compensate for the CPU cycles that pass while the SysTick is
* stopped (low power functionality only). * stopped (low power functionality only).
*/ */
@ -925,12 +922,6 @@ static void prvTaskExitError( void )
/* The only permitted number of regions are 8 or 16. */ /* The only permitted number of regions are 8 or 16. */
configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 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 );
/* Check that the MPU is present. */
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
{
/* MAIR0 - Index 0. */ /* MAIR0 - Index 0. */
portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
/* MAIR0 - Index 1. */ /* MAIR0 - Index 1. */
@ -983,7 +974,6 @@ static void prvTaskExitError( void )
* regions have privileged access. */ * regions have privileged access. */
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
} }
}
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -1210,7 +1200,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ]; extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulSystemCallStack; uint32_t * pulSystemCallStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1246,12 +1236,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1261,20 +1255,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the system call stack for the stack frame. */ /* Make space on the system call stack for the stack frame. */
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize; pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulSystemCallStack[ i ] = pulTaskStack[ i ]; pulSystemCallStack[ i ] = pulTaskStack[ i ];
} }
@ -1310,7 +1304,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Remember the location where we should copy the stack frame when we exit from /* Remember the location where we should copy the stack frame when we exit from
* the system call. */ * the system call. */
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize; pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
/* Record if the hardware used padding to force the stack pointer /* Record if the hardware used padding to force the stack pointer
* to be double word aligned. */ * to be double word aligned. */
@ -1360,7 +1354,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern TaskHandle_t pxCurrentTCB; extern TaskHandle_t pxCurrentTCB;
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulTaskStack; uint32_t * pulTaskStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1392,12 +1386,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1407,20 +1405,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the task stack for the stack frame. */ /* Make space on the task stack for the stack frame. */
pulTaskStack = pulTaskStack - ulStackFrameSize; pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulTaskStack[ i ] = pulSystemCallStack[ i ]; pulTaskStack[ i ] = pulSystemCallStack[ i ];
} }

View file

@ -1,7 +1,7 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates * Copyright 2024-2025 Arm Limited and/or its affiliates
* <open-source-office@arm.com> * <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
@ -230,7 +230,7 @@ typedef void ( * portISR_t )( void );
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
#endif /* portARMV8M_MINOR_VERSION >= 1 */ #endif /* portARMV8M_MINOR_VERSION >= 1 */
@ -241,9 +241,6 @@ typedef void ( * portISR_t )( void );
/* Enable MPU. */ /* Enable MPU. */
#define portMPU_ENABLE_BIT ( 1UL << 0UL ) #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 /* Extract first address of the MPU region as encoded in the
* RBAR (Region Base Address Register) value. */ * RBAR (Region Base Address Register) value. */
#define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \ #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@ -291,7 +288,7 @@ typedef void ( * portISR_t )( void );
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 ) #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF FD * FF FF FF FD
@ -308,7 +305,7 @@ typedef void ( * portISR_t )( void );
#define portINITIAL_EXC_RETURN ( 0xfffffffd ) #define portINITIAL_EXC_RETURN ( 0xfffffffd )
#else #else
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF BC * FF FF FF BC
@ -401,7 +398,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Extract MPU region's access permissions from the Region Base Address * @brief Extract MPU region's access permissions from the Region Base Address
* Register (RBAR) value. * Register (RBAR) value.
* *
@ -414,7 +411,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Setup the Memory Protection Unit (MPU). * @brief Setup the Memory Protection Unit (MPU).
*/ */
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
@ -422,7 +419,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
/** /**
* @brief Setup the Floating Point Unit (FPU). * @brief Setup the Floating Point Unit (FPU).
*/ */
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
@ -430,7 +427,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) ) #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
/** /**
* @brief Configures PACBTI features. * @brief Configures PACBTI features.
* *
* This function configures the Pointer Authentication, and Branch Target * This function configures the Pointer Authentication, and Branch Target
@ -491,7 +488,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Sets up the system call stack so that upon returning from * @brief Sets up the system call stack so that upon returning from
* SVC, the system call stack is used. * SVC, the system call stack is used.
* *
@ -507,7 +504,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
@ -516,7 +513,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( 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 * @brief Sets up the task stack so that upon returning from
* SVC, the task stack is used again. * SVC, the task stack is used again.
* *
@ -530,7 +527,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Checks whether or not the calling task is privileged. * @brief Checks whether or not the calling task is privileged.
* *
* @return pdTRUE if the calling task is privileged, pdFALSE otherwise. * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
@ -542,7 +539,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
@ -557,7 +554,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/** /**
* @brief Saved as part of the task context to indicate which context the * @brief Saved as part of the task context to indicate which context the
* task is using on the secure side. * task is using on the secure side.
*/ */
@ -579,18 +576,18 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configUSE_TICKLESS_IDLE == 1 ) #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; PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
/** /**
* @brief The maximum number of tick periods that can be suppressed is * @brief The maximum number of tick periods that can be suppressed is
* limited by the 24 bit resolution of the SysTick timer. * limited by the 24 bit resolution of the SysTick timer.
*/ */
PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
/** /**
* @brief Compensate for the CPU cycles that pass while the SysTick is * @brief Compensate for the CPU cycles that pass while the SysTick is
* stopped (low power functionality only). * stopped (low power functionality only).
*/ */
@ -925,12 +922,6 @@ static void prvTaskExitError( void )
/* The only permitted number of regions are 8 or 16. */ /* The only permitted number of regions are 8 or 16. */
configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 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 );
/* Check that the MPU is present. */
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
{
/* MAIR0 - Index 0. */ /* MAIR0 - Index 0. */
portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
/* MAIR0 - Index 1. */ /* MAIR0 - Index 1. */
@ -983,7 +974,6 @@ static void prvTaskExitError( void )
* regions have privileged access. */ * regions have privileged access. */
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
} }
}
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -1210,7 +1200,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ]; extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulSystemCallStack; uint32_t * pulSystemCallStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1246,12 +1236,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1261,20 +1255,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the system call stack for the stack frame. */ /* Make space on the system call stack for the stack frame. */
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize; pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulSystemCallStack[ i ] = pulTaskStack[ i ]; pulSystemCallStack[ i ] = pulTaskStack[ i ];
} }
@ -1310,7 +1304,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Remember the location where we should copy the stack frame when we exit from /* Remember the location where we should copy the stack frame when we exit from
* the system call. */ * the system call. */
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize; pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
/* Record if the hardware used padding to force the stack pointer /* Record if the hardware used padding to force the stack pointer
* to be double word aligned. */ * to be double word aligned. */
@ -1360,7 +1354,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern TaskHandle_t pxCurrentTCB; extern TaskHandle_t pxCurrentTCB;
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulTaskStack; uint32_t * pulTaskStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1392,12 +1386,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1407,20 +1405,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the task stack for the stack frame. */ /* Make space on the task stack for the stack frame. */
pulTaskStack = pulTaskStack - ulStackFrameSize; pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulTaskStack[ i ] = pulSystemCallStack[ i ]; pulTaskStack[ i ] = pulSystemCallStack[ i ];
} }

View file

@ -1,7 +1,7 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates * Copyright 2024-2025 Arm Limited and/or its affiliates
* <open-source-office@arm.com> * <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
@ -230,7 +230,7 @@ typedef void ( * portISR_t )( void );
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
#endif /* portARMV8M_MINOR_VERSION >= 1 */ #endif /* portARMV8M_MINOR_VERSION >= 1 */
@ -241,9 +241,6 @@ typedef void ( * portISR_t )( void );
/* Enable MPU. */ /* Enable MPU. */
#define portMPU_ENABLE_BIT ( 1UL << 0UL ) #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 /* Extract first address of the MPU region as encoded in the
* RBAR (Region Base Address Register) value. */ * RBAR (Region Base Address Register) value. */
#define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \ #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@ -291,7 +288,7 @@ typedef void ( * portISR_t )( void );
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 ) #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF FD * FF FF FF FD
@ -308,7 +305,7 @@ typedef void ( * portISR_t )( void );
#define portINITIAL_EXC_RETURN ( 0xfffffffd ) #define portINITIAL_EXC_RETURN ( 0xfffffffd )
#else #else
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF BC * FF FF FF BC
@ -401,7 +398,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Extract MPU region's access permissions from the Region Base Address * @brief Extract MPU region's access permissions from the Region Base Address
* Register (RBAR) value. * Register (RBAR) value.
* *
@ -414,7 +411,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Setup the Memory Protection Unit (MPU). * @brief Setup the Memory Protection Unit (MPU).
*/ */
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
@ -422,7 +419,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
/** /**
* @brief Setup the Floating Point Unit (FPU). * @brief Setup the Floating Point Unit (FPU).
*/ */
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
@ -430,7 +427,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) ) #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
/** /**
* @brief Configures PACBTI features. * @brief Configures PACBTI features.
* *
* This function configures the Pointer Authentication, and Branch Target * This function configures the Pointer Authentication, and Branch Target
@ -491,7 +488,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Sets up the system call stack so that upon returning from * @brief Sets up the system call stack so that upon returning from
* SVC, the system call stack is used. * SVC, the system call stack is used.
* *
@ -507,7 +504,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
@ -516,7 +513,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( 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 * @brief Sets up the task stack so that upon returning from
* SVC, the task stack is used again. * SVC, the task stack is used again.
* *
@ -530,7 +527,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Checks whether or not the calling task is privileged. * @brief Checks whether or not the calling task is privileged.
* *
* @return pdTRUE if the calling task is privileged, pdFALSE otherwise. * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
@ -542,7 +539,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
@ -557,7 +554,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/** /**
* @brief Saved as part of the task context to indicate which context the * @brief Saved as part of the task context to indicate which context the
* task is using on the secure side. * task is using on the secure side.
*/ */
@ -579,18 +576,18 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configUSE_TICKLESS_IDLE == 1 ) #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; PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
/** /**
* @brief The maximum number of tick periods that can be suppressed is * @brief The maximum number of tick periods that can be suppressed is
* limited by the 24 bit resolution of the SysTick timer. * limited by the 24 bit resolution of the SysTick timer.
*/ */
PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
/** /**
* @brief Compensate for the CPU cycles that pass while the SysTick is * @brief Compensate for the CPU cycles that pass while the SysTick is
* stopped (low power functionality only). * stopped (low power functionality only).
*/ */
@ -925,12 +922,6 @@ static void prvTaskExitError( void )
/* The only permitted number of regions are 8 or 16. */ /* The only permitted number of regions are 8 or 16. */
configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 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 );
/* Check that the MPU is present. */
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
{
/* MAIR0 - Index 0. */ /* MAIR0 - Index 0. */
portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
/* MAIR0 - Index 1. */ /* MAIR0 - Index 1. */
@ -983,7 +974,6 @@ static void prvTaskExitError( void )
* regions have privileged access. */ * regions have privileged access. */
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
} }
}
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -1210,7 +1200,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ]; extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulSystemCallStack; uint32_t * pulSystemCallStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1246,12 +1236,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1261,20 +1255,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the system call stack for the stack frame. */ /* Make space on the system call stack for the stack frame. */
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize; pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulSystemCallStack[ i ] = pulTaskStack[ i ]; pulSystemCallStack[ i ] = pulTaskStack[ i ];
} }
@ -1310,7 +1304,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Remember the location where we should copy the stack frame when we exit from /* Remember the location where we should copy the stack frame when we exit from
* the system call. */ * the system call. */
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize; pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
/* Record if the hardware used padding to force the stack pointer /* Record if the hardware used padding to force the stack pointer
* to be double word aligned. */ * to be double word aligned. */
@ -1360,7 +1354,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern TaskHandle_t pxCurrentTCB; extern TaskHandle_t pxCurrentTCB;
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulTaskStack; uint32_t * pulTaskStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1392,12 +1386,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1407,20 +1405,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the task stack for the stack frame. */ /* Make space on the task stack for the stack frame. */
pulTaskStack = pulTaskStack - ulStackFrameSize; pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulTaskStack[ i ] = pulSystemCallStack[ i ]; pulTaskStack[ i ] = pulSystemCallStack[ i ];
} }

View file

@ -1,7 +1,7 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates * Copyright 2024-2025 Arm Limited and/or its affiliates
* <open-source-office@arm.com> * <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
@ -230,7 +230,7 @@ typedef void ( * portISR_t )( void );
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
#endif /* portARMV8M_MINOR_VERSION >= 1 */ #endif /* portARMV8M_MINOR_VERSION >= 1 */
@ -241,9 +241,6 @@ typedef void ( * portISR_t )( void );
/* Enable MPU. */ /* Enable MPU. */
#define portMPU_ENABLE_BIT ( 1UL << 0UL ) #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 /* Extract first address of the MPU region as encoded in the
* RBAR (Region Base Address Register) value. */ * RBAR (Region Base Address Register) value. */
#define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \ #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@ -291,7 +288,7 @@ typedef void ( * portISR_t )( void );
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 ) #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF FD * FF FF FF FD
@ -308,7 +305,7 @@ typedef void ( * portISR_t )( void );
#define portINITIAL_EXC_RETURN ( 0xfffffffd ) #define portINITIAL_EXC_RETURN ( 0xfffffffd )
#else #else
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF BC * FF FF FF BC
@ -401,7 +398,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Extract MPU region's access permissions from the Region Base Address * @brief Extract MPU region's access permissions from the Region Base Address
* Register (RBAR) value. * Register (RBAR) value.
* *
@ -414,7 +411,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Setup the Memory Protection Unit (MPU). * @brief Setup the Memory Protection Unit (MPU).
*/ */
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
@ -422,7 +419,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
/** /**
* @brief Setup the Floating Point Unit (FPU). * @brief Setup the Floating Point Unit (FPU).
*/ */
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
@ -430,7 +427,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) ) #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
/** /**
* @brief Configures PACBTI features. * @brief Configures PACBTI features.
* *
* This function configures the Pointer Authentication, and Branch Target * This function configures the Pointer Authentication, and Branch Target
@ -491,7 +488,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Sets up the system call stack so that upon returning from * @brief Sets up the system call stack so that upon returning from
* SVC, the system call stack is used. * SVC, the system call stack is used.
* *
@ -507,7 +504,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
@ -516,7 +513,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( 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 * @brief Sets up the task stack so that upon returning from
* SVC, the task stack is used again. * SVC, the task stack is used again.
* *
@ -530,7 +527,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Checks whether or not the calling task is privileged. * @brief Checks whether or not the calling task is privileged.
* *
* @return pdTRUE if the calling task is privileged, pdFALSE otherwise. * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
@ -542,7 +539,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
@ -557,7 +554,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/** /**
* @brief Saved as part of the task context to indicate which context the * @brief Saved as part of the task context to indicate which context the
* task is using on the secure side. * task is using on the secure side.
*/ */
@ -579,18 +576,18 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configUSE_TICKLESS_IDLE == 1 ) #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; PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
/** /**
* @brief The maximum number of tick periods that can be suppressed is * @brief The maximum number of tick periods that can be suppressed is
* limited by the 24 bit resolution of the SysTick timer. * limited by the 24 bit resolution of the SysTick timer.
*/ */
PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
/** /**
* @brief Compensate for the CPU cycles that pass while the SysTick is * @brief Compensate for the CPU cycles that pass while the SysTick is
* stopped (low power functionality only). * stopped (low power functionality only).
*/ */
@ -925,12 +922,6 @@ static void prvTaskExitError( void )
/* The only permitted number of regions are 8 or 16. */ /* The only permitted number of regions are 8 or 16. */
configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 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 );
/* Check that the MPU is present. */
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
{
/* MAIR0 - Index 0. */ /* MAIR0 - Index 0. */
portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
/* MAIR0 - Index 1. */ /* MAIR0 - Index 1. */
@ -983,7 +974,6 @@ static void prvTaskExitError( void )
* regions have privileged access. */ * regions have privileged access. */
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
} }
}
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -1210,7 +1200,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ]; extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulSystemCallStack; uint32_t * pulSystemCallStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1246,12 +1236,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1261,20 +1255,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the system call stack for the stack frame. */ /* Make space on the system call stack for the stack frame. */
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize; pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulSystemCallStack[ i ] = pulTaskStack[ i ]; pulSystemCallStack[ i ] = pulTaskStack[ i ];
} }
@ -1310,7 +1304,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Remember the location where we should copy the stack frame when we exit from /* Remember the location where we should copy the stack frame when we exit from
* the system call. */ * the system call. */
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize; pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
/* Record if the hardware used padding to force the stack pointer /* Record if the hardware used padding to force the stack pointer
* to be double word aligned. */ * to be double word aligned. */
@ -1360,7 +1354,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern TaskHandle_t pxCurrentTCB; extern TaskHandle_t pxCurrentTCB;
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulTaskStack; uint32_t * pulTaskStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1392,12 +1386,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1407,20 +1405,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the task stack for the stack frame. */ /* Make space on the task stack for the stack frame. */
pulTaskStack = pulTaskStack - ulStackFrameSize; pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulTaskStack[ i ] = pulSystemCallStack[ i ]; pulTaskStack[ i ] = pulSystemCallStack[ i ];
} }

View file

@ -1,7 +1,7 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates * Copyright 2024-2025 Arm Limited and/or its affiliates
* <open-source-office@arm.com> * <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
@ -230,7 +230,7 @@ typedef void ( * portISR_t )( void );
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
#endif /* portARMV8M_MINOR_VERSION >= 1 */ #endif /* portARMV8M_MINOR_VERSION >= 1 */
@ -241,9 +241,6 @@ typedef void ( * portISR_t )( void );
/* Enable MPU. */ /* Enable MPU. */
#define portMPU_ENABLE_BIT ( 1UL << 0UL ) #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 /* Extract first address of the MPU region as encoded in the
* RBAR (Region Base Address Register) value. */ * RBAR (Region Base Address Register) value. */
#define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \ #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@ -291,7 +288,7 @@ typedef void ( * portISR_t )( void );
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 ) #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF FD * FF FF FF FD
@ -308,7 +305,7 @@ typedef void ( * portISR_t )( void );
#define portINITIAL_EXC_RETURN ( 0xfffffffd ) #define portINITIAL_EXC_RETURN ( 0xfffffffd )
#else #else
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF BC * FF FF FF BC
@ -401,7 +398,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Extract MPU region's access permissions from the Region Base Address * @brief Extract MPU region's access permissions from the Region Base Address
* Register (RBAR) value. * Register (RBAR) value.
* *
@ -414,7 +411,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Setup the Memory Protection Unit (MPU). * @brief Setup the Memory Protection Unit (MPU).
*/ */
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
@ -422,7 +419,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
/** /**
* @brief Setup the Floating Point Unit (FPU). * @brief Setup the Floating Point Unit (FPU).
*/ */
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
@ -430,7 +427,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) ) #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
/** /**
* @brief Configures PACBTI features. * @brief Configures PACBTI features.
* *
* This function configures the Pointer Authentication, and Branch Target * This function configures the Pointer Authentication, and Branch Target
@ -491,7 +488,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Sets up the system call stack so that upon returning from * @brief Sets up the system call stack so that upon returning from
* SVC, the system call stack is used. * SVC, the system call stack is used.
* *
@ -507,7 +504,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
@ -516,7 +513,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( 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 * @brief Sets up the task stack so that upon returning from
* SVC, the task stack is used again. * SVC, the task stack is used again.
* *
@ -530,7 +527,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Checks whether or not the calling task is privileged. * @brief Checks whether or not the calling task is privileged.
* *
* @return pdTRUE if the calling task is privileged, pdFALSE otherwise. * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
@ -542,7 +539,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
@ -557,7 +554,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/** /**
* @brief Saved as part of the task context to indicate which context the * @brief Saved as part of the task context to indicate which context the
* task is using on the secure side. * task is using on the secure side.
*/ */
@ -579,18 +576,18 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configUSE_TICKLESS_IDLE == 1 ) #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; PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
/** /**
* @brief The maximum number of tick periods that can be suppressed is * @brief The maximum number of tick periods that can be suppressed is
* limited by the 24 bit resolution of the SysTick timer. * limited by the 24 bit resolution of the SysTick timer.
*/ */
PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
/** /**
* @brief Compensate for the CPU cycles that pass while the SysTick is * @brief Compensate for the CPU cycles that pass while the SysTick is
* stopped (low power functionality only). * stopped (low power functionality only).
*/ */
@ -925,12 +922,6 @@ static void prvTaskExitError( void )
/* The only permitted number of regions are 8 or 16. */ /* The only permitted number of regions are 8 or 16. */
configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 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 );
/* Check that the MPU is present. */
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
{
/* MAIR0 - Index 0. */ /* MAIR0 - Index 0. */
portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
/* MAIR0 - Index 1. */ /* MAIR0 - Index 1. */
@ -983,7 +974,6 @@ static void prvTaskExitError( void )
* regions have privileged access. */ * regions have privileged access. */
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
} }
}
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -1210,7 +1200,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ]; extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulSystemCallStack; uint32_t * pulSystemCallStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1246,12 +1236,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1261,20 +1255,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the system call stack for the stack frame. */ /* Make space on the system call stack for the stack frame. */
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize; pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulSystemCallStack[ i ] = pulTaskStack[ i ]; pulSystemCallStack[ i ] = pulTaskStack[ i ];
} }
@ -1310,7 +1304,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Remember the location where we should copy the stack frame when we exit from /* Remember the location where we should copy the stack frame when we exit from
* the system call. */ * the system call. */
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize; pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
/* Record if the hardware used padding to force the stack pointer /* Record if the hardware used padding to force the stack pointer
* to be double word aligned. */ * to be double word aligned. */
@ -1360,7 +1354,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern TaskHandle_t pxCurrentTCB; extern TaskHandle_t pxCurrentTCB;
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulTaskStack; uint32_t * pulTaskStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1392,12 +1386,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1407,20 +1405,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the task stack for the stack frame. */ /* Make space on the task stack for the stack frame. */
pulTaskStack = pulTaskStack - ulStackFrameSize; pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulTaskStack[ i ] = pulSystemCallStack[ i ]; pulTaskStack[ i ] = pulSystemCallStack[ i ];
} }

View file

@ -1,7 +1,7 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates * Copyright 2024-2025 Arm Limited and/or its affiliates
* <open-source-office@arm.com> * <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
@ -230,7 +230,7 @@ typedef void ( * portISR_t )( void );
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
#endif /* portARMV8M_MINOR_VERSION >= 1 */ #endif /* portARMV8M_MINOR_VERSION >= 1 */
@ -241,9 +241,6 @@ typedef void ( * portISR_t )( void );
/* Enable MPU. */ /* Enable MPU. */
#define portMPU_ENABLE_BIT ( 1UL << 0UL ) #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 /* Extract first address of the MPU region as encoded in the
* RBAR (Region Base Address Register) value. */ * RBAR (Region Base Address Register) value. */
#define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \ #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@ -291,7 +288,7 @@ typedef void ( * portISR_t )( void );
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 ) #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF FD * FF FF FF FD
@ -308,7 +305,7 @@ typedef void ( * portISR_t )( void );
#define portINITIAL_EXC_RETURN ( 0xfffffffd ) #define portINITIAL_EXC_RETURN ( 0xfffffffd )
#else #else
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF BC * FF FF FF BC
@ -401,7 +398,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Extract MPU region's access permissions from the Region Base Address * @brief Extract MPU region's access permissions from the Region Base Address
* Register (RBAR) value. * Register (RBAR) value.
* *
@ -414,7 +411,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Setup the Memory Protection Unit (MPU). * @brief Setup the Memory Protection Unit (MPU).
*/ */
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
@ -422,7 +419,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
/** /**
* @brief Setup the Floating Point Unit (FPU). * @brief Setup the Floating Point Unit (FPU).
*/ */
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
@ -430,7 +427,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) ) #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
/** /**
* @brief Configures PACBTI features. * @brief Configures PACBTI features.
* *
* This function configures the Pointer Authentication, and Branch Target * This function configures the Pointer Authentication, and Branch Target
@ -491,7 +488,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Sets up the system call stack so that upon returning from * @brief Sets up the system call stack so that upon returning from
* SVC, the system call stack is used. * SVC, the system call stack is used.
* *
@ -507,7 +504,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
@ -516,7 +513,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( 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 * @brief Sets up the task stack so that upon returning from
* SVC, the task stack is used again. * SVC, the task stack is used again.
* *
@ -530,7 +527,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Checks whether or not the calling task is privileged. * @brief Checks whether or not the calling task is privileged.
* *
* @return pdTRUE if the calling task is privileged, pdFALSE otherwise. * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
@ -542,7 +539,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
@ -557,7 +554,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/** /**
* @brief Saved as part of the task context to indicate which context the * @brief Saved as part of the task context to indicate which context the
* task is using on the secure side. * task is using on the secure side.
*/ */
@ -579,18 +576,18 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configUSE_TICKLESS_IDLE == 1 ) #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; PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
/** /**
* @brief The maximum number of tick periods that can be suppressed is * @brief The maximum number of tick periods that can be suppressed is
* limited by the 24 bit resolution of the SysTick timer. * limited by the 24 bit resolution of the SysTick timer.
*/ */
PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
/** /**
* @brief Compensate for the CPU cycles that pass while the SysTick is * @brief Compensate for the CPU cycles that pass while the SysTick is
* stopped (low power functionality only). * stopped (low power functionality only).
*/ */
@ -925,12 +922,6 @@ static void prvTaskExitError( void )
/* The only permitted number of regions are 8 or 16. */ /* The only permitted number of regions are 8 or 16. */
configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 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 );
/* Check that the MPU is present. */
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
{
/* MAIR0 - Index 0. */ /* MAIR0 - Index 0. */
portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
/* MAIR0 - Index 1. */ /* MAIR0 - Index 1. */
@ -983,7 +974,6 @@ static void prvTaskExitError( void )
* regions have privileged access. */ * regions have privileged access. */
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
} }
}
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -1210,7 +1200,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ]; extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulSystemCallStack; uint32_t * pulSystemCallStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1246,12 +1236,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1261,20 +1255,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the system call stack for the stack frame. */ /* Make space on the system call stack for the stack frame. */
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize; pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulSystemCallStack[ i ] = pulTaskStack[ i ]; pulSystemCallStack[ i ] = pulTaskStack[ i ];
} }
@ -1310,7 +1304,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Remember the location where we should copy the stack frame when we exit from /* Remember the location where we should copy the stack frame when we exit from
* the system call. */ * the system call. */
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize; pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
/* Record if the hardware used padding to force the stack pointer /* Record if the hardware used padding to force the stack pointer
* to be double word aligned. */ * to be double word aligned. */
@ -1360,7 +1354,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern TaskHandle_t pxCurrentTCB; extern TaskHandle_t pxCurrentTCB;
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulTaskStack; uint32_t * pulTaskStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1392,12 +1386,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1407,20 +1405,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the task stack for the stack frame. */ /* Make space on the task stack for the stack frame. */
pulTaskStack = pulTaskStack - ulStackFrameSize; pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulTaskStack[ i ] = pulSystemCallStack[ i ]; pulTaskStack[ i ] = pulSystemCallStack[ i ];
} }

View file

@ -1,6 +1,8 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * 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 * SPDX-License-Identifier: MIT
* *
@ -484,7 +486,10 @@ void vSVCHandler_C( uint32_t * pulParam ) /* PRIVILEGED_FUNCTION */
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulSystemCallStack; uint32_t * pulSystemCallStack;
uint32_t ulSystemCallLocation, i; 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 ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
@ -520,10 +525,10 @@ void vSVCHandler_C( uint32_t * pulParam ) /* PRIVILEGED_FUNCTION */
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack; pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
/* Make space on the system call stack for the stack frame. */ /* Make space on the system call stack for the stack frame. */
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize; pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulSystemCallStack[ i ] = pulTaskStack[ i ]; pulSystemCallStack[ i ] = pulTaskStack[ i ];
} }
@ -541,7 +546,7 @@ void vSVCHandler_C( uint32_t * pulParam ) /* PRIVILEGED_FUNCTION */
/* Remember the location where we should copy the stack frame when we exit from /* Remember the location where we should copy the stack frame when we exit from
* the system call. */ * 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. /* Store the value of the Link Register before the SVC was raised.
* It contains the address of the caller of the System Call entry * It contains the address of the caller of the System Call entry
@ -594,7 +599,10 @@ void vSVCHandler_C( uint32_t * pulParam ) /* PRIVILEGED_FUNCTION */
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulTaskStack; uint32_t * pulTaskStack;
uint32_t ulSystemCallLocation, i; 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 ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
@ -626,10 +634,10 @@ void vSVCHandler_C( uint32_t * pulParam ) /* PRIVILEGED_FUNCTION */
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack; pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
/* Make space on the task stack for the stack frame. */ /* Make space on the task stack for the stack frame. */
pulTaskStack = pulTaskStack - ulStackFrameSize; pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulTaskStack[ i ] = pulSystemCallStack[ i ]; pulTaskStack[ i ] = pulSystemCallStack[ i ];
} }

View file

@ -1,6 +1,8 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * 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 * SPDX-License-Identifier: MIT
* *
@ -518,7 +520,7 @@ void vSVCHandler_C( uint32_t * pulParam ) /* PRIVILEGED_FUNCTION */
extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ]; extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulSystemCallStack; uint32_t * pulSystemCallStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
@ -553,10 +555,14 @@ void vSVCHandler_C( uint32_t * pulParam ) /* PRIVILEGED_FUNCTION */
{ {
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -566,14 +572,14 @@ void vSVCHandler_C( uint32_t * pulParam ) /* PRIVILEGED_FUNCTION */
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
/* Make space on the system call stack for the stack frame. */ /* Make space on the system call stack for the stack frame. */
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize; pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulSystemCallStack[ i ] = pulTaskStack[ i ]; pulSystemCallStack[ i ] = pulTaskStack[ i ];
} }
@ -591,7 +597,7 @@ void vSVCHandler_C( uint32_t * pulParam ) /* PRIVILEGED_FUNCTION */
/* Remember the location where we should copy the stack frame when we exit from /* Remember the location where we should copy the stack frame when we exit from
* the system call. */ * 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. /* Store the value of the Link Register before the SVC was raised.
* It contains the address of the caller of the System Call entry * It contains the address of the caller of the System Call entry
@ -644,7 +650,7 @@ void vSVCHandler_C( uint32_t * pulParam ) /* PRIVILEGED_FUNCTION */
extern TaskHandle_t pxCurrentTCB; extern TaskHandle_t pxCurrentTCB;
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulTaskStack; uint32_t * pulTaskStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
@ -675,10 +681,14 @@ void vSVCHandler_C( uint32_t * pulParam ) /* PRIVILEGED_FUNCTION */
{ {
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -688,14 +698,14 @@ void vSVCHandler_C( uint32_t * pulParam ) /* PRIVILEGED_FUNCTION */
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
/* Make space on the task stack for the stack frame. */ /* Make space on the task stack for the stack frame. */
pulTaskStack = pulTaskStack - ulStackFrameSize; pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulTaskStack[ i ] = pulSystemCallStack[ i ]; pulTaskStack[ i ] = pulSystemCallStack[ i ];
} }

View file

@ -1,7 +1,7 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates * Copyright 2024-2025 Arm Limited and/or its affiliates
* <open-source-office@arm.com> * <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
@ -230,7 +230,7 @@ typedef void ( * portISR_t )( void );
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
#endif /* portARMV8M_MINOR_VERSION >= 1 */ #endif /* portARMV8M_MINOR_VERSION >= 1 */
@ -241,9 +241,6 @@ typedef void ( * portISR_t )( void );
/* Enable MPU. */ /* Enable MPU. */
#define portMPU_ENABLE_BIT ( 1UL << 0UL ) #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 /* Extract first address of the MPU region as encoded in the
* RBAR (Region Base Address Register) value. */ * RBAR (Region Base Address Register) value. */
#define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \ #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@ -291,7 +288,7 @@ typedef void ( * portISR_t )( void );
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 ) #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF FD * FF FF FF FD
@ -308,7 +305,7 @@ typedef void ( * portISR_t )( void );
#define portINITIAL_EXC_RETURN ( 0xfffffffd ) #define portINITIAL_EXC_RETURN ( 0xfffffffd )
#else #else
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF BC * FF FF FF BC
@ -401,7 +398,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Extract MPU region's access permissions from the Region Base Address * @brief Extract MPU region's access permissions from the Region Base Address
* Register (RBAR) value. * Register (RBAR) value.
* *
@ -414,7 +411,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Setup the Memory Protection Unit (MPU). * @brief Setup the Memory Protection Unit (MPU).
*/ */
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
@ -422,7 +419,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
/** /**
* @brief Setup the Floating Point Unit (FPU). * @brief Setup the Floating Point Unit (FPU).
*/ */
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
@ -430,7 +427,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) ) #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
/** /**
* @brief Configures PACBTI features. * @brief Configures PACBTI features.
* *
* This function configures the Pointer Authentication, and Branch Target * This function configures the Pointer Authentication, and Branch Target
@ -491,7 +488,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Sets up the system call stack so that upon returning from * @brief Sets up the system call stack so that upon returning from
* SVC, the system call stack is used. * SVC, the system call stack is used.
* *
@ -507,7 +504,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
@ -516,7 +513,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( 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 * @brief Sets up the task stack so that upon returning from
* SVC, the task stack is used again. * SVC, the task stack is used again.
* *
@ -530,7 +527,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Checks whether or not the calling task is privileged. * @brief Checks whether or not the calling task is privileged.
* *
* @return pdTRUE if the calling task is privileged, pdFALSE otherwise. * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
@ -542,7 +539,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
@ -557,7 +554,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/** /**
* @brief Saved as part of the task context to indicate which context the * @brief Saved as part of the task context to indicate which context the
* task is using on the secure side. * task is using on the secure side.
*/ */
@ -579,18 +576,18 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configUSE_TICKLESS_IDLE == 1 ) #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; PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
/** /**
* @brief The maximum number of tick periods that can be suppressed is * @brief The maximum number of tick periods that can be suppressed is
* limited by the 24 bit resolution of the SysTick timer. * limited by the 24 bit resolution of the SysTick timer.
*/ */
PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
/** /**
* @brief Compensate for the CPU cycles that pass while the SysTick is * @brief Compensate for the CPU cycles that pass while the SysTick is
* stopped (low power functionality only). * stopped (low power functionality only).
*/ */
@ -925,12 +922,6 @@ static void prvTaskExitError( void )
/* The only permitted number of regions are 8 or 16. */ /* The only permitted number of regions are 8 or 16. */
configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 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 );
/* Check that the MPU is present. */
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
{
/* MAIR0 - Index 0. */ /* MAIR0 - Index 0. */
portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
/* MAIR0 - Index 1. */ /* MAIR0 - Index 1. */
@ -983,7 +974,6 @@ static void prvTaskExitError( void )
* regions have privileged access. */ * regions have privileged access. */
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
} }
}
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -1210,7 +1200,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ]; extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulSystemCallStack; uint32_t * pulSystemCallStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1246,12 +1236,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1261,20 +1255,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the system call stack for the stack frame. */ /* Make space on the system call stack for the stack frame. */
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize; pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulSystemCallStack[ i ] = pulTaskStack[ i ]; pulSystemCallStack[ i ] = pulTaskStack[ i ];
} }
@ -1310,7 +1304,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Remember the location where we should copy the stack frame when we exit from /* Remember the location where we should copy the stack frame when we exit from
* the system call. */ * the system call. */
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize; pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
/* Record if the hardware used padding to force the stack pointer /* Record if the hardware used padding to force the stack pointer
* to be double word aligned. */ * to be double word aligned. */
@ -1360,7 +1354,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern TaskHandle_t pxCurrentTCB; extern TaskHandle_t pxCurrentTCB;
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulTaskStack; uint32_t * pulTaskStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1392,12 +1386,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1407,20 +1405,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the task stack for the stack frame. */ /* Make space on the task stack for the stack frame. */
pulTaskStack = pulTaskStack - ulStackFrameSize; pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulTaskStack[ i ] = pulSystemCallStack[ i ]; pulTaskStack[ i ] = pulSystemCallStack[ i ];
} }

View file

@ -1,7 +1,7 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates * Copyright 2024-2025 Arm Limited and/or its affiliates
* <open-source-office@arm.com> * <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
@ -230,7 +230,7 @@ typedef void ( * portISR_t )( void );
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
#endif /* portARMV8M_MINOR_VERSION >= 1 */ #endif /* portARMV8M_MINOR_VERSION >= 1 */
@ -241,9 +241,6 @@ typedef void ( * portISR_t )( void );
/* Enable MPU. */ /* Enable MPU. */
#define portMPU_ENABLE_BIT ( 1UL << 0UL ) #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 /* Extract first address of the MPU region as encoded in the
* RBAR (Region Base Address Register) value. */ * RBAR (Region Base Address Register) value. */
#define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \ #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@ -291,7 +288,7 @@ typedef void ( * portISR_t )( void );
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 ) #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF FD * FF FF FF FD
@ -308,7 +305,7 @@ typedef void ( * portISR_t )( void );
#define portINITIAL_EXC_RETURN ( 0xfffffffd ) #define portINITIAL_EXC_RETURN ( 0xfffffffd )
#else #else
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF BC * FF FF FF BC
@ -401,7 +398,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Extract MPU region's access permissions from the Region Base Address * @brief Extract MPU region's access permissions from the Region Base Address
* Register (RBAR) value. * Register (RBAR) value.
* *
@ -414,7 +411,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Setup the Memory Protection Unit (MPU). * @brief Setup the Memory Protection Unit (MPU).
*/ */
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
@ -422,7 +419,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
/** /**
* @brief Setup the Floating Point Unit (FPU). * @brief Setup the Floating Point Unit (FPU).
*/ */
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
@ -430,7 +427,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) ) #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
/** /**
* @brief Configures PACBTI features. * @brief Configures PACBTI features.
* *
* This function configures the Pointer Authentication, and Branch Target * This function configures the Pointer Authentication, and Branch Target
@ -491,7 +488,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Sets up the system call stack so that upon returning from * @brief Sets up the system call stack so that upon returning from
* SVC, the system call stack is used. * SVC, the system call stack is used.
* *
@ -507,7 +504,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
@ -516,7 +513,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( 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 * @brief Sets up the task stack so that upon returning from
* SVC, the task stack is used again. * SVC, the task stack is used again.
* *
@ -530,7 +527,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Checks whether or not the calling task is privileged. * @brief Checks whether or not the calling task is privileged.
* *
* @return pdTRUE if the calling task is privileged, pdFALSE otherwise. * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
@ -542,7 +539,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
@ -557,7 +554,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/** /**
* @brief Saved as part of the task context to indicate which context the * @brief Saved as part of the task context to indicate which context the
* task is using on the secure side. * task is using on the secure side.
*/ */
@ -579,18 +576,18 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configUSE_TICKLESS_IDLE == 1 ) #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; PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
/** /**
* @brief The maximum number of tick periods that can be suppressed is * @brief The maximum number of tick periods that can be suppressed is
* limited by the 24 bit resolution of the SysTick timer. * limited by the 24 bit resolution of the SysTick timer.
*/ */
PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
/** /**
* @brief Compensate for the CPU cycles that pass while the SysTick is * @brief Compensate for the CPU cycles that pass while the SysTick is
* stopped (low power functionality only). * stopped (low power functionality only).
*/ */
@ -925,12 +922,6 @@ static void prvTaskExitError( void )
/* The only permitted number of regions are 8 or 16. */ /* The only permitted number of regions are 8 or 16. */
configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 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 );
/* Check that the MPU is present. */
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
{
/* MAIR0 - Index 0. */ /* MAIR0 - Index 0. */
portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
/* MAIR0 - Index 1. */ /* MAIR0 - Index 1. */
@ -983,7 +974,6 @@ static void prvTaskExitError( void )
* regions have privileged access. */ * regions have privileged access. */
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
} }
}
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -1210,7 +1200,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ]; extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulSystemCallStack; uint32_t * pulSystemCallStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1246,12 +1236,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1261,20 +1255,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the system call stack for the stack frame. */ /* Make space on the system call stack for the stack frame. */
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize; pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulSystemCallStack[ i ] = pulTaskStack[ i ]; pulSystemCallStack[ i ] = pulTaskStack[ i ];
} }
@ -1310,7 +1304,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Remember the location where we should copy the stack frame when we exit from /* Remember the location where we should copy the stack frame when we exit from
* the system call. */ * the system call. */
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize; pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
/* Record if the hardware used padding to force the stack pointer /* Record if the hardware used padding to force the stack pointer
* to be double word aligned. */ * to be double word aligned. */
@ -1360,7 +1354,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern TaskHandle_t pxCurrentTCB; extern TaskHandle_t pxCurrentTCB;
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulTaskStack; uint32_t * pulTaskStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1392,12 +1386,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1407,20 +1405,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the task stack for the stack frame. */ /* Make space on the task stack for the stack frame. */
pulTaskStack = pulTaskStack - ulStackFrameSize; pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulTaskStack[ i ] = pulSystemCallStack[ i ]; pulTaskStack[ i ] = pulSystemCallStack[ i ];
} }

View file

@ -1,7 +1,7 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates * Copyright 2024-2025 Arm Limited and/or its affiliates
* <open-source-office@arm.com> * <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
@ -230,7 +230,7 @@ typedef void ( * portISR_t )( void );
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
#endif /* portARMV8M_MINOR_VERSION >= 1 */ #endif /* portARMV8M_MINOR_VERSION >= 1 */
@ -241,9 +241,6 @@ typedef void ( * portISR_t )( void );
/* Enable MPU. */ /* Enable MPU. */
#define portMPU_ENABLE_BIT ( 1UL << 0UL ) #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 /* Extract first address of the MPU region as encoded in the
* RBAR (Region Base Address Register) value. */ * RBAR (Region Base Address Register) value. */
#define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \ #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@ -291,7 +288,7 @@ typedef void ( * portISR_t )( void );
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 ) #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF FD * FF FF FF FD
@ -308,7 +305,7 @@ typedef void ( * portISR_t )( void );
#define portINITIAL_EXC_RETURN ( 0xfffffffd ) #define portINITIAL_EXC_RETURN ( 0xfffffffd )
#else #else
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF BC * FF FF FF BC
@ -401,7 +398,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Extract MPU region's access permissions from the Region Base Address * @brief Extract MPU region's access permissions from the Region Base Address
* Register (RBAR) value. * Register (RBAR) value.
* *
@ -414,7 +411,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Setup the Memory Protection Unit (MPU). * @brief Setup the Memory Protection Unit (MPU).
*/ */
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
@ -422,7 +419,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
/** /**
* @brief Setup the Floating Point Unit (FPU). * @brief Setup the Floating Point Unit (FPU).
*/ */
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
@ -430,7 +427,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) ) #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
/** /**
* @brief Configures PACBTI features. * @brief Configures PACBTI features.
* *
* This function configures the Pointer Authentication, and Branch Target * This function configures the Pointer Authentication, and Branch Target
@ -491,7 +488,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Sets up the system call stack so that upon returning from * @brief Sets up the system call stack so that upon returning from
* SVC, the system call stack is used. * SVC, the system call stack is used.
* *
@ -507,7 +504,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
@ -516,7 +513,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( 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 * @brief Sets up the task stack so that upon returning from
* SVC, the task stack is used again. * SVC, the task stack is used again.
* *
@ -530,7 +527,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Checks whether or not the calling task is privileged. * @brief Checks whether or not the calling task is privileged.
* *
* @return pdTRUE if the calling task is privileged, pdFALSE otherwise. * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
@ -542,7 +539,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
@ -557,7 +554,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/** /**
* @brief Saved as part of the task context to indicate which context the * @brief Saved as part of the task context to indicate which context the
* task is using on the secure side. * task is using on the secure side.
*/ */
@ -579,18 +576,18 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configUSE_TICKLESS_IDLE == 1 ) #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; PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
/** /**
* @brief The maximum number of tick periods that can be suppressed is * @brief The maximum number of tick periods that can be suppressed is
* limited by the 24 bit resolution of the SysTick timer. * limited by the 24 bit resolution of the SysTick timer.
*/ */
PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
/** /**
* @brief Compensate for the CPU cycles that pass while the SysTick is * @brief Compensate for the CPU cycles that pass while the SysTick is
* stopped (low power functionality only). * stopped (low power functionality only).
*/ */
@ -925,12 +922,6 @@ static void prvTaskExitError( void )
/* The only permitted number of regions are 8 or 16. */ /* The only permitted number of regions are 8 or 16. */
configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 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 );
/* Check that the MPU is present. */
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
{
/* MAIR0 - Index 0. */ /* MAIR0 - Index 0. */
portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
/* MAIR0 - Index 1. */ /* MAIR0 - Index 1. */
@ -983,7 +974,6 @@ static void prvTaskExitError( void )
* regions have privileged access. */ * regions have privileged access. */
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
} }
}
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -1210,7 +1200,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ]; extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulSystemCallStack; uint32_t * pulSystemCallStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1246,12 +1236,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1261,20 +1255,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the system call stack for the stack frame. */ /* Make space on the system call stack for the stack frame. */
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize; pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulSystemCallStack[ i ] = pulTaskStack[ i ]; pulSystemCallStack[ i ] = pulTaskStack[ i ];
} }
@ -1310,7 +1304,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Remember the location where we should copy the stack frame when we exit from /* Remember the location where we should copy the stack frame when we exit from
* the system call. */ * the system call. */
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize; pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
/* Record if the hardware used padding to force the stack pointer /* Record if the hardware used padding to force the stack pointer
* to be double word aligned. */ * to be double word aligned. */
@ -1360,7 +1354,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern TaskHandle_t pxCurrentTCB; extern TaskHandle_t pxCurrentTCB;
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulTaskStack; uint32_t * pulTaskStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1392,12 +1386,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1407,20 +1405,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the task stack for the stack frame. */ /* Make space on the task stack for the stack frame. */
pulTaskStack = pulTaskStack - ulStackFrameSize; pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulTaskStack[ i ] = pulSystemCallStack[ i ]; pulTaskStack[ i ] = pulSystemCallStack[ i ];
} }

View file

@ -1,7 +1,7 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates * Copyright 2024-2025 Arm Limited and/or its affiliates
* <open-source-office@arm.com> * <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
@ -230,7 +230,7 @@ typedef void ( * portISR_t )( void );
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
#endif /* portARMV8M_MINOR_VERSION >= 1 */ #endif /* portARMV8M_MINOR_VERSION >= 1 */
@ -241,9 +241,6 @@ typedef void ( * portISR_t )( void );
/* Enable MPU. */ /* Enable MPU. */
#define portMPU_ENABLE_BIT ( 1UL << 0UL ) #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 /* Extract first address of the MPU region as encoded in the
* RBAR (Region Base Address Register) value. */ * RBAR (Region Base Address Register) value. */
#define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \ #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@ -291,7 +288,7 @@ typedef void ( * portISR_t )( void );
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 ) #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF FD * FF FF FF FD
@ -308,7 +305,7 @@ typedef void ( * portISR_t )( void );
#define portINITIAL_EXC_RETURN ( 0xfffffffd ) #define portINITIAL_EXC_RETURN ( 0xfffffffd )
#else #else
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF BC * FF FF FF BC
@ -401,7 +398,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Extract MPU region's access permissions from the Region Base Address * @brief Extract MPU region's access permissions from the Region Base Address
* Register (RBAR) value. * Register (RBAR) value.
* *
@ -414,7 +411,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Setup the Memory Protection Unit (MPU). * @brief Setup the Memory Protection Unit (MPU).
*/ */
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
@ -422,7 +419,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
/** /**
* @brief Setup the Floating Point Unit (FPU). * @brief Setup the Floating Point Unit (FPU).
*/ */
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
@ -430,7 +427,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) ) #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
/** /**
* @brief Configures PACBTI features. * @brief Configures PACBTI features.
* *
* This function configures the Pointer Authentication, and Branch Target * This function configures the Pointer Authentication, and Branch Target
@ -491,7 +488,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Sets up the system call stack so that upon returning from * @brief Sets up the system call stack so that upon returning from
* SVC, the system call stack is used. * SVC, the system call stack is used.
* *
@ -507,7 +504,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
@ -516,7 +513,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( 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 * @brief Sets up the task stack so that upon returning from
* SVC, the task stack is used again. * SVC, the task stack is used again.
* *
@ -530,7 +527,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Checks whether or not the calling task is privileged. * @brief Checks whether or not the calling task is privileged.
* *
* @return pdTRUE if the calling task is privileged, pdFALSE otherwise. * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
@ -542,7 +539,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
@ -557,7 +554,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/** /**
* @brief Saved as part of the task context to indicate which context the * @brief Saved as part of the task context to indicate which context the
* task is using on the secure side. * task is using on the secure side.
*/ */
@ -579,18 +576,18 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configUSE_TICKLESS_IDLE == 1 ) #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; PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
/** /**
* @brief The maximum number of tick periods that can be suppressed is * @brief The maximum number of tick periods that can be suppressed is
* limited by the 24 bit resolution of the SysTick timer. * limited by the 24 bit resolution of the SysTick timer.
*/ */
PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
/** /**
* @brief Compensate for the CPU cycles that pass while the SysTick is * @brief Compensate for the CPU cycles that pass while the SysTick is
* stopped (low power functionality only). * stopped (low power functionality only).
*/ */
@ -925,12 +922,6 @@ static void prvTaskExitError( void )
/* The only permitted number of regions are 8 or 16. */ /* The only permitted number of regions are 8 or 16. */
configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 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 );
/* Check that the MPU is present. */
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
{
/* MAIR0 - Index 0. */ /* MAIR0 - Index 0. */
portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
/* MAIR0 - Index 1. */ /* MAIR0 - Index 1. */
@ -983,7 +974,6 @@ static void prvTaskExitError( void )
* regions have privileged access. */ * regions have privileged access. */
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
} }
}
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -1210,7 +1200,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ]; extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulSystemCallStack; uint32_t * pulSystemCallStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1246,12 +1236,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1261,20 +1255,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the system call stack for the stack frame. */ /* Make space on the system call stack for the stack frame. */
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize; pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulSystemCallStack[ i ] = pulTaskStack[ i ]; pulSystemCallStack[ i ] = pulTaskStack[ i ];
} }
@ -1310,7 +1304,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Remember the location where we should copy the stack frame when we exit from /* Remember the location where we should copy the stack frame when we exit from
* the system call. */ * the system call. */
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize; pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
/* Record if the hardware used padding to force the stack pointer /* Record if the hardware used padding to force the stack pointer
* to be double word aligned. */ * to be double word aligned. */
@ -1360,7 +1354,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern TaskHandle_t pxCurrentTCB; extern TaskHandle_t pxCurrentTCB;
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulTaskStack; uint32_t * pulTaskStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1392,12 +1386,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1407,20 +1405,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the task stack for the stack frame. */ /* Make space on the task stack for the stack frame. */
pulTaskStack = pulTaskStack - ulStackFrameSize; pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulTaskStack[ i ] = pulSystemCallStack[ i ]; pulTaskStack[ i ] = pulSystemCallStack[ i ];
} }

View file

@ -0,0 +1,42 @@
# Arm Cortex-R82 FreeRTOS Kernel Port
# Overview
- This directory contains the FreeRTOS Kernel port for Arm Cortex-R82 based on Armv8-R AArch64 architecture.
- It provides the portable layer required by the kernel to run on this architecture.
# Supported toolchains
The port is supported and tested on the following toolchains:
* Arm Compiler for Embedded v6.23 (armclang).
* Arm GNU toolchain v14.2.
# Cache Coherency
- This port assumes the hardware or model is fully cache coherent.
- The port does not perform cache maintenance for shared buffers.
- If your hardware or model doesn't support full cache coherency, you must handle cache clean/invalidate operations, memory attributes, and any additional barriers in your BSP/application (especially around shared-memory regions).
# SMP Multicore Bring-up
For SMP systems using this port, the application only needs to start the scheduler on the primary core and issue an SVC from each secondary core once they are online. The kernel coordinates the rest and ensures all cores are properly managed.
- Developer-facing summary: call `vTaskStartScheduler()` on the primary core; each secondary core, in its **reset handler**, performs its local init and then issues an SVC (immediate value `106`) to hand off to the kernel. The port will bring all cores under the scheduler.
Primary core flow:
1. Perform core-specific and shared initialization (e.g., set EL1 stack pointer, zero-initialize `.bss`).
2. Jump to `main()`, create user tasks, optionally pin tasks to specific cores.
3. Call `vTaskStartScheduler()` which invokes `xPortStartScheduler()`.
4. `xPortStartScheduler()` configures the primary core tick timer and signals secondary cores that shared init is complete using the `ucPrimaryCoreInitDoneFlag` variable.
5. Wait until all secondary cores report as brought up.
6. Once all cores are up, call `vPortRestoreContext()` to schedule the first task on the primary core.
Secondary core flow (to be done in each cores reset handler):
1. Perform core-specific initialization (e.g., set EL1 stack pointer).
2. Wait for the primary core's signal that shared initialization is complete (i.e., `ucPrimaryCoreInitDoneFlag` set to 1).
3. Update `VBAR_EL1` from the boot vector table to the FreeRTOS vector table.
4. Initialize the GIC redistributor and enable SGIs so interrupts from the primary core are receivable; signal the primary that this secondary is online and ready by setting the its flag in the `ucSecondaryCoresReadyFlags` array.
5. Issue an SVC with immediate value `106` to enter `FreeRTOS_SWI_Handler`, which will call `vPortRestoreContext()` based on the SVC number to start scheduling on this core.

View file

@ -0,0 +1,873 @@
/*
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
* 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
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
/* Standard includes. */
#include <stdlib.h>
#include <string.h>
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
#ifndef configINTERRUPT_CONTROLLER_BASE_ADDRESS
#error configINTERRUPT_CONTROLLER_BASE_ADDRESS must be defined. Refer to Cortex-A equivalent: /* https://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors */
#endif
#ifndef configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET
#error configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET must be defined. Refer to Cortex-A equivalent: /* https://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors */
#endif
#ifndef configUNIQUE_INTERRUPT_PRIORITIES
#error configUNIQUE_INTERRUPT_PRIORITIES must be defined. Refer to Cortex-A equivalent: /* https://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors */
#endif
#ifndef configSETUP_TICK_INTERRUPT
#error configSETUP_TICK_INTERRUPT() must be defined. Refer to Cortex-A equivalent: /* https://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors */
#endif /* configSETUP_TICK_INTERRUPT */
#ifndef configMAX_API_CALL_INTERRUPT_PRIORITY
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be defined. Refer to Cortex-A equivalent: /* https://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors */
#endif
#if configMAX_API_CALL_INTERRUPT_PRIORITY == 0
#error "configMAX_API_CALL_INTERRUPT_PRIORITY must not be set to 0"
#endif
#if configMAX_API_CALL_INTERRUPT_PRIORITY > configUNIQUE_INTERRUPT_PRIORITIES
#error "configMAX_API_CALL_INTERRUPT_PRIORITY must be less than or equal to configUNIQUE_INTERRUPT_PRIORITIES as the lower the numeric priority value the higher the logical interrupt priority"
#endif
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Check the configuration. */
#if ( configMAX_PRIORITIES > 32 )
#error "configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice."
#endif
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/* In case security extensions are implemented. */
#if configMAX_API_CALL_INTERRUPT_PRIORITY <= ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
#error "configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )"
#endif
#ifndef configCLEAR_TICK_INTERRUPT
#error configCLEAR_TICK_INTERRUPT must be defined in FreeRTOSConfig.h to clear which ever interrupt was used to generate the tick interrupt.
#endif
#if configNUMBER_OF_CORES < 1
#error configNUMBER_OF_CORES must be set to 1 or greater. If the application is not using multiple cores then set configNUMBER_OF_CORES to 1.
#endif /* configNUMBER_OF_CORES < 1 */
/* A critical section is exited when the critical section nesting count reaches
* this value. */
#define portNO_CRITICAL_NESTING ( ( size_t ) 0 )
/* Macro to unmask all interrupt priorities. */
#define portCLEAR_INTERRUPT_PRIORITIES_MASK() __asm volatile ( "SVC %0" : : "i" ( portSVC_UNMASK_ALL_INTERRUPTS ) : "memory" )
/* Tasks are not created with a floating point context, but can be given a
* floating point context after they have been created. A variable is stored as
* part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
* does not have an FPU context, or any other value if the task does have an FPU
* context. */
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
/* Constants required to setup the initial task context. */
#define portSP_ELx ( ( StackType_t ) 0x01 )
#define portSP_EL0 ( ( StackType_t ) 0x00 )
#define portEL1 ( ( StackType_t ) 0x04 )
#define portEL0 ( ( StackType_t ) 0x00 )
#define portINITIAL_PSTATE ( portEL0 | portSP_EL0 )
/* Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary
* point is zero. */
#define portBINARY_POINT_BITS ( ( uint8_t ) 0x03 )
/* Masks all bits in the APSR other than the mode bits. */
#define portAPSR_MODE_BITS_MASK ( 0x0C )
/* The I bit in the DAIF bits. */
#define portDAIF_I ( 0x80 )
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
#define portBIT_0_SET ( ( uint8_t ) 0x01 )
/* The space on the stack required to hold the FPU registers.
* There are 32 128-bit plus 2 64-bit status registers. */
#define portFPU_REGISTER_WORDS ( ( 32 * 2 ) + 2 )
/*-----------------------------------------------------------*/
/*
* Starts the first task executing. This function is necessarily written in
* assembly code so is implemented in portASM.s.
*/
extern void vPortRestoreTaskContext( void );
extern void vGIC_EnableIRQ( uint32_t ulInterruptID );
extern void vGIC_SetPriority( uint32_t ulInterruptID, uint32_t ulPriority );
extern void vGIC_PowerUpRedistributor( void );
extern void vGIC_EnableCPUInterface( void );
/*-----------------------------------------------------------*/
#if ( configNUMBER_OF_CORES == 1 )
volatile uint64_t ullCriticalNesting = 0ULL;
/* Saved as part of the task context. If ullPortTaskHasFPUContext is non-zero
* then floating point context must be saved and restored for the task. */
uint64_t ullPortTaskHasFPUContext = pdFALSE;
/* Set to 1 to pend a context switch from an ISR. */
uint64_t ullPortYieldRequired = pdFALSE;
/* Counts the interrupt nesting depth. A context switch is only performed if
* if the nesting depth is 0. */
uint64_t ullPortInterruptNesting = 0;
#else /* #if ( configNUMBER_OF_CORES == 1 ) */
volatile uint64_t ullCriticalNestings[ configNUMBER_OF_CORES ] = { 0 };
/* Saved as part of the task context. If ullPortTaskHasFPUContext is non-zero
* then floating point context must be saved and restored for the task. */
uint64_t ullPortTaskHasFPUContext[ configNUMBER_OF_CORES ] = { pdFALSE };
uint64_t ullPortYieldRequired[ configNUMBER_OF_CORES ] = { pdFALSE };
uint64_t ullPortInterruptNestings[ configNUMBER_OF_CORES ] = { 0 };
/* Flags to check if the secondary cores are ready. */
volatile uint8_t ucSecondaryCoresReadyFlags[ configNUMBER_OF_CORES - 1 ] = { 0 };
volatile uint8_t ucPrimaryCoreInitDoneFlag = 0;
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */
/* Used in the ASM code. */
__attribute__( ( used ) ) const uint64_t ullMaxAPIPriorityMask = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
/*-----------------------------------------------------------*/
/*
* See header file for description.
*/
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters )
{
/* Setup the initial stack of the task. The stack is set exactly as
* expected by the portRESTORE_CONTEXT() macro. */
/* First all the general purpose registers. */
pxTopOfStack--;
*pxTopOfStack = 0x0101010101010101ULL; /* R1 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--;
*pxTopOfStack = 0x0303030303030303ULL; /* R3 */
pxTopOfStack--;
*pxTopOfStack = 0x0202020202020202ULL; /* R2 */
pxTopOfStack--;
*pxTopOfStack = 0x0505050505050505ULL; /* R5 */
pxTopOfStack--;
*pxTopOfStack = 0x0404040404040404ULL; /* R4 */
pxTopOfStack--;
*pxTopOfStack = 0x0707070707070707ULL; /* R7 */
pxTopOfStack--;
*pxTopOfStack = 0x0606060606060606ULL; /* R6 */
pxTopOfStack--;
*pxTopOfStack = 0x0909090909090909ULL; /* R9 */
pxTopOfStack--;
*pxTopOfStack = 0x0808080808080808ULL; /* R8 */
pxTopOfStack--;
*pxTopOfStack = 0x1111111111111111ULL; /* R11 */
pxTopOfStack--;
*pxTopOfStack = 0x1010101010101010ULL; /* R10 */
pxTopOfStack--;
*pxTopOfStack = 0x1313131313131313ULL; /* R13 */
pxTopOfStack--;
*pxTopOfStack = 0x1212121212121212ULL; /* R12 */
pxTopOfStack--;
*pxTopOfStack = 0x1515151515151515ULL; /* R15 */
pxTopOfStack--;
*pxTopOfStack = 0x1414141414141414ULL; /* R14 */
pxTopOfStack--;
*pxTopOfStack = 0x1717171717171717ULL; /* R17 */
pxTopOfStack--;
*pxTopOfStack = 0x1616161616161616ULL; /* R16 */
pxTopOfStack--;
*pxTopOfStack = 0x1919191919191919ULL; /* R19 */
pxTopOfStack--;
*pxTopOfStack = 0x1818181818181818ULL; /* R18 */
pxTopOfStack--;
*pxTopOfStack = 0x2121212121212121ULL; /* R21 */
pxTopOfStack--;
*pxTopOfStack = 0x2020202020202020ULL; /* R20 */
pxTopOfStack--;
*pxTopOfStack = 0x2323232323232323ULL; /* R23 */
pxTopOfStack--;
*pxTopOfStack = 0x2222222222222222ULL; /* R22 */
pxTopOfStack--;
*pxTopOfStack = 0x2525252525252525ULL; /* R25 */
pxTopOfStack--;
*pxTopOfStack = 0x2424242424242424ULL; /* R24 */
pxTopOfStack--;
*pxTopOfStack = 0x2727272727272727ULL; /* R27 */
pxTopOfStack--;
*pxTopOfStack = 0x2626262626262626ULL; /* R26 */
pxTopOfStack--;
*pxTopOfStack = 0x2929292929292929ULL; /* R29 */
pxTopOfStack--;
*pxTopOfStack = 0x2828282828282828ULL; /* R28 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x00; /* XZR - has no effect, used so there are an even number of registers. */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x00; /* R30 - procedure call link register. */
pxTopOfStack--;
*pxTopOfStack = portINITIAL_PSTATE;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxCode; /* Exception return address. */
#if ( configUSE_TASK_FPU_SUPPORT == portTASK_NO_FPU_CONTEXT_BY_DEFAULT )
{
/* The task will start with a critical nesting count of 0 as interrupts are
* enabled. */
pxTopOfStack--;
*pxTopOfStack = portNO_CRITICAL_NESTING;
/* The task will start without a floating point context. A task that
* uses the floating point hardware must call vPortTaskUsesFPU() before
* executing any floating point instructions. */
pxTopOfStack--;
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
}
#elif ( configUSE_TASK_FPU_SUPPORT == portTASK_HAVE_FPU_CONTEXT_BY_DEFAULT )
{
/* The task will start with a floating point context. Leave enough
* space for the registers - and ensure they are initialised to 0. */
pxTopOfStack -= portFPU_REGISTER_WORDS;
memset( pxTopOfStack, 0x00, portFPU_REGISTER_WORDS * sizeof( StackType_t ) );
/* The task will start with a critical nesting count of 0 as interrupts are
* enabled. */
pxTopOfStack--;
*pxTopOfStack = portNO_CRITICAL_NESTING;
pxTopOfStack--;
*pxTopOfStack = pdTRUE;
#if ( configNUMBER_OF_CORES == 1 )
ullPortTaskHasFPUContext = pdTRUE;
#else
ullPortTaskHasFPUContext[ portGET_CORE_ID() ] = pdTRUE;
#endif
}
#else /* if ( configUSE_TASK_FPU_SUPPORT == portTASK_NO_FPU_CONTEXT_BY_DEFAULT ) */
{
#error "Invalid configUSE_TASK_FPU_SUPPORT setting - configUSE_TASK_FPU_SUPPORT must be set to 1, 2, or left undefined."
}
#endif /* if ( configUSE_TASK_FPU_SUPPORT == portTASK_NO_FPU_CONTEXT_BY_DEFAULT ) */
return pxTopOfStack;
}
/*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void )
{
uint64_t ullAPSR;
#if ( configASSERT_DEFINED == 1 )
{
volatile uint8_t ucOriginalPriority;
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + portINTERRUPT_PRIORITY_REGISTER_OFFSET );
volatile uint8_t ucMaxPriorityValue;
/* Determine how many priority bits are implemented in the GIC.
*
* Save the interrupt priority value that is about to be clobbered. */
ucOriginalPriority = *pucFirstUserPriorityRegister;
/* Determine the number of priority bits available. First write to
* all possible bits. */
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* Read the value back to see how many bits stuck. */
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
/* Shift to the least significant bits. */
while( ( ucMaxPriorityValue & portBIT_0_SET ) != portBIT_0_SET )
{
ucMaxPriorityValue >>= ( uint8_t ) 0x01;
}
/* Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read
* value. */
configASSERT( ucMaxPriorityValue >= portLOWEST_INTERRUPT_PRIORITY );
/* Restore the clobbered interrupt priority register to its original
* value. */
*pucFirstUserPriorityRegister = ucOriginalPriority;
}
#endif /* configASSERT_DEFINED */
__asm volatile ( "MRS %0, CurrentEL" : "=r" ( ullAPSR ) );
ullAPSR &= portAPSR_MODE_BITS_MASK;
configASSERT( ullAPSR == portEL1 );
/* Interrupts are turned off in the CPU itself to ensure a tick does
* not execute while the scheduler is being started. Interrupts are
* automatically turned back on in the CPU when the first task starts
* executing. */
__asm volatile ( "MSR DAIFSET, #2\n"
"DSB SY\n"
"ISB SY\n" ::: "memory" );
#if ( configNUMBER_OF_CORES > 1 )
/* Start the timer that generates the tick ISR. */
configSETUP_TICK_INTERRUPT();
ucPrimaryCoreInitDoneFlag = 1;
__asm volatile ( "SEV \n"
"DSB SY \n"
"ISB SY \n"
::: "memory" );
/* 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( uint32_t ulCoreID = 0; ulCoreID < ( configNUMBER_OF_CORES - 1 ); ulCoreID++ )
{
if( ucSecondaryCoresReadyFlags[ ulCoreID ] != pdTRUE )
{
xAllCoresReady = pdFALSE;
break;
}
}
if ( xAllCoresReady == pdTRUE )
{
break;
}
}
#else /* if ( configNUMBER_OF_CORES > 1 ) */
/* Start the timer that generates the tick ISR. */
configSETUP_TICK_INTERRUPT();
#endif /* if ( configNUMBER_OF_CORES > 1 ) */
/* Start the first task executing. */
vPortRestoreTaskContext();
return 0;
}
/*-----------------------------------------------------------*/
void vPortEndScheduler( void )
{
/* Stub implementation for ports where there is nothing to return to
* Artificially force an assert. */
configASSERT( NULL );
}
/*-----------------------------------------------------------*/
#if ( configNUMBER_OF_CORES == 1 )
void vPortEnterCritical( void )
{
/* Mask interrupts up to the max syscall interrupt priority. */
uxPortSetInterruptMask();
/* Now interrupts are disabled ullCriticalNesting can be accessed
* directly. Increment ullCriticalNesting to keep a count of how many times
* portENTER_CRITICAL() has been called. */
ullCriticalNesting++;
/* This is not the interrupt safe version of the enter critical function so
* assert() if it is being called from an interrupt context. Only API
* functions that end in "FromISR" can be used in an interrupt. Only assert if
* the critical nesting count is 1 to protect against recursive calls if the
* assert function also uses a critical section. */
if( ullCriticalNesting == 1ULL )
{
configASSERT( ullPortInterruptNesting == 0 );
}
}
/*-----------------------------------------------------------*/
void vPortExitCritical( void )
{
if( ullCriticalNesting > portNO_CRITICAL_NESTING )
{
/* Decrement the nesting count as the critical section is being
* exited. */
ullCriticalNesting--;
/* If the nesting level has reached zero then all interrupt
* priorities must be re-enabled. */
if( ullCriticalNesting == portNO_CRITICAL_NESTING )
{
/* Critical nesting has reached zero so all interrupt priorities
* should be unmasked. */
portCLEAR_INTERRUPT_PRIORITIES_MASK();
}
}
}
#endif /* if ( configNUMBER_OF_CORES == 1 ) */
/*-----------------------------------------------------------*/
void FreeRTOS_Tick_Handler( void )
{
/* Must be the lowest possible priority. */
uint64_t ullRunningInterruptPriority;
__asm volatile ( "MRS %0, ICC_RPR_EL1" : "=r" ( ullRunningInterruptPriority ) );
configASSERT( ullRunningInterruptPriority == ( portLOWEST_USABLE_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
/* Interrupts should not be enabled before this point. */
#if ( configASSERT_DEFINED == 1 )
{
uint64_t ullMaskBits;
__asm volatile ( "MRS %0, DAIF" : "=r" ( ullMaskBits )::"memory" );
configASSERT( ( ullMaskBits & portDAIF_I ) != 0 );
}
#endif /* configASSERT_DEFINED */
/* Set interrupt mask before altering scheduler structures. The tick
* handler runs at the lowest priority, so interrupts cannot already be masked,
* so there is no need to save and restore the current mask value. It is
* necessary to turn off interrupts in the CPU itself while the ICCPMR is being
* updated. */
__asm volatile ( "MSR ICC_PMR_EL1, %0 \n"
"DSB SY \n"
"ISB SY \n"
::"r" ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) : "memory" );
/* Ok to enable interrupts after the interrupt source has been cleared. */
configCLEAR_TICK_INTERRUPT();
__asm volatile ( "MSR DAIFCLR, #2\n"
"DSB SY\n"
"ISB SY\n" ::: "memory" );
#if ( configNUMBER_OF_CORES > 1 )
UBaseType_t x = portENTER_CRITICAL_FROM_ISR();
#endif /* if ( configNUMBER_OF_CORES > 1 ) */
/* Increment the RTOS tick. */
if( xTaskIncrementTick() != pdFALSE )
{
#if ( configNUMBER_OF_CORES == 1 )
ullPortYieldRequired = pdTRUE;
#else
ullPortYieldRequired[ portGET_CORE_ID() ] = pdTRUE;
#endif
}
#if ( configNUMBER_OF_CORES > 1 )
portEXIT_CRITICAL_FROM_ISR(x);
#endif /* if ( configNUMBER_OF_CORES > 1 ) */
/* Ensure all interrupt priorities are active again. */
portCLEAR_INTERRUPT_PRIORITIES_MASK();
}
/*-----------------------------------------------------------*/
#if ( configUSE_TASK_FPU_SUPPORT == portTASK_NO_FPU_CONTEXT_BY_DEFAULT )
void vPortTaskUsesFPU( void )
{
/* A task is registering the fact that it needs an FPU context. Set the
* FPU flag (which is saved as part of the task context). */
#if ( configNUMBER_OF_CORES == 1 )
ullPortTaskHasFPUContext = pdTRUE;
#else
ullPortTaskHasFPUContext[ portGET_CORE_ID() ] = pdTRUE;
#endif
/* Consider initialising the FPSR here - but probably not necessary in
* AArch64. */
}
#endif /* configUSE_TASK_FPU_SUPPORT */
/*-----------------------------------------------------------*/
void vPortClearInterruptMask( UBaseType_t uxNewMaskValue )
{
if( uxNewMaskValue == portUNMASK_VALUE )
{
/* Unmask all interrupt priorities. */
portCLEAR_INTERRUPT_PRIORITIES_MASK();
}
else
{
__asm volatile (
"SVC %0 \n"
:
: "i" ( portSVC_UNMASK_INTERRUPTS ), "r" ( uxNewMaskValue )
: "memory"
);
}
}
void vPortClearInterruptMaskFromISR( UBaseType_t uxNewMaskValue )
{
__asm volatile (
"MSR DAIFSET, #2 \n"
"DSB SY \n"
"ISB SY \n"
"MSR ICC_PMR_EL1, %0 \n"
"DSB SY \n"
"ISB SY \n"
"MSR DAIFCLR, #2 \n"
"DSB SY \n"
"ISB SY \n"
:
: "r" ( uxNewMaskValue )
);
}
/*-----------------------------------------------------------*/
UBaseType_t uxPortSetInterruptMask( void )
{
UBaseType_t ullPMRValue;
/* Use SVC so this can be called safely from EL0 tasks. */
__asm volatile (
"svc %1 \n"
"mov %0, x0 \n"
: "=r" ( ullPMRValue )
: "i" ( portSVC_MASK_ALL_INTERRUPTS )
: "x0", "memory"
);
return ullPMRValue;
}
/* EL1/ISR variant to avoid SVC from interrupt context. */
UBaseType_t uxPortSetInterruptMaskFromISR( void )
{
UBaseType_t ullPMRValue;
__asm volatile ( "MRS %0, ICC_PMR_EL1" : "=r" ( ullPMRValue ) );
if( ullPMRValue != ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )
{
__asm volatile ( "MSR DAIFSET, #2 \n"
"DSB SY \n"
"ISB SY \n"
"MSR ICC_PMR_EL1, %0 \n"
"DSB SY \n"
"ISB SY \n"
"MSR DAIFCLR, #2 \n"
"DSB SY \n"
"ISB SY \n"
::"r" ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) : "memory" );
}
return ullPMRValue;
}
/*-----------------------------------------------------------*/
#if ( configASSERT_DEFINED == 1 )
void vPortValidateInterruptPriority( void )
{
/* The following assertion will fail if a service routine (ISR) for
* an interrupt that has been assigned a priority above
* configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
* function. ISR safe FreeRTOS API functions must *only* be called
* from interrupts that have been assigned a priority at or below
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
*
* Numerically low interrupt priority numbers represent logically high
* interrupt priorities, therefore the priority of the interrupt must
* be set to a value equal to or numerically *higher* than
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
*
* FreeRTOS maintains separate thread and ISR API functions to ensure
* interrupt entry is as fast and simple as possible. */
uint64_t ullRunningInterruptPriority;
__asm volatile ( "MRS %0, ICC_RPR_EL1" : "=r" ( ullRunningInterruptPriority ) );
configASSERT( ullRunningInterruptPriority >= ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
}
#endif /* configASSERT_DEFINED */
/*-----------------------------------------------------------*/
/*
* If the application provides an implementation of vApplicationIRQHandler(),
* then it will get called directly without saving the FPU registers on
* interrupt entry, and this weak implementation of
* vApplicationFPUSafeIRQHandler() is just provided to remove linkage errors -
* it should never actually get called so its implementation contains a
* call to configASSERT() that will always fail.
*
* If the application provides its own implementation of
* vApplicationFPUSafeIRQHandler() then the implementation of
* vApplicationIRQHandler() provided in portASM.S will save the FPU registers
* before calling it.
*
* Therefore, if the application writer wants FPU registers to be saved on
* interrupt entry their IRQ handler must be called
* vApplicationFPUSafeIRQHandler(), and if the application writer does not want
* FPU registers to be saved on interrupt entry their IRQ handler must be
* called vApplicationIRQHandler().
*/
__attribute__( ( weak ) ) void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR )
{
( void ) ulICCIAR;
configASSERT( ( volatile void * ) NULL );
}
/*-----------------------------------------------------------*/
#if ( configNUMBER_OF_CORES > 1 )
/* Which core owns the lock? */
volatile uint64_t ucOwnedByCore[ portMAX_CORE_COUNT ];
/* Lock count a core owns. */
volatile uint64_t ucRecursionCountByLock[ eLockCount ];
/* Index 0 is used for ISR lock and Index 1 is used for task lock. */
uint32_t ulGateWord[ eLockCount ];
void vInterruptCore( uint32_t ulInterruptID, uint32_t ulCoreID )
{
uint64_t ulRegVal = 0;
uint32_t ulCoreMask = ( 1UL << ulCoreID );
ulRegVal |= ( (ulCoreMask & 0xFFFF) | ( ( ulInterruptID & 0xF ) << 24U ) );
__asm__ volatile ( "msr ICC_SGI1R_EL1, %0" : : "r" ( ulRegVal ) );
__asm__ volatile ( "dsb sy");
__asm__ volatile ( "isb sy");
}
/*-----------------------------------------------------------*/
static inline void prvSpinUnlock( uint32_t * ulLock )
{
__asm volatile (
"dmb sy\n"
"mov w1, #0\n"
"str w1, [%x0]\n"
"sev\n"
"dsb sy\n"
"isb sy\n"
:
: "r" ( ulLock )
: "memory", "w1"
);
}
/*-----------------------------------------------------------*/
static inline uint32_t prvSpinTrylock( uint32_t * ulLock )
{
register uint32_t ulRet;
/* Try to acquire spinlock; caller is responsible for further barriers. */
__asm volatile (
"1:\n"
"ldxr w1, [%x1]\n"
"cmp w1, #1\n"
"beq 2f\n"
"mov w2, #1\n"
"stxr w1, w2, [%x1]\n"
"cmp w1, #0\n"
"bne 1b\n"
"2:\n"
"mov %w0, w1\n"
: "=r" ( ulRet )
: "r" ( ulLock )
: "memory", "w1", "w2"
);
return ulRet;
}
/*-----------------------------------------------------------*/
/* Read 64b value shared between cores. */
static inline uint64_t prvGet64( volatile uint64_t * x )
{
__asm( "dsb sy" );
return *x;
}
/*-----------------------------------------------------------*/
/* Write 64b value shared between cores. */
static inline void prvSet64( volatile uint64_t * x,
uint64_t value )
{
*x = value;
__asm( "dsb sy" );
}
/*-----------------------------------------------------------*/
void vPortRecursiveLock( BaseType_t xCoreID,
ePortRTOSLock eLockNum,
BaseType_t uxAcquire )
{
/* Validate the core ID and lock number. */
configASSERT( xCoreID < 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( prvGet64( &ucOwnedByCore[ xCoreID ] ) & ulLockBit )
{
configASSERT( prvGet64( &ucRecursionCountByLock[ eLockNum ] ) != 255u );
prvSet64( &ucRecursionCountByLock[ eLockNum ], ( prvGet64( &ucRecursionCountByLock[ eLockNum ] ) + 1 ) );
return;
}
/* Preload the gate word into the cache. */
uint32_t dummy = ulGateWord[ eLockNum ];
dummy++;
while( prvSpinTrylock( &ulGateWord[ eLockNum ] ) != 0 )
{
/* Follow Arm's recommended way of sleeping
* sevl is used to prime the wait loop,
* the first wfe wakes immediately as sevl has set the flag
* the second wfe sleeps the core. This way the core is ensured
* to sleep.
*/
__asm volatile ( "sevl; wfe; 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( prvGet64( &ucRecursionCountByLock[ eLockNum ] ) == 0 );
/* Set lock count as 1. */
prvSet64( &ucRecursionCountByLock[ eLockNum ], 1 );
/* Set ucOwnedByCore. */
prvSet64( &ucOwnedByCore[ xCoreID ], ( prvGet64( &ucOwnedByCore[ xCoreID ] ) | ulLockBit ) );
}
/* Lock release. */
else
{
/* Assert the lock is not free already. */
configASSERT( ( prvGet64( &ucOwnedByCore[ xCoreID ] ) & ulLockBit ) != 0 );
configASSERT( prvGet64( &ucRecursionCountByLock[ eLockNum ] ) != 0 );
/* Reduce ucRecursionCountByLock by 1. */
prvSet64( &ucRecursionCountByLock[ eLockNum ], ( prvGet64( &ucRecursionCountByLock[ eLockNum ] ) - 1 ) );
if( !prvGet64( &ucRecursionCountByLock[ eLockNum ] ) )
{
prvSet64( &ucOwnedByCore[ xCoreID ], ( prvGet64( &ucOwnedByCore[ xCoreID ] ) & ~ulLockBit ) );
prvSpinUnlock( &ulGateWord[ eLockNum ] );
/* Add barrier to ensure lock status is reflected before we proceed. */
__asm__ __volatile__ ( "dmb sy" ::: "memory" );
}
}
}
/*-----------------------------------------------------------*/
BaseType_t xPortGetCoreID( void )
{
BaseType_t xCoreID;
__asm volatile (
"svc %1 \n"
"mov %0, x0 \n"
: "=r" ( xCoreID )
: "i" ( portSVC_GET_CORE_ID )
: "x0", "memory"
);
return xCoreID;
}
/*-----------------------------------------------------------*/
void FreeRTOS_SGI_Handler( void )
{
/* Must be the lowest possible priority. */
uint64_t ullRunningInterruptPriority;
__asm volatile ( "MRS %0, ICC_RPR_EL1" : "=r" ( ullRunningInterruptPriority ) );
configASSERT( ullRunningInterruptPriority == ( portLOWEST_USABLE_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
/* Interrupts should not be enabled before this point. */
#if ( configASSERT_DEFINED == 1 )
{
uint64_t ullMaskBits;
__asm volatile ( "mrs %0, DAIF" : "=r" ( ullMaskBits )::"memory" );
configASSERT( ( ullMaskBits & portDAIF_I ) != 0 );
}
#endif /* configASSERT_DEFINED */
/* Set interrupt mask before altering scheduler structures. The SGI
* handler runs at the lowest priority, so interrupts cannot already be masked,
* so there is no need to save and restore the current mask value. It is
* necessary to turn off interrupts in the CPU itself while the ICCPMR is being
* updated. */
__asm volatile ( "MSR ICC_PMR_EL1, %0 \n"
"DSB SY \n"
"ISB SY \n"
::"r" ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) : "memory" );
/* Ok to enable interrupts after the interrupt source has been cleared. */
__asm volatile ( "MSR DAIFCLR, #2\n"
"DSB SY\n"
"ISB SY\n" ::: "memory" );
#if ( configNUMBER_OF_CORES == 1 )
ullPortYieldRequired = pdTRUE;
#else
ullPortYieldRequired[ portGET_CORE_ID() ] = pdTRUE;
#endif
/* Ensure all interrupt priorities are active again. */
portCLEAR_INTERRUPT_PRIORITIES_MASK();
}
/*-----------------------------------------------------------*/
#endif /* if( configNUMBER_OF_CORES > 1 ) */

View file

@ -0,0 +1,663 @@
/*
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
* 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
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
/*
* This file is tailored for ARM Cortex-R82 with SMP enabled.
* It includes macros and functions for saving/restoring task context,
* handling interrupts, and supporting multi-core operations.
*/
#include "FreeRTOSConfig.h"
#include "portmacro.h"
.text
/* Variables and functions. */
.extern ullMaxAPIPriorityMask
#if ( configNUMBER_OF_CORES == 1 )
.extern pxCurrentTCB
.extern ullCriticalNesting
.extern ullPortInterruptNesting
#else /* #if ( configNUMBER_OF_CORES == 1 ) */
.extern pxCurrentTCBs
.extern ullCriticalNestings
.extern ullPortInterruptNestings
#endif
.extern vTaskSwitchContext
.extern vApplicationIRQHandler
.extern ullPortTaskHasFPUContext
.extern ullPortYieldRequired
.extern _freertos_vector_table
.global FreeRTOS_IRQ_Handler
.global FreeRTOS_SWI_Handler
.global vPortRestoreTaskContext
.macro saveallgpregisters
/* Save all general-purpose registers on stack. */
STP X0, X1, [ SP, # - 0x10 ] !
STP X2, X3, [ SP, # - 0x10 ] !
STP X4, X5, [ SP, # - 0x10 ] !
STP X6, X7, [ SP, # - 0x10 ] !
STP X8, X9, [ SP, # - 0x10 ] !
STP X10, X11, [ SP, # - 0x10 ] !
STP X12, X13, [ SP, # - 0x10 ] !
STP X14, X15, [ SP, # - 0x10 ] !
STP X16, X17, [ SP, # - 0x10 ] !
STP X18, X19, [ SP, # - 0x10 ] !
STP X20, X21, [ SP, # - 0x10 ] !
STP X22, X23, [ SP, # - 0x10 ] !
STP X24, X25, [ SP, # - 0x10 ] !
STP X26, X27, [ SP, # - 0x10 ] !
STP X28, X29, [ SP, # - 0x10 ] !
STR X30, [ SP, # - 0x10 ] !
.endm
/*-----------------------------------------------------------*/
.macro restoreallgpregisters
/* Restore all general-purpose registers from stack. */
LDR X30, [ SP ], # 0x10
LDP X28, X29, [ SP ], # 0x10
LDP X26, X27, [ SP ], # 0x10
LDP X24, X25, [ SP ], # 0x10
LDP X22, X23, [ SP ], # 0x10
LDP X20, X21, [ SP ], # 0x10
LDP X18, X19, [ SP ], # 0x10
LDP X16, X17, [ SP ], # 0x10
LDP X14, X15, [ SP ], # 0x10
LDP X12, X13, [ SP ], # 0x10
LDP X10, X11, [ SP ], # 0x10
LDP X8, X9, [ SP ], # 0x10
LDP X6, X7, [ SP ], # 0x10
LDP X4, X5, [ SP ], # 0x10
LDP X2, X3, [ SP ], # 0x10
LDP X0, X1, [ SP ], # 0x10
.endm
/*-----------------------------------------------------------*/
.macro savefuncontextgpregs
/* Save function context general-purpose registers. */
STP X0, X1, [ SP, # - 0x10 ] !
STP X2, X3, [ SP, # - 0x10 ] !
STP X4, X5, [ SP, # - 0x10 ] !
STP X6, X7, [ SP, # - 0x10 ] !
STP X8, X9, [ SP, # - 0x10 ] !
STP X10, X11, [ SP, # - 0x10 ] !
STP X12, X13, [ SP, # - 0x10 ] !
STP X14, X15, [ SP, # - 0x10 ] !
STP X16, X17, [ SP, # - 0x10 ] !
STP X18, X29, [ SP, # - 0x10 ] !
STR X30, [ SP, # - 0x10 ] !
.endm
/*-----------------------------------------------------------*/
.macro restorefuncontextgpregs
/* Restore function context general-purpose registers. */
LDR X30, [ SP ], # 0x10
LDP X18, X29, [ SP ], # 0x10
LDP X16, X17, [ SP ], # 0x10
LDP X14, X15, [ SP ], # 0x10
LDP X12, X13, [ SP ], # 0x10
LDP X10, X11, [ SP ], # 0x10
LDP X8, X9, [ SP ], # 0x10
LDP X6, X7, [ SP ], # 0x10
LDP X4, X5, [ SP ], # 0x10
LDP X2, X3, [ SP ], # 0x10
LDP X0, X1, [ SP ], # 0x10
.endm
/*-----------------------------------------------------------*/
.macro savefloatregisters
/* Save floating-point registers and configuration/status registers. */
STP Q0, Q1, [ SP, # - 0x20 ] !
STP Q2, Q3, [ SP, # - 0x20 ] !
STP Q4, Q5, [ SP, # - 0x20 ] !
STP Q6, Q7, [ SP, # - 0x20 ] !
STP Q8, Q9, [ SP, # - 0x20 ] !
STP Q10, Q11, [ SP, # - 0x20 ] !
STP Q12, Q13, [ SP, # - 0x20 ] !
STP Q14, Q15, [ SP, # - 0x20 ] !
STP Q16, Q17, [ SP, # - 0x20 ] !
STP Q18, Q19, [ SP, # - 0x20 ] !
STP Q20, Q21, [ SP, # - 0x20 ] !
STP Q22, Q23, [ SP, # - 0x20 ] !
STP Q24, Q25, [ SP, # - 0x20 ] !
STP Q26, Q27, [ SP, # - 0x20 ] !
STP Q28, Q29, [ SP, # - 0x20 ] !
STP Q30, Q31, [ SP, # - 0x20 ] !
MRS X9, FPSR
MRS X10, FPCR
STP W9, W10, [ SP, # - 0x10 ] !
.endm
/*-----------------------------------------------------------*/
.macro restorefloatregisters
/* Restore floating-point registers and configuration/status registers. */
LDP W9, W10, [ SP ], # 0x10
MSR FPSR, X9
MSR FPCR, X10
LDP Q30, Q31, [ SP ], # 0x20
LDP Q28, Q29, [ SP ], # 0x20
LDP Q26, Q27, [ SP ], # 0x20
LDP Q24, Q25, [ SP ], # 0x20
LDP Q22, Q23, [ SP ], # 0x20
LDP Q20, Q21, [ SP ], # 0x20
LDP Q18, Q19, [ SP ], # 0x20
LDP Q16, Q17, [ SP ], # 0x20
LDP Q14, Q15, [ SP ], # 0x20
LDP Q12, Q13, [ SP ], # 0x20
LDP Q10, Q11, [ SP ], # 0x20
LDP Q8, Q9, [ SP ], # 0x20
LDP Q6, Q7, [ SP ], # 0x20
LDP Q4, Q5, [ SP ], # 0x20
LDP Q2, Q3, [ SP ], # 0x20
LDP Q0, Q1, [ SP ], # 0x20
.endm
/*-----------------------------------------------------------*/
.macro portSAVE_CONTEXT
/* Switch to use the EL0 stack pointer. */
MSR SPSEL, # 0
/* Save the entire context. */
saveallgpregisters
/* Save the SPSR and ELR values. */
MRS X3, SPSR_EL1
MRS X2, ELR_EL1
STP X2, X3, [ SP, # - 0x10 ] !
/* Save the critical section nesting depth. */
LDR X0, ullCriticalNestingsConst
#if configNUMBER_OF_CORES > 1
/* Calculate per-core index using MPIDR_EL1 for SMP support. */
MRS X1, MPIDR_EL1 /* Read the Multiprocessor Affinity Register. */
AND X1, X1, # 0xff /* Extract Aff0 (core ID). */
LSL X1, X1, # 3 /* Multiply core ID by pointer size (8 bytes). */
ADD X0, X0, X1 /* Add offset to base address. */
#endif
LDR X3, [ X0 ]
/* Save the FPU context indicator. */
LDR X0, ullPortTaskHasFPUContextConst
#if configNUMBER_OF_CORES > 1
ADD X0, X0, X1 /* Add to the base of the FPU array. */
#endif
LDR X2, [ X0 ]
/* Save the FPU context, if any (32 128-bit registers). */
CMP X2, # 0
B.EQ 1f /* FPU context not present, skip saving FPU registers. */
savefloatregisters
1 :
/* Store the critical nesting count and FPU context indicator. */
STP X2, X3, [ SP, # - 0x10 ] !
LDR X0, pxCurrentTCBsConst
#if ( configNUMBER_OF_CORES > 1 )
MRS X1, MPIDR_EL1 /* Read Multiprocessor Affinity Register .*/
AND X1, X1, # 0xff /* Extract core ID. */
LSL X1, X1, # 3 /* Multiply core ID by pointer size. */
ADD X0, X0, X1 /* Offset for current core's TCB pointer. */
#endif
LDR X1, [ X0 ]
MOV X0, SP /* Save current stack pointer. */
STR X0, [ X1 ]
/* Switch to use the ELx stack pointer. */
MSR SPSEL, # 1
.endm
/*-----------------------------------------------------------*/
.macro portRESTORE_CONTEXT
/* Switch to use the EL0 stack pointer. */
MSR SPSEL, # 0
/* Set the SP to point to the stack of the task being restored. */
LDR X0, pxCurrentTCBsConst
#if configNUMBER_OF_CORES > 1
/* Get the core ID to index the TCB correctly. */
MRS X2, MPIDR_EL1 /* Read the Multiprocessor Affinity Register. */
AND X2, X2, # 0xff /* Extract Aff0 which contains the core ID. */
LSL X2, X2, # 3 /* Scale the core ID to the size of a pointer (64-bit system). */
ADD X0, X0, X2 /* Add the offset for the current core's TCB pointer. */
#endif
LDR X1, [ X0 ]
LDR X0, [ X1 ]
MOV SP, X0
LDP X2, X3, [ SP ], # 0x10 /* Retrieve critical nesting and FPU indicator. */
LDR X0, ullCriticalNestingsConst
/* Calculate offset for current core's ullCriticalNesting. */
#if configNUMBER_OF_CORES > 1
/* Existing code to get core ID and scale to pointer size is reused. */
MRS X1, MPIDR_EL1 /* Read Multiprocessor Affinity Register. */
AND X1, X1, # 0xff /* Extract Aff0, which contains the core ID. */
LSL X1, X1, # 3 /* Scale core ID to the size of a pointer (assuming 64-bit system). */
ADD X0, X0, X1 /* Add offset for the current core's ullCriticalNesting. */
#endif
MOV X1, # 255 /* Default mask. */
CMP X3, # 0
B.EQ 1f
LDR X6, ullMaxAPIPriorityMaskConst
LDR X1, [ X6 ] /* Use computed mask value. */
1 :
MSR ICC_PMR_EL1, X1 /* Set interrupt mask. */
DSB SY
ISB SY
STR X3, [ X0 ] /* Restore critical nesting .*/
/* Restore the FPU context indicator. */
LDR X0, ullPortTaskHasFPUContextConst
#if configNUMBER_OF_CORES > 1
/* Existing code to get core ID and scale to pointer size is reused. */
MRS X1, MPIDR_EL1 /* Read Multiprocessor Affinity Register. */
AND X1, X1, # 0xff /* Extract Aff0, which contains the core ID. */
LSL X1, X1, # 3 /* Scale core ID to the size of a pointer (assuming 64-bit system). */
/* Restore the FPU context indicator. */
ADD X0, X0, X1 /* Add to the base of the FPU array. */
#endif
STR X2, [ X0 ]
/* Restore the FPU context, if any. */
CMP X2, # 0
B.EQ 1f
restorefloatregisters
1 :
LDP X2, X3, [ SP ], # 0x10 /* Restore SPSR and ELR. */
MSR SPSR_EL1, X3
MSR ELR_EL1, X2
restoreallgpregisters
/* Switch to use the ELx stack pointer. */
MSR SPSEL, # 1
ERET
.endm
/*-----------------------------------------------------------*/
/******************************************************************************
* FreeRTOS_SWI_Handler handler is used to perform a context switch.
*****************************************************************************/
.align 8
.type FreeRTOS_SWI_Handler, % function
FreeRTOS_SWI_Handler:
/* Save X0-X2 temporarily as they are used in the handler. */
STP X0, X1, [SP, #-0x10]!
STR X2, [SP, #-0x10]!
/* Decide action based on SVC immediate without corrupting any task context. */
MRS X0, ESR_EL1
/* Extract exception class. */
LSR X1, X0, # 26
CMP X1, # 0x15 /* 0x15 = SVC instruction. */
B.NE FreeRTOS_Abort
/* Extract SVC immediate from ISS[15:0]. */
AND X2, X0, # 0xFFFF
/* portSVC_START_FIRST_TASK: start first task on this core without saving any prior context. */
CMP X2, # portSVC_START_FIRST_TASK
B.NE 1f
/* Discard temp-saved X0-X2 before restoring first task. */
ADD SP, SP, # 0x20
B Start_First_Task
1:
/* portSVC_DISABLE_INTERRUPTS: disable IRQs (DAIF.I) without touching task context. */
CMP X2, # portSVC_DISABLE_INTERRUPTS
B.NE 2f
MSR DAIFSET, # 2
LDR X2, [SP], #0x10
LDP X0, X1, [SP], #0x10
DSB SY
ISB SY
ERET
2:
/* portSVC_ENABLE_INTERRUPTS: enable IRQs (DAIF.I clear) without touching task context. */
CMP X2, # portSVC_ENABLE_INTERRUPTS
B.NE 3f
MSR DAIFCLR, # 2
LDR X2, [SP], #0x10
LDP X0, X1, [SP], #0x10
DSB SY
ISB SY
ERET
3:
/* portSVC_GET_CORE_ID: return core ID in X0 (Aff0 of MPIDR_EL1). */
CMP X2, # portSVC_GET_CORE_ID
B.NE 4f
MRS X0, MPIDR_EL1
AND X0, X0, # 0xff
/* Restore X2, then restore X1 while discarding old X0. */
LDR X2, [ SP ], # 0x10
LDP XZR, X1, [ SP ], # 0x10
ERET
4:
/* portSVC_MASK_ALL_INTERRUPTS: set ICC_PMR_EL1 to max API mask and return previous-mask-equal flag in X0. */
CMP X2, # portSVC_MASK_ALL_INTERRUPTS
B.NE 5f
/* Load max API mask from ullMaxAPIPriorityMask. */
LDR X3, ullMaxAPIPriorityMaskConst
LDR X1, [ X3 ]
/* Read current PMR and compare. */
MRS X2, ICC_PMR_EL1
CMP X2, X1
B.EQ 41f
/* Disable IRQs while updating PMR. */
MSR DAIFSET, # 2
DSB SY
ISB SY
/* Write new PMR value. */
MSR ICC_PMR_EL1, X1
DSB SY
ISB SY
/* Re-enable IRQs. */
MSR DAIFCLR, # 2
DSB SY
ISB SY
41:
MOV X0, X2 /* return ICC_PMR_EL1 original value */
/* Restore X2, then restore X1 while discarding old X0. */
LDR X2, [ SP ], # 0x10
LDP XZR, X1, [ SP ], # 0x10
ERET
5:
/* portSVC_UNMASK_ALL_INTERRUPTS: set ICC_PMR_EL1 to portUNMASK_VALUE to unmask all interrupts. */
CMP X2, # portSVC_UNMASK_ALL_INTERRUPTS
B.NE 6f
/* Disable IRQs while updating PMR. */
MSR DAIFSET, # 2
DSB SY
ISB SY
MOV X0, #portUNMASK_VALUE /* Unmask all interrupts. */
MSR ICC_PMR_EL1, X0
DSB SY
ISB SY
/* Re-enable IRQs. */
MSR DAIFCLR, # 2
DSB SY
ISB SY
LDR X2, [SP], #0x10
LDP X0, X1, [SP], #0x10
ERET
6:
/* portSVC_UNMASK_INTERRUPTS: set ICC_PMR_EL1 to uxNewMaskValue. */
CMP X2, # portSVC_UNMASK_INTERRUPTS
B.NE 7f
/* Disable IRQs while updating PMR. */
MSR DAIFSET, # 2
DSB SY
ISB SY
MOV X0, X1 /* uxNewMaskValue is in X1. */
MSR ICC_PMR_EL1, X0
DSB SY
ISB SY
/* Re-enable IRQs. */
MSR DAIFCLR, # 2
DSB SY
ISB SY
LDR X2, [SP], #0x10
LDP X0, X1, [SP], #0x10
ERET
7:
/* Default (portSVC_YIELD): yield from a running task. Save context first. */
/* Restore X0-X2 to their original values before saving full context. */
LDR X2, [SP], #0x10
LDP X0, X1, [SP], #0x10
portSAVE_CONTEXT
#if configNUMBER_OF_CORES > 1
MRS x0, mpidr_el1
AND x0, x0, 255
#endif
BL vTaskSwitchContext
portRESTORE_CONTEXT
Start_First_Task:
/* Start-first-task path: pick a task and restore it (no prior save). */
portRESTORE_CONTEXT
FreeRTOS_Abort:
/* Full ESR is in X0, exception class code is in X1. */
B .
/******************************************************************************
* vPortRestoreTaskContext is used to start the scheduler.
*****************************************************************************/
.align 8
.type vPortRestoreTaskContext, % function
vPortRestoreTaskContext:
.set freertos_vector_base, _freertos_vector_table
/* Install the FreeRTOS interrupt handlers. */
LDR X1, = freertos_vector_base
MSR VBAR_EL1, X1
DSB SY
ISB SY
/* Start the first task. */
portRESTORE_CONTEXT
/******************************************************************************
* FreeRTOS_IRQ_Handler handles IRQ entry and exit.
*
* This handler is supposed to be used only for IRQs and never for FIQs. Per ARM
* GIC documentation [1], Group 0 interrupts are always signaled as FIQs. Since
* this handler is only for IRQs, We can safely assume Group 1 while accessing
* Interrupt Acknowledge and End Of Interrupt registers and therefore, use
* ICC_IAR1_EL1 and ICC_EOIR1_EL1.
*
* [1] https://developer.arm.com/documentation/198123/0300/Arm-CoreLink-GIC-fundamentals
*****************************************************************************/
.align 8
.type FreeRTOS_IRQ_Handler, % function
FreeRTOS_IRQ_Handler:
/* Save volatile registers. */
savefuncontextgpregs
savefloatregisters
/* Save the SPSR and ELR. */
MRS X3, SPSR_EL1
MRS X2, ELR_EL1
STP X2, X3, [ SP, # - 0x10 ] !
/* Increment the interrupt nesting counter. */
LDR X5, ullPortInterruptNestingsConst /* Load base address of the ullPortYieldRequired array */
#if configNUMBER_OF_CORES > 1
/* Existing code to get core ID and scale to pointer size is reused. */
MRS X2, MPIDR_EL1 /* Read Multiprocessor Affinity Register. */
AND X2, X2, # 0xff /* Extract Aff0, which contains the core ID. */
LSL X2, X2, # 3 /* Scale core ID to the size of a pointer (assuming 64-bit system). */
/* Calculate offset for the current core's ullPortYieldRequired and load its address. */
ADD X5, X5, X2 /* Add offset for the current core's ullPortYieldRequired. */
#endif
LDR X1, [ X5 ] /* Old nesting count in X1. */
ADD X6, X1, # 1
STR X6, [ X5 ] /* Address of nesting count variable in X5. */
/* Maintain the interrupt nesting information across the function call. */
STP X1, X5, [ SP, # - 0x10 ] !
/* Read interrupt ID from the interrupt acknowledge register and store it
* in X0 for future parameter and interrupt clearing use. */
MRS X0, ICC_IAR1_EL1
/* Maintain the interrupt ID value across the function call. */
STP X0, X1, [ SP, # - 0x10 ] !
/* Call the C handler. */
BL vApplicationIRQHandler
/* Disable interrupts. */
MSR DAIFSET, # 2
DSB SY
ISB SY
/* Restore the interrupt ID value. */
LDP X0, X1, [ SP ], # 0x10
/* End IRQ processing by writing interrupt ID value to the EOI register. */
MSR ICC_EOIR1_EL1, X0
/* Restore the critical nesting count. */
LDP X1, X5, [ SP ], # 0x10
STR X1, [ X5 ]
/* Has interrupt nesting unwound? */
CMP X1, # 0
B.NE Exit_IRQ_No_Context_Switch
/* Is a context switch required? */
LDR X0, ullPortYieldRequiredConst
#if configNUMBER_OF_CORES > 1
/* Existing code to get core ID and scale to pointer size is reused. */
MRS X2, MPIDR_EL1 /* Read Multiprocessor Affinity Register. */
AND X2, X2, # 0xff /* Extract Aff0, which contains the core ID. */
LSL X2, X2, # 3 /* Scale core ID to the size of a pointer (assuming 64-bit system). */
/* Calculate offset for the current core's ullPortYieldRequired and load its address. */
ADD X0, X0, X2 /* Add offset for the current core's ullPortYieldRequired. */
#endif
LDR X1, [ X0 ]
CMP X1, # 0
B.EQ Exit_IRQ_No_Context_Switch
/* Reset ullPortYieldRequired to 0. */
MOV X2, # 0
STR X2, [ X0 ]
/* Restore volatile registers. */
LDP X4, X5, [ SP ], # 0x10 /* SPSR and ELR. */
MSR SPSR_EL1, X5
MSR ELR_EL1, X4
DSB SY
ISB SY
restorefloatregisters
restorefuncontextgpregs
/* Save the context of the current task and select a new task to run. */
portSAVE_CONTEXT
#if configNUMBER_OF_CORES > 1
MRS x0, mpidr_el1
AND x0, x0, 255
#endif
BL vTaskSwitchContext
portRESTORE_CONTEXT
Exit_IRQ_No_Context_Switch:
/* Restore volatile registers. */
LDP X4, X5, [ SP ], # 0x10 /* SPSR and ELR. */
MSR SPSR_EL1, X5
MSR ELR_EL1, X4
DSB SY
ISB SY
restorefloatregisters
restorefuncontextgpregs
ERET
/******************************************************************************
* If the application provides an implementation of vApplicationIRQHandler(),
* then it will get called directly without saving the FPU registers on
* interrupt entry, and this weak implementation of
* vApplicationIRQHandler() will not get called.
*
* If the application provides its own implementation of
* vApplicationFPUSafeIRQHandler() then this implementation of
* vApplicationIRQHandler() will be called, save the FPU registers, and then
* call vApplicationFPUSafeIRQHandler().
*
* Therefore, if the application writer wants FPU registers to be saved on
* interrupt entry their IRQ handler must be called
* vApplicationFPUSafeIRQHandler(), and if the application writer does not want
* FPU registers to be saved on interrupt entry their IRQ handler must be
* called vApplicationIRQHandler().
*****************************************************************************/
.align 8
.weak vApplicationIRQHandler
.type vApplicationIRQHandler, % function
vApplicationIRQHandler:
/* Save LR and FP on the stack. */
STP X29, X30, [ SP, # - 0x10 ] !
/* Save FPU registers (32 128-bits + 2 64-bits configuration and status registers). */
savefloatregisters
/* Call the C handler. */
BL vApplicationFPUSafeIRQHandler
/* Restore FPU registers. */
restorefloatregisters
/* Restore FP and LR. */
LDP X29, X30, [ SP ], # 0x10
RET
.align 8
#if ( configNUMBER_OF_CORES == 1 )
pxCurrentTCBsConst:.dword pxCurrentTCB
ullCriticalNestingsConst:.dword ullCriticalNesting
ullPortInterruptNestingsConst:.dword ullPortInterruptNesting
ullPortYieldRequiredConst:.dword ullPortYieldRequired
ullPortTaskHasFPUContextConst:.dword ullPortTaskHasFPUContext
#else
pxCurrentTCBsConst:.dword pxCurrentTCBs
ullCriticalNestingsConst:.dword ullCriticalNestings
ullPortInterruptNestingsConst:.dword ullPortInterruptNestings
ullPortYieldRequiredConst:.dword ullPortYieldRequired
ullPortTaskHasFPUContextConst:.dword ullPortTaskHasFPUContext
#endif /* if ( configNUMBER_OF_CORES == 1 ) */
ullMaxAPIPriorityMaskConst:.dword ullMaxAPIPriorityMask
vApplicationIRQHandlerConst:.word vApplicationIRQHandler
.end

View file

@ -0,0 +1,297 @@
/*
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
* 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
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/*-----------------------------------------------------------
* Port specific definitions.
*
* The settings in this file configure FreeRTOS correctly for the given hardware
* and compiler.
*
* These settings should not be altered.
*-----------------------------------------------------------
*/
/* Type definitions. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE size_t
#define portBASE_TYPE long
#if !defined(__ASSEMBLER__)
typedef portSTACK_TYPE StackType_t;
typedef portBASE_TYPE BaseType_t;
typedef uint64_t UBaseType_t;
typedef uint64_t TickType_t;
#define portMAX_DELAY ( ( TickType_t ) 0xffffffffffffffff )
#endif /* if !defined(__ASSEMBLER__) */
/* 64-bit tick type on a 64-bit architecture, so reads of the tick count do
* not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1
/*-----------------------------------------------------------*/
/* Hardware specifics. */
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 16
#define portPOINTER_SIZE_TYPE uint64_t
/*-----------------------------------------------------------*/
/* Task utilities. */
#if !defined(__ASSEMBLER__)
/* Called at the end of an ISR that can cause a context switch. */
#if ( configNUMBER_OF_CORES == 1 )
#define portEND_SWITCHING_ISR( xSwitchRequired ) \
{ \
extern uint64_t ullPortYieldRequired; \
\
if( xSwitchRequired != pdFALSE ) \
{ \
ullPortYieldRequired = pdTRUE; \
} \
}
#else
#define portEND_SWITCHING_ISR( xSwitchRequired ) \
{ \
extern uint64_t ullPortYieldRequired[ configNUMBER_OF_CORES ]; \
\
if( xSwitchRequired != pdFALSE ) \
{ \
ullPortYieldRequired[ portGET_CORE_ID() ] = pdTRUE; \
} \
}
#endif /* if ( configNUMBER_OF_CORES == 1 ) */
#endif /* if !defined(__ASSEMBLER__) */
/**
* @brief SVC numbers.
*/
#define portSVC_YIELD 105
#define portSVC_START_FIRST_TASK 106
#define portSVC_DISABLE_INTERRUPTS 107
#define portSVC_ENABLE_INTERRUPTS 108
#define portSVC_GET_CORE_ID 109
#define portSVC_MASK_ALL_INTERRUPTS 110
#define portSVC_UNMASK_ALL_INTERRUPTS 111
#define portSVC_UNMASK_INTERRUPTS 112
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
#define portYIELD() __asm volatile ( "SVC %0" : : "i" ( portSVC_YIELD ) : "memory" )
/*-----------------------------------------------------------
* Critical section control
*----------------------------------------------------------*/
#if !defined(__ASSEMBLER__)
extern UBaseType_t vTaskEnterCriticalFromISR( void );
extern void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus );
extern UBaseType_t uxPortSetInterruptMask( void );
extern UBaseType_t uxPortSetInterruptMaskFromISR( void );
extern void vPortClearInterruptMask( UBaseType_t uxNewMaskValue );
extern void vPortClearInterruptMaskFromISR( UBaseType_t uxNewMaskValue );
extern void vInterruptCore( uint32_t ulInterruptID, uint32_t ulCoreID );
#endif /* if !defined(__ASSEMBLER__) */
/* Use SVC so this is safe from EL0. EL1 sites in the port use direct MSR. */\
#define portDISABLE_INTERRUPTS() __asm volatile ( "SVC %0" : : "i" ( portSVC_DISABLE_INTERRUPTS ) : "memory" )
#define portENABLE_INTERRUPTS() __asm volatile ( "SVC %0" : : "i" ( portSVC_ENABLE_INTERRUPTS ) : "memory" )
/* In all GICs 255 can be written to the priority mask register to unmask all
* (but the lowest) interrupt priority. */
#define portUNMASK_VALUE ( 0xFFUL )
#if !defined(__ASSEMBLER__)
/* These macros do not globally disable/enable interrupts. They do mask off
* interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
#if ( configNUMBER_OF_CORES == 1 )
extern void vPortEnterCritical( void );
extern void vPortExitCritical( void );
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
#else
#define portENTER_CRITICAL() vTaskEnterCritical()
#define portEXIT_CRITICAL() vTaskExitCritical()
#endif
#define portSET_INTERRUPT_MASK_FROM_ISR() uxPortSetInterruptMaskFromISR()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortClearInterruptMaskFromISR( x )
#define portENTER_CRITICAL_FROM_ISR() vTaskEnterCriticalFromISR()
#define portEXIT_CRITICAL_FROM_ISR( x ) vTaskExitCriticalFromISR( x )
#endif /* if !defined(__ASSEMBLER__) */
/*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. These are
* not required for this port but included in case common demo code that uses these
* macros is used. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
#if !defined(__ASSEMBLER__)
/* Prototype of the FreeRTOS tick handler. This must be installed as the
* handler for whichever peripheral is used to generate the RTOS tick. */
void FreeRTOS_Tick_Handler( void );
#endif /* if !defined(__ASSEMBLER__) */
#define portTASK_NO_FPU_CONTEXT_BY_DEFAULT ( 1U )
#define portTASK_HAVE_FPU_CONTEXT_BY_DEFAULT ( 2U )
/* If configUSE_TASK_FPU_SUPPORT is set to portTASK_NO_FPU_CONTEXT_BY_DEFAULT (1U)
* (or left undefined) then tasks are created without an FPU context and
* must call vPortTaskUsesFPU() to give themselves an FPU context before
* using any FPU instructions. If configUSE_TASK_FPU_SUPPORT is set to
* portTASK_HAVE_FPU_CONTEXT_BY_DEFAULT (2U) then all tasks will have an FPU context
* by default. */
#if ( configUSE_TASK_FPU_SUPPORT == portTASK_NO_FPU_CONTEXT_BY_DEFAULT )
void vPortTaskUsesFPU( void );
#else
/* Each task has an FPU context already, so define this function away to
* nothing to prevent it from being called accidentally. */
#define vPortTaskUsesFPU()
#endif
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
#define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
#define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL )
/* Architecture specific optimisations. */
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Store/clear the ready priorities in a bit map. */
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
/*-----------------------------------------------------------*/
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __builtin_clz( uxReadyPriorities ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
#if ( configASSERT_DEFINED == 1 )
void vPortValidateInterruptPriority( void );
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
#endif /* configASSERT */
#define portNOP() __asm volatile ( "NOP" )
#define portINLINE __inline
/* The number of bits to shift for an interrupt priority is dependent on the
* number of bits implemented by the interrupt controller. */
#if configUNIQUE_INTERRUPT_PRIORITIES == 16
#define portPRIORITY_SHIFT 4
#define portMAX_BINARY_POINT_VALUE 3
#elif configUNIQUE_INTERRUPT_PRIORITIES == 32
#define portPRIORITY_SHIFT 3
#define portMAX_BINARY_POINT_VALUE 2
#elif configUNIQUE_INTERRUPT_PRIORITIES == 64
#define portPRIORITY_SHIFT 2
#define portMAX_BINARY_POINT_VALUE 1
#elif configUNIQUE_INTERRUPT_PRIORITIES == 128
#define portPRIORITY_SHIFT 1
#define portMAX_BINARY_POINT_VALUE 0
#elif configUNIQUE_INTERRUPT_PRIORITIES == 256
#define portPRIORITY_SHIFT 0
#define portMAX_BINARY_POINT_VALUE 0
#else /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */
#error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware
#endif /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */
#define portINTERRUPT_PRIORITY_REGISTER_OFFSET ( 0x400U )
#define portYIELD_CORE_INT_ID ( 0x0U )
#if ( configNUMBER_OF_CORES > 1 )
#if !defined(__ASSEMBLER__)
typedef enum
{
eIsrLock = 0,
eTaskLock,
eLockCount
} ePortRTOSLock;
extern volatile uint64_t ullCriticalNestings[ configNUMBER_OF_CORES ];
extern void vPortRecursiveLock( BaseType_t xCoreID,
ePortRTOSLock eLockNum,
BaseType_t uxAcquire );
extern BaseType_t xPortGetCoreID( void );
#endif /* if !defined(__ASSEMBLER__) */
#define portSET_INTERRUPT_MASK() uxPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK( x ) vPortClearInterruptMask( x )
#define portMAX_CORE_COUNT configNUMBER_OF_CORES
#define portGET_CORE_ID() xPortGetCoreID()
/* Use SGI 0 as the yield core interrupt. */
#define portYIELD_CORE( xCoreID ) vInterruptCore( portYIELD_CORE_INT_ID, ( uint32_t ) xCoreID )
#define portRELEASE_ISR_LOCK( xCoreID ) vPortRecursiveLock( ( xCoreID ), eIsrLock, pdFALSE )
#define portGET_ISR_LOCK( xCoreID ) vPortRecursiveLock( ( xCoreID ), eIsrLock, pdTRUE )
#define portRELEASE_TASK_LOCK( xCoreID ) vPortRecursiveLock( ( xCoreID ), eTaskLock, pdFALSE )
#define portGET_TASK_LOCK( xCoreID ) vPortRecursiveLock( ( xCoreID ), eTaskLock, pdTRUE )
#define portGET_CRITICAL_NESTING_COUNT( xCoreID ) ( ullCriticalNestings[ ( xCoreID ) ] )
#define portSET_CRITICAL_NESTING_COUNT( xCoreID, x ) ( ullCriticalNestings[ ( xCoreID ) ] = ( x ) )
#define portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID ) ( ullCriticalNestings[ ( xCoreID ) ]++ )
#define portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID ) ( ullCriticalNestings[ ( xCoreID ) ]-- )
#endif /* configNUMBER_OF_CORES > 1 */
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* PORTMACRO_H */

View file

@ -30,7 +30,7 @@
.arm .arm
.syntax unified .syntax unified
.section freertos_system_calls .section freertos_system_calls, "ax"
#define FREERTOS_ASSEMBLY #define FREERTOS_ASSEMBLY
#include "FreeRTOSConfig.h" #include "FreeRTOSConfig.h"

View file

@ -28,7 +28,7 @@
.arm .arm
.syntax unified .syntax unified
.section privileged_functions .section privileged_functions, "ax"
#define FREERTOS_ASSEMBLY #define FREERTOS_ASSEMBLY
#include "portmacro_asm.h" #include "portmacro_asm.h"

View file

@ -90,7 +90,7 @@ void vPortSetupTimerInterrupt( void ) __attribute__( ( weak ) );
uint64_t ullNextTime = 0ULL; uint64_t ullNextTime = 0ULL;
const uint64_t * pullNextTime = &ullNextTime; const uint64_t * pullNextTime = &ullNextTime;
const size_t uxTimerIncrementsForOneTick = ( size_t ) ( ( configCPU_CLOCK_HZ ) / ( configTICK_RATE_HZ ) ); /* Assumes increment won't go over 32-bits. */ const size_t uxTimerIncrementsForOneTick = ( size_t ) ( ( configCPU_CLOCK_HZ ) / ( configTICK_RATE_HZ ) ); /* Assumes increment won't go over 32-bits. */
uint64_t const ullMachineTimerCompareRegisterBase = configMTIMECMP_BASE_ADDRESS; UBaseType_t const ullMachineTimerCompareRegisterBase = configMTIMECMP_BASE_ADDRESS;
volatile uint64_t * pullMachineTimerCompareRegister = NULL; volatile uint64_t * pullMachineTimerCompareRegister = NULL;
/* Holds the critical nesting value - deliberately non-zero at start up to /* Holds the critical nesting value - deliberately non-zero at start up to

View file

@ -162,7 +162,6 @@ definitions. */
* where the global and thread pointers are currently assumed to be constant so * where the global and thread pointers are currently assumed to be constant so
* are not saved: * are not saved:
* *
* mstatus
* xCriticalNesting * xCriticalNesting
* x31 * x31
* x30 * x30
@ -192,18 +191,13 @@ definitions. */
* x6 * x6
* x5 * x5
* portTASK_RETURN_ADDRESS * portTASK_RETURN_ADDRESS
* [FPU registers (when enabled/available) go here]
* [VPU registers (when enabled/available) go here]
* mstatus
* [chip specific registers go here] * [chip specific registers go here]
* pxCode * pxCode
*/ */
pxPortInitialiseStack: pxPortInitialiseStack:
csrr t0, mstatus /* Obtain current mstatus value. */
andi t0, t0, ~0x8 /* Ensure interrupts are disabled when the stack is restored within an ISR. Required when a task is created after the schedulre has been started, otherwise interrupts would be disabled anyway. */
addi t1, x0, 0x188 /* Generate the value 0x1880, which are the MPIE and MPP bits to set in mstatus. */
slli t1, t1, 4
or t0, t0, t1 /* Set MPIE and MPP bits in mstatus value. */
addi a0, a0, -portWORD_SIZE
store_x t0, 0(a0) /* mstatus onto the stack. */
addi a0, a0, -portWORD_SIZE /* Space for critical nesting count. */ addi a0, a0, -portWORD_SIZE /* Space for critical nesting count. */
store_x x0, 0(a0) /* Critical nesting count starts at 0 for every task. */ store_x x0, 0(a0) /* Critical nesting count starts at 0 for every task. */
@ -212,10 +206,37 @@ pxPortInitialiseStack:
#else #else
addi a0, a0, -(22 * portWORD_SIZE) /* Space for registers x10-x31. */ addi a0, a0, -(22 * portWORD_SIZE) /* Space for registers x10-x31. */
#endif #endif
store_x a2, 0(a0) /* Task parameters (pvParameters parameter) goes into register X10/a0 on the stack. */ store_x a2, 0(a0) /* Task parameters (pvParameters parameter) goes into register x10/a0 on the stack. */
addi a0, a0, -(6 * portWORD_SIZE) /* Space for registers x5-x9 + taskReturnAddress. */
addi a0, a0, -(6 * portWORD_SIZE) /* Space for registers x5-x9 + taskReturnAddress (register x1). */
load_x t0, xTaskReturnAddress load_x t0, xTaskReturnAddress
store_x t0, 0(a0) /* Return address onto the stack. */ store_x t0, 0(a0) /* Return address onto the stack. */
csrr t0, mstatus /* Obtain current mstatus value. */
andi t0, t0, ~0x8 /* Ensure interrupts are disabled when the stack is restored within an ISR. Required when a task is created after the scheduler has been started, otherwise interrupts would be disabled anyway. */
addi t1, x0, 0x188 /* Generate the value 0x1880, which are the MPIE=1 and MPP=M_Mode in mstatus. */
slli t1, t1, 4
or t0, t0, t1 /* Set MPIE and MPP bits in mstatus value. */
#if( configENABLE_FPU == 1 )
/* Mark the FPU as clean in the mstatus value. */
li t1, ~MSTATUS_FS_MASK
and t0, t0, t1
li t1, MSTATUS_FS_CLEAN
or t0, t0, t1
#endif
#if( configENABLE_VPU == 1 )
/* Mark the VPU as clean in the mstatus value. */
li t1, ~MSTATUS_VS_MASK
and t0, t0, t1
li t1, MSTATUS_VS_CLEAN
or t0, t0, t1
#endif
addi a0, a0, -portWORD_SIZE
store_x t0, 0(a0) /* mstatus onto the stack. */
addi t0, x0, portasmADDITIONAL_CONTEXT_SIZE /* The number of chip specific additional registers. */ addi t0, x0, portasmADDITIONAL_CONTEXT_SIZE /* The number of chip specific additional registers. */
chip_specific_stack_frame: /* First add any chip specific registers to the stack frame being created. */ chip_specific_stack_frame: /* First add any chip specific registers to the stack frame being created. */
beq t0, x0, 1f /* No more chip specific registers to save. */ beq t0, x0, 1f /* No more chip specific registers to save. */
@ -224,6 +245,7 @@ chip_specific_stack_frame: /* First add any chip specific registers
addi t0, t0, -1 /* Decrement the count of chip specific registers remaining. */ addi t0, t0, -1 /* Decrement the count of chip specific registers remaining. */
j chip_specific_stack_frame /* Until no more chip specific registers. */ j chip_specific_stack_frame /* Until no more chip specific registers. */
1: 1:
addi a0, a0, -portWORD_SIZE addi a0, a0, -portWORD_SIZE
store_x a1, 0(a0) /* mret value (pxCode parameter) onto the stack. */ store_x a1, 0(a0) /* mret value (pxCode parameter) onto the stack. */
ret ret
@ -237,44 +259,44 @@ xPortStartFirstTask:
portasmRESTORE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */ portasmRESTORE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */
load_x x7, 4 * portWORD_SIZE( sp ) /* t2 */ load_x x5, 1 * portWORD_SIZE( sp ) /* Initial mstatus into x5 (t0). */
load_x x8, 5 * portWORD_SIZE( sp ) /* s0/fp */ addi x5, x5, 0x08 /* Set MIE bit so the first task starts with interrupts enabled - required as returns with ret not eret. */
load_x x9, 6 * portWORD_SIZE( sp ) /* s1 */ csrw mstatus, x5 /* Interrupts enabled from here! */
load_x x10, 7 * portWORD_SIZE( sp ) /* a0 */
load_x x11, 8 * portWORD_SIZE( sp ) /* a1 */ load_x x7, 5 * portWORD_SIZE( sp ) /* t2 */
load_x x12, 9 * portWORD_SIZE( sp ) /* a2 */ load_x x8, 6 * portWORD_SIZE( sp ) /* s0/fp */
load_x x13, 10 * portWORD_SIZE( sp ) /* a3 */ load_x x9, 7 * portWORD_SIZE( sp ) /* s1 */
load_x x14, 11 * portWORD_SIZE( sp ) /* a4 */ load_x x10, 8 * portWORD_SIZE( sp ) /* a0 */
load_x x15, 12 * portWORD_SIZE( sp ) /* a5 */ load_x x11, 9 * portWORD_SIZE( sp ) /* a1 */
load_x x12, 10 * portWORD_SIZE( sp ) /* a2 */
load_x x13, 11 * portWORD_SIZE( sp ) /* a3 */
load_x x14, 12 * portWORD_SIZE( sp ) /* a4 */
load_x x15, 13 * portWORD_SIZE( sp ) /* a5 */
#ifndef __riscv_32e #ifndef __riscv_32e
load_x x16, 13 * portWORD_SIZE( sp ) /* a6 */ load_x x16, 14 * portWORD_SIZE( sp ) /* a6 */
load_x x17, 14 * portWORD_SIZE( sp ) /* a7 */ load_x x17, 15 * portWORD_SIZE( sp ) /* a7 */
load_x x18, 15 * portWORD_SIZE( sp ) /* s2 */ load_x x18, 16 * portWORD_SIZE( sp ) /* s2 */
load_x x19, 16 * portWORD_SIZE( sp ) /* s3 */ load_x x19, 17 * portWORD_SIZE( sp ) /* s3 */
load_x x20, 17 * portWORD_SIZE( sp ) /* s4 */ load_x x20, 18 * portWORD_SIZE( sp ) /* s4 */
load_x x21, 18 * portWORD_SIZE( sp ) /* s5 */ load_x x21, 19 * portWORD_SIZE( sp ) /* s5 */
load_x x22, 19 * portWORD_SIZE( sp ) /* s6 */ load_x x22, 20 * portWORD_SIZE( sp ) /* s6 */
load_x x23, 20 * portWORD_SIZE( sp ) /* s7 */ load_x x23, 21 * portWORD_SIZE( sp ) /* s7 */
load_x x24, 21 * portWORD_SIZE( sp ) /* s8 */ load_x x24, 22 * portWORD_SIZE( sp ) /* s8 */
load_x x25, 22 * portWORD_SIZE( sp ) /* s9 */ load_x x25, 23 * portWORD_SIZE( sp ) /* s9 */
load_x x26, 23 * portWORD_SIZE( sp ) /* s10 */ load_x x26, 24 * portWORD_SIZE( sp ) /* s10 */
load_x x27, 24 * portWORD_SIZE( sp ) /* s11 */ load_x x27, 25 * portWORD_SIZE( sp ) /* s11 */
load_x x28, 25 * portWORD_SIZE( sp ) /* t3 */ load_x x28, 26 * portWORD_SIZE( sp ) /* t3 */
load_x x29, 26 * portWORD_SIZE( sp ) /* t4 */ load_x x29, 27 * portWORD_SIZE( sp ) /* t4 */
load_x x30, 27 * portWORD_SIZE( sp ) /* t5 */ load_x x30, 28 * portWORD_SIZE( sp ) /* t5 */
load_x x31, 28 * portWORD_SIZE( sp ) /* t6 */ load_x x31, 29 * portWORD_SIZE( sp ) /* t6 */
#endif #endif
load_x x5, portCRITICAL_NESTING_OFFSET * portWORD_SIZE( sp ) /* Obtain xCriticalNesting value for this task from task's stack. */ load_x x5, portCRITICAL_NESTING_OFFSET * portWORD_SIZE( sp ) /* Obtain xCriticalNesting value for this task from task's stack. */
load_x x6, pxCriticalNesting /* Load the address of xCriticalNesting into x6. */ load_x x6, pxCriticalNesting /* Load the address of xCriticalNesting into x6. */
store_x x5, 0( x6 ) /* Restore the critical nesting value for this task. */ store_x x5, 0( x6 ) /* Restore the critical nesting value for this task. */
load_x x5, portMSTATUS_OFFSET * portWORD_SIZE( sp ) /* Initial mstatus into x5 (t0). */ load_x x5, 3 * portWORD_SIZE( sp ) /* Initial x5 (t0) value. */
addi x5, x5, 0x08 /* Set MIE bit so the first task starts with interrupts enabled - required as returns with ret not eret. */ load_x x6, 4 * portWORD_SIZE( sp ) /* Initial x6 (t1) value. */
csrrw x0, mstatus, x5 /* Interrupts enabled from here! */
load_x x5, 2 * portWORD_SIZE( sp ) /* Initial x5 (t0) value. */
load_x x6, 3 * portWORD_SIZE( sp ) /* Initial x6 (t1) value. */
addi sp, sp, portCONTEXT_SIZE addi sp, sp, portCONTEXT_SIZE
ret ret

View file

@ -29,6 +29,14 @@
#ifndef PORTCONTEXT_H #ifndef PORTCONTEXT_H
#define PORTCONTEXT_H #define PORTCONTEXT_H
#ifndef configENABLE_FPU
#define configENABLE_FPU 0
#endif
#ifndef configENABLE_VPU
#define configENABLE_VPU 0
#endif
#if __riscv_xlen == 64 #if __riscv_xlen == 64
#define portWORD_SIZE 8 #define portWORD_SIZE 8
#define store_x sd #define store_x sd
@ -50,65 +58,311 @@
* notes at the top of portASM.S file. */ * notes at the top of portASM.S file. */
#ifdef __riscv_32e #ifdef __riscv_32e
#define portCONTEXT_SIZE ( 15 * portWORD_SIZE ) #define portCONTEXT_SIZE ( 15 * portWORD_SIZE )
#define portCRITICAL_NESTING_OFFSET 13 #define portCRITICAL_NESTING_OFFSET 14
#define portMSTATUS_OFFSET 14
#else #else
#define portCONTEXT_SIZE ( 31 * portWORD_SIZE ) #define portCONTEXT_SIZE ( 31 * portWORD_SIZE )
#define portCRITICAL_NESTING_OFFSET 29 #define portCRITICAL_NESTING_OFFSET 30
#define portMSTATUS_OFFSET 30
#endif #endif
#if ( configENABLE_FPU == 1 )
/* Bit [14:13] in the mstatus encode the status of FPU state which is one of
* the following values:
* 1. Value: 0, Meaning: Off.
* 2. Value: 1, Meaning: Initial.
* 3. Value: 2, Meaning: Clean.
* 4. Value: 3, Meaning: Dirty.
*/
#define MSTATUS_FS_MASK 0x6000
#define MSTATUS_FS_INITIAL 0x2000
#define MSTATUS_FS_CLEAN 0x4000
#define MSTATUS_FS_DIRTY 0x6000
#define MSTATUS_FS_OFFSET 13
#ifdef __riscv_fdiv
#if __riscv_flen == 32
#define load_f flw
#define store_f fsw
#elif __riscv_flen == 64
#define load_f fld
#define store_f fsd
#else
#error Assembler did not define __riscv_flen
#endif
#define portFPU_REG_SIZE ( __riscv_flen / 8 )
#define portFPU_REG_COUNT 33 /* 32 Floating point registers plus one CSR. */
#define portFPU_REG_OFFSET( regIndex ) ( ( 2 * portWORD_SIZE ) + ( regIndex * portFPU_REG_SIZE ) )
#define portFPU_CONTEXT_SIZE ( portFPU_REG_SIZE * portFPU_REG_COUNT )
#else
#error configENABLE_FPU must not be set to 1 if the hardware does not have FPU
#endif
#endif
#if ( configENABLE_VPU == 1 )
/* Bit [10:9] in the mstatus encode the status of VPU state which is one of
* the following values:
* 1. Value: 0, Meaning: Off.
* 2. Value: 1, Meaning: Initial.
* 3. Value: 2, Meaning: Clean.
* 4. Value: 3, Meaning: Dirty.
*/
#define MSTATUS_VS_MASK 0x600
#define MSTATUS_VS_INITIAL 0x200
#define MSTATUS_VS_CLEAN 0x400
#define MSTATUS_VS_DIRTY 0x600
#define MSTATUS_VS_OFFSET 9
#ifndef __riscv_vector
#error configENABLE_VPU must not be set to 1 if the hardware does not have VPU
#endif
#endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
.extern pxCurrentTCB .extern pxCurrentTCB
.extern xISRStackTop .extern xISRStackTop
.extern xCriticalNesting .extern xCriticalNesting
.extern pxCriticalNesting .extern pxCriticalNesting
/*-----------------------------------------------------------*/
.macro portcontexSAVE_FPU_CONTEXT
addi sp, sp, -( portFPU_CONTEXT_SIZE )
/* Store the FPU registers. */
store_f f0, portFPU_REG_OFFSET( 0 )( sp )
store_f f1, portFPU_REG_OFFSET( 1 )( sp )
store_f f2, portFPU_REG_OFFSET( 2 )( sp )
store_f f3, portFPU_REG_OFFSET( 3 )( sp )
store_f f4, portFPU_REG_OFFSET( 4 )( sp )
store_f f5, portFPU_REG_OFFSET( 5 )( sp )
store_f f6, portFPU_REG_OFFSET( 6 )( sp )
store_f f7, portFPU_REG_OFFSET( 7 )( sp )
store_f f8, portFPU_REG_OFFSET( 8 )( sp )
store_f f9, portFPU_REG_OFFSET( 9 )( sp )
store_f f10, portFPU_REG_OFFSET( 10 )( sp )
store_f f11, portFPU_REG_OFFSET( 11 )( sp )
store_f f12, portFPU_REG_OFFSET( 12 )( sp )
store_f f13, portFPU_REG_OFFSET( 13 )( sp )
store_f f14, portFPU_REG_OFFSET( 14 )( sp )
store_f f15, portFPU_REG_OFFSET( 15 )( sp )
store_f f16, portFPU_REG_OFFSET( 16 )( sp )
store_f f17, portFPU_REG_OFFSET( 17 )( sp )
store_f f18, portFPU_REG_OFFSET( 18 )( sp )
store_f f19, portFPU_REG_OFFSET( 19 )( sp )
store_f f20, portFPU_REG_OFFSET( 20 )( sp )
store_f f21, portFPU_REG_OFFSET( 21 )( sp )
store_f f22, portFPU_REG_OFFSET( 22 )( sp )
store_f f23, portFPU_REG_OFFSET( 23 )( sp )
store_f f24, portFPU_REG_OFFSET( 24 )( sp )
store_f f25, portFPU_REG_OFFSET( 25 )( sp )
store_f f26, portFPU_REG_OFFSET( 26 )( sp )
store_f f27, portFPU_REG_OFFSET( 27 )( sp )
store_f f28, portFPU_REG_OFFSET( 28 )( sp )
store_f f29, portFPU_REG_OFFSET( 29 )( sp )
store_f f30, portFPU_REG_OFFSET( 30 )( sp )
store_f f31, portFPU_REG_OFFSET( 31 )( sp )
csrr t0, fcsr
store_x t0, portFPU_REG_OFFSET( 32 )( sp )
.endm
/*-----------------------------------------------------------*/
.macro portcontextRESTORE_FPU_CONTEXT
/* Restore the FPU registers. */
load_f f0, portFPU_REG_OFFSET( 0 )( sp )
load_f f1, portFPU_REG_OFFSET( 1 )( sp )
load_f f2, portFPU_REG_OFFSET( 2 )( sp )
load_f f3, portFPU_REG_OFFSET( 3 )( sp )
load_f f4, portFPU_REG_OFFSET( 4 )( sp )
load_f f5, portFPU_REG_OFFSET( 5 )( sp )
load_f f6, portFPU_REG_OFFSET( 6 )( sp )
load_f f7, portFPU_REG_OFFSET( 7 )( sp )
load_f f8, portFPU_REG_OFFSET( 8 )( sp )
load_f f9, portFPU_REG_OFFSET( 9 )( sp )
load_f f10, portFPU_REG_OFFSET( 10 )( sp )
load_f f11, portFPU_REG_OFFSET( 11 )( sp )
load_f f12, portFPU_REG_OFFSET( 12 )( sp )
load_f f13, portFPU_REG_OFFSET( 13 )( sp )
load_f f14, portFPU_REG_OFFSET( 14 )( sp )
load_f f15, portFPU_REG_OFFSET( 15 )( sp )
load_f f16, portFPU_REG_OFFSET( 16 )( sp )
load_f f17, portFPU_REG_OFFSET( 17 )( sp )
load_f f18, portFPU_REG_OFFSET( 18 )( sp )
load_f f19, portFPU_REG_OFFSET( 19 )( sp )
load_f f20, portFPU_REG_OFFSET( 20 )( sp )
load_f f21, portFPU_REG_OFFSET( 21 )( sp )
load_f f22, portFPU_REG_OFFSET( 22 )( sp )
load_f f23, portFPU_REG_OFFSET( 23 )( sp )
load_f f24, portFPU_REG_OFFSET( 24 )( sp )
load_f f25, portFPU_REG_OFFSET( 25 )( sp )
load_f f26, portFPU_REG_OFFSET( 26 )( sp )
load_f f27, portFPU_REG_OFFSET( 27 )( sp )
load_f f28, portFPU_REG_OFFSET( 28 )( sp )
load_f f29, portFPU_REG_OFFSET( 29 )( sp )
load_f f30, portFPU_REG_OFFSET( 30 )( sp )
load_f f31, portFPU_REG_OFFSET( 31 )( sp )
load_x t0, portFPU_REG_OFFSET( 32 )( sp )
csrw fcsr, t0
addi sp, sp, ( portFPU_CONTEXT_SIZE )
.endm
/*-----------------------------------------------------------*/
.macro portcontexSAVE_VPU_CONTEXT
/* Un-reserve the space reserved for mstatus and epc. */
add sp, sp, ( 2 * portWORD_SIZE )
csrr t0, vlenb /* t0 = vlenb. vlenb is the length of each vector register in bytes. */
slli t0, t0, 3 /* t0 = vlenb * 8. t0 now contains the space required to store 8 vector registers. */
neg t0, t0
/* Store the vector registers in group of 8. */
add sp, sp, t0
vs8r.v v24, (sp) /* Store v24-v31. */
add sp, sp, t0
vs8r.v v16, (sp) /* Store v16-v23. */
add sp, sp, t0
vs8r.v v8, (sp) /* Store v8-v15. */
add sp, sp, t0
vs8r.v v0, (sp) /* Store v0-v7. */
/* Store the VPU CSRs. */
addi sp, sp, -( 4 * portWORD_SIZE )
csrr t0, vstart
store_x t0, 0 * portWORD_SIZE( sp )
csrr t0, vcsr
store_x t0, 1 * portWORD_SIZE( sp )
csrr t0, vl
store_x t0, 2 * portWORD_SIZE( sp )
csrr t0, vtype
store_x t0, 3 * portWORD_SIZE( sp )
/* Re-reserve the space for mstatus and epc. */
add sp, sp, -( 2 * portWORD_SIZE )
.endm
/*-----------------------------------------------------------*/
.macro portcontextRESTORE_VPU_CONTEXT
/* Un-reserve the space reserved for mstatus and epc. */
add sp, sp, ( 2 * portWORD_SIZE )
/* Restore the VPU CSRs. */
load_x t0, 0 * portWORD_SIZE( sp )
csrw vstart, t0
load_x t0, 1 * portWORD_SIZE( sp )
csrw vcsr, t0
load_x t0, 2 * portWORD_SIZE( sp )
load_x t1, 3 * portWORD_SIZE( sp )
vsetvl x0, t0, t1 /* vlen and vtype can only be updated by using vset*vl* instructions. */
addi sp, sp, ( 4 * portWORD_SIZE )
csrr t0, vlenb /* t0 = vlenb. vlenb is the length of each vector register in bytes. */
slli t0, t0, 3 /* t0 = vlenb * 8. t0 now contains the space required to store 8 vector registers. */
/* Restore the vector registers. */
vl8r.v v0, (sp) /* Restore v0-v7. */
add sp, sp, t0
vl8r.v v8, (sp) /* Restore v8-v15. */
add sp, sp, t0
vl8r.v v16, (sp) /* Restore v16-v23. */
add sp, sp, t0
vl8r.v v24, (sp) /* Restore v23-v31. */
add sp, sp, t0
/* Re-reserve the space for mstatus and epc. */
add sp, sp, -( 2 * portWORD_SIZE )
.endm
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
.macro portcontextSAVE_CONTEXT_INTERNAL .macro portcontextSAVE_CONTEXT_INTERNAL
addi sp, sp, -portCONTEXT_SIZE addi sp, sp, -portCONTEXT_SIZE
store_x x1, 1 * portWORD_SIZE( sp ) store_x x1, 2 * portWORD_SIZE( sp )
store_x x5, 2 * portWORD_SIZE( sp ) store_x x5, 3 * portWORD_SIZE( sp )
store_x x6, 3 * portWORD_SIZE( sp ) store_x x6, 4 * portWORD_SIZE( sp )
store_x x7, 4 * portWORD_SIZE( sp ) store_x x7, 5 * portWORD_SIZE( sp )
store_x x8, 5 * portWORD_SIZE( sp ) store_x x8, 6 * portWORD_SIZE( sp )
store_x x9, 6 * portWORD_SIZE( sp ) store_x x9, 7 * portWORD_SIZE( sp )
store_x x10, 7 * portWORD_SIZE( sp ) store_x x10, 8 * portWORD_SIZE( sp )
store_x x11, 8 * portWORD_SIZE( sp ) store_x x11, 9 * portWORD_SIZE( sp )
store_x x12, 9 * portWORD_SIZE( sp ) store_x x12, 10 * portWORD_SIZE( sp )
store_x x13, 10 * portWORD_SIZE( sp ) store_x x13, 11 * portWORD_SIZE( sp )
store_x x14, 11 * portWORD_SIZE( sp ) store_x x14, 12 * portWORD_SIZE( sp )
store_x x15, 12 * portWORD_SIZE( sp ) store_x x15, 13 * portWORD_SIZE( sp )
#ifndef __riscv_32e #ifndef __riscv_32e
store_x x16, 13 * portWORD_SIZE( sp ) store_x x16, 14 * portWORD_SIZE( sp )
store_x x17, 14 * portWORD_SIZE( sp ) store_x x17, 15 * portWORD_SIZE( sp )
store_x x18, 15 * portWORD_SIZE( sp ) store_x x18, 16 * portWORD_SIZE( sp )
store_x x19, 16 * portWORD_SIZE( sp ) store_x x19, 17 * portWORD_SIZE( sp )
store_x x20, 17 * portWORD_SIZE( sp ) store_x x20, 18 * portWORD_SIZE( sp )
store_x x21, 18 * portWORD_SIZE( sp ) store_x x21, 19 * portWORD_SIZE( sp )
store_x x22, 19 * portWORD_SIZE( sp ) store_x x22, 20 * portWORD_SIZE( sp )
store_x x23, 20 * portWORD_SIZE( sp ) store_x x23, 21 * portWORD_SIZE( sp )
store_x x24, 21 * portWORD_SIZE( sp ) store_x x24, 22 * portWORD_SIZE( sp )
store_x x25, 22 * portWORD_SIZE( sp ) store_x x25, 23 * portWORD_SIZE( sp )
store_x x26, 23 * portWORD_SIZE( sp ) store_x x26, 24 * portWORD_SIZE( sp )
store_x x27, 24 * portWORD_SIZE( sp ) store_x x27, 25 * portWORD_SIZE( sp )
store_x x28, 25 * portWORD_SIZE( sp ) store_x x28, 26 * portWORD_SIZE( sp )
store_x x29, 26 * portWORD_SIZE( sp ) store_x x29, 27 * portWORD_SIZE( sp )
store_x x30, 27 * portWORD_SIZE( sp ) store_x x30, 28 * portWORD_SIZE( sp )
store_x x31, 28 * portWORD_SIZE( sp ) store_x x31, 29 * portWORD_SIZE( sp )
#endif /* ifndef __riscv_32e */ #endif /* ifndef __riscv_32e */
load_x t0, xCriticalNesting /* Load the value of xCriticalNesting into t0. */ load_x t0, xCriticalNesting /* Load the value of xCriticalNesting into t0. */
store_x t0, portCRITICAL_NESTING_OFFSET * portWORD_SIZE( sp ) /* Store the critical nesting value to the stack. */ store_x t0, portCRITICAL_NESTING_OFFSET * portWORD_SIZE( sp ) /* Store the critical nesting value to the stack. */
#if( configENABLE_FPU == 1 )
csrr t0, mstatus
srl t1, t0, MSTATUS_FS_OFFSET
andi t1, t1, 3
addi t2, x0, 3
bne t1, t2, 1f /* If FPU status is not dirty, do not save FPU registers. */
csrr t0, mstatus /* Required for MPIE bit. */ portcontexSAVE_FPU_CONTEXT
store_x t0, portMSTATUS_OFFSET * portWORD_SIZE( sp ) 1:
#endif
#if( configENABLE_VPU == 1 )
csrr t0, mstatus
srl t1, t0, MSTATUS_VS_OFFSET
andi t1, t1, 3
addi t2, x0, 3
bne t1, t2, 2f /* If VPU status is not dirty, do not save VPU registers. */
portcontexSAVE_VPU_CONTEXT
2:
#endif
csrr t0, mstatus
store_x t0, 1 * portWORD_SIZE( sp )
portasmSAVE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to save any registers unique to the RISC-V implementation. */ portasmSAVE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to save any registers unique to the RISC-V implementation. */
#if( configENABLE_FPU == 1 )
/* Mark the FPU as clean, if it was dirty and we saved FPU registers. */
srl t1, t0, MSTATUS_FS_OFFSET
andi t1, t1, 3
addi t2, x0, 3
bne t1, t2, 3f
li t1, ~MSTATUS_FS_MASK
and t0, t0, t1
li t1, MSTATUS_FS_CLEAN
or t0, t0, t1
csrw mstatus, t0
3:
#endif
#if( configENABLE_VPU == 1 )
/* Mark the VPU as clean, if it was dirty and we saved VPU registers. */
srl t1, t0, MSTATUS_VS_OFFSET
andi t1, t1, 3
addi t2, x0, 3
bne t1, t2, 4f
li t1, ~MSTATUS_VS_MASK
and t0, t0, t1
li t1, MSTATUS_VS_CLEAN
or t0, t0, t1
csrw mstatus, t0
4:
#endif
load_x t0, pxCurrentTCB /* Load pxCurrentTCB. */ load_x t0, pxCurrentTCB /* Load pxCurrentTCB. */
store_x sp, 0 ( t0 ) /* Write sp to first TCB member. */ store_x sp, 0 ( t0 ) /* Write sp to first TCB member. */
@ -145,43 +399,65 @@ csrw mepc, t0
/* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */ /* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */
portasmRESTORE_ADDITIONAL_REGISTERS portasmRESTORE_ADDITIONAL_REGISTERS
/* Load mstatus with the interrupt enable bits used by the task. */ /* Restore mstatus register. It is important to use t3 (and not t0) here as t3
load_x t0, portMSTATUS_OFFSET * portWORD_SIZE( sp ) * is not clobbered by portcontextRESTORE_VPU_CONTEXT and
csrw mstatus, t0 /* Required for MPIE bit. */ * portcontextRESTORE_FPU_CONTEXT. */
load_x t3, 1 * portWORD_SIZE( sp )
csrw mstatus, t3
#if( configENABLE_VPU == 1 )
srl t1, t3, MSTATUS_VS_OFFSET
andi t1, t1, 3
addi t2, x0, 3
bne t1, t2, 5f /* If VPU status is not dirty, do not restore VPU registers. */
portcontextRESTORE_VPU_CONTEXT
5:
#endif /* ifdef portasmSTORE_VPU_CONTEXT */
#if( configENABLE_FPU == 1 )
srl t1, t3, MSTATUS_FS_OFFSET
andi t1, t1, 3
addi t2, x0, 3
bne t1, t2, 6f /* If FPU status is not dirty, do not restore FPU registers. */
portcontextRESTORE_FPU_CONTEXT
6:
#endif /* ifdef portasmSTORE_FPU_CONTEXT */
load_x t0, portCRITICAL_NESTING_OFFSET * portWORD_SIZE( sp ) /* Obtain xCriticalNesting value for this task from task's stack. */ load_x t0, portCRITICAL_NESTING_OFFSET * portWORD_SIZE( sp ) /* Obtain xCriticalNesting value for this task from task's stack. */
load_x t1, pxCriticalNesting /* Load the address of xCriticalNesting into t1. */ load_x t1, pxCriticalNesting /* Load the address of xCriticalNesting into t1. */
store_x t0, 0 ( t1 ) /* Restore the critical nesting value for this task. */ store_x t0, 0 ( t1 ) /* Restore the critical nesting value for this task. */
load_x x1, 1 * portWORD_SIZE( sp ) load_x x1, 2 * portWORD_SIZE( sp )
load_x x5, 2 * portWORD_SIZE( sp ) load_x x5, 3 * portWORD_SIZE( sp )
load_x x6, 3 * portWORD_SIZE( sp ) load_x x6, 4 * portWORD_SIZE( sp )
load_x x7, 4 * portWORD_SIZE( sp ) load_x x7, 5 * portWORD_SIZE( sp )
load_x x8, 5 * portWORD_SIZE( sp ) load_x x8, 6 * portWORD_SIZE( sp )
load_x x9, 6 * portWORD_SIZE( sp ) load_x x9, 7 * portWORD_SIZE( sp )
load_x x10, 7 * portWORD_SIZE( sp ) load_x x10, 8 * portWORD_SIZE( sp )
load_x x11, 8 * portWORD_SIZE( sp ) load_x x11, 9 * portWORD_SIZE( sp )
load_x x12, 9 * portWORD_SIZE( sp ) load_x x12, 10 * portWORD_SIZE( sp )
load_x x13, 10 * portWORD_SIZE( sp ) load_x x13, 11 * portWORD_SIZE( sp )
load_x x14, 11 * portWORD_SIZE( sp ) load_x x14, 12 * portWORD_SIZE( sp )
load_x x15, 12 * portWORD_SIZE( sp ) load_x x15, 13 * portWORD_SIZE( sp )
#ifndef __riscv_32e #ifndef __riscv_32e
load_x x16, 13 * portWORD_SIZE( sp ) load_x x16, 14 * portWORD_SIZE( sp )
load_x x17, 14 * portWORD_SIZE( sp ) load_x x17, 15 * portWORD_SIZE( sp )
load_x x18, 15 * portWORD_SIZE( sp ) load_x x18, 16 * portWORD_SIZE( sp )
load_x x19, 16 * portWORD_SIZE( sp ) load_x x19, 17 * portWORD_SIZE( sp )
load_x x20, 17 * portWORD_SIZE( sp ) load_x x20, 18 * portWORD_SIZE( sp )
load_x x21, 18 * portWORD_SIZE( sp ) load_x x21, 19 * portWORD_SIZE( sp )
load_x x22, 19 * portWORD_SIZE( sp ) load_x x22, 20 * portWORD_SIZE( sp )
load_x x23, 20 * portWORD_SIZE( sp ) load_x x23, 21 * portWORD_SIZE( sp )
load_x x24, 21 * portWORD_SIZE( sp ) load_x x24, 22 * portWORD_SIZE( sp )
load_x x25, 22 * portWORD_SIZE( sp ) load_x x25, 23 * portWORD_SIZE( sp )
load_x x26, 23 * portWORD_SIZE( sp ) load_x x26, 24 * portWORD_SIZE( sp )
load_x x27, 24 * portWORD_SIZE( sp ) load_x x27, 25 * portWORD_SIZE( sp )
load_x x28, 25 * portWORD_SIZE( sp ) load_x x28, 26 * portWORD_SIZE( sp )
load_x x29, 26 * portWORD_SIZE( sp ) load_x x29, 27 * portWORD_SIZE( sp )
load_x x30, 27 * portWORD_SIZE( sp ) load_x x30, 28 * portWORD_SIZE( sp )
load_x x31, 28 * portWORD_SIZE( sp ) load_x x31, 29 * portWORD_SIZE( sp )
#endif /* ifndef __riscv_32e */ #endif /* ifndef __riscv_32e */
addi sp, sp, portCONTEXT_SIZE addi sp, sp, portCONTEXT_SIZE

View file

@ -1,7 +1,7 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates * Copyright 2024-2025 Arm Limited and/or its affiliates
* <open-source-office@arm.com> * <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
@ -230,7 +230,7 @@ typedef void ( * portISR_t )( void );
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
#endif /* portARMV8M_MINOR_VERSION >= 1 */ #endif /* portARMV8M_MINOR_VERSION >= 1 */
@ -241,9 +241,6 @@ typedef void ( * portISR_t )( void );
/* Enable MPU. */ /* Enable MPU. */
#define portMPU_ENABLE_BIT ( 1UL << 0UL ) #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 /* Extract first address of the MPU region as encoded in the
* RBAR (Region Base Address Register) value. */ * RBAR (Region Base Address Register) value. */
#define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \ #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@ -291,7 +288,7 @@ typedef void ( * portISR_t )( void );
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 ) #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF FD * FF FF FF FD
@ -308,7 +305,7 @@ typedef void ( * portISR_t )( void );
#define portINITIAL_EXC_RETURN ( 0xfffffffd ) #define portINITIAL_EXC_RETURN ( 0xfffffffd )
#else #else
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF BC * FF FF FF BC
@ -401,7 +398,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Extract MPU region's access permissions from the Region Base Address * @brief Extract MPU region's access permissions from the Region Base Address
* Register (RBAR) value. * Register (RBAR) value.
* *
@ -414,7 +411,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Setup the Memory Protection Unit (MPU). * @brief Setup the Memory Protection Unit (MPU).
*/ */
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
@ -422,7 +419,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
/** /**
* @brief Setup the Floating Point Unit (FPU). * @brief Setup the Floating Point Unit (FPU).
*/ */
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
@ -430,7 +427,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) ) #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
/** /**
* @brief Configures PACBTI features. * @brief Configures PACBTI features.
* *
* This function configures the Pointer Authentication, and Branch Target * This function configures the Pointer Authentication, and Branch Target
@ -491,7 +488,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Sets up the system call stack so that upon returning from * @brief Sets up the system call stack so that upon returning from
* SVC, the system call stack is used. * SVC, the system call stack is used.
* *
@ -507,7 +504,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
@ -516,7 +513,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( 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 * @brief Sets up the task stack so that upon returning from
* SVC, the task stack is used again. * SVC, the task stack is used again.
* *
@ -530,7 +527,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Checks whether or not the calling task is privileged. * @brief Checks whether or not the calling task is privileged.
* *
* @return pdTRUE if the calling task is privileged, pdFALSE otherwise. * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
@ -542,7 +539,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
@ -557,7 +554,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/** /**
* @brief Saved as part of the task context to indicate which context the * @brief Saved as part of the task context to indicate which context the
* task is using on the secure side. * task is using on the secure side.
*/ */
@ -579,18 +576,18 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configUSE_TICKLESS_IDLE == 1 ) #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; PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
/** /**
* @brief The maximum number of tick periods that can be suppressed is * @brief The maximum number of tick periods that can be suppressed is
* limited by the 24 bit resolution of the SysTick timer. * limited by the 24 bit resolution of the SysTick timer.
*/ */
PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
/** /**
* @brief Compensate for the CPU cycles that pass while the SysTick is * @brief Compensate for the CPU cycles that pass while the SysTick is
* stopped (low power functionality only). * stopped (low power functionality only).
*/ */
@ -925,12 +922,6 @@ static void prvTaskExitError( void )
/* The only permitted number of regions are 8 or 16. */ /* The only permitted number of regions are 8 or 16. */
configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 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 );
/* Check that the MPU is present. */
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
{
/* MAIR0 - Index 0. */ /* MAIR0 - Index 0. */
portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
/* MAIR0 - Index 1. */ /* MAIR0 - Index 1. */
@ -983,7 +974,6 @@ static void prvTaskExitError( void )
* regions have privileged access. */ * regions have privileged access. */
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
} }
}
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -1210,7 +1200,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ]; extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulSystemCallStack; uint32_t * pulSystemCallStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1246,12 +1236,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1261,20 +1255,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the system call stack for the stack frame. */ /* Make space on the system call stack for the stack frame. */
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize; pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulSystemCallStack[ i ] = pulTaskStack[ i ]; pulSystemCallStack[ i ] = pulTaskStack[ i ];
} }
@ -1310,7 +1304,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Remember the location where we should copy the stack frame when we exit from /* Remember the location where we should copy the stack frame when we exit from
* the system call. */ * the system call. */
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize; pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
/* Record if the hardware used padding to force the stack pointer /* Record if the hardware used padding to force the stack pointer
* to be double word aligned. */ * to be double word aligned. */
@ -1360,7 +1354,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern TaskHandle_t pxCurrentTCB; extern TaskHandle_t pxCurrentTCB;
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulTaskStack; uint32_t * pulTaskStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1392,12 +1386,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1407,20 +1405,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the task stack for the stack frame. */ /* Make space on the task stack for the stack frame. */
pulTaskStack = pulTaskStack - ulStackFrameSize; pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulTaskStack[ i ] = pulSystemCallStack[ i ]; pulTaskStack[ i ] = pulSystemCallStack[ i ];
} }

View file

@ -1,7 +1,7 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates * Copyright 2024-2025 Arm Limited and/or its affiliates
* <open-source-office@arm.com> * <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
@ -230,7 +230,7 @@ typedef void ( * portISR_t )( void );
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
#endif /* portARMV8M_MINOR_VERSION >= 1 */ #endif /* portARMV8M_MINOR_VERSION >= 1 */
@ -241,9 +241,6 @@ typedef void ( * portISR_t )( void );
/* Enable MPU. */ /* Enable MPU. */
#define portMPU_ENABLE_BIT ( 1UL << 0UL ) #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 /* Extract first address of the MPU region as encoded in the
* RBAR (Region Base Address Register) value. */ * RBAR (Region Base Address Register) value. */
#define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \ #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@ -291,7 +288,7 @@ typedef void ( * portISR_t )( void );
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 ) #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF FD * FF FF FF FD
@ -308,7 +305,7 @@ typedef void ( * portISR_t )( void );
#define portINITIAL_EXC_RETURN ( 0xfffffffd ) #define portINITIAL_EXC_RETURN ( 0xfffffffd )
#else #else
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF BC * FF FF FF BC
@ -401,7 +398,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Extract MPU region's access permissions from the Region Base Address * @brief Extract MPU region's access permissions from the Region Base Address
* Register (RBAR) value. * Register (RBAR) value.
* *
@ -414,7 +411,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Setup the Memory Protection Unit (MPU). * @brief Setup the Memory Protection Unit (MPU).
*/ */
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
@ -422,7 +419,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
/** /**
* @brief Setup the Floating Point Unit (FPU). * @brief Setup the Floating Point Unit (FPU).
*/ */
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
@ -430,7 +427,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) ) #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
/** /**
* @brief Configures PACBTI features. * @brief Configures PACBTI features.
* *
* This function configures the Pointer Authentication, and Branch Target * This function configures the Pointer Authentication, and Branch Target
@ -491,7 +488,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Sets up the system call stack so that upon returning from * @brief Sets up the system call stack so that upon returning from
* SVC, the system call stack is used. * SVC, the system call stack is used.
* *
@ -507,7 +504,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
@ -516,7 +513,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( 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 * @brief Sets up the task stack so that upon returning from
* SVC, the task stack is used again. * SVC, the task stack is used again.
* *
@ -530,7 +527,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Checks whether or not the calling task is privileged. * @brief Checks whether or not the calling task is privileged.
* *
* @return pdTRUE if the calling task is privileged, pdFALSE otherwise. * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
@ -542,7 +539,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
@ -557,7 +554,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/** /**
* @brief Saved as part of the task context to indicate which context the * @brief Saved as part of the task context to indicate which context the
* task is using on the secure side. * task is using on the secure side.
*/ */
@ -579,18 +576,18 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configUSE_TICKLESS_IDLE == 1 ) #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; PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
/** /**
* @brief The maximum number of tick periods that can be suppressed is * @brief The maximum number of tick periods that can be suppressed is
* limited by the 24 bit resolution of the SysTick timer. * limited by the 24 bit resolution of the SysTick timer.
*/ */
PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
/** /**
* @brief Compensate for the CPU cycles that pass while the SysTick is * @brief Compensate for the CPU cycles that pass while the SysTick is
* stopped (low power functionality only). * stopped (low power functionality only).
*/ */
@ -925,12 +922,6 @@ static void prvTaskExitError( void )
/* The only permitted number of regions are 8 or 16. */ /* The only permitted number of regions are 8 or 16. */
configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 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 );
/* Check that the MPU is present. */
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
{
/* MAIR0 - Index 0. */ /* MAIR0 - Index 0. */
portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
/* MAIR0 - Index 1. */ /* MAIR0 - Index 1. */
@ -983,7 +974,6 @@ static void prvTaskExitError( void )
* regions have privileged access. */ * regions have privileged access. */
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
} }
}
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -1210,7 +1200,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ]; extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulSystemCallStack; uint32_t * pulSystemCallStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1246,12 +1236,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1261,20 +1255,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the system call stack for the stack frame. */ /* Make space on the system call stack for the stack frame. */
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize; pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulSystemCallStack[ i ] = pulTaskStack[ i ]; pulSystemCallStack[ i ] = pulTaskStack[ i ];
} }
@ -1310,7 +1304,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Remember the location where we should copy the stack frame when we exit from /* Remember the location where we should copy the stack frame when we exit from
* the system call. */ * the system call. */
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize; pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
/* Record if the hardware used padding to force the stack pointer /* Record if the hardware used padding to force the stack pointer
* to be double word aligned. */ * to be double word aligned. */
@ -1360,7 +1354,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern TaskHandle_t pxCurrentTCB; extern TaskHandle_t pxCurrentTCB;
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulTaskStack; uint32_t * pulTaskStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1392,12 +1386,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1407,20 +1405,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the task stack for the stack frame. */ /* Make space on the task stack for the stack frame. */
pulTaskStack = pulTaskStack - ulStackFrameSize; pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulTaskStack[ i ] = pulSystemCallStack[ i ]; pulTaskStack[ i ] = pulSystemCallStack[ i ];
} }

View file

@ -1,7 +1,7 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates * Copyright 2024-2025 Arm Limited and/or its affiliates
* <open-source-office@arm.com> * <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
@ -230,7 +230,7 @@ typedef void ( * portISR_t )( void );
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
#endif /* portARMV8M_MINOR_VERSION >= 1 */ #endif /* portARMV8M_MINOR_VERSION >= 1 */
@ -241,9 +241,6 @@ typedef void ( * portISR_t )( void );
/* Enable MPU. */ /* Enable MPU. */
#define portMPU_ENABLE_BIT ( 1UL << 0UL ) #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 /* Extract first address of the MPU region as encoded in the
* RBAR (Region Base Address Register) value. */ * RBAR (Region Base Address Register) value. */
#define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \ #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@ -291,7 +288,7 @@ typedef void ( * portISR_t )( void );
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 ) #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF FD * FF FF FF FD
@ -308,7 +305,7 @@ typedef void ( * portISR_t )( void );
#define portINITIAL_EXC_RETURN ( 0xfffffffd ) #define portINITIAL_EXC_RETURN ( 0xfffffffd )
#else #else
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF BC * FF FF FF BC
@ -401,7 +398,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Extract MPU region's access permissions from the Region Base Address * @brief Extract MPU region's access permissions from the Region Base Address
* Register (RBAR) value. * Register (RBAR) value.
* *
@ -414,7 +411,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Setup the Memory Protection Unit (MPU). * @brief Setup the Memory Protection Unit (MPU).
*/ */
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
@ -422,7 +419,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
/** /**
* @brief Setup the Floating Point Unit (FPU). * @brief Setup the Floating Point Unit (FPU).
*/ */
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
@ -430,7 +427,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) ) #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
/** /**
* @brief Configures PACBTI features. * @brief Configures PACBTI features.
* *
* This function configures the Pointer Authentication, and Branch Target * This function configures the Pointer Authentication, and Branch Target
@ -491,7 +488,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Sets up the system call stack so that upon returning from * @brief Sets up the system call stack so that upon returning from
* SVC, the system call stack is used. * SVC, the system call stack is used.
* *
@ -507,7 +504,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
@ -516,7 +513,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( 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 * @brief Sets up the task stack so that upon returning from
* SVC, the task stack is used again. * SVC, the task stack is used again.
* *
@ -530,7 +527,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Checks whether or not the calling task is privileged. * @brief Checks whether or not the calling task is privileged.
* *
* @return pdTRUE if the calling task is privileged, pdFALSE otherwise. * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
@ -542,7 +539,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
@ -557,7 +554,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/** /**
* @brief Saved as part of the task context to indicate which context the * @brief Saved as part of the task context to indicate which context the
* task is using on the secure side. * task is using on the secure side.
*/ */
@ -579,18 +576,18 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configUSE_TICKLESS_IDLE == 1 ) #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; PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
/** /**
* @brief The maximum number of tick periods that can be suppressed is * @brief The maximum number of tick periods that can be suppressed is
* limited by the 24 bit resolution of the SysTick timer. * limited by the 24 bit resolution of the SysTick timer.
*/ */
PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
/** /**
* @brief Compensate for the CPU cycles that pass while the SysTick is * @brief Compensate for the CPU cycles that pass while the SysTick is
* stopped (low power functionality only). * stopped (low power functionality only).
*/ */
@ -925,12 +922,6 @@ static void prvTaskExitError( void )
/* The only permitted number of regions are 8 or 16. */ /* The only permitted number of regions are 8 or 16. */
configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 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 );
/* Check that the MPU is present. */
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
{
/* MAIR0 - Index 0. */ /* MAIR0 - Index 0. */
portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
/* MAIR0 - Index 1. */ /* MAIR0 - Index 1. */
@ -983,7 +974,6 @@ static void prvTaskExitError( void )
* regions have privileged access. */ * regions have privileged access. */
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
} }
}
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -1210,7 +1200,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ]; extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulSystemCallStack; uint32_t * pulSystemCallStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1246,12 +1236,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1261,20 +1255,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the system call stack for the stack frame. */ /* Make space on the system call stack for the stack frame. */
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize; pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulSystemCallStack[ i ] = pulTaskStack[ i ]; pulSystemCallStack[ i ] = pulTaskStack[ i ];
} }
@ -1310,7 +1304,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Remember the location where we should copy the stack frame when we exit from /* Remember the location where we should copy the stack frame when we exit from
* the system call. */ * the system call. */
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize; pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
/* Record if the hardware used padding to force the stack pointer /* Record if the hardware used padding to force the stack pointer
* to be double word aligned. */ * to be double word aligned. */
@ -1360,7 +1354,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern TaskHandle_t pxCurrentTCB; extern TaskHandle_t pxCurrentTCB;
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulTaskStack; uint32_t * pulTaskStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1392,12 +1386,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1407,20 +1405,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the task stack for the stack frame. */ /* Make space on the task stack for the stack frame. */
pulTaskStack = pulTaskStack - ulStackFrameSize; pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulTaskStack[ i ] = pulSystemCallStack[ i ]; pulTaskStack[ i ] = pulSystemCallStack[ i ];
} }

View file

@ -1,7 +1,7 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates * Copyright 2024-2025 Arm Limited and/or its affiliates
* <open-source-office@arm.com> * <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
@ -230,7 +230,7 @@ typedef void ( * portISR_t )( void );
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
#endif /* portARMV8M_MINOR_VERSION >= 1 */ #endif /* portARMV8M_MINOR_VERSION >= 1 */
@ -241,9 +241,6 @@ typedef void ( * portISR_t )( void );
/* Enable MPU. */ /* Enable MPU. */
#define portMPU_ENABLE_BIT ( 1UL << 0UL ) #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 /* Extract first address of the MPU region as encoded in the
* RBAR (Region Base Address Register) value. */ * RBAR (Region Base Address Register) value. */
#define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \ #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@ -291,7 +288,7 @@ typedef void ( * portISR_t )( void );
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 ) #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF FD * FF FF FF FD
@ -308,7 +305,7 @@ typedef void ( * portISR_t )( void );
#define portINITIAL_EXC_RETURN ( 0xfffffffd ) #define portINITIAL_EXC_RETURN ( 0xfffffffd )
#else #else
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF BC * FF FF FF BC
@ -401,7 +398,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Extract MPU region's access permissions from the Region Base Address * @brief Extract MPU region's access permissions from the Region Base Address
* Register (RBAR) value. * Register (RBAR) value.
* *
@ -414,7 +411,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Setup the Memory Protection Unit (MPU). * @brief Setup the Memory Protection Unit (MPU).
*/ */
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
@ -422,7 +419,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
/** /**
* @brief Setup the Floating Point Unit (FPU). * @brief Setup the Floating Point Unit (FPU).
*/ */
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
@ -430,7 +427,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) ) #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
/** /**
* @brief Configures PACBTI features. * @brief Configures PACBTI features.
* *
* This function configures the Pointer Authentication, and Branch Target * This function configures the Pointer Authentication, and Branch Target
@ -491,7 +488,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Sets up the system call stack so that upon returning from * @brief Sets up the system call stack so that upon returning from
* SVC, the system call stack is used. * SVC, the system call stack is used.
* *
@ -507,7 +504,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
@ -516,7 +513,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( 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 * @brief Sets up the task stack so that upon returning from
* SVC, the task stack is used again. * SVC, the task stack is used again.
* *
@ -530,7 +527,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Checks whether or not the calling task is privileged. * @brief Checks whether or not the calling task is privileged.
* *
* @return pdTRUE if the calling task is privileged, pdFALSE otherwise. * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
@ -542,7 +539,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
@ -557,7 +554,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/** /**
* @brief Saved as part of the task context to indicate which context the * @brief Saved as part of the task context to indicate which context the
* task is using on the secure side. * task is using on the secure side.
*/ */
@ -579,18 +576,18 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configUSE_TICKLESS_IDLE == 1 ) #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; PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
/** /**
* @brief The maximum number of tick periods that can be suppressed is * @brief The maximum number of tick periods that can be suppressed is
* limited by the 24 bit resolution of the SysTick timer. * limited by the 24 bit resolution of the SysTick timer.
*/ */
PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
/** /**
* @brief Compensate for the CPU cycles that pass while the SysTick is * @brief Compensate for the CPU cycles that pass while the SysTick is
* stopped (low power functionality only). * stopped (low power functionality only).
*/ */
@ -925,12 +922,6 @@ static void prvTaskExitError( void )
/* The only permitted number of regions are 8 or 16. */ /* The only permitted number of regions are 8 or 16. */
configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 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 );
/* Check that the MPU is present. */
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
{
/* MAIR0 - Index 0. */ /* MAIR0 - Index 0. */
portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
/* MAIR0 - Index 1. */ /* MAIR0 - Index 1. */
@ -983,7 +974,6 @@ static void prvTaskExitError( void )
* regions have privileged access. */ * regions have privileged access. */
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
} }
}
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -1210,7 +1200,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ]; extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulSystemCallStack; uint32_t * pulSystemCallStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1246,12 +1236,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1261,20 +1255,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the system call stack for the stack frame. */ /* Make space on the system call stack for the stack frame. */
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize; pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulSystemCallStack[ i ] = pulTaskStack[ i ]; pulSystemCallStack[ i ] = pulTaskStack[ i ];
} }
@ -1310,7 +1304,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Remember the location where we should copy the stack frame when we exit from /* Remember the location where we should copy the stack frame when we exit from
* the system call. */ * the system call. */
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize; pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
/* Record if the hardware used padding to force the stack pointer /* Record if the hardware used padding to force the stack pointer
* to be double word aligned. */ * to be double word aligned. */
@ -1360,7 +1354,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern TaskHandle_t pxCurrentTCB; extern TaskHandle_t pxCurrentTCB;
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulTaskStack; uint32_t * pulTaskStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1392,12 +1386,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1407,20 +1405,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the task stack for the stack frame. */ /* Make space on the task stack for the stack frame. */
pulTaskStack = pulTaskStack - ulStackFrameSize; pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulTaskStack[ i ] = pulSystemCallStack[ i ]; pulTaskStack[ i ] = pulSystemCallStack[ i ];
} }

View file

@ -1,7 +1,7 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates * Copyright 2024-2025 Arm Limited and/or its affiliates
* <open-source-office@arm.com> * <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
@ -230,7 +230,7 @@ typedef void ( * portISR_t )( void );
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
#endif /* portARMV8M_MINOR_VERSION >= 1 */ #endif /* portARMV8M_MINOR_VERSION >= 1 */
@ -241,9 +241,6 @@ typedef void ( * portISR_t )( void );
/* Enable MPU. */ /* Enable MPU. */
#define portMPU_ENABLE_BIT ( 1UL << 0UL ) #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 /* Extract first address of the MPU region as encoded in the
* RBAR (Region Base Address Register) value. */ * RBAR (Region Base Address Register) value. */
#define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \ #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@ -291,7 +288,7 @@ typedef void ( * portISR_t )( void );
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 ) #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF FD * FF FF FF FD
@ -308,7 +305,7 @@ typedef void ( * portISR_t )( void );
#define portINITIAL_EXC_RETURN ( 0xfffffffd ) #define portINITIAL_EXC_RETURN ( 0xfffffffd )
#else #else
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF BC * FF FF FF BC
@ -401,7 +398,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Extract MPU region's access permissions from the Region Base Address * @brief Extract MPU region's access permissions from the Region Base Address
* Register (RBAR) value. * Register (RBAR) value.
* *
@ -414,7 +411,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Setup the Memory Protection Unit (MPU). * @brief Setup the Memory Protection Unit (MPU).
*/ */
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
@ -422,7 +419,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
/** /**
* @brief Setup the Floating Point Unit (FPU). * @brief Setup the Floating Point Unit (FPU).
*/ */
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
@ -430,7 +427,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) ) #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
/** /**
* @brief Configures PACBTI features. * @brief Configures PACBTI features.
* *
* This function configures the Pointer Authentication, and Branch Target * This function configures the Pointer Authentication, and Branch Target
@ -491,7 +488,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Sets up the system call stack so that upon returning from * @brief Sets up the system call stack so that upon returning from
* SVC, the system call stack is used. * SVC, the system call stack is used.
* *
@ -507,7 +504,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
@ -516,7 +513,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( 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 * @brief Sets up the task stack so that upon returning from
* SVC, the task stack is used again. * SVC, the task stack is used again.
* *
@ -530,7 +527,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Checks whether or not the calling task is privileged. * @brief Checks whether or not the calling task is privileged.
* *
* @return pdTRUE if the calling task is privileged, pdFALSE otherwise. * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
@ -542,7 +539,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
@ -557,7 +554,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/** /**
* @brief Saved as part of the task context to indicate which context the * @brief Saved as part of the task context to indicate which context the
* task is using on the secure side. * task is using on the secure side.
*/ */
@ -579,18 +576,18 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configUSE_TICKLESS_IDLE == 1 ) #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; PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
/** /**
* @brief The maximum number of tick periods that can be suppressed is * @brief The maximum number of tick periods that can be suppressed is
* limited by the 24 bit resolution of the SysTick timer. * limited by the 24 bit resolution of the SysTick timer.
*/ */
PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
/** /**
* @brief Compensate for the CPU cycles that pass while the SysTick is * @brief Compensate for the CPU cycles that pass while the SysTick is
* stopped (low power functionality only). * stopped (low power functionality only).
*/ */
@ -925,12 +922,6 @@ static void prvTaskExitError( void )
/* The only permitted number of regions are 8 or 16. */ /* The only permitted number of regions are 8 or 16. */
configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 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 );
/* Check that the MPU is present. */
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
{
/* MAIR0 - Index 0. */ /* MAIR0 - Index 0. */
portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
/* MAIR0 - Index 1. */ /* MAIR0 - Index 1. */
@ -983,7 +974,6 @@ static void prvTaskExitError( void )
* regions have privileged access. */ * regions have privileged access. */
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
} }
}
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -1210,7 +1200,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ]; extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulSystemCallStack; uint32_t * pulSystemCallStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1246,12 +1236,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1261,20 +1255,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the system call stack for the stack frame. */ /* Make space on the system call stack for the stack frame. */
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize; pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulSystemCallStack[ i ] = pulTaskStack[ i ]; pulSystemCallStack[ i ] = pulTaskStack[ i ];
} }
@ -1310,7 +1304,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Remember the location where we should copy the stack frame when we exit from /* Remember the location where we should copy the stack frame when we exit from
* the system call. */ * the system call. */
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize; pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
/* Record if the hardware used padding to force the stack pointer /* Record if the hardware used padding to force the stack pointer
* to be double word aligned. */ * to be double word aligned. */
@ -1360,7 +1354,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern TaskHandle_t pxCurrentTCB; extern TaskHandle_t pxCurrentTCB;
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulTaskStack; uint32_t * pulTaskStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1392,12 +1386,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1407,20 +1405,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the task stack for the stack frame. */ /* Make space on the task stack for the stack frame. */
pulTaskStack = pulTaskStack - ulStackFrameSize; pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulTaskStack[ i ] = pulSystemCallStack[ i ]; pulTaskStack[ i ] = pulSystemCallStack[ i ];
} }

View file

@ -1,7 +1,7 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates * Copyright 2024-2025 Arm Limited and/or its affiliates
* <open-source-office@arm.com> * <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
@ -230,7 +230,7 @@ typedef void ( * portISR_t )( void );
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
#endif /* portARMV8M_MINOR_VERSION >= 1 */ #endif /* portARMV8M_MINOR_VERSION >= 1 */
@ -241,9 +241,6 @@ typedef void ( * portISR_t )( void );
/* Enable MPU. */ /* Enable MPU. */
#define portMPU_ENABLE_BIT ( 1UL << 0UL ) #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 /* Extract first address of the MPU region as encoded in the
* RBAR (Region Base Address Register) value. */ * RBAR (Region Base Address Register) value. */
#define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \ #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@ -291,7 +288,7 @@ typedef void ( * portISR_t )( void );
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 ) #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF FD * FF FF FF FD
@ -308,7 +305,7 @@ typedef void ( * portISR_t )( void );
#define portINITIAL_EXC_RETURN ( 0xfffffffd ) #define portINITIAL_EXC_RETURN ( 0xfffffffd )
#else #else
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF BC * FF FF FF BC
@ -401,7 +398,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Extract MPU region's access permissions from the Region Base Address * @brief Extract MPU region's access permissions from the Region Base Address
* Register (RBAR) value. * Register (RBAR) value.
* *
@ -414,7 +411,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Setup the Memory Protection Unit (MPU). * @brief Setup the Memory Protection Unit (MPU).
*/ */
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
@ -422,7 +419,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
/** /**
* @brief Setup the Floating Point Unit (FPU). * @brief Setup the Floating Point Unit (FPU).
*/ */
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
@ -430,7 +427,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) ) #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
/** /**
* @brief Configures PACBTI features. * @brief Configures PACBTI features.
* *
* This function configures the Pointer Authentication, and Branch Target * This function configures the Pointer Authentication, and Branch Target
@ -491,7 +488,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Sets up the system call stack so that upon returning from * @brief Sets up the system call stack so that upon returning from
* SVC, the system call stack is used. * SVC, the system call stack is used.
* *
@ -507,7 +504,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
@ -516,7 +513,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( 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 * @brief Sets up the task stack so that upon returning from
* SVC, the task stack is used again. * SVC, the task stack is used again.
* *
@ -530,7 +527,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Checks whether or not the calling task is privileged. * @brief Checks whether or not the calling task is privileged.
* *
* @return pdTRUE if the calling task is privileged, pdFALSE otherwise. * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
@ -542,7 +539,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
@ -557,7 +554,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/** /**
* @brief Saved as part of the task context to indicate which context the * @brief Saved as part of the task context to indicate which context the
* task is using on the secure side. * task is using on the secure side.
*/ */
@ -579,18 +576,18 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configUSE_TICKLESS_IDLE == 1 ) #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; PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
/** /**
* @brief The maximum number of tick periods that can be suppressed is * @brief The maximum number of tick periods that can be suppressed is
* limited by the 24 bit resolution of the SysTick timer. * limited by the 24 bit resolution of the SysTick timer.
*/ */
PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
/** /**
* @brief Compensate for the CPU cycles that pass while the SysTick is * @brief Compensate for the CPU cycles that pass while the SysTick is
* stopped (low power functionality only). * stopped (low power functionality only).
*/ */
@ -925,12 +922,6 @@ static void prvTaskExitError( void )
/* The only permitted number of regions are 8 or 16. */ /* The only permitted number of regions are 8 or 16. */
configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 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 );
/* Check that the MPU is present. */
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
{
/* MAIR0 - Index 0. */ /* MAIR0 - Index 0. */
portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
/* MAIR0 - Index 1. */ /* MAIR0 - Index 1. */
@ -983,7 +974,6 @@ static void prvTaskExitError( void )
* regions have privileged access. */ * regions have privileged access. */
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
} }
}
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -1210,7 +1200,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ]; extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulSystemCallStack; uint32_t * pulSystemCallStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1246,12 +1236,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1261,20 +1255,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the system call stack for the stack frame. */ /* Make space on the system call stack for the stack frame. */
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize; pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulSystemCallStack[ i ] = pulTaskStack[ i ]; pulSystemCallStack[ i ] = pulTaskStack[ i ];
} }
@ -1310,7 +1304,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Remember the location where we should copy the stack frame when we exit from /* Remember the location where we should copy the stack frame when we exit from
* the system call. */ * the system call. */
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize; pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
/* Record if the hardware used padding to force the stack pointer /* Record if the hardware used padding to force the stack pointer
* to be double word aligned. */ * to be double word aligned. */
@ -1360,7 +1354,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern TaskHandle_t pxCurrentTCB; extern TaskHandle_t pxCurrentTCB;
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulTaskStack; uint32_t * pulTaskStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1392,12 +1386,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1407,20 +1405,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the task stack for the stack frame. */ /* Make space on the task stack for the stack frame. */
pulTaskStack = pulTaskStack - ulStackFrameSize; pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulTaskStack[ i ] = pulSystemCallStack[ i ]; pulTaskStack[ i ] = pulSystemCallStack[ i ];
} }

View file

@ -1,6 +1,8 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * 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 * SPDX-License-Identifier: MIT
* *
@ -459,7 +461,7 @@ void vPortSVCHandler_C( uint32_t * pulParam ) /* PRIVILEGED_FUNCTION */
extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ]; extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulSystemCallStack; uint32_t * pulSystemCallStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
@ -494,10 +496,14 @@ void vPortSVCHandler_C( uint32_t * pulParam ) /* PRIVILEGED_FUNCTION */
{ {
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -507,14 +513,14 @@ void vPortSVCHandler_C( uint32_t * pulParam ) /* PRIVILEGED_FUNCTION */
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
/* Make space on the system call stack for the stack frame. */ /* Make space on the system call stack for the stack frame. */
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize; pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulSystemCallStack[ i ] = pulTaskStack[ i ]; pulSystemCallStack[ i ] = pulTaskStack[ i ];
} }
@ -532,7 +538,7 @@ void vPortSVCHandler_C( uint32_t * pulParam ) /* PRIVILEGED_FUNCTION */
/* Remember the location where we should copy the stack frame when we exit from /* Remember the location where we should copy the stack frame when we exit from
* the system call. */ * 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. /* Store the value of the Link Register before the SVC was raised.
* It contains the address of the caller of the System Call entry * It contains the address of the caller of the System Call entry
@ -586,7 +592,7 @@ void vPortSVCHandler_C( uint32_t * pulParam ) /* PRIVILEGED_FUNCTION */
extern TaskHandle_t pxCurrentTCB; extern TaskHandle_t pxCurrentTCB;
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulTaskStack; uint32_t * pulTaskStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
@ -617,10 +623,14 @@ void vPortSVCHandler_C( uint32_t * pulParam ) /* PRIVILEGED_FUNCTION */
{ {
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -630,14 +640,14 @@ void vPortSVCHandler_C( uint32_t * pulParam ) /* PRIVILEGED_FUNCTION */
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
/* Make space on the task stack for the stack frame. */ /* Make space on the task stack for the stack frame. */
pulTaskStack = pulTaskStack - ulStackFrameSize; pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulTaskStack[ i ] = pulSystemCallStack[ i ]; pulTaskStack[ i ] = pulSystemCallStack[ i ];
} }

View file

@ -1,7 +1,7 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates * Copyright 2024-2025 Arm Limited and/or its affiliates
* <open-source-office@arm.com> * <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
@ -230,7 +230,7 @@ typedef void ( * portISR_t )( void );
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
#endif /* portARMV8M_MINOR_VERSION >= 1 */ #endif /* portARMV8M_MINOR_VERSION >= 1 */
@ -241,9 +241,6 @@ typedef void ( * portISR_t )( void );
/* Enable MPU. */ /* Enable MPU. */
#define portMPU_ENABLE_BIT ( 1UL << 0UL ) #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 /* Extract first address of the MPU region as encoded in the
* RBAR (Region Base Address Register) value. */ * RBAR (Region Base Address Register) value. */
#define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \ #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@ -291,7 +288,7 @@ typedef void ( * portISR_t )( void );
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 ) #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF FD * FF FF FF FD
@ -308,7 +305,7 @@ typedef void ( * portISR_t )( void );
#define portINITIAL_EXC_RETURN ( 0xfffffffd ) #define portINITIAL_EXC_RETURN ( 0xfffffffd )
#else #else
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF BC * FF FF FF BC
@ -401,7 +398,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Extract MPU region's access permissions from the Region Base Address * @brief Extract MPU region's access permissions from the Region Base Address
* Register (RBAR) value. * Register (RBAR) value.
* *
@ -414,7 +411,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Setup the Memory Protection Unit (MPU). * @brief Setup the Memory Protection Unit (MPU).
*/ */
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
@ -422,7 +419,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
/** /**
* @brief Setup the Floating Point Unit (FPU). * @brief Setup the Floating Point Unit (FPU).
*/ */
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
@ -430,7 +427,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) ) #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
/** /**
* @brief Configures PACBTI features. * @brief Configures PACBTI features.
* *
* This function configures the Pointer Authentication, and Branch Target * This function configures the Pointer Authentication, and Branch Target
@ -491,7 +488,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Sets up the system call stack so that upon returning from * @brief Sets up the system call stack so that upon returning from
* SVC, the system call stack is used. * SVC, the system call stack is used.
* *
@ -507,7 +504,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
@ -516,7 +513,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( 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 * @brief Sets up the task stack so that upon returning from
* SVC, the task stack is used again. * SVC, the task stack is used again.
* *
@ -530,7 +527,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Checks whether or not the calling task is privileged. * @brief Checks whether or not the calling task is privileged.
* *
* @return pdTRUE if the calling task is privileged, pdFALSE otherwise. * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
@ -542,7 +539,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
@ -557,7 +554,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/** /**
* @brief Saved as part of the task context to indicate which context the * @brief Saved as part of the task context to indicate which context the
* task is using on the secure side. * task is using on the secure side.
*/ */
@ -579,18 +576,18 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configUSE_TICKLESS_IDLE == 1 ) #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; PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
/** /**
* @brief The maximum number of tick periods that can be suppressed is * @brief The maximum number of tick periods that can be suppressed is
* limited by the 24 bit resolution of the SysTick timer. * limited by the 24 bit resolution of the SysTick timer.
*/ */
PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
/** /**
* @brief Compensate for the CPU cycles that pass while the SysTick is * @brief Compensate for the CPU cycles that pass while the SysTick is
* stopped (low power functionality only). * stopped (low power functionality only).
*/ */
@ -925,12 +922,6 @@ static void prvTaskExitError( void )
/* The only permitted number of regions are 8 or 16. */ /* The only permitted number of regions are 8 or 16. */
configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 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 );
/* Check that the MPU is present. */
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
{
/* MAIR0 - Index 0. */ /* MAIR0 - Index 0. */
portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
/* MAIR0 - Index 1. */ /* MAIR0 - Index 1. */
@ -983,7 +974,6 @@ static void prvTaskExitError( void )
* regions have privileged access. */ * regions have privileged access. */
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
} }
}
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -1210,7 +1200,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ]; extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulSystemCallStack; uint32_t * pulSystemCallStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1246,12 +1236,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1261,20 +1255,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the system call stack for the stack frame. */ /* Make space on the system call stack for the stack frame. */
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize; pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulSystemCallStack[ i ] = pulTaskStack[ i ]; pulSystemCallStack[ i ] = pulTaskStack[ i ];
} }
@ -1310,7 +1304,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Remember the location where we should copy the stack frame when we exit from /* Remember the location where we should copy the stack frame when we exit from
* the system call. */ * the system call. */
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize; pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
/* Record if the hardware used padding to force the stack pointer /* Record if the hardware used padding to force the stack pointer
* to be double word aligned. */ * to be double word aligned. */
@ -1360,7 +1354,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern TaskHandle_t pxCurrentTCB; extern TaskHandle_t pxCurrentTCB;
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulTaskStack; uint32_t * pulTaskStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1392,12 +1386,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1407,20 +1405,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the task stack for the stack frame. */ /* Make space on the task stack for the stack frame. */
pulTaskStack = pulTaskStack - ulStackFrameSize; pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulTaskStack[ i ] = pulSystemCallStack[ i ]; pulTaskStack[ i ] = pulSystemCallStack[ i ];
} }

View file

@ -1,7 +1,7 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates * Copyright 2024-2025 Arm Limited and/or its affiliates
* <open-source-office@arm.com> * <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
@ -230,7 +230,7 @@ typedef void ( * portISR_t )( void );
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
#endif /* portARMV8M_MINOR_VERSION >= 1 */ #endif /* portARMV8M_MINOR_VERSION >= 1 */
@ -241,9 +241,6 @@ typedef void ( * portISR_t )( void );
/* Enable MPU. */ /* Enable MPU. */
#define portMPU_ENABLE_BIT ( 1UL << 0UL ) #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 /* Extract first address of the MPU region as encoded in the
* RBAR (Region Base Address Register) value. */ * RBAR (Region Base Address Register) value. */
#define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \ #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@ -291,7 +288,7 @@ typedef void ( * portISR_t )( void );
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 ) #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF FD * FF FF FF FD
@ -308,7 +305,7 @@ typedef void ( * portISR_t )( void );
#define portINITIAL_EXC_RETURN ( 0xfffffffd ) #define portINITIAL_EXC_RETURN ( 0xfffffffd )
#else #else
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF BC * FF FF FF BC
@ -401,7 +398,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Extract MPU region's access permissions from the Region Base Address * @brief Extract MPU region's access permissions from the Region Base Address
* Register (RBAR) value. * Register (RBAR) value.
* *
@ -414,7 +411,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Setup the Memory Protection Unit (MPU). * @brief Setup the Memory Protection Unit (MPU).
*/ */
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
@ -422,7 +419,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
/** /**
* @brief Setup the Floating Point Unit (FPU). * @brief Setup the Floating Point Unit (FPU).
*/ */
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
@ -430,7 +427,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) ) #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
/** /**
* @brief Configures PACBTI features. * @brief Configures PACBTI features.
* *
* This function configures the Pointer Authentication, and Branch Target * This function configures the Pointer Authentication, and Branch Target
@ -491,7 +488,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Sets up the system call stack so that upon returning from * @brief Sets up the system call stack so that upon returning from
* SVC, the system call stack is used. * SVC, the system call stack is used.
* *
@ -507,7 +504,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
@ -516,7 +513,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( 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 * @brief Sets up the task stack so that upon returning from
* SVC, the task stack is used again. * SVC, the task stack is used again.
* *
@ -530,7 +527,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Checks whether or not the calling task is privileged. * @brief Checks whether or not the calling task is privileged.
* *
* @return pdTRUE if the calling task is privileged, pdFALSE otherwise. * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
@ -542,7 +539,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
@ -557,7 +554,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/** /**
* @brief Saved as part of the task context to indicate which context the * @brief Saved as part of the task context to indicate which context the
* task is using on the secure side. * task is using on the secure side.
*/ */
@ -579,18 +576,18 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configUSE_TICKLESS_IDLE == 1 ) #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; PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
/** /**
* @brief The maximum number of tick periods that can be suppressed is * @brief The maximum number of tick periods that can be suppressed is
* limited by the 24 bit resolution of the SysTick timer. * limited by the 24 bit resolution of the SysTick timer.
*/ */
PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
/** /**
* @brief Compensate for the CPU cycles that pass while the SysTick is * @brief Compensate for the CPU cycles that pass while the SysTick is
* stopped (low power functionality only). * stopped (low power functionality only).
*/ */
@ -925,12 +922,6 @@ static void prvTaskExitError( void )
/* The only permitted number of regions are 8 or 16. */ /* The only permitted number of regions are 8 or 16. */
configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 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 );
/* Check that the MPU is present. */
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
{
/* MAIR0 - Index 0. */ /* MAIR0 - Index 0. */
portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
/* MAIR0 - Index 1. */ /* MAIR0 - Index 1. */
@ -983,7 +974,6 @@ static void prvTaskExitError( void )
* regions have privileged access. */ * regions have privileged access. */
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
} }
}
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -1210,7 +1200,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ]; extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulSystemCallStack; uint32_t * pulSystemCallStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1246,12 +1236,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1261,20 +1255,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the system call stack for the stack frame. */ /* Make space on the system call stack for the stack frame. */
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize; pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulSystemCallStack[ i ] = pulTaskStack[ i ]; pulSystemCallStack[ i ] = pulTaskStack[ i ];
} }
@ -1310,7 +1304,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Remember the location where we should copy the stack frame when we exit from /* Remember the location where we should copy the stack frame when we exit from
* the system call. */ * the system call. */
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize; pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
/* Record if the hardware used padding to force the stack pointer /* Record if the hardware used padding to force the stack pointer
* to be double word aligned. */ * to be double word aligned. */
@ -1360,7 +1354,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern TaskHandle_t pxCurrentTCB; extern TaskHandle_t pxCurrentTCB;
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulTaskStack; uint32_t * pulTaskStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1392,12 +1386,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1407,20 +1405,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the task stack for the stack frame. */ /* Make space on the task stack for the stack frame. */
pulTaskStack = pulTaskStack - ulStackFrameSize; pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulTaskStack[ i ] = pulSystemCallStack[ i ]; pulTaskStack[ i ] = pulSystemCallStack[ i ];
} }

View file

@ -1,7 +1,7 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates * Copyright 2024-2025 Arm Limited and/or its affiliates
* <open-source-office@arm.com> * <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
@ -230,7 +230,7 @@ typedef void ( * portISR_t )( void );
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
#endif /* portARMV8M_MINOR_VERSION >= 1 */ #endif /* portARMV8M_MINOR_VERSION >= 1 */
@ -241,9 +241,6 @@ typedef void ( * portISR_t )( void );
/* Enable MPU. */ /* Enable MPU. */
#define portMPU_ENABLE_BIT ( 1UL << 0UL ) #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 /* Extract first address of the MPU region as encoded in the
* RBAR (Region Base Address Register) value. */ * RBAR (Region Base Address Register) value. */
#define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \ #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@ -291,7 +288,7 @@ typedef void ( * portISR_t )( void );
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 ) #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF FD * FF FF FF FD
@ -308,7 +305,7 @@ typedef void ( * portISR_t )( void );
#define portINITIAL_EXC_RETURN ( 0xfffffffd ) #define portINITIAL_EXC_RETURN ( 0xfffffffd )
#else #else
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF BC * FF FF FF BC
@ -401,7 +398,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Extract MPU region's access permissions from the Region Base Address * @brief Extract MPU region's access permissions from the Region Base Address
* Register (RBAR) value. * Register (RBAR) value.
* *
@ -414,7 +411,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Setup the Memory Protection Unit (MPU). * @brief Setup the Memory Protection Unit (MPU).
*/ */
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
@ -422,7 +419,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
/** /**
* @brief Setup the Floating Point Unit (FPU). * @brief Setup the Floating Point Unit (FPU).
*/ */
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
@ -430,7 +427,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) ) #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
/** /**
* @brief Configures PACBTI features. * @brief Configures PACBTI features.
* *
* This function configures the Pointer Authentication, and Branch Target * This function configures the Pointer Authentication, and Branch Target
@ -491,7 +488,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Sets up the system call stack so that upon returning from * @brief Sets up the system call stack so that upon returning from
* SVC, the system call stack is used. * SVC, the system call stack is used.
* *
@ -507,7 +504,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
@ -516,7 +513,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( 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 * @brief Sets up the task stack so that upon returning from
* SVC, the task stack is used again. * SVC, the task stack is used again.
* *
@ -530,7 +527,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Checks whether or not the calling task is privileged. * @brief Checks whether or not the calling task is privileged.
* *
* @return pdTRUE if the calling task is privileged, pdFALSE otherwise. * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
@ -542,7 +539,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
@ -557,7 +554,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/** /**
* @brief Saved as part of the task context to indicate which context the * @brief Saved as part of the task context to indicate which context the
* task is using on the secure side. * task is using on the secure side.
*/ */
@ -579,18 +576,18 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configUSE_TICKLESS_IDLE == 1 ) #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; PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
/** /**
* @brief The maximum number of tick periods that can be suppressed is * @brief The maximum number of tick periods that can be suppressed is
* limited by the 24 bit resolution of the SysTick timer. * limited by the 24 bit resolution of the SysTick timer.
*/ */
PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
/** /**
* @brief Compensate for the CPU cycles that pass while the SysTick is * @brief Compensate for the CPU cycles that pass while the SysTick is
* stopped (low power functionality only). * stopped (low power functionality only).
*/ */
@ -925,12 +922,6 @@ static void prvTaskExitError( void )
/* The only permitted number of regions are 8 or 16. */ /* The only permitted number of regions are 8 or 16. */
configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 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 );
/* Check that the MPU is present. */
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
{
/* MAIR0 - Index 0. */ /* MAIR0 - Index 0. */
portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
/* MAIR0 - Index 1. */ /* MAIR0 - Index 1. */
@ -983,7 +974,6 @@ static void prvTaskExitError( void )
* regions have privileged access. */ * regions have privileged access. */
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
} }
}
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -1210,7 +1200,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ]; extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulSystemCallStack; uint32_t * pulSystemCallStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1246,12 +1236,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1261,20 +1255,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the system call stack for the stack frame. */ /* Make space on the system call stack for the stack frame. */
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize; pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulSystemCallStack[ i ] = pulTaskStack[ i ]; pulSystemCallStack[ i ] = pulTaskStack[ i ];
} }
@ -1310,7 +1304,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Remember the location where we should copy the stack frame when we exit from /* Remember the location where we should copy the stack frame when we exit from
* the system call. */ * the system call. */
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize; pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
/* Record if the hardware used padding to force the stack pointer /* Record if the hardware used padding to force the stack pointer
* to be double word aligned. */ * to be double word aligned. */
@ -1360,7 +1354,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern TaskHandle_t pxCurrentTCB; extern TaskHandle_t pxCurrentTCB;
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulTaskStack; uint32_t * pulTaskStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1392,12 +1386,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1407,20 +1405,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the task stack for the stack frame. */ /* Make space on the task stack for the stack frame. */
pulTaskStack = pulTaskStack - ulStackFrameSize; pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulTaskStack[ i ] = pulSystemCallStack[ i ]; pulTaskStack[ i ] = pulSystemCallStack[ i ];
} }

View file

@ -1,7 +1,7 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates * Copyright 2024-2025 Arm Limited and/or its affiliates
* <open-source-office@arm.com> * <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
@ -230,7 +230,7 @@ typedef void ( * portISR_t )( void );
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
#endif /* portARMV8M_MINOR_VERSION >= 1 */ #endif /* portARMV8M_MINOR_VERSION >= 1 */
@ -241,9 +241,6 @@ typedef void ( * portISR_t )( void );
/* Enable MPU. */ /* Enable MPU. */
#define portMPU_ENABLE_BIT ( 1UL << 0UL ) #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 /* Extract first address of the MPU region as encoded in the
* RBAR (Region Base Address Register) value. */ * RBAR (Region Base Address Register) value. */
#define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \ #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
@ -291,7 +288,7 @@ typedef void ( * portISR_t )( void );
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 ) #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF FD * FF FF FF FD
@ -308,7 +305,7 @@ typedef void ( * portISR_t )( void );
#define portINITIAL_EXC_RETURN ( 0xfffffffd ) #define portINITIAL_EXC_RETURN ( 0xfffffffd )
#else #else
/** /**
* @brief Initial EXC_RETURN value. * @brief Initial EXC_RETURN value.
* *
* FF FF FF BC * FF FF FF BC
@ -401,7 +398,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Extract MPU region's access permissions from the Region Base Address * @brief Extract MPU region's access permissions from the Region Base Address
* Register (RBAR) value. * Register (RBAR) value.
* *
@ -414,7 +411,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Setup the Memory Protection Unit (MPU). * @brief Setup the Memory Protection Unit (MPU).
*/ */
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
@ -422,7 +419,7 @@ static void prvTaskExitError( void );
#if ( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
/** /**
* @brief Setup the Floating Point Unit (FPU). * @brief Setup the Floating Point Unit (FPU).
*/ */
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
@ -430,7 +427,7 @@ static void prvTaskExitError( void );
#if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) ) #if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
/** /**
* @brief Configures PACBTI features. * @brief Configures PACBTI features.
* *
* This function configures the Pointer Authentication, and Branch Target * This function configures the Pointer Authentication, and Branch Target
@ -491,7 +488,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
/** /**
* @brief Sets up the system call stack so that upon returning from * @brief Sets up the system call stack so that upon returning from
* SVC, the system call stack is used. * SVC, the system call stack is used.
* *
@ -507,7 +504,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
@ -516,7 +513,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( 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 * @brief Sets up the task stack so that upon returning from
* SVC, the task stack is used again. * SVC, the task stack is used again.
* *
@ -530,7 +527,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
/** /**
* @brief Checks whether or not the calling task is privileged. * @brief Checks whether or not the calling task is privileged.
* *
* @return pdTRUE if the calling task is privileged, pdFALSE otherwise. * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
@ -542,7 +539,7 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIV
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) #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; PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
@ -557,7 +554,7 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configENABLE_TRUSTZONE == 1 ) #if ( configENABLE_TRUSTZONE == 1 )
/** /**
* @brief Saved as part of the task context to indicate which context the * @brief Saved as part of the task context to indicate which context the
* task is using on the secure side. * task is using on the secure side.
*/ */
@ -579,18 +576,18 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
#if ( configUSE_TICKLESS_IDLE == 1 ) #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; PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
/** /**
* @brief The maximum number of tick periods that can be suppressed is * @brief The maximum number of tick periods that can be suppressed is
* limited by the 24 bit resolution of the SysTick timer. * limited by the 24 bit resolution of the SysTick timer.
*/ */
PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
/** /**
* @brief Compensate for the CPU cycles that pass while the SysTick is * @brief Compensate for the CPU cycles that pass while the SysTick is
* stopped (low power functionality only). * stopped (low power functionality only).
*/ */
@ -925,12 +922,6 @@ static void prvTaskExitError( void )
/* The only permitted number of regions are 8 or 16. */ /* The only permitted number of regions are 8 or 16. */
configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 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 );
/* Check that the MPU is present. */
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
{
/* MAIR0 - Index 0. */ /* MAIR0 - Index 0. */
portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
/* MAIR0 - Index 1. */ /* MAIR0 - Index 1. */
@ -983,7 +974,6 @@ static void prvTaskExitError( void )
* regions have privileged access. */ * regions have privileged access. */
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
} }
}
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -1210,7 +1200,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ]; extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulSystemCallStack; uint32_t * pulSystemCallStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1246,12 +1236,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1261,20 +1255,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the system call stack for the stack frame. */ /* Make space on the system call stack for the stack frame. */
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize; pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulSystemCallStack[ i ] = pulTaskStack[ i ]; pulSystemCallStack[ i ] = pulTaskStack[ i ];
} }
@ -1310,7 +1304,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Remember the location where we should copy the stack frame when we exit from /* Remember the location where we should copy the stack frame when we exit from
* the system call. */ * the system call. */
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize; pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulHardwareSavedExceptionFrameSize;
/* Record if the hardware used padding to force the stack pointer /* Record if the hardware used padding to force the stack pointer
* to be double word aligned. */ * to be double word aligned. */
@ -1360,7 +1354,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
extern TaskHandle_t pxCurrentTCB; extern TaskHandle_t pxCurrentTCB;
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulTaskStack; uint32_t * pulTaskStack;
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulHardwareSavedExceptionFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
@ -1392,12 +1386,16 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
{ {
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
{ {
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
__asm volatile ( __asm volatile (
" vpush {s0} \n" /* Trigger lazy stacking. */ " vpush {s0} \n" /* Trigger lazy stacking. */
" vpop {s0} \n" /* Nullify the affect of the above instruction. */ " vpop {s0} \n" /* Nullify the affect of the above instruction. */
@ -1407,20 +1405,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
} }
#else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
{ {
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
/* Make space on the task stack for the stack frame. */ /* Make space on the task stack for the stack frame. */
pulTaskStack = pulTaskStack - ulStackFrameSize; pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulTaskStack[ i ] = pulSystemCallStack[ i ]; pulTaskStack[ i ] = pulSystemCallStack[ i ];
} }

View file

@ -98,7 +98,7 @@ void vPortSetupTimerInterrupt( void ) __attribute__( ( weak ) );
uint64_t ullNextTime = 0ULL; uint64_t ullNextTime = 0ULL;
const uint64_t * pullNextTime = &ullNextTime; const uint64_t * pullNextTime = &ullNextTime;
const size_t uxTimerIncrementsForOneTick = ( size_t ) ( ( configCPU_CLOCK_HZ ) / ( configTICK_RATE_HZ ) ); /* Assumes increment won't go over 32-bits. */ const size_t uxTimerIncrementsForOneTick = ( size_t ) ( ( configCPU_CLOCK_HZ ) / ( configTICK_RATE_HZ ) ); /* Assumes increment won't go over 32-bits. */
uint64_t const ullMachineTimerCompareRegisterBase = configMTIMECMP_BASE_ADDRESS; UBaseType_t const ullMachineTimerCompareRegisterBase = configMTIMECMP_BASE_ADDRESS;
volatile uint64_t * pullMachineTimerCompareRegister = NULL; volatile uint64_t * pullMachineTimerCompareRegister = NULL;
/* Holds the critical nesting value - deliberately non-zero at start up to /* Holds the critical nesting value - deliberately non-zero at start up to

View file

@ -93,12 +93,10 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
void * pvParameters ) void * pvParameters )
{ {
uint32_t * pulLocal; uint32_t * pulLocal;
/* With large data sizeof( StackType_t ) == 2, and
/* With large code and large data sizeof( StackType_t ) == 2, and * sizeof( StackType_t * ) == 4. With small data
* sizeof( StackType_t * ) == 4. With small code and small data
* sizeof( StackType_t ) == 2 and sizeof( StackType_t * ) == 2. */ * sizeof( StackType_t ) == 2 and sizeof( StackType_t * ) == 2. */
#if __DATA_MODEL__ == __DATA_MODEL_FAR__
#if __DATA_MODEL__ == __DATA_MODEL_FAR__
{ {
/* Far pointer parameters are passed using the A:DE registers (24-bit). /* Far pointer parameters are passed using the A:DE registers (24-bit).
* Although they are stored in memory as a 32-bit value. Hence decrement * Although they are stored in memory as a 32-bit value. Hence decrement
@ -106,9 +104,13 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
* storing the pvParameters value. */ * storing the pvParameters value. */
pxTopOfStack--; pxTopOfStack--;
pulLocal = ( uint32_t * ) pxTopOfStack; pulLocal = ( uint32_t * ) pxTopOfStack;
#if __CALLING_CONVENTION__ == __CC_V2__
/* V2: parameter via A:DE, do not push pvParameters on stack */
#else
/* V1 or unknown: keep stack write */
*pulLocal = ( uint32_t ) pvParameters; *pulLocal = ( uint32_t ) pvParameters;
pxTopOfStack--; pxTopOfStack--;
#endif
/* The return address is a 32-bit value. So decrement the stack pointer /* The return address is a 32-bit value. So decrement the stack pointer
* in order to make extra room needed to store the correct value. See the * in order to make extra room needed to store the correct value. See the
* comments above the prvTaskExitError() prototype at the top of this file. */ * comments above the prvTaskExitError() prototype at the top of this file. */
@ -116,19 +118,50 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pulLocal = ( uint32_t * ) pxTopOfStack; pulLocal = ( uint32_t * ) pxTopOfStack;
*pulLocal = ( uint32_t ) prvTaskExitError; *pulLocal = ( uint32_t ) prvTaskExitError;
pxTopOfStack--; pxTopOfStack--;
/* The task function start address combined with the PSW is also stored /* The task function start address combined with the PSW is also stored
* as a 32-bit value. So leave a space for the second two bytes. */ * as a 32-bit value. So leave a space for the second two bytes. */
pxTopOfStack--; pxTopOfStack--;
pulLocal = ( uint32_t * ) pxTopOfStack; pulLocal = ( uint32_t * ) pxTopOfStack;
*pulLocal = ( ( ( uint32_t ) pxCode ) | ( portPSW << 24UL ) ); *pulLocal = ( ( ( uint32_t ) pxCode ) | ( portPSW << 24UL ) );
pxTopOfStack--; pxTopOfStack--;
/* Register image on task entry. */
#if __CALLING_CONVENTION__ == __CC_V2__
{
uint32_t p = ( uint32_t ) pvParameters;
uint16_t de_init = (uint16_t)( p & 0xFFFFU );
uint16_t ax_init = (uint16_t)( ((p >> 16) & 0xFFU) << 8 );
/* AX register image */
*pxTopOfStack = ( StackType_t ) ax_init;
pxTopOfStack--;
/* HL register image (dummy) */
*pxTopOfStack = ( StackType_t ) 0x2222;
pxTopOfStack--;
/* CS:ES register image */
*pxTopOfStack = ( StackType_t ) 0x0F00;
pxTopOfStack--;
/* DE register image */
*pxTopOfStack = ( StackType_t ) de_init;
pxTopOfStack--;
}
#else
/* An initial value for the AX register. */ /* An initial value for the AX register. */
*pxTopOfStack = ( StackType_t ) 0x1111; *pxTopOfStack = ( StackType_t ) 0x1111;
pxTopOfStack--; pxTopOfStack--;
/* HL register image (dummy) */
*pxTopOfStack = ( StackType_t ) 0x2222;
pxTopOfStack--;
/* CS:ES register image */
*pxTopOfStack = ( StackType_t ) 0x0F00;
pxTopOfStack--;
/* DE register image (dummy) */
*pxTopOfStack = ( StackType_t ) 0xDEDE;
pxTopOfStack--;
#endif
/* BC remains a dummy value (not used for parameter passing). */
*pxTopOfStack = ( StackType_t ) 0xBCBC;
pxTopOfStack--;
} }
#else /* if __DATA_MODEL__ == __DATA_MODEL_FAR__ */ #else /* if __DATA_MODEL__ == __DATA_MODEL_FAR__ */
{ {
/* The return address, leaving space for the first two bytes of the /* The return address, leaving space for the first two bytes of the
* 32-bit value. See the comments above the prvTaskExitError() prototype * 32-bit value. See the comments above the prvTaskExitError() prototype
@ -137,44 +170,37 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pulLocal = ( uint32_t * ) pxTopOfStack; pulLocal = ( uint32_t * ) pxTopOfStack;
*pulLocal = ( uint32_t ) prvTaskExitError; *pulLocal = ( uint32_t ) prvTaskExitError;
pxTopOfStack--; pxTopOfStack--;
/* Task function. Again as it is written as a 32-bit value a space is /* Task function. Again as it is written as a 32-bit value a space is
* left on the stack for the second two bytes. */ * left on the stack for the second two bytes. */
pxTopOfStack--; pxTopOfStack--;
/* Task function start address combined with the PSW. */ /* Task function start address combined with the PSW. */
pulLocal = ( uint32_t * ) pxTopOfStack; pulLocal = ( uint32_t * ) pxTopOfStack;
*pulLocal = ( ( ( uint32_t ) pxCode ) | ( portPSW << 24UL ) ); *pulLocal = ( ( ( uint32_t ) pxCode ) | ( portPSW << 24UL ) );
pxTopOfStack--; pxTopOfStack--;
/* The parameter is passed in AX. */ /* The parameter is passed in AX. */
*pxTopOfStack = ( StackType_t ) pvParameters; *pxTopOfStack = ( StackType_t ) pvParameters;
pxTopOfStack--; pxTopOfStack--;
}
#endif /* if __DATA_MODEL__ == __DATA_MODEL_FAR__ */
/* An initial value for the HL register. */ /* An initial value for the HL register. */
*pxTopOfStack = ( StackType_t ) 0x2222; *pxTopOfStack = ( StackType_t ) 0x2222;
pxTopOfStack--; pxTopOfStack--;
/* CS and ES registers. */ /* CS and ES registers. */
*pxTopOfStack = ( StackType_t ) 0x0F00; *pxTopOfStack = ( StackType_t ) 0x0F00;
pxTopOfStack--; pxTopOfStack--;
/* The remaining general purpose registers DE and BC */ /* The remaining general purpose registers DE and BC */
*pxTopOfStack = ( StackType_t ) 0xDEDE; *pxTopOfStack = ( StackType_t ) 0xDEDE;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xBCBC; *pxTopOfStack = ( StackType_t ) 0xBCBC;
pxTopOfStack--; pxTopOfStack--;
}
#endif /* __DATA_MODEL__ */
/* Finally the critical section nesting count is set to zero when the task /* Finally the critical section nesting count is set to zero when the task
* first starts. */ * first starts. */
*pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING; *pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING;
/* Return a pointer to the top of the stack that has been generated so /* Return a pointer to the top of the stack that has been generated so
* it can be stored in the task control block for the task. */ * it can be stored in the task control block for the task. */
return pxTopOfStack; return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvTaskExitError( void ) static void prvTaskExitError( void )

View file

@ -187,7 +187,7 @@
* ; * memory mode) registers the _usCriticalNesting value and the Stack Pointer * ; * memory mode) registers the _usCriticalNesting value and the Stack Pointer
* ; * of the active Task onto the task stack. * ; * of the active Task onto the task stack.
* ; *---------------------------------------------------------------------------*/ * ; *---------------------------------------------------------------------------*/
portSAVE_CONTEXT MACRO portSAVE_CONTEXT MACRO
PUSH AX; /* Save AX Register to stack. */ PUSH AX; /* Save AX Register to stack. */
PUSH HL PUSH HL
#if __CODE_MODEL__ == __CODE_MODEL_FAR__ #if __CODE_MODEL__ == __CODE_MODEL_FAR__
@ -217,7 +217,7 @@
* ; * general purpose registers and the CS and ES (only in __far memory mode) * ; * general purpose registers and the CS and ES (only in __far memory mode)
* ; * of the selected task from the task stack. * ; * of the selected task from the task stack.
* ; *---------------------------------------------------------------------------*/ * ; *---------------------------------------------------------------------------*/
portRESTORE_CONTEXT MACRO portRESTORE_CONTEXT MACRO
MOVW AX, _pxCurrentTCB; /* Restore the Task stack pointer. */ MOVW AX, _pxCurrentTCB; /* Restore the Task stack pointer. */
MOVW HL, AX MOVW HL, AX
MOVW AX, [ HL ] MOVW AX, [ HL ]

View file

@ -234,6 +234,11 @@ __attribute__(( weak )) void vApplicationSetupTickTimerInterrupt( void )
{ {
const uint32_t ulCompareMatch = ( (configPERIPHERAL_CLOCK_HZ / portTIMER_PRESCALE) / configTICK_RATE_HZ ) - 1UL; const uint32_t ulCompareMatch = ( (configPERIPHERAL_CLOCK_HZ / portTIMER_PRESCALE) / configTICK_RATE_HZ ) - 1UL;
/* PR1 is 16-bit. Ensure that the configPERIPHERAL_CLOCK_HZ and
* configTICK_RATE_HZ are defined such that ulCompareMatch value would fit
* in 16-bits. */
configASSERT( ( ulCompareMatch & 0xFFFF0000 ) == 0 );
T1CON = 0x0000; T1CON = 0x0000;
T1CONbits.TCKPS = portPRESCALE_BITS; T1CONbits.TCKPS = portPRESCALE_BITS;
PR1 = ulCompareMatch; PR1 = ulCompareMatch;

View file

@ -33,6 +33,14 @@
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
#ifdef WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#else
#include <winsock.h>
#endif
#include <timeapi.h>
#ifdef __GNUC__ #ifdef __GNUC__
#include "mmsystem.h" #include "mmsystem.h"
#else #else
@ -144,6 +152,7 @@ static DWORD WINAPI prvSimulatedPeripheralTimer( LPVOID lpParameter )
TickType_t xWaitTimeBetweenTicks = portTICK_PERIOD_MS; TickType_t xWaitTimeBetweenTicks = portTICK_PERIOD_MS;
HANDLE hTimer = NULL; HANDLE hTimer = NULL;
LARGE_INTEGER liDueTime; LARGE_INTEGER liDueTime;
BOOL bSuccess;
/* Set the timer resolution to the maximum possible. */ /* Set the timer resolution to the maximum possible. */
if( timeGetDevCaps( &xTimeCaps, sizeof( xTimeCaps ) ) == MMSYSERR_NOERROR ) if( timeGetDevCaps( &xTimeCaps, sizeof( xTimeCaps ) ) == MMSYSERR_NOERROR )
@ -182,7 +191,8 @@ static DWORD WINAPI prvSimulatedPeripheralTimer( LPVOID lpParameter )
/* Set the Waitable Timer. The timer is set to run periodically at every /* Set the Waitable Timer. The timer is set to run periodically at every
xWaitTimeBetweenTicks milliseconds. */ xWaitTimeBetweenTicks milliseconds. */
configASSERT( SetWaitableTimer( hTimer, &liDueTime, xWaitTimeBetweenTicks, NULL, NULL, 0 ) ); bSuccess = SetWaitableTimer( hTimer, &liDueTime, xWaitTimeBetweenTicks, NULL, NULL, 0 );
configASSERT( bSuccess );
while( xPortRunning == pdTRUE ) while( xPortRunning == pdTRUE )
{ {

View file

@ -29,17 +29,6 @@
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#ifdef WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#else
#include <winsock.h>
#endif
#include <windows.h>
#include <timeapi.h>
#include <mmsystem.h>
#include <winbase.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -156,22 +145,25 @@ void vPortExitCritical( void );
: "cc" ) : "cc" )
#else /* __GNUC__ */ #else /* __GNUC__ */
#include <intrin.h>
/* BitScanReverse returns the bit position of the most significant '1' /* BitScanReverse returns the bit position of the most significant '1'
* in the word. */ * in the word. */
#if defined( __x86_64__ ) || defined( _M_X64 ) #if defined( __x86_64__ ) || defined( _M_X64 )
#pragma intrinsic(_BitScanReverse64)
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) \ #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) \
do \ do \
{ \ { \
DWORD ulTopPriority; \ unsigned long ulTopPriority; \
_BitScanReverse64( &ulTopPriority, ( uxReadyPriorities ) ); \ _BitScanReverse64( &ulTopPriority, ( uxReadyPriorities ) ); \
uxTopPriority = ulTopPriority; \ uxTopPriority = ulTopPriority; \
} while( 0 ) } while( 0 )
#else /* #if defined( __x86_64__ ) || defined( _M_X64 ) */ #else /* #if defined( __x86_64__ ) || defined( _M_X64 ) */
#pragma intrinsic(_BitScanReverse)
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) _BitScanReverse( ( DWORD * ) &( uxTopPriority ), ( uxReadyPriorities ) ) #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) _BitScanReverse( ( unsigned long * ) &( uxTopPriority ), ( uxReadyPriorities ) )
#endif /* #if defined( __x86_64__ ) || defined( _M_X64 ) */ #endif /* #if defined( __x86_64__ ) || defined( _M_X64 ) */

View file

@ -572,7 +572,7 @@ static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert ) /* PRIVI
void vPortGetHeapStats( HeapStats_t * pxHeapStats ) void vPortGetHeapStats( HeapStats_t * pxHeapStats )
{ {
BlockLink_t * pxBlock; 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(); vTaskSuspendAll();
{ {

View file

@ -672,7 +672,7 @@ void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) /* PRIVI
void vPortGetHeapStats( HeapStats_t * pxHeapStats ) void vPortGetHeapStats( HeapStats_t * pxHeapStats )
{ {
BlockLink_t * pxBlock; 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(); vTaskSuspendAll();
{ {

View file

@ -1,6 +1,8 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * 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 * SPDX-License-Identifier: MIT
* *
@ -474,7 +476,7 @@ void vSVCHandler_C( uint32_t * pulParam )
extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ]; extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulSystemCallStack; 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_start__;
extern uint32_t __syscalls_flash_end__; extern uint32_t __syscalls_flash_end__;
@ -500,23 +502,27 @@ void vSVCHandler_C( uint32_t * pulParam )
{ {
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
prvTriggerLazyStacking(); prvTriggerLazyStacking();
} }
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
/* Make space on the system call stack for the stack frame. */ /* Make space on the system call stack for the stack frame. */
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize; pulSystemCallStack = pulSystemCallStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulSystemCallStack[ i ] = pulTaskStack[ i ]; pulSystemCallStack[ i ] = pulTaskStack[ i ];
} }
@ -537,7 +543,7 @@ void vSVCHandler_C( uint32_t * pulParam )
/* Remember the location where we should copy the stack frame when we exit from /* Remember the location where we should copy the stack frame when we exit from
* the system call. */ * 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. /* Store the value of the Link Register before the SVC was raised.
* It contains the address of the caller of the System Call entry * It contains the address of the caller of the System Call entry
@ -592,7 +598,7 @@ void vSVCHandler_C( uint32_t * pulParam )
extern TaskHandle_t pxCurrentTCB; extern TaskHandle_t pxCurrentTCB;
xMPU_SETTINGS * pxMpuSettings; xMPU_SETTINGS * pxMpuSettings;
uint32_t * pulTaskStack; 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_start__;
extern uint32_t __privileged_functions_end__; extern uint32_t __privileged_functions_end__;
@ -614,23 +620,27 @@ void vSVCHandler_C( uint32_t * pulParam )
{ {
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack; 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 + S0S15 + FPSCR + reserved word = 26 words.
*/
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL ) if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
{ {
/* Extended frame i.e. FPU in use. */ /* Extended frame i.e. FPU in use. */
ulStackFrameSize = 26; ulHardwareSavedExceptionFrameSize = 26;
prvTriggerLazyStacking(); prvTriggerLazyStacking();
} }
else else
{ {
/* Standard frame i.e. FPU not in use. */ /* Standard frame i.e. FPU not in use. */
ulStackFrameSize = 8; ulHardwareSavedExceptionFrameSize = 8;
} }
/* Make space on the task stack for the stack frame. */ /* Make space on the task stack for the stack frame. */
pulTaskStack = pulTaskStack - ulStackFrameSize; pulTaskStack = pulTaskStack - ulHardwareSavedExceptionFrameSize;
/* Copy the stack frame. */ /* Copy the stack frame. */
for( i = 0; i < ulStackFrameSize; i++ ) for( i = 0; i < ulHardwareSavedExceptionFrameSize; i++ )
{ {
pulTaskStack[ i ] = pulSystemCallStack[ i ]; pulTaskStack[ i ] = pulSystemCallStack[ i ];
} }

View file

@ -52,13 +52,13 @@ Kernel runs in the Non-Secure Side.
The setting of this macro is decided by the setting in Secure Side which is platform-specific. 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. 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 note that Cortex-M23 does not support FPU.
Please refer to [TF-M documentation](https://tf-m-user-guide.trustedfirmware.org/integration_guide/tfm_fpu_support.html) for FPU usage on the Non-Secure side. 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` * `configENABLE_MVE`
The setting of this macro is decided by the setting in Secure Side which is platform-specific. 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. 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-M55 and Cortex-M85 support MVE. Please note that only Cortex-M55 and Cortex-M85 support MVE.
Please refer to [TF-M documentation](https://tf-m-user-guide.trustedfirmware.org/integration_guide/tfm_fpu_support.html) for MVE usage on the Non-Secure side. 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` * `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. 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.

View file

@ -140,6 +140,8 @@ static void prvThreadKeyDestructor( void * pvData )
static void prvInitThreadKey( void ) static void prvInitThreadKey( void )
{ {
pthread_key_create( &xThreadKey, prvThreadKeyDestructor ); pthread_key_create( &xThreadKey, prvThreadKeyDestructor );
/* Destroy xThreadKey when the process exits. */
atexit( prvDestroyThreadKey );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -193,7 +195,7 @@ void prvFatalError( const char * pcCall,
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvPortSetCurrentThreadName( char * pxThreadName ) static void prvPortSetCurrentThreadName( const char * pxThreadName )
{ {
#ifdef __APPLE__ #ifdef __APPLE__
pthread_setname_np( pxThreadName ); pthread_setname_np( pxThreadName );
@ -227,6 +229,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
/* Ensure that there is enough space to store Thread_t on the stack. */ /* Ensure that there is enough space to store Thread_t on the stack. */
ulStackSize = ( size_t ) ( pxTopOfStack + 1 - pxEndOfStack ) * sizeof( *pxTopOfStack ); ulStackSize = ( size_t ) ( pxTopOfStack + 1 - pxEndOfStack ) * sizeof( *pxTopOfStack );
configASSERT( ulStackSize > sizeof( Thread_t ) ); configASSERT( ulStackSize > sizeof( Thread_t ) );
( void ) ulStackSize; /* suppress set but not used warning */
thread->pxCode = pxCode; thread->pxCode = pxCode;
thread->pvParams = pvParameters; thread->pvParams = pvParameters;
@ -315,8 +318,6 @@ BaseType_t xPortStartScheduler( void )
/* Restore original signal mask. */ /* Restore original signal mask. */
( void ) pthread_sigmask( SIG_SETMASK, &xSchedulerOriginalSignalMask, NULL ); ( void ) pthread_sigmask( SIG_SETMASK, &xSchedulerOriginalSignalMask, NULL );
prvDestroyThreadKey();
return 0; return 0;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -324,17 +325,23 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
Thread_t * pxCurrentThread; Thread_t * pxCurrentThread;
BaseType_t xIsFreeRTOSThread;
/* Stop the timer tick thread. */ /* Stop the timer tick thread. */
xTimerTickThreadShouldRun = false; xTimerTickThreadShouldRun = false;
pthread_join( hTimerTickThread, NULL ); pthread_join( hTimerTickThread, NULL );
/* Check whether the current thread is a FreeRTOS thread.
* This has to happen before the scheduler is signaled to exit
* its loop to prevent data races on the thread key. */
xIsFreeRTOSThread = prvIsFreeRTOSThread();
/* Signal the scheduler to exit its loop. */ /* Signal the scheduler to exit its loop. */
xSchedulerEnd = pdTRUE; xSchedulerEnd = pdTRUE;
( void ) pthread_kill( hMainThread, SIG_RESUME ); ( void ) pthread_kill( hMainThread, SIG_RESUME );
/* Waiting to be deleted here. */ /* Waiting to be deleted here. */
if( prvIsFreeRTOSThread() == pdTRUE ) if( xIsFreeRTOSThread == pdTRUE )
{ {
pxCurrentThread = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() ); pxCurrentThread = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
event_wait( pxCurrentThread->ev ); event_wait( pxCurrentThread->ev );

View file

@ -45,6 +45,9 @@ if (NOT TARGET _FreeRTOS_kernel_inclusion_marker)
set(FREERTOS_KERNEL_PATH ${FREERTOS_KERNEL_PATH} PARENT_SCOPE) set(FREERTOS_KERNEL_PATH ${FREERTOS_KERNEL_PATH} PARENT_SCOPE)
set(PICO_CONFIG_HEADER_FILES ${PICO_CONFIG_HEADER_FILES} PARENT_SCOPE) set(PICO_CONFIG_HEADER_FILES ${PICO_CONFIG_HEADER_FILES} PARENT_SCOPE)
set(PICO_SDK_POST_LIST_FILES ${PICO_SDK_POST_LIST_FILES} PARENT_SCOPE) set(PICO_SDK_POST_LIST_FILES ${PICO_SDK_POST_LIST_FILES} PARENT_SCOPE)
set(PICO_SDK_VERSION_MAJOR ${PICO_SDK_VERSION_MAJOR} PARENT_SCOPE)
set(PICO_SDK_VERSION_MINOR ${PICO_SDK_VERSION_MINOR} PARENT_SCOPE)
set(PICO_SDK_VERSION_REVISION ${PICO_SDK_VERSION_REVISION} PARENT_SCOPE)
endif() endif()
endif() endif()
endif() endif()

View file

@ -227,7 +227,7 @@ static inline void vPortRecursiveLock( BaseType_t xCoreID,
if( ucOwnedByCore[ xCoreID ][ ulLockNum ] ) if( ucOwnedByCore[ xCoreID ][ ulLockNum ] )
{ {
configASSERT( ucRecursionCountByLock[ ulLockNum ] != 255u ); configASSERT( ucRecursionCountByLock[ ulLockNum ] != 255u );
ucRecursionCountByLock[ ulLockNum ]++; ucRecursionCountByLock[ ulLockNum ] = ucRecursionCountByLock[ ulLockNum ] + 1;
return; return;
} }
spin_lock_unsafe_blocking(pxSpinLock); spin_lock_unsafe_blocking(pxSpinLock);
@ -241,7 +241,8 @@ static inline void vPortRecursiveLock( BaseType_t xCoreID,
configASSERT( ( ucOwnedByCore[ xCoreID ] [ulLockNum ] ) != 0 ); configASSERT( ( ucOwnedByCore[ xCoreID ] [ulLockNum ] ) != 0 );
configASSERT( ucRecursionCountByLock[ ulLockNum ] != 0 ); configASSERT( ucRecursionCountByLock[ ulLockNum ] != 0 );
if( !--ucRecursionCountByLock[ ulLockNum ] ) ucRecursionCountByLock[ ulLockNum ] = ucRecursionCountByLock[ ulLockNum ] - 1;
if ( ucRecursionCountByLock[ ulLockNum ] == 0U )
{ {
ucOwnedByCore[ xCoreID ] [ ulLockNum ] = 0; ucOwnedByCore[ xCoreID ] [ ulLockNum ] = 0;
spin_unlock_unsafe(pxSpinLock); spin_unlock_unsafe(pxSpinLock);

View file

@ -243,16 +243,11 @@ void vPortStartFirstTask( void )
" ldr r0, [r0] \n" " ldr r0, [r0] \n"
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */ " msr msp, r0 \n" /* Set the msp back to the start of the stack. */
#endif /* configRESET_STACK_POINTER */ #endif /* configRESET_STACK_POINTER */
#if ( configNUMBER_OF_CORES != 1 )
" adr r1, ulAsmLocals \n" /* Get the location of the current TCB for the current core. */ " adr r1, ulAsmLocals \n" /* Get the location of the current TCB for the current core. */
" ldmia r1!, {r2, r3} \n" " ldmia r1!, {r2, r3} \n"
" ldr r2, [r2] \n" /* r2 = Core number */ " ldr r2, [r2] \n" /* r2 = Core number */
" lsls r2, #2 \n" " lsls r2, #2 \n"
" ldr r3, [r3, r2] \n" /* r3 = pxCurrentTCBs[get_core_num()] */ " ldr r3, [r3, r2] \n" /* r3 = pxCurrentTCBs[get_core_num()] */
#else /* configNUMBER_OF_CORES != 1 */
" ldr r3, =pxCurrentTCBs \n"
" ldr r3, [r3] \n" /* r3 = pxCurrentTCBs[0] */
#endif /* configNUMBER_OF_CORES != 1 */
" ldr r0, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" adds r0, #32 \n" /* Discard everything up to r0. */ " adds r0, #32 \n" /* Discard everything up to r0. */
" msr psp, r0 \n" /* This is now the new top of stack to use in the task. */ " msr psp, r0 \n" /* This is now the new top of stack to use in the task. */
@ -265,13 +260,11 @@ void vPortStartFirstTask( void )
" pop {r2} \n" /* Pop and discard XPSR. */ " pop {r2} \n" /* Pop and discard XPSR. */
" cpsie i \n" /* The first task has its context and interrupts can be enabled. */ " cpsie i \n" /* The first task has its context and interrupts can be enabled. */
" bx r3 \n" /* Finally, jump to the user defined task code. */ " bx r3 \n" /* Finally, jump to the user defined task code. */
#if configNUMBER_OF_CORES != 1
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"ulAsmLocals: \n" "ulAsmLocals: \n"
" .word 0xD0000000 \n" /* SIO */ " .word 0xD0000000 \n" /* SIO */
" .word pxCurrentTCBs \n" " .word pxCurrentTCBs \n"
#endif /* portRUNNING_ON_BOTH_CORES */
); );
#endif /* if ( configNUMBER_OF_CORES == 1 ) */ #endif /* if ( configNUMBER_OF_CORES == 1 ) */
} }
@ -369,14 +362,11 @@ void vPortStartFirstTask( void )
spin_lock_claim( configSMP_SPINLOCK_0 ); spin_lock_claim( configSMP_SPINLOCK_0 );
spin_lock_claim( configSMP_SPINLOCK_1 ); spin_lock_claim( configSMP_SPINLOCK_1 );
#if configNUMBER_OF_CORES != 1
ucPrimaryCoreNum = configTICK_CORE; ucPrimaryCoreNum = configTICK_CORE;
configASSERT( get_core_num() == 0 ); /* we must be started on core 0 */ configASSERT( get_core_num() == 0 ); /* we must be started on core 0 */
multicore_reset_core1(); multicore_reset_core1();
multicore_launch_core1( prvDisableInterruptsAndPortStartSchedulerOnCore ); multicore_launch_core1( prvDisableInterruptsAndPortStartSchedulerOnCore );
#else
ucPrimaryCoreNum = get_core_num();
#endif
xPortStartSchedulerOnCore(); xPortStartSchedulerOnCore();
/* Should not get here! */ /* Should not get here! */
@ -618,13 +608,9 @@ void xPortPendSVHandler( void )
" \n" " \n"
" adr r0, ulAsmLocals2 \n" /* Get the location of the current TCB for the current core. */ " adr r0, ulAsmLocals2 \n" /* Get the location of the current TCB for the current core. */
" ldmia r0!, {r2, r3} \n" " ldmia r0!, {r2, r3} \n"
#if configNUMBER_OF_CORES != 1
" ldr r0, [r2] \n" /* r0 = Core number */ " ldr r0, [r2] \n" /* r0 = Core number */
" lsls r0, r0, #2 \n" " lsls r0, r0, #2 \n"
" adds r3, r0 \n" /* r3 = &pxCurrentTCBs[get_core_num()] */ " adds r3, r0 \n" /* r3 = &pxCurrentTCBs[get_core_num()] */
#else
" \n" /* r3 = &pxCurrentTCBs[0] */
#endif /* portRUNNING_ON_BOTH_CORES */
" ldr r0, [r3] \n" /* r0 = pxCurrentTCB */ " ldr r0, [r3] \n" /* r0 = pxCurrentTCB */
" \n" " \n"
" subs r1, r1, #32 \n" /* Make space for the remaining low registers. */ " subs r1, r1, #32 \n" /* Make space for the remaining low registers. */
@ -658,11 +644,7 @@ void xPortPendSVHandler( void )
" subs r1, r1, #48 \n" " subs r1, r1, #48 \n"
" stmia r1!, {r4-r7} \n" " stmia r1!, {r4-r7} \n"
#endif /* portUSE_DIVIDER_SAVE_RESTORE */ #endif /* portUSE_DIVIDER_SAVE_RESTORE */
#if configNUMBER_OF_CORES != 1
" ldr r0, [r2] \n" /* r0 = Core number */ " ldr r0, [r2] \n" /* r0 = Core number */
#else
" movs r0, #0 \n"
#endif /* configNUMBER_OF_CORES != 1 */
" push {r3, r14} \n" " push {r3, r14} \n"
" cpsid i \n" " cpsid i \n"
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"

30
queue.c
View file

@ -833,6 +833,10 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength,
if( pxMutex->u.xSemaphore.xMutexHolder == xTaskGetCurrentTaskHandle() ) if( pxMutex->u.xSemaphore.xMutexHolder == xTaskGetCurrentTaskHandle() )
{ {
( pxMutex->u.xSemaphore.uxRecursiveCallCount )++; ( pxMutex->u.xSemaphore.uxRecursiveCallCount )++;
/* Check if an overflow occurred. */
configASSERT( pxMutex->u.xSemaphore.uxRecursiveCallCount );
xReturn = pdPASS; xReturn = pdPASS;
} }
else else
@ -845,6 +849,9 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength,
if( xReturn != pdFAIL ) if( xReturn != pdFAIL )
{ {
( pxMutex->u.xSemaphore.uxRecursiveCallCount )++; ( pxMutex->u.xSemaphore.uxRecursiveCallCount )++;
/* Check if an overflow occurred. */
configASSERT( pxMutex->u.xSemaphore.uxRecursiveCallCount );
} }
else else
{ {
@ -1168,9 +1175,8 @@ BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue,
traceENTER_xQueueGenericSendFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken, xCopyPosition ); traceENTER_xQueueGenericSendFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken, xCopyPosition );
configASSERT( pxQueue ); configASSERT( ( pxQueue != NULL ) && !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); configASSERT( ( pxQueue != NULL ) && !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
/* RTOS ports that support interrupt nesting have the concept of a maximum /* RTOS ports that support interrupt nesting have the concept of a maximum
* system call (or maximum API call) interrupt priority. Interrupts that are * system call (or maximum API call) interrupt priority. Interrupts that are
@ -1344,16 +1350,14 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue,
* not (i.e. has a task with a higher priority than us been woken by this * not (i.e. has a task with a higher priority than us been woken by this
* post). */ * post). */
configASSERT( pxQueue );
/* xQueueGenericSendFromISR() should be used instead of xQueueGiveFromISR() /* xQueueGenericSendFromISR() should be used instead of xQueueGiveFromISR()
* if the item size is not 0. */ * 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 /* 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 * there is a mutex holder, as priority inheritance makes no sense for an
* interrupts, only tasks. */ * interrupt, only tasks. */
configASSERT( !( ( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) && ( pxQueue->u.xSemaphore.xMutexHolder != NULL ) ) ); 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 /* RTOS ports that support interrupt nesting have the concept of a maximum
* system call (or maximum API call) interrupt priority. Interrupts that are * system call (or maximum API call) interrupt priority. Interrupts that are
@ -1888,12 +1892,9 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue,
traceENTER_xQueuePeek( xQueue, pvBuffer, xTicksToWait ); 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 /* 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. */ * 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. */ /* Cannot block if the scheduler is suspended. */
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
@ -2145,9 +2146,8 @@ BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue,
traceENTER_xQueuePeekFromISR( xQueue, pvBuffer ); traceENTER_xQueuePeekFromISR( xQueue, pvBuffer );
configASSERT( pxQueue ); configASSERT( ( pxQueue != NULL ) && !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); configASSERT( ( pxQueue != NULL ) && ( pxQueue->uxItemSize != 0 ) ); /* Can't peek a semaphore. */
configASSERT( pxQueue->uxItemSize != 0 ); /* Can't peek a semaphore. */
/* RTOS ports that support interrupt nesting have the concept of a maximum /* RTOS ports that support interrupt nesting have the concept of a maximum
* system call (or maximum API call) interrupt priority. Interrupts that are * system call (or maximum API call) interrupt priority. Interrupts that are

View file

@ -1653,11 +1653,9 @@ void vStreamBufferSetStreamBufferNotificationIndex( StreamBufferHandle_t xStream
traceENTER_vStreamBufferSetStreamBufferNotificationIndex( xStreamBuffer, uxNotificationIndex ); traceENTER_vStreamBufferSetStreamBufferNotificationIndex( xStreamBuffer, uxNotificationIndex );
configASSERT( pxStreamBuffer );
/* There should be no task waiting otherwise we'd never resume them. */ /* There should be no task waiting otherwise we'd never resume them. */
configASSERT( pxStreamBuffer->xTaskWaitingToReceive == NULL ); configASSERT( ( pxStreamBuffer != NULL ) && ( pxStreamBuffer->xTaskWaitingToReceive == NULL ) );
configASSERT( pxStreamBuffer->xTaskWaitingToSend == NULL ); configASSERT( ( pxStreamBuffer != NULL ) && ( pxStreamBuffer->xTaskWaitingToSend == NULL ) );
/* Check that the task notification index is valid. */ /* Check that the task notification index is valid. */
configASSERT( uxNotificationIndex < configTASK_NOTIFICATION_ARRAY_ENTRIES ); configASSERT( uxNotificationIndex < configTASK_NOTIFICATION_ARRAY_ENTRIES );

View file

@ -893,7 +893,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
BaseType_t xCurrentCoreTaskPriority; BaseType_t xCurrentCoreTaskPriority;
BaseType_t xLowestPriorityCore = ( BaseType_t ) -1; BaseType_t xLowestPriorityCore = ( BaseType_t ) -1;
BaseType_t xCoreID; BaseType_t xCoreID;
const BaseType_t xCurrentCoreID = portGET_CORE_ID(); const BaseType_t xCurrentCoreID = ( BaseType_t ) portGET_CORE_ID();
#if ( configRUN_MULTIPLE_PRIORITIES == 0 ) #if ( configRUN_MULTIPLE_PRIORITIES == 0 )
BaseType_t xYieldCount = 0; BaseType_t xYieldCount = 0;