Compare commits

...

33 commits

Author SHA1 Message Date
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
65 changed files with 5965 additions and 5625 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
@ -783,6 +786,7 @@ SHPR
SHTIM SHTIM
SIFIVE SIFIVE
sinclude sinclude
slli
SODR SODR
SOFTIRQ SOFTIRQ
SPCK SPCK
@ -934,6 +938,7 @@ USRIO
utest utest
utilises utilises
utilising utilising
vcsr
VDDCORE VDDCORE
vect vect
Vect Vect
@ -944,6 +949,7 @@ visualisation
vldmdbeq vldmdbeq
vldmia vldmia
vldmiaeq vldmiaeq
vlenb
VMSRNE VMSRNE
vpop vpop
VPOPNE VPOPNE
@ -951,6 +957,7 @@ vpush
VPUSHNE VPUSHNE
VRPM VRPM
Vrtc Vrtc
vsetvl
vstmdbeq vstmdbeq
vstmiaeq vstmiaeq
VTOR VTOR

View file

@ -114,6 +114,10 @@ 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*',
] ]
KERNEL_HEADER = [ KERNEL_HEADER = [
@ -150,8 +154,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

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

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

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

@ -769,6 +769,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

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

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

@ -80,22 +80,22 @@ csrr t2, lpcount0
csrr t3, lpstart1 csrr t3, lpstart1
csrr t4, lpend1 csrr t4, lpend1
csrr t5, lpcount1 csrr t5, lpcount1
sw t0, 1 * portWORD_SIZE( sp ) sw t0, 2 * portWORD_SIZE( sp )
sw t1, 2 * portWORD_SIZE( sp ) sw t1, 3 * portWORD_SIZE( sp )
sw t2, 3 * portWORD_SIZE( sp ) sw t2, 4 * portWORD_SIZE( sp )
sw t3, 4 * portWORD_SIZE( sp ) sw t3, 5 * portWORD_SIZE( sp )
sw t4, 5 * portWORD_SIZE( sp ) sw t4, 6 * portWORD_SIZE( sp )
sw t5, 6 * portWORD_SIZE( sp ) sw t5, 7 * portWORD_SIZE( sp )
.endm .endm
/* Restore the additional registers found on the Pulpino. */ /* Restore the additional registers found on the Pulpino. */
.macro portasmRESTORE_ADDITIONAL_REGISTERS .macro portasmRESTORE_ADDITIONAL_REGISTERS
lw t0, 1 * portWORD_SIZE( sp ) /* Load additional registers into accessible temporary registers. */ lw t0, 2 * portWORD_SIZE( sp ) /* Load additional registers into accessible temporary registers. */
lw t1, 2 * portWORD_SIZE( sp ) lw t1, 3 * portWORD_SIZE( sp )
lw t2, 3 * portWORD_SIZE( sp ) lw t2, 4 * portWORD_SIZE( sp )
lw t3, 4 * portWORD_SIZE( sp ) lw t3, 5 * portWORD_SIZE( sp )
lw t4, 5 * portWORD_SIZE( sp ) lw t4, 6 * portWORD_SIZE( sp )
lw t5, 6 * portWORD_SIZE( sp ) lw t5, 7 * portWORD_SIZE( sp )
csrw lpstart0, t0 csrw lpstart0, t0
csrw lpend0, t1 csrw lpend0, t1
csrw lpcount0, t2 csrw lpcount0, t2

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]
* [chip specific registers go here] * [chip specific registers go here]
* mstatus
* 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,12 @@ 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. */
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 +220,31 @@ 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:
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 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
@ -235,46 +256,46 @@ xPortStartFirstTask:
load_x x1, 0( sp ) /* Note for starting the scheduler the exception return address is used as the function return address. */ load_x x1, 0( sp ) /* Note for starting the scheduler the exception return address is used as the function return address. */
load_x x5, 1 * portWORD_SIZE( sp ) /* Initial mstatus into x5 (t0). */
addi x5, x5, 0x08 /* Set MIE bit so the first task starts with interrupts enabled - required as returns with ret not eret. */
csrw mstatus, x5 /* Interrupts enabled from here! */
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 x7, 5 * portWORD_SIZE( sp ) /* t2 */
load_x x8, 5 * portWORD_SIZE( sp ) /* s0/fp */ load_x x8, 6 * portWORD_SIZE( sp ) /* s0/fp */
load_x x9, 6 * portWORD_SIZE( sp ) /* s1 */ load_x x9, 7 * portWORD_SIZE( sp ) /* s1 */
load_x x10, 7 * portWORD_SIZE( sp ) /* a0 */ load_x x10, 8 * portWORD_SIZE( sp ) /* a0 */
load_x x11, 8 * portWORD_SIZE( sp ) /* a1 */ load_x x11, 9 * portWORD_SIZE( sp ) /* a1 */
load_x x12, 9 * portWORD_SIZE( sp ) /* a2 */ load_x x12, 10 * portWORD_SIZE( sp ) /* a2 */
load_x x13, 10 * portWORD_SIZE( sp ) /* a3 */ load_x x13, 11 * portWORD_SIZE( sp ) /* a3 */
load_x x14, 11 * portWORD_SIZE( sp ) /* a4 */ load_x x14, 12 * portWORD_SIZE( sp ) /* a4 */
load_x x15, 12 * portWORD_SIZE( sp ) /* a5 */ 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 v0, (sp) /* Store v0-v7. */
add sp, sp, t0
vs8r.v v8, (sp) /* Store v8-v15. */
add sp, sp, t0
vs8r.v v16, (sp) /* Store v16-v23. */
add sp, sp, t0
vs8r.v v24, (sp) /* Store v24-v31. */
/* 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 v24, (sp)
add sp, sp, t0
vl8r.v v16, (sp)
add sp, sp, t0
vl8r.v v8, (sp)
add sp, sp, t0
vl8r.v v0, (sp)
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 FPU registers. */
portcontexSAVE_VPU_CONTEXT
2:
#endif
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. */
csrr t0, mstatus
store_x t0, 1 * portWORD_SIZE( sp )
#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. */
@ -142,46 +396,68 @@ load_x sp, 0 ( t1 ) /* Read sp from first TCB member. */
load_x t0, 0 ( sp ) load_x t0, 0 ( sp )
csrw mepc, t0 csrw mepc, t0
/* Restore mstatus register. */
load_x t0, 1 * portWORD_SIZE( sp )
csrw mstatus, 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. */ #if( configENABLE_VPU == 1 )
load_x t0, portMSTATUS_OFFSET * portWORD_SIZE( sp ) csrr t0, mstatus
csrw mstatus, t0 /* Required for MPIE bit. */ srl t1, t0, 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 )
csrr t0, mstatus
srl t1, t0, 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

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

@ -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);

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;