Compare commits
355 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9591025942 | ||
|
|
cbb74d4e2f | ||
|
|
718e4592aa | ||
|
|
0feccf788c | ||
|
|
d38d06e977 | ||
|
|
ac7fee87ee | ||
|
|
6bacdd47e6 | ||
|
|
ea2439e70c | ||
|
|
d7ba097fd9 | ||
|
|
3159e9fff2 | ||
|
|
24f823234b | ||
|
|
14e8f84e2a | ||
|
|
cec657b2df | ||
|
|
1f238a13dc | ||
|
|
bbdf13de87 | ||
|
|
f3e91773a0 | ||
|
|
0fbaf2c6fa | ||
|
|
fa619bd6ba | ||
|
|
3ad9394afd | ||
|
|
700f41f667 | ||
|
|
d295a4f2e0 | ||
|
|
d72212adb3 | ||
|
|
16766c2051 | ||
|
|
475a2a9bf8 | ||
|
|
af443132e8 | ||
|
|
17ddcc03a1 | ||
|
|
261c0d5c96 | ||
|
|
1221125664 | ||
|
|
810e590cb5 | ||
|
|
3d18496538 | ||
|
|
79e1aea7f0 | ||
|
|
936588eecc | ||
|
|
0d028847fd | ||
|
|
b813c894e3 | ||
|
|
362131533c | ||
|
|
68f5b4077d | ||
|
|
499614667f | ||
|
|
d9434250cc | ||
|
|
95674c0040 | ||
|
|
af0d895f34 | ||
|
|
a2fa459f99 | ||
|
|
26665eb1c8 | ||
|
|
f8c58efea5 | ||
|
|
e98cb34ce7 | ||
|
|
8a5e66b6f3 | ||
|
|
da3371db03 | ||
|
|
4019d67af4 | ||
|
|
4811886abc | ||
|
|
1f7c22bc42 | ||
|
|
be16b583bb | ||
|
|
d23e801ad5 | ||
|
|
65f70acd18 | ||
|
|
45ff6b2dca | ||
|
|
babb2bfb2b | ||
|
|
13d04abd1d | ||
|
|
0370797560 | ||
|
|
8f5b5db7db | ||
|
|
f0fa7e2de3 | ||
|
|
49b06f044c | ||
|
|
89add1b798 | ||
|
|
5ad3f4a693 | ||
|
|
3caa1ca92d | ||
|
|
61e084f102 | ||
|
|
5fcaeaa93c | ||
|
|
96d56cc84d | ||
|
|
3f19a2e020 | ||
|
|
0d5640ecd7 | ||
|
|
ce83a7c0ae | ||
|
|
31842cc9e4 | ||
|
|
4ec14cc693 | ||
|
|
07964c23f1 | ||
|
|
98d3225492 | ||
|
|
3a42ff922f | ||
|
|
1b397ddef2 | ||
|
|
ccb2844ec7 | ||
|
|
93874f0cca | ||
|
|
7ddd15c289 | ||
|
|
caacf7caef | ||
|
|
2fc4a1d94e | ||
|
|
be4de1a60a | ||
|
|
689d63b1a0 | ||
|
|
ad4afacff9 | ||
|
|
9d16440356 | ||
|
|
3204df2903 | ||
|
|
6f21f39b47 | ||
|
|
baae719e3f | ||
|
|
83f71a2caf | ||
|
|
36684b4519 | ||
|
|
d216624615 | ||
|
|
e54f97e5e9 | ||
|
|
d5ea318c8b | ||
|
|
662a5425e5 | ||
|
|
7dded23a84 | ||
|
|
c59da31415 | ||
|
|
3dae810785 | ||
|
|
040ecf154a | ||
|
|
0d983a3d56 | ||
|
|
97996f3abe | ||
|
|
4ef8660b9a | ||
|
|
5ff798407f | ||
|
|
0a09250d92 | ||
|
|
f078060387 | ||
|
|
3f402ba529 | ||
|
|
896085abc5 | ||
|
|
c38ec879f6 | ||
|
|
e41dd6d3d3 | ||
|
|
c86c1b19a0 | ||
|
|
30f4fcb039 | ||
|
|
d6679e7739 | ||
|
|
3be43c5e22 | ||
|
|
650475e7ad | ||
|
|
f5ab2a897b | ||
|
|
9d6617dcc3 | ||
|
|
c62e43aee4 | ||
|
|
8f6a0d7a67 | ||
|
|
bf5d17a862 | ||
|
|
e7ea607b6b | ||
|
|
ef725487e2 | ||
|
|
9866122685 | ||
|
|
6715b80abf | ||
|
|
6cc836df3b | ||
|
|
3283cabb70 | ||
|
|
2fd43e4617 | ||
|
|
0695270d3a | ||
|
|
1e783c649d | ||
|
|
326727dc54 | ||
|
|
da83659d36 | ||
|
|
da3cfaff90 | ||
|
|
788399bb8b | ||
|
|
657b2f51f6 | ||
|
|
6c26811d56 | ||
|
|
b5ea0989b6 | ||
|
|
500d85c26b | ||
|
|
d80c0500e5 | ||
|
|
11d60f9661 | ||
|
|
c367281156 | ||
|
|
a8578ea2aa | ||
|
|
b23f856c5d | ||
|
|
a6737bb8d9 | ||
|
|
84bf14d682 | ||
|
|
2b1a8dd77a | ||
|
|
0c57ca579b | ||
|
|
b3a4d9c308 | ||
|
|
66edcfcefb | ||
|
|
7a9ad1f741 | ||
|
|
9077f6d2cc | ||
|
|
9dae70c137 | ||
|
|
3fa36b23e6 | ||
|
|
bd46765601 | ||
|
|
fbf9ac1ad7 | ||
|
|
4d47ece3e6 | ||
|
|
868ca61b51 | ||
|
|
8ec8a58fe8 | ||
|
|
af4effd9de | ||
|
|
4afa7739db | ||
|
|
95e056b196 | ||
|
|
ed0c8812ee | ||
|
|
6b726c0260 | ||
|
|
0c5593a05f | ||
|
|
0420e0646d | ||
|
|
d19c19da28 | ||
|
|
e5823dcf5d | ||
|
|
2829372121 | ||
|
|
e584837d1e | ||
|
|
c93673fbec | ||
|
|
95c84b25a8 | ||
|
|
069b7d3ef8 | ||
|
|
3d112a6c72 | ||
|
|
9fa7db868c | ||
|
|
5f455a6e66 | ||
|
|
0ce629178d | ||
|
|
105ff0446f | ||
|
|
d3f50fb6a7 | ||
|
|
1117710ffc | ||
|
|
e7ae2f17ca | ||
|
|
0000746002 | ||
|
|
4dfcb881e9 | ||
|
|
8b0fdf54ac | ||
|
|
113924134e | ||
|
|
37b867b08a | ||
|
|
6cec0bcc6b | ||
|
|
233c6d8540 | ||
|
|
a5a7831f4e | ||
|
|
ab5c2e3d0e | ||
|
|
5ba8569470 | ||
|
|
5b8488a936 | ||
|
|
03a52401c6 | ||
|
|
a3db646ee7 | ||
|
|
45a1852ce7 | ||
|
|
eaf7c2f4c2 | ||
|
|
d5b83ae461 | ||
|
|
c9f0148e3c | ||
|
|
f0f74e4f0e | ||
|
|
dfb96f40d6 | ||
|
|
4899c096ae | ||
|
|
528f787ddd | ||
|
|
db50b4ec2a | ||
|
|
d3ca4bdbdb | ||
|
|
301558a433 | ||
|
|
919aa1785a | ||
|
|
0f01fe754c | ||
|
|
fb199a2ac5 | ||
|
|
3c6f0742a7 | ||
|
|
5bbae10490 | ||
|
|
24d7e9e03f | ||
|
|
d4fd267086 | ||
|
|
9fb22af194 | ||
|
|
f35dc9c018 | ||
|
|
2761887b20 | ||
|
|
de50834455 | ||
|
|
683e14cc94 | ||
|
|
ee793280f3 | ||
|
|
8c2c5618de | ||
|
|
d7d9988d55 | ||
|
|
7e37ef4a7c | ||
|
|
47588913d3 | ||
|
|
b1991f9d12 | ||
|
|
686f3d21b4 | ||
|
|
a92a530465 | ||
|
|
2ae7f09dad | ||
|
|
a880994e06 | ||
|
|
f06bb3f1cd | ||
|
|
ea02a080a6 | ||
|
|
1ab6102343 | ||
|
|
0608aa8ffe | ||
|
|
618a2a7ea3 | ||
|
|
a51247e5fc | ||
|
|
5a418dd8f8 | ||
|
|
15a830a1ef | ||
|
|
f3e094afe3 | ||
|
|
bd49769964 | ||
|
|
3472eeaed4 | ||
|
|
c9af4aa4a8 | ||
|
|
08c4c32e91 | ||
|
|
d3f926f73f | ||
|
|
7cf70968fc | ||
|
|
e3f71020d3 | ||
|
|
6e96c8abca | ||
|
|
39121ae854 | ||
|
|
21609c2562 | ||
|
|
1c18dc7b2f | ||
|
|
bdf05c01e3 | ||
|
|
99ddf9ce0c | ||
|
|
6712db44b9 | ||
|
|
17b2abec79 | ||
|
|
4f52e63153 | ||
|
|
ed5625a837 | ||
|
|
344e275f31 | ||
|
|
e2b31e6c29 | ||
|
|
52cecb5148 | ||
|
|
92ebf5e6a8 | ||
|
|
3bbcdc79d0 | ||
|
|
2371a976d1 | ||
|
|
6d174a2b75 | ||
|
|
e798ae7e07 | ||
|
|
6950a38cb3 | ||
|
|
8fa76985b1 | ||
|
|
63841b5607 | ||
|
|
6f2cf7986d | ||
|
|
a72f851d12 | ||
|
|
f5d9f0b2af | ||
|
|
38d186a878 | ||
|
|
1b7b809f1d | ||
|
|
42b8d0c747 | ||
|
|
c55d817744 | ||
|
|
9403dd3126 | ||
|
|
251f48682a | ||
|
|
9ca3f9a967 | ||
|
|
bccaa9f4b7 | ||
|
|
c1191dec2d | ||
|
|
b504992306 | ||
|
|
9d00571faa | ||
|
|
870429de9a | ||
|
|
14a1f91d1e | ||
|
|
581a8cf218 | ||
|
|
7c44108677 | ||
|
|
4d7977f31d | ||
|
|
d01d68835e | ||
|
|
c5dca7f96a | ||
|
|
6a3e7ac12c | ||
|
|
3e142b4fd8 | ||
|
|
6bd02e3f33 | ||
|
|
9430a7e4e6 | ||
|
|
5df0f30930 | ||
|
|
d7189919c5 | ||
|
|
012f1c7445 | ||
|
|
203021bedb | ||
|
|
0f8de841af | ||
|
|
7586e60a89 | ||
|
|
fd4c012fd8 | ||
|
|
2af72beaf5 | ||
|
|
1f509d3baf | ||
|
|
1973bfa703 | ||
|
|
841df9aed2 | ||
|
|
01e086c007 | ||
|
|
fc67da0f5c | ||
|
|
8b0f062ff4 | ||
|
|
3f09b1293c | ||
|
|
2d05e7ab3f | ||
|
|
eee12033e7 | ||
|
|
cd8ccef8e4 | ||
|
|
ed6dc0ef13 | ||
|
|
7526dab2d5 | ||
|
|
c73cf83d85 | ||
|
|
26357e8e99 | ||
|
|
6fe0f2a14a | ||
|
|
c90b6332dc | ||
|
|
fdde0b06cf | ||
|
|
550e3165aa | ||
|
|
a4cc1f0fdc | ||
|
|
85348add23 | ||
|
|
f8be489b2e | ||
|
|
8812c7fd08 | ||
|
|
6cbdf40036 | ||
|
|
16a74a2fed | ||
|
|
c297c82039 | ||
|
|
1c5fa377a1 | ||
|
|
19b96e997e | ||
|
|
28ae163885 | ||
|
|
b8c44c2ada | ||
|
|
41b07b1d86 | ||
|
|
88b82c8152 | ||
|
|
6bd361409e | ||
|
|
12d6aa8b44 | ||
|
|
2ddf341e40 | ||
|
|
d4163bc17e | ||
|
|
14fe45898f | ||
|
|
f1b0df08e9 | ||
|
|
cea42e3554 | ||
|
|
e2d715b319 | ||
|
|
eb4fa6f000 | ||
|
|
a64cdc8388 | ||
|
|
56481d9edd | ||
|
|
8bf9538caf | ||
|
|
756ae3d542 | ||
|
|
fb5bde6f70 | ||
|
|
6993ee3cbf | ||
|
|
8d72bbdc79 | ||
|
|
a4afa13a7a | ||
|
|
93558f2fb9 | ||
|
|
23b54e42c3 | ||
|
|
ee9d7a960b | ||
|
|
a68fd9c733 | ||
|
|
ed47cf92cb | ||
|
|
25b00e8b6d | ||
|
|
1a9ef5ef4a | ||
|
|
349cc71d63 | ||
|
|
bdcc09ff2c | ||
|
|
c6325a66ca | ||
|
|
29c3fe5d77 | ||
|
|
82f176311d | ||
|
|
1b099c3e13 | ||
|
|
9132dcc697 | ||
|
|
d8236589e9 | ||
|
|
247330d62a |
@@ -1,4 +1,5 @@
|
||||
--mailback
|
||||
--no-tree
|
||||
--emacs
|
||||
--summary-file
|
||||
--show-types
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -8,7 +8,6 @@
|
||||
*.swo
|
||||
*~
|
||||
build*/
|
||||
!doc/guides/build
|
||||
cscope.*
|
||||
.dir
|
||||
|
||||
@@ -35,6 +34,7 @@ bsim_bt_out
|
||||
scripts/grub
|
||||
doc/reference/kconfig/*.rst
|
||||
doc/doc.warnings
|
||||
tags
|
||||
.*project
|
||||
.settings
|
||||
.envrc
|
||||
@@ -45,7 +45,5 @@ hide-defaults-note
|
||||
GPATH
|
||||
GRTAGS
|
||||
GTAGS
|
||||
TAGS
|
||||
tags
|
||||
|
||||
.idea
|
||||
|
||||
2
.gitlint
2
.gitlint
@@ -13,7 +13,7 @@ debug = false
|
||||
extra-path=scripts/gitlint
|
||||
|
||||
[title-max-length-no-revert]
|
||||
line-length=75
|
||||
line-length=72
|
||||
|
||||
[body-min-line-count]
|
||||
min-line-count=1
|
||||
|
||||
10
.mailmap
10
.mailmap
@@ -20,13 +20,3 @@ Felipe Neves <ryukokki.felipe@gmail.com> <ryukokki.felipe@gmail.com>
|
||||
Amir Kaplan <amir.kaplan@intel.com> <amir.kaplan@intel.com>
|
||||
Anas Nashif <anas.nashif@intel.com> <anas.nashif@intel.com>
|
||||
Ruud Derwig <Ruud.Derwig@synopsys.com> <Ruud.Derwig@synopsys.com>
|
||||
Flavio Arieta Netto <flavio@exati.com.br>
|
||||
Nishikant Nayak <nishikantax.nayak@intel.com>
|
||||
Justin Watson <jwatson5@gmail.com>
|
||||
Johann Fischer <j.fischer@phytec.de>
|
||||
Jun Li <jun.r.li@intel.com>
|
||||
Xiaorui Hu <xiaorui.hu@linaro.org>
|
||||
Yannis Damigos <giannis.damigos@gmail.com> <ydamigos@iccs.gr>
|
||||
Vinayak Kariappa Chettimada <vinayak.kariappa.chettimada@nordicsemi.no> <vinayak.kariappa.chettimada@nordicsemi.no> <vich@nordicsemi.no> <vinayak.kariappa@gmail.com>
|
||||
Sean Nyekjaer <sean@geanix.com> <sean.nyekjaer@prevas.dk>
|
||||
Sean Nyekjaer <sean@geanix.com> <sean@nyekjaer.dk>
|
||||
|
||||
@@ -4,7 +4,8 @@ compiler: gcc
|
||||
|
||||
env:
|
||||
global:
|
||||
- ZEPHYR_SDK_INSTALL_DIR=/opt/sdk/zephyr-sdk-0.10.3
|
||||
- SDK=0.10.0
|
||||
- ZEPHYR_SDK_INSTALL_DIR=/opt/sdk/zephyr-sdk-0.10.0
|
||||
- ZEPHYR_TOOLCHAIN_VARIANT=zephyr
|
||||
- MATRIX_BUILDS="5"
|
||||
matrix:
|
||||
@@ -20,7 +21,7 @@ build:
|
||||
- ${SHIPPABLE_BUILD_DIR}/ccache
|
||||
pre_ci_boot:
|
||||
image_name: zephyrprojectrtos/ci
|
||||
image_tag: v0.9.1
|
||||
image_tag: v0.6.4
|
||||
pull: true
|
||||
options: "-e HOME=/home/buildslave --privileged=true --tty --net=bridge --user buildslave"
|
||||
|
||||
@@ -70,6 +71,9 @@ integrations:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- net
|
||||
- bluetooth
|
||||
- arm
|
||||
- v1.14-branch
|
||||
on_success: never
|
||||
on_failure: always
|
||||
on_pull_request: never
|
||||
on_failure: never
|
||||
|
||||
882
CMakeLists.txt
882
CMakeLists.txt
File diff suppressed because it is too large
Load Diff
332
CODEOWNERS
332
CODEOWNERS
@@ -1,64 +1,52 @@
|
||||
# CODEOWNERS for autoreview assigning in github
|
||||
|
||||
# https://help.github.com/en/articles/about-code-owners#codeowners-syntax
|
||||
|
||||
# Order is important; for each modified file, the last matching
|
||||
# pattern takes the most precedence.
|
||||
# That is, with the last pattern being
|
||||
# *.rst @dbkinder
|
||||
# if only .rst files are being modified, only dbkinder is
|
||||
# automatically requested for review, but you can manually
|
||||
# add others as needed.
|
||||
# Order is important; the last matching pattern takes the most
|
||||
# precedence.
|
||||
|
||||
# Do not use wildcard on all source yet
|
||||
# * @galak @nashif
|
||||
|
||||
/.known-issues/ @inakypg @nashif
|
||||
/arch/arc/ @vonhust @ruuddw
|
||||
/arch/arm/ @MaureenHelm @galak @ioannisg
|
||||
/arch/arm/ @MaureenHelm @galak
|
||||
/arch/arm/core/cortex_m/cmse/ @ioannisg
|
||||
/arch/arm/include/cortex_m/cmse.h @ioannisg
|
||||
/arch/arm/core/cortex_r/ @MaureenHelm @galak @ioannisg @bbolen
|
||||
/arch/common/ @andrewboie @ioannisg @andyross
|
||||
/soc/arc/snps_*/ @vonhust @ruuddw
|
||||
/soc/nios2/ @nashif @wentongwu
|
||||
/soc/arm/ @MaureenHelm @galak @ioannisg
|
||||
arch/arm/include/cortex_m/cmse.h @ioannisg
|
||||
/soc/arm/ @MaureenHelm @galak
|
||||
/soc/arm/arm/mps2/ @fvincenzo
|
||||
/soc/arm/atmel_sam/sam3x/ @ioannisg
|
||||
/soc/arm/atmel_sam/sam4s/ @fallrisk
|
||||
/soc/arm/nxp*/ @MaureenHelm
|
||||
/soc/arm/nordic_nrf/ @ioannisg
|
||||
/soc/arm/st_stm32/ @erwango
|
||||
/soc/arm/st_stm32/stm32f4/ @rsalveti @idlethread
|
||||
/soc/arm/st_stm32/stm32mp1/ @arnop2
|
||||
/soc/arm/ti_simplelink/cc13x2_cc26x2/ @bwitherspoon
|
||||
/soc/arm/ti_simplelink/cc32xx/ @vanti
|
||||
/soc/arm/ti_simplelink/msp432p4xx/ @Mani-Sadhasivam
|
||||
/soc/xtensa/intel_s1000/ @sathishkuttan @dcpleung
|
||||
/arch/x86/ @andrewboie
|
||||
/arch/nios2/ @andrewboie @wentongwu
|
||||
/soc/xtensa/intel_s1000/ @sathishkuttan @dcpleung @rgundi
|
||||
/arch/nios2/ @andrewboie @ramakrishnapallala
|
||||
/arch/posix/ @aescolar
|
||||
/arch/riscv/ @kgugala @pgielda @nategraff-sifive
|
||||
/arch/riscv32/ @kgugala @pgielda @nategraff-sifive
|
||||
/soc/posix/ @aescolar
|
||||
/soc/riscv/ @kgugala @pgielda @nategraff-sifive
|
||||
/soc/riscv/openisa*/ @MaureenHelm
|
||||
/soc/x86/ @andrewboie
|
||||
/arch/xtensa/ @andrewboie @dcpleung @andyross
|
||||
/soc/xtensa/ @andrewboie @dcpleung @andyross
|
||||
/soc/riscv32/ @kgugala @pgielda @nategraff-sifive
|
||||
/arch/x86/ @andrewboie @ramakrishnapallala
|
||||
/arch/x86/core/ @andrewboie
|
||||
/arch/x86/core/crt0.S @ramakrishnapallala @nashif
|
||||
/soc/x86/ @andrewboie @ramakrishnapallala
|
||||
/soc/x86/intel_quark/quark_d2000/ @nashif
|
||||
/soc/x86/intel_quark/quark_se/ @nashif
|
||||
/soc/x86/intel_quark/quark_x1000/ @nashif
|
||||
/arch/xtensa/ @andrewboie @rgundi @andyross
|
||||
/soc/xtensa/ @andrewboie @rgundi @andyross
|
||||
/boards/arc/ @vonhust @ruuddw
|
||||
/boards/arc/arduino_101_sss/ @nashif
|
||||
/boards/arc/em_starterkit/ @vonhust
|
||||
/boards/arc/quark_se_c1000_ss_devboard/ @nashif
|
||||
/boards/arm/ @MaureenHelm @galak
|
||||
/boards/arm/96b_argonkey/ @avisconti
|
||||
/boards/arm/96b_avenger96/ @Mani-Sadhasivam
|
||||
/boards/arm/96b_carbon/ @rsalveti @idlethread
|
||||
/boards/arm/96b_meerkat96/ @Mani-Sadhasivam
|
||||
/boards/arm/96b_nitrogen/ @idlethread
|
||||
/boards/arm/96b_neonkey/ @Mani-Sadhasivam
|
||||
/boards/arm/96b_stm32_sensor_mez/ @Mani-Sadhasivam
|
||||
/boards/arm/96b_wistrio/ @Mani-Sadhasivam
|
||||
/boards/arm/arduino_due/ @ioannisg
|
||||
/boards/arm/cc1352r1_launchxl/ @bwitherspoon
|
||||
/boards/arm/cc26x2r1_launchxl/ @bwitherspoon
|
||||
/boards/arm/cc3220sf_launchxl/ @vanti
|
||||
/boards/arm/curie_ble/ @jhedberg
|
||||
/boards/arm/disco_l475_iot1/ @erwango
|
||||
/boards/arm/frdm*/ @MaureenHelm
|
||||
/boards/arm/frdm*/doc/ @MaureenHelm @MeganHansen
|
||||
@@ -70,219 +58,158 @@
|
||||
/boards/arm/mimxrt*/doc/ @MaureenHelm @MeganHansen
|
||||
/boards/arm/mps2_an385/ @fvincenzo
|
||||
/boards/arm/msp_exp432p401r_launchxl/ @Mani-Sadhasivam
|
||||
/boards/arm/nrf*/ @carlescufi @lemrey @ioannisg
|
||||
/boards/arm/nrf51_blenano/ @rsalveti
|
||||
/boards/arm/nrf51_pca10028/ @carlescufi
|
||||
/boards/arm/nrf52_pca10040/ @carlescufi
|
||||
/boards/arm/nrf52_pca20020/ @tkln
|
||||
/boards/arm/nrf52810_pca10040/ @carlescufi
|
||||
/boards/arm/nrf52840_pca10056/ @carlescufi
|
||||
/boards/arm/nrf52840_pca10059/ @lemrey
|
||||
/boards/arm/nrf9160_pca10090/ @ioannisg
|
||||
/boards/arm/nucleo*/ @erwango
|
||||
/boards/arm/nucleo_f401re/ @rsalveti @idlethread
|
||||
/boards/arm/qemu_cortex_m*/ @ioannisg
|
||||
/boards/arm/sam4s_xplained/ @fallrisk
|
||||
/boards/arm/v2m_beetle/ @fvincenzo
|
||||
/boards/arm/olimexino_stm32/ @ydamigos
|
||||
/boards/arm/sensortile_box/ @avisconti
|
||||
/boards/arm/steval_fcu001v1/ @Navin-Sankar
|
||||
/boards/arm/stm32l1_disco/ @karlp
|
||||
/boards/arm/stm32*_disco/ @erwango
|
||||
/boards/arm/stm32f3_disco/ @ydamigos
|
||||
/boards/arm/stm32*_eval/ @erwango
|
||||
/boards/common/ @mbolivar
|
||||
/boards/nios2/ @wentongwu
|
||||
/boards/nios2/altera_max10/ @wentongwu
|
||||
/boards/arm/stm32_min_dev/ @cbsiddharth
|
||||
/boards/nios2/ @ramakrishnapallala
|
||||
/boards/nios2/altera_max10/ @ramakrishnapallala
|
||||
/boards/posix/ @aescolar
|
||||
/boards/riscv/ @kgugala @pgielda @nategraff-sifive
|
||||
/boards/riscv/rv32m1_vega/ @MaureenHelm
|
||||
/boards/riscv32/ @kgugala @pgielda @nategraff-sifive
|
||||
/boards/shields/ @erwango
|
||||
/boards/x86/ @andrewboie @nashif
|
||||
/boards/x86/arduino_101/ @nashif
|
||||
/boards/x86/galileo/ @nashif
|
||||
/boards/x86/quark_d2000_crb/ @nashif
|
||||
/boards/x86/quark_se_c1000_devboard/ @nashif
|
||||
/boards/xtensa/ @nashif @dcpleung
|
||||
/boards/xtensa/intel_s1000_crb/ @sathishkuttan @dcpleung
|
||||
/boards/xtensa/odroid_go/ @ydamigos
|
||||
# All cmake related files
|
||||
/cmake/ @SebastianBoe @nashif
|
||||
/cmake/compiler/xcc/ @nashif
|
||||
/cmake/toolchain/xcc/ @nashif
|
||||
/CMakeLists.txt @SebastianBoe @nashif
|
||||
/doc/ @dbkinder
|
||||
/doc/guides/coccinelle.rst @himanshujha199640 @JuliaLawall
|
||||
/doc/CMakeLists.txt @carlescufi
|
||||
/doc/scripts/ @carlescufi
|
||||
/doc/guides/bluetooth/ @joerchan @jhedberg @Vudentz
|
||||
/doc/reference/bluetooth/ @joerchan @jhedberg @Vudentz
|
||||
/drivers/*/*cc13xx_cc26xx* @bwitherspoon
|
||||
/doc/guides/bluetooth/ @sjanc @jhedberg @Vudentz
|
||||
/doc/reference/bluetooth/ @sjanc @jhedberg @Vudentz
|
||||
/drivers/*/*mcux* @MaureenHelm
|
||||
/drivers/*/*qmsi* @nashif
|
||||
/drivers/*/*stm32* @erwango
|
||||
/drivers/*/*native_posix* @aescolar
|
||||
/drivers/adc/ @anangl
|
||||
/drivers/adc/adc_stm32.c @cybertale
|
||||
/drivers/bluetooth/ @joerchan @jhedberg @Vudentz
|
||||
/drivers/bluetooth/ @sjanc @jhedberg @Vudentz
|
||||
/drivers/can/ @alexanderwachter
|
||||
/drivers/can/*mcp2515* @karstenkoenig
|
||||
/drivers/clock_control/*nrf* @nordic-krch
|
||||
/drivers/clock_control/*stm32f4* @rsalveti @idlethread
|
||||
/drivers/counter/ @nordic-krch
|
||||
/drivers/counter/counter_cmos.c @andrewboie
|
||||
/drivers/display/ @vanwinkeljan
|
||||
/drivers/display/display_framebuf.c @andrewboie
|
||||
/drivers/dma/*sam0* @Sizurka
|
||||
/drivers/dma/dma_stm32* @cybertale
|
||||
/drivers/eeprom/ @henrikbrixandersen
|
||||
/drivers/entropy/*rv32m1* @MaureenHelm
|
||||
/drivers/espi/ @albertofloyd @franciscomunoz @scottwcpg
|
||||
/drivers/ps2/ @albertofloyd @franciscomunoz @scottwcpg
|
||||
/drivers/kscan/ @albertofloyd @franciscomunoz @scottwcpg
|
||||
/drivers/ethernet/ @jukkar @tbursztyka @pfalcon
|
||||
/drivers/flash/ @nashif @nvlsianpu
|
||||
/drivers/flash/*native_posix* @vanwinkeljan @aescolar
|
||||
/drivers/flash/*nrf* @nvlsianpu
|
||||
/drivers/flash/*spi_nor* @pabigot
|
||||
/drivers/flash/ @nashif
|
||||
/drivers/flash/*stm32* @superna9999
|
||||
/drivers/gpio/ @mnkp @pabigot
|
||||
/drivers/gpio/*ht16k33* @henrikbrixandersen
|
||||
/drivers/gpio/*stm32* @rsalveti @idlethread
|
||||
/drivers/hwinfo/ @alexanderwachter
|
||||
/drivers/i2s/i2s_ll_stm32* @avisconti
|
||||
/drivers/ieee802154/ @jukkar @tbursztyka
|
||||
/drivers/interrupt_controller/ @andrewboie
|
||||
/drivers/ipm/ipm_mhu* @karl-zh
|
||||
/drivers/ipm/Kconfig.nrfx @masz-nordic @ioannisg
|
||||
/drivers/ipm/Kconfig.nrfx_ipc_channel @masz-nordic @ioannisg
|
||||
/drivers/ipm/ipm_nrfx_ipc.c @masz-nordic @ioannisg
|
||||
/drivers/ipm/ipm_nrfx_ipc.h @masz-nordic @ioannisg
|
||||
/drivers/ipm/ipm_stm32_ipcc.c @arnop2
|
||||
/drivers/*/vexriscv_litex.c @mateusz-holenko @kgugala @pgielda
|
||||
/drivers/led/ @Mani-Sadhasivam
|
||||
/drivers/led_strip/ @mbolivar
|
||||
/drivers/modem/ @mike-scott
|
||||
/drivers/pcie/ @andrewboie
|
||||
/drivers/pci/ @gnuless
|
||||
/drivers/pinmux/stm32/ @rsalveti @idlethread
|
||||
/drivers/pinmux/*hsdk* @iriszzw
|
||||
/drivers/sensor/ @MaureenHelm
|
||||
/drivers/sensor/ams_iAQcore/ @alexanderwachter
|
||||
/drivers/sensor/ens210/ @alexanderwachter
|
||||
/drivers/sensor/ @bogdan-davidoaia @MaureenHelm
|
||||
/drivers/sensor/hts*/ @avisconti
|
||||
/drivers/sensor/lis*/ @avisconti
|
||||
/drivers/sensor/lps*/ @avisconti
|
||||
/drivers/sensor/lsm*/ @avisconti
|
||||
/drivers/sensor/st*/ @avisconti
|
||||
/drivers/serial/uart_altera_jtag_hal.c @wentongwu
|
||||
/drivers/serial/*ns16550* @andrewboie
|
||||
/drivers/serial/Kconfig.litex @mateusz-holenko @kgugala @pgielda
|
||||
/drivers/serial/uart_liteuart.c @mateusz-holenko @kgugala @pgielda
|
||||
/drivers/serial/Kconfig.rtt @carlescufi @pkral78
|
||||
/drivers/serial/uart_rtt.c @carlescufi @pkral78
|
||||
/drivers/serial/Kconfig.xlnx @wjliang
|
||||
/drivers/serial/uart_xlnx_ps.c @wjliang
|
||||
/drivers/net/ @jukkar @tbursztyka
|
||||
/drivers/ptp_clock/ @jukkar
|
||||
/drivers/pwm/pwm_shell.c @henrikbrixandersen
|
||||
/drivers/serial/uart_altera_jtag_hal.c @ramakrishnapallala
|
||||
/drivers/net/slip.c @jukkar @tbursztyka
|
||||
/drivers/spi/ @tbursztyka
|
||||
/drivers/spi/spi_ll_stm32.* @superna9999
|
||||
/drivers/spi/spi_rv32m1_lpspi* @karstenkoenig
|
||||
/drivers/timer/apic_timer.c @andrewboie
|
||||
/drivers/timer/cortex_m_systick.c @ioannisg
|
||||
/drivers/timer/altera_avalon_timer_hal.c @wentongwu
|
||||
/drivers/timer/altera_avalon_timer_hal.c @ramakrishnapallala
|
||||
/drivers/timer/riscv_machine_timer.c @nategraff-sifive @kgugala @pgielda
|
||||
/drivers/timer/litex_timer.c @mateusz-holenko @kgugala @pgielda
|
||||
/drivers/timer/xlnx_psttc_timer.c @wjliang
|
||||
/drivers/timer/cc13x2_cc26x2_rtc_timer.c @vanti
|
||||
/drivers/usb/ @jfischer-phytec-iot @finikorg
|
||||
/drivers/usb/device/usb_dc_stm32.c @ydamigos @loicpoulain
|
||||
/drivers/video/ @loicpoulain
|
||||
/drivers/i2c/i2c_ll_stm32* @ldts @ydamigos
|
||||
/drivers/i2c/i2c_rv32m1_lpi2c* @henrikbrixandersen
|
||||
/drivers/i2c/*sam0* @Sizurka
|
||||
/drivers/i2c/i2c_dw* @dcpleung
|
||||
/drivers/*/*xec* @franciscomunoz @albertofloyd @scottwcpg
|
||||
/drivers/wifi/ @jukkar @tbursztyka @pfalcon
|
||||
/drivers/wifi/eswifi/ @loicpoulain
|
||||
/dts/arc/ @vonhust @ruuddw @iriszzw
|
||||
/dts/arm/atmel/samr21.dtsi @benpicco
|
||||
/dts/arm/atmel/sam*5*.dtsi @benpicco
|
||||
/dts/arm/st/ @erwango
|
||||
/dts/arm/ti/cc13?2* @bwitherspoon
|
||||
/dts/arm/ti/cc26?2* @bwitherspoon
|
||||
/dts/arm/ti/cc3235* @vanti
|
||||
/dts/arm/nordic/ @ioannisg @carlescufi
|
||||
/dts/arm/nxp/ @MaureenHelm
|
||||
/dts/arm/microchip/ @franciscomunoz @albertofloyd @scottwcpg
|
||||
/dts/riscv/microsemi-miv.dtsi @galak
|
||||
/dts/riscv/rv32m1* @MaureenHelm
|
||||
/dts/riscv/riscv32-fe310.dtsi @nategraff-sifive
|
||||
/dts/riscv/riscv32-litex-vexriscv.dtsi @mateusz-holenko @kgugala @pgielda
|
||||
/dts/arm/armv7-r.dtsi @bbolen
|
||||
/dts/arm/xilinx/ @bbolen
|
||||
/dts/xtensa/xtensa.dtsi @ydamigos
|
||||
/dts/bindings/ @galak
|
||||
/dts/bindings/can/ @alexanderwachter
|
||||
/dts/bindings/iio/adc/st*stm32-adc.yaml @cybertale
|
||||
/dts/bindings/serial/ns16550.yaml @andrewboie
|
||||
/dts/bindings/*/nordic* @anangl
|
||||
/dts/bindings/*/nxp* @MaureenHelm
|
||||
/dts/bindings/*/openisa* @MaureenHelm
|
||||
/dts/bindings/*/st* @erwango
|
||||
/dts/bindings/sensor/ams* @alexanderwachter
|
||||
/dts/bindings/*/sifive* @mateusz-holenko @kgugala @pgielda @nategraff-sifive
|
||||
/dts/bindings/*/litex* @mateusz-holenko @kgugala @pgielda
|
||||
/dts/bindings/*/vexriscv* @mateusz-holenko @kgugala @pgielda
|
||||
/dts/posix/ @aescolar @vanwinkeljan
|
||||
/dts/bindings/sensor/*bme680* @BoschSensortec
|
||||
/dts/bindings/sensor/st* @avisconti
|
||||
/ext/hal/cmsis/ @MaureenHelm @galak @stephanosio
|
||||
/ext/fs/ @nashif @ramakrishnapallala
|
||||
/ext/hal/cmsis/ @MaureenHelm @galak
|
||||
/ext/hal/libmetal/ @galak
|
||||
/ext/hal/nordic/ @carlescufi @anangl
|
||||
/ext/hal/nxp/ @MaureenHelm
|
||||
/ext/hal/qmsi/ @nashif
|
||||
/ext/hal/st/stm32cube/ @erwango
|
||||
/ext/hal/ti/simplelink/ @vanti
|
||||
/ext/lib/crypto/mbedtls/ @nashif
|
||||
/ext/lib/crypto/tinycrypt/ @ceolin
|
||||
/include/ @nashif @carlescufi @galak @MaureenHelm
|
||||
/include/drivers/adc.h @anangl
|
||||
/include/drivers/can.h @alexanderwachter
|
||||
/include/drivers/counter.h @nordic-krch
|
||||
/include/drivers/display.h @vanwinkeljan
|
||||
/include/drivers/espi.h @albertofloyd @franciscomunoz @scottwcpg
|
||||
/include/drivers/bluetooth/ @joerchan @jhedberg @Vudentz
|
||||
/include/drivers/flash.h @nashif @carlescufi @galak @MaureenHelm @nvlsianpu
|
||||
/include/drivers/led/ht16k33.h @henrikbrixandersen
|
||||
/include/drivers/interrupt_controller/ @andrewboie
|
||||
/include/drivers/pcie/ @andrewboie
|
||||
/include/drivers/hwinfo.h @alexanderwachter
|
||||
/include/drivers/led.h @Mani-Sadhasivam
|
||||
/include/drivers/led_strip.h @mbolivar
|
||||
/include/drivers/sensor.h @MaureenHelm
|
||||
/include/drivers/spi.h @tbursztyka
|
||||
/include/adc.h @anangl
|
||||
/include/app_memory/ @andrewboie
|
||||
/include/arch/arc/ @vonhust @ruuddw
|
||||
/include/arch/arc/arch.h @andrewboie
|
||||
/include/arch/arc/v2/irq.h @andrewboie
|
||||
/include/arch/arm/ @MaureenHelm @galak @ioannisg
|
||||
/include/arch/arm/irq.h @andrewboie
|
||||
/include/arch/arm/ @MaureenHelm @galak
|
||||
/include/arch/arm/cortex_m/irq.h @andrewboie
|
||||
/include/arch/nios2/ @andrewboie
|
||||
/include/arch/nios2/arch.h @andrewboie
|
||||
/include/arch/posix/ @aescolar
|
||||
/include/arch/riscv/ @nategraff-sifive @kgugala @pgielda
|
||||
/include/arch/x86/ @andrewboie @wentongwu
|
||||
/include/arch/common/ @andrewboie @andyross @nashif
|
||||
/include/arch/riscv32/ @nategraff-sifive @kgugala @pgielda
|
||||
/include/arch/x86/ @andrewboie @ramakrishnapallala
|
||||
/include/arch/x86/arch.h @andrewboie
|
||||
/include/arch/xtensa/ @andrewboie
|
||||
/include/sys/atomic.h @andrewboie @andyross
|
||||
/include/bluetooth/ @joerchan @jhedberg @Vudentz
|
||||
/include/atomic.h @andrewboie @andyross
|
||||
/include/bluetooth/ @sjanc @jhedberg @Vudentz
|
||||
/include/cache.h @andrewboie @andyross
|
||||
/include/device.h @wentongwu @nashif
|
||||
/include/can.h @alexanderwachter
|
||||
/include/counter.h @nordic-krch
|
||||
/include/device.h @ramakrishnapallala @nashif
|
||||
/include/display.h @vanwinkeljan
|
||||
/include/display/ @vanwinkeljan
|
||||
/include/dt-bindings/clock/kinetis_mcg.h @henrikbrixandersen
|
||||
/include/dt-bindings/clock/kinetis_scg.h @henrikbrixandersen
|
||||
/include/dt-bindings/dma/stm32_dma.h @cybertale
|
||||
/include/dt-bindings/pcie/ @andrewboie
|
||||
/include/dt-bindings/usb/usb.h @galak @finikorg
|
||||
/include/fs/ @nashif @wentongwu
|
||||
/include/drivers/bluetooth/ @sjanc @jhedberg @Vudentz
|
||||
/include/drivers/modem/ @mike-scott
|
||||
/include/drivers/ioapic.h @andrewboie
|
||||
/include/drivers/loapic.h @andrewboie
|
||||
/include/drivers/mvic.h @andrewboie
|
||||
/include/fs.h @nashif @ramakrishnapallala
|
||||
/include/fs/ @nashif @ramakrishnapallala
|
||||
/include/hwinfo.h @alexanderwachter
|
||||
/include/init.h @andrewboie @andyross
|
||||
/include/irq.h @andrewboie @andyross
|
||||
/include/irq_offload.h @andrewboie @andyross
|
||||
/include/kernel.h @andrewboie @andyross
|
||||
/include/kernel_version.h @andrewboie @andyross
|
||||
/include/led.h @Mani-Sadhasivam
|
||||
/include/led_strip.h @mbolivar
|
||||
/include/linker/app_smem*.ld @andrewboie
|
||||
/include/linker/ @andrewboie @andyross
|
||||
/include/linker/linker-defs.h @andrewboie @andyross
|
||||
/include/linker/linker-tool-gcc.h @andrewboie @andyross
|
||||
/include/linker/linker-tool.h @andrewboie @andyross
|
||||
/include/linker/section_tags.h @andrewboie @andyross
|
||||
/include/linker/sections.h @andrewboie @andyross
|
||||
/include/logging/ @nordic-krch
|
||||
/include/misc/ @andrewboie @andyross
|
||||
/include/net/ @jukkar @tbursztyka @pfalcon
|
||||
/include/net/buf.h @jukkar @jhedberg @tbursztyka @pfalcon
|
||||
/include/posix/ @pfalcon
|
||||
/include/power/power.h @wentongwu @nashif
|
||||
/include/ptp_clock.h @jukkar
|
||||
/include/power.h @ramakrishnapallala @nashif
|
||||
/include/sensor.h @bogdan-davidoaia
|
||||
/include/shared_irq.h @andrewboie @andyross
|
||||
/include/shell/ @jakub-uC @nordic-krch
|
||||
/include/shell/ @jarz-nordic @nordic-krch
|
||||
/include/spi.h @tbursztyka
|
||||
/include/sw_isr_table.h @andrewboie @andyross
|
||||
/include/sys_clock.h @andrewboie @andyross
|
||||
/include/sys/sys_io.h @andrewboie @andyross
|
||||
/include/sys_io.h @andrewboie @andyross
|
||||
/include/toolchain.h @andrewboie @andyross @nashif
|
||||
/include/toolchain/ @andrewboie @andyross
|
||||
/include/zephyr.h @andrewboie @andyross
|
||||
@@ -290,107 +217,75 @@
|
||||
/lib/gui/ @vanwinkeljan
|
||||
/lib/os/ @andrewboie @andyross
|
||||
/lib/posix/ @pfalcon
|
||||
/lib/cmsis_rtos_v2/ @nashif
|
||||
/lib/cmsis_rtos_v1/ @nashif
|
||||
/lib/libc/ @nashif @andrewboie
|
||||
/modules/ @nashif
|
||||
/kernel/device.c @andrewboie @andyross @nashif
|
||||
/kernel/idle.c @andrewboie @andyross @nashif
|
||||
/samples/ @nashif
|
||||
/samples/basic/minimal/ @carlescufi
|
||||
/samples/basic/servo_motor/*microbit* @jhe
|
||||
/lib/updatehub/ @chtavares592 @otavio
|
||||
/samples/bluetooth/ @jhedberg @Vudentz @joerchan
|
||||
/samples/boards/intel_s1000_crb/ @sathishkuttan @dcpleung @nashif
|
||||
/samples/bluetooth/ @sjanc @jhedberg @Vudentz
|
||||
/samples/boards/intel_s1000_crb/ @sathishkuttan @rgundi @nashif
|
||||
/samples/display/ @vanwinkeljan
|
||||
/samples/drivers/CAN/ @alexanderwachter
|
||||
/samples/drivers/ht16k33/ @henrikbrixandersen
|
||||
/samples/gui/ @vanwinkeljan
|
||||
/samples/net/ @jukkar @tbursztyka @pfalcon
|
||||
/samples/net/dns_resolve/ @jukkar @tbursztyka @pfalcon
|
||||
/samples/net/lwm2m_client/ @mike-scott
|
||||
/samples/net/mqtt_publisher/ @jukkar @tbursztyka
|
||||
/samples/net/sockets/coap_*/ @rveerama1
|
||||
/samples/net/sockets/coap_client/ @rveerama1
|
||||
/samples/net/sockets/coap_server/ @rveerama1
|
||||
/samples/net/sockets/ @jukkar @tbursztyka @pfalcon
|
||||
/samples/net/updatehub/ @chtavares592 @otavio
|
||||
/samples/sensor/ @MaureenHelm
|
||||
/samples/shields/ @avisconti
|
||||
/samples/subsys/logging/ @nordic-krch @jakub-uC
|
||||
/samples/subsys/shell/ @jakub-uC @nordic-krch
|
||||
/samples/sensor/ @bogdan-davidoaia
|
||||
/samples/subsys/logging/ @nordic-krch @jarz-nordic
|
||||
/samples/subsys/shell/ @jarz-nordic @nordic-krch
|
||||
/samples/subsys/usb/ @jfischer-phytec-iot @finikorg
|
||||
/samples/subsys/power/ @wentongwu @pabigot
|
||||
/samples/subsys/power/ @ramakrishnapallala @pizi-nordic
|
||||
/scripts/coccicheck @himanshujha199640 @JuliaLawall
|
||||
/scripts/coccinelle/ @himanshujha199640 @JuliaLawall
|
||||
/scripts/kconfig/ @ulfalizer
|
||||
/scripts/elf_helper.py @andrewboie
|
||||
/scripts/sanity_chk/expr_parser.py @nashif
|
||||
/scripts/sanity_chk/expr_parser.py @andrewboie @nashif
|
||||
/scripts/gen_app_partitions.py @andrewboie
|
||||
/scripts/dts/ @ulfalizer @galak
|
||||
/scripts/release/ @nashif
|
||||
/arch/x86/gen_gdt.py @andrewboie
|
||||
/arch/x86/gen_idt.py @andrewboie
|
||||
/scripts/gen_kobject_list.py @andrewboie
|
||||
/scripts/gen_priv_stacks.py @andrewboie @agross-oss @ioannisg
|
||||
/arch/x86/gen_mmu_x86.py @andrewboie
|
||||
/scripts/gen_priv_stacks.py @agross-linaro
|
||||
/scripts/gen_syscall_header.py @andrewboie
|
||||
/scripts/gen_syscalls.py @andrewboie
|
||||
/scripts/process_gperf.py @andrewboie
|
||||
/scripts/gen_relocate_app.py @wentongwu
|
||||
/scripts/sanity_chk/ @nashif
|
||||
/scripts/sanitycheck @nashif
|
||||
/scripts/sanity_chk/ @andrewboie @nashif
|
||||
/scripts/sanitycheck @andrewboie @nashif
|
||||
/scripts/series-push-hook.sh @erwango
|
||||
/scripts/west_commands/ @mbolivar
|
||||
/scripts/west-commands.yml @mbolivar
|
||||
/scripts/zephyr_module.py @tejlmand
|
||||
/scripts/valgrind.supp @aescolar
|
||||
/subsys/bluetooth/ @joerchan @jhedberg @Vudentz
|
||||
/subsys/bluetooth/ @sjanc @jhedberg @Vudentz
|
||||
/subsys/bluetooth/controller/ @carlescufi @cvinayak @thoh-ot
|
||||
/subsys/bluetooth/mesh/ @jhedberg @trond-snekvik @joerchan @Vudentz
|
||||
/subsys/cpp/ @pabigot @vanwinkeljan
|
||||
/subsys/debug/ @nashif
|
||||
/subsys/debug/asan.c @vanwinkeljan @aescolar
|
||||
/subsys/disk/disk_access_spi_sdhc.c @JunYangNXP
|
||||
/subsys/disk/disk_access_sdhc.h @JunYangNXP
|
||||
/subsys/disk/disk_access_usdhc.c @JunYangNXP
|
||||
/subsys/fb/ @jfischer-phytec-iot
|
||||
/subsys/fs/ @nashif
|
||||
/subsys/fs/fcb/ @nvlsianpu
|
||||
/subsys/fs/fuse_fs_access.c @vanwinkeljan
|
||||
/subsys/fs/littlefs_fs.c @pabigot
|
||||
/subsys/fs/nvs/ @Laczen
|
||||
/subsys/logging/ @nordic-krch
|
||||
/subsys/logging/log_backend_net.c @nordic-krch @jukkar
|
||||
/subsys/mgmt/ @carlescufi @nvlsianpu
|
||||
/subsys/net/buf.c @jukkar @jhedberg @tbursztyka @pfalcon
|
||||
/subsys/net/ip/ @jukkar @tbursztyka @pfalcon
|
||||
/subsys/net/lib/ @jukkar @tbursztyka @pfalcon
|
||||
/subsys/net/lib/dns/ @jukkar @tbursztyka @pfalcon
|
||||
/subsys/net/lib/http/ @jukkar @tbursztyka
|
||||
/subsys/net/lib/lwm2m/ @mike-scott
|
||||
/subsys/net/lib/config/ @jukkar @tbursztyka
|
||||
/subsys/net/lib/mqtt/ @jukkar @tbursztyka @rlubos
|
||||
/subsys/net/lib/openthread/ @rlubos
|
||||
/subsys/net/lib/mqtt/ @jukkar @tbursztyka
|
||||
/subsys/net/lib/coap/ @rveerama1
|
||||
/subsys/net/lib/sockets/ @jukkar @tbursztyka @pfalcon
|
||||
/subsys/net/lib/tls_credentials/ @rlubos
|
||||
/subsys/net/l2/ @jukkar @tbursztyka
|
||||
/subsys/net/l2/canbus/ @alexanderwachter @jukkar
|
||||
/subsys/power/ @wentongwu @pabigot
|
||||
/subsys/random/ @dleach02
|
||||
/subsys/power/ @ramakrishnapallala @pizi-nordic
|
||||
/subsys/settings/ @nvlsianpu
|
||||
/subsys/shell/ @jakub-uC @nordic-krch
|
||||
/subsys/shell/ @jarz-nordic @nordic-krch
|
||||
/subsys/storage/ @nvlsianpu
|
||||
/subsys/testsuite/ @nashif
|
||||
/subsys/usb/ @jfischer-phytec-iot @finikorg
|
||||
/tests/ @nashif
|
||||
/tests/application_development/libcxx/ @pabigot
|
||||
/tests/arch/arm/ @ioannisg
|
||||
/tests/boards/native_posix/ @aescolar
|
||||
/tests/boards/intel_s1000_crb/ @dcpleung @sathishkuttan
|
||||
/tests/bluetooth/ @joerchan @jhedberg @Vudentz
|
||||
/tests/boards/intel_s1000_crb/ @rgundi @dcpleung @sathishkuttan
|
||||
/tests/bluetooth/ @sjanc @jhedberg @Vudentz
|
||||
/tests/posix/ @pfalcon
|
||||
/tests/crypto/ @ceolin
|
||||
/tests/crypto/mbedtls/ @nashif @ceolin
|
||||
/tests/drivers/can/ @alexanderwachter
|
||||
/tests/drivers/flash_simulator/ @nvlsianpu
|
||||
/tests/drivers/hwinfo/ @alexanderwachter
|
||||
/tests/drivers/spi/ @tbursztyka
|
||||
/tests/drivers/uart/uart_async_api/ @Mierunski
|
||||
@@ -403,9 +298,8 @@
|
||||
/tests/net/lib/mqtt_packet/ @jukkar @tbursztyka
|
||||
/tests/net/lib/coap/ @rveerama1
|
||||
/tests/net/socket/ @jukkar @tbursztyka @pfalcon
|
||||
/tests/subsys/fs/ @nashif @wentongwu
|
||||
/tests/subsys/fs/ @nashif @ramakrishnapallala
|
||||
/tests/subsys/settings/ @nvlsianpu
|
||||
/tests/subsys/shell/ @jakub-uC @nordic-krch
|
||||
|
||||
# Get all docs reviewed
|
||||
*.rst @dbkinder
|
||||
*posix*.rst @dbkinder @aescolar
|
||||
|
||||
6
Kconfig
6
Kconfig
@@ -1,8 +1,10 @@
|
||||
# General configuration options
|
||||
# Kconfig - general configuration options
|
||||
|
||||
#
|
||||
# Copyright (c) 2014-2015 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#
|
||||
mainmenu "Zephyr Kernel Configuration"
|
||||
|
||||
source "Kconfig.zephyr"
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
# General configuration options
|
||||
# Kconfig - general configuration options
|
||||
|
||||
#
|
||||
# Copyright (c) 2014-2015 Wind River Systems, Inc.
|
||||
# Copyright (c) 2016 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
menu "Modules"
|
||||
#
|
||||
|
||||
source "$(CMAKE_BINARY_DIR)/Kconfig.modules"
|
||||
source "modules/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
||||
# Include these first so that any properties (e.g. defaults) below can be
|
||||
# overridden in *.defconfig files (by defining symbols in multiple locations).
|
||||
# overriden in *.defconfig files (by defining symbols in multiple locations).
|
||||
# After merging all the symbol definitions, Kconfig picks the first property
|
||||
# (e.g. the first default) with a satisfied condition.
|
||||
#
|
||||
@@ -42,7 +40,6 @@ source "subsys/Kconfig"
|
||||
|
||||
source "ext/Kconfig"
|
||||
|
||||
|
||||
menu "Build and Link Features"
|
||||
|
||||
menu "Linker Options"
|
||||
@@ -60,7 +57,7 @@ config LINKER_ORPHAN_SECTION_PLACE
|
||||
config LINKER_ORPHAN_SECTION_WARN
|
||||
bool "Warn"
|
||||
help
|
||||
Linker places the orphan sections in output and issues
|
||||
Linker places the orphan sections in ouput and issues
|
||||
warning about those sections.
|
||||
|
||||
config LINKER_ORPHAN_SECTION_ERROR
|
||||
@@ -71,13 +68,13 @@ config LINKER_ORPHAN_SECTION_ERROR
|
||||
endchoice
|
||||
|
||||
config CODE_DATA_RELOCATION
|
||||
bool "Relocate code/data sections"
|
||||
depends on ARM
|
||||
help
|
||||
bool "Relocate code/data sections"
|
||||
depends on ARM
|
||||
help
|
||||
When selected this will relocate .text, data and .bss sections from
|
||||
the specified files and places it in the required memory region. The
|
||||
files should be specified in the CMakeList.txt file with
|
||||
a cmake API zephyr_code_relocate().
|
||||
a cmake API zephyr_code_relocation().
|
||||
|
||||
config HAS_FLASH_LOAD_OFFSET
|
||||
bool
|
||||
@@ -91,12 +88,9 @@ config USE_CODE_PARTITION
|
||||
help
|
||||
When selected application will be linked into chosen code-partition.
|
||||
|
||||
# Workaround for not being able to have commas in macro arguments
|
||||
DT_CHOSEN_Z_CODE_PARTITION := zephyr,code-partition
|
||||
|
||||
config FLASH_LOAD_OFFSET
|
||||
hex "Kernel load offset"
|
||||
default $(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) if USE_CODE_PARTITION
|
||||
default $(dt_hex_val,DT_CODE_PARTITION_OFFSET) if USE_CODE_PARTITION
|
||||
default 0
|
||||
depends on HAS_FLASH_LOAD_OFFSET
|
||||
help
|
||||
@@ -109,7 +103,7 @@ config FLASH_LOAD_OFFSET
|
||||
|
||||
config FLASH_LOAD_SIZE
|
||||
hex "Kernel load size"
|
||||
default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) if USE_CODE_PARTITION
|
||||
default $(dt_hex_val,DT_CODE_PARTITION_SIZE) if USE_CODE_PARTITION
|
||||
default 0
|
||||
depends on HAS_FLASH_LOAD_OFFSET
|
||||
help
|
||||
@@ -156,39 +150,41 @@ config CUSTOM_LINKER_SCRIPT
|
||||
Zephyr.
|
||||
|
||||
config CUSTOM_RODATA_LD
|
||||
bool "(DEPRECATED) Include custom-rodata.ld"
|
||||
bool "Include custom-rodata.ld"
|
||||
help
|
||||
Note: This is deprecated, use Cmake function zephyr_linker_sources() instead.
|
||||
Include a customized linker script fragment for inserting additional
|
||||
data and linker directives into the rodata section.
|
||||
|
||||
config CUSTOM_RWDATA_LD
|
||||
bool "(DEPRECATED) Include custom-rwdata.ld"
|
||||
bool "Include custom-rwdata.ld"
|
||||
help
|
||||
Note: This is deprecated, use Cmake function zephyr_linker_sources() instead.
|
||||
Include a customized linker script fragment for inserting additional
|
||||
data and linker directives into the data section.
|
||||
|
||||
config CUSTOM_SECTIONS_LD
|
||||
bool "(DEPRECATED) Include custom-sections.ld"
|
||||
bool "Include custom-sections.ld"
|
||||
help
|
||||
Note: This is deprecated, use Cmake function zephyr_linker_sources() instead.
|
||||
Include a customized linker script fragment for inserting additional
|
||||
arbitrary sections.
|
||||
|
||||
config LINK_WHOLE_ARCHIVE
|
||||
bool "Allow linking with --whole-archive"
|
||||
help
|
||||
This options allows linking external libraries with the
|
||||
--whole-archive option to keep all symbols.
|
||||
|
||||
config KERNEL_ENTRY
|
||||
string "Kernel entry symbol"
|
||||
default "__start"
|
||||
help
|
||||
Code entry symbol, to be set at linking phase.
|
||||
|
||||
config LINKER_SORT_BY_ALIGNMENT
|
||||
bool "Sort input sections by alignment"
|
||||
config CHECK_LINK_MAP
|
||||
bool "Check linker map"
|
||||
default y
|
||||
help
|
||||
This turns on the linker flag to sort sections by alignment
|
||||
in decreasing size of symbols. This helps to minimize
|
||||
padding between symbols.
|
||||
Run a linker address generation validity checker at the end of the
|
||||
build.
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -374,6 +370,13 @@ config BOOTLOADER_ESP_IDF
|
||||
inside the build folder.
|
||||
At flash time, the bootloader will be flashed with the zephyr image
|
||||
|
||||
config REALMODE
|
||||
bool "boot from x86 real mode"
|
||||
depends on X86
|
||||
help
|
||||
This option enabled Zephyr to start in x86 real mode, instead of
|
||||
protected mode.
|
||||
|
||||
config BOOTLOADER_KEXEC
|
||||
bool "Boot using Linux kexec() system call"
|
||||
depends on X86
|
||||
@@ -381,6 +384,15 @@ config BOOTLOADER_KEXEC
|
||||
This option signifies that Linux boots the kernel using kexec system call
|
||||
and utility. This method is used to boot the kernel over the network.
|
||||
|
||||
config BOOTLOADER_UNKNOWN
|
||||
bool "Generic boot loader support"
|
||||
depends on X86
|
||||
help
|
||||
This option signifies that the target has a generic bootloader
|
||||
or that it supports multiple ways of booting and it isn't clear
|
||||
at build time which method is to be used. When this option is enabled
|
||||
the board may have to do extra work to ensure a proper startup.
|
||||
|
||||
config BOOTLOADER_CONTEXT_RESTORE
|
||||
bool "Boot loader has context restore support"
|
||||
default y
|
||||
@@ -407,15 +419,3 @@ config MISRA_SANE
|
||||
arrays are not permitted (and gcc will enforce this).
|
||||
|
||||
endmenu
|
||||
|
||||
|
||||
menu "Compatibility"
|
||||
|
||||
config COMPAT_INCLUDES
|
||||
bool "Suppress warnings when using header shims"
|
||||
default y
|
||||
help
|
||||
Suppress any warnings from the pre-processor when including
|
||||
deprecated header files.
|
||||
|
||||
endmenu
|
||||
|
||||
116
README.rst
116
README.rst
@@ -32,56 +32,102 @@ Intel x86, ARC, Nios II, Tensilica Xtensa, and RISC-V, and a large number of
|
||||
Getting Started
|
||||
***************
|
||||
|
||||
Welcome to Zephyr! See the `Introduction to Zephyr`_ for a high-level overview,
|
||||
and the documentation's `Getting Started Guide`_ to start developing.
|
||||
To start developing Zephyr applications refer to the `Getting Started Guide`_
|
||||
in the `Zephyr Documentation`_ pages.
|
||||
A brief introduction to Zephyr can be found in the `Zephyr Introduction`_
|
||||
page.
|
||||
|
||||
Community Support
|
||||
*****************
|
||||
|
||||
Community support is provided via mailing lists and Slack; see the Resources
|
||||
below for details.
|
||||
The Zephyr Project Developer Community includes developers from member
|
||||
organizations and the general community all joining in the development of
|
||||
software within the Zephyr Project. Members contribute and discuss ideas,
|
||||
submit bugs and bug fixes, and provide training. They also help those in need
|
||||
through the community's forums such as mailing lists and IRC channels. Anyone
|
||||
can join the developer community and the community is always willing to help
|
||||
its members and the User Community to get the most out of the Zephyr Project.
|
||||
|
||||
.. _project-resources:
|
||||
Welcome to the Zephyr community!
|
||||
|
||||
Resources
|
||||
*********
|
||||
|
||||
Here's a quick summary of resources to help you find your way around:
|
||||
Here's a quick summary of resources to find your way around the Zephyr Project
|
||||
support systems:
|
||||
|
||||
* **Help**: `Asking for Help Tips`_
|
||||
* **Documentation**: http://docs.zephyrproject.org (`Getting Started Guide`_)
|
||||
* **Source Code**: https://github.com/zephyrproject-rtos/zephyr is the main
|
||||
repository; https://elixir.bootlin.com/zephyr/latest/source contains a
|
||||
searchable index
|
||||
* **Releases**: https://zephyrproject.org/developers/#downloads
|
||||
* **Samples and example code**: see `Sample and Demo Code Examples`_
|
||||
* **Mailing Lists**: users@lists.zephyrproject.org and
|
||||
devel@lists.zephyrproject.org are the main user and developer mailing lists,
|
||||
respectively. You can join the developer's list and search its archives at
|
||||
`Zephyr Development mailing list`_. The other `Zephyr mailing list
|
||||
subgroups`_ have their own archives and sign-up pages.
|
||||
* **Nightly CI Build Status**: https://lists.zephyrproject.org/g/builds
|
||||
The builds@lists.zephyrproject.org mailing list archives the CI
|
||||
(shippable) nightly build results.
|
||||
* **Chat**: Zephyr's Slack workspace is https://zephyrproject.slack.com. Use
|
||||
this `Slack Invite`_ to register.
|
||||
* **Contributing**: see the `Contribution Guide`_
|
||||
* **Wiki**: `Zephyr GitHub wiki`_
|
||||
* **Issues**: https://github.com/zephyrproject-rtos/zephyr/issues
|
||||
* **Security Issues**: Email vulnerabilities@zephyrproject.org to report
|
||||
security issues; also see our `Security`_ documentation. Security issues are
|
||||
tracked separately at https://zephyrprojectsec.atlassian.net.
|
||||
* **Zephyr Project Website**: https://zephyrproject.org
|
||||
* **Zephyr Project Website**: The https://zephyrproject.org website is the
|
||||
central source of information about the Zephyr Project. On this site, you'll
|
||||
find background and current information about the project as well as all the
|
||||
relevant links to project material.
|
||||
|
||||
.. _Slack Invite: https://tinyurl.com/y5glwylp
|
||||
.. _supported boards: http://docs.zephyrproject.org/latest/boards/index.html
|
||||
* **Releases**: Source code for Zephyr kernel releases are available at
|
||||
https://zephyrproject.org/developers/#downloads. On this page,
|
||||
you'll find release information, and links to download or clone source
|
||||
code from our GitHub repository. You'll also find links for the Zephyr
|
||||
SDK, a moderated collection of tools and libraries used to develop your
|
||||
applications.
|
||||
|
||||
* **Source Code in GitHub**: Zephyr Project source code is maintained on a
|
||||
public GitHub repository at https://github.com/zephyrproject-rtos/zephyr.
|
||||
You'll find information about getting access to the repository and how to
|
||||
contribute to the project in this `Contribution Guide`_ document.
|
||||
|
||||
* **Samples Code**: In addition to the kernel source code, there are also
|
||||
many documented `Sample and Demo Code Examples`_ that can help show you
|
||||
how to use Zephyr services and subsystems.
|
||||
|
||||
* **Documentation**: Extensive Project technical documentation is developed
|
||||
along with the Zephyr kernel itself, and can be found at
|
||||
http://docs.zephyrproject.org. Additional documentation is maintained in
|
||||
the `Zephyr GitHub wiki`_.
|
||||
|
||||
* **Cross-reference**: Source code cross-reference for the Zephyr
|
||||
kernel and samples code is available at
|
||||
https://elixir.bootlin.com/zephyr/latest/source.
|
||||
|
||||
* **Issue Reporting and Tracking**: Requirements and Issue tracking is done in
|
||||
the Github issues system: https://github.com/zephyrproject-rtos/zephyr/issues.
|
||||
You can browse through the reported issues and submit issues of your own.
|
||||
|
||||
* **Security-related Issue Reporting and Tracking**: For security-related
|
||||
inquiries or reporting suspected security-related bugs in the Zephyr OS,
|
||||
please send email to vulnerabilities@zephyrproject.org. We will assess and
|
||||
fix flaws according to our security policy outlined in the Zephyr Project
|
||||
`Security Overview`_.
|
||||
|
||||
Security related issue tracking is done in JIRA. The location of this JIRA
|
||||
is https://zephyrprojectsec.atlassian.net.
|
||||
|
||||
* **Mailing List**: The `Zephyr Development mailing list`_ is perhaps the most convenient
|
||||
way to track developer discussions and to ask your own support questions to
|
||||
the Zephyr project community. There are also specific `Zephyr mailing list
|
||||
subgroups`_ for announcements, builds, marketing, and Technical
|
||||
Steering Committee notes, for example.
|
||||
You can read through the message archives to follow
|
||||
past posts and discussions, a good thing to do to discover more about the
|
||||
Zephyr project.
|
||||
|
||||
* **Chatting**: You can chat online with the Zephyr project developer
|
||||
community and other users in two ways:
|
||||
|
||||
* On `Slack`_: Zephyr has dedicated channels on Slack. To register, use the
|
||||
following `Slack Invite`_.
|
||||
|
||||
* IRC channel #zephyrproject on the freenode.net IRC server. You can use the
|
||||
http://webchat.freenode.net web client or use a client-side application such
|
||||
as pidgin (Note that all discussions have moved to Slack, although we still
|
||||
have many developers still available on the IRC channel).
|
||||
|
||||
.. _Slack Invite: https://tinyurl.com/yarkuemx
|
||||
.. _Slack: https://zephyrproject.slack.com
|
||||
.. _supported boards: http://docs.zephyrproject.org/latest/boards
|
||||
.. _Zephyr Documentation: http://docs.zephyrproject.org
|
||||
.. _Introduction to Zephyr: http://docs.zephyrproject.org/latest/introduction/index.html
|
||||
.. _Zephyr Introduction: http://docs.zephyrproject.org/latest/introduction/index.html
|
||||
.. _Getting Started Guide: http://docs.zephyrproject.org/latest/getting_started/index.html
|
||||
.. _Contribution Guide: http://docs.zephyrproject.org/latest/contribute/index.html
|
||||
.. _Zephyr GitHub wiki: https://github.com/zephyrproject-rtos/zephyr/wiki
|
||||
.. _Zephyr Development mailing list: https://lists.zephyrproject.org/g/devel
|
||||
.. _Zephyr mailing list subgroups: https://lists.zephyrproject.org/g/main/subgroups
|
||||
.. _Sample and Demo Code Examples: http://docs.zephyrproject.org/latest/samples/index.html
|
||||
.. _Security: http://docs.zephyrproject.org/latest/security/index.html
|
||||
.. _Asking for Help Tips: https://docs.zephyrproject.org/latest/guides/getting-help.html
|
||||
.. _Security Overview: http://docs.zephyrproject.org/latest/security/index.html
|
||||
|
||||
6
VERSION
6
VERSION
@@ -1,5 +1,5 @@
|
||||
VERSION_MAJOR = 2
|
||||
VERSION_MINOR = 1
|
||||
PATCHLEVEL = 0
|
||||
VERSION_MAJOR = 1
|
||||
VERSION_MINOR = 14
|
||||
PATCHLEVEL = 1
|
||||
VERSION_TWEAK = 0
|
||||
EXTRAVERSION =
|
||||
|
||||
@@ -2,10 +2,5 @@
|
||||
|
||||
add_definitions(-D__ZEPHYR_SUPERVISOR__)
|
||||
|
||||
include_directories(
|
||||
${ZEPHYR_BASE}/kernel/include
|
||||
${ZEPHYR_BASE}/arch/${ARCH}/include
|
||||
)
|
||||
|
||||
add_subdirectory(common)
|
||||
add_subdirectory(${ARCH_DIR}/${ARCH} arch/${ARCH})
|
||||
|
||||
131
arch/Kconfig
131
arch/Kconfig
@@ -1,17 +1,20 @@
|
||||
# General architecture configuration options
|
||||
# Kconfig - general architecture configuration options
|
||||
|
||||
#
|
||||
# Copyright (c) 2014-2015 Wind River Systems, Inc.
|
||||
# Copyright (c) 2015 Intel Corporation
|
||||
# Copyright (c) 2016 Cadence Design Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
# Include these first so that any properties (e.g. defaults) below can be
|
||||
# overridden (by defining symbols in multiple locations)
|
||||
# overriden (by defining symbols in multiple locations)
|
||||
|
||||
# Note: $ARCH might be a glob pattern
|
||||
source "$(ARCH_DIR)/$(ARCH)/Kconfig"
|
||||
|
||||
choice ARCH_CHOICE
|
||||
choice
|
||||
prompt "Architecture"
|
||||
default X86
|
||||
|
||||
@@ -21,6 +24,7 @@ config ARC
|
||||
|
||||
config ARM
|
||||
bool "ARM architecture"
|
||||
select ARCH_HAS_THREAD_ABORT
|
||||
select HAS_DTS
|
||||
|
||||
config X86
|
||||
@@ -28,20 +32,23 @@ config X86
|
||||
select ATOMIC_OPERATIONS_BUILTIN
|
||||
select HAS_DTS
|
||||
|
||||
config X86_64
|
||||
bool "x86_64 architecture"
|
||||
select ATOMIC_OPERATIONS_BUILTIN
|
||||
select SCHED_IPI_SUPPORTED
|
||||
|
||||
config NIOS2
|
||||
bool "Nios II Gen 2 architecture"
|
||||
select ATOMIC_OPERATIONS_C
|
||||
select HAS_DTS
|
||||
|
||||
config RISCV
|
||||
bool "RISCV architecture"
|
||||
config RISCV32
|
||||
bool "RISCV32 architecture"
|
||||
select HAS_DTS
|
||||
|
||||
config XTENSA
|
||||
bool "Xtensa architecture"
|
||||
select HAS_DTS
|
||||
select USE_SWITCH
|
||||
select USE_SWITCH_SUPPORTED
|
||||
|
||||
config ARCH_POSIX
|
||||
bool "POSIX (native) architecture"
|
||||
@@ -66,32 +73,21 @@ module-str = mpu
|
||||
source "subsys/logging/Kconfig.template.log_config"
|
||||
|
||||
config BIG_ENDIAN
|
||||
bool
|
||||
help
|
||||
This option tells the build system that the target system is big-endian.
|
||||
Little-endian architecture is the default and should leave this option
|
||||
unselected. This option is selected by arch/$ARCH/Kconfig,
|
||||
soc/**/Kconfig, or boards/**/Kconfig and the user should generally avoid
|
||||
modifying it. The option is used to select linker script OUTPUT_FORMAT
|
||||
and command line option for gen_isr_tables.py.
|
||||
|
||||
config 64BIT
|
||||
bool
|
||||
help
|
||||
This option tells the build system that the target system is
|
||||
using a 64-bit address space, meaning that pointer and long types
|
||||
are 64 bits wide. This option is selected by arch/$ARCH/Kconfig,
|
||||
soc/**/Kconfig, or boards/**/Kconfig and the user should generally
|
||||
avoid modifying it.
|
||||
bool
|
||||
help
|
||||
This option tells the build system that the target system is
|
||||
big-endian. Little-endian architecture is the default and
|
||||
should leave this option unselected. This option is selected
|
||||
by arch/$ARCH/Kconfig, soc/**/Kconfig, or boards/**/Kconfig
|
||||
and the user should generally avoid modifying it. The option
|
||||
is used to select linker script OUTPUT_FORMAT and command
|
||||
line option for gen_isr_tables.py.
|
||||
|
||||
if ARC || ARM || NIOS2 || X86
|
||||
|
||||
# Workaround for not being able to have commas in macro arguments
|
||||
DT_CHOSEN_Z_SRAM := zephyr,sram
|
||||
|
||||
config SRAM_SIZE
|
||||
int "SRAM Size in kB"
|
||||
default $(dt_chosen_reg_size_int,$(DT_CHOSEN_Z_SRAM),0,K)
|
||||
default $(dt_int_val,DT_SRAM_SIZE)
|
||||
help
|
||||
This option specifies the size of the SRAM in kB. It is normally set by
|
||||
the board's defconfig file and the user should generally avoid modifying
|
||||
@@ -99,18 +95,15 @@ config SRAM_SIZE
|
||||
|
||||
config SRAM_BASE_ADDRESS
|
||||
hex "SRAM Base Address"
|
||||
default $(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_SRAM))
|
||||
default $(dt_hex_val,DT_SRAM_BASE_ADDRESS)
|
||||
help
|
||||
This option specifies the base address of the SRAM on the board. It is
|
||||
normally set by the board's defconfig file and the user should generally
|
||||
avoid modifying it via the menu configuration.
|
||||
|
||||
# Workaround for not being able to have commas in macro arguments
|
||||
DT_CHOSEN_Z_FLASH := zephyr,flash
|
||||
|
||||
config FLASH_SIZE
|
||||
int "Flash Size in kB"
|
||||
default $(dt_chosen_reg_size_int,$(DT_CHOSEN_Z_FLASH),0,K) if (XIP && ARM) || !ARM
|
||||
default $(dt_int_val,DT_FLASH_SIZE) if (XIP && ARM) || !ARM
|
||||
help
|
||||
This option specifies the size of the flash in kB. It is normally set by
|
||||
the board's defconfig file and the user should generally avoid modifying
|
||||
@@ -118,7 +111,7 @@ config FLASH_SIZE
|
||||
|
||||
config FLASH_BASE_ADDRESS
|
||||
hex "Flash Base Address"
|
||||
default $(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_FLASH)) if (XIP && ARM) || !ARM
|
||||
default $(dt_hex_val,DT_FLASH_BASE_ADDRESS) if (XIP && ARM) || !ARM
|
||||
help
|
||||
This option specifies the base address of the flash on the board. It is
|
||||
normally set by the board's defconfig file and the user should generally
|
||||
@@ -230,14 +223,23 @@ config DYNAMIC_OBJECTS
|
||||
bool "Allow kernel objects to be allocated at runtime"
|
||||
depends on USERSPACE
|
||||
help
|
||||
Enabling this option allows for kernel objects to be requested from
|
||||
the calling thread's resource pool, at a slight cost in performance
|
||||
due to the supplemental run-time tables required to validate such
|
||||
objects.
|
||||
Enabling this option allows for kernel objects to be requested from
|
||||
the calling thread's resource pool, at a slight cost in performance
|
||||
due to the supplemental run-time tables required to validate such
|
||||
objects.
|
||||
|
||||
Objects allocated in this way can be freed with a supervisor-only
|
||||
API call, or when the number of references to that object drops to
|
||||
zero.
|
||||
Objects allocated in this way can be freed with a supervisor-only
|
||||
API call, or when the number of references to that object drops to
|
||||
zero.
|
||||
|
||||
config SIMPLE_FATAL_ERROR_HANDLER
|
||||
bool "Simple system fatal error handler"
|
||||
default y if !MULTITHREADING
|
||||
help
|
||||
Provides an implementation of _SysFatalErrorHandler() that hard hangs
|
||||
instead of aborting the faulting thread, and does not print anything,
|
||||
for footprint-concerned systems. Only enable this option if you do not
|
||||
want debug capabilities in case of system fatal error.
|
||||
|
||||
if ARCH_HAS_NOCACHE_MEMORY_SUPPORT
|
||||
|
||||
@@ -291,16 +293,6 @@ config GEN_SW_ISR_TABLE
|
||||
_isr_table_entry containing the interrupt service routine and supplied
|
||||
parameter.
|
||||
|
||||
config ARCH_SW_ISR_TABLE_ALIGN
|
||||
int "Alignment size of a software ISR table"
|
||||
default 0
|
||||
depends on GEN_SW_ISR_TABLE
|
||||
help
|
||||
This option controls alignment size of generated
|
||||
_sw_isr_table. Some architecture needs a software ISR table
|
||||
to be aligned to architecture specific size. The default
|
||||
size is 0 for no alignment.
|
||||
|
||||
config GEN_IRQ_START_VECTOR
|
||||
int
|
||||
default 0
|
||||
@@ -316,11 +308,9 @@ config GEN_IRQ_START_VECTOR
|
||||
|
||||
config IRQ_OFFLOAD
|
||||
bool "Enable IRQ offload"
|
||||
depends on TEST
|
||||
help
|
||||
Enable irq_offload() API which allows functions to be synchronously
|
||||
run in interrupt context. Only useful for test cases that need
|
||||
to validate the correctness of kernel objects in IRQ context.
|
||||
run in interrupt context. Mainly useful for test cases.
|
||||
|
||||
endmenu # Interrupt configuration
|
||||
|
||||
@@ -347,9 +337,6 @@ config ARCH_HAS_NOCACHE_MEMORY_SUPPORT
|
||||
config ARCH_HAS_RAMFUNC_SUPPORT
|
||||
bool
|
||||
|
||||
config ARCH_HAS_NESTED_EXCEPTION_DETECTION
|
||||
bool
|
||||
|
||||
#
|
||||
# Other architecture related options
|
||||
#
|
||||
@@ -429,11 +416,13 @@ config CPU_HAS_FPU
|
||||
|
||||
config CPU_HAS_MPU
|
||||
bool
|
||||
# Omit prompt to signify "hidden" option
|
||||
help
|
||||
This option is enabled when the CPU has a Memory Protection Unit (MPU).
|
||||
|
||||
config MEMORY_PROTECTION
|
||||
bool
|
||||
# Omit prompt to signify "hidden" option
|
||||
help
|
||||
This option is enabled when Memory Protection features are supported.
|
||||
Memory protection support is currently available on ARC, ARM, and x86
|
||||
@@ -441,45 +430,21 @@ config MEMORY_PROTECTION
|
||||
|
||||
config MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT
|
||||
bool
|
||||
# Omit prompt to signify "hidden" option
|
||||
help
|
||||
This option is enabled when the MPU requires a power of two alignment
|
||||
and size for MPU regions.
|
||||
|
||||
config MPU_REQUIRES_NON_OVERLAPPING_REGIONS
|
||||
bool
|
||||
# Omit prompt to signify "hidden" option
|
||||
help
|
||||
This option is enabled when the MPU requires the active (i.e. enabled)
|
||||
MPU regions to be non-overlapping with each other.
|
||||
|
||||
config MPU_GAP_FILLING
|
||||
bool "Force MPU to be filling in background memory regions"
|
||||
depends on MPU_REQUIRES_NON_OVERLAPPING_REGIONS
|
||||
default y if !USERSPACE
|
||||
help
|
||||
This Kconfig option instructs the MPU driver to enforce
|
||||
a full kernel SRAM partitioning, when it programs the
|
||||
dynamic MPU regions (user thread stack, PRIV stack guard
|
||||
and application memory domains) during context-switch. We
|
||||
allow this to be a configurable option, in order to be able
|
||||
to switch the option off and have an increased number of MPU
|
||||
regions available for application memory domain programming.
|
||||
|
||||
Notes:
|
||||
An increased number of MPU regions should only be required,
|
||||
when building with USERSPACE support. As a result, when we
|
||||
build without USERSPACE support, gap filling should always
|
||||
be required.
|
||||
|
||||
When the option is switched off, access to memory areas not
|
||||
covered by explicit MPU regions is restricted to privileged
|
||||
code on an ARCH-specific basis. Refer to ARCH-specific
|
||||
documentation for more information on how this option is
|
||||
used.
|
||||
|
||||
menuconfig FLOAT
|
||||
bool "Floating point"
|
||||
depends on CPU_HAS_FPU
|
||||
depends on ARM || X86 || ARC
|
||||
help
|
||||
This option allows threads to use the floating point registers.
|
||||
By default, only a single thread may use the registers.
|
||||
|
||||
@@ -10,6 +10,4 @@ zephyr_cc_option(-g3 -gdwarf-2)
|
||||
# See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63691
|
||||
zephyr_cc_option(-fno-delete-null-pointer-checks)
|
||||
|
||||
zephyr_cc_option_ifdef(CONFIG_ARC_USE_UNALIGNED_MEM_ACCESS -munaligned-access)
|
||||
|
||||
add_subdirectory(core)
|
||||
|
||||
193
arch/arc/Kconfig
193
arch/arc/Kconfig
@@ -1,7 +1,10 @@
|
||||
# ARC options
|
||||
# ARC EM4 options
|
||||
|
||||
# Copyright (c) 2014, 2019 Wind River Systems, Inc.
|
||||
#
|
||||
# Copyright (c) 2014 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
menu "ARC Options"
|
||||
depends on ARC
|
||||
@@ -9,69 +12,37 @@ menu "ARC Options"
|
||||
config ARCH
|
||||
default "arc"
|
||||
|
||||
choice
|
||||
prompt "ARC core family"
|
||||
default CPU_ARCEM
|
||||
menu "ARC EM4 processor options"
|
||||
|
||||
config CPU_ARCEM
|
||||
bool "ARC EM cores"
|
||||
config CPU_ARCEM4
|
||||
bool
|
||||
default y
|
||||
select CPU_ARCV2
|
||||
select ATOMIC_OPERATIONS_C
|
||||
help
|
||||
This option signifies the use of an ARC EM CPU
|
||||
This option signifies the use of an ARC EM4 CPU
|
||||
|
||||
config CPU_ARCHS
|
||||
bool "ARC HS cores"
|
||||
select CPU_ARCV2
|
||||
select ATOMIC_OPERATIONS_BUILTIN
|
||||
help
|
||||
This option signifies the use of an ARC HS CPU
|
||||
|
||||
endchoice
|
||||
|
||||
config CPU_EM4
|
||||
bool
|
||||
help
|
||||
If y, the SoC uses an ARC EM4 CPU
|
||||
|
||||
config CPU_EM4_DMIPS
|
||||
bool
|
||||
help
|
||||
If y, the SoC uses an ARC EM4 DMIPS CPU
|
||||
|
||||
config CPU_EM4_FPUS
|
||||
bool
|
||||
help
|
||||
If y, the SoC uses an ARC EM4 DMIPS CPU with the single-precision
|
||||
floating-point extension
|
||||
|
||||
config CPU_EM4_FPUDA
|
||||
bool
|
||||
help
|
||||
If y, the SoC uses an ARC EM4 DMIPS CPU with single-precision
|
||||
floating-point and double assist instructions
|
||||
|
||||
config CPU_EM6
|
||||
bool
|
||||
help
|
||||
If y, the SoC uses an ARC EM6 CPU
|
||||
|
||||
config FP_FPU_DA
|
||||
bool
|
||||
endmenu
|
||||
|
||||
menu "ARCv2 Family Options"
|
||||
|
||||
config CPU_ARCV2
|
||||
config CPU_ARCV2
|
||||
bool
|
||||
select ARCH_HAS_STACK_PROTECTION if ARC_HAS_STACK_CHECKING || ARC_MPU
|
||||
select ARCH_HAS_USERSPACE if ARC_MPU
|
||||
select USE_SWITCH
|
||||
select USE_SWITCH_SUPPORTED
|
||||
default y
|
||||
help
|
||||
This option signifies the use of a CPU of the ARCv2 family.
|
||||
|
||||
config NUM_IRQ_PRIO_LEVELS
|
||||
config DATA_ENDIANNESS_LITTLE
|
||||
bool
|
||||
default y
|
||||
help
|
||||
This is driven by the processor implementation, since it is fixed in
|
||||
hardware. The BSP should set this value to 'n' if the data is
|
||||
implemented as big endian.
|
||||
|
||||
config NUM_IRQ_PRIO_LEVELS
|
||||
int "Number of supported interrupt priority levels"
|
||||
range 1 16
|
||||
help
|
||||
@@ -80,7 +51,7 @@ config NUM_IRQ_PRIO_LEVELS
|
||||
|
||||
The BSP must provide a valid default for proper operation.
|
||||
|
||||
config NUM_IRQS
|
||||
config NUM_IRQS
|
||||
int "Upper limit of interrupt numbers/IDs used"
|
||||
range 17 256
|
||||
help
|
||||
@@ -91,7 +62,7 @@ config NUM_IRQS
|
||||
The BSP must provide a valid default. This drives the size of the
|
||||
vector table.
|
||||
|
||||
config RGF_NUM_BANKS
|
||||
config RGF_NUM_BANKS
|
||||
int "Number of General Purpose Register Banks"
|
||||
depends on CPU_ARCV2
|
||||
range 1 2
|
||||
@@ -114,21 +85,6 @@ config ARC_FIRQ
|
||||
If FIRQ is disabled, the handle of interrupts with highest priority
|
||||
will be same with other interrupts.
|
||||
|
||||
config ARC_FIRQ_STACK
|
||||
bool "Enable separate firq stack"
|
||||
depends on ARC_FIRQ && RGF_NUM_BANKS > 1
|
||||
default n
|
||||
help
|
||||
Use separate stack for FIRQ handing. When the fast irq is also a direct
|
||||
irq, this will get the minimal interrupt latency.
|
||||
|
||||
config ARC_FIRQ_STACK_SIZE
|
||||
int "FIRQ stack size"
|
||||
depends on ARC_FIRQ_STACK
|
||||
default 1024
|
||||
help
|
||||
The size of firq stack.
|
||||
|
||||
config ARC_HAS_STACK_CHECKING
|
||||
bool "ARC has STACK_CHECKING"
|
||||
default y
|
||||
@@ -137,19 +93,12 @@ config ARC_HAS_STACK_CHECKING
|
||||
checking stack accesses and raising an exception when a stack
|
||||
overflow or underflow is detected.
|
||||
|
||||
config ARC_CONNECT
|
||||
bool "ARC has ARC connect"
|
||||
select SCHED_IPI_SUPPORTED
|
||||
help
|
||||
ARC is configured with ARC CONNECT which is a hardware for connecting
|
||||
multi cores.
|
||||
|
||||
config ARC_STACK_CHECKING
|
||||
config ARC_STACK_CHECKING
|
||||
bool
|
||||
help
|
||||
Use ARC STACK_CHECKING to do stack protection
|
||||
|
||||
config ARC_STACK_PROTECTION
|
||||
config ARC_STACK_PROTECTION
|
||||
bool
|
||||
default y if HW_STACK_PROTECTION
|
||||
select ARC_STACK_CHECKING if ARC_HAS_STACK_CHECKING
|
||||
@@ -165,17 +114,7 @@ config ARC_STACK_PROTECTION
|
||||
selection of the ARC stack checking is
|
||||
prioritized over the MPU-based stack guard.
|
||||
|
||||
config ARC_USE_UNALIGNED_MEM_ACCESS
|
||||
bool "Enable unaligned access in HW"
|
||||
default n if CPU_ARCEM
|
||||
default y if CPU_ARCHS
|
||||
depends on (CPU_ARCEM && !ARC_HAS_SECURE) || CPU_ARCHS
|
||||
help
|
||||
ARC EM cores w/o secure shield 2+2 mode support might be configured
|
||||
to support unaligned memory access which is then disabled by default.
|
||||
Enable unaligned access in hardware and make software to use it.
|
||||
|
||||
config FAULT_DUMP
|
||||
config FAULT_DUMP
|
||||
int "Fault dump level"
|
||||
default 2
|
||||
range 0 2
|
||||
@@ -190,7 +129,7 @@ config FAULT_DUMP
|
||||
|
||||
0: Off.
|
||||
|
||||
config XIP
|
||||
config XIP
|
||||
default y if !UART_NSIM
|
||||
|
||||
config GEN_ISR_TABLES
|
||||
@@ -210,68 +149,12 @@ config CODE_DENSITY
|
||||
help
|
||||
Enable code density option to get better code density
|
||||
|
||||
config ARC_HAS_ACCL_REGS
|
||||
bool "Reg Pair ACCL:ACCH (FPU and/or MPY > 6)"
|
||||
default y if FLOAT
|
||||
help
|
||||
Depending on the configuration, CPU can contain accumulator reg-pair
|
||||
(also referred to as r58:r59). These can also be used by gcc as GPR so
|
||||
kernel needs to save/restore per process
|
||||
|
||||
config ARC_HAS_SECURE
|
||||
bool "ARC has SecureShield"
|
||||
select CPU_HAS_TEE
|
||||
select ARCH_HAS_TRUSTED_EXECUTION
|
||||
bool
|
||||
# a hidden option
|
||||
help
|
||||
This option is enabled when ARC core supports secure mode
|
||||
|
||||
config SJLI_TABLE_SIZE
|
||||
int "SJLI table size"
|
||||
depends on ARC_SECURE_FIRMWARE
|
||||
default 8
|
||||
help
|
||||
The size of sjli (Secure Jump and Link Indexed) table. The
|
||||
code in normal mode call secure services in secure mode through
|
||||
sjli instruction.
|
||||
|
||||
config ARC_SECURE_FIRMWARE
|
||||
prompt "Generate Secure Firmware"
|
||||
bool
|
||||
depends on ARC_HAS_SECURE
|
||||
default y if TRUSTED_EXECUTION_SECURE
|
||||
help
|
||||
This option indicates that we are building a Zephyr image that
|
||||
is intended to execute in secure mode. The option is only
|
||||
applicable to ARC processors that implement the SecureShield.
|
||||
|
||||
This option enables Zephyr to include code that executes in
|
||||
secure mode, as well as to exclude code that is designed to
|
||||
execute only in normal mode.
|
||||
|
||||
Code executing in secure mode has access to both the secure
|
||||
and normal resources of the ARC processors.
|
||||
|
||||
config ARC_NORMAL_FIRMWARE
|
||||
prompt "Generate Normal Firmware"
|
||||
bool
|
||||
depends on !ARC_SECURE_FIRMWARE
|
||||
depends on ARC_HAS_SECURE
|
||||
default y if TRUSTED_EXECUTION_NONSECURE
|
||||
help
|
||||
This option indicates that we are building a Zephyr image that
|
||||
is intended to execute in normal mode. Execution of this
|
||||
image is triggered by secure firmware that executes in secure
|
||||
mode. The option is only applicable to ARC processors that
|
||||
implement the SecureShield.
|
||||
|
||||
This option enables Zephyr to include code that executes in
|
||||
normal mode only, as well as to exclude code that is
|
||||
designed to execute only in secure mode.
|
||||
|
||||
Code executing in normal mode has no access to secure
|
||||
resources of the ARC processors, and, therefore, it shall avoid
|
||||
accessing them.
|
||||
|
||||
menu "ARC MPU Options"
|
||||
depends on CPU_HAS_MPU
|
||||
|
||||
@@ -314,24 +197,6 @@ config CACHE_FLUSHING
|
||||
If the d-cache is present, set this to y.
|
||||
If the d-cache is NOT present, set this to n.
|
||||
|
||||
config ARC_EXCEPTION_STACK_SIZE
|
||||
int "ARC exception handling stack size"
|
||||
default 768
|
||||
help
|
||||
Size in bytes of exception handling stack which is at the top of
|
||||
interrupt stack to get smaller memory footprint because exception
|
||||
is not frequent. To reduce the impact on interrupt handling,
|
||||
especially nested interrupt, it cannot be too large.
|
||||
|
||||
endmenu
|
||||
|
||||
config ARC_EXCEPTION_DEBUG
|
||||
bool "Unhandled exception debugging information"
|
||||
default n
|
||||
depends on PRINTK || LOG
|
||||
help
|
||||
Print human-readable information about exception vectors, cause codes,
|
||||
and parameters, at a cost of code/data size for the human-readable
|
||||
strings.
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -3,30 +3,27 @@
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources(
|
||||
thread.c
|
||||
thread_entry_wrapper.S
|
||||
cpu_idle.S
|
||||
fatal.c
|
||||
fault.c
|
||||
fault_s.S
|
||||
irq_manage.c
|
||||
timestamp.c
|
||||
isr_wrapper.S
|
||||
regular_irq.S
|
||||
switch.S
|
||||
prep_c.c
|
||||
reset.S
|
||||
vector_table.c
|
||||
)
|
||||
thread.c
|
||||
thread_entry_wrapper.S
|
||||
cpu_idle.S
|
||||
fatal.c
|
||||
fault.c
|
||||
fault_s.S
|
||||
irq_manage.c
|
||||
cache.c
|
||||
timestamp.c
|
||||
isr_wrapper.S
|
||||
regular_irq.S
|
||||
swap.S
|
||||
sys_fatal_error_handler.c
|
||||
prep_c.c
|
||||
reset.S
|
||||
vector_table.c
|
||||
)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_CACHE_FLUSHING cache.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_ARC_FIRQ fast_irq.S)
|
||||
|
||||
zephyr_library_sources_if_kconfig(irq_offload.c)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_USERSPACE userspace.S)
|
||||
zephyr_library_sources_ifdef(CONFIG_ARC_CONNECT arc_connect.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_ARC_CONNECT arc_smp.c)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_ATOMIC_OPERATIONS_CUSTOM atomic.c)
|
||||
add_subdirectory_ifdef(CONFIG_ARC_CORE_MPU mpu)
|
||||
add_subdirectory_ifdef(CONFIG_ARC_SECURE_FIRMWARE secureshield)
|
||||
zephyr_library_sources_ifdef(CONFIG_USERSPACE userspace.S)
|
||||
|
||||
@@ -1,449 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Synopsys.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief ARCv2 ARC CONNECT driver
|
||||
*
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <spinlock.h>
|
||||
|
||||
|
||||
static struct k_spinlock arc_connect_spinlock;
|
||||
|
||||
#define LOCKED(lck) for (k_spinlock_key_t __i = {}, \
|
||||
__key = k_spin_lock(lck); \
|
||||
!__i.key; \
|
||||
k_spin_unlock(lck, __key), __i.key = 1)
|
||||
|
||||
|
||||
/* Generate an inter-core interrupt to the target core */
|
||||
void z_arc_connect_ici_generate(u32_t core)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_INTRPT_GENERATE_IRQ, core);
|
||||
}
|
||||
}
|
||||
|
||||
/* Acknowledge the inter-core interrupt raised by core */
|
||||
void z_arc_connect_ici_ack(u32_t core)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_INTRPT_GENERATE_ACK, core);
|
||||
}
|
||||
}
|
||||
|
||||
/* Read inter-core interrupt status */
|
||||
u32_t z_arc_connect_ici_read_status(u32_t core)
|
||||
{
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_INTRPT_READ_STATUS, core);
|
||||
ret = z_arc_connect_cmd_readback();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Check the source of inter-core interrupt */
|
||||
u32_t z_arc_connect_ici_check_src(void)
|
||||
{
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_INTRPT_CHECK_SOURCE, 0);
|
||||
ret = z_arc_connect_cmd_readback();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Clear the inter-core interrupt */
|
||||
void z_arc_connect_ici_clear(void)
|
||||
{
|
||||
u32_t cpu, c;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_INTRPT_CHECK_SOURCE, 0);
|
||||
cpu = z_arc_connect_cmd_readback(); /* 1,2,4,8... */
|
||||
/*
|
||||
* In rare case, multiple concurrent ICIs sent to same target can
|
||||
* possibly be coalesced by MCIP into 1 asserted IRQ, so @cpu can be
|
||||
* "vectored" (multiple bits sets) as opposed to typical single bit
|
||||
*/
|
||||
while (cpu) {
|
||||
c = find_lsb_set(cpu) - 1;
|
||||
z_arc_connect_cmd(
|
||||
ARC_CONNECT_CMD_INTRPT_GENERATE_ACK, c);
|
||||
cpu &= ~(1U << c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset the cores in core_mask */
|
||||
void z_arc_connect_debug_reset(u32_t core_mask)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd_data(ARC_CONNECT_CMD_DEBUG_RESET,
|
||||
0, core_mask);
|
||||
}
|
||||
}
|
||||
|
||||
/* Halt the cores in core_mask */
|
||||
void z_arc_connect_debug_halt(u32_t core_mask)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd_data(ARC_CONNECT_CMD_DEBUG_HALT,
|
||||
0, core_mask);
|
||||
}
|
||||
}
|
||||
|
||||
/* Run the cores in core_mask */
|
||||
void z_arc_connect_debug_run(u32_t core_mask)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd_data(ARC_CONNECT_CMD_DEBUG_RUN,
|
||||
0, core_mask);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set core mask */
|
||||
void z_arc_connect_debug_mask_set(u32_t core_mask, u32_t mask)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd_data(ARC_CONNECT_CMD_DEBUG_SET_MASK,
|
||||
mask, core_mask);
|
||||
}
|
||||
}
|
||||
|
||||
/* Read core mask */
|
||||
u32_t z_arc_connect_debug_mask_read(u32_t core_mask)
|
||||
{
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd_data(ARC_CONNECT_CMD_DEBUG_READ_MASK,
|
||||
0, core_mask);
|
||||
ret = z_arc_connect_cmd_readback();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Select cores that should be halted if the core issuing the command is halted
|
||||
*/
|
||||
void z_arc_connect_debug_select_set(u32_t core_mask)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd_data(ARC_CONNECT_CMD_DEBUG_SET_SELECT,
|
||||
0, core_mask);
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the select value */
|
||||
u32_t z_arc_connect_debug_select_read(void)
|
||||
{
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_DEBUG_READ_SELECT, 0);
|
||||
ret = z_arc_connect_cmd_readback();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Read the status, halt or run of all cores in the system */
|
||||
u32_t z_arc_connect_debug_en_read(void)
|
||||
{
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_DEBUG_READ_EN, 0);
|
||||
ret = z_arc_connect_cmd_readback();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Read the last command sent */
|
||||
u32_t z_arc_connect_debug_cmd_read(void)
|
||||
{
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_DEBUG_READ_CMD, 0);
|
||||
ret = z_arc_connect_cmd_readback();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Read the value of internal MCD_CORE register */
|
||||
u32_t z_arc_connect_debug_core_read(void)
|
||||
{
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_DEBUG_READ_CORE, 0);
|
||||
ret = z_arc_connect_cmd_readback();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Clear global free running counter */
|
||||
void z_arc_connect_gfrc_clear(void)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_GFRC_CLEAR, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Read total 64 bits of global free running counter */
|
||||
u64_t z_arc_connect_gfrc_read(void)
|
||||
{
|
||||
u32_t low;
|
||||
u32_t high;
|
||||
u32_t key;
|
||||
|
||||
/*
|
||||
* each core has its own arc connect interface, i.e.,
|
||||
* CMD/READBACK. So several concurrent commands to ARC
|
||||
* connect are of if they are trying to access different
|
||||
* sub-components. For GFRC, HW allows simultaneously accessing to
|
||||
* counters. So an irq lock is enough.
|
||||
*/
|
||||
key = arch_irq_lock();
|
||||
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_GFRC_READ_LO, 0);
|
||||
low = z_arc_connect_cmd_readback();
|
||||
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_GFRC_READ_HI, 0);
|
||||
high = z_arc_connect_cmd_readback();
|
||||
|
||||
arch_irq_unlock(key);
|
||||
|
||||
return (((u64_t)high) << 32) | low;
|
||||
}
|
||||
|
||||
/* Enable global free running counter */
|
||||
void z_arc_connect_gfrc_enable(void)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_GFRC_ENABLE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable global free running counter */
|
||||
void z_arc_connect_gfrc_disable(void)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_GFRC_DISABLE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable global free running counter */
|
||||
void z_arc_connect_gfrc_core_set(u32_t core_mask)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd_data(ARC_CONNECT_CMD_GFRC_SET_CORE,
|
||||
0, core_mask);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the relevant cores to halt global free running counter */
|
||||
u32_t z_arc_connect_gfrc_halt_read(void)
|
||||
{
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_GFRC_READ_HALT, 0);
|
||||
ret = z_arc_connect_cmd_readback();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Read the internal CORE register */
|
||||
u32_t z_arc_connect_gfrc_core_read(void)
|
||||
{
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_GFRC_READ_CORE, 0);
|
||||
ret = z_arc_connect_cmd_readback();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Enable interrupt distribute unit */
|
||||
void z_arc_connect_idu_enable(void)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_ENABLE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable interrupt distribute unit */
|
||||
void z_arc_connect_idu_disable(void)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_DISABLE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Read enable status of interrupt distribute unit */
|
||||
u32_t z_arc_connect_idu_read_enable(void)
|
||||
{
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_READ_ENABLE, 0);
|
||||
ret = z_arc_connect_cmd_readback();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the triggering mode and distribution mode for the specified common
|
||||
* interrupt
|
||||
*/
|
||||
void z_arc_connect_idu_set_mode(u32_t irq_num,
|
||||
u16_t trigger_mode, u16_t distri_mode)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd_data(ARC_CONNECT_CMD_IDU_SET_MODE,
|
||||
irq_num, (distri_mode | (trigger_mode << 4)));
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the internal MODE register of the specified common interrupt */
|
||||
u32_t z_arc_connect_idu_read_mode(u32_t irq_num)
|
||||
{
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_READ_MODE, irq_num);
|
||||
ret = z_arc_connect_cmd_readback();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the target cores to receive the specified common interrupt
|
||||
* when it is triggered
|
||||
*/
|
||||
void z_arc_connect_idu_set_dest(u32_t irq_num, u32_t core_mask)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd_data(ARC_CONNECT_CMD_IDU_SET_DEST,
|
||||
irq_num, core_mask);
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the internal DEST register of the specified common interrupt */
|
||||
u32_t z_arc_connect_idu_read_dest(u32_t irq_num)
|
||||
{
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_READ_DEST, irq_num);
|
||||
ret = z_arc_connect_cmd_readback();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Assert the specified common interrupt */
|
||||
void z_arc_connect_idu_gen_cirq(u32_t irq_num)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_GEN_CIRQ, irq_num);
|
||||
}
|
||||
}
|
||||
|
||||
/* Acknowledge the specified common interrupt */
|
||||
void z_arc_connect_idu_ack_cirq(u32_t irq_num)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_ACK_CIRQ, irq_num);
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the internal STATUS register of the specified common interrupt */
|
||||
u32_t z_arc_connect_idu_check_status(u32_t irq_num)
|
||||
{
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_CHECK_STATUS, irq_num);
|
||||
ret = z_arc_connect_cmd_readback();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Read the internal SOURCE register of the specified common interrupt */
|
||||
u32_t z_arc_connect_idu_check_source(u32_t irq_num)
|
||||
{
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_CHECK_SOURCE, irq_num);
|
||||
ret = z_arc_connect_cmd_readback();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Mask or unmask the specified common interrupt */
|
||||
void z_arc_connect_idu_set_mask(u32_t irq_num, u32_t mask)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd_data(ARC_CONNECT_CMD_IDU_SET_MASK,
|
||||
irq_num, mask);
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the internal MASK register of the specified common interrupt */
|
||||
u32_t z_arc_connect_idu_read_mask(u32_t irq_num)
|
||||
{
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_READ_MASK, irq_num);
|
||||
ret = z_arc_connect_cmd_readback();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if it is the first-acknowledging core to the common interrupt
|
||||
* if IDU is programmed in the first-acknowledged mode
|
||||
*/
|
||||
u32_t z_arc_connect_idu_check_first(u32_t irq_num)
|
||||
{
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_CHECK_FIRST, irq_num);
|
||||
ret = z_arc_connect_cmd_readback();
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
@@ -1,185 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Synopsys.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief codes required for ARC multicore and Zephyr smp support
|
||||
*
|
||||
*/
|
||||
#include <device.h>
|
||||
#include <kernel.h>
|
||||
#include <kernel_structs.h>
|
||||
#include <ksched.h>
|
||||
#include <soc.h>
|
||||
#include <init.h>
|
||||
|
||||
|
||||
#ifndef IRQ_ICI
|
||||
#define IRQ_ICI 19
|
||||
#endif
|
||||
|
||||
#define ARCV2_ICI_IRQ_PRIORITY 1
|
||||
|
||||
volatile struct {
|
||||
void (*fn)(int, void*);
|
||||
void *arg;
|
||||
} arc_cpu_init[CONFIG_MP_NUM_CPUS];
|
||||
|
||||
/*
|
||||
* arc_cpu_wake_flag is used to sync up master core and slave cores
|
||||
* Slave core will spin for arc_cpu_wake_flag until master core sets
|
||||
* it to the core id of slave core. Then, slave core clears it to notify
|
||||
* master core that it's waken
|
||||
*
|
||||
*/
|
||||
volatile u32_t arc_cpu_wake_flag;
|
||||
|
||||
volatile char *arc_cpu_sp;
|
||||
/*
|
||||
* _curr_cpu is used to record the struct of _cpu_t of each cpu.
|
||||
* for efficient usage in assembly
|
||||
*/
|
||||
volatile _cpu_t *_curr_cpu[CONFIG_MP_NUM_CPUS];
|
||||
|
||||
/* Called from Zephyr initialization */
|
||||
void arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz,
|
||||
void (*fn)(int, void *), void *arg)
|
||||
{
|
||||
_curr_cpu[cpu_num] = &(_kernel.cpus[cpu_num]);
|
||||
arc_cpu_init[cpu_num].fn = fn;
|
||||
arc_cpu_init[cpu_num].arg = arg;
|
||||
|
||||
/* set the initial sp of target sp through arc_cpu_sp
|
||||
* arc_cpu_wake_flag will protect arc_cpu_sp that
|
||||
* only one slave cpu can read it per time
|
||||
*/
|
||||
arc_cpu_sp = Z_THREAD_STACK_BUFFER(stack) + sz;
|
||||
|
||||
arc_cpu_wake_flag = cpu_num;
|
||||
|
||||
/* wait slave cpu to start */
|
||||
while (arc_cpu_wake_flag != 0) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/* the C entry of slave cores */
|
||||
void z_arc_slave_start(int cpu_num)
|
||||
{
|
||||
void (*fn)(int, void*);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
z_icache_setup();
|
||||
z_irq_setup();
|
||||
|
||||
z_arc_connect_ici_clear();
|
||||
z_irq_priority_set(IRQ_ICI, ARCV2_ICI_IRQ_PRIORITY, 0);
|
||||
irq_enable(IRQ_ICI);
|
||||
#endif
|
||||
/* call the function set by arch_start_cpu */
|
||||
fn = arc_cpu_init[cpu_num].fn;
|
||||
|
||||
fn(cpu_num, arc_cpu_init[cpu_num].arg);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
static void sched_ipi_handler(void *unused)
|
||||
{
|
||||
ARG_UNUSED(unused);
|
||||
|
||||
z_arc_connect_ici_clear();
|
||||
z_sched_ipi();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check whether need to do thread switch in isr context
|
||||
*
|
||||
* @details u64_t is used to let compiler use (r0, r1) as return register.
|
||||
* use register r0 and register r1 as return value, r0 has
|
||||
* new thread, r1 has old thread. If r0 == 0, it means no thread switch.
|
||||
*/
|
||||
u64_t z_arc_smp_switch_in_isr(void)
|
||||
{
|
||||
u64_t ret = 0;
|
||||
u32_t new_thread;
|
||||
u32_t old_thread;
|
||||
|
||||
old_thread = (u32_t)_current;
|
||||
|
||||
new_thread = (u32_t)z_get_next_ready_thread();
|
||||
|
||||
if (new_thread != old_thread) {
|
||||
#ifdef CONFIG_TIMESLICING
|
||||
z_reset_time_slice();
|
||||
#endif
|
||||
_current_cpu->swap_ok = 0;
|
||||
((struct k_thread *)new_thread)->base.cpu =
|
||||
arch_curr_cpu()->id;
|
||||
_current = (struct k_thread *) new_thread;
|
||||
ret = new_thread | ((u64_t)(old_thread) << 32);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* arch implementation of sched_ipi */
|
||||
void arch_sched_ipi(void)
|
||||
{
|
||||
u32_t i;
|
||||
|
||||
/* broadcast sched_ipi request to other cores
|
||||
* if the target is current core, hardware will ignore it
|
||||
*/
|
||||
for (i = 0; i < CONFIG_MP_NUM_CPUS; i++) {
|
||||
z_arc_connect_ici_generate(i);
|
||||
}
|
||||
}
|
||||
|
||||
static int arc_smp_init(struct device *dev)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
struct arc_connect_bcr bcr;
|
||||
|
||||
/* necessary master core init */
|
||||
_kernel.cpus[0].id = 0;
|
||||
_kernel.cpus[0].irq_stack = Z_THREAD_STACK_BUFFER(_interrupt_stack)
|
||||
+ CONFIG_ISR_STACK_SIZE;
|
||||
_curr_cpu[0] = &(_kernel.cpus[0]);
|
||||
|
||||
bcr.val = z_arc_v2_aux_reg_read(_ARC_V2_CONNECT_BCR);
|
||||
|
||||
if (bcr.ipi) {
|
||||
/* register ici interrupt, just need master core to register once */
|
||||
z_arc_connect_ici_clear();
|
||||
IRQ_CONNECT(IRQ_ICI, ARCV2_ICI_IRQ_PRIORITY,
|
||||
sched_ipi_handler, NULL, 0);
|
||||
|
||||
irq_enable(IRQ_ICI);
|
||||
} else {
|
||||
__ASSERT(0,
|
||||
"ARC connect has no inter-core interrupt\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (bcr.gfrc) {
|
||||
/* global free running count init */
|
||||
z_arc_connect_gfrc_enable();
|
||||
|
||||
/* when all cores halt, gfrc halt */
|
||||
z_arc_connect_gfrc_core_set((1 << CONFIG_MP_NUM_CPUS) - 1);
|
||||
z_arc_connect_gfrc_clear();
|
||||
} else {
|
||||
__ASSERT(0,
|
||||
"ARC connect has no global free running counter\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYS_INIT(arc_smp_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||
#endif
|
||||
422
arch/arc/core/atomic.S
Normal file
422
arch/arc/core/atomic.S
Normal file
@@ -0,0 +1,422 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief ARC atomic operations library
|
||||
*
|
||||
* This library provides routines to perform a number of atomic operations
|
||||
* on a memory location: add, subtract, increment, decrement, bitwise OR,
|
||||
* bitwise NOR, bitwise AND, bitwise NAND, set, clear and compare-and-swap.
|
||||
*
|
||||
* This requires the processor to support LLOCK and SCOND instructions,
|
||||
* where they are not supported on ARC EM family processors.
|
||||
*/
|
||||
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
|
||||
/* exports */
|
||||
|
||||
GTEXT(atomic_set)
|
||||
GTEXT(atomic_get)
|
||||
GTEXT(atomic_add)
|
||||
GTEXT(atomic_nand)
|
||||
GTEXT(atomic_and)
|
||||
GTEXT(atomic_or)
|
||||
GTEXT(atomic_xor)
|
||||
GTEXT(atomic_clear)
|
||||
GTEXT(atomic_dec)
|
||||
GTEXT(atomic_inc)
|
||||
GTEXT(atomic_sub)
|
||||
GTEXT(atomic_cas)
|
||||
|
||||
.section .TEXT._Atomic, "ax"
|
||||
.balign 2
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomically clear a memory location
|
||||
*
|
||||
* This routine atomically clears the contents of <target> and returns the old
|
||||
* value that was in <target>.
|
||||
*
|
||||
* This routine can be used from both task and interrupt level.
|
||||
*
|
||||
* @return Contents of <target> before the atomic operation
|
||||
*
|
||||
* ERRNO: N/A
|
||||
*
|
||||
* atomic_val_t atomic_clear
|
||||
* (
|
||||
* atomic_t *target /@ memory location to clear @/
|
||||
* )
|
||||
*/
|
||||
|
||||
SECTION_SUBSEC_FUNC(TEXT, atomic_clear_set, atomic_clear)
|
||||
mov_s r1, 0
|
||||
/* fall through into atomic_set */
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomically set a memory location
|
||||
*
|
||||
* This routine atomically sets the contents of <target> to <value> and returns
|
||||
* the old value that was in <target>.
|
||||
*
|
||||
* This routine can be used from both task and interrupt level.
|
||||
*
|
||||
* @return Contents of <target> before the atomic operation
|
||||
*
|
||||
* ERRNO: N/A
|
||||
*
|
||||
* atomic_val_t atomic_set
|
||||
* (
|
||||
* atomic_t *target, /@ memory location to set @/
|
||||
* atomic_val_t value /@ set with this value @/
|
||||
* )
|
||||
*
|
||||
*/
|
||||
|
||||
SECTION_SUBSEC_FUNC(TEXT, atomic_clear_set, atomic_set)
|
||||
|
||||
ex r1, [r0] /* swap new value with old value */
|
||||
|
||||
j_s.d [blink]
|
||||
mov_s r0, r1 /* return old value */
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Get the value of a shared memory atomically
|
||||
*
|
||||
* This routine atomically retrieves the value in *target
|
||||
*
|
||||
* atomic_val_t atomic_get
|
||||
* (
|
||||
* atomic_t *target /@ address of atom to be retrieved @/
|
||||
* )
|
||||
*
|
||||
* RETURN: value read from address target.
|
||||
*
|
||||
*/
|
||||
|
||||
SECTION_FUNC(TEXT, atomic_get)
|
||||
ld_s r0, [r0, 0]
|
||||
j_s [blink]
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomically increment a memory location
|
||||
*
|
||||
* This routine atomically increments the value in <target>. The operation is
|
||||
* done using unsigned integer arithmetic. Various CPU architectures may impose
|
||||
* restrictions with regards to the alignment and cache attributes of the
|
||||
* atomic_t type.
|
||||
*
|
||||
* This routine can be used from both task and interrupt level.
|
||||
*
|
||||
* @return Contents of <target> before the atomic operation
|
||||
*
|
||||
* ERRNO: N/A
|
||||
*
|
||||
* atomic_val_t atomic_inc
|
||||
* (
|
||||
* atomic_t *target, /@ memory location to increment @/
|
||||
* )
|
||||
*
|
||||
*/
|
||||
|
||||
SECTION_SUBSEC_FUNC(TEXT, atomic_inc_add, atomic_inc)
|
||||
mov_s r1, 1
|
||||
/* fall through into atomic_add */
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomically add a value to a memory location
|
||||
*
|
||||
* This routine atomically adds the contents of <target> and <value>, placing
|
||||
* the result in <target>. The operation is done using signed integer arithmetic.
|
||||
* Various CPU architectures may impose restrictions with regards to the
|
||||
* alignment and cache attributes of the atomic_t type.
|
||||
*
|
||||
* This routine can be used from both task and interrupt level.
|
||||
*
|
||||
* @return Contents of <target> before the atomic operation
|
||||
*
|
||||
* ERRNO: N/A
|
||||
*
|
||||
* atomic_val_t atomic_add
|
||||
* (
|
||||
* atomic_t *target, /@ memory location to add to @/
|
||||
* atomic_val_t value /@ value to add @/
|
||||
* )
|
||||
*/
|
||||
|
||||
SECTION_SUBSEC_FUNC(TEXT, atomic_inc_add, atomic_add)
|
||||
|
||||
llock r2, [r0] /* load old value and mark exclusive access */
|
||||
add_s r3, r1, r2
|
||||
scond r3, [r0] /* try to store new value */
|
||||
|
||||
/* STATUS32.Z = 1 if successful */
|
||||
|
||||
bne_s atomic_add /* if store is not successful, retry */
|
||||
|
||||
j_s.d [blink]
|
||||
mov_s r0, r2 /* return old value */
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomically decrement a memory location
|
||||
*
|
||||
* This routine atomically decrements the value in <target>. The operation is
|
||||
* done using unsigned integer arithmetic. Various CPU architectures may impose
|
||||
* restrictions with regards to the alignment and cache attributes of the
|
||||
* atomic_t type.
|
||||
*
|
||||
* This routine can be used from both task and interrupt level.
|
||||
*
|
||||
* @return Contents of <target> before the atomic operation
|
||||
*
|
||||
* ERRNO: N/A
|
||||
*
|
||||
* atomic_val_t atomic_dec
|
||||
* (
|
||||
* atomic_t *target, /@ memory location to decrement @/
|
||||
* )
|
||||
*
|
||||
*/
|
||||
|
||||
SECTION_SUBSEC_FUNC(TEXT, atomic_dec_sub, atomic_dec)
|
||||
mov_s r1, 1
|
||||
/* fall through into atomic_sub */
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomically subtract a value from a memory location
|
||||
*
|
||||
* This routine atomically subtracts <value> from the contents of <target>,
|
||||
* placing the result in <target>. The operation is done using signed integer
|
||||
* arithmetic. Various CPU architectures may impose restrictions with regards to
|
||||
* the alignment and cache attributes of the atomic_t type.
|
||||
*
|
||||
* This routine can be used from both task and interrupt level.
|
||||
*
|
||||
* @return Contents of <target> before the atomic operation
|
||||
*
|
||||
* ERRNO: N/A
|
||||
*
|
||||
* atomic_val_t atomic_sub
|
||||
* (
|
||||
* atomic_t *target, /@ memory location to subtract from @/
|
||||
* atomic_val_t value /@ value to subtract @/
|
||||
* )
|
||||
*
|
||||
*/
|
||||
|
||||
SECTION_SUBSEC_FUNC(TEXT, atomic_dec_sub, atomic_sub)
|
||||
|
||||
llock r2, [r0] /* load old value and mark exclusive access */
|
||||
sub r3, r2, r1
|
||||
scond r3, [r0] /* try to store new value */
|
||||
|
||||
/* STATUS32.Z = 1 if successful */
|
||||
|
||||
bne_s atomic_sub /* if store is not successful, retry */
|
||||
|
||||
j_s.d [blink]
|
||||
mov_s r0, r2 /* return old value */
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomically perform a bitwise NAND on a memory location
|
||||
*
|
||||
* This routine atomically performs a bitwise NAND operation of the contents of
|
||||
* <target> and <value>, placing the result in <target>.
|
||||
* Various CPU architectures may impose restrictions with regards to the
|
||||
* alignment and cache attributes of the atomic_t type.
|
||||
*
|
||||
* This routine can be used from both task and interrupt level.
|
||||
*
|
||||
* @return Contents of <target> before the atomic operation
|
||||
*
|
||||
* ERRNO: N/A
|
||||
*
|
||||
* atomic_val_t atomic_nand
|
||||
* (
|
||||
* atomic_t *target, /@ memory location to NAND @/
|
||||
* atomic_val_t value /@ NAND with this value @/
|
||||
* )
|
||||
*
|
||||
*/
|
||||
|
||||
SECTION_FUNC(TEXT, atomic_nand)
|
||||
|
||||
llock r2, [r0] /* load old value and mark exclusive access */
|
||||
and r3, r1, r2
|
||||
not r3, r3
|
||||
scond r3, [r0] /* try to store new value */
|
||||
|
||||
/* STATUS32.Z = 1 if successful */
|
||||
|
||||
bne_s atomic_nand /* if store is not successful, retry */
|
||||
|
||||
j_s.d [blink]
|
||||
mov_s r0, r2 /* return old value */
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomically perform a bitwise AND on a memory location
|
||||
*
|
||||
* This routine atomically performs a bitwise AND operation of the contents of
|
||||
* <target> and <value>, placing the result in <target>.
|
||||
* Various CPU architectures may impose restrictions with regards to the
|
||||
* alignment and cache attributes of the atomic_t type.
|
||||
*
|
||||
* This routine can be used from both task and interrupt level.
|
||||
*
|
||||
* @return Contents of <target> before the atomic operation
|
||||
*
|
||||
* ERRNO: N/A
|
||||
*
|
||||
* atomic_val_t atomic_and
|
||||
* (
|
||||
* atomic_t *target, /@ memory location to AND @/
|
||||
* atomic_val_t value /@ AND with this value @/
|
||||
* )
|
||||
*
|
||||
*/
|
||||
|
||||
SECTION_FUNC(TEXT, atomic_and)
|
||||
|
||||
llock r2, [r0] /* load old value and mark exclusive access */
|
||||
and r3, r1, r2
|
||||
scond r3, [r0] /* try to store new value */
|
||||
|
||||
/* STATUS32.Z = 1 if successful */
|
||||
|
||||
bne_s atomic_and /* if store is not successful, retry */
|
||||
|
||||
j_s.d [blink]
|
||||
mov_s r0, r2 /* return old value */
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomically perform a bitwise OR on memory location
|
||||
*
|
||||
* This routine atomically performs a bitwise OR operation of the contents of
|
||||
* <target> and <value>, placing the result in <target>.
|
||||
* Various CPU architectures may impose restrictions with regards to the
|
||||
* alignment and cache attributes of the atomic_t type.
|
||||
*
|
||||
* This routine can be used from both task and interrupt level.
|
||||
*
|
||||
* @return Contents of <target> before the atomic operation
|
||||
*
|
||||
* ERRNO: N/A
|
||||
*
|
||||
* atomic_val_t atomic_or
|
||||
* (
|
||||
* atomic_t *target, /@ memory location to OR @/
|
||||
* atomic_val_t value /@ OR with this value @/
|
||||
* )
|
||||
*
|
||||
*/
|
||||
|
||||
SECTION_FUNC(TEXT, atomic_or)
|
||||
|
||||
llock r2, [r0] /* load old value and mark exclusive access */
|
||||
or r3, r1, r2
|
||||
scond r3, [r0] /* try to store new value */
|
||||
|
||||
/* STATUS32.Z = 1 if successful */
|
||||
|
||||
bne_s atomic_or /* if store is not successful, retry */
|
||||
|
||||
j_s.d [blink]
|
||||
mov_s r0, r2 /* return old value */
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomically perform a bitwise XOR on a memory location
|
||||
*
|
||||
* This routine atomically performs a bitwise XOR operation of the contents of
|
||||
* <target> and <value>, placing the result in <target>.
|
||||
* Various CPU architectures may impose restrictions with regards to the
|
||||
* alignment and cache attributes of the atomic_t type.
|
||||
*
|
||||
* This routine can be used from both task and interrupt level.
|
||||
*
|
||||
* @return Contents of <target> before the atomic operation
|
||||
*
|
||||
* ERRNO: N/A
|
||||
*
|
||||
* atomic_val_t atomic_xor
|
||||
* (
|
||||
* atomic_t *target, /@ memory location to XOR @/
|
||||
* atomic_val_t value /@ XOR with this value @/
|
||||
* )
|
||||
*
|
||||
*/
|
||||
|
||||
SECTION_FUNC(TEXT, atomic_xor)
|
||||
|
||||
llock r2, [r0] /* load old value and mark exclusive access */
|
||||
xor r3, r1, r2
|
||||
scond r3, [r0] /* try to store new value */
|
||||
|
||||
/* STATUS32.Z = 1 if successful */
|
||||
|
||||
bne_s atomic_xor /* if store is not successful, retry */
|
||||
|
||||
j_s.d [blink]
|
||||
mov_s r0, r2 /* return old value */
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Atomically compare-and-swap the contents of a memory location
|
||||
*
|
||||
* This routine performs an atomic compare-and-swap. testing that the contents of
|
||||
* <target> contains <oldValue>, and if it does, setting the value of <target>
|
||||
* to <newValue>. Various CPU architectures may impose restrictions with regards
|
||||
* to the alignment and cache attributes of the atomic_t type.
|
||||
*
|
||||
* This routine can be used from both task and interrupt level.
|
||||
*
|
||||
* @return 1 if the swap is actually executed, 0 otherwise.
|
||||
*
|
||||
* ERRNO: N/A
|
||||
*
|
||||
* int atomic_cas
|
||||
* (
|
||||
* atomic_t *target, /@ memory location to compare-and-swap @/
|
||||
* atomic_val_t oldValue, /@ compare to this value @/
|
||||
* atomic_val_t newValue, /@ swap with this value @/
|
||||
* )
|
||||
*
|
||||
*/
|
||||
|
||||
SECTION_FUNC(TEXT, atomic_cas)
|
||||
|
||||
llock r3, [r0] /* load old value and mark exclusive access */
|
||||
cmp_s r1, r3
|
||||
|
||||
bne_s nanoAtomicCas_fail
|
||||
|
||||
scond r2, [r0] /* try to store new value */
|
||||
|
||||
/* STATUS32.Z = 1 if successful */
|
||||
|
||||
bne_s atomic_cas /* if store is not successful, retry */
|
||||
|
||||
j_s.d [blink]
|
||||
mov_s r0, 1 /* return TRUE */
|
||||
|
||||
/* failed comparison */
|
||||
nanoAtomicCas_fail:
|
||||
scond r1, [r0] /* write old value to clear the access lock */
|
||||
j_s.d [blink]
|
||||
mov_s r0, 0 /* return FALSE */
|
||||
@@ -15,16 +15,18 @@
|
||||
|
||||
#include <kernel.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <sys/util.h>
|
||||
#include <misc/util.h>
|
||||
#include <toolchain.h>
|
||||
#include <cache.h>
|
||||
#include <linker/linker-defs.h>
|
||||
#include <arch/arc/v2/aux_regs.h>
|
||||
#include <kernel_internal.h>
|
||||
#include <sys/__assert.h>
|
||||
#include <misc/__assert.h>
|
||||
#include <init.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#if defined(CONFIG_CACHE_FLUSHING)
|
||||
|
||||
#if (CONFIG_CACHE_LINE_SIZE == 0) && !defined(CONFIG_CACHE_LINE_SIZE_DETECT)
|
||||
#error Cannot use this implementation with a cache line size of 0
|
||||
#endif
|
||||
@@ -169,3 +171,6 @@ static int init_dcache(struct device *unused)
|
||||
}
|
||||
|
||||
SYS_INIT(init_dcache, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||
|
||||
#endif /* CONFIG_CACHE_FLUSHING */
|
||||
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
#include <linker/sections.h>
|
||||
#include <arch/cpu.h>
|
||||
|
||||
GTEXT(arch_cpu_idle)
|
||||
GTEXT(arch_cpu_atomic_idle)
|
||||
GDATA(z_arc_cpu_sleep_mode)
|
||||
GTEXT(k_cpu_idle)
|
||||
GTEXT(k_cpu_atomic_idle)
|
||||
GDATA(k_cpu_sleep_mode)
|
||||
|
||||
SECTION_VAR(BSS, z_arc_cpu_sleep_mode)
|
||||
SECTION_VAR(BSS, k_cpu_sleep_mode)
|
||||
.balign 4
|
||||
.word 0
|
||||
|
||||
@@ -33,29 +33,17 @@ SECTION_VAR(BSS, z_arc_cpu_sleep_mode)
|
||||
* void nanCpuIdle(void)
|
||||
*/
|
||||
|
||||
SECTION_FUNC(TEXT, arch_cpu_idle)
|
||||
SECTION_FUNC(TEXT, k_cpu_idle)
|
||||
|
||||
#ifdef CONFIG_TRACING
|
||||
push_s blink
|
||||
jl sys_trace_idle
|
||||
jl z_sys_trace_idle
|
||||
pop_s blink
|
||||
#endif
|
||||
|
||||
ld r1, [z_arc_cpu_sleep_mode]
|
||||
ld r1, [k_cpu_sleep_mode]
|
||||
or r1, r1, (1 << 4) /* set IRQ-enabled bit */
|
||||
/*
|
||||
* It's found that (in nsim_hs_smp), when cpu
|
||||
* is sleeping, no response to inter-processor interrupt
|
||||
* although it's pending and interrupts are enabled.
|
||||
* here is a workround
|
||||
*/
|
||||
#if !defined(CONFIG_SOC_NSIM) && !defined(CONFIG_SMP)
|
||||
sleep r1
|
||||
#else
|
||||
seti r1
|
||||
_z_arc_idle_loop:
|
||||
b _z_arc_idle_loop
|
||||
#endif
|
||||
j_s [blink]
|
||||
nop
|
||||
|
||||
@@ -64,17 +52,17 @@ _z_arc_idle_loop:
|
||||
*
|
||||
* This function exits with interrupts restored to <key>.
|
||||
*
|
||||
* void arch_cpu_atomic_idle(unsigned int key)
|
||||
* void k_cpu_atomic_idle(unsigned int key)
|
||||
*/
|
||||
SECTION_FUNC(TEXT, arch_cpu_atomic_idle)
|
||||
SECTION_FUNC(TEXT, k_cpu_atomic_idle)
|
||||
|
||||
#ifdef CONFIG_TRACING
|
||||
push_s blink
|
||||
jl sys_trace_idle
|
||||
jl z_sys_trace_idle
|
||||
pop_s blink
|
||||
#endif
|
||||
|
||||
ld r1, [z_arc_cpu_sleep_mode]
|
||||
ld r1, [k_cpu_sleep_mode]
|
||||
or r1, r1, (1 << 4) /* set IRQ-enabled bit */
|
||||
sleep r1
|
||||
j_s.d [blink]
|
||||
|
||||
@@ -16,13 +16,19 @@
|
||||
#include <kernel_structs.h>
|
||||
#include <offsets_short.h>
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <swap_macros.h>
|
||||
|
||||
GTEXT(_firq_enter)
|
||||
GTEXT(_firq_exit)
|
||||
|
||||
GDATA(exc_nest_count)
|
||||
#if CONFIG_RGF_NUM_BANKS == 1
|
||||
GDATA(saved_r0)
|
||||
#else
|
||||
GDATA(saved_sp)
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Work to be done before handing control to a FIRQ ISR
|
||||
@@ -54,10 +60,12 @@ SECTION_FUNC(TEXT, _firq_enter)
|
||||
* This has already been done by _isr_wrapper.
|
||||
*/
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
lr r2, [_ARC_V2_SEC_STAT]
|
||||
bclr r2, r2, _ARC_V2_SEC_STAT_SSC_BIT
|
||||
sflag r2
|
||||
/* sflag r2 */
|
||||
/* sflag instruction is not supported in current ARC GNU */
|
||||
.long 0x00bf302f
|
||||
#else
|
||||
/* disable stack checking */
|
||||
lr r2, [_ARC_V2_STATUS32]
|
||||
@@ -77,50 +85,32 @@ SECTION_FUNC(TEXT, _firq_enter)
|
||||
lr r25, [_ARC_V2_LP_END]
|
||||
#endif
|
||||
|
||||
/* check whether irq stack is used */
|
||||
_check_and_inc_int_nest_counter r0, r1
|
||||
ld r1, [exc_nest_count]
|
||||
add r0, r1, 1
|
||||
st r0, [exc_nest_count]
|
||||
cmp r1, 0
|
||||
|
||||
bne.d firq_nest
|
||||
mov_s r0, sp
|
||||
bgt.d firq_nest
|
||||
mov r0, sp
|
||||
|
||||
_get_curr_cpu_irq_stack sp
|
||||
mov r1, _kernel
|
||||
ld sp, [r1, _kernel_offset_to_irq_stack]
|
||||
#if CONFIG_RGF_NUM_BANKS != 1
|
||||
b firq_nest_1
|
||||
firq_nest:
|
||||
/*
|
||||
* because firq and rirq share the same interrupt stack,
|
||||
* switch back to original register bank to get correct sp.
|
||||
* to get better firq latency, an approach is to prepare
|
||||
* separate interrupt stack for firq and do not do thread
|
||||
* switch in firq.
|
||||
*/
|
||||
lr r1, [_ARC_V2_STATUS32]
|
||||
and r1, r1, ~_ARC_V2_STATUS32_RB(7)
|
||||
kflag r1
|
||||
mov r1, ilink
|
||||
lr r0, [_ARC_V2_STATUS32]
|
||||
and r0, r0, ~_ARC_V2_STATUS32_RB(7)
|
||||
kflag r0
|
||||
|
||||
/* here use _ARC_V2_USER_SP and ilink to exchange sp
|
||||
* save original value of _ARC_V2_USER_SP and ilink into
|
||||
* the stack of interrupted context first, then restore them later
|
||||
*/
|
||||
push ilink
|
||||
PUSHAX ilink, _ARC_V2_USER_SP
|
||||
st sp, [saved_sp]
|
||||
|
||||
/* sp here is the sp of interrupted context */
|
||||
sr sp, [_ARC_V2_USER_SP]
|
||||
/* here, bank 0 sp must go back to the value before push and
|
||||
* PUSHAX as we will switch to bank1, the pop and POPAX later will
|
||||
* change bank1's sp, not bank0's sp
|
||||
*/
|
||||
add sp, sp, 8
|
||||
|
||||
/* switch back to banked reg, only ilink can be used */
|
||||
lr ilink, [_ARC_V2_STATUS32]
|
||||
or ilink, ilink, _ARC_V2_STATUS32_RB(1)
|
||||
kflag ilink
|
||||
lr sp, [_ARC_V2_USER_SP]
|
||||
|
||||
POPAX ilink, _ARC_V2_USER_SP
|
||||
pop ilink
|
||||
mov r0, sp
|
||||
ld sp, [saved_sp]
|
||||
mov ilink, r1
|
||||
firq_nest_1:
|
||||
#else
|
||||
firq_nest:
|
||||
@@ -145,11 +135,19 @@ SECTION_FUNC(TEXT, _firq_exit)
|
||||
sr r24, [_ARC_V2_LP_START]
|
||||
sr r25, [_ARC_V2_LP_END]
|
||||
#endif
|
||||
_dec_int_nest_counter r0, r1
|
||||
|
||||
_check_nest_int_by_irq_act r0, r1
|
||||
|
||||
jne _firq_no_reschedule
|
||||
/* check if we're a nested interrupt: if so, let the interrupted
|
||||
* interrupt handle the reschedule */
|
||||
mov r1, exc_nest_count
|
||||
ld r0, [r1]
|
||||
sub r0, r0, 1
|
||||
st r0, [r1]
|
||||
/* see comments in _rirq_exit */
|
||||
lr r0, [_ARC_V2_AUX_IRQ_ACT]
|
||||
and r0, r0, 0xffff
|
||||
ffs r1, r0
|
||||
fls r2, r0
|
||||
cmp r1, r2
|
||||
jne _firq_no_reschedule
|
||||
|
||||
#ifdef CONFIG_STACK_SENTINEL
|
||||
bl z_check_stack_sentinel
|
||||
@@ -157,18 +155,13 @@ SECTION_FUNC(TEXT, _firq_exit)
|
||||
|
||||
#ifdef CONFIG_PREEMPT_ENABLED
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
bl z_arc_smp_switch_in_isr
|
||||
/* r0 points to new thread, r1 points to old thread */
|
||||
brne r0, 0, _firq_reschedule
|
||||
#else
|
||||
mov_s r1, _kernel
|
||||
ld_s r2, [r1, _kernel_offset_to_current]
|
||||
|
||||
/* Check if the current thread (in r2) is the cached thread */
|
||||
ld_s r0, [r1, _kernel_offset_to_ready_q_cache]
|
||||
brne r0, r2, _firq_reschedule
|
||||
#endif
|
||||
|
||||
/* fall to no rescheduling */
|
||||
|
||||
#endif /* CONFIG_PREEMPT_ENABLED */
|
||||
@@ -182,7 +175,37 @@ _firq_no_reschedule:
|
||||
* instruction instead of a pair of cmp and bxx
|
||||
*/
|
||||
#if CONFIG_RGF_NUM_BANKS == 1
|
||||
_pop_irq_stack_frame
|
||||
add sp,sp,4 /* don't need r0 from stack */
|
||||
pop_s r1
|
||||
pop_s r2
|
||||
pop_s r3
|
||||
pop r4
|
||||
pop r5
|
||||
pop r6
|
||||
pop r7
|
||||
pop r8
|
||||
pop r9
|
||||
pop r10
|
||||
pop r11
|
||||
pop_s r12
|
||||
pop_s r13
|
||||
pop_s blink
|
||||
pop_s r0
|
||||
sr r0, [_ARC_V2_LP_END]
|
||||
pop_s r0
|
||||
sr r0, [_ARC_V2_LP_START]
|
||||
pop_s r0
|
||||
mov lp_count,r0
|
||||
#ifdef CONFIG_CODE_DENSITY
|
||||
pop_s r0
|
||||
sr r0, [_ARC_V2_EI_BASE]
|
||||
pop_s r0
|
||||
sr r0, [_ARC_V2_LDI_BASE]
|
||||
pop_s r0
|
||||
sr r0, [_ARC_V2_JLI_BASE]
|
||||
#endif
|
||||
ld r0,[saved_r0]
|
||||
add sp,sp,8 /* don't need ilink & status32_po from stack */
|
||||
#endif
|
||||
rtie
|
||||
|
||||
@@ -193,15 +216,6 @@ _firq_reschedule:
|
||||
pop sp
|
||||
|
||||
#if CONFIG_RGF_NUM_BANKS != 1
|
||||
#ifdef CONFIG_SMP
|
||||
/*
|
||||
* save r0, r1 in irq stack for a while, as they will be changed by register
|
||||
* bank switch
|
||||
*/
|
||||
_get_curr_cpu_irq_stack r2
|
||||
st r0, [r2, -4]
|
||||
st r1, [r2, -8]
|
||||
#endif
|
||||
/*
|
||||
* We know there is no interrupted interrupt of lower priority at this
|
||||
* point, so when switching back to register bank 0, it will contain the
|
||||
@@ -225,32 +239,17 @@ _firq_reschedule:
|
||||
st_s r0, [sp, ___isf_t_status32_OFFSET]
|
||||
|
||||
st ilink, [sp, ___isf_t_pc_OFFSET] /* ilink into pc */
|
||||
#ifdef CONFIG_SMP
|
||||
/*
|
||||
* load r0, r1 from irq stack
|
||||
*/
|
||||
_get_curr_cpu_irq_stack r2
|
||||
ld r0, [r2, -4]
|
||||
ld r1, [r2, -8]
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
mov_s r2, r1
|
||||
#else
|
||||
mov_s r1, _kernel
|
||||
ld_s r2, [r1, _kernel_offset_to_current]
|
||||
#endif
|
||||
|
||||
_save_callee_saved_regs
|
||||
|
||||
st _CAUSE_FIRQ, [r2, _thread_offset_to_relinquish_cause]
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
mov_s r2, r0
|
||||
#else
|
||||
ld_s r2, [r1, _kernel_offset_to_ready_q_cache]
|
||||
st_s r2, [r1, _kernel_offset_to_current]
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
_load_stack_check_regs
|
||||
@@ -263,7 +262,7 @@ _firq_reschedule:
|
||||
|
||||
#if defined(CONFIG_MPU_STACK_GUARD) || defined(CONFIG_USERSPACE)
|
||||
push_s r2
|
||||
mov_s r0, r2
|
||||
mov r0, r2
|
||||
bl configure_mpu_thread
|
||||
pop_s r2
|
||||
#endif
|
||||
@@ -279,21 +278,35 @@ _firq_reschedule:
|
||||
ld r3, [r2, _thread_offset_to_relinquish_cause]
|
||||
|
||||
breq r3, _CAUSE_RIRQ, _firq_return_from_rirq
|
||||
nop_s
|
||||
nop
|
||||
breq r3, _CAUSE_FIRQ, _firq_return_from_firq
|
||||
nop_s
|
||||
nop
|
||||
|
||||
/* fall through */
|
||||
|
||||
.balign 4
|
||||
_firq_return_from_coop:
|
||||
|
||||
ld r3, [r2, _thread_offset_to_intlock_key]
|
||||
st 0, [r2, _thread_offset_to_intlock_key]
|
||||
|
||||
/* pc into ilink */
|
||||
pop_s r0
|
||||
mov_s ilink, r0
|
||||
mov ilink, r0
|
||||
|
||||
pop_s r0 /* status32 into r0 */
|
||||
/*
|
||||
* There are only two interrupt lock states: locked and unlocked. When
|
||||
* entering z_swap(), they are always locked, so the IE bit is unset in
|
||||
* status32. If the incoming thread had them locked recursively, it
|
||||
* means that the IE bit should stay unset. The only time the bit
|
||||
* has to change is if they were not locked recursively.
|
||||
*/
|
||||
and.f r3, r3, (1 << 4)
|
||||
or.nz r0, r0, _ARC_V2_STATUS32_IE
|
||||
sr r0, [_ARC_V2_STATUS32_P0]
|
||||
|
||||
ld r0, [r2, _thread_offset_to_return_value]
|
||||
rtie
|
||||
|
||||
.balign 4
|
||||
|
||||
@@ -12,33 +12,81 @@
|
||||
* ARCv2 CPUs.
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <kernel_structs.h>
|
||||
#include <offsets_short.h>
|
||||
#include <toolchain.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_DECLARE(os);
|
||||
#include <misc/printk.h>
|
||||
#include <logging/log_ctrl.h>
|
||||
|
||||
void z_arc_fatal_error(unsigned int reason, const z_arch_esf_t *esf)
|
||||
/**
|
||||
*
|
||||
* @brief Kernel fatal error handler
|
||||
*
|
||||
* This routine is called when fatal error conditions are detected by software
|
||||
* and is responsible only for reporting the error. Once reported, it then
|
||||
* invokes the user provided routine z_SysFatalErrorHandler() which is
|
||||
* responsible for implementing the error handling policy.
|
||||
*
|
||||
* The caller is expected to always provide a usable ESF. In the event that the
|
||||
* fatal error does not have a hardware generated ESF, the caller should either
|
||||
* create its own or use a pointer to the global default ESF <_default_esf>.
|
||||
*
|
||||
* @return This function does not return.
|
||||
*/
|
||||
void z_NanoFatalErrorHandler(unsigned int reason, const NANO_ESF *pEsf)
|
||||
{
|
||||
if (reason == K_ERR_CPU_EXCEPTION) {
|
||||
LOG_ERR("Faulting instruction address = 0x%lx",
|
||||
z_arc_v2_aux_reg_read(_ARC_V2_ERET));
|
||||
LOG_PANIC();
|
||||
|
||||
switch (reason) {
|
||||
case _NANO_ERR_HW_EXCEPTION:
|
||||
break;
|
||||
|
||||
#if defined(CONFIG_STACK_CANARIES) || defined(CONFIG_ARC_STACK_CHECKING) \
|
||||
|| defined(CONFIG_STACK_SENTINEL) || defined(CONFIG_MPU_STACK_GUARD)
|
||||
case _NANO_ERR_STACK_CHK_FAIL:
|
||||
printk("***** Stack Check Fail! *****\n");
|
||||
break;
|
||||
#endif
|
||||
|
||||
case _NANO_ERR_ALLOCATION_FAIL:
|
||||
printk("**** Kernel Allocation Failure! ****\n");
|
||||
break;
|
||||
|
||||
case _NANO_ERR_KERNEL_OOPS:
|
||||
printk("***** Kernel OOPS! *****\n");
|
||||
break;
|
||||
|
||||
case _NANO_ERR_KERNEL_PANIC:
|
||||
printk("***** Kernel Panic! *****\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
printk("**** Unknown Fatal Error %d! ****\n", reason);
|
||||
break;
|
||||
}
|
||||
|
||||
z_fatal_error(reason, esf);
|
||||
printk("Current thread ID = %p\n", k_current_get());
|
||||
|
||||
if (reason == _NANO_ERR_HW_EXCEPTION) {
|
||||
printk("Faulting instruction address = 0x%lx\n",
|
||||
z_arc_v2_aux_reg_read(_ARC_V2_ERET));
|
||||
}
|
||||
|
||||
/*
|
||||
* Now that the error has been reported, call the user implemented
|
||||
* policy
|
||||
* to respond to the error. The decisions as to what responses are
|
||||
* appropriate to the various errors are something the customer must
|
||||
* decide.
|
||||
*/
|
||||
|
||||
z_SysFatalErrorHandler(reason, pEsf);
|
||||
}
|
||||
|
||||
FUNC_NORETURN void arch_syscall_oops(void *ssf_ptr)
|
||||
FUNC_NORETURN void z_arch_syscall_oops(void *ssf_ptr)
|
||||
{
|
||||
z_arc_fatal_error(K_ERR_KERNEL_OOPS, ssf_ptr);
|
||||
CODE_UNREACHABLE;
|
||||
}
|
||||
|
||||
FUNC_NORETURN void arch_system_halt(unsigned int reason)
|
||||
{
|
||||
ARG_UNUSED(reason);
|
||||
|
||||
__asm__("brk");
|
||||
|
||||
LOG_PANIC();
|
||||
z_SysFatalErrorHandler(_NANO_ERR_KERNEL_OOPS, ssf_ptr);
|
||||
CODE_UNREACHABLE;
|
||||
}
|
||||
|
||||
@@ -16,17 +16,18 @@
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <kernel.h>
|
||||
#include <kernel_internal.h>
|
||||
#include <kernel_structs.h>
|
||||
#include <misc/printk.h>
|
||||
#include <exc_handle.h>
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_DECLARE(os);
|
||||
#include <logging/log_ctrl.h>
|
||||
|
||||
u32_t arc_exc_saved_sp;
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
Z_EXC_DECLARE(z_arc_user_string_nlen);
|
||||
Z_EXC_DECLARE(z_arch_user_string_nlen);
|
||||
|
||||
static const struct z_exc_handle exceptions[] = {
|
||||
Z_EXC_HANDLE(z_arc_user_string_nlen)
|
||||
Z_EXC_HANDLE(z_arch_user_string_nlen)
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -122,253 +123,22 @@ static u32_t z_check_thread_stack_fail(const u32_t fault_addr, u32_t sp)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARC_EXCEPTION_DEBUG
|
||||
/* For EV_ProtV, the numbering/semantics of the parameter are consistent across
|
||||
* several codes, although not all combination will be reported.
|
||||
*
|
||||
* These codes and parameters do not have associated* names in
|
||||
* the technical manual, just switch on the values in Table 6-5
|
||||
*/
|
||||
static const char *get_protv_access_err(u32_t parameter)
|
||||
{
|
||||
switch (parameter) {
|
||||
case 0x1:
|
||||
return "code protection scheme";
|
||||
case 0x2:
|
||||
return "stack checking scheme";
|
||||
case 0x4:
|
||||
return "MPU";
|
||||
case 0x8:
|
||||
return "MMU";
|
||||
case 0x10:
|
||||
return "NVM";
|
||||
case 0x24:
|
||||
return "Secure MPU";
|
||||
case 0x44:
|
||||
return "Secure MPU with SID mismatch";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_protv_exception(u32_t cause, u32_t parameter)
|
||||
{
|
||||
switch (cause) {
|
||||
case 0x0:
|
||||
LOG_ERR("Instruction fetch violation (%s)",
|
||||
get_protv_access_err(parameter));
|
||||
break;
|
||||
case 0x1:
|
||||
LOG_ERR("Memory read protection violation (%s)",
|
||||
get_protv_access_err(parameter));
|
||||
break;
|
||||
case 0x2:
|
||||
LOG_ERR("Memory write protection violation (%s)",
|
||||
get_protv_access_err(parameter));
|
||||
break;
|
||||
case 0x3:
|
||||
LOG_ERR("Memory read-modify-write violation (%s)",
|
||||
get_protv_access_err(parameter));
|
||||
break;
|
||||
case 0x10:
|
||||
LOG_ERR("Normal vector table in secure memory");
|
||||
break;
|
||||
case 0x11:
|
||||
LOG_ERR("NS handler code located in S memory");
|
||||
break;
|
||||
case 0x12:
|
||||
LOG_ERR("NSC Table Range Violation");
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("unknown");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_machine_check_exception(u32_t cause, u32_t parameter)
|
||||
{
|
||||
switch (cause) {
|
||||
case 0x0:
|
||||
LOG_ERR("double fault");
|
||||
break;
|
||||
case 0x1:
|
||||
LOG_ERR("overlapping TLB entries");
|
||||
break;
|
||||
case 0x2:
|
||||
LOG_ERR("fatal TLB error");
|
||||
break;
|
||||
case 0x3:
|
||||
LOG_ERR("fatal cache error");
|
||||
break;
|
||||
case 0x4:
|
||||
LOG_ERR("internal memory error on instruction fetch");
|
||||
break;
|
||||
case 0x5:
|
||||
LOG_ERR("internal memory error on data fetch");
|
||||
break;
|
||||
case 0x6:
|
||||
LOG_ERR("illegal overlapping MPU entries");
|
||||
if (parameter == 0x1) {
|
||||
LOG_ERR(" - jump and branch target");
|
||||
}
|
||||
break;
|
||||
case 0x10:
|
||||
LOG_ERR("secure vector table not located in secure memory");
|
||||
break;
|
||||
case 0x11:
|
||||
LOG_ERR("NSC jump table not located in secure memory");
|
||||
break;
|
||||
case 0x12:
|
||||
LOG_ERR("secure handler code not located in secure memory");
|
||||
break;
|
||||
case 0x13:
|
||||
LOG_ERR("NSC target address not located in secure memory");
|
||||
break;
|
||||
case 0x80:
|
||||
LOG_ERR("uncorrectable ECC or parity error in vector memory");
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("unknown");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_privilege_exception(u32_t cause, u32_t parameter)
|
||||
{
|
||||
switch (cause) {
|
||||
case 0x0:
|
||||
LOG_ERR("Privilege violation");
|
||||
break;
|
||||
case 0x1:
|
||||
LOG_ERR("disabled extension");
|
||||
break;
|
||||
case 0x2:
|
||||
LOG_ERR("action point hit");
|
||||
break;
|
||||
case 0x10:
|
||||
switch (parameter) {
|
||||
case 0x1:
|
||||
LOG_ERR("N to S return using incorrect return mechanism");
|
||||
break;
|
||||
case 0x2:
|
||||
LOG_ERR("N to S return with incorrect operating mode");
|
||||
break;
|
||||
case 0x3:
|
||||
LOG_ERR("IRQ/exception return fetch from wrong mode");
|
||||
break;
|
||||
case 0x4:
|
||||
LOG_ERR("attempt to halt secure processor in NS mode");
|
||||
break;
|
||||
case 0x20:
|
||||
LOG_ERR("attempt to access secure resource from normal mode");
|
||||
break;
|
||||
case 0x40:
|
||||
LOG_ERR("SID violation on resource access (APEX/UAUX/key NVM)");
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("unknown");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x13:
|
||||
switch (parameter) {
|
||||
case 0x20:
|
||||
LOG_ERR("attempt to access secure APEX feature from NS mode");
|
||||
break;
|
||||
case 0x40:
|
||||
LOG_ERR("SID violation on access to APEX feature");
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("unknown");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("unknown");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_exception_info(u32_t vector, u32_t cause, u32_t parameter)
|
||||
{
|
||||
if (vector >= 0x10 && vector <= 0xFF) {
|
||||
LOG_ERR("interrupt %u", vector);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Names are exactly as they appear in Designware ARCv2 ISA
|
||||
* Programmer's reference manual for easy searching
|
||||
*/
|
||||
switch (vector) {
|
||||
case ARC_EV_RESET:
|
||||
LOG_ERR("Reset");
|
||||
break;
|
||||
case ARC_EV_MEM_ERROR:
|
||||
LOG_ERR("Memory Error");
|
||||
break;
|
||||
case ARC_EV_INS_ERROR:
|
||||
LOG_ERR("Instruction Error");
|
||||
break;
|
||||
case ARC_EV_MACHINE_CHECK:
|
||||
LOG_ERR("EV_MachineCheck");
|
||||
dump_machine_check_exception(cause, parameter);
|
||||
break;
|
||||
case ARC_EV_TLB_MISS_I:
|
||||
LOG_ERR("EV_TLBMissI");
|
||||
break;
|
||||
case ARC_EV_TLB_MISS_D:
|
||||
LOG_ERR("EV_TLBMissD");
|
||||
break;
|
||||
case ARC_EV_PROT_V:
|
||||
LOG_ERR("EV_ProtV");
|
||||
dump_protv_exception(cause, parameter);
|
||||
break;
|
||||
case ARC_EV_PRIVILEGE_V:
|
||||
LOG_ERR("EV_PrivilegeV");
|
||||
dump_privilege_exception(cause, parameter);
|
||||
break;
|
||||
case ARC_EV_SWI:
|
||||
LOG_ERR("EV_SWI");
|
||||
break;
|
||||
case ARC_EV_TRAP:
|
||||
LOG_ERR("EV_Trap");
|
||||
break;
|
||||
case ARC_EV_EXTENSION:
|
||||
LOG_ERR("EV_Extension");
|
||||
break;
|
||||
case ARC_EV_DIV_ZERO:
|
||||
LOG_ERR("EV_DivZero");
|
||||
break;
|
||||
case ARC_EV_DC_ERROR:
|
||||
LOG_ERR("EV_DCError");
|
||||
break;
|
||||
case ARC_EV_MISALIGNED:
|
||||
LOG_ERR("EV_Misaligned");
|
||||
break;
|
||||
case ARC_EV_VEC_UNIT:
|
||||
LOG_ERR("EV_VecUnit");
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("unknown");
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_ARC_EXCEPTION_DEBUG */
|
||||
|
||||
/*
|
||||
* @brief Fault handler
|
||||
*
|
||||
* This routine is called when fatal error conditions are detected by hardware
|
||||
* and is responsible only for reporting the error. Once reported, it then
|
||||
* invokes the user provided routine k_sys_fatal_error_handler() which is
|
||||
* invokes the user provided routine z_SysFatalErrorHandler() which is
|
||||
* responsible for implementing the error handling policy.
|
||||
*/
|
||||
void _Fault(z_arch_esf_t *esf, u32_t old_sp)
|
||||
void _Fault(NANO_ESF *esf)
|
||||
{
|
||||
u32_t vector, cause, parameter;
|
||||
u32_t vector, code, parameter;
|
||||
u32_t exc_addr = z_arc_v2_aux_reg_read(_ARC_V2_EFA);
|
||||
u32_t ecr = z_arc_v2_aux_reg_read(_ARC_V2_ECR);
|
||||
|
||||
LOG_PANIC();
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
for (int i = 0; i < ARRAY_SIZE(exceptions); i++) {
|
||||
u32_t start = (u32_t)exceptions[i].start;
|
||||
@@ -382,53 +152,38 @@ void _Fault(z_arch_esf_t *esf, u32_t old_sp)
|
||||
#endif
|
||||
|
||||
vector = Z_ARC_V2_ECR_VECTOR(ecr);
|
||||
cause = Z_ARC_V2_ECR_CODE(ecr);
|
||||
code = Z_ARC_V2_ECR_CODE(ecr);
|
||||
parameter = Z_ARC_V2_ECR_PARAMETER(ecr);
|
||||
|
||||
/* exception raised by kernel */
|
||||
if (vector == ARC_EV_TRAP && parameter == _TRAP_S_CALL_RUNTIME_EXCEPT) {
|
||||
/*
|
||||
* in user mode software-triggered system fatal exceptions only allow
|
||||
* K_ERR_KERNEL_OOPS and K_ERR_STACK_CHK_FAIL
|
||||
*/
|
||||
#ifdef CONFIG_USERSPACE
|
||||
if ((esf->status32 & _ARC_V2_STATUS32_U) &&
|
||||
esf->r0 != K_ERR_STACK_CHK_FAIL) {
|
||||
esf->r0 = K_ERR_KERNEL_OOPS;
|
||||
}
|
||||
#endif
|
||||
|
||||
z_arc_fatal_error(esf->r0, esf);
|
||||
/* exception raised by kernel */
|
||||
if (vector == 0x9 && parameter == _TRAP_S_CALL_RUNTIME_EXCEPT) {
|
||||
z_NanoFatalErrorHandler(esf->r0, esf);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_ERR("***** Exception vector: 0x%x, cause code: 0x%x, parameter 0x%x",
|
||||
vector, cause, parameter);
|
||||
LOG_ERR("Address 0x%x", exc_addr);
|
||||
#ifdef CONFIG_ARC_EXCEPTION_DEBUG
|
||||
dump_exception_info(vector, cause, parameter);
|
||||
#endif
|
||||
|
||||
printk("Exception vector: 0x%x, cause code: 0x%x, parameter 0x%x\n",
|
||||
vector, code, parameter);
|
||||
printk("Address 0x%x\n", exc_addr);
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
/* Vector 6 = EV_ProV. Regardless of cause, parameter 2 means stack
|
||||
/* Vector 6 = EV_ProV. Regardless of code, parameter 2 means stack
|
||||
* check violation
|
||||
* stack check and mpu violation can come out together, then
|
||||
* parameter = 0x2 | [0x4 | 0x8 | 0x1]
|
||||
*/
|
||||
if (vector == ARC_EV_PROT_V && parameter & 0x2) {
|
||||
z_arc_fatal_error(K_ERR_STACK_CHK_FAIL, esf);
|
||||
if (vector == 6U && parameter & 0x2) {
|
||||
z_NanoFatalErrorHandler(_NANO_ERR_STACK_CHK_FAIL, esf);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MPU_STACK_GUARD
|
||||
if (vector == ARC_EV_PROT_V && ((parameter == 0x4) ||
|
||||
(parameter == 0x24))) {
|
||||
if (z_check_thread_stack_fail(exc_addr, old_sp)) {
|
||||
z_arc_fatal_error(K_ERR_STACK_CHK_FAIL, esf);
|
||||
if (vector == 0x6 && ((parameter == 0x4) || (parameter == 0x24))) {
|
||||
if (z_check_thread_stack_fail(exc_addr, arc_exc_saved_sp)) {
|
||||
z_NanoFatalErrorHandler(_NANO_ERR_STACK_CHK_FAIL, esf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
z_arc_fatal_error(K_ERR_CPU_EXCEPTION, esf);
|
||||
z_NanoFatalErrorHandler(_NANO_ERR_HW_EXCEPTION, esf);
|
||||
}
|
||||
|
||||
@@ -38,17 +38,11 @@ GTEXT(__ev_maligned)
|
||||
GTEXT(z_irq_do_offload);
|
||||
#endif
|
||||
|
||||
GDATA(exc_nest_count)
|
||||
GDATA(arc_exc_saved_sWWp)
|
||||
|
||||
/*
|
||||
* The exception handling will use top part of interrupt stack to
|
||||
* get smaller memory footprint, because exception is not frequent.
|
||||
* To reduce the impact on interrupt handling, especially nested interrupt
|
||||
* the top part of interrupt stack cannot be too large, so add a check
|
||||
* here
|
||||
*/
|
||||
#if CONFIG_ARC_EXCEPTION_STACK_SIZE > (CONFIG_ISR_STACK_SIZE >> 1)
|
||||
#error "interrupt stack size is too small"
|
||||
#endif
|
||||
/* the necessary stack size for exception handling */
|
||||
#define EXCEPTION_STACK_SIZE 384
|
||||
|
||||
/*
|
||||
* @brief Fault handler installed in the fault and reserved vectors
|
||||
@@ -68,15 +62,15 @@ SECTION_SUBSEC_FUNC(TEXT,__fault,__ev_dc_error)
|
||||
SECTION_SUBSEC_FUNC(TEXT,__fault,__ev_maligned)
|
||||
|
||||
_exc_entry:
|
||||
st sp, [arc_exc_saved_sp]
|
||||
/*
|
||||
* re-use the top part of interrupt stack as exception
|
||||
* stack. If this top part is used by interrupt handling,
|
||||
* and exception is raised, then here it's guaranteed that
|
||||
* exception handling has necessary stack to use
|
||||
*/
|
||||
mov_s ilink, sp
|
||||
_get_curr_cpu_irq_stack sp
|
||||
sub sp, sp, (CONFIG_ISR_STACK_SIZE - CONFIG_ARC_EXCEPTION_STACK_SIZE)
|
||||
mov_s sp, _interrupt_stack
|
||||
add sp, sp, EXCEPTION_STACK_SIZE
|
||||
|
||||
/*
|
||||
* save caller saved registers
|
||||
@@ -90,7 +84,6 @@ _exc_entry:
|
||||
_create_irq_stack_frame
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
/* ERSEC_STAT is IOW/RAZ in normal mode */
|
||||
lr r0,[_ARC_V2_ERSEC_STAT]
|
||||
st_s r0, [sp, ___isf_t_sec_stat_OFFSET]
|
||||
#endif
|
||||
@@ -100,26 +93,12 @@ _exc_entry:
|
||||
st_s r0, [sp, ___isf_t_pc_OFFSET] /* eret into pc */
|
||||
|
||||
/* sp is parameter of _Fault */
|
||||
mov_s r0, sp
|
||||
/* ilink is the thread's original sp */
|
||||
mov_s r1, ilink
|
||||
mov r0, sp
|
||||
jl _Fault
|
||||
|
||||
_exc_return:
|
||||
/* the exception cause must be fixed in exception handler when exception returns
|
||||
* directly, or exception will be repeated.
|
||||
*
|
||||
* If thread switch is raised in exception handler, the context of old thread will
|
||||
* not be saved, i.e., it cannot be recovered, because we don't know where the
|
||||
* exception comes out, thread context?irq_context?nest irq context?
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_PREEMPT_ENABLED
|
||||
#ifdef CONFIG_SMP
|
||||
bl z_arc_smp_switch_in_isr
|
||||
breq r0, 0, _exc_return_from_exc
|
||||
mov_s r2, r0
|
||||
#else
|
||||
mov_s r1, _kernel
|
||||
ld_s r2, [r1, _kernel_offset_to_current]
|
||||
|
||||
@@ -129,9 +108,8 @@ _exc_return:
|
||||
|
||||
ld_s r2, [r1, _kernel_offset_to_ready_q_cache]
|
||||
st_s r2, [r1, _kernel_offset_to_current]
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
/*
|
||||
* sync up the ERSEC_STAT.ERM and SEC_STAT.IRM.
|
||||
* use a fake interrupt return to simulate an exception turn.
|
||||
@@ -140,50 +118,20 @@ _exc_return:
|
||||
*/
|
||||
lr r3,[_ARC_V2_ERSEC_STAT]
|
||||
btst r3, 31
|
||||
bset.nz r3, r3, _ARC_V2_SEC_STAT_IRM_BIT
|
||||
bclr.z r3, r3, _ARC_V2_SEC_STAT_IRM_BIT
|
||||
sflag r3
|
||||
#endif
|
||||
/* clear AE bit to forget this was an exception, and go to
|
||||
* register bank0 (if exception is raised in firq with 2 reg
|
||||
* banks, then we may be bank1)
|
||||
*/
|
||||
#if defined(CONFIG_ARC_FIRQ) && CONFIG_RGF_NUM_BANKS != 1
|
||||
/* save r2 in ilink because of the possible following reg
|
||||
* bank switch
|
||||
*/
|
||||
mov_s ilink, r2
|
||||
bset.nz r3, r3, 3
|
||||
bclr.z r3, r3, 3
|
||||
/* sflag r3 */
|
||||
/* sflag instruction is not supported in current ARC GNU */
|
||||
.long 0x00ff302f
|
||||
#endif
|
||||
/* clear AE bit to forget this was an exception */
|
||||
lr r3, [_ARC_V2_STATUS32]
|
||||
and r3,r3,(~(_ARC_V2_STATUS32_AE | _ARC_V2_STATUS32_RB(7)))
|
||||
and r3,r3,(~_ARC_V2_STATUS32_AE)
|
||||
kflag r3
|
||||
/* pretend lowest priority interrupt happened to use common handler
|
||||
* if exception is raised in irq, i.e., _ARC_V2_AUX_IRQ_ACT !=0,
|
||||
* ignore irq handling, we cannot return to irq handling which may
|
||||
* raise exception again. The ignored interrupts will be re-triggered
|
||||
* if not cleared, or re-triggered by interrupt sources, or just missed
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
mov_s r3, (1 << (ARC_N_IRQ_START_LEVEL - 1))
|
||||
#else
|
||||
mov_s r3, (1 << (CONFIG_NUM_IRQ_PRIO_LEVELS - 1))
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARC_NORMAL_FIRMWARE
|
||||
push_s r2
|
||||
mov_s r0, _ARC_V2_AUX_IRQ_ACT
|
||||
mov_s r1, r3
|
||||
mov_s r6, ARC_S_CALL_AUX_WRITE
|
||||
sjli SJLI_CALL_ARC_SECURE
|
||||
pop_s r2
|
||||
#else
|
||||
/* pretend lowest priority interrupt happened to use common handler */
|
||||
lr r3, [_ARC_V2_AUX_IRQ_ACT]
|
||||
or r3,r3,(1<<(CONFIG_NUM_IRQ_PRIO_LEVELS-1)) /* use lowest */
|
||||
sr r3, [_ARC_V2_AUX_IRQ_ACT]
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ARC_FIRQ) && CONFIG_RGF_NUM_BANKS != 1
|
||||
mov r2, ilink
|
||||
#endif
|
||||
|
||||
/* Assumption: r2 has current thread */
|
||||
b _rirq_common_interrupt_swap
|
||||
@@ -194,7 +142,7 @@ _exc_return_from_exc:
|
||||
sr r0, [_ARC_V2_ERET]
|
||||
|
||||
_pop_irq_stack_frame
|
||||
mov_s sp, ilink
|
||||
ld sp, [arc_exc_saved_sp]
|
||||
rtie
|
||||
|
||||
|
||||
@@ -205,36 +153,30 @@ SECTION_SUBSEC_FUNC(TEXT,__fault,__ev_trap)
|
||||
#ifdef CONFIG_USERSPACE
|
||||
cmp ilink, _TRAP_S_CALL_SYSTEM_CALL
|
||||
bne _do_non_syscall_trap
|
||||
/* do sys_call */
|
||||
mov_s ilink, K_SYSCALL_LIMIT
|
||||
/* do sys_call */
|
||||
mov ilink, K_SYSCALL_LIMIT
|
||||
cmp r6, ilink
|
||||
blt valid_syscall_id
|
||||
|
||||
mov_s r0, r6
|
||||
mov_s r6, K_SYSCALL_BAD
|
||||
mov r0, r6
|
||||
mov r6, K_SYSCALL_BAD
|
||||
|
||||
valid_syscall_id:
|
||||
/* create a sys call frame
|
||||
* caller regs (r0 - 12) are saved in _create_irq_stack_frame
|
||||
* ok to use them later
|
||||
*/
|
||||
_create_irq_stack_frame
|
||||
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
/* ERSEC_STAT is IOW/RAZ in normal mode */
|
||||
lr r0, [_ARC_V2_ERSEC_STAT]
|
||||
st_s r0, [sp, ___isf_t_sec_stat_OFFSET]
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
lr ilink, [_ARC_V2_ERSEC_STAT]
|
||||
push ilink
|
||||
#endif
|
||||
lr r0,[_ARC_V2_ERET]
|
||||
st_s r0, [sp, ___isf_t_pc_OFFSET] /* eret into pc */
|
||||
lr r0,[_ARC_V2_ERSTATUS]
|
||||
st_s r0, [sp, ___isf_t_status32_OFFSET]
|
||||
lr ilink, [_ARC_V2_ERET]
|
||||
push ilink
|
||||
lr ilink, [_ARC_V2_ERSTATUS]
|
||||
push ilink
|
||||
|
||||
bclr r0, r0, _ARC_V2_STATUS32_U_BIT
|
||||
sr r0, [_ARC_V2_ERSTATUS]
|
||||
|
||||
mov_s r0, _arc_do_syscall
|
||||
sr r0, [_ARC_V2_ERET]
|
||||
bclr ilink, ilink, _ARC_V2_STATUS32_U_BIT
|
||||
sr ilink, [_ARC_V2_ERSTATUS]
|
||||
|
||||
mov ilink, _arc_do_syscall
|
||||
sr ilink, [_ARC_V2_ERET]
|
||||
|
||||
rtie
|
||||
|
||||
@@ -260,14 +202,16 @@ _do_non_syscall_trap:
|
||||
lr r0,[_ARC_V2_ERET]
|
||||
st_s r0, [sp, ___isf_t_pc_OFFSET] /* eret into pc */
|
||||
|
||||
ld r1, [exc_nest_count]
|
||||
add r0, r1, 1
|
||||
st r0, [exc_nest_count]
|
||||
cmp r1, 0
|
||||
|
||||
/* check whether irq stack is used */
|
||||
_check_and_inc_int_nest_counter r0, r1
|
||||
bgt.d exc_nest_handle
|
||||
mov r0, sp
|
||||
|
||||
bne.d exc_nest_handle
|
||||
mov_s r0, sp
|
||||
|
||||
_get_curr_cpu_irq_stack sp
|
||||
mov r1, _kernel
|
||||
ld sp, [r1, _kernel_offset_to_irq_stack]
|
||||
exc_nest_handle:
|
||||
push_s r0
|
||||
|
||||
@@ -275,32 +219,30 @@ exc_nest_handle:
|
||||
|
||||
pop sp
|
||||
|
||||
_dec_int_nest_counter r0, r1
|
||||
|
||||
lr r0, [_ARC_V2_AUX_IRQ_ACT]
|
||||
and r0, r0, 0xffff
|
||||
cmp r0, 0
|
||||
bne _exc_return_from_exc
|
||||
mov r1, exc_nest_count
|
||||
ld r0, [r1]
|
||||
sub r0, r0, 1
|
||||
cmp r0, 0
|
||||
bne.d _exc_return_from_exc
|
||||
st r0, [r1]
|
||||
|
||||
#ifdef CONFIG_PREEMPT_ENABLED
|
||||
#ifdef CONFIG_SMP
|
||||
bl z_arc_smp_switch_in_isr
|
||||
breq r0, 0, _exc_return_from_irqoffload_trap
|
||||
mov_s r2, r1
|
||||
|
||||
_save_callee_saved_regs
|
||||
|
||||
st _CAUSE_RIRQ, [r2, _thread_offset_to_relinquish_cause]
|
||||
mov_s r2, r0
|
||||
#else
|
||||
mov_s r1, _kernel
|
||||
ld_s r2, [r1, _kernel_offset_to_current]
|
||||
|
||||
/* check if the current thread needs to be rescheduled */
|
||||
ld_s r0, [r1, _kernel_offset_to_ready_q_cache]
|
||||
breq r0, r2, _exc_return_from_irqoffload_trap
|
||||
#endif
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
|
||||
_save_callee_saved_regs
|
||||
|
||||
st _CAUSE_RIRQ, [r2, _thread_offset_to_relinquish_cause]
|
||||
/* note: Ok to use _CAUSE_RIRQ since everything is saved */
|
||||
|
||||
ld_s r2, [r1, _kernel_offset_to_ready_q_cache]
|
||||
st_s r2, [r1, _kernel_offset_to_current]
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
/*
|
||||
* sync up the ERSEC_STAT.ERM and SEC_STAT.IRM.
|
||||
* use a fake interrupt return to simulate an exception turn.
|
||||
@@ -309,22 +251,11 @@ exc_nest_handle:
|
||||
*/
|
||||
lr r3,[_ARC_V2_ERSEC_STAT]
|
||||
btst r3, 31
|
||||
bset.nz r3, r3, _ARC_V2_SEC_STAT_IRM_BIT
|
||||
bclr.z r3, r3, _ARC_V2_SEC_STAT_IRM_BIT
|
||||
sflag r3
|
||||
/* save _ARC_V2_SEC_STAT */
|
||||
and r3, r3, 0xff
|
||||
push_s r3
|
||||
#endif
|
||||
|
||||
_save_callee_saved_regs
|
||||
|
||||
st _CAUSE_RIRQ, [r2, _thread_offset_to_relinquish_cause]
|
||||
/* note: Ok to use _CAUSE_RIRQ since everything is saved */
|
||||
|
||||
mov_s r2, r0
|
||||
#ifndef CONFIG_SMP
|
||||
st_s r2, [r1, _kernel_offset_to_current]
|
||||
bset.nz r3, r3, 3
|
||||
bclr.z r3, r3, 3
|
||||
/* sflag r3 */
|
||||
/* sflag instruction is not supported in current ARC GNU */
|
||||
.long 0x00ff302f
|
||||
#endif
|
||||
/* clear AE bit to forget this was an exception */
|
||||
lr r3, [_ARC_V2_STATUS32]
|
||||
@@ -332,23 +263,9 @@ exc_nest_handle:
|
||||
kflag r3
|
||||
/* pretend lowest priority interrupt happened to use common handler */
|
||||
lr r3, [_ARC_V2_AUX_IRQ_ACT]
|
||||
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
or r3, r3, (1 << (ARC_N_IRQ_START_LEVEL - 1))
|
||||
#else
|
||||
or r3, r3, (1 << (CONFIG_NUM_IRQ_PRIO_LEVELS - 1))
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARC_NORMAL_FIRMWARE
|
||||
push_s r2
|
||||
mov_s r0, _ARC_V2_AUX_IRQ_ACT
|
||||
mov_s r1, r3
|
||||
mov_s r6, ARC_S_CALL_AUX_WRITE
|
||||
sjli SJLI_CALL_ARC_SECURE
|
||||
pop_s r2
|
||||
#else
|
||||
or r3,r3,(1<<(CONFIG_NUM_IRQ_PRIO_LEVELS-1)) /* use lowest */
|
||||
sr r3, [_ARC_V2_AUX_IRQ_ACT]
|
||||
#endif
|
||||
|
||||
/* Assumption: r2 has current thread */
|
||||
b _rirq_common_interrupt_swap
|
||||
#endif
|
||||
|
||||
@@ -19,69 +19,12 @@
|
||||
|
||||
#include <kernel.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <sys/__assert.h>
|
||||
#include <misc/__assert.h>
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <sw_isr_table.h>
|
||||
#include <irq.h>
|
||||
#include <sys/printk.h>
|
||||
|
||||
|
||||
/*
|
||||
* storage space for the interrupt stack of fast_irq
|
||||
*/
|
||||
#if defined(CONFIG_ARC_FIRQ_STACK)
|
||||
#if defined(CONFIG_SMP)
|
||||
K_THREAD_STACK_ARRAY_DEFINE(_firq_interrupt_stack, CONFIG_MP_NUM_CPUS,
|
||||
CONFIG_ARC_FIRQ_STACK_SIZE);
|
||||
#else
|
||||
K_THREAD_STACK_DEFINE(_firq_interrupt_stack, CONFIG_ARC_FIRQ_STACK_SIZE);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* @brief Set the stack pointer for firq handling
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
void z_arc_firq_stack_set(void)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
char *firq_sp = Z_THREAD_STACK_BUFFER(
|
||||
_firq_interrupt_stack[z_arc_v2_core_id()]) +
|
||||
CONFIG_ARC_FIRQ_STACK_SIZE;
|
||||
#else
|
||||
char *firq_sp = Z_THREAD_STACK_BUFFER(_firq_interrupt_stack) +
|
||||
CONFIG_ARC_FIRQ_STACK_SIZE;
|
||||
#endif
|
||||
|
||||
/* the z_arc_firq_stack_set must be called when irq diasbled, as
|
||||
* it can be called not only in the init phase but also other places
|
||||
*/
|
||||
unsigned int key = irq_lock();
|
||||
|
||||
__asm__ volatile (
|
||||
/* only ilink will not be banked, so use ilink as channel
|
||||
* between 2 banks
|
||||
*/
|
||||
"mov ilink, %0 \n\t"
|
||||
"lr %0, [%1] \n\t"
|
||||
"or %0, %0, %2 \n\t"
|
||||
"kflag %0 \n\t"
|
||||
"mov sp, ilink \n\t"
|
||||
/* switch back to bank0, use ilink to avoid the pollution of
|
||||
* bank1's gp regs.
|
||||
*/
|
||||
"lr ilink, [%1] \n\t"
|
||||
"and ilink, ilink, %3 \n\t"
|
||||
"kflag ilink \n\t"
|
||||
:
|
||||
: "r"(firq_sp), "i"(_ARC_V2_STATUS32),
|
||||
"i"(_ARC_V2_STATUS32_RB(1)),
|
||||
"i"(~_ARC_V2_STATUS32_RB(7))
|
||||
);
|
||||
irq_unlock(key);
|
||||
}
|
||||
#endif
|
||||
#include <misc/printk.h>
|
||||
|
||||
/*
|
||||
* @brief Enable an interrupt line
|
||||
@@ -93,7 +36,7 @@ void z_arc_firq_stack_set(void)
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void arch_irq_enable(unsigned int irq)
|
||||
void z_arch_irq_enable(unsigned int irq)
|
||||
{
|
||||
unsigned int key = irq_lock();
|
||||
|
||||
@@ -110,7 +53,7 @@ void arch_irq_enable(unsigned int irq)
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void arch_irq_disable(unsigned int irq)
|
||||
void z_arch_irq_disable(unsigned int irq)
|
||||
{
|
||||
unsigned int key = irq_lock();
|
||||
|
||||
@@ -118,17 +61,6 @@ void arch_irq_disable(unsigned int irq)
|
||||
irq_unlock(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return IRQ enable state
|
||||
*
|
||||
* @param irq IRQ line
|
||||
* @return interrupt enable state, true or false
|
||||
*/
|
||||
int arch_irq_is_enabled(unsigned int irq)
|
||||
{
|
||||
return z_arc_v2_irq_unit_int_enabled(irq);
|
||||
}
|
||||
|
||||
/*
|
||||
* @internal
|
||||
*
|
||||
@@ -151,16 +83,6 @@ void z_irq_priority_set(unsigned int irq, unsigned int prio, u32_t flags)
|
||||
|
||||
__ASSERT(prio < CONFIG_NUM_IRQ_PRIO_LEVELS,
|
||||
"invalid priority %d for irq %d", prio, irq);
|
||||
/* 0 -> CONFIG_NUM_IRQ_PRIO_LEVELS allocted to secure world
|
||||
* left prio levels allocated to normal world
|
||||
*/
|
||||
#if defined(CONFIG_ARC_SECURE_FIRMWARE)
|
||||
prio = prio < ARC_N_IRQ_START_LEVEL ?
|
||||
prio : (ARC_N_IRQ_START_LEVEL - 1);
|
||||
#elif defined(CONFIG_ARC_NORMAL_FIRMWARE)
|
||||
prio = prio < ARC_N_IRQ_START_LEVEL ?
|
||||
ARC_N_IRQ_START_LEVEL : prio;
|
||||
#endif
|
||||
z_arc_v2_irq_unit_prio_set(irq, prio);
|
||||
irq_unlock(key);
|
||||
}
|
||||
@@ -177,13 +99,16 @@ void z_irq_priority_set(unsigned int irq, unsigned int prio, u32_t flags)
|
||||
void z_irq_spurious(void *unused)
|
||||
{
|
||||
ARG_UNUSED(unused);
|
||||
z_fatal_error(K_ERR_SPURIOUS_IRQ, NULL);
|
||||
printk("z_irq_spurious(). Spinning...\n");
|
||||
for (;;) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DYNAMIC_INTERRUPTS
|
||||
int arch_irq_connect_dynamic(unsigned int irq, unsigned int priority,
|
||||
void (*routine)(void *parameter), void *parameter,
|
||||
u32_t flags)
|
||||
int z_arch_irq_connect_dynamic(unsigned int irq, unsigned int priority,
|
||||
void (*routine)(void *parameter), void *parameter,
|
||||
u32_t flags)
|
||||
{
|
||||
z_isr_install(irq, routine, parameter);
|
||||
z_irq_priority_set(irq, priority, flags);
|
||||
|
||||
@@ -20,7 +20,7 @@ void z_irq_do_offload(void)
|
||||
offload_routine(offload_param);
|
||||
}
|
||||
|
||||
void arch_irq_offload(irq_offload_routine_t routine, void *parameter)
|
||||
void irq_offload(irq_offload_routine_t routine, void *parameter)
|
||||
{
|
||||
unsigned int key;
|
||||
|
||||
|
||||
@@ -24,6 +24,26 @@
|
||||
GTEXT(_isr_wrapper)
|
||||
GTEXT(_isr_demux)
|
||||
|
||||
GDATA(exc_nest_count)
|
||||
SECTION_VAR(BSS, exc_nest_count)
|
||||
.balign 4
|
||||
.word 0
|
||||
|
||||
|
||||
#if CONFIG_RGF_NUM_BANKS == 1
|
||||
GDATA(saved_r0)
|
||||
|
||||
SECTION_VAR(BSS, saved_r0)
|
||||
.balign 4
|
||||
.word 0
|
||||
#else
|
||||
GDATA(saved_sp)
|
||||
|
||||
SECTION_VAR(BSS, saved_sp)
|
||||
.balign 4
|
||||
.word 0
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SYS_POWER_MANAGEMENT)
|
||||
GTEXT(z_sys_power_save_idle_exit)
|
||||
#endif
|
||||
@@ -42,7 +62,7 @@ Context switch explanation:
|
||||
|
||||
The context switch code is spread in these files:
|
||||
|
||||
isr_wrapper.s, switch.s, swap_macros.s, fast_irq.s, regular_irq.s
|
||||
isr_wrapper.s, swap.s, swap_macros.s, fast_irq.s, regular_irq.s
|
||||
|
||||
IRQ stack frame layout:
|
||||
|
||||
@@ -60,6 +80,13 @@ IRQ stack frame layout:
|
||||
|
||||
low address
|
||||
|
||||
Registers not taken into account in the current implementation.
|
||||
jli_base
|
||||
ldi_base
|
||||
ei_base
|
||||
accl
|
||||
acch
|
||||
|
||||
The context switch code adopts this standard so that it is easier to follow:
|
||||
|
||||
- r1 contains _kernel ASAP and is not overwritten over the lifespan of
|
||||
@@ -68,7 +95,7 @@ The context switch code adopts this standard so that it is easier to follow:
|
||||
transition from outgoing thread to incoming thread
|
||||
|
||||
Not loading _kernel into r0 allows loading _kernel without stomping on
|
||||
the parameter in r0 in arch_switch().
|
||||
the parameter in r0 in z_swap().
|
||||
|
||||
|
||||
ARCv2 processors have two kinds of interrupts: fast (FIRQ) and regular. The
|
||||
@@ -100,7 +127,7 @@ done upfront, and the rest is done when needed:
|
||||
|
||||
o RIRQ
|
||||
|
||||
All needed registers to run C code in the ISR are saved automatically
|
||||
All needed regisers to run C code in the ISR are saved automatically
|
||||
on the outgoing thread's stack: loop, status32, pc, and the caller-
|
||||
saved GPRs. That stack frame layout is pre-determined. If returning
|
||||
to a thread, the stack is popped and no registers have to be saved by
|
||||
@@ -150,7 +177,7 @@ From coop:
|
||||
|
||||
o to coop
|
||||
|
||||
Do a normal function call return.
|
||||
Restore interrupt lock level and do a normal function call return.
|
||||
|
||||
o to any irq
|
||||
|
||||
@@ -168,13 +195,14 @@ From FIRQ:
|
||||
|
||||
o to coop
|
||||
|
||||
The address of the returning instruction from arch_switch() is loaded
|
||||
in ilink and the saved status32 in status32_p0.
|
||||
The address of the returning instruction from z_swap() is loaded in ilink and
|
||||
the saved status32 in status32_p0, taking care to adjust the interrupt lock
|
||||
state desired in status32_p0. The return value is put in r0.
|
||||
|
||||
o to any irq
|
||||
|
||||
The IRQ has saved the caller-saved registers in a stack frame, which must be
|
||||
popped, and status32 and pc loaded in status32_p0 and ilink.
|
||||
popped, and statu32 and pc loaded in status32_p0 and ilink.
|
||||
|
||||
From RIRQ:
|
||||
|
||||
@@ -182,7 +210,7 @@ From RIRQ:
|
||||
|
||||
The interrupt return mechanism in the processor expects a stack frame, but
|
||||
the outgoing context did not create one. A fake one is created here, with
|
||||
only the relevant values filled in: pc, status32.
|
||||
only the relevant values filled in: pc, status32 and the return value in r0.
|
||||
|
||||
There is a discrepancy between the ABI from the ARCv2 docs, including the
|
||||
way the processor pushes GPRs in pairs in the IRQ stack frame, and the ABI
|
||||
@@ -202,34 +230,56 @@ From RIRQ:
|
||||
*/
|
||||
|
||||
SECTION_FUNC(TEXT, _isr_wrapper)
|
||||
#if defined(CONFIG_ARC_FIRQ)
|
||||
#if CONFIG_ARC_FIRQ
|
||||
#if CONFIG_RGF_NUM_BANKS == 1
|
||||
/* free r0 here, use r0 to check whether irq is firq.
|
||||
* for rirq, as sp will not change and r0 already saved, this action
|
||||
* in fact is an action like nop.
|
||||
* for firq, r0 will be restored later
|
||||
*/
|
||||
st_s r0, [sp]
|
||||
st r0,[saved_r0]
|
||||
#endif
|
||||
lr r0, [_ARC_V2_AUX_IRQ_ACT]
|
||||
ffs r0, r0
|
||||
cmp r0, 0
|
||||
#if CONFIG_RGF_NUM_BANKS == 1
|
||||
bnz rirq_path
|
||||
ld_s r0, [sp]
|
||||
/* 1-register bank FIRQ handling must save registers on stack */
|
||||
_create_irq_stack_frame
|
||||
lr r0, [_ARC_V2_STATUS32_P0]
|
||||
st_s r0, [sp, ___isf_t_status32_OFFSET]
|
||||
lr r0, [_ARC_V2_ERET]
|
||||
st_s r0, [sp, ___isf_t_pc_OFFSET]
|
||||
|
||||
mov_s r3, _firq_exit
|
||||
mov_s r2, _firq_enter
|
||||
lr r0,[_ARC_V2_STATUS32_P0]
|
||||
push_s r0
|
||||
mov r0,ilink
|
||||
push_s r0
|
||||
#ifdef CONFIG_CODE_DENSITY
|
||||
lr r0, [_ARC_V2_JLI_BASE]
|
||||
push_s r0
|
||||
lr r0, [_ARC_V2_LDI_BASE]
|
||||
push_s r0
|
||||
lr r0, [_ARC_V2_EI_BASE]
|
||||
push_s r0
|
||||
#endif
|
||||
mov r0,lp_count
|
||||
push_s r0
|
||||
lr r0, [_ARC_V2_LP_START]
|
||||
push_s r0
|
||||
lr r0, [_ARC_V2_LP_END]
|
||||
push_s r0
|
||||
push_s blink
|
||||
push_s r13
|
||||
push_s r12
|
||||
push r11
|
||||
push r10
|
||||
push r9
|
||||
push r8
|
||||
push r7
|
||||
push r6
|
||||
push r5
|
||||
push r4
|
||||
push_s r3
|
||||
push_s r2
|
||||
push_s r1
|
||||
ld r0,[saved_r0]
|
||||
push_s r0
|
||||
mov r3, _firq_exit
|
||||
mov r2, _firq_enter
|
||||
j_s [r2]
|
||||
rirq_path:
|
||||
mov_s r3, _rirq_exit
|
||||
mov_s r2, _rirq_enter
|
||||
mov r3, _rirq_exit
|
||||
mov r2, _rirq_enter
|
||||
j_s [r2]
|
||||
#else
|
||||
mov.z r3, _firq_exit
|
||||
@@ -239,19 +289,19 @@ rirq_path:
|
||||
j_s [r2]
|
||||
#endif
|
||||
#else
|
||||
mov_s r3, _rirq_exit
|
||||
mov_s r2, _rirq_enter
|
||||
mov r3, _rirq_exit
|
||||
mov r2, _rirq_enter
|
||||
j_s [r2]
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_TRACING)
|
||||
GTEXT(sys_trace_isr_enter)
|
||||
GTEXT(z_sys_trace_isr_enter)
|
||||
|
||||
.macro log_interrupt_k_event
|
||||
clri r0 /* do not interrupt event logger operations */
|
||||
push_s r0
|
||||
push_s blink
|
||||
jl sys_trace_isr_enter
|
||||
jl z_sys_trace_isr_enter
|
||||
pop_s blink
|
||||
pop_s r0
|
||||
seti r0
|
||||
@@ -287,16 +337,6 @@ _skip_sys_power_save_idle_exit:
|
||||
SECTION_FUNC(TEXT, _isr_demux)
|
||||
push_s r3
|
||||
|
||||
/* according to ARCv2 ISA, r25, r30, r58, r59 are caller-saved
|
||||
* scratch registers, possibly used by interrupt handlers
|
||||
*/
|
||||
push r25
|
||||
push r30
|
||||
#ifdef CONFIG_ARC_HAS_ACCL_REGS
|
||||
push r58
|
||||
push r59
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXECUTION_BENCHMARKING
|
||||
bl read_timer_start_of_isr
|
||||
#endif
|
||||
@@ -314,7 +354,7 @@ irq_hint_handled:
|
||||
|
||||
sub r0, r0, 16
|
||||
|
||||
mov_s r1, _sw_isr_table
|
||||
mov r1, _sw_isr_table
|
||||
add3 r0, r1, r0 /* table entries are 8-bytes wide */
|
||||
|
||||
ld_s r1, [r0, 4] /* ISR into r1 */
|
||||
@@ -328,15 +368,7 @@ irq_hint_handled:
|
||||
jl_s.d [r1]
|
||||
ld_s r0, [r0] /* delay slot: ISR parameter into r0 */
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_ACCL_REGS
|
||||
pop r59
|
||||
pop r58
|
||||
#endif
|
||||
|
||||
pop r30
|
||||
pop r25
|
||||
|
||||
/* back from ISR, jump to exit stub */
|
||||
pop_s r3
|
||||
j_s [r3]
|
||||
nop_s
|
||||
nop
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# Memory Protection Unit (MPU) configuration options
|
||||
# Kconfig - Memory Protection Unit (MPU) configuration options
|
||||
|
||||
#
|
||||
# Copyright (c) 2017 Synopsys
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#
|
||||
config ARC_MPU_VER
|
||||
int "ARC MPU version"
|
||||
range 2 4
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include <kernel.h>
|
||||
#include <soc.h>
|
||||
#include <arch/arc/v2/mpu/arc_core_mpu.h>
|
||||
#include <kernel_structs.h>
|
||||
|
||||
/*
|
||||
* @brief Configure MPU for the thread
|
||||
@@ -27,7 +26,7 @@ void configure_mpu_thread(struct k_thread *thread)
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
|
||||
int arch_mem_domain_max_partitions_get(void)
|
||||
int z_arch_mem_domain_max_partitions_get(void)
|
||||
{
|
||||
return arc_core_mpu_get_max_domain_partition_regions();
|
||||
}
|
||||
@@ -35,13 +34,9 @@ int arch_mem_domain_max_partitions_get(void)
|
||||
/*
|
||||
* Reset MPU region for a single memory partition
|
||||
*/
|
||||
void arch_mem_domain_partition_remove(struct k_mem_domain *domain,
|
||||
u32_t partition_id)
|
||||
void z_arch_mem_domain_partition_remove(struct k_mem_domain *domain,
|
||||
u32_t partition_id)
|
||||
{
|
||||
if (_current->mem_domain_info.mem_domain != domain) {
|
||||
return;
|
||||
}
|
||||
|
||||
arc_core_mpu_disable();
|
||||
arc_core_mpu_remove_mem_partition(domain, partition_id);
|
||||
arc_core_mpu_enable();
|
||||
@@ -50,12 +45,8 @@ void arch_mem_domain_partition_remove(struct k_mem_domain *domain,
|
||||
/*
|
||||
* Configure MPU memory domain
|
||||
*/
|
||||
void arch_mem_domain_thread_add(struct k_thread *thread)
|
||||
void z_arch_mem_domain_configure(struct k_thread *thread)
|
||||
{
|
||||
if (_current != thread) {
|
||||
return;
|
||||
}
|
||||
|
||||
arc_core_mpu_disable();
|
||||
arc_core_mpu_configure_mem_domain(thread);
|
||||
arc_core_mpu_enable();
|
||||
@@ -64,36 +55,23 @@ void arch_mem_domain_thread_add(struct k_thread *thread)
|
||||
/*
|
||||
* Destroy MPU regions for the mem domain
|
||||
*/
|
||||
void arch_mem_domain_destroy(struct k_mem_domain *domain)
|
||||
void z_arch_mem_domain_destroy(struct k_mem_domain *domain)
|
||||
{
|
||||
if (_current->mem_domain_info.mem_domain != domain) {
|
||||
return;
|
||||
}
|
||||
|
||||
arc_core_mpu_disable();
|
||||
arc_core_mpu_remove_mem_domain(domain);
|
||||
arc_core_mpu_enable();
|
||||
}
|
||||
|
||||
void arch_mem_domain_partition_add(struct k_mem_domain *domain,
|
||||
u32_t partition_id)
|
||||
void _arch_mem_domain_partition_add(struct k_mem_domain *domain,
|
||||
u32_t partition_id)
|
||||
{
|
||||
/* No-op on this architecture */
|
||||
}
|
||||
|
||||
void arch_mem_domain_thread_remove(struct k_thread *thread)
|
||||
{
|
||||
if (_current != thread) {
|
||||
return;
|
||||
}
|
||||
|
||||
arch_mem_domain_destroy(thread->mem_domain_info.mem_domain);
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate the given buffer is user accessible or not
|
||||
*/
|
||||
int arch_buffer_validate(void *addr, size_t size, int write)
|
||||
int z_arch_buffer_validate(void *addr, size_t size, int write)
|
||||
{
|
||||
return arc_core_mpu_buffer_validate(addr, size, write);
|
||||
}
|
||||
|
||||
@@ -325,7 +325,7 @@ void arc_core_mpu_configure_mem_domain(struct k_thread *thread)
|
||||
|
||||
for (; region_index >= 0; region_index--) {
|
||||
if (num_partitions) {
|
||||
LOG_DBG("set region 0x%x 0x%lx 0x%x",
|
||||
LOG_DBG("set region 0x%x 0x%x 0x%x",
|
||||
region_index, pparts->start, pparts->size);
|
||||
_region_init(region_index, pparts->start,
|
||||
pparts->size, pparts->attr);
|
||||
|
||||
@@ -62,68 +62,6 @@ static u8_t dynamic_region_index;
|
||||
*/
|
||||
static struct dynamic_region_info dyn_reg_info[MPU_DYNAMIC_REGION_AREAS_NUM];
|
||||
|
||||
#ifdef CONFIG_ARC_NORMAL_FIRMWARE
|
||||
/* \todo through secure service to access mpu */
|
||||
static inline void _region_init(u32_t index, u32_t region_addr, u32_t size,
|
||||
u32_t region_attr)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void _region_set_attr(u32_t index, u32_t attr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static inline u32_t _region_get_attr(u32_t index)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline u32_t _region_get_start(u32_t index)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void _region_set_start(u32_t index, u32_t start)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static inline u32_t _region_get_end(u32_t index)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void _region_set_end(u32_t index, u32_t end)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function probes the given addr's MPU index.if not
|
||||
* in MPU, returns error
|
||||
*/
|
||||
static inline int _mpu_probe(u32_t addr)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function checks if MPU region is enabled or not
|
||||
*/
|
||||
static inline bool _is_enabled_region(u32_t r_index)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function check if the region is user accessible or not
|
||||
*/
|
||||
static inline bool _is_user_accessible_region(u32_t r_index, int write)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#else /* CONFIG_ARC_NORMAL_FIRMWARE */
|
||||
/* the following functions are prepared for SECURE_FRIMWARE */
|
||||
static inline void _region_init(u32_t index, u32_t region_addr, u32_t size,
|
||||
u32_t region_attr)
|
||||
{
|
||||
@@ -139,7 +77,7 @@ static inline void _region_init(u32_t index, u32_t region_addr, u32_t size,
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_INDEX, index);
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_RSTART, region_addr);
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_REND,
|
||||
CALC_REGION_END_ADDR(region_addr, size));
|
||||
CALC_REGION_END_ADDR(region_addr, size));
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_RPER, region_attr);
|
||||
}
|
||||
|
||||
@@ -204,6 +142,20 @@ static inline int _mpu_probe(u32_t addr)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function allocates a dynamic MPU region and returns
|
||||
* the index or error
|
||||
*/
|
||||
static inline int _dynamic_region_allocate_index(void)
|
||||
{
|
||||
if (dynamic_region_index >= get_num_regions()) {
|
||||
LOG_ERR("no enough mpu entries %d", dynamic_region_index);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return dynamic_region_index++;
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function checks if MPU region is enabled or not
|
||||
*/
|
||||
@@ -214,6 +166,21 @@ static inline bool _is_enabled_region(u32_t r_index)
|
||||
AUX_MPU_RPER_VALID_MASK) == AUX_MPU_RPER_VALID_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function checks the area given by (start, size)
|
||||
* and returns the index if the area match one MPU entry
|
||||
*/
|
||||
static inline int _get_region_index(u32_t start, u32_t size)
|
||||
{
|
||||
int index = _mpu_probe(start);
|
||||
|
||||
if (index > 0 && index == _mpu_probe(start + size - 1)) {
|
||||
return index;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function check if the region is user accessible or not
|
||||
*/
|
||||
@@ -234,37 +201,6 @@ static inline bool _is_user_accessible_region(u32_t r_index, int write)
|
||||
(AUX_MPU_ATTR_UR | AUX_MPU_ATTR_KR));
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARC_NORMAL_FIRMWARE */
|
||||
|
||||
/**
|
||||
* This internal function allocates a dynamic MPU region and returns
|
||||
* the index or error
|
||||
*/
|
||||
static inline int _dynamic_region_allocate_index(void)
|
||||
{
|
||||
if (dynamic_region_index >= get_num_regions()) {
|
||||
LOG_ERR("no enough mpu entries %d", dynamic_region_index);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return dynamic_region_index++;
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function checks the area given by (start, size)
|
||||
* and returns the index if the area match one MPU entry
|
||||
*/
|
||||
static inline int _get_region_index(u32_t start, u32_t size)
|
||||
{
|
||||
int index = _mpu_probe(start);
|
||||
|
||||
if (index > 0 && index == _mpu_probe(start + size - 1)) {
|
||||
return index;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* @brief allocate and init a dynamic MPU region
|
||||
*
|
||||
* This internal function performs the allocation and initialization of
|
||||
@@ -417,14 +353,7 @@ static inline int _mpu_configure(u8_t type, u32_t base, u32_t size)
|
||||
*/
|
||||
void arc_core_mpu_enable(void)
|
||||
{
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
/* the default region:
|
||||
* normal:0x000, SID:0x10000, KW:0x100 KR:0x80, KE:0x4 0
|
||||
*/
|
||||
#define MPU_ENABLE_ATTR 0x101c0
|
||||
#else
|
||||
#define MPU_ENABLE_ATTR 0
|
||||
#endif
|
||||
#define MPU_ENABLE_ATTR 0
|
||||
arc_core_mpu_default(MPU_ENABLE_ATTR);
|
||||
}
|
||||
|
||||
@@ -436,8 +365,7 @@ void arc_core_mpu_disable(void)
|
||||
/* MPU is always enabled, use default region to
|
||||
* simulate MPU disable
|
||||
*/
|
||||
arc_core_mpu_default(REGION_ALL_ATTR | AUX_MPU_ATTR_S |
|
||||
AUX_MPU_RPER_SID1);
|
||||
arc_core_mpu_default(REGION_ALL_ATTR);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -546,11 +474,12 @@ void arc_core_mpu_configure_thread(struct k_thread *thread)
|
||||
*/
|
||||
void arc_core_mpu_default(u32_t region_attr)
|
||||
{
|
||||
#ifdef CONFIG_ARC_NORMAL_FIRMWARE
|
||||
/* \todo through secure service to access mpu */
|
||||
#else
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_EN, region_attr);
|
||||
#endif
|
||||
u32_t val = z_arc_v2_aux_reg_read(_ARC_V2_MPU_EN) &
|
||||
(~AUX_MPU_RPER_ATTR_MASK);
|
||||
|
||||
region_attr &= AUX_MPU_RPER_ATTR_MASK;
|
||||
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_EN, region_attr | val);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -711,9 +640,9 @@ static int arc_mpu_init(struct device *arg)
|
||||
|
||||
/* record the static region which can be split */
|
||||
if (mpu_config.mpu_regions[i].attr & REGION_DYNAMIC) {
|
||||
if (dynamic_regions_num >=
|
||||
if (dynamic_regions_num >
|
||||
MPU_DYNAMIC_REGION_AREAS_NUM) {
|
||||
LOG_ERR("not enough dynamic regions %d",
|
||||
LOG_ERR("no enough dynamic regions %d",
|
||||
dynamic_regions_num);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -22,12 +22,13 @@
|
||||
* completeness.
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <kernel_arch_data.h>
|
||||
#include <gen_offset.h>
|
||||
#include <kernel_structs.h>
|
||||
#include <kernel_offsets.h>
|
||||
|
||||
GEN_OFFSET_SYM(_thread_arch_t, intlock_key);
|
||||
GEN_OFFSET_SYM(_thread_arch_t, relinquish_cause);
|
||||
GEN_OFFSET_SYM(_thread_arch_t, return_value);
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
GEN_OFFSET_SYM(_thread_arch_t, k_stack_base);
|
||||
GEN_OFFSET_SYM(_thread_arch_t, k_stack_top);
|
||||
@@ -95,11 +96,9 @@ GEN_OFFSET_SYM(_callee_saved_stack_t, user_sp);
|
||||
#endif
|
||||
#endif
|
||||
GEN_OFFSET_SYM(_callee_saved_stack_t, r30);
|
||||
#ifdef CONFIG_ARC_HAS_ACCL_REGS
|
||||
#ifdef CONFIG_FP_SHARING
|
||||
GEN_OFFSET_SYM(_callee_saved_stack_t, r58);
|
||||
GEN_OFFSET_SYM(_callee_saved_stack_t, r59);
|
||||
#endif
|
||||
#ifdef CONFIG_FP_SHARING
|
||||
GEN_OFFSET_SYM(_callee_saved_stack_t, fpu_status);
|
||||
GEN_OFFSET_SYM(_callee_saved_stack_t, fpu_ctrl);
|
||||
#ifdef CONFIG_FP_FPU_DA
|
||||
|
||||
@@ -73,6 +73,38 @@ static void invalidate_dcache(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Adjust the vector table base
|
||||
*
|
||||
* Set the vector table base if the value found in the
|
||||
* _ARC_V2_IRQ_VECT_BASE auxiliary register is different from the
|
||||
* _VectorTable known by software. It is important to do this very early
|
||||
* so that exception vectors can be handled.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
static void adjust_vector_table_base(void)
|
||||
{
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
#undef _ARC_V2_IRQ_VECT_BASE
|
||||
#define _ARC_V2_IRQ_VECT_BASE _ARC_V2_IRQ_VECT_BASE_S
|
||||
#endif
|
||||
extern struct vector_table _VectorTable;
|
||||
unsigned int vbr;
|
||||
/* if the compiled-in vector table is different
|
||||
* from the base address known by the ARC CPU,
|
||||
* set the vector base to the compiled-in address.
|
||||
*/
|
||||
vbr = z_arc_v2_aux_reg_read(_ARC_V2_IRQ_VECT_BASE);
|
||||
vbr &= 0xfffffc00;
|
||||
if (vbr != (unsigned int)&_VectorTable) {
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_IRQ_VECT_BASE,
|
||||
(unsigned int)&_VectorTable);
|
||||
}
|
||||
}
|
||||
|
||||
extern FUNC_NORETURN void z_cstart(void);
|
||||
/**
|
||||
*
|
||||
@@ -86,6 +118,7 @@ extern FUNC_NORETURN void z_cstart(void);
|
||||
void _PrepC(void)
|
||||
{
|
||||
z_icache_setup();
|
||||
adjust_vector_table_base();
|
||||
z_bss_zero();
|
||||
z_data_copy();
|
||||
z_cstart();
|
||||
|
||||
@@ -17,14 +17,13 @@
|
||||
#include <kernel_structs.h>
|
||||
#include <offsets_short.h>
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <swap_macros.h>
|
||||
|
||||
GTEXT(_rirq_enter)
|
||||
GTEXT(_rirq_exit)
|
||||
GTEXT(_rirq_common_interrupt_swap)
|
||||
|
||||
GDATA(exc_nest_count)
|
||||
|
||||
#if 0 /* TODO: when FIRQ is not present, all would be regular */
|
||||
#define NUM_REGULAR_IRQ_PRIO_LEVELS CONFIG_NUM_IRQ_PRIO_LEVELS
|
||||
@@ -36,168 +35,6 @@ GTEXT(_rirq_common_interrupt_swap)
|
||||
* TODO: Revist this if FIRQ becomes configurable.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
===========================================================
|
||||
RETURN FROM INTERRUPT TO COOPERATIVE THREAD
|
||||
===========================================================
|
||||
|
||||
That's a special case because:
|
||||
1. We return from IRQ handler to a cooperative thread
|
||||
2. During IRQ handling context switch did happen
|
||||
3. Returning to a thread which previously gave control
|
||||
to another thread because of:
|
||||
- Calling k_sleep()
|
||||
- Explicitly yielding
|
||||
- Bumping into locked sync primitive etc
|
||||
|
||||
What (3) means is before passing control to another thread our thread
|
||||
in question:
|
||||
a. Stashed all precious caller-saved registers on its stack
|
||||
b. Pushed return address to the top of the stack as well
|
||||
|
||||
That's how thread's stack looks like right before jumping to another thread:
|
||||
----------------------------->8---------------------------------
|
||||
PRE-CONTEXT-SWITCH STACK
|
||||
|
||||
lower_addr, let's say: 0x1000
|
||||
|
||||
--------------------------------------
|
||||
SP -> | Return address; PC (Program Counter), in fact value taken from
|
||||
| BLINK register in arch_switch()
|
||||
--------------------------------------
|
||||
| STATUS32 value, we explicitly save it here for later usage, read-on
|
||||
--------------------------------------
|
||||
| Caller-saved registers: some of R0-R12
|
||||
--------------------------------------
|
||||
|...
|
||||
|...
|
||||
|
||||
higher_addr, let's say: 0x2000
|
||||
----------------------------->8---------------------------------
|
||||
|
||||
When context gets switched the kernel saves callee-saved registers in the
|
||||
thread's stack right on top of pre-switch contents so that's what we have:
|
||||
----------------------------->8---------------------------------
|
||||
POST-CONTEXT-SWITCH STACK
|
||||
|
||||
lower_addr, let's say: 0x1000
|
||||
|
||||
--------------------------------------
|
||||
SP -> | Callee-saved registers: see struct _callee_saved_stack{}
|
||||
| |- R13
|
||||
| |- R14
|
||||
| | ...
|
||||
| \- FP
|
||||
| ...
|
||||
--------------------------------------
|
||||
| Return address; PC (Program Counter)
|
||||
--------------------------------------
|
||||
| STATUS32 value
|
||||
--------------------------------------
|
||||
| Caller-saved registers: some of R0-R12
|
||||
--------------------------------------
|
||||
|...
|
||||
|...
|
||||
|
||||
higher_addr, let's say: 0x2000
|
||||
----------------------------->8---------------------------------
|
||||
|
||||
So how do we return in such a complex scenario.
|
||||
|
||||
First we restore callee-saved regs with help of _load_callee_saved_regs().
|
||||
Now we're back to PRE-CONTEXT-SWITCH STACK (see above).
|
||||
|
||||
Logically our next step is to load return address from the top of the stack
|
||||
and jump to that address to continue execution of the desired thread, but
|
||||
we're still in interrupt handling mode and the only way to return to normal
|
||||
execution mode is to execute "rtie" instruction. And here we need to deal
|
||||
with peculiarities of return from IRQ on ARCv2 cores.
|
||||
|
||||
Instead of simple jump to a return address stored in the tip of thread's stack
|
||||
(with subsequent interrupt enable) ARCv2 core additionally automatically
|
||||
restores some registers from stack. Most important ones are
|
||||
PC ("Program Counter") which holds address of the next instruction to execute
|
||||
and STATUS32 which holds imortant flags including global interrupt enable,
|
||||
zero, carry etc.
|
||||
|
||||
To make things worse depending on ARC core configuration and run-time setup
|
||||
of certain features different set of registers will be restored.
|
||||
|
||||
Typically those same registers are automatically saved on stack on entry to
|
||||
an interrupt, but remember we're returning to the thread which was
|
||||
not interrupted by interrupt and so on its stack there're no automatically
|
||||
saved registers, still inevitably on RTIE execution register restoration
|
||||
will happen. So if we do nothing special we'll end-up with that:
|
||||
----------------------------->8---------------------------------
|
||||
lower_addr, let's say: 0x1000
|
||||
|
||||
--------------------------------------
|
||||
# | Return address; PC (Program Counter)
|
||||
| --------------------------------------
|
||||
| | STATUS32 value
|
||||
| --------------------------------------
|
||||
|
|
||||
sizeof(_irq_stack_frame)
|
||||
|
|
||||
| | Caller-saved registers: R0-R12
|
||||
V --------------------------------------
|
||||
|...
|
||||
SP -> | < Some data on thread's stack>
|
||||
|...
|
||||
|
||||
higher_addr, let's say: 0x2000
|
||||
----------------------------->8---------------------------------
|
||||
|
||||
I.e. we'll go much deeper down the stack over needed return address, read
|
||||
some value from unexpected location in stack and will try to jump there.
|
||||
Nobody knows were we end-up then.
|
||||
|
||||
To work-around that problem we need to mimic existance of IRQ stack frame
|
||||
of which we really only need return address obviously to return where we
|
||||
need to. For that we just shift SP so that it points sizeof(_irq_stack_frame)
|
||||
above like that:
|
||||
----------------------------->8---------------------------------
|
||||
lower_addr, let's say: 0x1000
|
||||
|
||||
SP -> |
|
||||
A | < Some unrelated data >
|
||||
| |
|
||||
|
|
||||
sizeof(_irq_stack_frame)
|
||||
|
|
||||
| --------------------------------------
|
||||
| | Return address; PC (Program Counter)
|
||||
| --------------------------------------
|
||||
# | STATUS32 value
|
||||
--------------------------------------
|
||||
| Caller-saved registers: R0-R12
|
||||
--------------------------------------
|
||||
|...
|
||||
| < Some data on thread's stack>
|
||||
|...
|
||||
|
||||
higher_addr, let's say: 0x2000
|
||||
----------------------------->8---------------------------------
|
||||
|
||||
Indeed R0-R13 "restored" from IRQ stack frame will contain garbage but
|
||||
it makes no difference because we're returning to execution of code as if
|
||||
we're returning from yet another function call and so we will restore
|
||||
all needed registers from the stack.
|
||||
|
||||
One other important remark here is R13.
|
||||
|
||||
CPU hardware automatically save/restore registers in pairs and since we
|
||||
wanted to save/restore R12 in IRQ stack frame as a caller-saved register we
|
||||
just happen to do that for R13 as well. But given compiler treats it as
|
||||
a callee-saved register we save/restore it separately in _callee_saved_stack
|
||||
structure. And when we restore callee-saved registers from stack we among
|
||||
other registers recover R13. But later on return from IRQ with RTIE
|
||||
instruction, R13 will be "restored" again from fake IRQ stack frame and
|
||||
if we don't copy correct R13 value to fake IRQ stack frame R13 value
|
||||
will be corrupted.
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -216,11 +53,12 @@ SECTION_FUNC(TEXT, _rirq_enter)
|
||||
|
||||
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
lr r2, [_ARC_V2_SEC_STAT]
|
||||
bclr r2, r2, _ARC_V2_SEC_STAT_SSC_BIT
|
||||
sflag r2
|
||||
|
||||
/* sflag r2 */
|
||||
/* sflag instruction is not supported in current ARC GNU */
|
||||
.long 0x00bf302f
|
||||
#else
|
||||
/* disable stack checking */
|
||||
lr r2, [_ARC_V2_STATUS32]
|
||||
@@ -229,14 +67,16 @@ SECTION_FUNC(TEXT, _rirq_enter)
|
||||
#endif
|
||||
#endif
|
||||
clri
|
||||
ld r1, [exc_nest_count]
|
||||
add r0, r1, 1
|
||||
st r0, [exc_nest_count]
|
||||
cmp r1, 0
|
||||
|
||||
/* check whether irq stack is used */
|
||||
_check_and_inc_int_nest_counter r0, r1
|
||||
bgt.d rirq_nest
|
||||
mov r0, sp
|
||||
|
||||
bne.d rirq_nest
|
||||
mov_s r0, sp
|
||||
|
||||
_get_curr_cpu_irq_stack sp
|
||||
mov r1, _kernel
|
||||
ld sp, [r1, _kernel_offset_to_irq_stack]
|
||||
rirq_nest:
|
||||
push_s r0
|
||||
|
||||
@@ -256,11 +96,27 @@ SECTION_FUNC(TEXT, _rirq_exit)
|
||||
|
||||
pop sp
|
||||
|
||||
_dec_int_nest_counter r0, r1
|
||||
|
||||
_check_nest_int_by_irq_act r0, r1
|
||||
|
||||
jne _rirq_no_reschedule
|
||||
mov r1, exc_nest_count
|
||||
ld r0, [r1]
|
||||
sub r0, r0, 1
|
||||
st r0, [r1]
|
||||
/*
|
||||
* using exc_nest_count to decide whether is nest int is not reliable.
|
||||
* a better option is to use IRQ_ACT
|
||||
* A case is: a high priority int preempts a low priority int before
|
||||
* rirq_enter/firq_enter, then in _rirq_exit/_firq_exit, it will see
|
||||
* exc_nest_cout is 0, this will lead to possible thread switch, but
|
||||
* a low priority int is still pending.
|
||||
*
|
||||
* If multi bits in IRQ_ACT are set, i.e. last bit != fist bit, it's
|
||||
* in nest interrupt
|
||||
*/
|
||||
lr r0, [_ARC_V2_AUX_IRQ_ACT]
|
||||
and r0, r0, 0xffff
|
||||
ffs r1, r0
|
||||
fls r2, r0
|
||||
cmp r1, r2
|
||||
jne _rirq_return_from_rirq
|
||||
|
||||
#ifdef CONFIG_STACK_SENTINEL
|
||||
bl z_check_stack_sentinel
|
||||
@@ -268,16 +124,14 @@ SECTION_FUNC(TEXT, _rirq_exit)
|
||||
|
||||
#ifdef CONFIG_PREEMPT_ENABLED
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
bl z_arc_smp_switch_in_isr
|
||||
/* r0 points to new thread, r1 points to old thread */
|
||||
cmp_s r0, 0
|
||||
beq _rirq_no_reschedule
|
||||
mov_s r2, r1
|
||||
#else
|
||||
mov_s r1, _kernel
|
||||
mov r1, _kernel
|
||||
ld_s r2, [r1, _kernel_offset_to_current]
|
||||
|
||||
/*
|
||||
* Lock interrupts to ensure kernel queues do not change from this
|
||||
* point on until return from interrupt.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Both (a)reschedule and (b)non-reschedule cases need to load the
|
||||
* current thread's stack, but don't have to use it until the decision
|
||||
@@ -294,27 +148,18 @@ SECTION_FUNC(TEXT, _rirq_exit)
|
||||
beq _rirq_no_reschedule
|
||||
|
||||
/* cached thread to run is in r0, fall through */
|
||||
#endif
|
||||
|
||||
.balign 4
|
||||
_rirq_reschedule:
|
||||
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
/* here need to remember SEC_STAT.IRM bit */
|
||||
lr r3, [_ARC_V2_SEC_STAT]
|
||||
push_s r3
|
||||
#endif
|
||||
/* _save_callee_saved_regs expects outgoing thread in r2 */
|
||||
_save_callee_saved_regs
|
||||
|
||||
st _CAUSE_RIRQ, [r2, _thread_offset_to_relinquish_cause]
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
mov_s r2, r0
|
||||
#else
|
||||
/* incoming thread is in r0: it becomes the new 'current' */
|
||||
mov_s r2, r0
|
||||
mov r2, r0
|
||||
st_s r2, [r1, _kernel_offset_to_current]
|
||||
#endif
|
||||
|
||||
.balign 4
|
||||
_rirq_common_interrupt_swap:
|
||||
@@ -331,7 +176,7 @@ _rirq_common_interrupt_swap:
|
||||
|
||||
#if defined(CONFIG_MPU_STACK_GUARD) || defined(CONFIG_USERSPACE)
|
||||
push_s r2
|
||||
mov_s r0, r2
|
||||
mov r0, r2
|
||||
bl configure_mpu_thread
|
||||
pop_s r2
|
||||
#endif
|
||||
@@ -355,30 +200,36 @@ _rirq_common_interrupt_swap:
|
||||
ld r3, [r2, _thread_offset_to_relinquish_cause]
|
||||
|
||||
breq r3, _CAUSE_RIRQ, _rirq_return_from_rirq
|
||||
nop_s
|
||||
nop
|
||||
breq r3, _CAUSE_FIRQ, _rirq_return_from_firq
|
||||
nop_s
|
||||
nop
|
||||
|
||||
/* fall through */
|
||||
|
||||
.balign 4
|
||||
_rirq_return_from_coop:
|
||||
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
/* must return to secure mode, so set IRM bit to 1 */
|
||||
lr r0, [_ARC_V2_SEC_STAT]
|
||||
bset r0, r0, _ARC_V2_SEC_STAT_IRM_BIT
|
||||
sflag r0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* See verbose explanation of
|
||||
* RETURN FROM INTERRUPT TO COOPERATIVE THREAD above
|
||||
* status32, sec_stat (when CONFIG_ARC_HAS_SECURE is enabled) and pc
|
||||
* (blink) are already on the stack in the right order
|
||||
*/
|
||||
ld_s r0, [sp, ___isf_t_status32_OFFSET - ___isf_t_pc_OFFSET]
|
||||
|
||||
/* update status32.ie (explanation in firq_exit:_firq_return_from_coop) */
|
||||
|
||||
ld r3, [r2, _thread_offset_to_intlock_key]
|
||||
st 0, [r2, _thread_offset_to_intlock_key]
|
||||
cmp r3, 0
|
||||
or.ne r0, r0, _ARC_V2_STATUS32_IE
|
||||
|
||||
st_s r0, [sp, ___isf_t_status32_OFFSET - ___isf_t_pc_OFFSET]
|
||||
|
||||
/* carve fake stack */
|
||||
sub sp, sp, ___isf_t_pc_OFFSET
|
||||
|
||||
/* update return value on stack */
|
||||
ld r0, [r2, _thread_offset_to_return_value]
|
||||
st_s r0, [sp, ___isf_t_r0_OFFSET]
|
||||
|
||||
/* reset zero-overhead loops */
|
||||
st 0, [sp, ___isf_t_lp_end_OFFSET]
|
||||
@@ -391,20 +242,19 @@ _rirq_return_from_coop:
|
||||
*/
|
||||
st_s r13, [sp, ___isf_t_r13_OFFSET]
|
||||
|
||||
/* stack now has the IRQ stack frame layout, pointing to sp */
|
||||
/* stack now has the IRQ stack frame layout, pointing to r0 */
|
||||
|
||||
/* fall through to rtie instruction */
|
||||
|
||||
/* rtie will pop the rest from the stack */
|
||||
rtie
|
||||
|
||||
/* fall through to rtie instruction */
|
||||
|
||||
#endif /* CONFIG_PREEMPT_ENABLED */
|
||||
|
||||
.balign 4
|
||||
_rirq_return_from_firq:
|
||||
_rirq_return_from_rirq:
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
/* here need to recover SEC_STAT.IRM bit */
|
||||
pop_s r3
|
||||
sflag r3
|
||||
#endif
|
||||
_rirq_no_reschedule:
|
||||
|
||||
rtie
|
||||
|
||||
@@ -14,11 +14,9 @@
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <swap_macros.h>
|
||||
|
||||
GDATA(_interrupt_stack)
|
||||
GDATA(z_main_stack)
|
||||
GDATA(_VectorTable)
|
||||
GDATA(_main_stack)
|
||||
|
||||
/* use one of the available interrupt stacks during init */
|
||||
|
||||
@@ -45,57 +43,35 @@ GTEXT(__start)
|
||||
|
||||
SECTION_FUNC(TEXT,__reset)
|
||||
SECTION_FUNC(TEXT,__start)
|
||||
|
||||
/* lock interrupts: will get unlocked when switch to main task
|
||||
* also make sure the processor in the correct status
|
||||
*/
|
||||
mov_s r0, 0
|
||||
mov r0, 0
|
||||
kflag r0
|
||||
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
sflag r0
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BOOT_TIME_MEASUREMENT) && defined(CONFIG_ARCV2_TIMER)
|
||||
/*
|
||||
* ARCV2 timer (timer0) is a free run timer, let it start to count
|
||||
* here.
|
||||
*/
|
||||
mov_s r0, 0xffffffff
|
||||
mov r0, 0xffffffff
|
||||
sr r0, [_ARC_V2_TMR0_LIMIT]
|
||||
mov_s r0, 0
|
||||
mov r0, 0
|
||||
sr r0, [_ARC_V2_TMR0_COUNT]
|
||||
#endif
|
||||
/* interrupt related init */
|
||||
#ifndef CONFIG_ARC_NORMAL_FIRMWARE
|
||||
/* IRQ_ACT and IRQ_CTRL should be initialized and set in secure mode */
|
||||
sr r0, [_ARC_V2_AUX_IRQ_ACT]
|
||||
sr r0, [_ARC_V2_AUX_IRQ_CTRL]
|
||||
#endif
|
||||
sr r0, [_ARC_V2_AUX_IRQ_HINT]
|
||||
|
||||
/* set the vector table base early,
|
||||
* so that exception vectors can be handled.
|
||||
*/
|
||||
mov_s r0, _VectorTable
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
sr r0, [_ARC_V2_IRQ_VECT_BASE_S]
|
||||
#else
|
||||
sr r0, [_ARC_V2_IRQ_VECT_BASE]
|
||||
#endif
|
||||
/* \todo: MPU init, gp for small data? */
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
#if CONFIG_USERSPACE
|
||||
lr r0, [_ARC_V2_STATUS32]
|
||||
bset r0, r0, _ARC_V2_STATUS32_US_BIT
|
||||
kflag r0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARC_USE_UNALIGNED_MEM_ACCESS
|
||||
lr r0, [_ARC_V2_STATUS32]
|
||||
bset r0, r0, _ARC_V2_STATUS32_AD_BIT
|
||||
kflag r0
|
||||
#endif
|
||||
|
||||
mov_s r1, 1
|
||||
mov r1, 1
|
||||
|
||||
invalidate_and_disable_icache:
|
||||
|
||||
@@ -106,9 +82,9 @@ invalidate_and_disable_icache:
|
||||
mov_s r2, 0
|
||||
sr r2, [_ARC_V2_IC_IVIC]
|
||||
/* writing to IC_IVIC needs 3 NOPs */
|
||||
nop_s
|
||||
nop_s
|
||||
nop_s
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
sr r1, [_ARC_V2_IC_CTRL]
|
||||
|
||||
invalidate_dcache:
|
||||
@@ -126,36 +102,13 @@ done_cache_invalidate:
|
||||
jl @_sys_resume_from_deep_sleep
|
||||
#endif
|
||||
|
||||
#if CONFIG_MP_NUM_CPUS > 1
|
||||
_get_cpu_id r0
|
||||
breq r0, 0, _master_core_startup
|
||||
|
||||
/*
|
||||
* Non-masters wait for master core (core 0) to boot enough
|
||||
*/
|
||||
_slave_core_wait:
|
||||
ld r1, [arc_cpu_wake_flag]
|
||||
brne r0, r1, _slave_core_wait
|
||||
|
||||
ld sp, [arc_cpu_sp]
|
||||
/* signal master core that slave core runs */
|
||||
st 0, [arc_cpu_wake_flag]
|
||||
|
||||
#if defined(CONFIG_ARC_FIRQ_STACK)
|
||||
jl z_arc_firq_stack_set
|
||||
#endif
|
||||
j z_arc_slave_start
|
||||
|
||||
_master_core_startup:
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_INIT_STACKS
|
||||
/*
|
||||
* use the main stack to call memset on the interrupt stack and the
|
||||
* FIRQ stack when CONFIG_INIT_STACKS is enabled before switching to
|
||||
* one of them for the rest of the early boot
|
||||
*/
|
||||
mov_s sp, z_main_stack
|
||||
mov sp, _main_stack
|
||||
add sp, sp, CONFIG_MAIN_STACK_SIZE
|
||||
|
||||
mov_s r0, _interrupt_stack
|
||||
@@ -165,11 +118,7 @@ _master_core_startup:
|
||||
|
||||
#endif /* CONFIG_INIT_STACKS */
|
||||
|
||||
mov_s sp, INIT_STACK
|
||||
mov sp, INIT_STACK
|
||||
add sp, sp, INIT_STACK_SIZE
|
||||
|
||||
#if defined(CONFIG_ARC_FIRQ_STACK)
|
||||
jl z_arc_firq_stack_set
|
||||
#endif
|
||||
|
||||
j @_PrepC
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2018 Synopsys, Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources(
|
||||
arc_sjli.c
|
||||
arc_secure.S
|
||||
secure_sys_services.c
|
||||
)
|
||||
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Synopsys.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <arch/cpu.h>
|
||||
|
||||
.macro clear_scratch_regs
|
||||
mov r1, 0
|
||||
mov r2, 0
|
||||
mov r3, 0
|
||||
mov r4, 0
|
||||
mov r5, 0
|
||||
mov r6, 0
|
||||
mov r7, 0
|
||||
mov r8, 0
|
||||
mov r9, 0
|
||||
mov r10, 0
|
||||
mov r11, 0
|
||||
mov r12, 0
|
||||
.endm
|
||||
|
||||
.macro clear_callee_regs
|
||||
mov r25, 0
|
||||
mov r24, 0
|
||||
mov r23, 0
|
||||
mov r22, 0
|
||||
mov r21, 0
|
||||
mov r20, 0
|
||||
mov r19, 0
|
||||
mov r18, 0
|
||||
mov r17, 0
|
||||
mov r16, 0
|
||||
|
||||
mov r15, 0
|
||||
mov r14, 0
|
||||
mov r13, 0
|
||||
.endm
|
||||
|
||||
GTEXT(arc_go_to_normal)
|
||||
GTEXT(_arc_do_secure_call)
|
||||
GDATA(arc_s_call_table)
|
||||
|
||||
|
||||
SECTION_FUNC(TEXT, _arc_do_secure_call)
|
||||
/* r0-r5: arg1-arg6, r6 is call id */
|
||||
/* the call id should be checked */
|
||||
/* disable normal interrupt happened when processor in secure mode ? */
|
||||
/* seti (0x30 | (ARC_N_IRQ_START_LEVEL-1)) */
|
||||
breq r6, ARC_S_CALL_CLRI, _s_clri
|
||||
breq r6, ARC_S_CALL_SETI, _s_seti
|
||||
push_s blink
|
||||
mov blink, arc_s_call_table
|
||||
ld.as r6, [blink, r6]
|
||||
|
||||
jl [r6]
|
||||
|
||||
/*
|
||||
* no need to clear callee regs, as they will be saved and restored
|
||||
* automatically
|
||||
*/
|
||||
clear_scratch_regs
|
||||
|
||||
mov r29, 0
|
||||
mov r30, 0
|
||||
|
||||
|
||||
_arc_do_secure_call_exit:
|
||||
pop_s blink
|
||||
|
||||
j [blink]
|
||||
/* enable normal interrupt */
|
||||
/*
|
||||
* j.d [blink]
|
||||
* seti (0x30 | (CONFIG_NUM_IRQ_PRIO_LEVELS - 1))
|
||||
*/
|
||||
|
||||
_s_clri:
|
||||
lr r0, [_ARC_V2_STATUS32]
|
||||
and r0, r0, 0x1e
|
||||
asr r0, r0
|
||||
or r0, r0, 0x30
|
||||
mov r6, (0x30 | (ARC_N_IRQ_START_LEVEL-1))
|
||||
|
||||
j.d [blink]
|
||||
seti r6
|
||||
|
||||
_s_seti:
|
||||
btst r0, 4
|
||||
jnz __seti_0
|
||||
mov r0, (CONFIG_NUM_IRQ_PRIO_LEVELS - 1)
|
||||
lr r6, [_ARC_V2_STATUS32]
|
||||
and r6, r6, 0x1e
|
||||
asr r6, r6
|
||||
cmp r0, r6
|
||||
mov.hs r0, r6
|
||||
__seti_0:
|
||||
and r0, r0, 0xf
|
||||
brhs r0, ARC_N_IRQ_START_LEVEL, __seti_1
|
||||
mov r0, ARC_N_IRQ_START_LEVEL
|
||||
__seti_1:
|
||||
or r0, r0, 0x30
|
||||
|
||||
j.d [blink]
|
||||
seti r0
|
||||
|
||||
|
||||
SECTION_FUNC(TEXT, arc_go_to_normal)
|
||||
clear_callee_regs
|
||||
clear_scratch_regs
|
||||
|
||||
mov fp, 0
|
||||
mov r29, 0
|
||||
mov r30, 0
|
||||
mov blink, 0
|
||||
|
||||
jl [r0]
|
||||
/* should not come here */
|
||||
kflag 1
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Synopsys, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <device.h>
|
||||
#include <kernel.h>
|
||||
#include <errno.h>
|
||||
#include <zephyr/types.h>
|
||||
#include <init.h>
|
||||
#include <toolchain.h>
|
||||
|
||||
#include <arch/arc/v2/secureshield/arc_secure.h>
|
||||
|
||||
static void _default_sjli_entry(void);
|
||||
/*
|
||||
* sjli vector table must be in instruction space
|
||||
* \todo: how to let user to install customized sjli entry easily, e.g.
|
||||
* through macros or with the help of compiler?
|
||||
*/
|
||||
const static u32_t _sjli_vector_table[CONFIG_SJLI_TABLE_SIZE] = {
|
||||
[0] = (u32_t)_arc_do_secure_call,
|
||||
[1 ... (CONFIG_SJLI_TABLE_SIZE - 1)] = (u32_t)_default_sjli_entry,
|
||||
};
|
||||
|
||||
/*
|
||||
* @brief default entry of sjli call
|
||||
*
|
||||
*/
|
||||
static void _default_sjli_entry(void)
|
||||
{
|
||||
printk("default sjli entry\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief initializaiton of sjli related functions
|
||||
*
|
||||
*/
|
||||
static void sjli_table_init(void)
|
||||
{
|
||||
/* install SJLI table */
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_NSC_TABLE_BASE, _sjli_vector_table);
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_NSC_TABLE_TOP,
|
||||
(_sjli_vector_table + CONFIG_SJLI_TABLE_SIZE));
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief initializaiton of secureshield related functions.
|
||||
*/
|
||||
static int arc_secureshield_init(struct device *arg)
|
||||
{
|
||||
sjli_table_init();
|
||||
|
||||
/* set nic bit to enable seti/clri and
|
||||
* sleep/wevt in normal mode.
|
||||
* If not set, direct call of seti/clri etc. will raise exception.
|
||||
* Then, these seti/clri instructions should be replaced with secure
|
||||
* secure services (sjli call)
|
||||
*
|
||||
*/
|
||||
__asm__ volatile("sflag 0x20");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYS_INIT(arc_secureshield_init, PRE_KERNEL_1,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Synopsys, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <kernel.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <zephyr/types.h>
|
||||
#include <soc.h>
|
||||
#include <toolchain.h>
|
||||
|
||||
#include <arch/arc/v2/secureshield/arc_secure.h>
|
||||
|
||||
#define IRQ_PRIO_MASK (0xffff << ARC_N_IRQ_START_LEVEL)
|
||||
/*
|
||||
* @brief read secure auxiliary regs on behalf of normal mode
|
||||
*
|
||||
* @param aux_reg address of aux reg
|
||||
*
|
||||
* Some aux regs require secure privilege, this function implements
|
||||
* an secure service to access secure aux regs. Check should be done
|
||||
* to decide whether the access is valid.
|
||||
*/
|
||||
static s32_t arc_s_aux_read(u32_t aux_reg)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief write secure auxiliary regs on behalf of normal mode
|
||||
*
|
||||
* @param aux_reg address of aux reg
|
||||
* @param val, the val to write
|
||||
*
|
||||
* Some aux regs require secure privilege, this function implements
|
||||
* an secure service to access secure aux regs. Check should be done
|
||||
* to decide whether the access is valid.
|
||||
*/
|
||||
static s32_t arc_s_aux_write(u32_t aux_reg, u32_t val)
|
||||
{
|
||||
if (aux_reg == _ARC_V2_AUX_IRQ_ACT) {
|
||||
/* 0 -> CONFIG_NUM_IRQ_PRIO_LEVELS allocated to secure world
|
||||
* left prio levels allocated to normal world
|
||||
*/
|
||||
val &= IRQ_PRIO_MASK;
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_AUX_IRQ_ACT, val |
|
||||
(z_arc_v2_aux_reg_read(_ARC_V2_AUX_IRQ_ACT) &
|
||||
(~IRQ_PRIO_MASK)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief allocate interrupt for normal world
|
||||
*
|
||||
* @param intno, the interrupt to be allocated to normal world
|
||||
*
|
||||
* By default, most interrupts are configured to be secure in initialization.
|
||||
* If normal world wants to use an interrupt, through this secure service to
|
||||
* apply one. Necessary check should be done to decide whether the apply is
|
||||
* valid
|
||||
*/
|
||||
static s32_t arc_s_irq_alloc(u32_t intno)
|
||||
{
|
||||
z_arc_v2_irq_uinit_secure_set(intno, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* \todo, to access MPU from normal mode, secure mpu service should be
|
||||
* created. In the secure mpu service, the parameters should be checked
|
||||
* (e.g., not overwrite the mpu regions for secure world)that operations
|
||||
* are valid
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* \todo, how to add secure service easily
|
||||
*/
|
||||
const _arc_s_call_handler_t arc_s_call_table[ARC_S_CALL_LIMIT] = {
|
||||
[ARC_S_CALL_AUX_READ] = (_arc_s_call_handler_t)arc_s_aux_read,
|
||||
[ARC_S_CALL_AUX_WRITE] = (_arc_s_call_handler_t)arc_s_aux_write,
|
||||
[ARC_S_CALL_IRQ_ALLOC] = (_arc_s_call_handler_t)arc_s_irq_alloc,
|
||||
};
|
||||
248
arch/arc/core/swap.S
Normal file
248
arch/arc/core/swap.S
Normal file
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2015 Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Thread context switching
|
||||
*
|
||||
* This module implements the routines necessary for thread context switching
|
||||
* on ARCv2 CPUs.
|
||||
*
|
||||
* See isr_wrapper.S for details.
|
||||
*/
|
||||
|
||||
#include <kernel_structs.h>
|
||||
#include <offsets_short.h>
|
||||
#include <toolchain.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <v2/irq.h>
|
||||
#include <swap_macros.h>
|
||||
|
||||
GTEXT(__swap)
|
||||
GDATA(_k_neg_eagain)
|
||||
GDATA(_kernel)
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Initiate a cooperative context switch
|
||||
*
|
||||
* The __swap() routine is invoked by various kernel services to effect
|
||||
* a cooperative context switch. Prior to invoking __swap(), the caller
|
||||
* disables interrupts via irq_lock() and the return 'key' is passed as a
|
||||
* parameter to __swap(). The key is in fact the value stored in the register
|
||||
* operand of a CLRI instruction.
|
||||
*
|
||||
* It stores the intlock key parameter into current->intlock_key.
|
||||
|
||||
* Given that __swap() is called to effect a cooperative context switch,
|
||||
* the caller-saved integer registers are saved on the stack by the function
|
||||
* call preamble to __swap(). This creates a custom stack frame that will be
|
||||
* popped when returning from __swap(), but is not suitable for handling a
|
||||
* return from an exception. Thus, the fact that the thread is pending because
|
||||
* of a cooperative call to __swap() has to be recorded via the _CAUSE_COOP code
|
||||
* in the relinquish_cause of the thread's k_thread structure. The
|
||||
* _IrqExit()/_FirqExit() code will take care of doing the right thing to
|
||||
* restore the thread status.
|
||||
*
|
||||
* When __swap() is invoked, we know the decision to perform a context switch or
|
||||
* not has already been taken and a context switch must happen.
|
||||
*
|
||||
* @return may contain a return value setup by a call to
|
||||
* z_set_thread_return_value()
|
||||
*
|
||||
* C function prototype:
|
||||
*
|
||||
* unsigned int __swap (unsigned int key);
|
||||
*
|
||||
*/
|
||||
|
||||
SECTION_FUNC(TEXT, __swap)
|
||||
|
||||
#ifdef CONFIG_EXECUTION_BENCHMARKING
|
||||
mov r1, _kernel
|
||||
ld_s r2, [r1, _kernel_offset_to_current]
|
||||
_save_callee_saved_regs
|
||||
push_s r31
|
||||
|
||||
bl read_timer_start_of_swap
|
||||
|
||||
pop_s r31
|
||||
mov r1, _kernel
|
||||
ld_s r2, [r1, _kernel_offset_to_current]
|
||||
_load_callee_saved_regs
|
||||
st sp, [r2, _thread_offset_to_sp]
|
||||
#endif
|
||||
|
||||
/* interrupts are locked, interrupt key is in r0 */
|
||||
|
||||
mov r1, _kernel
|
||||
ld_s r2, [r1, _kernel_offset_to_current]
|
||||
|
||||
/* save intlock key */
|
||||
st r0, [r2, _thread_offset_to_intlock_key]
|
||||
st _CAUSE_COOP, [r2, _thread_offset_to_relinquish_cause]
|
||||
|
||||
/*
|
||||
* Carve space for the return value. Setting it to a default of
|
||||
* -EAGAIN eliminates the need for the timeout code to set it.
|
||||
* If another value is ever needed, it can be modified with
|
||||
* z_set_thread_return_value().
|
||||
*/
|
||||
ld r3, [_k_neg_eagain]
|
||||
st r3, [r2, _thread_offset_to_return_value]
|
||||
|
||||
/*
|
||||
* Save status32 and blink on the stack before the callee-saved registers.
|
||||
* This is the same layout as the start of an IRQ stack frame.
|
||||
*/
|
||||
lr r3, [_ARC_V2_STATUS32]
|
||||
push_s r3
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
lr r3, [_ARC_V2_SEC_STAT]
|
||||
push_s r3
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
bclr r3, r3, _ARC_V2_SEC_STAT_SSC_BIT
|
||||
/* sflag r3 */
|
||||
/* sflag instruction is not supported in current ARC GNU */
|
||||
.long 0x00ff302f
|
||||
#else
|
||||
/* disable stack checking during swap */
|
||||
bclr r3, r3, _ARC_V2_STATUS32_SC_BIT
|
||||
kflag r3
|
||||
#endif
|
||||
#endif
|
||||
|
||||
push_s blink
|
||||
|
||||
_save_callee_saved_regs
|
||||
|
||||
/* get the cached thread to run */
|
||||
ld_s r2, [r1, _kernel_offset_to_ready_q_cache]
|
||||
|
||||
/* entering here, r2 contains the new current thread */
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
_load_stack_check_regs
|
||||
#endif
|
||||
/* XXX - can be moved to delay slot of _CAUSE_RIRQ ? */
|
||||
st_s r2, [r1, _kernel_offset_to_current]
|
||||
|
||||
_load_callee_saved_regs
|
||||
|
||||
#if defined(CONFIG_MPU_STACK_GUARD) || defined(CONFIG_USERSPACE)
|
||||
push_s r2
|
||||
mov r0, r2
|
||||
bl configure_mpu_thread
|
||||
pop_s r2
|
||||
#endif
|
||||
|
||||
ld r3, [r2, _thread_offset_to_relinquish_cause]
|
||||
|
||||
breq r3, _CAUSE_RIRQ, _swap_return_from_rirq
|
||||
nop
|
||||
breq r3, _CAUSE_FIRQ, _swap_return_from_firq
|
||||
nop
|
||||
|
||||
/* fall through to _swap_return_from_coop */
|
||||
|
||||
.balign 4
|
||||
_swap_return_from_coop:
|
||||
|
||||
ld r1, [r2, _thread_offset_to_intlock_key]
|
||||
st 0, [r2, _thread_offset_to_intlock_key]
|
||||
ld r0, [r2, _thread_offset_to_return_value]
|
||||
|
||||
lr ilink, [_ARC_V2_STATUS32]
|
||||
bbit1 ilink, _ARC_V2_STATUS32_AE_BIT, _return_from_exc
|
||||
|
||||
pop_s blink /* pc into blink */
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
pop_s r3 /* pop SEC_STAT */
|
||||
/* sflag r3 */
|
||||
/* sflag instruction is not supported in current ARC GNU */
|
||||
.long 0x00ff302f
|
||||
#endif
|
||||
#ifdef CONFIG_EXECUTION_BENCHMARKING
|
||||
b _capture_value_for_benchmarking
|
||||
#endif
|
||||
return_loc:
|
||||
|
||||
pop_s r3 /* status32 into r3 */
|
||||
kflag r3 /* write status32 */
|
||||
|
||||
j_s.d [blink] /* always execute delay slot */
|
||||
seti r1 /* delay slot */
|
||||
|
||||
|
||||
.balign 4
|
||||
_swap_return_from_rirq:
|
||||
_swap_return_from_firq:
|
||||
|
||||
lr r3, [_ARC_V2_STATUS32]
|
||||
bbit1 r3, _ARC_V2_STATUS32_AE_BIT, _return_from_exc_irq
|
||||
|
||||
/* pretend interrupt happened to use rtie instruction */
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
lr r3, [_ARC_V2_SEC_STAT]
|
||||
/* set SEC_STAT.IRM = SECURE for interrupt return */
|
||||
bset r3, r3, 3
|
||||
/* sflag r3 */
|
||||
/* sflag instruction is not supported in current ARC GNU */
|
||||
.long 0x00ff302f
|
||||
#endif
|
||||
|
||||
lr r3, [_ARC_V2_AUX_IRQ_ACT]
|
||||
brne r3, 0, _swap_already_in_irq
|
||||
|
||||
/* use lowest interrupt priority */
|
||||
or r3, r3, (1<<(CONFIG_NUM_IRQ_PRIO_LEVELS-1))
|
||||
sr r3, [_ARC_V2_AUX_IRQ_ACT]
|
||||
|
||||
_swap_already_in_irq:
|
||||
rtie
|
||||
|
||||
.balign 4
|
||||
_return_from_exc_irq:
|
||||
_pop_irq_stack_frame
|
||||
sub_s sp, sp, ___isf_t_status32_OFFSET - ___isf_t_pc_OFFSET + 4
|
||||
|
||||
_return_from_exc:
|
||||
|
||||
/* put the return address to eret */
|
||||
ld ilink, [sp] /* pc into ilink */
|
||||
sr ilink, [_ARC_V2_ERET]
|
||||
|
||||
/* SEC_STAT is bypassed when CONFIG_ARC_HAS_SECURE */
|
||||
|
||||
/* put status32 into estatus */
|
||||
ld ilink, [sp, ___isf_t_status32_OFFSET - ___isf_t_pc_OFFSET]
|
||||
sr ilink, [_ARC_V2_ERSTATUS]
|
||||
add_s sp, sp, ___isf_t_status32_OFFSET - ___isf_t_pc_OFFSET + 4
|
||||
|
||||
rtie
|
||||
|
||||
|
||||
#ifdef CONFIG_EXECUTION_BENCHMARKING
|
||||
.balign 4
|
||||
_capture_value_for_benchmarking:
|
||||
mov r1, _kernel
|
||||
ld_s r2, [r1, _kernel_offset_to_current]
|
||||
_save_callee_saved_regs
|
||||
push_s blink
|
||||
|
||||
bl read_timer_end_of_swap
|
||||
|
||||
pop_s blink
|
||||
mov r1, _kernel
|
||||
ld_s r2, [r1, _kernel_offset_to_current]
|
||||
_load_callee_saved_regs
|
||||
st sp, [r2, _thread_offset_to_sp]
|
||||
b return_loc
|
||||
#endif /* CONFIG_EXECUTION_BENCHMARKING */
|
||||
@@ -1,198 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Synopsys.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Thread context switching
|
||||
*
|
||||
* This module implements the routines necessary for thread context switching
|
||||
* on ARCv2 CPUs.
|
||||
*
|
||||
* See isr_wrapper.S for details.
|
||||
*/
|
||||
|
||||
#include <kernel_structs.h>
|
||||
#include <offsets_short.h>
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <v2/irq.h>
|
||||
#include <swap_macros.h>
|
||||
|
||||
GTEXT(arch_switch)
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Initiate a cooperative context switch
|
||||
*
|
||||
* The arch_switch routine is invoked by various kernel services to effect
|
||||
* a cooperative context switch. Prior to invoking arch_switch, the caller
|
||||
* disables interrupts via irq_lock()
|
||||
|
||||
* Given that arch_switch() is called to effect a cooperative context switch,
|
||||
* the caller-saved integer registers are saved on the stack by the function
|
||||
* call preamble to arch_switch. This creates a custom stack frame that will
|
||||
* be popped when returning from arch_switch, but is not suitable for handling
|
||||
* a return from an exception. Thus, the fact that the thread is pending because
|
||||
* of a cooperative call to arch_switch() has to be recorded via the
|
||||
* _CAUSE_COOP code in the relinquish_cause of the thread's k_thread structure.
|
||||
* The _rirq_exit()/_firq_exit() code will take care of doing the right thing
|
||||
* to restore the thread status.
|
||||
*
|
||||
* When arch_switch() is invoked, we know the decision to perform a context
|
||||
* switch or not has already been taken and a context switch must happen.
|
||||
*
|
||||
*
|
||||
* C function prototype:
|
||||
*
|
||||
* void arch_switch(void *switch_to, void **switched_from);
|
||||
*
|
||||
*/
|
||||
|
||||
SECTION_FUNC(TEXT, arch_switch)
|
||||
|
||||
#ifdef CONFIG_EXECUTION_BENCHMARKING
|
||||
push_s r0
|
||||
push_s r1
|
||||
push_s blink
|
||||
|
||||
bl read_timer_start_of_swap
|
||||
|
||||
pop_s blink
|
||||
pop_s r1
|
||||
pop_s r0
|
||||
#endif
|
||||
/*
|
||||
* r0 = new_thread->switch_handle = switch_to thread,
|
||||
* r1 = &old_thread->switch_handle = &switch_from thread
|
||||
*/
|
||||
|
||||
ld_s r2, [r1]
|
||||
/*
|
||||
* r2 may be dummy_thread in z_cstart, dummy_thread->switch_handle
|
||||
* must be 0
|
||||
*/
|
||||
breq r2, 0, _switch_to_target_thread
|
||||
|
||||
st _CAUSE_COOP, [r2, _thread_offset_to_relinquish_cause]
|
||||
|
||||
/*
|
||||
* Save status32 and blink on the stack before the callee-saved registers.
|
||||
* This is the same layout as the start of an IRQ stack frame.
|
||||
*/
|
||||
lr r3, [_ARC_V2_STATUS32]
|
||||
push_s r3
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
lr r3, [_ARC_V2_SEC_STAT]
|
||||
#else
|
||||
mov_s r3, 0
|
||||
#endif
|
||||
push_s r3
|
||||
#endif
|
||||
|
||||
push_s blink
|
||||
|
||||
_save_callee_saved_regs
|
||||
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
/* disable stack checking here, as sp will be changed to target
|
||||
* thread'sp
|
||||
*/
|
||||
#if defined(CONFIG_ARC_HAS_SECURE) && defined(CONFIG_ARC_SECURE_FIRMWARE)
|
||||
bclr r3, r3, _ARC_V2_SEC_STAT_SSC_BIT
|
||||
sflag r3
|
||||
#else
|
||||
bclr r3, r3, _ARC_V2_STATUS32_SC_BIT
|
||||
kflag r3
|
||||
#endif
|
||||
#endif
|
||||
|
||||
_switch_to_target_thread:
|
||||
|
||||
mov_s r2, r0
|
||||
|
||||
/* entering here, r2 contains the new current thread */
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
_load_stack_check_regs
|
||||
#endif
|
||||
|
||||
_load_callee_saved_regs
|
||||
|
||||
#if defined(CONFIG_MPU_STACK_GUARD) || defined(CONFIG_USERSPACE)
|
||||
push_s r2
|
||||
bl configure_mpu_thread
|
||||
pop_s r2
|
||||
#endif
|
||||
|
||||
ld r3, [r2, _thread_offset_to_relinquish_cause]
|
||||
|
||||
breq r3, _CAUSE_RIRQ, _switch_return_from_rirq
|
||||
nop_s
|
||||
breq r3, _CAUSE_FIRQ, _switch_return_from_firq
|
||||
nop_s
|
||||
|
||||
/* fall through to _switch_return_from_coop */
|
||||
|
||||
.balign 4
|
||||
_switch_return_from_coop:
|
||||
|
||||
pop_s blink /* pc into blink */
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
pop_s r3 /* pop SEC_STAT */
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
sflag r3
|
||||
#endif
|
||||
#endif
|
||||
pop_s r3 /* status32 into r3 */
|
||||
kflag r3 /* write status32 */
|
||||
|
||||
#ifdef CONFIG_EXECUTION_BENCHMARKING
|
||||
b _capture_value_for_benchmarking
|
||||
#endif
|
||||
return_loc:
|
||||
j_s [blink]
|
||||
|
||||
|
||||
.balign 4
|
||||
_switch_return_from_rirq:
|
||||
_switch_return_from_firq:
|
||||
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
/* here need to recover SEC_STAT.IRM bit */
|
||||
pop_s r3
|
||||
sflag r3
|
||||
#endif
|
||||
|
||||
lr r3, [_ARC_V2_AUX_IRQ_ACT]
|
||||
/* use lowest interrupt priority */
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
or r3, r3, (1 << (ARC_N_IRQ_START_LEVEL - 1))
|
||||
#else
|
||||
or r3, r3, (1 << (CONFIG_NUM_IRQ_PRIO_LEVELS - 1))
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARC_NORMAL_FIRMWARE
|
||||
mov_s r0, _ARC_V2_AUX_IRQ_ACT
|
||||
mov_s r1, r3
|
||||
mov_s r6, ARC_S_CALL_AUX_WRITE
|
||||
sjli SJLI_CALL_ARC_SECURE
|
||||
#else
|
||||
sr r3, [_ARC_V2_AUX_IRQ_ACT]
|
||||
#endif
|
||||
rtie
|
||||
|
||||
#ifdef CONFIG_EXECUTION_BENCHMARKING
|
||||
.balign 4
|
||||
_capture_value_for_benchmarking:
|
||||
push_s blink
|
||||
|
||||
bl read_timer_end_of_swap
|
||||
|
||||
pop_s blink
|
||||
b return_loc
|
||||
#endif /* CONFIG_EXECUTION_BENCHMARKING */
|
||||
74
arch/arc/core/sys_fatal_error_handler.c
Normal file
74
arch/arc/core/sys_fatal_error_handler.c
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief ARCv2 system fatal error handler
|
||||
*
|
||||
* This module provides the z_SysFatalErrorHandler() routine for ARCv2 BSPs.
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <kernel_structs.h>
|
||||
#include <misc/printk.h>
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Fatal error handler
|
||||
*
|
||||
* This routine implements the corrective action to be taken when the system
|
||||
* detects a fatal error.
|
||||
*
|
||||
* This sample implementation attempts to abort the current thread and allow
|
||||
* the system to continue executing, which may permit the system to continue
|
||||
* functioning with degraded capabilities.
|
||||
*
|
||||
* System designers may wish to enhance or substitute this sample
|
||||
* implementation to take other actions, such as logging error (or debug)
|
||||
* information to a persistent repository and/or rebooting the system.
|
||||
*
|
||||
* @param reason the fatal error reason
|
||||
* @param pEsf pointer to exception stack frame
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
__weak void z_SysFatalErrorHandler(unsigned int reason,
|
||||
const NANO_ESF *pEsf)
|
||||
{
|
||||
ARG_UNUSED(pEsf);
|
||||
|
||||
#if !defined(CONFIG_SIMPLE_FATAL_ERROR_HANDLER)
|
||||
#if defined(CONFIG_STACK_SENTINEL)
|
||||
if (reason == _NANO_ERR_STACK_CHK_FAIL) {
|
||||
goto hang_system;
|
||||
}
|
||||
#endif
|
||||
if (reason == _NANO_ERR_KERNEL_PANIC) {
|
||||
goto hang_system;
|
||||
}
|
||||
|
||||
if (z_is_thread_essential()) {
|
||||
printk("Fatal fault in essential thread! Spinning...\n");
|
||||
goto hang_system;
|
||||
}
|
||||
|
||||
printk("Fatal fault in thread %p! Aborting.\n", _current);
|
||||
|
||||
k_thread_abort(_current);
|
||||
|
||||
return;
|
||||
|
||||
hang_system:
|
||||
#else
|
||||
ARG_UNUSED(reason);
|
||||
#endif
|
||||
|
||||
for (;;) {
|
||||
k_cpu_idle();
|
||||
}
|
||||
}
|
||||
@@ -12,9 +12,13 @@
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <ksched.h>
|
||||
#include <toolchain.h>
|
||||
#include <kernel_structs.h>
|
||||
#include <offsets_short.h>
|
||||
#include <wait_q.h>
|
||||
#ifdef CONFIG_INIT_STACKS
|
||||
#include <string.h>
|
||||
#endif /* CONFIG_INIT_STACKS */
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
#include <arch/arc/v2/mpu/arc_core_mpu.h>
|
||||
@@ -58,10 +62,10 @@ struct init_stack_frame {
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
|
||||
size_t stackSize, k_thread_entry_t pEntry,
|
||||
void *parameter1, void *parameter2, void *parameter3,
|
||||
int priority, unsigned int options)
|
||||
void z_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
|
||||
size_t stackSize, k_thread_entry_t pEntry,
|
||||
void *parameter1, void *parameter2, void *parameter3,
|
||||
int priority, unsigned int options)
|
||||
{
|
||||
char *pStackMem = Z_THREAD_STACK_BUFFER(stack);
|
||||
Z_ASSERT_VALID_PRIO(priority, pEntry);
|
||||
@@ -70,7 +74,7 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
|
||||
char *stackAdjEnd;
|
||||
struct init_stack_frame *pInitCtx;
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
#if CONFIG_USERSPACE
|
||||
|
||||
size_t stackAdjSize;
|
||||
size_t offset = 0;
|
||||
@@ -83,7 +87,7 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
|
||||
#endif
|
||||
stackEnd = pStackMem + stackAdjSize;
|
||||
|
||||
#ifdef CONFIG_STACK_POINTER_RANDOM
|
||||
#if CONFIG_STACK_POINTER_RANDOM
|
||||
offset = stackAdjSize - stackSize;
|
||||
#endif
|
||||
|
||||
@@ -92,7 +96,7 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
|
||||
(u32_t)(stackEnd + STACK_GUARD_SIZE);
|
||||
|
||||
stackAdjEnd = (char *)STACK_ROUND_DOWN(stackEnd +
|
||||
ARCH_THREAD_STACK_RESERVED);
|
||||
Z_ARCH_THREAD_STACK_RESERVED);
|
||||
|
||||
/* reserve 4 bytes for the start of user sp */
|
||||
stackAdjEnd -= 4;
|
||||
@@ -122,7 +126,7 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
|
||||
*/
|
||||
pStackMem += STACK_GUARD_SIZE;
|
||||
stackAdjSize = stackAdjSize + CONFIG_PRIVILEGED_STACK_SIZE;
|
||||
stackEnd += ARCH_THREAD_STACK_RESERVED;
|
||||
stackEnd += Z_ARCH_THREAD_STACK_RESERVED;
|
||||
|
||||
thread->arch.priv_stack_start = 0;
|
||||
|
||||
@@ -161,7 +165,7 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
|
||||
*/
|
||||
pInitCtx->status32 |= _ARC_V2_STATUS32_US;
|
||||
#else /* For no USERSPACE feature */
|
||||
pStackMem += ARCH_THREAD_STACK_RESERVED;
|
||||
pStackMem += Z_ARCH_THREAD_STACK_RESERVED;
|
||||
stackEnd = pStackMem + stackSize;
|
||||
|
||||
z_new_thread_init(thread, pStackMem, stackSize, priority, options);
|
||||
@@ -176,7 +180,7 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
|
||||
pInitCtx->pc = ((u32_t)z_thread_entry_wrapper);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
pInitCtx->sec_stat = z_arc_v2_aux_reg_read(_ARC_V2_SEC_STAT);
|
||||
#endif
|
||||
|
||||
@@ -187,7 +191,7 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
|
||||
|
||||
/* stack check configuration */
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
pInitCtx->sec_stat |= _ARC_V2_SEC_STAT_SSC;
|
||||
#else
|
||||
pInitCtx->status32 |= _ARC_V2_STATUS32_SC;
|
||||
@@ -199,7 +203,7 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
|
||||
thread->arch.k_stack_top =
|
||||
(u32_t)(stackEnd + STACK_GUARD_SIZE);
|
||||
thread->arch.k_stack_base = (u32_t)
|
||||
(stackEnd + ARCH_THREAD_STACK_RESERVED);
|
||||
(stackEnd + Z_ARCH_THREAD_STACK_RESERVED);
|
||||
} else {
|
||||
thread->arch.k_stack_top = (u32_t)pStackMem;
|
||||
thread->arch.k_stack_base = (u32_t)stackEnd;
|
||||
@@ -211,12 +215,17 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
|
||||
thread->arch.k_stack_base = (u32_t) stackEnd;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARC_USE_UNALIGNED_MEM_ACCESS
|
||||
pInitCtx->status32 |= _ARC_V2_STATUS32_AD;
|
||||
#endif
|
||||
|
||||
thread->switch_handle = thread;
|
||||
/*
|
||||
* seti instruction in the end of the z_swap() will
|
||||
* enable the interrupts based on intlock_key
|
||||
* value.
|
||||
*
|
||||
* intlock_key is constructed based on ARCv2 ISA Programmer's
|
||||
* Reference Manual CLRI instruction description:
|
||||
* dst[31:6] dst[5] dst[4] dst[3:0]
|
||||
* 26'd0 1 STATUS32.IE STATUS32.E[3:0]
|
||||
*/
|
||||
thread->arch.intlock_key = 0x30 | (_ARC_V2_DEF_IRQ_LEVEL & 0xf);
|
||||
thread->arch.relinquish_cause = _CAUSE_COOP;
|
||||
thread->callee_saved.sp =
|
||||
(u32_t)pInitCtx - ___callee_saved_stack_t_SIZEOF;
|
||||
@@ -227,8 +236,8 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
|
||||
FUNC_NORETURN void arch_user_mode_enter(k_thread_entry_t user_entry,
|
||||
void *p1, void *p2, void *p3)
|
||||
FUNC_NORETURN void z_arch_user_mode_enter(k_thread_entry_t user_entry,
|
||||
void *p1, void *p2, void *p3)
|
||||
{
|
||||
|
||||
/*
|
||||
@@ -268,38 +277,3 @@ FUNC_NORETURN void arch_user_mode_enter(k_thread_entry_t user_entry,
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_FLOAT) && defined(CONFIG_FP_SHARING)
|
||||
int arch_float_disable(struct k_thread *thread)
|
||||
{
|
||||
unsigned int key;
|
||||
|
||||
/* Ensure a preemptive context switch does not occur */
|
||||
|
||||
key = irq_lock();
|
||||
|
||||
/* Disable all floating point capabilities for the thread */
|
||||
thread->base.user_options &= ~K_FP_REGS;
|
||||
|
||||
irq_unlock(key);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int arch_float_enable(struct k_thread *thread)
|
||||
{
|
||||
unsigned int key;
|
||||
|
||||
/* Ensure a preemptive context switch does not occur */
|
||||
|
||||
key = irq_lock();
|
||||
|
||||
/* Enable all floating point capabilities for the thread */
|
||||
thread->base.user_options |= K_FP_REGS;
|
||||
|
||||
irq_unlock(key);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_FLOAT && CONFIG_FP_SHARING */
|
||||
|
||||
@@ -13,23 +13,20 @@
|
||||
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <v2/irq.h>
|
||||
|
||||
GTEXT(z_thread_entry_wrapper)
|
||||
GTEXT(z_thread_entry_wrapper1)
|
||||
|
||||
/*
|
||||
* @brief Wrapper for z_thread_entry
|
||||
*
|
||||
* The routine pops parameters for the z_thread_entry from stack frame, prepared
|
||||
* by the arch_new_thread() routine.
|
||||
* by the z_new_thread() routine.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
SECTION_FUNC(TEXT, z_thread_entry_wrapper)
|
||||
seti _ARC_V2_INIT_IRQ_LOCK_KEY
|
||||
z_thread_entry_wrapper1:
|
||||
|
||||
pop_s r3
|
||||
pop_s r2
|
||||
pop_s r1
|
||||
|
||||
@@ -33,7 +33,7 @@ u64_t z_tsc_read(void)
|
||||
t = (u64_t)z_tick_get();
|
||||
count = z_arc_v2_aux_reg_read(_ARC_V2_TMR0_COUNT);
|
||||
irq_unlock(key);
|
||||
t *= k_ticks_to_cyc_floor64(1);
|
||||
t *= (u64_t)sys_clock_hw_cycles_per_tick();
|
||||
t += (u64_t)count;
|
||||
return t;
|
||||
}
|
||||
|
||||
@@ -11,47 +11,46 @@
|
||||
#include <arch/cpu.h>
|
||||
#include <syscall.h>
|
||||
#include <swap_macros.h>
|
||||
#include <v2/irq.h>
|
||||
|
||||
.macro clear_scratch_regs
|
||||
mov_s r1, 0
|
||||
mov_s r2, 0
|
||||
mov_s r3, 0
|
||||
mov_s r4, 0
|
||||
mov_s r5, 0
|
||||
mov_s r6, 0
|
||||
mov_s r7, 0
|
||||
mov_s r8, 0
|
||||
mov_s r9, 0
|
||||
mov_s r10, 0
|
||||
mov_s r11, 0
|
||||
mov_s r12, 0
|
||||
mov r1, 0
|
||||
mov r2, 0
|
||||
mov r3, 0
|
||||
mov r4, 0
|
||||
mov r5, 0
|
||||
mov r6, 0
|
||||
mov r7, 0
|
||||
mov r8, 0
|
||||
mov r9, 0
|
||||
mov r10, 0
|
||||
mov r11, 0
|
||||
mov r12, 0
|
||||
.endm
|
||||
|
||||
.macro clear_callee_regs
|
||||
mov_s r25, 0
|
||||
mov_s r24, 0
|
||||
mov_s r23, 0
|
||||
mov_s r22, 0
|
||||
mov_s r21, 0
|
||||
mov_s r20, 0
|
||||
mov_s r19, 0
|
||||
mov_s r18, 0
|
||||
mov_s r17, 0
|
||||
mov_s r16, 0
|
||||
mov r25, 0
|
||||
mov r24, 0
|
||||
mov r23, 0
|
||||
mov r22, 0
|
||||
mov r21, 0
|
||||
mov r20, 0
|
||||
mov r19, 0
|
||||
mov r18, 0
|
||||
mov r17, 0
|
||||
mov r16, 0
|
||||
|
||||
mov_s r15, 0
|
||||
mov_s r14, 0
|
||||
mov_s r13, 0
|
||||
mov r15, 0
|
||||
mov r14, 0
|
||||
mov r13, 0
|
||||
.endm
|
||||
|
||||
GTEXT(z_arc_userspace_enter)
|
||||
GTEXT(_arc_do_syscall)
|
||||
GTEXT(z_user_thread_entry_wrapper)
|
||||
GTEXT(arch_user_string_nlen)
|
||||
GTEXT(z_arc_user_string_nlen_fault_start)
|
||||
GTEXT(z_arc_user_string_nlen_fault_end)
|
||||
GTEXT(z_arc_user_string_nlen_fixup)
|
||||
GTEXT(z_arch_user_string_nlen)
|
||||
GTEXT(z_arch_user_string_nlen_fault_start)
|
||||
GTEXT(z_arch_user_string_nlen_fault_end)
|
||||
GTEXT(z_arch_user_string_nlen_fixup)
|
||||
/*
|
||||
* @brief Wrapper for z_thread_entry in the case of user thread
|
||||
* The init parameters are in privileged stack
|
||||
@@ -59,7 +58,6 @@ GTEXT(z_arc_user_string_nlen_fixup)
|
||||
* @return N/A
|
||||
*/
|
||||
SECTION_FUNC(TEXT, z_user_thread_entry_wrapper)
|
||||
seti _ARC_V2_INIT_IRQ_LOCK_KEY
|
||||
pop_s r3
|
||||
pop_s r2
|
||||
pop_s r1
|
||||
@@ -67,7 +65,7 @@ SECTION_FUNC(TEXT, z_user_thread_entry_wrapper)
|
||||
/* the start of user sp is in r5 */
|
||||
pop r5
|
||||
/* start of privilege stack in blink */
|
||||
mov_s blink, sp
|
||||
mov blink, sp
|
||||
|
||||
st.aw r0, [r5, -4]
|
||||
st.aw r1, [r5, -4]
|
||||
@@ -95,10 +93,12 @@ SECTION_FUNC(TEXT, z_arc_userspace_enter)
|
||||
*/
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
/* disable stack checking as the stack should be initialized */
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
lr blink, [_ARC_V2_SEC_STAT]
|
||||
bclr blink, blink, _ARC_V2_SEC_STAT_SSC_BIT
|
||||
sflag blink
|
||||
/* sflag blink */
|
||||
/* sflag instruction is not supported in current ARC GNU */
|
||||
.long 0x07ff302f
|
||||
#else
|
||||
lr blink, [_ARC_V2_STATUS32]
|
||||
bclr blink, blink, _ARC_V2_STATUS32_SC_BIT
|
||||
@@ -109,7 +109,7 @@ SECTION_FUNC(TEXT, z_arc_userspace_enter)
|
||||
add r5, r4, r5
|
||||
/* start of privilege stack */
|
||||
add blink, r5, CONFIG_PRIVILEGED_STACK_SIZE+STACK_GUARD_SIZE
|
||||
mov_s sp, r5
|
||||
mov sp, r5
|
||||
|
||||
push_s r0
|
||||
push_s r1
|
||||
@@ -119,9 +119,9 @@ SECTION_FUNC(TEXT, z_arc_userspace_enter)
|
||||
mov r5, sp /* skip r0, r1, r2, r3 */
|
||||
|
||||
#ifdef CONFIG_INIT_STACKS
|
||||
mov_s r0, 0xaaaaaaaa
|
||||
mov r0, 0xaaaaaaaa
|
||||
#else
|
||||
mov_s r0, 0x0
|
||||
mov r0, 0x0
|
||||
#endif
|
||||
_clear_user_stack:
|
||||
st.ab r0, [r4, 4]
|
||||
@@ -129,15 +129,17 @@ _clear_user_stack:
|
||||
jlt _clear_user_stack
|
||||
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
mov_s r1, _kernel
|
||||
mov r1, _kernel
|
||||
ld_s r2, [r1, _kernel_offset_to_current]
|
||||
|
||||
_load_stack_check_regs
|
||||
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
lr r0, [_ARC_V2_SEC_STAT]
|
||||
bset r0, r0, _ARC_V2_SEC_STAT_SSC_BIT
|
||||
sflag r0
|
||||
/* sflag r0 */
|
||||
/* sflag instruction is not supported in current ARC GNU */
|
||||
.long 0x003f302f
|
||||
#else
|
||||
lr r0, [_ARC_V2_STATUS32]
|
||||
bset r0, r0, _ARC_V2_STATUS32_SC_BIT
|
||||
@@ -149,40 +151,38 @@ _arc_go_to_user_space:
|
||||
lr r0, [_ARC_V2_STATUS32]
|
||||
bset r0, r0, _ARC_V2_STATUS32_U_BIT
|
||||
|
||||
mov_s r1, z_thread_entry_wrapper1
|
||||
mov r1, z_thread_entry_wrapper
|
||||
|
||||
/* fake exception return */
|
||||
kflag _ARC_V2_STATUS32_AE
|
||||
|
||||
sr r0, [_ARC_V2_ERSTATUS]
|
||||
sr r1, [_ARC_V2_ERET]
|
||||
|
||||
/* fake exception return */
|
||||
lr r0, [_ARC_V2_STATUS32]
|
||||
bclr r0, r0, _ARC_V2_STATUS32_AE_BIT
|
||||
kflag r0
|
||||
|
||||
/* when exception returns from kernel to user, sp and _ARC_V2_USER_SP
|
||||
* /_ARC_V2_SECU_SP will be switched
|
||||
*/
|
||||
#if defined(CONFIG_ARC_HAS_SECURE) && defined(CONFIG_ARC_SECURE_FIRMWARE)
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
lr r0, [_ARC_V2_SEC_STAT]
|
||||
/* the mode returns from exception return is secure mode */
|
||||
bset r0, r0, 31
|
||||
sr r0, [_ARC_V2_ERSEC_STAT]
|
||||
sr r5, [_ARC_V2_SEC_U_SP]
|
||||
#else
|
||||
/* when exception returns from kernel to user, sp and _ARC_V2_USER_SP
|
||||
* will be switched
|
||||
*/
|
||||
sr r5, [_ARC_V2_USER_SP]
|
||||
#endif
|
||||
mov_s sp, blink
|
||||
mov sp, blink
|
||||
|
||||
mov_s r0, 0
|
||||
mov r0, 0
|
||||
|
||||
clear_callee_regs
|
||||
|
||||
clear_scratch_regs
|
||||
|
||||
mov_s fp, 0
|
||||
mov_s r29, 0
|
||||
mov_s r30, 0
|
||||
mov_s blink, 0
|
||||
mov fp, 0
|
||||
mov r29, 0
|
||||
mov r30, 0
|
||||
mov blink, 0
|
||||
|
||||
#ifdef CONFIG_EXECUTION_BENCHMARKING
|
||||
b _capture_value_for_benchmarking_userspace
|
||||
@@ -202,55 +202,48 @@ return_loc_userspace_enter:
|
||||
*
|
||||
*/
|
||||
SECTION_FUNC(TEXT, _arc_do_syscall)
|
||||
/*
|
||||
* r0-r5: arg1-arg6, r6 is call id which is already checked in
|
||||
* trap_s handler, r7 is the system call stack frame pointer
|
||||
* need to recover r0, r1, r2 because they will be modified in
|
||||
* _create_irq_stack_frame. If a specific syscall frame (different
|
||||
* with irq stack frame) is defined, the cover of r0, r1, r2 can be
|
||||
* optimized.
|
||||
*/
|
||||
ld_s r0, [sp, ___isf_t_r0_OFFSET]
|
||||
ld_s r1, [sp, ___isf_t_r1_OFFSET]
|
||||
ld_s r2, [sp, ___isf_t_r2_OFFSET]
|
||||
/* r0-r5: arg1-arg6, r6 is call id */
|
||||
/* the call id is already checked in trap_s handler */
|
||||
push_s blink
|
||||
|
||||
mov r7, sp
|
||||
|
||||
mov_s blink, _k_syscall_table
|
||||
mov blink, _k_syscall_table
|
||||
ld.as r6, [blink, r6]
|
||||
|
||||
jl [r6]
|
||||
|
||||
/* save return value */
|
||||
st_s r0, [sp, ___isf_t_r0_OFFSET]
|
||||
/*
|
||||
* no need to clear callee regs, as they will be saved and restored
|
||||
* automatically
|
||||
*/
|
||||
clear_scratch_regs
|
||||
|
||||
mov_s r29, 0
|
||||
mov_s r30, 0
|
||||
mov r29, 0
|
||||
mov r30, 0
|
||||
|
||||
pop_s blink
|
||||
|
||||
/* through fake exception return, go back to the caller */
|
||||
lr r0, [_ARC_V2_STATUS32]
|
||||
bset r0, r0, _ARC_V2_STATUS32_AE_BIT
|
||||
kflag r0
|
||||
kflag _ARC_V2_STATUS32_AE
|
||||
|
||||
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
ld_s r0, [sp, ___isf_t_sec_stat_OFFSET]
|
||||
sr r0,[_ARC_V2_ERSEC_STAT]
|
||||
/* the status and return address are saved in trap_s handler */
|
||||
pop r6
|
||||
sr r6, [_ARC_V2_ERSTATUS]
|
||||
pop r6
|
||||
sr r6, [_ARC_V2_ERET]
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
pop r6
|
||||
sr r6, [_ARC_V2_ERSEC_STAT]
|
||||
#endif
|
||||
ld_s r0, [sp, ___isf_t_status32_OFFSET]
|
||||
sr r0,[_ARC_V2_ERSTATUS]
|
||||
|
||||
ld_s r0, [sp, ___isf_t_pc_OFFSET] /* eret into pc */
|
||||
sr r0,[_ARC_V2_ERET]
|
||||
|
||||
_pop_irq_stack_frame
|
||||
mov r6, 0
|
||||
|
||||
rtie
|
||||
|
||||
|
||||
/*
|
||||
* size_t arch_user_string_nlen(const char *s, size_t maxsize, int *err_arg)
|
||||
* size_t z_arch_user_string_nlen(const char *s, size_t maxsize, int *err_arg)
|
||||
*/
|
||||
SECTION_FUNC(TEXT, arch_user_string_nlen)
|
||||
SECTION_FUNC(TEXT, z_arch_user_string_nlen)
|
||||
/* int err; */
|
||||
sub_s sp,sp,0x4
|
||||
|
||||
@@ -269,11 +262,11 @@ SECTION_FUNC(TEXT, arch_user_string_nlen)
|
||||
mov lp_count, r1
|
||||
|
||||
strlen_loop:
|
||||
z_arc_user_string_nlen_fault_start:
|
||||
z_arch_user_string_nlen_fault_start:
|
||||
/* is the byte at ++r12 a NULL? if so, we're done. Might fault! */
|
||||
ldb.aw r1, [r12, 1]
|
||||
|
||||
z_arc_user_string_nlen_fault_end:
|
||||
z_arch_user_string_nlen_fault_end:
|
||||
brne_s r1, 0, not_null
|
||||
|
||||
strlen_done:
|
||||
@@ -281,7 +274,7 @@ strlen_done:
|
||||
mov_s r1, 0
|
||||
st_s r1, [sp, 0]
|
||||
|
||||
z_arc_user_string_nlen_fixup:
|
||||
z_arch_user_string_nlen_fixup:
|
||||
/* *err_arg = err; Pop stack and return */
|
||||
ld_s r1, [sp, 0]
|
||||
add_s sp, sp, 4
|
||||
|
||||
@@ -20,21 +20,25 @@
|
||||
#ifndef ZEPHYR_ARCH_ARC_INCLUDE_KERNEL_ARCH_DATA_H_
|
||||
#define ZEPHYR_ARCH_ARC_INCLUDE_KERNEL_ARCH_DATA_H_
|
||||
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <vector_table.h>
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
#include <kernel.h>
|
||||
#include <zephyr/types.h>
|
||||
#include <sys/util.h>
|
||||
#include <sys/dlist.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <vector_table.h>
|
||||
#include <kernel_arch_thread.h>
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
#include <kernel.h>
|
||||
#include <kernel_internal.h>
|
||||
#include <zephyr/types.h>
|
||||
#include <misc/util.h>
|
||||
#include <misc/dlist.h>
|
||||
#endif
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
struct _irq_stack_frame {
|
||||
u32_t lp_end;
|
||||
@@ -137,13 +141,9 @@ struct _callee_saved_stack {
|
||||
/* r28 is the stack pointer and saved separately */
|
||||
/* r29 is ILINK and does not need to be saved */
|
||||
u32_t r30;
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_ACCL_REGS
|
||||
#ifdef CONFIG_FP_SHARING
|
||||
u32_t r58;
|
||||
u32_t r59;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FP_SHARING
|
||||
u32_t fpu_status;
|
||||
u32_t fpu_ctrl;
|
||||
#ifdef CONFIG_FP_FPU_DA
|
||||
@@ -162,9 +162,18 @@ struct _callee_saved_stack {
|
||||
|
||||
typedef struct _callee_saved_stack _callee_saved_stack_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
struct _kernel_arch {
|
||||
|
||||
char *rirq_sp; /* regular IRQ stack pointer base */
|
||||
|
||||
/*
|
||||
* FIRQ stack pointer is installed once in the second bank's SP, so
|
||||
* there is no need to track it in _kernel.
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
typedef struct _kernel_arch _kernel_arch_t;
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
@@ -175,5 +184,8 @@ typedef struct _callee_saved_stack _callee_saved_stack_t;
|
||||
#define STACK_ROUND_UP(x) ROUND_UP(x, STACK_ALIGN_SIZE)
|
||||
#define STACK_ROUND_DOWN(x) ROUND_DOWN(x, STACK_ALIGN_SIZE)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZEPHYR_ARCH_ARC_INCLUDE_KERNEL_ARCH_DATA_H_ */
|
||||
|
||||
@@ -20,26 +20,27 @@
|
||||
#ifndef ZEPHYR_ARCH_ARC_INCLUDE_KERNEL_ARCH_FUNC_H_
|
||||
#define ZEPHYR_ARCH_ARC_INCLUDE_KERNEL_ARCH_FUNC_H_
|
||||
|
||||
#if !defined(_ASMLANGUAGE)
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <kernel_arch_data.h>
|
||||
#if !defined(_ASMLANGUAGE)
|
||||
|
||||
#ifdef CONFIG_CPU_ARCV2
|
||||
#include <v2/cache.h>
|
||||
#include <v2/irq.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static ALWAYS_INLINE void arch_kernel_init(void)
|
||||
static ALWAYS_INLINE void kernel_arch_init(void)
|
||||
{
|
||||
z_irq_setup();
|
||||
_current_cpu->irq_stack =
|
||||
Z_THREAD_STACK_BUFFER(_interrupt_stack) + CONFIG_ISR_STACK_SIZE;
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE void
|
||||
z_set_thread_return_value(struct k_thread *thread, unsigned int value)
|
||||
{
|
||||
thread->arch.return_value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -55,10 +56,7 @@ static ALWAYS_INLINE int Z_INTERRUPT_CAUSE(void)
|
||||
return irq_num;
|
||||
}
|
||||
|
||||
static inline bool arch_is_in_isr(void)
|
||||
{
|
||||
return z_arc_v2_irq_unit_is_in_isr();
|
||||
}
|
||||
#define z_is_in_isr z_arc_v2_irq_unit_is_in_isr
|
||||
|
||||
extern void z_thread_entry_wrapper(void);
|
||||
extern void z_user_thread_entry_wrapper(void);
|
||||
@@ -66,16 +64,10 @@ extern void z_user_thread_entry_wrapper(void);
|
||||
extern void z_arc_userspace_enter(k_thread_entry_t user_entry, void *p1,
|
||||
void *p2, void *p3, u32_t stack, u32_t size);
|
||||
|
||||
|
||||
extern void arch_switch(void *switch_to, void **switched_from);
|
||||
extern void z_arc_fatal_error(unsigned int reason, const z_arch_esf_t *esf);
|
||||
|
||||
extern void arch_sched_ipi(void);
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#endif /* ZEPHYR_ARCH_ARC_INCLUDE_KERNEL_ARCH_FUNC_H_ */
|
||||
|
||||
81
arch/arc/include/kernel_arch_thread.h
Normal file
81
arch/arc/include/kernel_arch_thread.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Per-arch thread definition
|
||||
*
|
||||
* This file contains definitions for
|
||||
*
|
||||
* struct _thread_arch
|
||||
* struct _callee_saved
|
||||
* struct _caller_saved
|
||||
*
|
||||
* necessary to instantiate instances of struct k_thread.
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_ARCH_ARC_INCLUDE_KERNEL_ARCH_THREAD_H_
|
||||
#define ZEPHYR_ARCH_ARC_INCLUDE_KERNEL_ARCH_THREAD_H_
|
||||
|
||||
/*
|
||||
* Reason a thread has relinquished control: threads can only be in the NONE
|
||||
* or COOP state, threads can be one in the four.
|
||||
*/
|
||||
#define _CAUSE_NONE 0
|
||||
#define _CAUSE_COOP 1
|
||||
#define _CAUSE_RIRQ 2
|
||||
#define _CAUSE_FIRQ 3
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
#include <zephyr/types.h>
|
||||
|
||||
struct _caller_saved {
|
||||
/*
|
||||
* Saved on the stack as part of handling a regular IRQ or by the
|
||||
* kernel when calling the FIRQ return code.
|
||||
*/
|
||||
};
|
||||
|
||||
typedef struct _caller_saved _caller_saved_t;
|
||||
|
||||
struct _callee_saved {
|
||||
u32_t sp; /* r28 */
|
||||
};
|
||||
typedef struct _callee_saved _callee_saved_t;
|
||||
|
||||
struct _thread_arch {
|
||||
|
||||
/* interrupt key when relinquishing control */
|
||||
u32_t intlock_key;
|
||||
|
||||
/* one of the _CAUSE_xxxx definitions above */
|
||||
int relinquish_cause;
|
||||
|
||||
/* return value from z_swap */
|
||||
unsigned int return_value;
|
||||
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
/* High address of stack region, stack grows downward from this
|
||||
* location. Usesd for hardware stack checking
|
||||
*/
|
||||
u32_t k_stack_base;
|
||||
u32_t k_stack_top;
|
||||
#ifdef CONFIG_USERSPACE
|
||||
u32_t u_stack_base;
|
||||
u32_t u_stack_top;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
u32_t priv_stack_start;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct _thread_arch _thread_arch_t;
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#endif /* ZEPHYR_ARCH_ARC_INCLUDE_KERNEL_ARCH_THREAD_H_ */
|
||||
@@ -17,9 +17,15 @@
|
||||
|
||||
/* threads */
|
||||
|
||||
#define _thread_offset_to_intlock_key \
|
||||
(___thread_t_arch_OFFSET + ___thread_arch_t_intlock_key_OFFSET)
|
||||
|
||||
#define _thread_offset_to_relinquish_cause \
|
||||
(___thread_t_arch_OFFSET + ___thread_arch_t_relinquish_cause_OFFSET)
|
||||
|
||||
#define _thread_offset_to_return_value \
|
||||
(___thread_t_arch_OFFSET + ___thread_arch_t_return_value_OFFSET)
|
||||
|
||||
#define _thread_offset_to_k_stack_base \
|
||||
(___thread_t_arch_OFFSET + ___thread_arch_t_k_stack_base_OFFSET)
|
||||
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
#include <toolchain.h>
|
||||
#include <arch/cpu.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _ASMLANGUAGE
|
||||
|
||||
/* entering this macro, current is in r2 */
|
||||
@@ -40,33 +44,20 @@
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
lr r13, [_ARC_V2_SEC_U_SP]
|
||||
st_s r13, [sp, ___callee_saved_stack_t_user_sp_OFFSET]
|
||||
st r13, [sp, ___callee_saved_stack_t_user_sp_OFFSET]
|
||||
lr r13, [_ARC_V2_SEC_K_SP]
|
||||
st_s r13, [sp, ___callee_saved_stack_t_kernel_sp_OFFSET]
|
||||
st r13, [sp, ___callee_saved_stack_t_kernel_sp_OFFSET]
|
||||
#else
|
||||
lr r13, [_ARC_V2_USER_SP]
|
||||
st_s r13, [sp, ___callee_saved_stack_t_user_sp_OFFSET]
|
||||
lr r13, [_ARC_V2_KERNEL_SP]
|
||||
st_s r13, [sp, ___callee_saved_stack_t_kernel_sp_OFFSET]
|
||||
#endif /* CONFIG_ARC_SECURE_FIRMWARE */
|
||||
#else
|
||||
lr r13, [_ARC_V2_USER_SP]
|
||||
st_s r13, [sp, ___callee_saved_stack_t_user_sp_OFFSET]
|
||||
st r13, [sp, ___callee_saved_stack_t_user_sp_OFFSET]
|
||||
#endif
|
||||
#endif
|
||||
st r30, [sp, ___callee_saved_stack_t_r30_OFFSET]
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_ACCL_REGS
|
||||
#ifdef CONFIG_FP_SHARING
|
||||
st r58, [sp, ___callee_saved_stack_t_r58_OFFSET]
|
||||
st r59, [sp, ___callee_saved_stack_t_r59_OFFSET]
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FP_SHARING
|
||||
ld_s r13, [r2, ___thread_base_t_user_options_OFFSET]
|
||||
/* K_FP_REGS is bit 1 */
|
||||
bbit0 r13, 1, 1f
|
||||
lr r13, [_ARC_V2_FPU_STATUS]
|
||||
st_s r13, [sp, ___callee_saved_stack_t_fpu_status_OFFSET]
|
||||
lr r13, [_ARC_V2_FPU_CTRL]
|
||||
@@ -82,7 +73,7 @@
|
||||
lr r13, [_ARC_V2_FPU_DPFP2H]
|
||||
st_s r13, [sp, ___callee_saved_stack_t_dpfp2h_OFFSET]
|
||||
#endif
|
||||
1 :
|
||||
|
||||
#endif
|
||||
|
||||
/* save stack pointer in struct k_thread */
|
||||
@@ -94,15 +85,9 @@
|
||||
/* restore stack pointer from struct k_thread */
|
||||
ld sp, [r2, _thread_offset_to_sp]
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_ACCL_REGS
|
||||
#ifdef CONFIG_FP_SHARING
|
||||
ld r58, [sp, ___callee_saved_stack_t_r58_OFFSET]
|
||||
ld r59, [sp, ___callee_saved_stack_t_r59_OFFSET]
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FP_SHARING
|
||||
ld_s r13, [r2, ___thread_base_t_user_options_OFFSET]
|
||||
/* K_FP_REGS is bit 1 */
|
||||
bbit0 r13, 1, 2f
|
||||
|
||||
ld_s r13, [sp, ___callee_saved_stack_t_fpu_status_OFFSET]
|
||||
sr r13, [_ARC_V2_FPU_STATUS]
|
||||
@@ -119,22 +104,15 @@
|
||||
ld_s r13, [sp, ___callee_saved_stack_t_dpfp2h_OFFSET]
|
||||
sr r13, [_ARC_V2_FPU_DPFP2H]
|
||||
#endif
|
||||
2 :
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
ld_s r13, [sp, ___callee_saved_stack_t_user_sp_OFFSET]
|
||||
ld r13, [sp, ___callee_saved_stack_t_user_sp_OFFSET]
|
||||
sr r13, [_ARC_V2_SEC_U_SP]
|
||||
ld_s r13, [sp, ___callee_saved_stack_t_kernel_sp_OFFSET]
|
||||
ld r13, [sp, ___callee_saved_stack_t_kernel_sp_OFFSET]
|
||||
sr r13, [_ARC_V2_SEC_K_SP]
|
||||
#else
|
||||
ld_s r13, [sp, ___callee_saved_stack_t_user_sp_OFFSET]
|
||||
sr r13, [_ARC_V2_USER_SP]
|
||||
ld_s r13, [sp, ___callee_saved_stack_t_kernel_sp_OFFSET]
|
||||
sr r13, [_ARC_V2_KERNEL_SP]
|
||||
#endif /* CONFIG_ARC_SECURE_FIRMWARE */
|
||||
#else
|
||||
ld_s r13, [sp, ___callee_saved_stack_t_user_sp_OFFSET]
|
||||
sr r13, [_ARC_V2_USER_SP]
|
||||
@@ -258,7 +236,7 @@
|
||||
* The pc and status32 values will still be on the stack. We cannot
|
||||
* pop them yet because the callers of _pop_irq_stack_frame must reload
|
||||
* status32 differently depending on the execution context they are
|
||||
* running in (arch_switch(), firq or exception).
|
||||
* running in (z_swap(), firq or exception).
|
||||
*/
|
||||
add_s sp, sp, ___isf_t_SIZEOF
|
||||
|
||||
@@ -269,7 +247,7 @@
|
||||
* _kernel.current. r3 is a scratch reg.
|
||||
*/
|
||||
.macro _load_stack_check_regs
|
||||
#if defined(CONFIG_ARC_SECURE_FIRMWARE)
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
ld r3, [r2, _thread_offset_to_k_stack_base]
|
||||
sr r3, [_ARC_V2_S_KSTACK_BASE]
|
||||
ld r3, [r2, _thread_offset_to_k_stack_top]
|
||||
@@ -291,92 +269,13 @@
|
||||
ld r3, [r2, _thread_offset_to_u_stack_top]
|
||||
sr r3, [_ARC_V2_USTACK_TOP]
|
||||
#endif
|
||||
#endif /* CONFIG_ARC_SECURE_FIRMWARE */
|
||||
.endm
|
||||
|
||||
/* check and increase the interrupt nest counter
|
||||
* after increase, check whether nest counter == 1
|
||||
* the result will be EQ bit of status32
|
||||
*/
|
||||
.macro _check_and_inc_int_nest_counter reg1 reg2
|
||||
#ifdef CONFIG_SMP
|
||||
_get_cpu_id \reg1
|
||||
ld.as \reg1, [@_curr_cpu, \reg1]
|
||||
ld \reg2, [\reg1, ___cpu_t_nested_OFFSET]
|
||||
#else
|
||||
mov \reg1, _kernel
|
||||
ld \reg2, [\reg1, ___kernel_t_nested_OFFSET]
|
||||
#endif
|
||||
add \reg2, \reg2, 1
|
||||
#ifdef CONFIG_SMP
|
||||
st \reg2, [\reg1, ___cpu_t_nested_OFFSET]
|
||||
#else
|
||||
st \reg2, [\reg1, ___kernel_t_nested_OFFSET]
|
||||
#endif
|
||||
cmp \reg2, 1
|
||||
.endm
|
||||
|
||||
/* decrease interrupt nest counter */
|
||||
.macro _dec_int_nest_counter reg1 reg2
|
||||
#ifdef CONFIG_SMP
|
||||
_get_cpu_id \reg1
|
||||
ld.as \reg1, [@_curr_cpu, \reg1]
|
||||
ld \reg2, [\reg1, ___cpu_t_nested_OFFSET]
|
||||
#else
|
||||
mov \reg1, _kernel
|
||||
ld \reg2, [\reg1, ___kernel_t_nested_OFFSET]
|
||||
#endif
|
||||
sub \reg2, \reg2, 1
|
||||
#ifdef CONFIG_SMP
|
||||
st \reg2, [\reg1, ___cpu_t_nested_OFFSET]
|
||||
#else
|
||||
st \reg2, [\reg1, ___kernel_t_nested_OFFSET]
|
||||
#endif
|
||||
.endm
|
||||
|
||||
/* If multi bits in IRQ_ACT are set, i.e. last bit != fist bit, it's
|
||||
* in nest interrupt. The result will be EQ bit of status32
|
||||
*/
|
||||
.macro _check_nest_int_by_irq_act reg1, reg2
|
||||
lr \reg1, [_ARC_V2_AUX_IRQ_ACT]
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
and \reg1, \reg1, ((1 << ARC_N_IRQ_START_LEVEL) - 1)
|
||||
#else
|
||||
and \reg1, \reg1, 0xffff
|
||||
#endif
|
||||
ffs \reg2, \reg1
|
||||
fls \reg1, \reg1
|
||||
cmp \reg1, \reg2
|
||||
.endm
|
||||
|
||||
.macro _get_cpu_id reg
|
||||
lr \reg, [_ARC_V2_IDENTITY]
|
||||
xbfu \reg, \reg, 0xe8
|
||||
.endm
|
||||
|
||||
.macro _get_curr_cpu_irq_stack irq_sp
|
||||
#ifdef CONFIG_SMP
|
||||
_get_cpu_id \irq_sp
|
||||
ld.as \irq_sp, [@_curr_cpu, \irq_sp]
|
||||
ld \irq_sp, [\irq_sp, ___cpu_t_irq_stack_OFFSET]
|
||||
#else
|
||||
mov \irq_sp, _kernel
|
||||
ld \irq_sp, [\irq_sp, _kernel_offset_to_irq_stack]
|
||||
#endif
|
||||
.endm
|
||||
|
||||
/* macro to push aux reg through reg */
|
||||
.macro PUSHAX reg aux
|
||||
lr \reg, [\aux]
|
||||
st.a \reg, [sp, -4]
|
||||
.endm
|
||||
|
||||
/* macro to pop aux reg through reg */
|
||||
.macro POPAX reg aux
|
||||
ld.ab \reg, [sp, 4]
|
||||
sr \reg, [\aux]
|
||||
#endif /* CONFIG_ARC_HAS_SECURE */
|
||||
.endm
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZEPHYR_ARCH_ARC_INCLUDE_SWAP_MACROS_H_ */
|
||||
|
||||
36
arch/arc/include/tracing_arch.h
Normal file
36
arch/arc/include/tracing_arch.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Kernel event logger support for ARM
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_ARCH_ARC_INCLUDE_TRACING_ARCH_H_
|
||||
#define ZEPHYR_ARCH_ARC_INCLUDE_TRACING_ARCH_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Get the identification of the current interrupt.
|
||||
*
|
||||
* This routine obtain the key of the interrupt that is currently processed
|
||||
* if it is called from a ISR context.
|
||||
*
|
||||
* @return The key of the interrupt that is currently being processed.
|
||||
*/
|
||||
int z_sys_current_irq_key_get(void)
|
||||
{
|
||||
return Z_INTERRUPT_CAUSE();
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZEPHYR_ARCH_ARC_INCLUDE_TRACING_ARCH_H_ */
|
||||
@@ -17,12 +17,12 @@
|
||||
|
||||
#include <arch/cpu.h>
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
|
||||
/* i-cache defines for IC_CTRL register */
|
||||
#define IC_CACHE_ENABLE 0x00
|
||||
#define IC_CACHE_DISABLE 0x01
|
||||
@@ -50,10 +50,10 @@ static ALWAYS_INLINE void z_icache_setup(void)
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#endif /* ZEPHYR_ARCH_ARC_INCLUDE_V2_CACHE_H_ */
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
#ifndef ZEPHYR_ARCH_ARC_INCLUDE_V2_IRQ_H_
|
||||
#define ZEPHYR_ARCH_ARC_INCLUDE_V2_IRQ_H_
|
||||
|
||||
#include <arch/cpu.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -30,21 +28,9 @@ extern "C" {
|
||||
#define _ARC_V2_AUX_IRQ_CTRL_32_REGS 16
|
||||
|
||||
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
#define _ARC_V2_DEF_IRQ_LEVEL (ARC_N_IRQ_START_LEVEL - 1)
|
||||
#else
|
||||
#define _ARC_V2_DEF_IRQ_LEVEL (CONFIG_NUM_IRQ_PRIO_LEVELS - 1)
|
||||
#endif
|
||||
|
||||
#define _ARC_V2_DEF_IRQ_LEVEL (CONFIG_NUM_IRQ_PRIO_LEVELS-1)
|
||||
#define _ARC_V2_WAKE_IRQ_LEVEL _ARC_V2_DEF_IRQ_LEVEL
|
||||
|
||||
/*
|
||||
* INIT_IRQ_LOCK_KEY is init interrupt level setting of a thread.
|
||||
* It's configured by seti instruction when a thread starts to run
|
||||
*, i.e., z_thread_entry_wrapper and z_user_thread_entry_wrapper
|
||||
*/
|
||||
#define _ARC_V2_INIT_IRQ_LOCK_KEY (0x10 | _ARC_V2_DEF_IRQ_LEVEL)
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
|
||||
extern K_THREAD_STACK_DEFINE(_interrupt_stack, CONFIG_ISR_STACK_SIZE);
|
||||
@@ -65,14 +51,11 @@ static ALWAYS_INLINE void z_irq_setup(void)
|
||||
_ARC_V2_AUX_IRQ_CTRL_14_REGS /* save r0 -> r13 (caller-saved) */
|
||||
);
|
||||
|
||||
z_arc_cpu_sleep_mode = _ARC_V2_WAKE_IRQ_LEVEL;
|
||||
|
||||
#ifdef CONFIG_ARC_NORMAL_FIRMWARE
|
||||
/* normal mode cannot write irq_ctrl, ignore it */
|
||||
aux_irq_ctrl_value = aux_irq_ctrl_value;
|
||||
#else
|
||||
k_cpu_sleep_mode = _ARC_V2_WAKE_IRQ_LEVEL;
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_AUX_IRQ_CTRL, aux_irq_ctrl_value);
|
||||
#endif
|
||||
|
||||
_kernel.irq_stack =
|
||||
Z_THREAD_STACK_BUFFER(_interrupt_stack) + CONFIG_ISR_STACK_SIZE;
|
||||
}
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
#ifndef ZEPHYR_ARCH_ARC_INCLUDE_VECTOR_TABLE_H_
|
||||
#define ZEPHYR_ARCH_ARC_INCLUDE_VECTOR_TABLE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define EXC_EV_TRAP 0x9
|
||||
|
||||
#ifdef _ASMLANGUAGE
|
||||
@@ -51,10 +55,6 @@ GTEXT(_isr_wrapper)
|
||||
|
||||
#else
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void __reset(void);
|
||||
extern void __memory_error(void);
|
||||
extern void __instruction_error(void);
|
||||
@@ -70,10 +70,10 @@ extern void __ev_div_zero(void);
|
||||
extern void __ev_dc_error(void);
|
||||
extern void __ev_maligned(void);
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#endif /* ZEPHYR_ARCH_ARC_INCLUDE_VECTOR_TABLE_H_ */
|
||||
|
||||
@@ -7,7 +7,6 @@ set(ARCH_FOR_cortex-m4 armv7e-m )
|
||||
set(ARCH_FOR_cortex-m23 armv8-m.base )
|
||||
set(ARCH_FOR_cortex-m33 armv8-m.main+dsp)
|
||||
set(ARCH_FOR_cortex-m33+nodsp armv8-m.main )
|
||||
set(ARCH_FOR_cortex-r4 armv7-r )
|
||||
|
||||
if(ARCH_FOR_${GCC_M_CPU})
|
||||
set(ARCH_FLAG -march=${ARCH_FOR_${GCC_M_CPU}})
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
# ARM architecture configuration options
|
||||
# Kconfig - ARM architecture configuration options
|
||||
|
||||
#
|
||||
# Copyright (c) 2014-2015 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
|
||||
menu "ARM Options"
|
||||
depends on ARM
|
||||
|
||||
@@ -2,22 +2,25 @@
|
||||
|
||||
zephyr_library()
|
||||
|
||||
if (CONFIG_COVERAGE)
|
||||
toolchain_cc_coverage()
|
||||
endif ()
|
||||
zephyr_compile_options_ifdef(CONFIG_COVERAGE_GCOV
|
||||
-ftest-coverage
|
||||
-fprofile-arcs
|
||||
-fno-inline
|
||||
)
|
||||
|
||||
zephyr_library_sources(
|
||||
exc_exit.S
|
||||
irq_init.c
|
||||
swap.c
|
||||
swap_helper.S
|
||||
fault.c
|
||||
irq_manage.c
|
||||
thread.c
|
||||
cpu_idle.S
|
||||
fault_s.S
|
||||
fatal.c
|
||||
nmi.c
|
||||
nmi_on_reset.S
|
||||
prep_c.c
|
||||
sys_fatal_error_handler.c
|
||||
thread_abort.c
|
||||
)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_GEN_SW_ISR_TABLE isr_wrapper.S)
|
||||
@@ -30,6 +33,3 @@ add_subdirectory_ifdef(CONFIG_CPU_CORTEX_M cortex_m)
|
||||
add_subdirectory_ifdef(CONFIG_ARM_MPU cortex_m/mpu)
|
||||
add_subdirectory_ifdef(CONFIG_CPU_CORTEX_M_HAS_CMSE cortex_m/cmse)
|
||||
add_subdirectory_ifdef(CONFIG_ARM_SECURE_FIRMWARE cortex_m/tz)
|
||||
add_subdirectory_ifdef(CONFIG_ARM_NONSECURE_FIRMWARE cortex_m/tz)
|
||||
|
||||
add_subdirectory_ifdef(CONFIG_CPU_CORTEX_R cortex_r)
|
||||
|
||||
@@ -1,120 +1,38 @@
|
||||
# ARM core configuration options
|
||||
# Kconfig - ARM core configuration options
|
||||
|
||||
#
|
||||
# Copyright (c) 2015 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
config CPU_CORTEX
|
||||
bool
|
||||
# Omit prompt to signify "hidden" option
|
||||
help
|
||||
This option signifies the use of a CPU of the Cortex family.
|
||||
|
||||
config CPU_CORTEX_M
|
||||
bool
|
||||
# Omit prompt to signify "hidden" option
|
||||
select CPU_CORTEX
|
||||
select ARCH_HAS_CUSTOM_SWAP_TO_MAIN
|
||||
select HAS_CMSIS_CORE
|
||||
select HAS_CMSIS
|
||||
select HAS_FLASH_LOAD_OFFSET
|
||||
select ARCH_HAS_THREAD_ABORT
|
||||
select ARCH_HAS_TRUSTED_EXECUTION if ARM_TRUSTZONE_M
|
||||
select ARCH_HAS_STACK_PROTECTION if (ARM_MPU && !ARMV6_M_ARMV8_M_BASELINE) || CPU_CORTEX_M_HAS_SPLIM
|
||||
select ARCH_HAS_STACK_PROTECTION if ARM_MPU || CPU_CORTEX_M_HAS_SPLIM
|
||||
select ARCH_HAS_USERSPACE if ARM_MPU
|
||||
select ARCH_HAS_NOCACHE_MEMORY_SUPPORT if ARM_MPU && CPU_HAS_ARM_MPU && CPU_CORTEX_M7
|
||||
select ARCH_HAS_RAMFUNC_SUPPORT
|
||||
select ARCH_HAS_NESTED_EXCEPTION_DETECTION
|
||||
select SWAP_NONATOMIC
|
||||
help
|
||||
This option signifies the use of a CPU of the Cortex-M family.
|
||||
|
||||
config CPU_CORTEX_R
|
||||
config CPU_HAS_SYSTICK
|
||||
bool
|
||||
select CPU_CORTEX
|
||||
select HAS_FLASH_LOAD_OFFSET
|
||||
# Omit prompt to signify "hidden" option
|
||||
help
|
||||
This option signifies the use of a CPU of the Cortex-R family.
|
||||
|
||||
config ISA_THUMB2
|
||||
bool
|
||||
help
|
||||
From: http://www.arm.com/products/processors/technologies/instruction-set-architectures.php
|
||||
|
||||
Thumb-2 technology is the instruction set underlying the ARM Cortex
|
||||
architecture which provides enhanced levels of performance, energy
|
||||
efficiency, and code density for a wide range of embedded
|
||||
applications.
|
||||
|
||||
Thumb-2 technology builds on the success of Thumb, the innovative
|
||||
high code density instruction set for ARM microprocessor cores, to
|
||||
increase the power of the ARM microprocessor core available to
|
||||
developers of low cost, high performance systems.
|
||||
|
||||
The technology is backwards compatible with existing ARM and Thumb
|
||||
solutions, while significantly extending the features available to
|
||||
the Thumb instructions set. This allows more of the application to
|
||||
benefit from the best in class code density of Thumb.
|
||||
|
||||
For performance optimized code Thumb-2 technology uses 31 percent
|
||||
less memory to reduce system cost, while providing up to 38 percent
|
||||
higher performance than existing high density code, which can be used
|
||||
to prolong battery-life or to enrich the product feature set. Thumb-2
|
||||
technology is featured in the processor, and in all ARMv7
|
||||
architecture-based processors.
|
||||
|
||||
config ISA_ARM
|
||||
bool
|
||||
help
|
||||
From: https://developer.arm.com/products/architecture/instruction-sets/a32-and-t32-instruction-sets
|
||||
|
||||
A32 instructions, known as Arm instructions in pre-Armv8 architectures,
|
||||
are 32 bits wide, and are aligned on 4-byte boundaries. A32 instructions
|
||||
are supported by both A-profile and R-profile architectures.
|
||||
|
||||
A32 was traditionally used in applications requiring the highest
|
||||
performance, or for handling hardware exceptions such as interrupts and
|
||||
processor start-up. Much of its functionality was subsumed into T32 with
|
||||
the introduction of Thumb-2 technology.
|
||||
|
||||
config NUM_IRQS
|
||||
int
|
||||
|
||||
config STACK_ALIGN_DOUBLE_WORD
|
||||
bool "Align stacks on double-words (8 octets)"
|
||||
default y
|
||||
help
|
||||
This is needed to conform to AAPCS, the procedure call standard for
|
||||
the ARM. It wastes stack space. The option also enforces alignment
|
||||
of stack upon exception entry on Cortex-M3 and Cortex-M4 (ARMv7-M).
|
||||
Note that for ARMv6-M, ARMv8-M, and Cortex-M7 MCUs stack alignment
|
||||
on exception entry is enabled by default and it is not configurable.
|
||||
|
||||
config RUNTIME_NMI
|
||||
bool "Attach an NMI handler at runtime"
|
||||
select REBOOT
|
||||
help
|
||||
The kernel provides a simple NMI handler that simply hangs in a tight
|
||||
loop if triggered. This fills the requirement that there must be an
|
||||
NMI handler installed when the CPU boots. If a custom handler is
|
||||
needed, enable this option and attach it via _NmiHandlerSet().
|
||||
|
||||
config PLATFORM_SPECIFIC_INIT
|
||||
bool "Enable platform (SOC) specific startup hook"
|
||||
help
|
||||
The platform specific initialization code (z_platform_init) is executed
|
||||
at the beginning of the startup code (__start).
|
||||
|
||||
config FAULT_DUMP
|
||||
int "Fault dump level"
|
||||
default 2
|
||||
range 0 2
|
||||
help
|
||||
Different levels for display information when a fault occurs.
|
||||
|
||||
2: The default. Display specific and verbose information. Consumes
|
||||
the most memory (long strings).
|
||||
|
||||
1: Display general and short information. Consumes less memory
|
||||
(short strings).
|
||||
|
||||
0: Off.
|
||||
This option is enabled when the CPU has systick timer implemented.
|
||||
|
||||
config BUILTIN_STACK_GUARD
|
||||
bool "Thread Stack Guards based on built-in ARM stack limit checking"
|
||||
@@ -127,7 +45,7 @@ config BUILTIN_STACK_GUARD
|
||||
config ARM_STACK_PROTECTION
|
||||
bool
|
||||
default y if HW_STACK_PROTECTION
|
||||
imply BUILTIN_STACK_GUARD if CPU_CORTEX_M_HAS_SPLIM
|
||||
select BUILTIN_STACK_GUARD if CPU_CORTEX_M_HAS_SPLIM
|
||||
select MPU_STACK_GUARD if (!BUILTIN_STACK_GUARD && ARM_MPU)
|
||||
help
|
||||
This option enables either:
|
||||
@@ -137,9 +55,7 @@ config ARM_STACK_PROTECTION
|
||||
if the bounds of the current process stack are overflowed.
|
||||
The two stack guard options are mutually exclusive. The
|
||||
selection of the built-in Stack Pointer limit checking is
|
||||
prioritized over the MPU-based stack guard. The developer
|
||||
still has the option to manually select the MPU-based
|
||||
stack guard, if this is desired.
|
||||
prioritized over the MPU-based stack guard.
|
||||
|
||||
config ARM_SECURE_FIRMWARE
|
||||
bool
|
||||
@@ -182,26 +98,11 @@ config ARM_NONSECURE_FIRMWARE
|
||||
resources of the Cortex-M MCU, and, therefore, it shall avoid
|
||||
accessing them.
|
||||
|
||||
|
||||
menu "ARM TrustZone Options"
|
||||
depends on ARM_SECURE_FIRMWARE || ARM_NONSECURE_FIRMWARE
|
||||
|
||||
comment "Secure firmware"
|
||||
depends on ARM_SECURE_FIRMWARE
|
||||
|
||||
comment "Non-secure firmware"
|
||||
depends on !ARM_SECURE_FIRMWARE
|
||||
|
||||
config ARM_SECURE_BUSFAULT_HARDFAULT_NMI
|
||||
bool "BusFault, HardFault, and NMI target Secure state"
|
||||
depends on ARM_SECURE_FIRMWARE
|
||||
help
|
||||
Force NMI, HardFault, and BusFault (in Mainline ARMv8-M)
|
||||
exceptions as Secure exceptions.
|
||||
menu "ARM Secure Firmware Options"
|
||||
depends on ARM_SECURE_FIRMWARE
|
||||
|
||||
config ARM_FIRMWARE_HAS_SECURE_ENTRY_FUNCS
|
||||
bool "Secure Firmware has Secure Entry functions"
|
||||
depends on ARM_SECURE_FIRMWARE
|
||||
help
|
||||
Option indicates that ARM Secure Firmware contains
|
||||
Secure Entry functions that may be called from
|
||||
@@ -225,24 +126,15 @@ config ARM_NSC_REGION_BASE_ADDRESS
|
||||
a Non-Secure Callable section, depending on the available
|
||||
security attribution unit (SAU or IDAU) for a given SOC.
|
||||
|
||||
config ARM_FIRMWARE_USES_SECURE_ENTRY_FUNCS
|
||||
bool "Non-Secure Firmware uses Secure Entry functions"
|
||||
depends on ARM_NONSECURE_FIRMWARE
|
||||
help
|
||||
Option indicates that ARM Non-Secure Firmware uses Secure
|
||||
Entry functions provided by the Secure Firmware. The Secure
|
||||
Firmware must be configured to provide these functions.
|
||||
|
||||
config ARM_ENTRY_VENEERS_LIB_NAME
|
||||
string "Entry Veneers symbol file"
|
||||
depends on ARM_FIRMWARE_HAS_SECURE_ENTRY_FUNCS \
|
||||
|| ARM_FIRMWARE_USES_SECURE_ENTRY_FUNCS
|
||||
depends on ARM_FIRMWARE_HAS_SECURE_ENTRY_FUNCS
|
||||
default "libentryveneers.a"
|
||||
help
|
||||
Library file to find the symbol table for the entry veneers.
|
||||
The library will typically come from building the Secure
|
||||
Firmware that contains secure entry functions, and allows
|
||||
the Non-Secure Firmware to call into the Secure Firmware.
|
||||
Library file to store the symbol table for
|
||||
the entry veneers. The library may be used
|
||||
for building a Non-Secure firmware with
|
||||
access to Secure Entry functions.
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -272,7 +164,6 @@ endchoice
|
||||
endmenu
|
||||
|
||||
source "arch/arm/core/cortex_m/Kconfig"
|
||||
source "arch/arm/core/cortex_r/Kconfig"
|
||||
|
||||
source "arch/arm/core/cortex_m/mpu/Kconfig"
|
||||
|
||||
|
||||
@@ -5,13 +5,9 @@ zephyr_library()
|
||||
zephyr_library_sources(
|
||||
vector_table.S
|
||||
reset.S
|
||||
fault.c
|
||||
nmi_on_reset.S
|
||||
prep_c.c
|
||||
scb.c
|
||||
irq_init.c
|
||||
thread_abort.c
|
||||
)
|
||||
|
||||
zephyr_linker_sources_ifdef(CONFIG_SW_VECTOR_RELAY
|
||||
RAM_SECTIONS
|
||||
vt_pointer_section.ld
|
||||
nmi.c
|
||||
exc_manage.c
|
||||
)
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
# ARM Cortex-M platform configuration options
|
||||
# Kconfig - ARM Cortex-M platform configuration options
|
||||
|
||||
#
|
||||
# Copyright (c) 2014-2015 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
# NOTE: We have the specific core implementations first and outside of the
|
||||
# if CPU_CORTEX_M block so that SoCs can select which core they are using
|
||||
@@ -12,6 +15,7 @@
|
||||
config CPU_CORTEX_M0
|
||||
bool
|
||||
select CPU_CORTEX_M
|
||||
# Omit prompt to signify "hidden" option
|
||||
select ARMV6_M_ARMV8_M_BASELINE
|
||||
help
|
||||
This option signifies the use of a Cortex-M0 CPU
|
||||
@@ -19,6 +23,7 @@ config CPU_CORTEX_M0
|
||||
config CPU_CORTEX_M0PLUS
|
||||
bool
|
||||
select CPU_CORTEX_M
|
||||
# Omit prompt to signify "hidden" option
|
||||
select ARMV6_M_ARMV8_M_BASELINE
|
||||
help
|
||||
This option signifies the use of a Cortex-M0+ CPU
|
||||
@@ -26,6 +31,7 @@ config CPU_CORTEX_M0PLUS
|
||||
config CPU_CORTEX_M3
|
||||
bool
|
||||
select CPU_CORTEX_M
|
||||
# Omit prompt to signify "hidden" option
|
||||
select ARMV7_M_ARMV8_M_MAINLINE
|
||||
help
|
||||
This option signifies the use of a Cortex-M3 CPU
|
||||
@@ -33,6 +39,7 @@ config CPU_CORTEX_M3
|
||||
config CPU_CORTEX_M4
|
||||
bool
|
||||
select CPU_CORTEX_M
|
||||
# Omit prompt to signify "hidden" option
|
||||
select ARMV7_M_ARMV8_M_MAINLINE
|
||||
select ARMV7_M_ARMV8_M_FP if CPU_HAS_FPU
|
||||
help
|
||||
@@ -41,6 +48,7 @@ config CPU_CORTEX_M4
|
||||
config CPU_CORTEX_M23
|
||||
bool
|
||||
select CPU_CORTEX_M
|
||||
# Omit prompt to signify "hidden" option
|
||||
select ARMV8_M_BASELINE
|
||||
select ARMV8_M_SE if CPU_HAS_TEE
|
||||
help
|
||||
@@ -49,6 +57,7 @@ config CPU_CORTEX_M23
|
||||
config CPU_CORTEX_M33
|
||||
bool
|
||||
select CPU_CORTEX_M
|
||||
# Omit prompt to signify "hidden" option
|
||||
select ARMV8_M_MAINLINE
|
||||
select ARMV8_M_SE if CPU_HAS_TEE
|
||||
select ARMV7_M_ARMV8_M_FP if CPU_HAS_FPU
|
||||
@@ -58,6 +67,7 @@ config CPU_CORTEX_M33
|
||||
config CPU_CORTEX_M7
|
||||
bool
|
||||
select CPU_CORTEX_M
|
||||
# Omit prompt to signify "hidden" option
|
||||
select ARMV7_M_ARMV8_M_MAINLINE
|
||||
select ARMV7_M_ARMV8_M_FP if CPU_HAS_FPU
|
||||
help
|
||||
@@ -65,13 +75,37 @@ config CPU_CORTEX_M7
|
||||
|
||||
if CPU_CORTEX_M
|
||||
|
||||
config CPU_CORTEX_M_HAS_SYSTICK
|
||||
config ISA_THUMB2
|
||||
bool
|
||||
# Omit prompt to signify "hidden" option
|
||||
help
|
||||
This option is enabled when the CPU implements the SysTick timer.
|
||||
From: http://www.arm.com/products/processors/technologies/instruction-set-architectures.php
|
||||
|
||||
Thumb-2 technology is the instruction set underlying the ARM Cortex
|
||||
architecture which provides enhanced levels of performance, energy
|
||||
efficiency, and code density for a wide range of embedded
|
||||
applications.
|
||||
|
||||
Thumb-2 technology builds on the success of Thumb, the innovative
|
||||
high code density instruction set for ARM microprocessor cores, to
|
||||
increase the power of the ARM microprocessor core available to
|
||||
developers of low cost, high performance systems.
|
||||
|
||||
The technology is backwards compatible with existing ARM and Thumb
|
||||
solutions, while significantly extending the features available to
|
||||
the Thumb instructions set. This allows more of the application to
|
||||
benefit from the best in class code density of Thumb.
|
||||
|
||||
For performance optimized code Thumb-2 technology uses 31 percent
|
||||
less memory to reduce system cost, while providing up to 38 percent
|
||||
higher performance than existing high density code, which can be used
|
||||
to prolong battery-life or to enrich the product feature set. Thumb-2
|
||||
technology is featured in the processor, and in all ARMv7
|
||||
architecture-based processors.
|
||||
|
||||
config CPU_CORTEX_M_HAS_BASEPRI
|
||||
bool
|
||||
# Omit prompt to signify "hidden" option
|
||||
depends on ARMV7_M_ARMV8_M_MAINLINE
|
||||
help
|
||||
This option signifies the CPU has the BASEPRI register.
|
||||
@@ -85,6 +119,7 @@ config CPU_CORTEX_M_HAS_BASEPRI
|
||||
|
||||
config CPU_CORTEX_M_HAS_VTOR
|
||||
bool
|
||||
# Omit prompt to signify "hidden" option
|
||||
depends on !CPU_CORTEX_M0
|
||||
help
|
||||
This option signifies the CPU has the VTOR register.
|
||||
@@ -97,6 +132,7 @@ config CPU_CORTEX_M_HAS_VTOR
|
||||
|
||||
config CPU_CORTEX_M_HAS_SPLIM
|
||||
bool
|
||||
# Omit prompt to signify "hidden" option
|
||||
depends on ARMV8_M_MAINLINE || (ARMV8_M_SE && !ARM_NONSECURE_FIRMWARE)
|
||||
help
|
||||
This option signifies the CPU has the MSPLIM, PSPLIM registers.
|
||||
@@ -108,11 +144,12 @@ config CPU_CORTEX_M_HAS_SPLIM
|
||||
|
||||
In an ARMv8-M Mainline implementation with the Security Extension
|
||||
the MSPLIM, PSPLIM registers have additional Secure instances.
|
||||
In an ARMv8-M Baseline implementation with the Security Extension
|
||||
In an ARMv8-M Baseline implementation with the Security Extension
|
||||
the MSPLIM, PSPLIM registers have only Secure instances.
|
||||
|
||||
config CPU_CORTEX_M_HAS_PROGRAMMABLE_FAULT_PRIOS
|
||||
bool
|
||||
# Omit prompt to signify "hidden" option
|
||||
depends on ARMV7_M_ARMV8_M_MAINLINE
|
||||
help
|
||||
This option signifies the CPU may trigger system faults
|
||||
@@ -121,6 +158,7 @@ config CPU_CORTEX_M_HAS_PROGRAMMABLE_FAULT_PRIOS
|
||||
|
||||
config CPU_CORTEX_M0_HAS_VECTOR_TABLE_REMAP
|
||||
bool
|
||||
# Omit prompt to signify "hidden" option
|
||||
help
|
||||
This option signifies the Cortex-M0 has some mechanisms that can map
|
||||
the vector table to SRAM
|
||||
@@ -133,6 +171,7 @@ config CPU_CORTEX_M_HAS_CMSE
|
||||
|
||||
config ARMV6_M_ARMV8_M_BASELINE
|
||||
bool
|
||||
# Omit prompt to signify "hidden" option
|
||||
select ATOMIC_OPERATIONS_C
|
||||
select ISA_THUMB2
|
||||
help
|
||||
@@ -150,6 +189,7 @@ config ARMV6_M_ARMV8_M_BASELINE
|
||||
|
||||
config ARMV8_M_BASELINE
|
||||
bool
|
||||
# Omit prompt to signify "hidden" option
|
||||
select ARMV6_M_ARMV8_M_BASELINE
|
||||
select CPU_CORTEX_M_HAS_CMSE
|
||||
help
|
||||
@@ -161,12 +201,12 @@ config ARMV8_M_BASELINE
|
||||
|
||||
config ARMV7_M_ARMV8_M_MAINLINE
|
||||
bool
|
||||
# Omit prompt to signify "hidden" option
|
||||
select ATOMIC_OPERATIONS_BUILTIN
|
||||
select ISA_THUMB2
|
||||
select CPU_CORTEX_M_HAS_BASEPRI
|
||||
select CPU_CORTEX_M_HAS_VTOR
|
||||
select CPU_CORTEX_M_HAS_PROGRAMMABLE_FAULT_PRIOS
|
||||
select CPU_CORTEX_M_HAS_SYSTICK
|
||||
help
|
||||
This option signifies the use of an ARMv7-M processor
|
||||
implementation, or the use of a backwards-compatible
|
||||
@@ -184,6 +224,7 @@ config ARMV7_M_ARMV8_M_MAINLINE
|
||||
|
||||
config ARMV8_M_MAINLINE
|
||||
bool
|
||||
# Omit prompt to signify "hidden" option
|
||||
select ARMV7_M_ARMV8_M_MAINLINE
|
||||
select CPU_CORTEX_M_HAS_SPLIM
|
||||
select CPU_CORTEX_M_HAS_CMSE
|
||||
@@ -196,6 +237,7 @@ config ARMV8_M_MAINLINE
|
||||
|
||||
config ARMV8_M_SE
|
||||
bool
|
||||
# Omit prompt to signify "hidden" option
|
||||
depends on ARMV8_M_BASELINE || ARMV8_M_MAINLINE
|
||||
select CPU_CORTEX_M_HAS_SPLIM if !ARM_NONSECURE_FIRMWARE
|
||||
help
|
||||
@@ -205,6 +247,7 @@ config ARMV8_M_SE
|
||||
|
||||
config ARMV7_M_ARMV8_M_FP
|
||||
bool
|
||||
# Omit prompt to signify "hidden" option
|
||||
depends on ARMV7_M_ARMV8_M_MAINLINE && !CPU_CORTEX_M3
|
||||
help
|
||||
This option signifies the use of an ARMv7-M processor
|
||||
@@ -213,14 +256,65 @@ config ARMV7_M_ARMV8_M_FP
|
||||
|
||||
config ARMV8_M_DSP
|
||||
bool
|
||||
# Omit prompt to signify "hidden" option
|
||||
depends on ARMV8_M_MAINLINE
|
||||
help
|
||||
This option signifies the use of an ARMv8-M processor
|
||||
implementation supporting the DSP Extension.
|
||||
|
||||
menu "ARM Cortex-M options"
|
||||
|
||||
config LDREX_STREX_AVAILABLE
|
||||
bool
|
||||
default y
|
||||
|
||||
config DATA_ENDIANNESS_LITTLE
|
||||
bool
|
||||
default y
|
||||
help
|
||||
This is driven by the processor implementation, since it is fixed in
|
||||
hardware. The board should set this value to 'n' if the data is
|
||||
implemented as big endian.
|
||||
|
||||
config STACK_ALIGN_DOUBLE_WORD
|
||||
bool "Align stacks on double-words (8 octets)"
|
||||
default y
|
||||
help
|
||||
This is needed to conform to AAPCS, the procedure call standard for
|
||||
the ARM. It wastes stack space. The option also enforces alignment
|
||||
of stack upon exception entry on Cortex-M3 and Cortex-M4 (ARMv7-M).
|
||||
Note that for ARMv6-M, ARMv8-M, and Cortex-M7 MCUs stack alignment
|
||||
on exception entry is enabled by default and it is not configurable.
|
||||
|
||||
config RUNTIME_NMI
|
||||
bool "Attach an NMI handler at runtime"
|
||||
select REBOOT
|
||||
help
|
||||
The kernel provides a simple NMI handler that simply hangs in a tight
|
||||
loop if triggered. This fills the requirement that there must be an
|
||||
NMI handler installed when the CPU boots. If a custom handler is
|
||||
needed, enable this option and attach it via _NmiHandlerSet().
|
||||
|
||||
config FAULT_DUMP
|
||||
int "Fault dump level"
|
||||
default 2
|
||||
range 0 2
|
||||
help
|
||||
Different levels for display information when a fault occurs.
|
||||
|
||||
2: The default. Display specific and verbose information. Consumes
|
||||
the most memory (long strings).
|
||||
|
||||
1: Display general and short information. Consumes less memory
|
||||
(short strings).
|
||||
|
||||
0: Off.
|
||||
|
||||
config XIP
|
||||
default y
|
||||
|
||||
endmenu
|
||||
|
||||
menu "ARM Cortex-M0/M0+/M3/M4/M7/M23/M33 options"
|
||||
depends on ARMV6_M_ARMV8_M_BASELINE || ARMV7_M_ARMV8_M_MAINLINE
|
||||
|
||||
@@ -255,6 +349,12 @@ config SW_VECTOR_RELAY
|
||||
(or an Armv8-M baseline core) with no VTOR and no other hardware
|
||||
relocation table mechanisms.
|
||||
|
||||
config PLATFORM_SPECIFIC_INIT
|
||||
bool "Enable platform (SOC) specific startup hook"
|
||||
help
|
||||
The platform specific initialization code (_PlatformInit) is executed
|
||||
at the beginning of the startup code (__start).
|
||||
|
||||
endmenu
|
||||
|
||||
endif # CPU_CORTEX_M
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources(arm_core_cmse.c)
|
||||
zephyr_sources(arm_core_cmse.c)
|
||||
|
||||
37
arch/arm/core/cortex_m/exc_manage.c
Normal file
37
arch/arm/core/cortex_m/exc_manage.c
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file exception related routines
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <misc/printk.h>
|
||||
void sys_exc_esf_dump(NANO_ESF *esf)
|
||||
{
|
||||
printk("r0/a1: %x ", esf->a1);
|
||||
printk("r1/a2: %x ", esf->a2);
|
||||
printk("r2/a3: %x\n", esf->a3);
|
||||
printk("r3/a4: %x ", esf->a4);
|
||||
printk("r12/ip: %x ", esf->ip);
|
||||
printk("r14/lr: %x\n", esf->lr);
|
||||
printk("r15/pc: %x ", esf->pc);
|
||||
printk("xpsr: %x\n", esf->xpsr);
|
||||
#ifdef CONFIG_FLOAT
|
||||
for (int i = 0; i < 16; i += 4) {
|
||||
printk("s[%d]: %x s[%d]: %x s[%d]: %x s[%d]: %x\n",
|
||||
i, (u32_t)esf->s[i],
|
||||
i + 1, (u32_t)esf->s[i + 1],
|
||||
i + 2, (u32_t)esf->s[i + 2],
|
||||
i + 3, (u32_t)esf->s[i + 3]);
|
||||
}
|
||||
printk("fpscr: %x\n", esf->fpscr);
|
||||
#endif
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief ARM Cortex-M interrupt initialization
|
||||
*
|
||||
*/
|
||||
|
||||
#include <arch/cpu.h>
|
||||
#include <arch/arm/cortex_m/cmsis.h>
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Initialize interrupts
|
||||
*
|
||||
* Ensures all interrupts have their priority set to _EXC_IRQ_DEFAULT_PRIO and
|
||||
* not 0, which they have it set to when coming out of reset. This ensures that
|
||||
* interrupt locking via BASEPRI works as expected.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void z_arm_int_lib_init(void)
|
||||
{
|
||||
int irq = 0;
|
||||
|
||||
for (; irq < CONFIG_NUM_IRQS; irq++) {
|
||||
NVIC_SetPriority((IRQn_Type)irq, _IRQ_PRIO_OFFSET);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
# Memory Protection Unit (MPU) configuration options
|
||||
# Kconfig - Memory Protection Unit (MPU) configuration options
|
||||
|
||||
#
|
||||
# Copyright (c) 2017 Linaro Limited
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
if CPU_HAS_MPU
|
||||
|
||||
@@ -14,37 +17,13 @@ config ARM_MPU
|
||||
select MPU_REQUIRES_NON_OVERLAPPING_REGIONS if CPU_HAS_ARM_MPU && (ARMV8_M_BASELINE || ARMV8_M_MAINLINE)
|
||||
help
|
||||
MCU implements Memory Protection Unit.
|
||||
|
||||
Notes:
|
||||
The ARMv6-M and ARMv8-M MPU architecture requires a power-of-two
|
||||
alignment of MPU region base address and size.
|
||||
|
||||
The NXP MPU as well as the ARMv8-M MPU do not require MPU regions
|
||||
Note that NXP MPU as well as ARMv8-M MPU does not require MPU regions
|
||||
to have power-of-two alignment for base address and region size.
|
||||
|
||||
The ARMv8-M MPU requires the active MPU regions be non-overlapping.
|
||||
As a result of this, the ARMv8-M MPU needs to fully partition the
|
||||
memory map when programming dynamic memory regions (e.g. PRIV stack
|
||||
guard, user thread stack, and application memory domains), if the
|
||||
system requires PRIV access policy different from the access policy
|
||||
of the ARMv8-M background memory map. The application developer may
|
||||
enforce full PRIV (kernel) memory partition by enabling the
|
||||
CONFIG_MPU_GAP_FILLING option.
|
||||
By not enforcing full partition, MPU may leave part of kernel
|
||||
SRAM area covered only by the default ARMv8-M memory map. This
|
||||
is fine for User Mode, since the background ARM map does not
|
||||
allow nPRIV access at all. However, since the background map
|
||||
policy allows instruction fetches by privileged code, forcing
|
||||
this Kconfig option off prevents the system from directly
|
||||
triggering MemManage exceptions upon accidental attempts to
|
||||
execute code from SRAM in XIP builds.
|
||||
Since this does not compromise User Mode, we make the skipping
|
||||
of full partitioning the default behavior for the ARMv8-M MPU
|
||||
driver.
|
||||
In addition to the above, ARMv8-M MPU requires the active MPU regions
|
||||
be non-overlapping.
|
||||
|
||||
config ARM_MPU_REGION_MIN_ALIGN_AND_SIZE
|
||||
int
|
||||
default 256 if ARM_MPU && ARMV6_M_ARMV8_M_BASELINE && !ARMV8_M_BASELINE
|
||||
default 32 if ARM_MPU
|
||||
default 4
|
||||
help
|
||||
@@ -53,32 +32,15 @@ config ARM_MPU_REGION_MIN_ALIGN_AND_SIZE
|
||||
A minimum 4-byte alignment is enforced in ARM builds without
|
||||
support for Memory Protection.
|
||||
|
||||
if ARM_MPU
|
||||
|
||||
config MPU_STACK_GUARD
|
||||
bool "Thread Stack Guards"
|
||||
depends on ARM_MPU
|
||||
help
|
||||
Enable Thread Stack Guards via MPU
|
||||
|
||||
if MPU_STACK_GUARD
|
||||
|
||||
config MPU_STACK_GUARD_MIN_SIZE_FLOAT
|
||||
int
|
||||
depends on FP_SHARING
|
||||
default 128
|
||||
help
|
||||
Minimum size (and alignment when applicable) of an ARM MPU
|
||||
region, which guards the stack of a thread that is using the
|
||||
Floating Point (FP) context. The width of the guard is set to
|
||||
128, to accommodate the length of a Cortex-M exception stack
|
||||
frame when the floating point context is active. The FP context
|
||||
is only stacked in sharing FP registers mode, therefore, the
|
||||
option is applicable only when FP_SHARING is selected.
|
||||
|
||||
endif # MPU_STACK_GUARD
|
||||
|
||||
config MPU_ALLOW_FLASH_WRITE
|
||||
bool "Add MPU access to write to flash"
|
||||
depends on ARM_MPU
|
||||
help
|
||||
Enable this to allow MPU RWX access to flash memory
|
||||
|
||||
@@ -96,11 +58,9 @@ config CUSTOM_SECTION_MIN_ALIGN_SIZE
|
||||
int "Custom Section Align Size"
|
||||
default 32
|
||||
help
|
||||
Custom align size of memory section in linker scripts. Usually
|
||||
it should consume less alignment memory. Although this alignment
|
||||
Custom algin size of memory section in linker scripts. Usually
|
||||
it should consume less alignment memory. Alougth this alignment
|
||||
size is configured by users, it must also respect the power of
|
||||
two regulation if hardware requires.
|
||||
|
||||
endif # ARM_MPU
|
||||
|
||||
endif # CPU_HAS_MPU
|
||||
|
||||
@@ -8,9 +8,8 @@
|
||||
#include <init.h>
|
||||
#include <kernel.h>
|
||||
#include <soc.h>
|
||||
#include <kernel_structs.h>
|
||||
|
||||
#include "arm_core_mpu_dev.h"
|
||||
#include <arch/arm/cortex_m/mpu/arm_core_mpu_dev.h>
|
||||
#include <linker/linker-defs.h>
|
||||
|
||||
#define LOG_LEVEL CONFIG_MPU_LOG_LEVEL
|
||||
@@ -23,7 +22,7 @@ LOG_MODULE_REGISTER(mpu);
|
||||
* available MPU regions for dynamic programming depends on the number of the
|
||||
* static MPU regions currently being programmed, and the total number of HW-
|
||||
* available MPU regions. This macro is only used internally in function
|
||||
* z_arm_configure_dynamic_mpu_regions(), to reserve sufficient area for the
|
||||
* z_arch_configure_dynamic_mpu_regions(), to reserve sufficient area for the
|
||||
* array of dynamic regions passed to the underlying driver.
|
||||
*/
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
@@ -59,7 +58,7 @@ LOG_MODULE_REGISTER(mpu);
|
||||
* For some MPU architectures, such as the unmodified ARMv8-M MPU,
|
||||
* the function must execute with MPU enabled.
|
||||
*/
|
||||
void z_arm_configure_static_mpu_regions(void)
|
||||
void z_arch_configure_static_mpu_regions(void)
|
||||
{
|
||||
#if defined(CONFIG_COVERAGE_GCOV) && defined(CONFIG_USERSPACE)
|
||||
const struct k_mem_partition gcov_region =
|
||||
@@ -142,7 +141,7 @@ void z_arm_configure_static_mpu_regions(void)
|
||||
* For some MPU architectures, such as the unmodified ARMv8-M MPU,
|
||||
* the function must execute with MPU enabled.
|
||||
*/
|
||||
void z_arm_configure_dynamic_mpu_regions(struct k_thread *thread)
|
||||
void z_arch_configure_dynamic_mpu_regions(struct k_thread *thread)
|
||||
{
|
||||
/* Define an array of k_mem_partition objects to hold the configuration
|
||||
* of the respective dynamic MPU regions to be programmed for
|
||||
@@ -176,7 +175,7 @@ void z_arm_configure_dynamic_mpu_regions(struct k_thread *thread)
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
LOG_DBG("set region 0x%lx 0x%x",
|
||||
LOG_DBG("set region 0x%x 0x%x",
|
||||
partition.start, partition.size);
|
||||
__ASSERT(region_num < _MAX_DYNAMIC_MPU_REGIONS_NUM,
|
||||
"Out-of-bounds error for dynamic region map.");
|
||||
@@ -213,30 +212,19 @@ void z_arm_configure_dynamic_mpu_regions(struct k_thread *thread)
|
||||
|
||||
/* Privileged stack guard */
|
||||
u32_t guard_start;
|
||||
u32_t guard_size = MPU_GUARD_ALIGN_AND_SIZE;
|
||||
|
||||
#if defined(CONFIG_FLOAT) && defined(CONFIG_FP_SHARING)
|
||||
if ((thread->base.user_options & K_FP_REGS) != 0) {
|
||||
guard_size = MPU_GUARD_ALIGN_AND_SIZE_FLOAT;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
if (thread->arch.priv_stack_start) {
|
||||
guard_start = thread->arch.priv_stack_start - guard_size;
|
||||
|
||||
__ASSERT((u32_t)&z_priv_stacks_ram_start <= guard_start,
|
||||
"Guard start: (0x%x) below privilege stacks boundary: (0x%x)",
|
||||
guard_start, (u32_t)&z_priv_stacks_ram_start);
|
||||
guard_start = thread->arch.priv_stack_start;
|
||||
} else {
|
||||
guard_start = thread->stack_info.start - guard_size;
|
||||
|
||||
guard_start = thread->stack_info.start -
|
||||
MPU_GUARD_ALIGN_AND_SIZE;
|
||||
__ASSERT((u32_t)thread->stack_obj == guard_start,
|
||||
"Guard start (0x%x) not beginning at stack object (0x%x)\n",
|
||||
guard_start, (u32_t)thread->stack_obj);
|
||||
}
|
||||
#else
|
||||
guard_start = thread->stack_info.start - guard_size;
|
||||
guard_start = thread->stack_info.start -
|
||||
MPU_GUARD_ALIGN_AND_SIZE;
|
||||
#endif /* CONFIG_USERSPACE */
|
||||
|
||||
__ASSERT(region_num < _MAX_DYNAMIC_MPU_REGIONS_NUM,
|
||||
@@ -244,7 +232,7 @@ void z_arm_configure_dynamic_mpu_regions(struct k_thread *thread)
|
||||
guard = (const struct k_mem_partition)
|
||||
{
|
||||
guard_start,
|
||||
guard_size,
|
||||
MPU_GUARD_ALIGN_AND_SIZE,
|
||||
K_MEM_PARTITION_P_RO_U_NA
|
||||
};
|
||||
dynamic_regions[region_num] = &guard;
|
||||
@@ -259,7 +247,13 @@ void z_arm_configure_dynamic_mpu_regions(struct k_thread *thread)
|
||||
}
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
int arch_mem_domain_max_partitions_get(void)
|
||||
|
||||
/**
|
||||
* @brief Get the maximum number of partitions for a memory domain
|
||||
* that is supported by the MPU hardware, and with respect
|
||||
* to the current static memory region configuration.
|
||||
*/
|
||||
int z_arch_mem_domain_max_partitions_get(void)
|
||||
{
|
||||
int available_regions = arm_core_mpu_get_max_available_dyn_regions();
|
||||
|
||||
@@ -274,31 +268,31 @@ int arch_mem_domain_max_partitions_get(void)
|
||||
return ARM_CORE_MPU_MAX_DOMAIN_PARTITIONS_GET(available_regions);
|
||||
}
|
||||
|
||||
void arch_mem_domain_thread_add(struct k_thread *thread)
|
||||
/**
|
||||
* @brief Configure the memory domain of the thread.
|
||||
*/
|
||||
void z_arch_mem_domain_configure(struct k_thread *thread)
|
||||
{
|
||||
if (_current != thread) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Request to configure memory domain for a thread.
|
||||
* This triggers re-programming of the entire dynamic
|
||||
* memory map.
|
||||
*/
|
||||
z_arm_configure_dynamic_mpu_regions(thread);
|
||||
z_arch_configure_dynamic_mpu_regions(thread);
|
||||
}
|
||||
|
||||
void arch_mem_domain_destroy(struct k_mem_domain *domain)
|
||||
/*
|
||||
* @brief Reset the MPU configuration related to the memory domain
|
||||
* partitions
|
||||
*
|
||||
* @param domain pointer to the memory domain (must be valid)
|
||||
*/
|
||||
void z_arch_mem_domain_destroy(struct k_mem_domain *domain)
|
||||
{
|
||||
/* This function will reset the access permission configuration
|
||||
* of the active partitions of the memory domain.
|
||||
*/
|
||||
int i;
|
||||
struct k_mem_partition partition;
|
||||
|
||||
if (_current->mem_domain_info.mem_domain != domain) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Partitions belonging to the memory domain will be reset
|
||||
* to default (Privileged RW, Unprivileged NA) permissions.
|
||||
*/
|
||||
@@ -317,8 +311,15 @@ void arch_mem_domain_destroy(struct k_mem_domain *domain)
|
||||
}
|
||||
}
|
||||
|
||||
void arch_mem_domain_partition_remove(struct k_mem_domain *domain,
|
||||
u32_t partition_id)
|
||||
/*
|
||||
* @brief Remove a partition from the memory domain
|
||||
*
|
||||
* @param domain pointer to the memory domain (must be valid
|
||||
* @param partition_id the ID (sequence) number of the memory domain
|
||||
* partition (must be a valid partition).
|
||||
*/
|
||||
void z_arch_mem_domain_partition_remove(struct k_mem_domain *domain,
|
||||
u32_t partition_id)
|
||||
{
|
||||
/* Request to remove a partition from a memory domain.
|
||||
* This resets the access permissions of the partition
|
||||
@@ -326,30 +327,20 @@ void arch_mem_domain_partition_remove(struct k_mem_domain *domain,
|
||||
*/
|
||||
k_mem_partition_attr_t reset_attr = K_MEM_PARTITION_P_RW_U_NA;
|
||||
|
||||
if (_current->mem_domain_info.mem_domain != domain) {
|
||||
return;
|
||||
}
|
||||
|
||||
arm_core_mpu_mem_partition_config_update(
|
||||
&domain->partitions[partition_id], &reset_attr);
|
||||
}
|
||||
|
||||
void arch_mem_domain_partition_add(struct k_mem_domain *domain,
|
||||
u32_t partition_id)
|
||||
void _arch_mem_domain_partition_add(struct k_mem_domain *domain,
|
||||
u32_t partition_id)
|
||||
{
|
||||
/* No-op on this architecture */
|
||||
}
|
||||
|
||||
void arch_mem_domain_thread_remove(struct k_thread *thread)
|
||||
{
|
||||
if (_current != thread) {
|
||||
return;
|
||||
}
|
||||
|
||||
arch_mem_domain_destroy(thread->mem_domain_info.mem_domain);
|
||||
}
|
||||
|
||||
int arch_buffer_validate(void *addr, size_t size, int write)
|
||||
/*
|
||||
* Validate the given buffer is user accessible or not
|
||||
*/
|
||||
int z_arch_buffer_validate(void *addr, size_t size, int write)
|
||||
{
|
||||
return arm_core_mpu_buffer_validate(addr, size, write);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
#include <init.h>
|
||||
#include <kernel.h>
|
||||
#include <soc.h>
|
||||
#include "arm_core_mpu_dev.h"
|
||||
#include <arch/arm/cortex_m/mpu/arm_core_mpu_dev.h>
|
||||
#include <arch/arm/cortex_m/mpu/arm_core_mpu.h>
|
||||
#include <linker/linker-defs.h>
|
||||
|
||||
#define LOG_LEVEL CONFIG_MPU_LOG_LEVEL
|
||||
@@ -34,17 +35,13 @@ static inline u8_t get_num_regions(void)
|
||||
* have a fixed number of 8 MPU regions.
|
||||
*/
|
||||
return 8;
|
||||
#elif defined(DT_NUM_MPU_REGIONS)
|
||||
/* Retrieve the number of regions from DTS configuration. */
|
||||
return DT_NUM_MPU_REGIONS;
|
||||
#else
|
||||
|
||||
u32_t type = MPU->TYPE;
|
||||
|
||||
type = (type & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos;
|
||||
|
||||
return (u8_t)type;
|
||||
#endif /* CPU_CORTEX_M0PLUS | CPU_CORTEX_M3 | CPU_CORTEX_M4 */
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Include architecture-specific internal headers. */
|
||||
@@ -99,45 +96,6 @@ static int mpu_configure_region(const u8_t index,
|
||||
(const struct arm_mpu_region *)®ion_conf);
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_MPU_REQUIRES_NON_OVERLAPPING_REGIONS) || \
|
||||
!defined(CONFIG_MPU_GAP_FILLING)
|
||||
/* This internal function programs a set of given MPU regions
|
||||
* over a background memory area, optionally performing a
|
||||
* sanity check of the memory regions to be programmed.
|
||||
*/
|
||||
static int mpu_configure_regions(const struct k_mem_partition
|
||||
*regions[], u8_t regions_num, u8_t start_reg_index,
|
||||
bool do_sanity_check)
|
||||
{
|
||||
int i;
|
||||
int reg_index = start_reg_index;
|
||||
|
||||
for (i = 0; i < regions_num; i++) {
|
||||
if (regions[i]->size == 0U) {
|
||||
continue;
|
||||
}
|
||||
/* Non-empty region. */
|
||||
|
||||
if (do_sanity_check &&
|
||||
(!mpu_partition_is_valid(regions[i]))) {
|
||||
LOG_ERR("Partition %u: sanity check failed.", i);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
reg_index = mpu_configure_region(reg_index, regions[i]);
|
||||
|
||||
if (reg_index == -EINVAL) {
|
||||
return reg_index;
|
||||
}
|
||||
|
||||
/* Increment number of programmed MPU indices. */
|
||||
reg_index++;
|
||||
}
|
||||
|
||||
return reg_index;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ARM Core MPU Driver API Implementation for ARM MPU */
|
||||
|
||||
/**
|
||||
@@ -327,12 +285,7 @@ static int arm_mpu_init(struct device *arg)
|
||||
__ASSERT(
|
||||
(MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos == 8,
|
||||
"Invalid number of MPU regions\n");
|
||||
#elif defined(DT_NUM_MPU_REGIONS)
|
||||
__ASSERT(
|
||||
(MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos ==
|
||||
DT_NUM_MPU_REGIONS,
|
||||
"Invalid number of MPU regions\n");
|
||||
#endif /* CORTEX_M0PLUS || CPU_CORTEX_M3 || CPU_CORTEX_M4 */
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -252,9 +252,41 @@ static inline int mpu_buffer_validate(void *addr, size_t size, int write)
|
||||
static int mpu_configure_region(const u8_t index,
|
||||
const struct k_mem_partition *new_region);
|
||||
|
||||
/* This internal function programs a set of given MPU regions
|
||||
* over a background memory area, optionally performing a
|
||||
* sanity check of the memory regions to be programmed.
|
||||
*/
|
||||
static int mpu_configure_regions(const struct k_mem_partition
|
||||
*regions[], u8_t regions_num, u8_t start_reg_index,
|
||||
bool do_sanity_check);
|
||||
bool do_sanity_check)
|
||||
{
|
||||
int i;
|
||||
int reg_index = start_reg_index;
|
||||
|
||||
for (i = 0; i < regions_num; i++) {
|
||||
if (regions[i]->size == 0U) {
|
||||
continue;
|
||||
}
|
||||
/* Non-empty region. */
|
||||
|
||||
if (do_sanity_check &&
|
||||
(!mpu_partition_is_valid(regions[i]))) {
|
||||
LOG_ERR("Partition %u: sanity check failed.", i);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
reg_index = mpu_configure_region(reg_index, regions[i]);
|
||||
|
||||
if (reg_index == -EINVAL) {
|
||||
return reg_index;
|
||||
}
|
||||
|
||||
/* Increment number of programmed MPU indices. */
|
||||
reg_index++;
|
||||
}
|
||||
|
||||
return reg_index;
|
||||
}
|
||||
|
||||
/* This internal function programs the static MPU regions.
|
||||
*
|
||||
|
||||
@@ -318,20 +318,11 @@ static int region_allocate_and_init(const u8_t index,
|
||||
static int mpu_configure_region(const u8_t index,
|
||||
const struct k_mem_partition *new_region);
|
||||
|
||||
#if !defined(CONFIG_MPU_GAP_FILLING)
|
||||
static int mpu_configure_regions(const struct k_mem_partition
|
||||
*regions[], u8_t regions_num, u8_t start_reg_index,
|
||||
bool do_sanity_check);
|
||||
#endif
|
||||
|
||||
/* This internal function programs a set of given MPU regions
|
||||
* over a background memory area, optionally performing a
|
||||
* sanity check of the memory regions to be programmed.
|
||||
*
|
||||
* The function performs a full partition of the background memory
|
||||
* area, effectively, leaving no space in this area uncovered by MPU.
|
||||
*/
|
||||
static int mpu_configure_regions_and_partition(const struct k_mem_partition
|
||||
static int mpu_configure_regions(const struct k_mem_partition
|
||||
*regions[], u8_t regions_num, u8_t start_reg_index,
|
||||
bool do_sanity_check)
|
||||
{
|
||||
@@ -481,7 +472,7 @@ static int mpu_configure_static_mpu_regions(const struct k_mem_partition
|
||||
ARG_UNUSED(background_area_base);
|
||||
ARG_UNUSED(background_area_end);
|
||||
|
||||
mpu_reg_index = mpu_configure_regions_and_partition(static_regions,
|
||||
mpu_reg_index = mpu_configure_regions(static_regions,
|
||||
regions_num, mpu_reg_index, true);
|
||||
|
||||
static_regions_num = mpu_reg_index;
|
||||
@@ -548,7 +539,6 @@ static int mpu_configure_dynamic_mpu_regions(const struct k_mem_partition
|
||||
ARM_MPU_ClrRegion(i);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_MPU_GAP_FILLING)
|
||||
/* Reset MPU regions inside which dynamic memory regions may
|
||||
* be programmed.
|
||||
*/
|
||||
@@ -561,25 +551,10 @@ static int mpu_configure_dynamic_mpu_regions(const struct k_mem_partition
|
||||
* forming a full partition of the background area, specified by the
|
||||
* given boundaries.
|
||||
*/
|
||||
mpu_reg_index = mpu_configure_regions_and_partition(dynamic_regions,
|
||||
regions_num, mpu_reg_index, true);
|
||||
#else
|
||||
|
||||
/* We are going to skip the full partition of the background areas.
|
||||
* So we can disable MPU regions inside which dynamic memroy regions
|
||||
* may be programmed.
|
||||
*/
|
||||
for (int i = 0; i < MPU_DYNAMIC_REGION_AREAS_NUM; i++) {
|
||||
ARM_MPU_ClrRegion(dyn_reg_info[i].index);
|
||||
}
|
||||
|
||||
/* The dynamic regions are now programmed on top of
|
||||
* existing SRAM region configuration.
|
||||
*/
|
||||
mpu_reg_index = mpu_configure_regions(dynamic_regions,
|
||||
regions_num, mpu_reg_index, true);
|
||||
|
||||
#endif /* CONFIG_MPU_GAP_FILLING */
|
||||
return mpu_reg_index;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
#include <init.h>
|
||||
#include <kernel.h>
|
||||
#include <soc.h>
|
||||
#include "arm_core_mpu_dev.h"
|
||||
#include <sys/__assert.h>
|
||||
#include <arch/arm/cortex_m/mpu/arm_core_mpu_dev.h>
|
||||
#include <arch/arm/cortex_m/mpu/arm_core_mpu.h>
|
||||
#include <misc/__assert.h>
|
||||
#include <linker/linker-defs.h>
|
||||
|
||||
#define LOG_LEVEL CONFIG_MPU_LOG_LEVEL
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
|
||||
#include <kernel.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <sys/printk.h>
|
||||
#include <power/reboot.h>
|
||||
#include <misc/printk.h>
|
||||
#include <misc/reboot.h>
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
|
||||
@@ -34,7 +34,7 @@ static _NmiHandler_t handler = z_SysNmiOnReset;
|
||||
* @brief Default NMI handler installed when kernel is up
|
||||
*
|
||||
* The default handler outputs a error message and reboots the target. It is
|
||||
* installed by calling z_arm_nmi_init();
|
||||
* installed by calling z_NmiInit();
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
@@ -57,7 +57,7 @@ static void DefaultHandler(void)
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void z_arm_nmi_init(void)
|
||||
void z_NmiInit(void)
|
||||
{
|
||||
handler = DefaultHandler;
|
||||
}
|
||||
@@ -88,8 +88,8 @@ void z_NmiHandlerSet(void (*pHandler)(void))
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void z_arm_nmi(void)
|
||||
void __nmi(void)
|
||||
{
|
||||
handler();
|
||||
z_arm_exc_exit();
|
||||
z_ExcExit();
|
||||
}
|
||||
142
arch/arm/core/cortex_m/prep_c.c
Normal file
142
arch/arm/core/cortex_m/prep_c.c
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2014 Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Full C support initialization
|
||||
*
|
||||
*
|
||||
* Initialization of full C support: zero the .bss, copy the .data if XIP,
|
||||
* call z_cstart().
|
||||
*
|
||||
* Stack is available in this module, but not the global data/bss until their
|
||||
* initialization is performed.
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <zephyr/types.h>
|
||||
#include <toolchain.h>
|
||||
#include <linker/linker-defs.h>
|
||||
#include <kernel_internal.h>
|
||||
#include <arch/arm/cortex_m/cmsis.h>
|
||||
|
||||
#if defined(__GNUC__)
|
||||
/*
|
||||
* GCC can detect if memcpy is passed a NULL argument, however one of
|
||||
* the cases of relocate_vector_table() it is valid to pass NULL, so we
|
||||
* supress the warning for this case. We need to do this before
|
||||
* string.h is included to get the declaration of memcpy.
|
||||
*/
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wnonnull"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef CONFIG_CPU_CORTEX_M_HAS_VTOR
|
||||
|
||||
#ifdef CONFIG_XIP
|
||||
#define VECTOR_ADDRESS ((uintptr_t)_vector_start)
|
||||
#else
|
||||
#define VECTOR_ADDRESS CONFIG_SRAM_BASE_ADDRESS
|
||||
#endif
|
||||
static inline void relocate_vector_table(void)
|
||||
{
|
||||
SCB->VTOR = VECTOR_ADDRESS & SCB_VTOR_TBLOFF_Msk;
|
||||
__DSB();
|
||||
__ISB();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#if defined(CONFIG_SW_VECTOR_RELAY)
|
||||
Z_GENERIC_SECTION(.vt_pointer_section) void *_vector_table_pointer;
|
||||
#endif
|
||||
|
||||
#define VECTOR_ADDRESS 0
|
||||
|
||||
void __weak relocate_vector_table(void)
|
||||
{
|
||||
#if defined(CONFIG_XIP) && (CONFIG_FLASH_BASE_ADDRESS != 0) || \
|
||||
!defined(CONFIG_XIP) && (CONFIG_SRAM_BASE_ADDRESS != 0)
|
||||
size_t vector_size = (size_t)_vector_end - (size_t)_vector_start;
|
||||
(void)memcpy(VECTOR_ADDRESS, _vector_start, vector_size);
|
||||
#elif defined(CONFIG_SW_VECTOR_RELAY)
|
||||
_vector_table_pointer = _vector_start;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_CPU_CORTEX_M_HAS_VTOR */
|
||||
|
||||
#ifdef CONFIG_FLOAT
|
||||
static inline void enable_floating_point(void)
|
||||
{
|
||||
/*
|
||||
* Upon reset, the Co-Processor Access Control Register is 0x00000000.
|
||||
* Enable CP10 and CP11 co-processors to enable floating point.
|
||||
*/
|
||||
SCB->CPACR |= CPACR_CP10_FULL_ACCESS | CPACR_CP11_FULL_ACCESS;
|
||||
/*
|
||||
* Upon reset, the FPU Context Control Register is 0xC0000000
|
||||
* (both Automatic and Lazy state preservation is enabled).
|
||||
* Disable lazy state preservation so the volatile FP registers are
|
||||
* always saved on exception.
|
||||
*/
|
||||
FPU->FPCCR = FPU_FPCCR_ASPEN_Msk; /* FPU_FPCCR_LSPEN = 0 */
|
||||
|
||||
/*
|
||||
* Although automatic state preservation is enabled, the processor
|
||||
* does not automatically save the volatile FP registers until they
|
||||
* have first been touched. Perform a dummy move operation so that
|
||||
* the stack frames are created as expected before any thread
|
||||
* context switching can occur. It has to be surrounded by instruction
|
||||
* synchronization barriers to ensure that the whole sequence is
|
||||
* serialized.
|
||||
*/
|
||||
__asm__ volatile(
|
||||
"isb;\n\t"
|
||||
"vmov s0, s0;\n\t"
|
||||
"isb;\n\t"
|
||||
);
|
||||
}
|
||||
#else
|
||||
static inline void enable_floating_point(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
extern FUNC_NORETURN void z_cstart(void);
|
||||
/**
|
||||
*
|
||||
* @brief Prepare to and run C code
|
||||
*
|
||||
* This routine prepares for the execution of and runs C code.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
extern void z_IntLibInit(void);
|
||||
|
||||
#ifdef CONFIG_BOOT_TIME_MEASUREMENT
|
||||
extern u64_t __start_time_stamp;
|
||||
#endif
|
||||
void _PrepC(void)
|
||||
{
|
||||
relocate_vector_table();
|
||||
enable_floating_point();
|
||||
z_bss_zero();
|
||||
z_data_copy();
|
||||
#ifdef CONFIG_BOOT_TIME_MEASUREMENT
|
||||
__start_time_stamp = 0U;
|
||||
#endif
|
||||
z_IntLibInit();
|
||||
z_cstart();
|
||||
CODE_UNREACHABLE;
|
||||
}
|
||||
@@ -18,11 +18,11 @@
|
||||
|
||||
_ASM_FILE_PROLOGUE
|
||||
|
||||
GTEXT(z_arm_reset)
|
||||
GTEXT(__reset)
|
||||
GTEXT(memset)
|
||||
GDATA(_interrupt_stack)
|
||||
#if defined(CONFIG_PLATFORM_SPECIFIC_INIT)
|
||||
GTEXT(z_platform_init)
|
||||
GTEXT(_PlatformInit)
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -39,19 +39,19 @@ GTEXT(z_platform_init)
|
||||
* deep trouble.
|
||||
*
|
||||
* We want to use the process stack pointer (PSP) instead of the MSP, since the
|
||||
* MSP is to be set up to point to the one-and-only interrupt stack during
|
||||
* later boot. That would not be possible if in use for running C code.
|
||||
* MSP is to be set up to point to the one-and-only interrupt stack during later
|
||||
* boot. That would not be possible if in use for running C code.
|
||||
*
|
||||
* When these steps are completed, jump to z_arm_prep_c(), which will finish
|
||||
* setting up the system for running C code.
|
||||
* When these steps are completed, jump to _PrepC(), which will finish setting
|
||||
* up the system for running C code.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
SECTION_SUBSEC_FUNC(TEXT,_reset_section,z_arm_reset)
|
||||
SECTION_SUBSEC_FUNC(TEXT,_reset_section,__reset)
|
||||
|
||||
/*
|
||||
* The entry point is located at the z_arm_reset symbol, which
|
||||
* The entry point is located at the __reset symbol, which
|
||||
* is fetched by a XIP image playing the role of a bootloader, which jumps to
|
||||
* it, not through the reset vector mechanism. Such bootloaders might want to
|
||||
* search for a __start symbol instead, so create that alias here.
|
||||
@@ -59,7 +59,7 @@ SECTION_SUBSEC_FUNC(TEXT,_reset_section,z_arm_reset)
|
||||
SECTION_SUBSEC_FUNC(TEXT,_reset_section,__start)
|
||||
|
||||
#if defined(CONFIG_PLATFORM_SPECIFIC_INIT)
|
||||
bl z_platform_init
|
||||
bl _PlatformInit
|
||||
#endif
|
||||
|
||||
/* lock interrupts: will get unlocked when switch to main task */
|
||||
@@ -74,7 +74,7 @@ SECTION_SUBSEC_FUNC(TEXT,_reset_section,__start)
|
||||
|
||||
#ifdef CONFIG_WDOG_INIT
|
||||
/* board-specific watchdog initialization is necessary */
|
||||
bl z_arm_watchdog_init
|
||||
bl _WdogInit
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_INIT_STACKS
|
||||
@@ -105,7 +105,7 @@ SECTION_SUBSEC_FUNC(TEXT,_reset_section,__start)
|
||||
|
||||
/*
|
||||
* 'bl' jumps the furthest of the branch instructions that are
|
||||
* supported on all platforms. So it is used when jumping to z_arm_prep_c
|
||||
* supported on all platforms. So it is used when jumping to _PrepC
|
||||
* (even though we do not intend to return).
|
||||
*/
|
||||
bl z_arm_prep_c
|
||||
bl _PrepC
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#include <kernel.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <sys/util.h>
|
||||
#include <misc/util.h>
|
||||
#include <arch/arm/cortex_m/cmsis.h>
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,38 +2,22 @@
|
||||
|
||||
# '-mcmse' enables the generation of code for the Secure state of the ARMv8-M
|
||||
# Security Extensions. This option is required when building a Secure firmware.
|
||||
zephyr_compile_options_ifdef(CONFIG_ARM_SECURE_FIRMWARE -mcmse)
|
||||
zephyr_compile_options(-mcmse)
|
||||
|
||||
if(CONFIG_ARM_FIRMWARE_HAS_SECURE_ENTRY_FUNCS)
|
||||
|
||||
# --out-implib and --cmse-implib instruct the linker to produce
|
||||
# an import library that consists of a relocatable file containing
|
||||
# only a symbol table with the entry veneers. The library may be used
|
||||
# when building a Non-Secure image which shall have access to Secure
|
||||
# Entry functions.
|
||||
# --out-implib and --cmse-implib instruct the linker to produce
|
||||
# an import library that consists of a relocatable file containing
|
||||
# only a symbol table with the entry veneers. The library may be used
|
||||
# when building a Non-Secure image which shall have access to Secure
|
||||
# Entry functions.
|
||||
zephyr_ld_options(
|
||||
${LINKERFLAGPREFIX},--out-implib=${CMAKE_BINARY_DIR}/${CONFIG_ARM_ENTRY_VENEERS_LIB_NAME}
|
||||
${LINKERFLAGPREFIX},--out-implib=${CONFIG_ARM_ENTRY_VENEERS_LIB_NAME}
|
||||
)
|
||||
|
||||
zephyr_ld_options(
|
||||
${LINKERFLAGPREFIX},--cmse-implib
|
||||
)
|
||||
|
||||
# Indicate that the entry veneers library file is created during linking of this firmware.
|
||||
set_property(
|
||||
GLOBAL APPEND PROPERTY
|
||||
extra_post_build_byproducts
|
||||
${CMAKE_BINARY_DIR}/${CONFIG_ARM_ENTRY_VENEERS_LIB_NAME}
|
||||
)
|
||||
endif()
|
||||
|
||||
# Link the entry veneers library file with the Non-Secure Firmware that needs it.
|
||||
zephyr_link_libraries_ifdef(CONFIG_ARM_FIRMWARE_USES_SECURE_ENTRY_FUNCS
|
||||
${CMAKE_BINARY_DIR}/${CONFIG_ARM_ENTRY_VENEERS_LIB_NAME}
|
||||
)
|
||||
|
||||
if(CONFIG_ARM_SECURE_FIRMWARE)
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources(arm_core_tz.c)
|
||||
endif()
|
||||
zephyr_sources(arm_core_tz.c)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# ARM TrustZone-M core configuration options
|
||||
# Kconfig - ARM TrustZone-M core configuration options
|
||||
|
||||
#
|
||||
# Copyright (c) 2018 Nordic Semiconductor ASA.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config ARM_TRUSTZONE_M
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
_ASM_FILE_PROLOGUE
|
||||
|
||||
GDATA(z_main_stack)
|
||||
GDATA(_main_stack)
|
||||
|
||||
SECTION_SUBSEC_FUNC(exc_vector_table,_vector_table_section,_vector_table)
|
||||
|
||||
@@ -31,44 +31,40 @@ SECTION_SUBSEC_FUNC(exc_vector_table,_vector_table_section,_vector_table)
|
||||
* on the interrupt stack when CONFIG_INIT_STACKS is enabled before
|
||||
* switching to the interrupt stack for the rest of the early boot
|
||||
*/
|
||||
.word z_main_stack + CONFIG_MAIN_STACK_SIZE
|
||||
.word _main_stack + CONFIG_MAIN_STACK_SIZE
|
||||
|
||||
.word z_arm_reset
|
||||
.word z_arm_nmi
|
||||
.word __reset
|
||||
.word __nmi
|
||||
|
||||
.word z_arm_hard_fault
|
||||
.word __hard_fault
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
.word z_arm_reserved
|
||||
.word z_arm_reserved
|
||||
.word z_arm_reserved
|
||||
.word z_arm_reserved
|
||||
.word z_arm_reserved
|
||||
.word z_arm_reserved
|
||||
.word z_arm_reserved
|
||||
.word z_arm_svc
|
||||
.word z_arm_reserved
|
||||
.word __reserved
|
||||
.word __reserved
|
||||
.word __reserved
|
||||
.word __reserved
|
||||
.word __reserved
|
||||
.word __reserved
|
||||
.word __reserved
|
||||
.word __svc
|
||||
.word __reserved
|
||||
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
|
||||
.word z_arm_mpu_fault
|
||||
.word z_arm_bus_fault
|
||||
.word z_arm_usage_fault
|
||||
.word __mpu_fault
|
||||
.word __bus_fault
|
||||
.word __usage_fault
|
||||
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
|
||||
.word z_arm_secure_fault
|
||||
.word __secure_fault
|
||||
#else
|
||||
.word z_arm_reserved
|
||||
.word __reserved
|
||||
#endif /* CONFIG_ARM_SECURE_FIRMWARE */
|
||||
.word z_arm_reserved
|
||||
.word z_arm_reserved
|
||||
.word z_arm_reserved
|
||||
.word z_arm_svc
|
||||
.word z_arm_debug_monitor
|
||||
.word __reserved
|
||||
.word __reserved
|
||||
.word __reserved
|
||||
.word __svc
|
||||
.word __debug_monitor
|
||||
#else
|
||||
#error Unknown ARM architecture
|
||||
#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
|
||||
.word z_arm_reserved
|
||||
.word z_arm_pendsv
|
||||
#if defined(CONFIG_SYS_CLOCK_EXISTS)
|
||||
.word __reserved
|
||||
.word __pendsv
|
||||
.word z_clock_isr
|
||||
#else
|
||||
.word z_arm_reserved
|
||||
#endif
|
||||
|
||||
|
||||
@@ -21,50 +21,50 @@
|
||||
#ifndef ZEPHYR_ARCH_ARM_CORE_CORTEX_M_VECTOR_TABLE_H_
|
||||
#define ZEPHYR_ARCH_ARM_CORE_CORTEX_M_VECTOR_TABLE_H_
|
||||
|
||||
#ifdef _ASMLANGUAGE
|
||||
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <sys/util.h>
|
||||
|
||||
GTEXT(__start)
|
||||
GTEXT(_vector_table)
|
||||
|
||||
GTEXT(z_arm_reset)
|
||||
GTEXT(z_arm_nmi)
|
||||
GTEXT(z_arm_hard_fault)
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
GTEXT(z_arm_svc)
|
||||
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
|
||||
GTEXT(z_arm_mpu_fault)
|
||||
GTEXT(z_arm_bus_fault)
|
||||
GTEXT(z_arm_usage_fault)
|
||||
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
|
||||
GTEXT(z_arm_secure_fault)
|
||||
#endif /* CONFIG_ARM_SECURE_FIRMWARE */
|
||||
GTEXT(z_arm_svc)
|
||||
GTEXT(z_arm_debug_monitor)
|
||||
#else
|
||||
#error Unknown ARM architecture
|
||||
#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
|
||||
GTEXT(z_arm_pendsv)
|
||||
GTEXT(z_arm_reserved)
|
||||
|
||||
GTEXT(z_arm_prep_c)
|
||||
GTEXT(_isr_wrapper)
|
||||
|
||||
#else /* _ASMLANGUAGE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _ASMLANGUAGE
|
||||
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <misc/util.h>
|
||||
|
||||
GTEXT(__start)
|
||||
GTEXT(_vector_table)
|
||||
|
||||
GTEXT(__reset)
|
||||
GTEXT(__nmi)
|
||||
GTEXT(__hard_fault)
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
GTEXT(__svc)
|
||||
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
|
||||
GTEXT(__mpu_fault)
|
||||
GTEXT(__bus_fault)
|
||||
GTEXT(__usage_fault)
|
||||
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
|
||||
GTEXT(__secure_fault)
|
||||
#endif /* CONFIG_ARM_SECURE_FIRMWARE */
|
||||
GTEXT(__svc)
|
||||
GTEXT(__debug_monitor)
|
||||
#else
|
||||
#error Unknown ARM architecture
|
||||
#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
|
||||
GTEXT(__pendsv)
|
||||
GTEXT(__reserved)
|
||||
|
||||
GTEXT(_PrepC)
|
||||
GTEXT(_isr_wrapper)
|
||||
|
||||
#else
|
||||
|
||||
extern void *_vector_table[];
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#endif /* ZEPHYR_ARCH_ARM_CORE_CORTEX_M_VECTOR_TABLE_H_ */
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
/* Copied from linker.ld */
|
||||
|
||||
/* Reserved 4 bytes to save vector table base address */
|
||||
SECTION_PROLOGUE(.vt_pointer,(NOLOAD),)
|
||||
{
|
||||
*(.vt_pointer_section)
|
||||
*(".vt_pointer_section.*")
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources(
|
||||
vector_table.S
|
||||
reset.S
|
||||
fault.c
|
||||
reboot.c
|
||||
stacks.c
|
||||
)
|
||||
@@ -1,91 +0,0 @@
|
||||
# ARM Cortex-R platform configuration options
|
||||
|
||||
# Copyright (c) 2018 Marvell
|
||||
# Copyright (c) 2018 Lexmark International, Inc.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# NOTE: We have the specific core implementations first and outside of the
|
||||
# if CPU_CORTEX_R block so that SoCs can select which core they are using
|
||||
# without having to select all the options related to that core. Everything
|
||||
# else is captured inside the if CPU_CORTEX_R block so they are not exposed
|
||||
# if one selects a different ARM Cortex Family (Cortex-A or Cortex-M)
|
||||
|
||||
|
||||
config CPU_CORTEX_R4
|
||||
bool
|
||||
select CPU_CORTEX_R
|
||||
select ARMV7_R
|
||||
select ARMV7_R_FP if CPU_HAS_FPU
|
||||
help
|
||||
This option signifies the use of a Cortex-R4 CPU
|
||||
|
||||
config CPU_CORTEX_R5
|
||||
bool
|
||||
select CPU_CORTEX_R
|
||||
select ARMV7_R
|
||||
select ARMV7_R_FP if CPU_HAS_FPU
|
||||
help
|
||||
This option signifies the use of a Cortex-R5 CPU
|
||||
|
||||
if CPU_CORTEX_R
|
||||
|
||||
config ARMV7_R
|
||||
bool
|
||||
select ATOMIC_OPERATIONS_BUILTIN
|
||||
select ISA_ARM
|
||||
help
|
||||
This option signifies the use of an ARMv7-R processor
|
||||
implementation.
|
||||
|
||||
From https://developer.arm.com/products/architecture/cpu-architecture/r-profile:
|
||||
The Armv7-R architecture implements a traditional Arm architecture with
|
||||
multiple modes and supports a Protected Memory System Architecture
|
||||
(PMSA) based on a Memory Protection Unit (MPU). It supports the Arm (32)
|
||||
and Thumb (T32) instruction sets.
|
||||
|
||||
config ARMV7_R_FP
|
||||
bool
|
||||
depends on ARMV7_R
|
||||
help
|
||||
This option signifies the use of an ARMv7-R processor
|
||||
implementation supporting the Floating-Point Extension.
|
||||
|
||||
config ARMV7_EXCEPTION_STACK_SIZE
|
||||
int "Undefined Instruction and Abort stack size (in bytes)"
|
||||
default 256
|
||||
help
|
||||
This option specifies the size of the stack used by the undefined
|
||||
instruction and data abort exception handlers.
|
||||
|
||||
config ARMV7_FIQ_STACK_SIZE
|
||||
int "FIQ stack size (in bytes)"
|
||||
default 256
|
||||
help
|
||||
This option specifies the size of the stack used by the FIQ handler.
|
||||
|
||||
config ARMV7_SVC_STACK_SIZE
|
||||
int "SVC stack size (in bytes)"
|
||||
default 512
|
||||
help
|
||||
This option specifies the size of the stack used by the SVC handler.
|
||||
|
||||
config ARMV7_SYS_STACK_SIZE
|
||||
int "SYS stack size (in bytes)"
|
||||
default 1024
|
||||
help
|
||||
This option specifies the size of the stack used by the system mode.
|
||||
|
||||
if CPU_CORTEX_R
|
||||
|
||||
config RUNTIME_NMI
|
||||
default y
|
||||
|
||||
config GEN_ISR_TABLES
|
||||
default y
|
||||
|
||||
config GEN_IRQ_VECTOR_TABLE
|
||||
default n
|
||||
|
||||
endif # CPU_CORTEX_R
|
||||
|
||||
endif # CPU_CORTEX_R
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Lexmark International, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <kernel_internal.h>
|
||||
#include <kernel_structs.h>
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Fault handler
|
||||
*
|
||||
* This routine is called when fatal error conditions are detected by hardware
|
||||
* and is responsible only for reporting the error. Once reported, it then
|
||||
* invokes the user provided routine _SysFatalErrorHandler() which is
|
||||
* responsible for implementing the error handling policy.
|
||||
*
|
||||
* This is a stub for more exception handling code to be added later.
|
||||
*/
|
||||
void z_arm_fault(z_arch_esf_t *esf, u32_t exc_return)
|
||||
{
|
||||
z_arm_fatal_error(K_ERR_CPU_EXCEPTION, esf);
|
||||
}
|
||||
|
||||
void z_arm_fault_init(void)
|
||||
{
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2014 Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief ARM Cortex-R System Control Block interface
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <misc/util.h>
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Reset the system
|
||||
*
|
||||
* This routine resets the processor.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void __weak sys_arch_reboot(int type)
|
||||
{
|
||||
ARG_UNUSED(type);
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2014 Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Reset handler
|
||||
*
|
||||
* Reset handler that prepares the system for running C code.
|
||||
*/
|
||||
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <offsets_short.h>
|
||||
#include "vector_table.h"
|
||||
|
||||
_ASM_FILE_PROLOGUE
|
||||
|
||||
GTEXT(z_arm_reset)
|
||||
GDATA(_interrupt_stack)
|
||||
GDATA(z_arm_svc_stack)
|
||||
GDATA(z_arm_sys_stack)
|
||||
GDATA(z_arm_fiq_stack)
|
||||
GDATA(z_arm_abort_stack)
|
||||
GDATA(z_arm_undef_stack)
|
||||
|
||||
#define STACK_MARGIN 4
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Reset vector
|
||||
*
|
||||
* Ran when the system comes out of reset. The processor is in thread mode with
|
||||
* privileged level. At this point, the main stack pointer (MSP) is already
|
||||
* pointing to a valid area in SRAM.
|
||||
*
|
||||
* When these steps are completed, jump to z_arm_prep_c(), which will finish
|
||||
* setting up the system for running C code.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
SECTION_SUBSEC_FUNC(TEXT, _reset_section, z_arm_reset)
|
||||
SECTION_SUBSEC_FUNC(TEXT,_reset_section,__start)
|
||||
mov r0, #0
|
||||
mov r1, #0
|
||||
mov r2, #0
|
||||
mov r3, #0
|
||||
mov r4, #0
|
||||
mov r5, #0
|
||||
mov r6, #0
|
||||
mov r7, #0
|
||||
mov r8, #0
|
||||
mov r9, #0
|
||||
mov r10, #0
|
||||
mov r11, #0
|
||||
mov r12, #0
|
||||
mov r14, #0
|
||||
|
||||
/* lock interrupts: will get unlocked when switch to main task */
|
||||
cpsid if
|
||||
|
||||
/* Setup FIQ stack */
|
||||
msr CPSR_c, #(MODE_FIQ | I_BIT | F_BIT)
|
||||
ldr sp, =(z_arm_fiq_stack + CONFIG_ARMV7_FIQ_STACK_SIZE - STACK_MARGIN)
|
||||
|
||||
/* Setup IRQ stack */
|
||||
msr CPSR_c, #(MODE_IRQ | I_BIT | F_BIT)
|
||||
ldr sp, =(_interrupt_stack + CONFIG_ISR_STACK_SIZE - STACK_MARGIN)
|
||||
|
||||
/* Setup data abort stack */
|
||||
msr CPSR_c, #(MODE_ABT | I_BIT | F_BIT)
|
||||
ldr sp, =(z_arm_abort_stack + CONFIG_ARMV7_EXCEPTION_STACK_SIZE - \
|
||||
STACK_MARGIN)
|
||||
|
||||
/* Setup undefined mode stack */
|
||||
msr CPSR_c, #(MODE_UDF | I_BIT | F_BIT)
|
||||
ldr sp, =(z_arm_undef_stack + CONFIG_ARMV7_EXCEPTION_STACK_SIZE - \
|
||||
STACK_MARGIN)
|
||||
|
||||
/* Setup SVC mode stack */
|
||||
msr CPSR_c, #(MODE_SVC | I_BIT | F_BIT)
|
||||
ldr sp, =(z_arm_svc_stack + CONFIG_ARMV7_SVC_STACK_SIZE - STACK_MARGIN)
|
||||
|
||||
/* Setup System mode stack */
|
||||
msr CPSR_c, #(MODE_SYS | I_BIT | F_BIT)
|
||||
ldr sp, =(z_arm_sys_stack + CONFIG_ARMV7_SYS_STACK_SIZE - STACK_MARGIN)
|
||||
|
||||
/* Setup system control register */
|
||||
mrc p15, 0, r0, c1, c0, 0 /* SCTLR */
|
||||
bic r0, r0, #HIVECS /* Exception vectors from 0-0x1c */
|
||||
mcr p15, 0, r0, c1, c0, 0
|
||||
|
||||
#if defined(CONFIG_WDOG_INIT)
|
||||
/* board-specific watchdog initialization is necessary */
|
||||
bl z_arm_watchdog_init
|
||||
#endif
|
||||
|
||||
b z_arm_prep_c
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Lexmark International, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <cortex_r/stack.h>
|
||||
#include <string.h>
|
||||
|
||||
K_THREAD_STACK_DEFINE(z_arm_fiq_stack, CONFIG_ARMV7_FIQ_STACK_SIZE);
|
||||
K_THREAD_STACK_DEFINE(z_arm_abort_stack, CONFIG_ARMV7_EXCEPTION_STACK_SIZE);
|
||||
K_THREAD_STACK_DEFINE(z_arm_undef_stack, CONFIG_ARMV7_EXCEPTION_STACK_SIZE);
|
||||
K_THREAD_STACK_DEFINE(z_arm_svc_stack, CONFIG_ARMV7_SVC_STACK_SIZE);
|
||||
K_THREAD_STACK_DEFINE(z_arm_sys_stack, CONFIG_ARMV7_SYS_STACK_SIZE);
|
||||
|
||||
#if defined(CONFIG_INIT_STACKS)
|
||||
void z_arm_init_stacks(void)
|
||||
{
|
||||
memset(z_arm_fiq_stack, 0xAA, CONFIG_ARMV7_FIQ_STACK_SIZE);
|
||||
memset(z_arm_svc_stack, 0xAA, CONFIG_ARMV7_SVC_STACK_SIZE);
|
||||
memset(z_arm_abort_stack, 0xAA, CONFIG_ARMV7_EXCEPTION_STACK_SIZE);
|
||||
memset(z_arm_undef_stack, 0xAA, CONFIG_ARMV7_EXCEPTION_STACK_SIZE);
|
||||
memset(&_interrupt_stack, 0xAA, CONFIG_ISR_STACK_SIZE);
|
||||
}
|
||||
#endif
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Marvell
|
||||
* Copyright (c) 2018 Lexmark International, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Populated vector table in ROM
|
||||
*/
|
||||
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include "vector_table.h"
|
||||
|
||||
_ASM_FILE_PROLOGUE
|
||||
|
||||
SECTION_SUBSEC_FUNC(exc_vector_table,_vector_table_section,_vector_table)
|
||||
ldr pc, =z_arm_reset /* offset 0 */
|
||||
ldr pc, =z_arm_undef_instruction /* undef instruction offset 4 */
|
||||
ldr pc, =z_arm_svc /* svc offset 8 */
|
||||
ldr pc, =z_arm_prefetch_abort /* prefetch abort offset 0xc */
|
||||
ldr pc, =z_arm_data_abort /* data abort offset 0x10 */
|
||||
nop /* offset 0x14 */
|
||||
ldr pc, =_isr_wrapper /* IRQ offset 0x18 */
|
||||
ldr pc, =z_arm_nmi /* FIQ offset 0x1c */
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Marvell
|
||||
* Copyright (c) 2018 Lexmark International, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Definitions for the boot vector table
|
||||
*
|
||||
*
|
||||
* Definitions for the boot vector table.
|
||||
*
|
||||
* System exception handler names all have the same format:
|
||||
*
|
||||
* __<exception name with underscores>
|
||||
*
|
||||
* No other symbol has the same format, so they are easy to spot.
|
||||
*/
|
||||
|
||||
#ifndef _VECTOR_TABLE__H_
|
||||
#define _VECTOR_TABLE__H_
|
||||
|
||||
#ifdef _ASMLANGUAGE
|
||||
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <misc/util.h>
|
||||
|
||||
GTEXT(__start)
|
||||
GTEXT(_vector_table)
|
||||
|
||||
GTEXT(z_arm_nmi)
|
||||
GTEXT(z_arm_undef_instruction)
|
||||
GTEXT(z_arm_svc)
|
||||
GTEXT(z_arm_prefetch_abort)
|
||||
GTEXT(z_arm_data_abort)
|
||||
|
||||
GTEXT(z_arm_pendsv)
|
||||
GTEXT(z_arm_reserved)
|
||||
|
||||
GTEXT(z_arm_prep_c)
|
||||
GTEXT(_isr_wrapper)
|
||||
|
||||
#else /* _ASMLANGUAGE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void *_vector_table[];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#endif /* _VECTOR_TABLE__H_ */
|
||||
@@ -6,54 +6,116 @@
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief ARM Cortex-M and Cortex-R power management
|
||||
* @brief ARM Cortex-M power management
|
||||
*
|
||||
*/
|
||||
|
||||
#include <offsets_short.h>
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <arch/cpu.h>
|
||||
#ifdef CONFIG_TICKLESS_IDLE
|
||||
#include <kernel_structs.h>
|
||||
#endif
|
||||
|
||||
_ASM_FILE_PROLOGUE
|
||||
|
||||
GTEXT(z_arm_cpu_idle_init)
|
||||
GTEXT(arch_cpu_idle)
|
||||
GTEXT(arch_cpu_atomic_idle)
|
||||
GTEXT(z_CpuIdleInit)
|
||||
#ifdef CONFIG_SYS_POWER_MANAGEMENT
|
||||
GTEXT(_NanoIdleValGet)
|
||||
GTEXT(_NanoIdleValClear)
|
||||
#endif
|
||||
GTEXT(k_cpu_idle)
|
||||
GTEXT(k_cpu_atomic_idle)
|
||||
|
||||
#if defined(CONFIG_CPU_CORTEX_M)
|
||||
#define _SCB_SCR 0xE000ED10
|
||||
|
||||
#define _SCB_SCR_SEVONPEND (1 << 4)
|
||||
#define _SCB_SCR_SLEEPDEEP (1 << 2)
|
||||
#define _SCB_SCR_SLEEPONEXIT (1 << 1)
|
||||
#define _SCR_INIT_BITS _SCB_SCR_SEVONPEND
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Initialization of CPU idle
|
||||
*
|
||||
* Only called by arch_kernel_init(). Sets SEVONPEND bit once for the system's
|
||||
* Only called by kernel_arch_init(). Sets SEVONPEND bit once for the system's
|
||||
* duration.
|
||||
*
|
||||
* @return N/A
|
||||
*
|
||||
* C function prototype:
|
||||
*
|
||||
* void z_arm_cpu_idle_init(void);
|
||||
* void z_CpuIdleInit (void);
|
||||
*/
|
||||
|
||||
SECTION_FUNC(TEXT, z_arm_cpu_idle_init)
|
||||
#if defined(CONFIG_CPU_CORTEX_M)
|
||||
SECTION_FUNC(TEXT, z_CpuIdleInit)
|
||||
ldr r1, =_SCB_SCR
|
||||
movs.n r2, #_SCR_INIT_BITS
|
||||
str r2, [r1]
|
||||
#endif
|
||||
bx lr
|
||||
|
||||
SECTION_FUNC(TEXT, arch_cpu_idle)
|
||||
#ifdef CONFIG_SYS_POWER_MANAGEMENT
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Get the kernel idle setting
|
||||
*
|
||||
* Returns the kernel idle setting, in ticks. Only called by __systick().
|
||||
*
|
||||
* @return the requested number of ticks for the kernel to be idle
|
||||
*
|
||||
* C function prototype:
|
||||
*
|
||||
* s32_t _NanoIdleValGet (void);
|
||||
*/
|
||||
|
||||
SECTION_FUNC(TEXT, _NanoIdleValGet)
|
||||
ldr r0, =_kernel
|
||||
ldr r0, [r0, #_kernel_offset_to_idle]
|
||||
bx lr
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Clear the kernel idle setting
|
||||
*
|
||||
* Sets the kernel idle setting to 0. Only called by __systick().
|
||||
*
|
||||
* @return N/A
|
||||
*
|
||||
* C function prototype:
|
||||
*
|
||||
* void _NanoIdleValClear (void);
|
||||
*/
|
||||
|
||||
SECTION_FUNC(TEXT, _NanoIdleValClear)
|
||||
ldr r0, =_kernel
|
||||
eors.n r1, r1
|
||||
str r1, [r0, #_kernel_offset_to_idle]
|
||||
bx lr
|
||||
|
||||
#endif /* CONFIG_SYS_POWER_MANAGEMENT */
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Power save idle routine for ARM Cortex-M
|
||||
*
|
||||
* This function will be called by the kernel idle loop or possibly within
|
||||
* an implementation of _sys_power_save_idle in the kernel when the
|
||||
* '_sys_power_save_flag' variable is non-zero. The ARM 'wfi' instruction
|
||||
* will be issued, causing a low-power consumption sleep mode.
|
||||
*
|
||||
* @return N/A
|
||||
*
|
||||
* C function prototype:
|
||||
*
|
||||
* void k_cpu_idle (void);
|
||||
*/
|
||||
|
||||
SECTION_FUNC(TEXT, k_cpu_idle)
|
||||
#ifdef CONFIG_TRACING
|
||||
push {r0, lr}
|
||||
bl sys_trace_idle
|
||||
bl z_sys_trace_idle
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
pop {r0, r1}
|
||||
mov lr, r1
|
||||
@@ -62,8 +124,7 @@ SECTION_FUNC(TEXT, arch_cpu_idle)
|
||||
#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
|
||||
#endif /* CONFIG_TRACING */
|
||||
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) \
|
||||
|| defined(CONFIG_ARMV7_R)
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
cpsie i
|
||||
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
|
||||
/* clear BASEPRI so wfi is awakened by incoming interrupts */
|
||||
@@ -77,10 +138,32 @@ SECTION_FUNC(TEXT, arch_cpu_idle)
|
||||
|
||||
bx lr
|
||||
|
||||
SECTION_FUNC(TEXT, arch_cpu_atomic_idle)
|
||||
/**
|
||||
*
|
||||
* @brief Atomically re-enable interrupts and enter low power mode
|
||||
*
|
||||
* INTERNAL
|
||||
* The requirements for k_cpu_atomic_idle() are as follows:
|
||||
* 1) The enablement of interrupts and entering a low-power mode needs to be
|
||||
* atomic, i.e. there should be no period of time where interrupts are
|
||||
* enabled before the processor enters a low-power mode. See the comments
|
||||
* in k_lifo_get(), for example, of the race condition that occurs
|
||||
* if this requirement is not met.
|
||||
*
|
||||
* 2) After waking up from the low-power mode, the interrupt lockout state
|
||||
* must be restored as indicated in the 'key' input parameter.
|
||||
*
|
||||
* @return N/A
|
||||
*
|
||||
* C function prototype:
|
||||
*
|
||||
* void k_cpu_atomic_idle (unsigned int key);
|
||||
*/
|
||||
|
||||
SECTION_FUNC(TEXT, k_cpu_atomic_idle)
|
||||
#ifdef CONFIG_TRACING
|
||||
push {r0, lr}
|
||||
bl sys_trace_idle
|
||||
bl z_sys_trace_idle
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
pop {r0, r1}
|
||||
mov lr, r1
|
||||
@@ -102,8 +185,7 @@ SECTION_FUNC(TEXT, arch_cpu_atomic_idle)
|
||||
|
||||
/* r0: interrupt mask from caller */
|
||||
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) \
|
||||
|| defined(CONFIG_ARMV7_R)
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
/* No BASEPRI, call wfe directly (SEVONPEND set in z_CpuIdleInit()) */
|
||||
wfe
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief ARM Cortex-M and Cortex-R exception/interrupt exit API
|
||||
* @brief ARM Cortex-M exception/interrupt exit API
|
||||
*
|
||||
*
|
||||
* Provides functions for performing kernel handling when exiting exceptions or
|
||||
@@ -14,19 +14,16 @@
|
||||
* wrapped around by _isr_wrapper()).
|
||||
*/
|
||||
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <kernel_structs.h>
|
||||
#include <offsets_short.h>
|
||||
#include <toolchain.h>
|
||||
#include <arch/cpu.h>
|
||||
|
||||
_ASM_FILE_PROLOGUE
|
||||
|
||||
GTEXT(z_arm_exc_exit)
|
||||
GTEXT(z_arm_int_exit)
|
||||
GTEXT(z_ExcExit)
|
||||
GTEXT(_IntExit)
|
||||
GDATA(_kernel)
|
||||
#if defined(CONFIG_CPU_CORTEX_R)
|
||||
GTEXT(z_arm_pendsv)
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -34,13 +31,13 @@ GTEXT(z_arm_pendsv)
|
||||
* directly in vector table
|
||||
*
|
||||
* Kernel allows installing interrupt handlers (ISRs) directly into the vector
|
||||
* table to get the lowest interrupt latency possible. This allows the ISR to
|
||||
* be invoked directly without going through a software interrupt table.
|
||||
* However, upon exiting the ISR, some kernel work must still be performed,
|
||||
* namely possible context switching. While ISRs connected in the software
|
||||
* interrupt table do this automatically via a wrapper, ISRs connected directly
|
||||
* in the vector table must invoke z_arm_int_exit() as the *very last* action
|
||||
* before returning.
|
||||
* table to get the lowest interrupt latency possible. This allows the ISR to be
|
||||
* invoked directly without going through a software interrupt table. However,
|
||||
* upon exiting the ISR, some kernel work must still be performed, namely
|
||||
* possible context switching. While ISRs connected in the software interrupt
|
||||
* table do this automatically via a wrapper, ISRs connected directly in the
|
||||
* vector table must invoke _IntExit() as the *very last* action before
|
||||
* returning.
|
||||
*
|
||||
* e.g.
|
||||
*
|
||||
@@ -48,33 +45,27 @@ GTEXT(z_arm_pendsv)
|
||||
* {
|
||||
* printk("in %s\n", __FUNCTION__);
|
||||
* doStuff();
|
||||
* z_arm_int_exit();
|
||||
* _IntExit();
|
||||
* }
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
SECTION_SUBSEC_FUNC(TEXT, _HandlerModeExit, z_arm_int_exit)
|
||||
SECTION_SUBSEC_FUNC(TEXT, _HandlerModeExit, _IntExit)
|
||||
|
||||
/* z_arm_int_exit falls through to z_arm_exc_exit (they are aliases of each
|
||||
* other)
|
||||
*/
|
||||
/* _IntExit falls through to z_ExcExit (they are aliases of each other) */
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Kernel housekeeping when exiting exception handler installed
|
||||
* directly in vector table
|
||||
*
|
||||
* See z_arm_int_exit().
|
||||
* See _IntExit().
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
SECTION_SUBSEC_FUNC(TEXT, _HandlerModeExit, z_arm_exc_exit)
|
||||
#if defined(CONFIG_CPU_CORTEX_R)
|
||||
/* r0 contains the caller mode */
|
||||
push {r0, lr}
|
||||
#endif
|
||||
SECTION_SUBSEC_FUNC(TEXT, _HandlerModeExit, z_ExcExit)
|
||||
|
||||
#ifdef CONFIG_PREEMPT_ENABLED
|
||||
ldr r0, =_kernel
|
||||
@@ -85,14 +76,10 @@ SECTION_SUBSEC_FUNC(TEXT, _HandlerModeExit, z_arm_exc_exit)
|
||||
cmp r0, r1
|
||||
beq _EXIT_EXC
|
||||
|
||||
#if defined(CONFIG_CPU_CORTEX_M)
|
||||
/* context switch required, pend the PendSV exception */
|
||||
ldr r1, =_SCS_ICSR
|
||||
ldr r2, =_SCS_ICSR_PENDSV
|
||||
str r2, [r1]
|
||||
#elif defined(CONFIG_CPU_CORTEX_R)
|
||||
bl z_arm_pendsv
|
||||
#endif
|
||||
|
||||
_ExcExitWithGdbStub:
|
||||
|
||||
@@ -100,7 +87,6 @@ _EXIT_EXC:
|
||||
#endif /* CONFIG_PREEMPT_ENABLED */
|
||||
|
||||
#ifdef CONFIG_STACK_SENTINEL
|
||||
#if defined(CONFIG_CPU_CORTEX_M)
|
||||
push {r0, lr}
|
||||
bl z_check_stack_sentinel
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
@@ -109,41 +95,5 @@ _EXIT_EXC:
|
||||
#else
|
||||
pop {r0, lr}
|
||||
#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
|
||||
#else
|
||||
bl z_check_stack_sentinel
|
||||
#endif /* CONFIG_CPU_CORTEX_M */
|
||||
#endif /* CONFIG_STACK_SENTINEL */
|
||||
|
||||
#if defined(CONFIG_CPU_CORTEX_M)
|
||||
bx lr
|
||||
#elif defined(CONFIG_CPU_CORTEX_R)
|
||||
/* Restore the caller mode to r0 */
|
||||
pop {r0, lr}
|
||||
|
||||
/*
|
||||
* Restore r0-r3, r12 and lr stored into the process stack by the mode
|
||||
* entry function. These registers are saved by _isr_wrapper for IRQ mode
|
||||
* and z_arm_svc for SVC mode.
|
||||
*
|
||||
* r0-r3 are either the values from the thread before it was switched out
|
||||
* or they are the args to _new_thread for a new thread.
|
||||
*/
|
||||
push {r4, r5}
|
||||
|
||||
cmp r0, #RET_FROM_SVC
|
||||
cps #MODE_SYS
|
||||
ldmia sp!, {r0-r5}
|
||||
beq _svc_exit
|
||||
|
||||
cps #MODE_IRQ
|
||||
b _exc_exit
|
||||
|
||||
_svc_exit:
|
||||
cps #MODE_SVC
|
||||
|
||||
_exc_exit:
|
||||
mov r12, r4
|
||||
mov lr, r5
|
||||
pop {r4, r5}
|
||||
movs pc, lr
|
||||
#endif
|
||||
|
||||
@@ -6,94 +6,106 @@
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Kernel fatal error handler for ARM Cortex-M and Cortex-R
|
||||
* @brief Kernel fatal error handler for ARM Cortex-M
|
||||
*
|
||||
* This module provides the z_arm_fatal_error() routine for ARM Cortex-M
|
||||
* and Cortex-R CPUs.
|
||||
* This module provides the z_NanoFatalErrorHandler() routine for ARM Cortex-M.
|
||||
*/
|
||||
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <kernel.h>
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_DECLARE(os);
|
||||
|
||||
static void esf_dump(const z_arch_esf_t *esf)
|
||||
{
|
||||
LOG_ERR("r0/a1: 0x%08x r1/a2: 0x%08x r2/a3: 0x%08x",
|
||||
esf->basic.a1, esf->basic.a2, esf->basic.a3);
|
||||
LOG_ERR("r3/a4: 0x%08x r12/ip: 0x%08x r14/lr: 0x%08x",
|
||||
esf->basic.a4, esf->basic.ip, esf->basic.lr);
|
||||
LOG_ERR(" xpsr: 0x%08x", esf->basic.xpsr);
|
||||
#if defined(CONFIG_FLOAT) && defined(CONFIG_FP_SHARING)
|
||||
for (int i = 0; i < 16; i += 4) {
|
||||
LOG_ERR("s[%2d]: 0x%08x s[%2d]: 0x%08x"
|
||||
" s[%2d]: 0x%08x s[%2d]: 0x%08x",
|
||||
i, (u32_t)esf->s[i],
|
||||
i + 1, (u32_t)esf->s[i + 1],
|
||||
i + 2, (u32_t)esf->s[i + 2],
|
||||
i + 3, (u32_t)esf->s[i + 3]);
|
||||
}
|
||||
LOG_ERR("fpscr: 0x%08x", esf->fpscr);
|
||||
#endif
|
||||
LOG_ERR("Faulting instruction address (r15/pc): 0x%08x",
|
||||
esf->basic.pc);
|
||||
}
|
||||
|
||||
void z_arm_fatal_error(unsigned int reason, const z_arch_esf_t *esf)
|
||||
{
|
||||
|
||||
if (esf != NULL) {
|
||||
esf_dump(esf);
|
||||
}
|
||||
z_fatal_error(reason, esf);
|
||||
}
|
||||
#include <kernel_structs.h>
|
||||
#include <misc/printk.h>
|
||||
#include <logging/log_ctrl.h>
|
||||
|
||||
/**
|
||||
* @brief Handle a software-generated fatal exception
|
||||
* (e.g. kernel oops, panic, etc.).
|
||||
*
|
||||
* Notes:
|
||||
* - the function is invoked in SVC Handler
|
||||
* - if triggered from nPRIV mode, only oops and stack fail error reasons
|
||||
* may be propagated to the fault handling process.
|
||||
* - We expect the supplied exception stack frame to always be a valid
|
||||
* frame. That is because, if the ESF cannot be stacked during an SVC,
|
||||
* a processor fault (e.g. stacking error) will be generated, and the
|
||||
* fault handler will executed insted of the SVC.
|
||||
* @brief Kernel fatal error handler
|
||||
*
|
||||
* @param esf exception frame
|
||||
* This routine is called when fatal error conditions are detected by software
|
||||
* and is responsible only for reporting the error. Once reported, it then
|
||||
* invokes the user provided routine z_SysFatalErrorHandler() which is
|
||||
* responsible for implementing the error handling policy.
|
||||
*
|
||||
* The caller is expected to always provide a usable ESF. In the event that the
|
||||
* fatal error does not have a hardware generated ESF, the caller should either
|
||||
* create its own or use a pointer to the global default ESF <_default_esf>.
|
||||
*
|
||||
* Unlike other arches, this function may return if z_SysFatalErrorHandler
|
||||
* determines that only the current thread should be aborted and the CPU
|
||||
* was in handler mode. PendSV will be asserted in this case and the current
|
||||
* thread taken off the run queue. Leaving the exception will immediately
|
||||
* trigger a context switch.
|
||||
*
|
||||
* @param reason the reason that the handler was called
|
||||
* @param pEsf pointer to the exception stack frame
|
||||
*
|
||||
* @return This function does not return.
|
||||
*/
|
||||
void z_do_kernel_oops(const z_arch_esf_t *esf)
|
||||
void z_NanoFatalErrorHandler(unsigned int reason,
|
||||
const NANO_ESF *pEsf)
|
||||
{
|
||||
/* Stacked R0 holds the exception reason. */
|
||||
unsigned int reason = esf->basic.r0;
|
||||
LOG_PANIC();
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
if ((__get_CONTROL() & CONTROL_nPRIV_Msk) == CONTROL_nPRIV_Msk) {
|
||||
/*
|
||||
* Exception triggered from nPRIV mode.
|
||||
*
|
||||
* User mode is only allowed to induce oopses and stack check
|
||||
* failures via software-triggered system fatal exceptions.
|
||||
*/
|
||||
if (!((esf->basic.r0 == K_ERR_KERNEL_OOPS) ||
|
||||
(esf->basic.r0 == K_ERR_STACK_CHK_FAIL))) {
|
||||
switch (reason) {
|
||||
case _NANO_ERR_HW_EXCEPTION:
|
||||
printk("***** Hardware exception *****\n");
|
||||
break;
|
||||
#if defined(CONFIG_STACK_CANARIES) || defined(CONFIG_STACK_SENTINEL) || \
|
||||
defined(CONFIG_HW_STACK_PROTECTION) || \
|
||||
defined(CONFIG_USERSPACE)
|
||||
case _NANO_ERR_STACK_CHK_FAIL:
|
||||
printk("***** Stack Check Fail! *****\n");
|
||||
break;
|
||||
#endif /* CONFIG_STACK_CANARIES */
|
||||
|
||||
reason = K_ERR_KERNEL_OOPS;
|
||||
}
|
||||
case _NANO_ERR_ALLOCATION_FAIL:
|
||||
printk("**** Kernel Allocation Failure! ****\n");
|
||||
break;
|
||||
|
||||
case _NANO_ERR_KERNEL_OOPS:
|
||||
printk("***** Kernel OOPS! *****\n");
|
||||
break;
|
||||
|
||||
case _NANO_ERR_KERNEL_PANIC:
|
||||
printk("***** Kernel Panic! *****\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
printk("**** Unknown Fatal Error %d! ****\n", reason);
|
||||
break;
|
||||
}
|
||||
printk("Current thread ID = %p\n"
|
||||
"Faulting instruction address = 0x%x\n",
|
||||
k_current_get(), pEsf->pc);
|
||||
|
||||
#endif /* CONFIG_USERSPACE */
|
||||
z_arm_fatal_error(reason, esf);
|
||||
/*
|
||||
* Now that the error has been reported, call the user implemented
|
||||
* policy
|
||||
* to respond to the error. The decisions as to what responses are
|
||||
* appropriate to the various errors are something the customer must
|
||||
* decide.
|
||||
*/
|
||||
|
||||
z_SysFatalErrorHandler(reason, pEsf);
|
||||
}
|
||||
|
||||
FUNC_NORETURN void arch_syscall_oops(void *ssf_ptr)
|
||||
void z_do_kernel_oops(const NANO_ESF *esf)
|
||||
{
|
||||
z_NanoFatalErrorHandler(esf->r0, esf);
|
||||
}
|
||||
|
||||
FUNC_NORETURN void z_arch_syscall_oops(void *ssf_ptr)
|
||||
{
|
||||
u32_t *ssf_contents = ssf_ptr;
|
||||
z_arch_esf_t oops_esf = { 0 };
|
||||
NANO_ESF oops_esf = { 0 };
|
||||
|
||||
/* TODO: Copy the rest of the register set out of ssf_ptr */
|
||||
oops_esf.basic.pc = ssf_contents[3];
|
||||
LOG_PANIC();
|
||||
|
||||
z_arm_fatal_error(K_ERR_KERNEL_OOPS, &oops_esf);
|
||||
oops_esf.pc = ssf_contents[3];
|
||||
|
||||
z_do_kernel_oops(&oops_esf);
|
||||
CODE_UNREACHABLE;
|
||||
}
|
||||
|
||||
909
arch/arm/core/fault.c
Normal file
909
arch/arm/core/fault.c
Normal file
@@ -0,0 +1,909 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Common fault handler for ARM Cortex-M
|
||||
*
|
||||
* Common fault handler for ARM Cortex-M processors.
|
||||
*/
|
||||
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
|
||||
#include <kernel.h>
|
||||
#include <kernel_structs.h>
|
||||
#include <inttypes.h>
|
||||
#include <exc_handle.h>
|
||||
#include <logging/log_ctrl.h>
|
||||
|
||||
#ifdef CONFIG_PRINTK
|
||||
#include <misc/printk.h>
|
||||
#define PR_EXC(...) printk(__VA_ARGS__)
|
||||
#define STORE_xFAR(reg_var, reg) u32_t reg_var = (u32_t)reg
|
||||
#else
|
||||
#define PR_EXC(...)
|
||||
#define STORE_xFAR(reg_var, reg)
|
||||
#endif /* CONFIG_PRINTK */
|
||||
|
||||
#if (CONFIG_FAULT_DUMP == 2)
|
||||
#define PR_FAULT_INFO(...) PR_EXC(__VA_ARGS__)
|
||||
#else
|
||||
#define PR_FAULT_INFO(...)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ARM_MPU) && defined(CONFIG_CPU_HAS_NXP_MPU)
|
||||
#define EMN(edr) (((edr) & SYSMPU_EDR_EMN_MASK) >> SYSMPU_EDR_EMN_SHIFT)
|
||||
#define EACD(edr) (((edr) & SYSMPU_EDR_EACD_MASK) >> SYSMPU_EDR_EACD_SHIFT)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ARM_SECURE_FIRMWARE) || \
|
||||
defined(CONFIG_ARM_NONSECURE_FIRMWARE)
|
||||
|
||||
/* Exception Return (EXC_RETURN) is provided in LR upon exception entry.
|
||||
* It is used to perform an exception return and to detect possible state
|
||||
* transition upon exception.
|
||||
*/
|
||||
|
||||
/* Prefix. Indicates that this is an EXC_RETURN value.
|
||||
* This field reads as 0b11111111.
|
||||
*/
|
||||
#define EXC_RETURN_INDICATOR_PREFIX (0xFF << 24)
|
||||
/* bit[0]: Exception Secure. The security domain the exception was taken to. */
|
||||
#define EXC_RETURN_EXCEPTION_SECURE_Pos 0
|
||||
#define EXC_RETURN_EXCEPTION_SECURE_Msk \
|
||||
BIT(EXC_RETURN_EXCEPTION_SECURE_Pos)
|
||||
#define EXC_RETURN_EXCEPTION_SECURE_Non_Secure 0
|
||||
#define EXC_RETURN_EXCEPTION_SECURE_Secure EXC_RETURN_EXCEPTION_SECURE_Msk
|
||||
/* bit[2]: Stack Pointer selection. */
|
||||
#define EXC_RETURN_SPSEL_Pos 2
|
||||
#define EXC_RETURN_SPSEL_Msk BIT(EXC_RETURN_SPSEL_Pos)
|
||||
#define EXC_RETURN_SPSEL_MAIN 0
|
||||
#define EXC_RETURN_SPSEL_PROCESS EXC_RETURN_SPSEL_Msk
|
||||
/* bit[3]: Mode. Indicates the Mode that was stacked from. */
|
||||
#define EXC_RETURN_MODE_Pos 3
|
||||
#define EXC_RETURN_MODE_Msk BIT(EXC_RETURN_MODE_Pos)
|
||||
#define EXC_RETURN_MODE_HANDLER 0
|
||||
#define EXC_RETURN_MODE_THREAD EXC_RETURN_MODE_Msk
|
||||
/* bit[4]: Stack frame type. Indicates whether the stack frame is a standard
|
||||
* integer only stack frame or an extended floating-point stack frame.
|
||||
*/
|
||||
#define EXC_RETURN_STACK_FRAME_TYPE_Pos 4
|
||||
#define EXC_RETURN_STACK_FRAME_TYPE_Msk BIT(EXC_RETURN_STACK_FRAME_TYPE_Pos)
|
||||
#define EXC_RETURN_STACK_FRAME_TYPE_EXTENDED 0
|
||||
#define EXC_RETURN_STACK_FRAME_TYPE_STANDARD EXC_RETURN_STACK_FRAME_TYPE_Msk
|
||||
/* bit[5]: Default callee register stacking. Indicates whether the default
|
||||
* stacking rules apply, or whether the callee registers are already on the
|
||||
* stack.
|
||||
*/
|
||||
#define EXC_RETURN_CALLEE_STACK_Pos 5
|
||||
#define EXC_RETURN_CALLEE_STACK_Msk BIT(EXC_RETURN_CALLEE_STACK_Pos)
|
||||
#define EXC_RETURN_CALLEE_STACK_SKIPPED 0
|
||||
#define EXC_RETURN_CALLEE_STACK_DEFAULT EXC_RETURN_CALLEE_STACK_Msk
|
||||
/* bit[6]: Secure or Non-secure stack. Indicates whether a Secure or
|
||||
* Non-secure stack is used to restore stack frame on exception return.
|
||||
*/
|
||||
#define EXC_RETURN_RETURN_STACK_Pos 6
|
||||
#define EXC_RETURN_RETURN_STACK_Msk BIT(EXC_RETURN_RETURN_STACK_Pos)
|
||||
#define EXC_RETURN_RETURN_STACK_Non_Secure 0
|
||||
#define EXC_RETURN_RETURN_STACK_Secure EXC_RETURN_RETURN_STACK_Msk
|
||||
|
||||
/* Integrity signature for an ARMv8-M implementation */
|
||||
#if defined(CONFIG_ARMV7_M_ARMV8_M_FP)
|
||||
#define INTEGRITY_SIGNATURE_STD 0xFEFA125BUL
|
||||
#define INTEGRITY_SIGNATURE_EXT 0xFEFA125AUL
|
||||
#else
|
||||
#define INTEGRITY_SIGNATURE 0xFEFA125BUL
|
||||
#endif /* CONFIG_ARMV7_M_ARMV8_M_FP */
|
||||
/* Size (in words) of the additional state context that is pushed
|
||||
* to the Secure stack during a Non-Secure exception entry.
|
||||
*/
|
||||
#define ADDITIONAL_STATE_CONTEXT_WORDS 10
|
||||
#endif /* CONFIG_ARM_SECURE_FIRMWARE || CONFIG_ARM_NONSECURE_FIRMWARE */
|
||||
|
||||
/**
|
||||
*
|
||||
* Dump information regarding fault (FAULT_DUMP == 1)
|
||||
*
|
||||
* Dump information regarding the fault when CONFIG_FAULT_DUMP is set to 1
|
||||
* (short form).
|
||||
*
|
||||
* eg. (precise bus error escalated to hard fault):
|
||||
*
|
||||
* Fault! EXC #3
|
||||
* HARD FAULT: Escalation (see below)!
|
||||
* MMFSR: 0x00000000, BFSR: 0x00000082, UFSR: 0x00000000
|
||||
* BFAR: 0xff001234
|
||||
*
|
||||
*
|
||||
*
|
||||
* Dump information regarding fault (FAULT_DUMP == 2)
|
||||
*
|
||||
* Dump information regarding the fault when CONFIG_FAULT_DUMP is set to 2
|
||||
* (long form), and return the error code for the kernel to identify the fatal
|
||||
* error reason.
|
||||
*
|
||||
* eg. (precise bus error escalated to hard fault):
|
||||
*
|
||||
* ***** HARD FAULT *****
|
||||
* Fault escalation (see below)
|
||||
* ***** BUS FAULT *****
|
||||
* Precise data bus error
|
||||
* Address: 0xff001234
|
||||
*
|
||||
*/
|
||||
|
||||
#if (CONFIG_FAULT_DUMP == 1)
|
||||
static void FaultShow(const NANO_ESF *esf, int fault)
|
||||
{
|
||||
PR_EXC("Fault! EXC #%d\n", fault);
|
||||
|
||||
#if defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
|
||||
PR_EXC("MMFSR: 0x%x, BFSR: 0x%x, UFSR: 0x%x\n",
|
||||
SCB_MMFSR, SCB_BFSR, SCB_UFSR);
|
||||
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
|
||||
PR_EXC("SFSR: 0x%x\n", SAU->SFSR);
|
||||
#endif /* CONFIG_ARM_SECURE_FIRMWARE */
|
||||
#endif /* CONFIG_ARMV7_M_ARMV8_M_MAINLINE */
|
||||
}
|
||||
#else
|
||||
/* For Dump level 2, detailed information is generated by the
|
||||
* fault handling functions for individual fault conditions, so this
|
||||
* function is left empty.
|
||||
*
|
||||
* For Dump level 0, no information needs to be generated.
|
||||
*/
|
||||
static void FaultShow(const NANO_ESF *esf, int fault)
|
||||
{
|
||||
(void)esf;
|
||||
(void)fault;
|
||||
}
|
||||
#endif /* FAULT_DUMP == 1 */
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
Z_EXC_DECLARE(z_arch_user_string_nlen);
|
||||
|
||||
static const struct z_exc_handle exceptions[] = {
|
||||
Z_EXC_HANDLE(z_arch_user_string_nlen)
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Perform an assessment whether an MPU fault shall be
|
||||
* treated as recoverable.
|
||||
*
|
||||
* @return 1 if error is recoverable, otherwise return 0.
|
||||
*/
|
||||
static int MemoryFaultIsRecoverable(NANO_ESF *esf)
|
||||
{
|
||||
#ifdef CONFIG_USERSPACE
|
||||
for (int i = 0; i < ARRAY_SIZE(exceptions); i++) {
|
||||
/* Mask out instruction mode */
|
||||
u32_t start = (u32_t)exceptions[i].start & ~0x1;
|
||||
u32_t end = (u32_t)exceptions[i].end & ~0x1;
|
||||
|
||||
if (esf->pc >= start && esf->pc < end) {
|
||||
esf->pc = (u32_t)(exceptions[i].fixup);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
/* HardFault is used for all fault conditions on ARMv6-M. */
|
||||
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
|
||||
|
||||
#if defined(CONFIG_MPU_STACK_GUARD) || defined(CONFIG_USERSPACE)
|
||||
u32_t z_check_thread_stack_fail(const u32_t fault_addr,
|
||||
const u32_t psp);
|
||||
#endif /* CONFIG_MPU_STACK_GUARD || defined(CONFIG_USERSPACE) */
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Dump MPU fault information
|
||||
*
|
||||
* See _FaultDump() for example.
|
||||
*
|
||||
* @return error code to identify the fatal error reason
|
||||
*/
|
||||
static u32_t MpuFault(NANO_ESF *esf, int fromHardFault)
|
||||
{
|
||||
u32_t reason = _NANO_ERR_HW_EXCEPTION;
|
||||
u32_t mmfar = -EINVAL;
|
||||
|
||||
PR_FAULT_INFO("***** MPU FAULT *****\n");
|
||||
|
||||
if ((SCB->CFSR & SCB_CFSR_MSTKERR_Msk) != 0) {
|
||||
PR_FAULT_INFO(" Stacking error (context area might be"
|
||||
" not valid)\n");
|
||||
}
|
||||
if ((SCB->CFSR & SCB_CFSR_MUNSTKERR_Msk) != 0) {
|
||||
PR_FAULT_INFO(" Unstacking error\n");
|
||||
}
|
||||
if ((SCB->CFSR & SCB_CFSR_DACCVIOL_Msk) != 0) {
|
||||
PR_FAULT_INFO(" Data Access Violation\n");
|
||||
/* In a fault handler, to determine the true faulting address:
|
||||
* 1. Read and save the MMFAR value.
|
||||
* 2. Read the MMARVALID bit in the MMFSR.
|
||||
* The MMFAR address is valid only if this bit is 1.
|
||||
*
|
||||
* Software must follow this sequence because another higher
|
||||
* priority exception might change the MMFAR value.
|
||||
*/
|
||||
mmfar = SCB->MMFAR;
|
||||
|
||||
if ((SCB->CFSR & SCB_CFSR_MMARVALID_Msk) != 0) {
|
||||
PR_EXC(" MMFAR Address: 0x%x\n", mmfar);
|
||||
if (fromHardFault) {
|
||||
/* clear SCB_MMAR[VALID] to reset */
|
||||
SCB->CFSR &= ~SCB_CFSR_MMARVALID_Msk;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((SCB->CFSR & SCB_CFSR_IACCVIOL_Msk) != 0) {
|
||||
PR_FAULT_INFO(" Instruction Access Violation\n");
|
||||
}
|
||||
#if defined(CONFIG_ARMV7_M_ARMV8_M_FP)
|
||||
if ((SCB->CFSR & SCB_CFSR_MLSPERR_Msk) != 0) {
|
||||
PR_FAULT_INFO(
|
||||
" Floating-point lazy state preservation error\n");
|
||||
}
|
||||
#endif /* !defined(CONFIG_ARMV7_M_ARMV8_M_FP) */
|
||||
|
||||
/* When stack protection is enabled, we need to assess
|
||||
* if the memory violation error is a stack corruption.
|
||||
*
|
||||
* By design, being a Stacking MemManage fault is a necessary
|
||||
* and sufficient condition for a thread stack corruption.
|
||||
*/
|
||||
if (SCB->CFSR & SCB_CFSR_MSTKERR_Msk) {
|
||||
#if defined(CONFIG_MPU_STACK_GUARD) || defined(CONFIG_USERSPACE)
|
||||
/* MemManage Faults are always banked between security
|
||||
* states. Therefore, we can safely assume the fault
|
||||
* originated from the same security state.
|
||||
*
|
||||
* As we only assess thread stack corruption, we only
|
||||
* process the error further if the stack frame is on
|
||||
* PSP. For always-banked MemManage Fault, this is
|
||||
* equivalent to inspecting the RETTOBASE flag.
|
||||
*/
|
||||
if (SCB->ICSR & SCB_ICSR_RETTOBASE_Msk) {
|
||||
u32_t min_stack_ptr = z_check_thread_stack_fail(mmfar,
|
||||
((u32_t) &esf[0]));
|
||||
|
||||
if (min_stack_ptr) {
|
||||
/* When MemManage Stacking Error has occurred,
|
||||
* the stack context frame might be corrupted
|
||||
* but the stack pointer may have actually
|
||||
* descent below the allowed (thread) stack
|
||||
* area. We may face a problem with un-stacking
|
||||
* the frame, upon the exception return, if we
|
||||
* do not have sufficient access permissions to
|
||||
* read the corrupted stack frame. Therefore,
|
||||
* we manually force the stack pointer to the
|
||||
* lowest allowed position, inside the thread's
|
||||
* stack.
|
||||
*
|
||||
* Note:
|
||||
* The PSP will normally be adjusted in a tail-
|
||||
* chained exception performing context switch,
|
||||
* after aborting the corrupted thread. The
|
||||
* adjustment, here, is required as tail-chain
|
||||
* cannot always be guaranteed.
|
||||
*
|
||||
* The manual adjustment of PSP is safe, as we
|
||||
* will not be re-scheduling this thread again
|
||||
* for execution; thread stack corruption is a
|
||||
* fatal error and a thread that corrupted its
|
||||
* stack needs to be aborted.
|
||||
*/
|
||||
__set_PSP(min_stack_ptr);
|
||||
|
||||
reason = _NANO_ERR_STACK_CHK_FAIL;
|
||||
} else {
|
||||
__ASSERT(0,
|
||||
"Stacking error not a stack fail\n");
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)mmfar;
|
||||
__ASSERT(0,
|
||||
"Stacking error without stack guard / User-mode support\n");
|
||||
#endif /* CONFIG_MPU_STACK_GUARD || CONFIG_USERSPACE */
|
||||
}
|
||||
|
||||
/* clear MMFSR sticky bits */
|
||||
SCB->CFSR |= SCB_CFSR_MEMFAULTSR_Msk;
|
||||
|
||||
/* Assess whether system shall ignore/recover from this MPU fault. */
|
||||
if (MemoryFaultIsRecoverable(esf)) {
|
||||
reason = _NANO_ERR_RECOVERABLE;
|
||||
}
|
||||
|
||||
return reason;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Dump bus fault information
|
||||
*
|
||||
* See _FaultDump() for example.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
static int BusFault(NANO_ESF *esf, int fromHardFault)
|
||||
{
|
||||
u32_t reason = _NANO_ERR_HW_EXCEPTION;
|
||||
|
||||
PR_FAULT_INFO("***** BUS FAULT *****\n");
|
||||
|
||||
if (SCB->CFSR & SCB_CFSR_STKERR_Msk) {
|
||||
PR_FAULT_INFO(" Stacking error\n");
|
||||
}
|
||||
if (SCB->CFSR & SCB_CFSR_UNSTKERR_Msk) {
|
||||
PR_FAULT_INFO(" Unstacking error\n");
|
||||
}
|
||||
if (SCB->CFSR & SCB_CFSR_PRECISERR_Msk) {
|
||||
PR_FAULT_INFO(" Precise data bus error\n");
|
||||
/* In a fault handler, to determine the true faulting address:
|
||||
* 1. Read and save the BFAR value.
|
||||
* 2. Read the BFARVALID bit in the BFSR.
|
||||
* The BFAR address is valid only if this bit is 1.
|
||||
*
|
||||
* Software must follow this sequence because another
|
||||
* higher priority exception might change the BFAR value.
|
||||
*/
|
||||
STORE_xFAR(bfar, SCB->BFAR);
|
||||
|
||||
if ((SCB->CFSR & SCB_CFSR_BFARVALID_Msk) != 0) {
|
||||
PR_EXC(" BFAR Address: 0x%x\n", bfar);
|
||||
if (fromHardFault) {
|
||||
/* clear SCB_CFSR_BFAR[VALID] to reset */
|
||||
SCB->CFSR &= ~SCB_CFSR_BFARVALID_Msk;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (SCB->CFSR & SCB_CFSR_IMPRECISERR_Msk) {
|
||||
PR_FAULT_INFO(" Imprecise data bus error\n");
|
||||
}
|
||||
if ((SCB->CFSR & SCB_CFSR_IBUSERR_Msk) != 0) {
|
||||
PR_FAULT_INFO(" Instruction bus error\n");
|
||||
#if !defined(CONFIG_ARMV7_M_ARMV8_M_FP)
|
||||
}
|
||||
#else
|
||||
} else if (SCB->CFSR & SCB_CFSR_LSPERR_Msk) {
|
||||
PR_FAULT_INFO(" Floating-point lazy state preservation error\n");
|
||||
}
|
||||
#endif /* !defined(CONFIG_ARMV7_M_ARMV8_M_FP) */
|
||||
|
||||
#if defined(CONFIG_ARM_MPU) && defined(CONFIG_CPU_HAS_NXP_MPU)
|
||||
u32_t sperr = SYSMPU->CESR & SYSMPU_CESR_SPERR_MASK;
|
||||
u32_t mask = BIT(31);
|
||||
int i;
|
||||
u32_t ear = -EINVAL;
|
||||
|
||||
if (sperr) {
|
||||
for (i = 0; i < SYSMPU_EAR_COUNT; i++, mask >>= 1) {
|
||||
if ((sperr & mask) == 0U) {
|
||||
continue;
|
||||
}
|
||||
STORE_xFAR(edr, SYSMPU->SP[i].EDR);
|
||||
ear = SYSMPU->SP[i].EAR;
|
||||
|
||||
PR_FAULT_INFO(" NXP MPU error, port %d\n", i);
|
||||
PR_FAULT_INFO(" Mode: %s, %s Address: 0x%x\n",
|
||||
edr & BIT(2) ? "Supervisor" : "User",
|
||||
edr & BIT(1) ? "Data" : "Instruction",
|
||||
ear);
|
||||
PR_FAULT_INFO(
|
||||
" Type: %s, Master: %d, Regions: 0x%x\n",
|
||||
edr & BIT(0) ? "Write" : "Read",
|
||||
EMN(edr), EACD(edr));
|
||||
|
||||
/* When stack protection is enabled, we need to assess
|
||||
* if the memory violation error is a stack corruption.
|
||||
*
|
||||
* By design, being a Stacking Bus fault is a necessary
|
||||
* and sufficient condition for a stack corruption.
|
||||
*/
|
||||
if (SCB->CFSR & SCB_CFSR_STKERR_Msk) {
|
||||
#if defined(CONFIG_MPU_STACK_GUARD) || defined(CONFIG_USERSPACE)
|
||||
/* Note: we can assume the fault originated
|
||||
* from the same security state for ARM
|
||||
* platforms implementing the NXP MPU
|
||||
* (CONFIG_CPU_HAS_NXP_MPU=y).
|
||||
*
|
||||
* As we only assess thread stack corruption,
|
||||
* we only process the error further, if the
|
||||
* stack frame is on PSP. For NXP MPU-related
|
||||
* Bus Faults (banked), this is equivalent to
|
||||
* inspecting the RETTOBASE flag.
|
||||
*/
|
||||
if (SCB->ICSR & SCB_ICSR_RETTOBASE_Msk) {
|
||||
u32_t min_stack_ptr =
|
||||
z_check_thread_stack_fail(ear,
|
||||
((u32_t) &esf[0]));
|
||||
|
||||
if (min_stack_ptr) {
|
||||
/* When BusFault Stacking Error
|
||||
* has occurred, the stack
|
||||
* context frame might be
|
||||
* corrupted but the stack
|
||||
* pointer may have actually
|
||||
* moved. We may face problems
|
||||
* with un-stacking the frame,
|
||||
* upon exception return, if we
|
||||
* do not have sufficient
|
||||
* permissions to read the
|
||||
* corrupted stack frame.
|
||||
* Therefore, we manually force
|
||||
* the stack pointer to the
|
||||
* lowest allowed position.
|
||||
*
|
||||
* Note:
|
||||
* The PSP will normally be
|
||||
* adjusted in a tail-chained
|
||||
* exception performing context
|
||||
* switch, after aborting the
|
||||
* corrupted thread. Here, the
|
||||
* adjustment is required as
|
||||
* tail-chain cannot always be
|
||||
* guaranteed.
|
||||
*/
|
||||
__set_PSP(min_stack_ptr);
|
||||
|
||||
reason =
|
||||
_NANO_ERR_STACK_CHK_FAIL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)ear;
|
||||
__ASSERT(0,
|
||||
"Stacking error without stack guard"
|
||||
"or User-mode support\n");
|
||||
#endif /* CONFIG_MPU_STACK_GUARD || CONFIG_USERSPACE */
|
||||
}
|
||||
}
|
||||
SYSMPU->CESR &= ~sperr;
|
||||
}
|
||||
#endif /* defined(CONFIG_ARM_MPU) && defined(CONFIG_CPU_HAS_NXP_MPU) */
|
||||
|
||||
/* clear BFSR sticky bits */
|
||||
SCB->CFSR |= SCB_CFSR_BUSFAULTSR_Msk;
|
||||
|
||||
if (MemoryFaultIsRecoverable(esf)) {
|
||||
reason = _NANO_ERR_RECOVERABLE;
|
||||
}
|
||||
|
||||
return reason;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Dump usage fault information
|
||||
*
|
||||
* See _FaultDump() for example.
|
||||
*
|
||||
* @return error code to identify the fatal error reason
|
||||
*/
|
||||
static u32_t UsageFault(const NANO_ESF *esf)
|
||||
{
|
||||
u32_t reason = _NANO_ERR_HW_EXCEPTION;
|
||||
|
||||
PR_FAULT_INFO("***** USAGE FAULT *****\n");
|
||||
|
||||
/* bits are sticky: they stack and must be reset */
|
||||
if ((SCB->CFSR & SCB_CFSR_DIVBYZERO_Msk) != 0) {
|
||||
PR_FAULT_INFO(" Division by zero\n");
|
||||
}
|
||||
if ((SCB->CFSR & SCB_CFSR_UNALIGNED_Msk) != 0) {
|
||||
PR_FAULT_INFO(" Unaligned memory access\n");
|
||||
}
|
||||
#if defined(CONFIG_ARMV8_M_MAINLINE)
|
||||
if ((SCB->CFSR & SCB_CFSR_STKOF_Msk) != 0) {
|
||||
PR_FAULT_INFO(" Stack overflow (context area not valid)\n");
|
||||
#if defined(CONFIG_BUILTIN_STACK_GUARD)
|
||||
/* Stack Overflows are always reported as stack corruption
|
||||
* errors. Note that the built-in stack overflow mechanism
|
||||
* prevents the context area to be loaded on the stack upon
|
||||
* UsageFault exception entry. As a result, we cannot rely
|
||||
* on the reported faulty instruction address, to determine
|
||||
* the instruction that triggered the stack overflow.
|
||||
*/
|
||||
reason = _NANO_ERR_STACK_CHK_FAIL;
|
||||
#endif /* CONFIG_BUILTIN_STACK_GUARD */
|
||||
}
|
||||
#endif /* CONFIG_ARMV8_M_MAINLINE */
|
||||
if ((SCB->CFSR & SCB_CFSR_NOCP_Msk) != 0) {
|
||||
PR_FAULT_INFO(" No coprocessor instructions\n");
|
||||
}
|
||||
if ((SCB->CFSR & SCB_CFSR_INVPC_Msk) != 0) {
|
||||
PR_FAULT_INFO(" Illegal load of EXC_RETURN into PC\n");
|
||||
}
|
||||
if ((SCB->CFSR & SCB_CFSR_INVSTATE_Msk) != 0) {
|
||||
PR_FAULT_INFO(" Illegal use of the EPSR\n");
|
||||
}
|
||||
if ((SCB->CFSR & SCB_CFSR_UNDEFINSTR_Msk) != 0) {
|
||||
PR_FAULT_INFO(" Attempt to execute undefined instruction\n");
|
||||
}
|
||||
|
||||
/* clear UFSR sticky bits */
|
||||
SCB->CFSR |= SCB_CFSR_USGFAULTSR_Msk;
|
||||
|
||||
return reason;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
|
||||
/**
|
||||
*
|
||||
* @brief Dump secure fault information
|
||||
*
|
||||
* See _FaultDump() for example.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
static void SecureFault(const NANO_ESF *esf)
|
||||
{
|
||||
PR_FAULT_INFO("***** SECURE FAULT *****\n");
|
||||
|
||||
STORE_xFAR(sfar, SAU->SFAR);
|
||||
if ((SAU->SFSR & SAU_SFSR_SFARVALID_Msk) != 0) {
|
||||
PR_EXC(" Address: 0x%x\n", sfar);
|
||||
}
|
||||
|
||||
/* bits are sticky: they stack and must be reset */
|
||||
if ((SAU->SFSR & SAU_SFSR_INVEP_Msk) != 0) {
|
||||
PR_FAULT_INFO(" Invalid entry point\n");
|
||||
} else if ((SAU->SFSR & SAU_SFSR_INVIS_Msk) != 0) {
|
||||
PR_FAULT_INFO(" Invalid integrity signature\n");
|
||||
} else if ((SAU->SFSR & SAU_SFSR_INVER_Msk) != 0) {
|
||||
PR_FAULT_INFO(" Invalid exception return\n");
|
||||
} else if ((SAU->SFSR & SAU_SFSR_AUVIOL_Msk) != 0) {
|
||||
PR_FAULT_INFO(" Attribution unit violation\n");
|
||||
} else if ((SAU->SFSR & SAU_SFSR_INVTRAN_Msk) != 0) {
|
||||
PR_FAULT_INFO(" Invalid transition\n");
|
||||
} else if ((SAU->SFSR & SAU_SFSR_LSPERR_Msk) != 0) {
|
||||
PR_FAULT_INFO(" Lazy state preservation\n");
|
||||
} else if ((SAU->SFSR & SAU_SFSR_LSERR_Msk) != 0) {
|
||||
PR_FAULT_INFO(" Lazy state error\n");
|
||||
}
|
||||
|
||||
/* clear SFSR sticky bits */
|
||||
SAU->SFSR |= 0xFF;
|
||||
}
|
||||
#endif /* defined(CONFIG_ARM_SECURE_FIRMWARE) */
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Dump debug monitor exception information
|
||||
*
|
||||
* See _FaultDump() for example.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
static void DebugMonitor(const NANO_ESF *esf)
|
||||
{
|
||||
ARG_UNUSED(esf);
|
||||
|
||||
PR_FAULT_INFO(
|
||||
"***** Debug monitor exception (not implemented) *****\n");
|
||||
}
|
||||
|
||||
#else
|
||||
#error Unknown ARM architecture
|
||||
#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Dump hard fault information
|
||||
*
|
||||
* See _FaultDump() for example.
|
||||
*
|
||||
* @return error code to identify the fatal error reason
|
||||
*/
|
||||
static u32_t HardFault(NANO_ESF *esf)
|
||||
{
|
||||
u32_t reason = _NANO_ERR_HW_EXCEPTION;
|
||||
|
||||
PR_FAULT_INFO("***** HARD FAULT *****\n");
|
||||
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
if (MemoryFaultIsRecoverable(esf) != 0) {
|
||||
reason = _NANO_ERR_RECOVERABLE;
|
||||
}
|
||||
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
|
||||
if ((SCB->HFSR & SCB_HFSR_VECTTBL_Msk) != 0) {
|
||||
PR_EXC(" Bus fault on vector table read\n");
|
||||
} else if ((SCB->HFSR & SCB_HFSR_FORCED_Msk) != 0) {
|
||||
PR_EXC(" Fault escalation (see below)\n");
|
||||
if (SCB_MMFSR != 0) {
|
||||
reason = MpuFault(esf, 1);
|
||||
} else if (SCB_BFSR != 0) {
|
||||
reason = BusFault(esf, 1);
|
||||
} else if (SCB_UFSR != 0) {
|
||||
reason = UsageFault(esf);
|
||||
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
|
||||
} else if (SAU->SFSR != 0) {
|
||||
SecureFault(esf);
|
||||
#endif /* CONFIG_ARM_SECURE_FIRMWARE */
|
||||
}
|
||||
}
|
||||
#else
|
||||
#error Unknown ARM architecture
|
||||
#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
|
||||
|
||||
return reason;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Dump reserved exception information
|
||||
*
|
||||
* See _FaultDump() for example.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
static void ReservedException(const NANO_ESF *esf, int fault)
|
||||
{
|
||||
ARG_UNUSED(esf);
|
||||
|
||||
PR_FAULT_INFO("***** %s %d) *****\n",
|
||||
fault < 16 ? "Reserved Exception (" : "Spurious interrupt (IRQ ",
|
||||
fault - 16);
|
||||
}
|
||||
|
||||
/* Handler function for ARM fault conditions. */
|
||||
static u32_t FaultHandle(NANO_ESF *esf, int fault)
|
||||
{
|
||||
u32_t reason = _NANO_ERR_HW_EXCEPTION;
|
||||
|
||||
switch (fault) {
|
||||
case 3:
|
||||
reason = HardFault(esf);
|
||||
break;
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
/* HardFault is used for all fault conditions on ARMv6-M. */
|
||||
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
|
||||
case 4:
|
||||
reason = MpuFault(esf, 0);
|
||||
break;
|
||||
case 5:
|
||||
reason = BusFault(esf, 0);
|
||||
break;
|
||||
case 6:
|
||||
reason = UsageFault(esf);
|
||||
break;
|
||||
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
|
||||
case 7:
|
||||
SecureFault(esf);
|
||||
break;
|
||||
#endif /* CONFIG_ARM_SECURE_FIRMWARE */
|
||||
case 12:
|
||||
DebugMonitor(esf);
|
||||
break;
|
||||
#else
|
||||
#error Unknown ARM architecture
|
||||
#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
|
||||
default:
|
||||
ReservedException(esf, fault);
|
||||
break;
|
||||
}
|
||||
|
||||
if (reason != _NANO_ERR_RECOVERABLE) {
|
||||
/* Dump generic information about the fault. */
|
||||
FaultShow(esf, fault);
|
||||
}
|
||||
|
||||
return reason;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
|
||||
#if (CONFIG_FAULT_DUMP == 2)
|
||||
/**
|
||||
* @brief Dump the Secure Stack information for an exception that
|
||||
* has occurred in Non-Secure state.
|
||||
*
|
||||
* @param secure_esf Pointer to the secure stack frame.
|
||||
*/
|
||||
static void SecureStackDump(const NANO_ESF *secure_esf)
|
||||
{
|
||||
/*
|
||||
* In case a Non-Secure exception interrupted the Secure
|
||||
* execution, the Secure state has stacked the additional
|
||||
* state context and the top of the stack contains the
|
||||
* integrity signature.
|
||||
*
|
||||
* In case of a Non-Secure function call the top of the
|
||||
* stack contains the return address to Secure state.
|
||||
*/
|
||||
u32_t *top_of_sec_stack = (u32_t *)secure_esf;
|
||||
u32_t sec_ret_addr;
|
||||
#if defined(CONFIG_ARMV7_M_ARMV8_M_FP)
|
||||
if ((*top_of_sec_stack == INTEGRITY_SIGNATURE_STD) ||
|
||||
(*top_of_sec_stack == INTEGRITY_SIGNATURE_EXT)) {
|
||||
#else
|
||||
if (*top_of_sec_stack == INTEGRITY_SIGNATURE) {
|
||||
#endif /* CONFIG_ARMV7_M_ARMV8_M_FP */
|
||||
/* Secure state interrupted by a Non-Secure exception.
|
||||
* The return address after the additional state
|
||||
* context, stacked by the Secure code upon
|
||||
* Non-Secure exception entry.
|
||||
*/
|
||||
top_of_sec_stack += ADDITIONAL_STATE_CONTEXT_WORDS;
|
||||
secure_esf = (const NANO_ESF *)top_of_sec_stack;
|
||||
sec_ret_addr = secure_esf->pc;
|
||||
} else {
|
||||
/* Exception during Non-Secure function call.
|
||||
* The return address is located on top of stack.
|
||||
*/
|
||||
sec_ret_addr = *top_of_sec_stack;
|
||||
}
|
||||
PR_FAULT_INFO(" S instruction address: 0x%x\n", sec_ret_addr);
|
||||
|
||||
}
|
||||
#define SECURE_STACK_DUMP(esf) SecureStackDump(esf)
|
||||
#else
|
||||
/* We do not dump the Secure stack information for lower dump levels. */
|
||||
#define SECURE_STACK_DUMP(esf)
|
||||
#endif /* CONFIG_FAULT_DUMP== 2 */
|
||||
#endif /* CONFIG_ARM_SECURE_FIRMWARE */
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief ARM Fault handler
|
||||
*
|
||||
* This routine is called when fatal error conditions are detected by hardware
|
||||
* and is responsible for:
|
||||
* - resetting the processor fault status registers (for the case when the
|
||||
* error handling policy allows the system to recover from the error),
|
||||
* - reporting the error information,
|
||||
* - determining the error reason to be provided as input to the user-
|
||||
* provided routine, z_NanoFatalErrorHandler().
|
||||
* The z_NanoFatalErrorHandler() is invoked once the above operations are
|
||||
* completed, and is responsible for implementing the error handling policy.
|
||||
*
|
||||
* The provided ESF pointer points to the exception stack frame of the current
|
||||
* security state. Note that the current security state might not be the actual
|
||||
* state in which the processor was executing, when the exception occurred.
|
||||
* The actual state may need to be determined by inspecting the EXC_RETURN
|
||||
* value, which is provided as argument to the Fault handler.
|
||||
*
|
||||
* @param esf Pointer to the exception stack frame of the current security
|
||||
* state. The stack frame may be either on the Main stack (MSP) or Process
|
||||
* stack (PSP) depending at what execution state the exception was taken.
|
||||
*
|
||||
* @param exc_return EXC_RETURN value present in LR after exception entry.
|
||||
*
|
||||
* Note: exc_return argument shall only be used by the Fault handler if we are
|
||||
* running a Secure Firmware.
|
||||
*/
|
||||
void _Fault(NANO_ESF *esf, u32_t exc_return)
|
||||
{
|
||||
u32_t reason = _NANO_ERR_HW_EXCEPTION;
|
||||
int fault = SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk;
|
||||
|
||||
LOG_PANIC();
|
||||
|
||||
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
|
||||
if ((exc_return & EXC_RETURN_INDICATOR_PREFIX) !=
|
||||
EXC_RETURN_INDICATOR_PREFIX) {
|
||||
/* Invalid EXC_RETURN value */
|
||||
goto _exit_fatal;
|
||||
}
|
||||
if ((exc_return & EXC_RETURN_EXCEPTION_SECURE_Secure) == 0U) {
|
||||
/* Secure Firmware shall only handle Secure Exceptions.
|
||||
* This is a fatal error.
|
||||
*/
|
||||
goto _exit_fatal;
|
||||
}
|
||||
|
||||
if (exc_return & EXC_RETURN_RETURN_STACK_Secure) {
|
||||
/* Exception entry occurred in Secure stack. */
|
||||
} else {
|
||||
/* Exception entry occurred in Non-Secure stack. Therefore, 'esf'
|
||||
* holds the Secure stack information, however, the actual
|
||||
* exception stack frame is located in the Non-Secure stack.
|
||||
*/
|
||||
|
||||
/* Dump the Secure stack before handling the actual fault. */
|
||||
SECURE_STACK_DUMP(esf);
|
||||
|
||||
/* Handle the actual fault.
|
||||
* Extract the correct stack frame from the Non-Secure state
|
||||
* and supply it to the fault handing function.
|
||||
*/
|
||||
if (exc_return & EXC_RETURN_MODE_THREAD) {
|
||||
esf = (NANO_ESF *)__TZ_get_PSP_NS();
|
||||
if ((SCB->ICSR & SCB_ICSR_RETTOBASE_Msk) == 0) {
|
||||
PR_EXC("RETTOBASE does not match EXC_RETURN\n");
|
||||
goto _exit_fatal;
|
||||
}
|
||||
} else {
|
||||
esf = (NANO_ESF *)__TZ_get_MSP_NS();
|
||||
if ((SCB->ICSR & SCB_ICSR_RETTOBASE_Msk) != 0) {
|
||||
PR_EXC("RETTOBASE does not match EXC_RETURN\n");
|
||||
goto _exit_fatal;
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif defined(CONFIG_ARM_NONSECURE_FIRMWARE)
|
||||
if ((exc_return & EXC_RETURN_INDICATOR_PREFIX) !=
|
||||
EXC_RETURN_INDICATOR_PREFIX) {
|
||||
/* Invalid EXC_RETURN value */
|
||||
goto _exit_fatal;
|
||||
}
|
||||
if (exc_return & EXC_RETURN_EXCEPTION_SECURE_Secure) {
|
||||
/* Non-Secure Firmware shall only handle Non-Secure Exceptions.
|
||||
* This is a fatal error.
|
||||
*/
|
||||
goto _exit_fatal;
|
||||
}
|
||||
|
||||
if (exc_return & EXC_RETURN_RETURN_STACK_Secure) {
|
||||
/* Exception entry occurred in Secure stack.
|
||||
*
|
||||
* Note that Non-Secure firmware cannot inspect the Secure
|
||||
* stack to determine the root cause of the fault. Fault
|
||||
* inspection will indicate the Non-Secure instruction
|
||||
* that performed the branch to the Secure domain.
|
||||
*/
|
||||
PR_FAULT_INFO("Exception occurred in Secure State\n");
|
||||
}
|
||||
#else
|
||||
(void) exc_return;
|
||||
#endif /* CONFIG_ARM_SECURE_FIRMWARE */
|
||||
|
||||
reason = FaultHandle(esf, fault);
|
||||
|
||||
if (reason == _NANO_ERR_RECOVERABLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ARM_SECURE_FIRMWARE) || \
|
||||
defined(CONFIG_ARM_NONSECURE_FIRMWARE)
|
||||
_exit_fatal:
|
||||
#endif
|
||||
z_NanoFatalErrorHandler(reason, esf);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Initialization of fault handling
|
||||
*
|
||||
* Turns on the desired hardware faults.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
void z_FaultInit(void)
|
||||
{
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
|
||||
SCB->CCR |= SCB_CCR_DIV_0_TRP_Msk;
|
||||
#else
|
||||
#error Unknown ARM architecture
|
||||
#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
|
||||
#if defined(CONFIG_BUILTIN_STACK_GUARD)
|
||||
/* If Stack guarding via SP limit checking is enabled, disable
|
||||
* SP limit checking inside HardFault and NMI. This is done
|
||||
* in order to allow for the desired fault logging to execute
|
||||
* properly in all cases.
|
||||
*
|
||||
* Note that this could allow a Secure Firmware Main Stack
|
||||
* to descend into non-secure region during HardFault and
|
||||
* NMI exception entry. To prevent from this, non-secure
|
||||
* memory regions must be located higher than secure memory
|
||||
* regions.
|
||||
*
|
||||
* For Non-Secure Firmware this could allow the Non-Secure Main
|
||||
* Stack to attempt to descend into secure region, in which case a
|
||||
* Secure Hard Fault will occur and we can track the fault from there.
|
||||
*/
|
||||
SCB->CCR |= SCB_CCR_STKOFHFNMIGN_Msk;
|
||||
#endif /* CONFIG_BUILTIN_STACK_GUARD */
|
||||
}
|
||||
@@ -1,117 +1,151 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2014 Wind River Systems, Inc.
|
||||
* Copyright (c) 2017-2019 Nordic Semiconductor ASA.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Fault handlers for ARM Cortex-M and Cortex-R
|
||||
* @brief Fault handlers for ARM Cortex-M
|
||||
*
|
||||
* Fault handlers for ARM Cortex-M and Cortex-R processors.
|
||||
* Fault handlers for ARM Cortex-M processors.
|
||||
*/
|
||||
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <arch/cpu.h>
|
||||
|
||||
_ASM_FILE_PROLOGUE
|
||||
|
||||
GTEXT(z_arm_fault)
|
||||
GTEXT(_Fault)
|
||||
|
||||
GTEXT(z_arm_hard_fault)
|
||||
GTEXT(__hard_fault)
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
/* HardFault is used for all fault conditions on ARMv6-M. */
|
||||
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
|
||||
GTEXT(z_arm_mpu_fault)
|
||||
GTEXT(z_arm_bus_fault)
|
||||
GTEXT(z_arm_usage_fault)
|
||||
GTEXT(__mpu_fault)
|
||||
GTEXT(__bus_fault)
|
||||
GTEXT(__usage_fault)
|
||||
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
|
||||
GTEXT(z_arm_secure_fault)
|
||||
GTEXT(__secure_fault)
|
||||
#endif /* CONFIG_ARM_SECURE_FIRMWARE*/
|
||||
GTEXT(z_arm_debug_monitor)
|
||||
#elif defined(CONFIG_ARMV7_R)
|
||||
GTEXT(z_arm_undef_instruction)
|
||||
GTEXT(z_arm_prefetch_abort)
|
||||
GTEXT(z_arm_data_abort)
|
||||
GTEXT(__debug_monitor)
|
||||
#else
|
||||
#error Unknown ARM architecture
|
||||
#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
|
||||
GTEXT(z_arm_reserved)
|
||||
GTEXT(__reserved)
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Fault handler installed in the fault and reserved vectors
|
||||
*
|
||||
* Entry point for the HardFault, MemManageFault, BusFault, UsageFault,
|
||||
* SecureFault, Debug Monitor, and reserved exceptions.
|
||||
* Entry point for the hard fault, MPU fault, bus fault, usage fault, debug
|
||||
* monitor and reserved exceptions.
|
||||
*
|
||||
* For Cortex-M: the function supplies the values of
|
||||
* - the MSP
|
||||
* - the PSP
|
||||
* - the EXC_RETURN value
|
||||
* as parameters to the z_arm_fault() C function that will perform the
|
||||
* rest of the fault handling (i.e. z_arm_fault(MSP, PSP, EXC_RETURN)).
|
||||
*
|
||||
* For Cortex-R: the function simply invokes z_arm_fault() with currently
|
||||
* unused arguments.
|
||||
* Save the values of the MSP and PSP in r0 and r1 respectively, so the first
|
||||
* and second parameters to the _Fault() C function that will handle the rest.
|
||||
* This has to be done because at this point we do not know if the fault
|
||||
* happened while handling an exception or not, and thus the ESF could be on
|
||||
* either stack. _Fault() will find out where the ESF resides.
|
||||
*
|
||||
* Provides these symbols:
|
||||
*
|
||||
* z_arm_hard_fault
|
||||
* z_arm_mpu_fault
|
||||
* z_arm_bus_fault
|
||||
* z_arm_usage_fault
|
||||
* z_arm_secure_fault
|
||||
* z_arm_debug_monitor
|
||||
* z_arm_reserved
|
||||
* __hard_fault
|
||||
* __mpu_fault
|
||||
* __bus_fault
|
||||
* __usage_fault
|
||||
* __secure_fault
|
||||
* __debug_monitor
|
||||
* __reserved
|
||||
*/
|
||||
|
||||
SECTION_SUBSEC_FUNC(TEXT,__fault,z_arm_hard_fault)
|
||||
SECTION_SUBSEC_FUNC(TEXT,__fault,__hard_fault)
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
/* HardFault is used for all fault conditions on ARMv6-M. */
|
||||
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
|
||||
SECTION_SUBSEC_FUNC(TEXT,__fault,z_arm_mpu_fault)
|
||||
SECTION_SUBSEC_FUNC(TEXT,__fault,z_arm_bus_fault)
|
||||
SECTION_SUBSEC_FUNC(TEXT,__fault,z_arm_usage_fault)
|
||||
SECTION_SUBSEC_FUNC(TEXT,__fault,__mpu_fault)
|
||||
SECTION_SUBSEC_FUNC(TEXT,__fault,__bus_fault)
|
||||
SECTION_SUBSEC_FUNC(TEXT,__fault,__usage_fault)
|
||||
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
|
||||
SECTION_SUBSEC_FUNC(TEXT,__fault,z_arm_secure_fault)
|
||||
SECTION_SUBSEC_FUNC(TEXT,__fault,__secure_fault)
|
||||
#endif /* CONFIG_ARM_SECURE_FIRMWARE */
|
||||
SECTION_SUBSEC_FUNC(TEXT,__fault,z_arm_debug_monitor)
|
||||
#elif defined(CONFIG_ARMV7_R)
|
||||
SECTION_SUBSEC_FUNC(TEXT,__fault,z_arm_undef_instruction)
|
||||
SECTION_SUBSEC_FUNC(TEXT,__fault,z_arm_prefetch_abort)
|
||||
SECTION_SUBSEC_FUNC(TEXT,__fault,z_arm_data_abort)
|
||||
SECTION_SUBSEC_FUNC(TEXT,__fault,__debug_monitor)
|
||||
#else
|
||||
#error Unknown ARM architecture
|
||||
#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
|
||||
SECTION_SUBSEC_FUNC(TEXT,__fault,z_arm_reserved)
|
||||
SECTION_SUBSEC_FUNC(TEXT,__fault,__reserved)
|
||||
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) || \
|
||||
defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
|
||||
mrs r0, MSP
|
||||
mrs r1, PSP
|
||||
mov r2, lr /* EXC_RETURN */
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
/* force unlock interrupts */
|
||||
cpsie i
|
||||
|
||||
push {r0, lr}
|
||||
#elif defined(CONFIG_ARMV7_R)
|
||||
/*
|
||||
* Pass null for the esf to z_arm_fault for now. A future PR will add
|
||||
* better exception debug for Cortex-R that subsumes what esf
|
||||
* provides.
|
||||
/* Use EXC_RETURN state to find out if stack frame is on the
|
||||
* MSP or PSP
|
||||
*/
|
||||
mov r0, #0
|
||||
ldr r0, =0x4
|
||||
mov r1, lr
|
||||
tst r1, r0
|
||||
beq _stack_frame_msp
|
||||
mrs r0, PSP
|
||||
bne _stack_frame_endif
|
||||
_stack_frame_msp:
|
||||
mrs r0, MSP
|
||||
_stack_frame_endif:
|
||||
|
||||
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
|
||||
/* force unlock interrupts */
|
||||
eors.n r0, r0
|
||||
msr BASEPRI, r0
|
||||
|
||||
#if !defined(CONFIG_ARM_SECURE_FIRMWARE) && \
|
||||
!defined(CONFIG_ARM_NONSECURE_FIRMWARE)
|
||||
/* this checks to see if we are in a nested exception */
|
||||
ldr ip, =_SCS_ICSR
|
||||
ldr ip, [ip]
|
||||
ands.w ip, #_SCS_ICSR_RETTOBASE
|
||||
|
||||
ite eq /* is the RETTOBASE bit zero ? */
|
||||
mrseq r0, MSP /* if so, we're not returning to thread mode,
|
||||
* thus this is a nested exception: the stack
|
||||
* frame is on the MSP */
|
||||
mrsne r0, PSP /* if not, we are returning to thread mode, thus
|
||||
* this is not a nested exception: the stack
|
||||
* frame is on the PSP */
|
||||
#else
|
||||
/* RETTOBASE flag is not banked between security states.
|
||||
* Therefore, we cannot rely on this flag, to obtain the SP
|
||||
* of the current security state.
|
||||
* Instead, we use the EXC_RETURN.SPSEL flag.
|
||||
*/
|
||||
ldr r0, =0x4
|
||||
mov r1, lr
|
||||
tst r1, r0
|
||||
beq _s_stack_frame_msp
|
||||
mrs r0, PSP
|
||||
bne _s_stack_frame_endif
|
||||
_s_stack_frame_msp:
|
||||
mrs r0, MSP
|
||||
_s_stack_frame_endif:
|
||||
#endif /* CONFIG_ARM_SECURE_FIRMWARE || CONFIG_ARM_NONSECURE_FIRMWARE */
|
||||
#else
|
||||
#error Unknown ARM architecture
|
||||
#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE || CONFIG_ARMv7_M_ARMV8_M_MAINLINE */
|
||||
#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
|
||||
|
||||
bl z_arm_fault
|
||||
#if defined(CONFIG_ARM_SECURE_FIRMWARE) || \
|
||||
defined(CONFIG_ARM_NONSECURE_FIRMWARE)
|
||||
/* The stack pointer that is retrieved above, points to the stack,
|
||||
* where the exception is taken. However, the exeption may have
|
||||
* occurred in the alternative security state.
|
||||
*
|
||||
* To determine this we need to inspect the EXC_RETURN value
|
||||
* located in the LR. Therefore, we supply the LR value as an
|
||||
* argument to the fault handler.
|
||||
*/
|
||||
mov r1, lr
|
||||
#endif /* CONFIG_ARM_SECURE_FIRMWARE || CONFIG_ARM_NONSECURE_FIRMWARE */
|
||||
push {r0, lr}
|
||||
bl _Fault
|
||||
|
||||
#if defined(CONFIG_CPU_CORTEX_M)
|
||||
pop {r0, pc}
|
||||
#elif defined(CONFIG_CPU_CORTEX_R)
|
||||
pop {r0, lr}
|
||||
subs pc, lr, #8
|
||||
#endif
|
||||
|
||||
.end
|
||||
|
||||
43
arch/arm/core/irq_init.c
Normal file
43
arch/arm/core/irq_init.c
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief ARM Cortex-M interrupt initialization
|
||||
*
|
||||
* The ARM Cortex-M architecture provides its own k_thread_abort() to deal with
|
||||
* different CPU modes (handler vs thread) when a thread aborts. When its entry
|
||||
* point returns or when it aborts itself, the CPU is in thread mode and must
|
||||
* call z_swap() (which triggers a service call), but when in handler mode, the
|
||||
* CPU must exit handler mode to cause the context switch, and thus must queue
|
||||
* the PendSV exception.
|
||||
*/
|
||||
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <kernel.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <arch/arm/cortex_m/cmsis.h>
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Initialize interrupts
|
||||
*
|
||||
* Ensures all interrupts have their priority set to _EXC_IRQ_DEFAULT_PRIO and
|
||||
* not 0, which they have it set to when coming out of reset. This ensures that
|
||||
* interrupt locking via BASEPRI works as expected.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void z_IntLibInit(void)
|
||||
{
|
||||
int irq = 0;
|
||||
|
||||
for (; irq < CONFIG_NUM_IRQS; irq++) {
|
||||
NVIC_SetPriority((IRQn_Type)irq, _IRQ_PRIO_OFFSET);
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief ARM Cortex-M and Cortex-R interrupt management
|
||||
* @brief ARM Cortex-M interrupt management
|
||||
*
|
||||
*
|
||||
* Interrupt management: enabling/disabling and dynamic ISR
|
||||
@@ -16,37 +16,56 @@
|
||||
|
||||
#include <kernel.h>
|
||||
#include <arch/cpu.h>
|
||||
#if defined(CONFIG_CPU_CORTEX_M)
|
||||
#include <arch/arm/cortex_m/cmsis.h>
|
||||
#elif defined(CONFIG_CPU_CORTEX_R)
|
||||
#include <device.h>
|
||||
#include <irq_nextlevel.h>
|
||||
#endif
|
||||
#include <sys/__assert.h>
|
||||
#include <misc/__assert.h>
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <sw_isr_table.h>
|
||||
#include <irq.h>
|
||||
#include <debug/tracing.h>
|
||||
#include <kernel_structs.h>
|
||||
#include <tracing.h>
|
||||
|
||||
extern void z_arm_reserved(void);
|
||||
extern void __reserved(void);
|
||||
|
||||
#if defined(CONFIG_CPU_CORTEX_M)
|
||||
#define NUM_IRQS_PER_REG 32
|
||||
#define REG_FROM_IRQ(irq) (irq / NUM_IRQS_PER_REG)
|
||||
#define BIT_FROM_IRQ(irq) (irq % NUM_IRQS_PER_REG)
|
||||
|
||||
void arch_irq_enable(unsigned int irq)
|
||||
/**
|
||||
*
|
||||
* @brief Enable an interrupt line
|
||||
*
|
||||
* Enable the interrupt. After this call, the CPU will receive interrupts for
|
||||
* the specified <irq>.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
void z_arch_irq_enable(unsigned int irq)
|
||||
{
|
||||
NVIC_EnableIRQ((IRQn_Type)irq);
|
||||
}
|
||||
|
||||
void arch_irq_disable(unsigned int irq)
|
||||
/**
|
||||
*
|
||||
* @brief Disable an interrupt line
|
||||
*
|
||||
* Disable an interrupt line. After this call, the CPU will stop receiving
|
||||
* interrupts for the specified <irq>.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
void z_arch_irq_disable(unsigned int irq)
|
||||
{
|
||||
NVIC_DisableIRQ((IRQn_Type)irq);
|
||||
}
|
||||
|
||||
int arch_irq_is_enabled(unsigned int irq)
|
||||
/**
|
||||
* @brief Return IRQ enable state
|
||||
*
|
||||
* @param irq IRQ line
|
||||
* @return interrupt enable state, true or false
|
||||
*/
|
||||
int z_arch_irq_is_enabled(unsigned int irq)
|
||||
{
|
||||
return NVIC->ISER[REG_FROM_IRQ(irq)] & BIT(BIT_FROM_IRQ(irq));
|
||||
}
|
||||
@@ -62,14 +81,14 @@ int arch_irq_is_enabled(unsigned int irq)
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, u32_t flags)
|
||||
void z_irq_priority_set(unsigned int irq, unsigned int prio, u32_t flags)
|
||||
{
|
||||
/* The kernel may reserve some of the highest priority levels.
|
||||
* So we offset the requested priority level with the number
|
||||
* of priority levels reserved by the kernel.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_ZERO_LATENCY_IRQS)
|
||||
#if CONFIG_ZERO_LATENCY_IRQS
|
||||
/* If we have zero latency interrupts, those interrupts will
|
||||
* run at a priority level which is not masked by irq_lock().
|
||||
* Our policy is to express priority levels with special properties
|
||||
@@ -96,52 +115,6 @@ void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, u32_t flags)
|
||||
NVIC_SetPriority((IRQn_Type)irq, prio);
|
||||
}
|
||||
|
||||
#elif defined(CONFIG_CPU_CORTEX_R)
|
||||
void arch_irq_enable(unsigned int irq)
|
||||
{
|
||||
struct device *dev = _sw_isr_table[0].arg;
|
||||
|
||||
irq_enable_next_level(dev, (irq >> 8) - 1);
|
||||
}
|
||||
|
||||
void arch_irq_disable(unsigned int irq)
|
||||
{
|
||||
struct device *dev = _sw_isr_table[0].arg;
|
||||
|
||||
irq_disable_next_level(dev, (irq >> 8) - 1);
|
||||
}
|
||||
|
||||
int arch_irq_is_enabled(unsigned int irq)
|
||||
{
|
||||
struct device *dev = _sw_isr_table[0].arg;
|
||||
|
||||
return irq_is_enabled_next_level(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Set an interrupt's priority
|
||||
*
|
||||
* The priority is verified if ASSERT_ON is enabled. The maximum number
|
||||
* of priority levels is a little complex, as there are some hardware
|
||||
* priority levels which are reserved: three for various types of exceptions,
|
||||
* and possibly one additional to support zero latency interrupts.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, u32_t flags)
|
||||
{
|
||||
struct device *dev = _sw_isr_table[0].arg;
|
||||
|
||||
if (irq == 0)
|
||||
return;
|
||||
|
||||
irq_set_priority_next_level(dev, (irq >> 8) - 1, prio, flags);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Spurious interrupt handler
|
||||
@@ -149,21 +122,29 @@ void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, u32_t flags)
|
||||
* Installed in all dynamic interrupt slots at boot time. Throws an error if
|
||||
* called.
|
||||
*
|
||||
* See z_arm_reserved().
|
||||
* See __reserved().
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
void z_irq_spurious(void *unused)
|
||||
{
|
||||
ARG_UNUSED(unused);
|
||||
z_arm_reserved();
|
||||
__reserved();
|
||||
}
|
||||
|
||||
/* FIXME: IRQ direct inline functions have to be placed here and not in
|
||||
* arch/cpu.h as inline functions due to nasty circular dependency between
|
||||
* arch/cpu.h and kernel_structs.h; the inline functions typically need to
|
||||
* perform operations on _kernel. For now, leave as regular functions, a
|
||||
* future iteration will resolve this.
|
||||
*
|
||||
* See https://github.com/zephyrproject-rtos/zephyr/issues/3056
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SYS_POWER_MANAGEMENT
|
||||
void _arch_isr_direct_pm(void)
|
||||
{
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) \
|
||||
|| defined(CONFIG_ARMV7_R)
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
unsigned int key;
|
||||
|
||||
/* irq_lock() does what we wan for this CPU */
|
||||
@@ -185,8 +166,7 @@ void _arch_isr_direct_pm(void)
|
||||
z_sys_power_save_idle_exit(idle_val);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) \
|
||||
|| defined(CONFIG_ARMV7_R)
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
irq_unlock(key);
|
||||
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
|
||||
__asm__ volatile("cpsie i" : : : "memory");
|
||||
@@ -197,6 +177,11 @@ void _arch_isr_direct_pm(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
void z_arch_isr_direct_header(void)
|
||||
{
|
||||
z_sys_trace_isr_enter();
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
|
||||
/**
|
||||
*
|
||||
@@ -254,12 +239,12 @@ int irq_target_state_is_secure(unsigned int irq)
|
||||
#endif /* CONFIG_ARM_SECURE_FIRMWARE */
|
||||
|
||||
#ifdef CONFIG_DYNAMIC_INTERRUPTS
|
||||
int arch_irq_connect_dynamic(unsigned int irq, unsigned int priority,
|
||||
void (*routine)(void *parameter), void *parameter,
|
||||
u32_t flags)
|
||||
int z_arch_irq_connect_dynamic(unsigned int irq, unsigned int priority,
|
||||
void (*routine)(void *parameter), void *parameter,
|
||||
u32_t flags)
|
||||
{
|
||||
z_isr_install(irq, routine, parameter);
|
||||
z_arm_irq_priority_set(irq, priority, flags);
|
||||
z_irq_priority_set(irq, priority, flags);
|
||||
return irq;
|
||||
}
|
||||
#endif /* CONFIG_DYNAMIC_INTERRUPTS */
|
||||
|
||||
@@ -14,13 +14,13 @@
|
||||
volatile irq_offload_routine_t offload_routine;
|
||||
static void *offload_param;
|
||||
|
||||
/* Called by z_arm_svc */
|
||||
/* Called by __svc */
|
||||
void z_irq_do_offload(void)
|
||||
{
|
||||
offload_routine(offload_param);
|
||||
}
|
||||
|
||||
void arch_irq_offload(irq_offload_routine_t routine, void *parameter)
|
||||
void irq_offload(irq_offload_routine_t routine, void *parameter)
|
||||
{
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) && defined(CONFIG_ASSERT)
|
||||
/* ARMv6-M/ARMv8-M Baseline HardFault if you make a SVC call with
|
||||
|
||||
@@ -29,7 +29,7 @@ _ASM_FILE_PROLOGUE
|
||||
#if defined(CONFIG_SW_VECTOR_RELAY)
|
||||
|
||||
GDATA(_vector_table_pointer)
|
||||
GDATA(z_main_stack)
|
||||
GDATA(_main_stack)
|
||||
|
||||
SECTION_FUNC(vector_relay_handler, __vector_relay_handler)
|
||||
mrs r0, ipsr;
|
||||
@@ -52,9 +52,9 @@ SECTION_FUNC(vector_relay_handler, __vector_relay_handler)
|
||||
GTEXT(__vector_relay_handler)
|
||||
|
||||
SECTION_FUNC(vector_relay_table, __vector_relay_table)
|
||||
.word z_main_stack + CONFIG_MAIN_STACK_SIZE
|
||||
.word _main_stack + CONFIG_MAIN_STACK_SIZE
|
||||
|
||||
.word z_arm_reset
|
||||
.word __reset
|
||||
|
||||
.word __vector_relay_handler /* nmi */
|
||||
.word __vector_relay_handler /* hard fault */
|
||||
|
||||
@@ -6,76 +6,59 @@
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief ARM Cortex-M and Cortex-R wrapper for ISRs with parameter
|
||||
* @brief ARM Cortex-M wrapper for ISRs with parameter
|
||||
*
|
||||
* Wrapper installed in vector table for handling dynamic interrupts that accept
|
||||
* a parameter.
|
||||
*/
|
||||
|
||||
#include <offsets_short.h>
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <offsets_short.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <sw_isr_table.h>
|
||||
|
||||
#include <kernel_structs.h>
|
||||
#include <arch/cpu.h>
|
||||
|
||||
_ASM_FILE_PROLOGUE
|
||||
|
||||
GDATA(_sw_isr_table)
|
||||
|
||||
GTEXT(_isr_wrapper)
|
||||
GTEXT(z_arm_int_exit)
|
||||
GTEXT(_IntExit)
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Wrapper around ISRs when inserted in software ISR table
|
||||
*
|
||||
* When inserted in the vector table, _isr_wrapper() demuxes the ISR table
|
||||
* using the running interrupt number as the index, and invokes the registered
|
||||
* ISR with its corresponding argument. When returning from the ISR, it
|
||||
* determines if a context switch needs to happen (see documentation for
|
||||
* z_arm_pendsv()) and pends the PendSV exception if so: the latter will
|
||||
* perform the context switch itself.
|
||||
* When inserted in the vector table, _isr_wrapper() demuxes the ISR table using
|
||||
* the running interrupt number as the index, and invokes the registered ISR
|
||||
* with its corresponding argument. When returning from the ISR, it determines
|
||||
* if a context switch needs to happen (see documentation for __pendsv()) and
|
||||
* pends the PendSV exception if so: the latter will perform the context switch
|
||||
* itself.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
SECTION_FUNC(TEXT, _isr_wrapper)
|
||||
|
||||
#if defined(CONFIG_CPU_CORTEX_M)
|
||||
push {r0,lr} /* r0, lr are now the first items on the stack */
|
||||
#elif defined(CONFIG_CPU_CORTEX_R)
|
||||
/*
|
||||
* Save away r0-r3 from previous context to the process stack since
|
||||
* they are clobbered here. Also, save away lr since we may swap
|
||||
* processes and return to a different thread.
|
||||
*/
|
||||
push {r4, r5}
|
||||
mov r4, r12
|
||||
sub r5, lr, #4
|
||||
|
||||
cps #MODE_SYS
|
||||
stmdb sp!, {r0-r5}
|
||||
cps #MODE_IRQ
|
||||
|
||||
pop {r4, r5}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXECUTION_BENCHMARKING
|
||||
bl read_timer_start_of_isr
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TRACING
|
||||
bl sys_trace_isr_enter
|
||||
bl z_sys_trace_isr_enter
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_POWER_MANAGEMENT
|
||||
/*
|
||||
* All interrupts are disabled when handling idle wakeup. For tickless
|
||||
* idle, this ensures that the calculation and programming of the
|
||||
* device for the next timer deadline is not interrupted. For
|
||||
* non-tickless idle, this ensures that the clearing of the kernel idle
|
||||
* state is not interrupted. In each case, z_sys_power_save_idle_exit
|
||||
* is called with interrupts disabled.
|
||||
* idle, this ensures that the calculation and programming of the device
|
||||
* for the next timer deadline is not interrupted. For non-tickless idle,
|
||||
* this ensures that the clearing of the kernel idle state is not
|
||||
* interrupted. In each case, z_sys_power_save_idle_exit is called with
|
||||
* interrupts disabled.
|
||||
*/
|
||||
cpsid i /* PRIMASK = 1 */
|
||||
|
||||
@@ -99,13 +82,6 @@ _idle_state_cleared:
|
||||
/* clear kernel idle state */
|
||||
strne r1, [r2, #_kernel_offset_to_idle]
|
||||
blne z_sys_power_save_idle_exit
|
||||
#elif defined(CONFIG_ARMV7_R)
|
||||
beq _idle_state_cleared
|
||||
movs r1, #0
|
||||
/* clear kernel idle state */
|
||||
str r1, [r2, #_kernel_offset_to_idle]
|
||||
bl z_sys_power_save_idle_exit
|
||||
_idle_state_cleared:
|
||||
#else
|
||||
#error Unknown ARM architecture
|
||||
#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
|
||||
@@ -113,9 +89,7 @@ _idle_state_cleared:
|
||||
cpsie i /* re-enable interrupts (PRIMASK = 0) */
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CPU_CORTEX_M)
|
||||
mrs r0, IPSR /* get exception number */
|
||||
#endif
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
ldr r1, =16
|
||||
subs r0, r1 /* get IRQ number */
|
||||
@@ -123,12 +97,6 @@ _idle_state_cleared:
|
||||
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
|
||||
sub r0, r0, #16 /* get IRQ number */
|
||||
lsl r0, r0, #3 /* table is 8-byte wide */
|
||||
#elif defined(CONFIG_ARMV7_R)
|
||||
/*
|
||||
* Cortex-R only has one IRQ line so the main handler will be at
|
||||
* offset 0 of the table.
|
||||
*/
|
||||
mov r0, #0
|
||||
#else
|
||||
#error Unknown ARM architecture
|
||||
#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
|
||||
@@ -152,7 +120,7 @@ _idle_state_cleared:
|
||||
blx r3 /* call ISR */
|
||||
|
||||
#ifdef CONFIG_TRACING
|
||||
bl sys_trace_isr_exit
|
||||
bl z_sys_trace_isr_exit
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
@@ -160,23 +128,12 @@ _idle_state_cleared:
|
||||
mov lr, r3
|
||||
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
|
||||
pop {r0, lr}
|
||||
#elif defined(CONFIG_ARMV7_R)
|
||||
/*
|
||||
* r0,lr were saved on the process stack since a swap could
|
||||
* happen. exc_exit will handle getting those values back
|
||||
* from the process stack to return to the correct location
|
||||
* so there is no need to do anything here.
|
||||
*/
|
||||
#else
|
||||
#error Unknown ARM architecture
|
||||
#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
|
||||
|
||||
#if defined(CONFIG_CPU_CORTEX_R)
|
||||
mov r0, #RET_FROM_IRQ
|
||||
#endif
|
||||
|
||||
/* Use 'bx' instead of 'b' because 'bx' can jump further, and use
|
||||
* 'bx' instead of 'blx' because exception return is done in
|
||||
* z_arm_int_exit() */
|
||||
ldr r1, =z_arm_int_exit
|
||||
bx r1
|
||||
* _IntExit() */
|
||||
ldr r0, =_IntExit
|
||||
bx r0
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user