Compare commits
161 commits
master
...
releases/1
Author | SHA1 | Date | |
---|---|---|---|
|
5d8cdeaea8 | ||
|
57a385a994 | ||
|
c87454220d | ||
|
7e6f83a2b8 | ||
|
f3d6119282 | ||
|
46b1c8605a | ||
|
f81c8051a3 | ||
|
dceb26c7b2 | ||
|
17efd01d13 | ||
|
f61bfd5608 | ||
|
001de69be9 | ||
|
7e89ff5d11 | ||
|
c2bcc56546 | ||
|
cff121bc23 | ||
|
2c0e2ac36b | ||
|
803489b546 | ||
|
17cbaadce8 | ||
|
c0ce2083ad | ||
|
2f12e18297 | ||
|
1c8d0bfdc7 | ||
|
ca989b5101 | ||
|
9dc3e4ee41 | ||
|
6e7d90e195 | ||
|
956d77ba23 | ||
|
6dd26a3e68 | ||
|
5ff98fb4e1 | ||
|
d39bcd4ad5 | ||
|
9a317472fd | ||
|
946b01d4a8 | ||
|
8b8a2610ab | ||
|
064415a765 | ||
|
aa4a428825 | ||
|
33e30239f1 | ||
|
cdb5a7c6d4 | ||
|
b52ad53cc1 | ||
|
28cfadb4b0 | ||
|
1b64c80d72 | ||
|
71d57aac25 | ||
|
cedcb1a674 | ||
|
9192916a4e | ||
|
997162685c | ||
|
8ca0bb35af | ||
|
07c48eb7d0 | ||
|
cc711e0c99 | ||
|
002d89885e | ||
|
c5f816e16a | ||
|
a157436a57 | ||
|
801805d4a2 | ||
|
0b98e9e680 | ||
|
8074812517 | ||
|
e65b03edd2 | ||
|
9da6761453 | ||
|
f51c5452b2 | ||
|
b1932c668d | ||
|
c35e25b7e5 | ||
|
d54bc8a9f8 | ||
|
6392d5a6b3 | ||
|
fbed4ece2c | ||
|
f5a449487c | ||
|
4a796c39bb | ||
|
5e2d205e1b | ||
|
755bef6c56 | ||
|
e0d9cc432c | ||
|
4fd92edee7 | ||
|
487fcb3bce | ||
|
8275a846b1 | ||
|
ec58a6ab25 | ||
|
fad4232925 | ||
|
a33528fa4a | ||
|
bbea8dcefe | ||
|
192dde1b58 | ||
|
7975c94d88 | ||
|
669cd3aa2c | ||
|
7cbcf82bed | ||
|
d782f6c1ac | ||
|
40d40015f4 | ||
|
068c7176bb | ||
|
bb8eb9398d | ||
|
542e46319c | ||
|
a9df7f0d1e | ||
|
1fb4f8f50e | ||
|
2f4c067c50 | ||
|
c48f158e66 | ||
|
7cf9b73f18 | ||
|
1cb81f9a8f | ||
|
3b1870028c | ||
|
f2a4d59900 | ||
|
fb97285a36 | ||
|
dbcef4f297 | ||
|
fe1286b44a | ||
|
87b940a611 | ||
|
52473d7fa2 | ||
|
7f4f7f293d | ||
|
e33bdd9e38 | ||
|
1407a44862 | ||
|
519c5c86aa | ||
|
1e091fb2e0 | ||
|
db95659a9c | ||
|
271893ed6d | ||
|
439c52937a | ||
|
536ed46ac4 | ||
|
5613675834 | ||
|
3f47fd767a | ||
|
94fe00ebec | ||
|
01bed328ef | ||
|
0ac21a911b | ||
|
8155102f7d | ||
|
e6b703c29f | ||
|
52ffca5b8e | ||
|
45bb7a9c1c | ||
|
63515d584b | ||
|
9b698b2304 | ||
|
2bb4ec0fd2 | ||
|
ccddaa78c9 | ||
|
4324970980 | ||
|
f791311138 | ||
|
508c5889d7 | ||
|
1237e9fcea | ||
|
f1f38b6e16 | ||
|
6fd1ca64a1 | ||
|
a26051e7bc | ||
|
a8717c6453 | ||
|
ed998c08c4 | ||
|
cc9d42804b | ||
|
a8ffa96b65 | ||
7edb84c0c5 | |||
|
5f6eb292a8 | ||
|
9dbde04327 | ||
|
8cd52bee2e | ||
|
d573952790 | ||
|
4ecb6efee8 | ||
|
ee81823546 | ||
|
b63826a736 | ||
|
42ee317eab | ||
|
593768e11e | ||
|
b7121aac86 | ||
|
d8637788a7 | ||
|
dff79e8e54 | ||
|
77d1f78996 | ||
|
431b848c79 | ||
|
21501f65b1 | ||
|
a23ed77782 | ||
|
835aac23b7 | ||
|
2f512f78bf | ||
|
753e4d64ee | ||
|
d309d49cae | ||
|
3100deda9d | ||
|
9403bc126b | ||
|
79b4b39994 | ||
|
3b0e2be058 | ||
|
a965e3c3f9 | ||
|
10e44f8915 | ||
|
2d3c94411b | ||
|
d1fec65e1b | ||
|
57f84aaca8 | ||
|
a4e90b7268 | ||
|
6a4196c572 | ||
|
eb0732a183 | ||
|
40354619f3 | ||
|
1179802cfe | ||
|
2ec6c6e1fc |
541 changed files with 13068 additions and 15857 deletions
1
.github/linters/setup.cfg
vendored
1
.github/linters/setup.cfg
vendored
|
@ -2,6 +2,7 @@
|
|||
ignore = W503,W605,E203
|
||||
max-complexity = 27
|
||||
max-line-length = 125
|
||||
multi_line_output=3
|
||||
show-source = True
|
||||
statistics = True
|
||||
|
||||
|
|
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
|
@ -86,7 +86,7 @@ jobs:
|
|||
fi
|
||||
|
||||
echo "name=$OS_REF" >> $GITHUB_OUTPUT
|
||||
echo "app_ref=$APPS_REF" >> $GITHUB_OUTPUT
|
||||
echo "apps_ref=$APPS_REF" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Checkout nuttx repo
|
||||
uses: actions/checkout@v4
|
||||
|
|
4
.github/workflows/check.yml
vendored
4
.github/workflows/check.yml
vendored
|
@ -39,7 +39,9 @@ jobs:
|
|||
- name: Check Pull Request
|
||||
run: |
|
||||
echo "::add-matcher::nuttx/.github/nxstyle.json"
|
||||
pip install cmake-format
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install cmake-format black isort flake8
|
||||
cd nuttx
|
||||
commits="${{ github.event.pull_request.base.sha }}..HEAD"
|
||||
git log --oneline $commits
|
||||
|
|
|
@ -667,6 +667,9 @@ elseif(WIN32)
|
|||
"${CONFIG_SIM_STACKSIZE_ADJUSTMENT} + ${CONFIG_IDLETHREAD_STACKSIZE}"
|
||||
OUTPUT_FORMAT DECIMAL)
|
||||
target_link_options(nuttx PUBLIC /STACK:${LINK_STACKSIZE},${LINK_STACKSIZE})
|
||||
if("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "x64")
|
||||
target_link_options(nuttx PUBLIC /LARGEADDRESSAWARE:NO)
|
||||
endif()
|
||||
set(nuttx_libs_paths)
|
||||
foreach(lib ${nuttx_libs})
|
||||
list(APPEND nuttx_libs_paths $<TARGET_FILE:${lib}>)
|
||||
|
|
768
Documentation/ReleaseNotes/NuttX-12.7.0
Normal file
768
Documentation/ReleaseNotes/NuttX-12.7.0
Normal file
|
@ -0,0 +1,768 @@
|
|||
What's New In This Release
|
||||
Core OS
|
||||
Sched
|
||||
* [#13395](https://github.com/apache/nuttx/pull/13395) Critmon optimize, make possible open cpuload based on critmon and disable critical section & sched_lock to save cost.
|
||||
* [#12691](https://github.com/apache/nuttx/pull/12691) sched.h: add SCHED_BATCH and SCHED_IDLE definition
|
||||
* [#12584](https://github.com/apache/nuttx/pull/12584) sched.h: CPU_XXX macros can also be used without CONFIG_SMP
|
||||
* [#12703](https://github.com/apache/nuttx/pull/12703) sched.h: Update doc link for tcbinfo_s
|
||||
* [#13274](https://github.com/apache/nuttx/pull/13274) sched: add DEBUGASSERT to assure that affinity not zero
|
||||
* [#13341](https://github.com/apache/nuttx/pull/13341) sched: adjust the scheduling strategy
|
||||
* [#13105](https://github.com/apache/nuttx/pull/13105) sched: change pthread_mutex implementation from sem to mutex
|
||||
* [#12742](https://github.com/apache/nuttx/pull/12742) sched: Improve Kconfig help of INIT_ENTRYPOINT
|
||||
* [#13525](https://github.com/apache/nuttx/pull/13525) sched: move DUMP_ON_EXIT to sched
|
||||
* [#13211](https://github.com/apache/nuttx/pull/13211) sched: replace up_cpu_index with this_cpu
|
||||
* [#13271](https://github.com/apache/nuttx/pull/13271) sched: use this_task replace nxsched_self
|
||||
* [#13263](https://github.com/apache/nuttx/pull/13263) sched/event: clear pending events before enable the scheduler
|
||||
* [#13329](https://github.com/apache/nuttx/pull/13329) sched/group/setuptask_file: duplicate idle task fd for kernel thread
|
||||
* [#13083](https://github.com/apache/nuttx/pull/13083) sched/irq: correct critical section to spin lock
|
||||
* [#12802](https://github.com/apache/nuttx/pull/12802) sched/nxevent: add support of kernel event group
|
||||
* [#13264](https://github.com/apache/nuttx/pull/13264) sched/policy: move g_policy from data to rodata
|
||||
* [#13017](https://github.com/apache/nuttx/pull/13017) sched/sched: simplify the implementation of the function nxsched_readytorun_setpriority
|
||||
* [#13134](https://github.com/apache/nuttx/pull/13134) sched/signal: fix pthread_kill use after free
|
||||
* [#13530](https://github.com/apache/nuttx/pull/13530) sched/signal: Simplified Implementation for SIGEV_THREAD_TID
|
||||
* [#12283](https://github.com/apache/nuttx/pull/12283) sched/signal: There is no need to use sched_[un]lock
|
||||
* [#12553](https://github.com/apache/nuttx/pull/12553) sched/tcb: amend pull/12320
|
||||
MM
|
||||
* [#12550](https://github.com/apache/nuttx/pull/12550) mm: add mm_initialize_pool, make pool more flexible
|
||||
* [#12556](https://github.com/apache/nuttx/pull/12556) mm: mm_threshold perfer from init
|
||||
* [#12501](https://github.com/apache/nuttx/pull/12501) mm/iob: Simplify IOB alloc/free logic
|
||||
* [#12923](https://github.com/apache/nuttx/pull/12923) mm/map/vm_region.c: Fix usage of void* arithmetics
|
||||
* [#12946](https://github.com/apache/nuttx/pull/12946) mm/mempool: rename the mempool_alloc and mempool_free function
|
||||
* [#12659](https://github.com/apache/nuttx/pull/12659) mm_ubsan: add dummy to bypass runtime actions
|
||||
* [#12646](https://github.com/apache/nuttx/pull/12646) mm_ubsan: add implement for dynamic_type_cache_miss
|
||||
libc
|
||||
* [#12672](https://github.com/apache/nuttx/pull/12672) add rint and expm1 function to cmath from libm
|
||||
* [#13420](https://github.com/apache/nuttx/pull/13420) Add dummy implementations for `shm_open` `pthread_setaffinity_np` and `RLIMIT_RTPRIO`
|
||||
* [#13429](https://github.com/apache/nuttx/pull/13429) arm64_task/pthread_start: Convert the C / inline ASM code to assembly
|
||||
* [#13366](https://github.com/apache/nuttx/pull/13366) arm64/task/pthread_start: Fix rare issue with context register location
|
||||
* [#13011](https://github.com/apache/nuttx/pull/13011) lib_getcwd:Fix the Name in the function description.
|
||||
* [#12966](https://github.com/apache/nuttx/pull/12966) lib_remove:Repair the logical judgment
|
||||
* [#12890](https://github.com/apache/nuttx/pull/12890) libc: Add macro restrictions to code that uses floating point numbers
|
||||
* [#13111](https://github.com/apache/nuttx/pull/13111) libc: compile stackchk function by default
|
||||
* [#12953](https://github.com/apache/nuttx/pull/12953) libs: fix the default value of process-shared attribute
|
||||
* [#12975](https://github.com/apache/nuttx/pull/12975) libs: fix the default value of process-shared attribute
|
||||
* [#12605](https://github.com/apache/nuttx/pull/12605) libc: scanf, printf %z change switch const to if
|
||||
* [#12585](https://github.com/apache/nuttx/pull/12585) libc/execinfo: extract a common backtrace format function
|
||||
* [#13013](https://github.com/apache/nuttx/pull/13013) libc/msic: Implement get_nprocs API
|
||||
* [#13381](https://github.com/apache/nuttx/pull/13381) libc/misc/crc32: crc32 add slow mode, optional decrease size
|
||||
* [#13441](https://github.com/apache/nuttx/pull/13441) libc/netdb: Remove unnecessary CONFIG_LIBC_NETDB checks
|
||||
* [#13025](https://github.com/apache/nuttx/pull/13025) libc/netdb: Separate IPv4 and IPv6 cache size limit
|
||||
* [#13220](https://github.com/apache/nuttx/pull/13220) libc/sysconf: add _SC_GETPW_R_SIZE_MAX
|
||||
* [#13479](https://github.com/apache/nuttx/pull/13479) libc/time: add g_lcl_lock to protect local context in localsub
|
||||
* [#13080](https://github.com/apache/nuttx/pull/13080) libc/time: remove lib_strptime
|
||||
* [#12693](https://github.com/apache/nuttx/pull/12693) libc/unistd: added an implementation of the lib_flock function
|
||||
* [#12609](https://github.com/apache/nuttx/pull/12609) libc/x86_64: port string functions from bionic
|
||||
* [#13110](https://github.com/apache/nuttx/pull/13110) libcxxabi: libcxxabi enables exceptions by default
|
||||
* [#13079](https://github.com/apache/nuttx/pull/13079) libs/libc/obstack: correctly append null byte at the end of string
|
||||
* [#13482](https://github.com/apache/nuttx/pull/13482) libs/libc/obstack: implement ptr and int growing functions
|
||||
* [#13495](https://github.com/apache/nuttx/pull/13495) libs/libc/obstack: revert invalid null byte append to obstack_vprintf
|
||||
* [#13185](https://github.com/apache/nuttx/pull/13185) libs/libc/stdio/*printf *scanf:Add string serialization and deserialization functions
|
||||
* [#13294](https://github.com/apache/nuttx/pull/13294) libs/libm: fix epsilon relaxation in log and logf
|
||||
* [#13307](https://github.com/apache/nuttx/pull/13307) libs/libm/libm: apply epsilon relax factor only if epsilon is small
|
||||
* [#12568](https://github.com/apache/nuttx/pull/12568) libm{libm|newlib}: fix broken sincos optimization for GCC
|
||||
* [#12811](https://github.com/apache/nuttx/pull/12811) libm/copysign: respect signed zero/NaN handling in copysign
|
||||
* [#13174](https://github.com/apache/nuttx/pull/13174) syscall: delete getrandom in syscall because it have moved to lib
|
||||
* [#13428](https://github.com/apache/nuttx/pull/13428) gdb plugin: Encapsulate the gdb native command gcore as nxgcore
|
||||
* [#12557](https://github.com/apache/nuttx/pull/12557) gdbstub: fix typo
|
||||
* [#12549](https://github.com/apache/nuttx/pull/12549) gdbstub: support gdbstub_debugpoint_add/remove smp call
|
||||
* [#13339](https://github.com/apache/nuttx/pull/13339) nuttx/pthread: export priority protect in pthread with ceiling priority in semaphore
|
||||
* [#12561](https://github.com/apache/nuttx/pull/12561) pthread: add pthread_self/pthread_gettid_np function
|
||||
* [#13462](https://github.com/apache/nuttx/pull/13462) pthread_mutx: remove unused critical_secton lock
|
||||
* [#13456](https://github.com/apache/nuttx/pull/13456) pthread_mutex: add deadlock assert
|
||||
tools
|
||||
* [#12701](https://github.com/apache/nuttx/pull/12701) Feature/mcuboot toolchain support
|
||||
* [#13021](https://github.com/apache/nuttx/pull/13021) tools: add improved pre-commit tool
|
||||
* [#12794](https://github.com/apache/nuttx/pull/12794) tools: nxstyle if statement check
|
||||
* [#12651](https://github.com/apache/nuttx/pull/12651) tools/imx9: prepare bootable bootloader image
|
||||
* [#12838](https://github.com/apache/nuttx/pull/12838) tools/[Rust|D]: Fix build break for RISC-V
|
||||
* [#12854](https://github.com/apache/nuttx/pull/12854) tools/[Rust|D]: Fix the Rust and D Builds for QEMU RISC-V
|
||||
* [#12983](https://github.com/apache/nuttx/pull/12983) tools/parsetrace.py:fix parsetrace script error
|
||||
* [#13321](https://github.com/apache/nuttx/pull/13321) greenhills support: add ghs linker script for mps2-an500 platform
|
||||
* [#12884](https://github.com/apache/nuttx/pull/12884) greenhills support: add Kconfig, makefile, make.defs support for ghs compiler
|
||||
* [#12887](https://github.com/apache/nuttx/pull/12887) greenhills support: add new platform of qemu cortex-m7
|
||||
* [#13146](https://github.com/apache/nuttx/pull/13146) greenhills support: add the "__sync_synchronize" func impl
|
||||
* [#12877](https://github.com/apache/nuttx/pull/12877) greenhills support: add up_getsp() implementation to adapting greenhills compiler
|
||||
* [#12883](https://github.com/apache/nuttx/pull/12883) greenhills support: fix the asm build error for adapting to greenhills compiler
|
||||
* [#12885](https://github.com/apache/nuttx/pull/12885) greenhills support: fix the build and link error specific to ghs platform
|
||||
* [#13144](https://github.com/apache/nuttx/pull/13144) greenhills support: fix the build options warning
|
||||
* [#13207](https://github.com/apache/nuttx/pull/13207) greenhills support: fix the build option warning
|
||||
* [#13145](https://github.com/apache/nuttx/pull/13145) greenhills support: fix the build warning while support greenhills build
|
||||
* [#12886](https://github.com/apache/nuttx/pull/12886) greenhills support: fix the build warning for ghs platform
|
||||
* [#13533](https://github.com/apache/nuttx/pull/13533) greenhills support: fix the enumerated type mixed using warning
|
||||
* [#13322](https://github.com/apache/nuttx/pull/13322) greenhills support: fix the ghs build warning
|
||||
* [#13502](https://github.com/apache/nuttx/pull/13502) greenhills support: fix the greenhills compile warning on sizeof operand
|
||||
* [#13195](https://github.com/apache/nuttx/pull/13195) greenhills support: fix the pointless comparison build warning
|
||||
various
|
||||
* [#12552](https://github.com/apache/nuttx/pull/12552) compiler.h: rename CMSE extension attribute macros
|
||||
* [#12874](https://github.com/apache/nuttx/pull/12874) fix stm32wl5_rcc.h: Add the missing argument to RCC_PLLCFG_PLLP define.
|
||||
* [#13148](https://github.com/apache/nuttx/pull/13148) include/fcntl.h: add O_LARGEFILE flags
|
||||
* [#13324](https://github.com/apache/nuttx/pull/13324) include/sensors: import public definitions types and to uorb.h
|
||||
* [#12690](https://github.com/apache/nuttx/pull/12690) ioctl.h: add SIOCATMARK definition to resolve compilation errors
|
||||
* [#13314](https://github.com/apache/nuttx/pull/13314) ip6_tables.h: fix gcc 14 errors
|
||||
* [#13257](https://github.com/apache/nuttx/pull/13257) socketlin : add lin.h and lin bus-type
|
||||
* [#12692](https://github.com/apache/nuttx/pull/12692) sysinfo.h: add get_nprocs_conf/get_nprocs definition
|
||||
* [#13149](https://github.com/apache/nuttx/pull/13149) sys/shm.h: add macro define for posix
|
||||
* [#12594](https://github.com/apache/nuttx/pull/12594) x86_64/irq.h: use 32bit operations in up_cpu_index(
|
||||
|
||||
Build System
|
||||
New Features
|
||||
* [#12904](https://github.com/apache/nuttx/pull/12904) [Cross-Platform] Remove Unix-specific code in savedefconfig and replace it with cmake script
|
||||
* [#12910](https://github.com/apache/nuttx/pull/12910) [cmake] add_application supports only registration but not compilation
|
||||
* [#12964](https://github.com/apache/nuttx/pull/12964) [cmake] split the archive process to avoid parameter too long problems
|
||||
* [#13019](https://github.com/apache/nuttx/pull/13019) [cmake] add nuttx_post and app_context inter targets for timing control
|
||||
* [#12908](https://github.com/apache/nuttx/pull/12908) [Win32 sim] enable win32 native platfrom sim compilation by CMake fix compilation error
|
||||
* [#12900](https://github.com/apache/nuttx/pull/12900) arch/sim/src/cmake/Toolchain.cmake: macOS fix unknown options: --gc-sections
|
||||
* [#12856](https://github.com/apache/nuttx/pull/12856) build: Fix libc/pwd CMakeLists.txt
|
||||
* [#13347](https://github.com/apache/nuttx/pull/13347) build: fix memory manager compile options for CMake
|
||||
* [#12859](https://github.com/apache/nuttx/pull/12859) build: Fix Toolchain.cmake for CONFIG_SIM_ASAN enabled
|
||||
* [#12880](https://github.com/apache/nuttx/pull/12880) build: set CMake policy to allow FetchContent_Populate
|
||||
* [#12784](https://github.com/apache/nuttx/pull/12784) build/cmake: add user_ldscript preprocessing
|
||||
* [#12866](https://github.com/apache/nuttx/pull/12866) build/cmake: fix system include dir for PROTECTED mode
|
||||
* [#13143](https://github.com/apache/nuttx/pull/13143) board/maix-bit: initial cmake support
|
||||
* [#13090](https://github.com/apache/nuttx/pull/13090) board/qemu-armv7a: add CMake support
|
||||
* [#12868](https://github.com/apache/nuttx/pull/12868) boards/rv-virt: cmake for pnsh and nsbi
|
||||
* [#13175](https://github.com/apache/nuttx/pull/13175) Cmake: [arch arm] added initial support for MSYS2
|
||||
* [#13389](https://github.com/apache/nuttx/pull/13389) cmake: add support for PCI
|
||||
* [#12516](https://github.com/apache/nuttx/pull/12516) cmake: reuse OpenAMP own CMake script for CMake build
|
||||
* [#12592](https://github.com/apache/nuttx/pull/12592) cmake: refine sim cmake redefine symbols
|
||||
* [#13449](https://github.com/apache/nuttx/pull/13449) cmake: Refactor extra_lib tagert,build include_arch path,refine sim link script target
|
||||
* [#12667](https://github.com/apache/nuttx/pull/12667) cmake: strip file full path to save the code size
|
||||
* [#13451](https://github.com/apache/nuttx/pull/13451) cmake: support openlibm,dhara,libmcs,lic regex CMake build scripts
|
||||
* [#12608](https://github.com/apache/nuttx/pull/12608) cmake/add_library: enable library install by default
|
||||
* [#12714](https://github.com/apache/nuttx/pull/12714) cmake/boards: fix build break on custom board
|
||||
* [#13085](https://github.com/apache/nuttx/pull/13085) CMakeLists.txt: warning D9002 on Windows + msvc
|
||||
* [#13253](https://github.com/apache/nuttx/pull/13253) cmake/nuttx_kconfig.cmake: fixed the correct .config path in the buid folder
|
||||
* [#13276](https://github.com/apache/nuttx/pull/13276) cmake/tricore: filter out nostdlib in linker phase to avoid build break
|
||||
* [#13499](https://github.com/apache/nuttx/pull/13499) libc: add missing preadv/pwritev in CMakeLists.txt
|
||||
* [#12700](https://github.com/apache/nuttx/pull/12700) riscv/cmake: fix Toolchain.cmake
|
||||
* [#12694](https://github.com/apache/nuttx/pull/12694) riscv/k230: fix apps ROMFS cmake
|
||||
* [#12996](https://github.com/apache/nuttx/pull/12996) riscv/qemu-rv: add RPTUN cmake
|
||||
* [#12634](https://github.com/apache/nuttx/pull/12634) sim/cmake: enable garbage collection of unused input sections
|
||||
* [#12721](https://github.com/apache/nuttx/pull/12721) tools/testbuild.sh: add option -N use CMake with Ninja
|
||||
* [#12805](https://github.com/apache/nuttx/pull/12805) tools/testbuild.sh: added store compilation artifacts for cmake
|
||||
* [#12724](https://github.com/apache/nuttx/pull/12724) tricore/cmake: add support of cmake build for tricore
|
||||
Bug Fixes
|
||||
* [#12558](https://github.com/apache/nuttx/pull/12558) [bugfix] cmake:fix a few issues during CMake build
|
||||
* [#12915](https://github.com/apache/nuttx/pull/12915) [bugfix] fix CMake build block when enable LTO
|
||||
* [#12582](https://github.com/apache/nuttx/pull/12582) Fix cmake for cxd56xx
|
||||
* [#12581](https://github.com/apache/nuttx/pull/12581) cmake: Fix build failure when -DNUTTX_APPS_DIR is specified
|
||||
* [#13171](https://github.com/apache/nuttx/pull/13171) CMake: fix CMake compile errors during the protected build mode
|
||||
* [#13081](https://github.com/apache/nuttx/pull/13081) cmake: fix invalid syntax when generating version.h from tags
|
||||
|
||||
Architectural Support
|
||||
unsorted
|
||||
* [#12827](https://github.com/apache/nuttx/pull/12827) Additional encoder for F7 and added functions for TimerHook for F745 …
|
||||
* [#12924](https://github.com/apache/nuttx/pull/12924) Bugfix/esp spi fix
|
||||
* [#12770](https://github.com/apache/nuttx/pull/12770) Enable SMPS for STM32H745I-DISCO by default
|
||||
* [#12574](https://github.com/apache/nuttx/pull/12574) arch: Add --whole-archive linker option for some of architectures
|
||||
* [#13200](https://github.com/apache/nuttx/pull/13200) arch: cxd56xx: Add logic for i2c reset
|
||||
* [#13496](https://github.com/apache/nuttx/pull/13496) arch: cxd56xx: Fix issue by update of inode reference
|
||||
* [#13201](https://github.com/apache/nuttx/pull/13201) arch: cxd56xx: Fix SCU sensor data format
|
||||
* [#12962](https://github.com/apache/nuttx/pull/12962) arch: inline this_task to improve performence
|
||||
* [#13270](https://github.com/apache/nuttx/pull/13270) arch: remove unused up_cpu_pausereq waiting
|
||||
* [#13423](https://github.com/apache/nuttx/pull/13423) arch: use up_current_regs/up_set_current_regs replace CURRENT_REGS
|
||||
* [#13041](https://github.com/apache/nuttx/pull/13041) arch/EXTRA_LIBS: link all staging library.
|
||||
* [#12624](https://github.com/apache/nuttx/pull/12624) arch/sim: add custom data section support
|
||||
* [#12909](https://github.com/apache/nuttx/pull/12909) arch/sim/Kconfig: set SIM_FBBPP to 32 by default
|
||||
* [#12845](https://github.com/apache/nuttx/pull/12845) arch/stm32h7: add defines for USART clock selection
|
||||
* [#13292](https://github.com/apache/nuttx/pull/13292) arch/xmc4 : Add input pin DX0 selection for multiple SPI channel
|
||||
* [#12823](https://github.com/apache/nuttx/pull/12823) arch/xmc4 : Fixed critical section in i2c_transfer
|
||||
* [#12761](https://github.com/apache/nuttx/pull/12761) arch/xmc4 : i2c master lower-half driver
|
||||
* [#12545](https://github.com/apache/nuttx/pull/12545) BL808: Add support for UARTs 0-2 and serial configuration
|
||||
* [#12575](https://github.com/apache/nuttx/pull/12575) BL808: Replace courier with M0 interrupt controller
|
||||
* [#12795](https://github.com/apache/nuttx/pull/12795) elf: Enable ELF loader if text heap read is word-aligned and enable ELF loader for ESP32-S3
|
||||
* [#12620](https://github.com/apache/nuttx/pull/12620) esp32: add simple boot support
|
||||
* [#12616](https://github.com/apache/nuttx/pull/12616) ESP32: emac initialization adding cpu id
|
||||
* [#13249](https://github.com/apache/nuttx/pull/13249) esp32: enable APP_CPU cache earlier
|
||||
* [#13244](https://github.com/apache/nuttx/pull/13244) esp32: cache_sram_mmu_set: update the correct register bits
|
||||
* [#13222](https://github.com/apache/nuttx/pull/13222) esp32: fix a crash with PSRAM + SMP
|
||||
* [#13243](https://github.com/apache/nuttx/pull/13243) esp32: fix seemingly wrong calculations
|
||||
* [#13250](https://github.com/apache/nuttx/pull/13250) esp32: psram_set_cs_timing: sync with esp-idf
|
||||
* [#13311](https://github.com/apache/nuttx/pull/13311) esp32: Port the bootloader patch
|
||||
* [#12572](https://github.com/apache/nuttx/pull/12572) esp32[c3|c6|h2]: Add I2C master support
|
||||
* [#12573](https://github.com/apache/nuttx/pull/12573) esp32[c3|c6|h2]: Add GDMA support
|
||||
* [#13298](https://github.com/apache/nuttx/pull/13298) esp32c6: PCNT Quadrature Encoder driver
|
||||
* [#13269](https://github.com/apache/nuttx/pull/13269) esp32s2: fix SPI flash and file system mounting
|
||||
* [#12647](https://github.com/apache/nuttx/pull/12647) esp32s3-devkit: add a config for qemu
|
||||
* [#12851](https://github.com/apache/nuttx/pull/12851) esp32s3-devkit/toywasm: enable ESP32S3_SPI_FLASH_SUPPORT_PSRAM_STACK
|
||||
* [#12725](https://github.com/apache/nuttx/pull/12725) esp32s3_textheap.c: fix a build error w/o CONFIG_ESP32S3_SPIRAM
|
||||
* [#12565](https://github.com/apache/nuttx/pull/12565) esp32s3/wifi: Fix bug related to IOB off-loading with SMP
|
||||
* [#12789](https://github.com/apache/nuttx/pull/12789) esp32s3/i2s: Fix faulty initialization when SMP is enabled
|
||||
* [#13265](https://github.com/apache/nuttx/pull/13265) esp32_psram.c: Remove a seemingly stale comment
|
||||
* [#12669](https://github.com/apache/nuttx/pull/12669) Feature/esp mcuboot support
|
||||
* [#12776](https://github.com/apache/nuttx/pull/12776) Feature/esp spi dma
|
||||
* [#12775](https://github.com/apache/nuttx/pull/12775) Feature/esp temperature sensor
|
||||
* [#12604](https://github.com/apache/nuttx/pull/12604) fix(esp32-qemu-openeth): allocate buffers in internal memory
|
||||
* [#13193](https://github.com/apache/nuttx/pull/13193) gd32f4xx_at24: Fix uninitialized use of local variables i2c and at24
|
||||
* [#13401](https://github.com/apache/nuttx/pull/13401) Imx9 ethernet fixes
|
||||
* [#12632](https://github.com/apache/nuttx/pull/12632) Imx9 support flexspi m25p nor
|
||||
* [#13399](https://github.com/apache/nuttx/pull/13399) imx9/edma: Fix function prototypes
|
||||
* [#13400](https://github.com/apache/nuttx/pull/13400) imx9/LPUART fixes
|
||||
* [#12921](https://github.com/apache/nuttx/pull/12921) imx93: Add more base addresses
|
||||
* [#12623](https://github.com/apache/nuttx/pull/12623) imxrt: Correctly update PLL, bit has to toggled instead of being set
|
||||
* [#12562](https://github.com/apache/nuttx/pull/12562) imxrt: imxrt11xx set core clock to 1p15v regardless of ocotp
|
||||
* [#12821](https://github.com/apache/nuttx/pull/12821) k230_start.c: Fix condition for k230_copy_init_data()
|
||||
* [#12894](https://github.com/apache/nuttx/pull/12894) mps3-an547:support mps3-an547 reset
|
||||
* [#12989](https://github.com/apache/nuttx/pull/12989) nuttx/sim:By default, stack-use-after-return is not checked when enabling SIM_ASAN.
|
||||
* [#13043](https://github.com/apache/nuttx/pull/13043) nuttx/sim:By default, stack-use-after-return is not checked when enabling SIM_ASAN.
|
||||
* [#13548](https://github.com/apache/nuttx/pull/13548) nrf91: Update GPS to GNSS
|
||||
* [#12612](https://github.com/apache/nuttx/pull/12612) refactor(esp32-qemu-openeth): use lower half driver interface
|
||||
* [#12660](https://github.com/apache/nuttx/pull/12660) refresh esp32s3-devkit:qemu_debug
|
||||
* [#12707](https://github.com/apache/nuttx/pull/12707) rp2040 Rename the RP2040-specific PWM_MULTICHAN definition
|
||||
* [#12610](https://github.com/apache/nuttx/pull/12610) rp2040: Add support to MAX6675
|
||||
* [#13318](https://github.com/apache/nuttx/pull/13318) rp2040: Support pico-sdk 2.0.0
|
||||
* [#13070](https://github.com/apache/nuttx/pull/13070) Sync the modifications of the WiFi function in simulator.
|
||||
* [#12697](https://github.com/apache/nuttx/pull/12697) s32k1xx: FlexIO i2c driver
|
||||
* [#12678](https://github.com/apache/nuttx/pull/12678) samv7: fix compile warning in PWM driver
|
||||
* [#12627](https://github.com/apache/nuttx/pull/12627) samv7/sam_mcan.c: fix TSEG1, TSEG2 and SJW compile warnings for MCAN1
|
||||
* [#12622](https://github.com/apache/nuttx/pull/12622) sim: make possible keep ubsan and bypass feature
|
||||
* [#13034](https://github.com/apache/nuttx/pull/13034) sim: read the second buffer
|
||||
* [#13097](https://github.com/apache/nuttx/pull/13097) sim: Support to use of non-consecutive framebuffers
|
||||
* [#13355](https://github.com/apache/nuttx/pull/13355) sim_offload: add lame library to apps/audioutils/lame
|
||||
* [#12870](https://github.com/apache/nuttx/pull/12870) sim/login: remove login restrictions to improve the experience for green hands
|
||||
* [#13534](https://github.com/apache/nuttx/pull/13534) sim/minmea: Fix defconfig warning
|
||||
* [#13042](https://github.com/apache/nuttx/pull/13042) simwifi: Add the netlink event of connect/disconnect.
|
||||
* [#12778](https://github.com/apache/nuttx/pull/12778) Small improvements to nrf91
|
||||
* [#13282](https://github.com/apache/nuttx/pull/13282) smp: enable smp_call in all smp arch
|
||||
* [#12566](https://github.com/apache/nuttx/pull/12566) STM32G47XXX: Added basic HRTIM support.
|
||||
* [#12600](https://github.com/apache/nuttx/pull/12600) tee smp support
|
||||
* [#12640](https://github.com/apache/nuttx/pull/12640) Userleds support to seed-xiao-rp2040
|
||||
* [#13032](https://github.com/apache/nuttx/pull/13032) wifi_sim.c:fix compile warning
|
||||
|
||||
Architecture Improvements
|
||||
arm
|
||||
* [#12626](https://github.com/apache/nuttx/pull/12626) arch/arm/stm32: Fix EXTI lines definitions for STM32G47XX.
|
||||
* [#12664](https://github.com/apache/nuttx/pull/12664) arch/armv8-r: new config to set SPIs Configuration to edge-triggered
|
||||
* [#12666](https://github.com/apache/nuttx/pull/12666) arch/armv8-r: update g_running_tasks before context switch
|
||||
* [#13472](https://github.com/apache/nuttx/pull/13472) arch/arm-m: Clear lr before jump to __start
|
||||
* [#13284](https://github.com/apache/nuttx/pull/13284) arch/arm: support kernel heap in BUILD_FLAT mode
|
||||
* [#13416](https://github.com/apache/nuttx/pull/13416) arm generate busfault & recursive bug fix
|
||||
* [#13268](https://github.com/apache/nuttx/pull/13268) arm: armv7-a/r and armv8-r up_cpu_index inline
|
||||
* [#13024](https://github.com/apache/nuttx/pull/13024) arm: Fix DS1307 initialization for common STM32 logic
|
||||
* [#12888](https://github.com/apache/nuttx/pull/12888) arm: Select ram vector on armv6m
|
||||
* [#13505](https://github.com/apache/nuttx/pull/13505) arm_addrenv:fix app crash when enable shm in kernel mode
|
||||
* [#12787](https://github.com/apache/nuttx/pull/12787) arm_backtrace_unwind:Make the backtrace search the entire stack as much as possible
|
||||
* [#12954](https://github.com/apache/nuttx/pull/12954) arm/armv[7|8]-m: add syn barrier for MPU ops
|
||||
* [#12925](https://github.com/apache/nuttx/pull/12925) arm/armv8-r: invalidate d-cache on boot
|
||||
* [#12928](https://github.com/apache/nuttx/pull/12928) arm/armv8-r: add cp15 ops for mpu
|
||||
* [#13529](https://github.com/apache/nuttx/pull/13529) arm/cortex-a,r: replace cp15 instruct to macros to align operation
|
||||
* [#13239](https://github.com/apache/nuttx/pull/13239) arm/giv3: add g_ prefix to some global variables
|
||||
* [#13262](https://github.com/apache/nuttx/pull/13262) arm/gicv3: set routing affinity before enable IRQ
|
||||
* [#13240](https://github.com/apache/nuttx/pull/13240) arm/linum-stm32h753bi: Add support to RFID MFRC522
|
||||
* [#12873](https://github.com/apache/nuttx/pull/12873) arm/lm3s6965-ek: Disable NTPC for lm3s6965 to fix maximum flash space…
|
||||
* [#13557](https://github.com/apache/nuttx/pull/13557) arm/qemu: Add mounting of tmpfs
|
||||
* [#13117](https://github.com/apache/nuttx/pull/13117) arm/qemu: enable WFI in `up_idle`
|
||||
* [#13131](https://github.com/apache/nuttx/pull/13131) arm/spinlock: up_testset() sould not depends on SMP
|
||||
* [#12879](https://github.com/apache/nuttx/pull/12879) arm/stm32f401rc-rs485: Add support to BMP280 sensor
|
||||
* [#13565](https://github.com/apache/nuttx/pull/13565) arm/stm32f401rc-rs485: Add support to LCD 16x2 with I2C Backpack
|
||||
* [#12839](https://github.com/apache/nuttx/pull/12839) arm/stm32f401rc-rs485: Add support to RFID MFRC522
|
||||
* [#12860](https://github.com/apache/nuttx/pull/12860) arm/stm32h7/stm32h745i-disco: Add STM32H745I-DISCO Per Core Support
|
||||
* [#12902](https://github.com/apache/nuttx/pull/12902) arm/stm32h7x3x_rcc.c: Add External Power Supply option to stm32h7x3x …
|
||||
* [#12679](https://github.com/apache/nuttx/pull/12679) arm/xmc4: pwm driver
|
||||
* [#13466](https://github.com/apache/nuttx/pull/13466) armv7-a gic related update
|
||||
* [#13176](https://github.com/apache/nuttx/pull/13176) armv7-a timer:fix timer overflow.
|
||||
* [#12956](https://github.com/apache/nuttx/pull/12956) armv7a/irq: enable fiq in tee, enable irq in ap
|
||||
* [#13453](https://github.com/apache/nuttx/pull/13453) armv8-m:arch libc function need save ip register use pacbti
|
||||
* [#13237](https://github.com/apache/nuttx/pull/13237) armv8-r/gicv3: correct cpu index of irouter
|
||||
* [#13275](https://github.com/apache/nuttx/pull/13275) armv8-r/r52: add neon support into compiler lin
|
||||
|
||||
arm64
|
||||
* [#12633](https://github.com/apache/nuttx/pull/12633) arch/arm64/src/imx9/imx9_lowputc.c: Fix an arithmetic sign error in d…
|
||||
* [#12648](https://github.com/apache/nuttx/pull/12648) arch/arm64: allow to use custom up_idle
|
||||
* [#13397](https://github.com/apache/nuttx/pull/13397) arch/arm64/src/imx9/imx9_lpi2c.c: Cleanups and error fixes
|
||||
* [#13402](https://github.com/apache/nuttx/pull/13402) arch/arm64/imx9: Change Kconfig logic
|
||||
* [#13403](https://github.com/apache/nuttx/pull/13403) arch/arm64/imx9: Add system reset controller
|
||||
* [#13427](https://github.com/apache/nuttx/pull/13427) arch/arm64/src/imx9/imx9_lpi2c.c: Ignore spurious RX interrupts
|
||||
* [#13218](https://github.com/apache/nuttx/pull/13218) arch/arm64: Move ELF_64BIT selection to arch/Kconfig
|
||||
* [#12681](https://github.com/apache/nuttx/pull/12681) arm64: add initial support for ZYNQ MPSOC and ZCU111 Evaluation Kit
|
||||
* [#12580](https://github.com/apache/nuttx/pull/12580) arm64: inline up_cpu_index
|
||||
* [#13560](https://github.com/apache/nuttx/pull/13560) arm64_addrenv: Add support for 4 level MMU translations
|
||||
* [#13363](https://github.com/apache/nuttx/pull/13363) arm64_addrenv_pgmap.c: Revoke user execution access to kernel mmap'd pages
|
||||
* [#13364](https://github.com/apache/nuttx/pull/13364) arm64_addrenv.c: Flush kernel page table copy to user mappings
|
||||
* [#13204](https://github.com/apache/nuttx/pull/13204) arm64_checkstack.c: Fix traversing of user stack when ARCH_ADDRENV=Y
|
||||
* [#13361](https://github.com/apache/nuttx/pull/13361) arm64_syscall.c: Don't need to set register context during syscall
|
||||
* [#13365](https://github.com/apache/nuttx/pull/13365) arm64_vector_table.S: Remove unnecessary instruction
|
||||
* [#12695](https://github.com/apache/nuttx/pull/12695) arm64/arm64_boot.c: Fix exception caused by accesses to ICC_SRE_EL3 when GICv3 was not implemented
|
||||
* [#13373](https://github.com/apache/nuttx/pull/13373) arm64/crt0.c: Fix stack alignment when executing signal trampoline
|
||||
* [#12649](https://github.com/apache/nuttx/pull/12649) arm64/imx9: ccm: add default clk init
|
||||
* [#13205](https://github.com/apache/nuttx/pull/13205) arm64/imx9: Force 64-bit ELF format
|
||||
* [#13360](https://github.com/apache/nuttx/pull/13360) arm64/mmu: Fixes for MMU driver
|
||||
* [#13362](https://github.com/apache/nuttx/pull/13362) arm64/syscall: (Re-)enable interrupts only if they were previously enable
|
||||
|
||||
tricore
|
||||
* [#12682](https://github.com/apache/nuttx/pull/12682) arch/tricore: add support of tricore gcc toolchain
|
||||
* [#12706](https://github.com/apache/nuttx/pull/12706) arch/tricore: synchronize instruction/data following MTCR/MFC
|
||||
|
||||
risc-v
|
||||
* [#12961](https://github.com/apache/nuttx/pull/12961) arch: inline up_testset in arm arm64 riscv xtensa
|
||||
* [#12579](https://github.com/apache/nuttx/pull/12579) arch/riscv: add all region in NAPOT
|
||||
* [#12881](https://github.com/apache/nuttx/pull/12881) arch/riscv: add cluster local hartid
|
||||
* [#12906](https://github.com/apache/nuttx/pull/12906) arch/riscv: fix IRQ_SOFT for non-SMP
|
||||
* [#12546](https://github.com/apache/nuttx/pull/12546) arch/riscv: fix NuttSBI PMP config
|
||||
* [#12717](https://github.com/apache/nuttx/pull/12717) arch/riscv: fix trap sp restore logic
|
||||
* [#13430](https://github.com/apache/nuttx/pull/13430) arch/riscv: Fixed hardware timer warps-around issue
|
||||
* [#13278](https://github.com/apache/nuttx/pull/13278) arch/riscv: revert pull#12864
|
||||
* [#12864](https://github.com/apache/nuttx/pull/12864) arch/riscv: unify in-kernel syscall
|
||||
* [#12619](https://github.com/apache/nuttx/pull/12619) arch/risc-v: add support for capture driver on ESP32C6 and ESP32H2.
|
||||
* [#12726](https://github.com/apache/nuttx/pull/12726) arch/risc-v: make common up_allocate_heap weak symbol
|
||||
* [#12732](https://github.com/apache/nuttx/pull/12732) arch/risc-v: does not clear IPI address in S mode
|
||||
* [#12460](https://github.com/apache/nuttx/pull/12460) arch/risc-v/common: provide architecture specific perfmon bindings.
|
||||
* [#13353](https://github.com/apache/nuttx/pull/13353) arch/risc-v/litex: Fix the litex arty_a7 build
|
||||
* [#13382](https://github.com/apache/nuttx/pull/13382) arch/risc-v/src/litex: Claim all pending PLIC interrupts.
|
||||
* [#13547](https://github.com/apache/nuttx/pull/13547) arch/risc-v/src/litex_ticked: Set initial tick count to known value.
|
||||
* [#12804](https://github.com/apache/nuttx/pull/12804) arch/risc-v: introduce AIA support
|
||||
* [#12843](https://github.com/apache/nuttx/pull/12843) arch/risc-v: add support for DC motor control on ESP32|C6|H2|
|
||||
* [#12586](https://github.com/apache/nuttx/pull/12586) riscv_exception.c: Add missing comma in exception reasons array
|
||||
* [#13408](https://github.com/apache/nuttx/pull/13408) riscv_mtimer: modify riscv_mtimer_current to reduce precision lost
|
||||
* [#12643](https://github.com/apache/nuttx/pull/12643) riscv_tcbinfo: Fix register ordering for PC
|
||||
* [#13564](https://github.com/apache/nuttx/pull/13564) riscv: add a return value to riscv_swint
|
||||
* [#13561](https://github.com/apache/nuttx/pull/13561) riscv: g_current_regs is only used to determine if we are in irq
|
||||
* [#12812](https://github.com/apache/nuttx/pull/12812) riscv: Fix fork() system call
|
||||
* [#13354](https://github.com/apache/nuttx/pull/13354) riscv: Unify the extended context save/restore
|
||||
* [#12554](https://github.com/apache/nuttx/pull/12554) riscv: Initial support for debug trigger module
|
||||
* [#12559](https://github.com/apache/nuttx/pull/12559) riscv: Improve exception and irq mapping
|
||||
* [#12809](https://github.com/apache/nuttx/pull/12809) riscv/debug: Add support for steppoint
|
||||
* [#12819](https://github.com/apache/nuttx/pull/12819) riscv/espressif: Mark private data as static in esp_spi.c
|
||||
* [#12861](https://github.com/apache/nuttx/pull/12861) riscv/fork: fix fp/gp handling
|
||||
* [#12589](https://github.com/apache/nuttx/pull/12589) riscv/k230: revise canmv230:nsbi
|
||||
* [#12677](https://github.com/apache/nuttx/pull/12677) riscv/k230: updates for nsh and pnsh
|
||||
* [#12744](https://github.com/apache/nuttx/pull/12744) riscv/nsbi: fix k230 AMP confs
|
||||
* [#12799](https://github.com/apache/nuttx/pull/12799) riscv/qemu-rv: skip reloading mhartid
|
||||
* [#12807](https://github.com/apache/nuttx/pull/12807) riscv/qemu-rv: Add BUILD_PROTECTED target for rv-virt
|
||||
* [#12944](https://github.com/apache/nuttx/pull/12944) riscv/qemu-rv: add RPTUN support
|
||||
* [#12772](https://github.com/apache/nuttx/pull/12772) riscv/rv-virt: use RAM_START in ld.script
|
||||
* [#12816](https://github.com/apache/nuttx/pull/12816) riscv/qemu-rv: add NuttSBI target for rv-virt
|
||||
* [#12831](https://github.com/apache/nuttx/pull/12831) riscv/qemu-rv: revise PROTECTED mode
|
||||
* [#12840](https://github.com/apache/nuttx/pull/12840) riscv/nsbi: fix up_udelay for rv32
|
||||
* [#13510](https://github.com/apache/nuttx/pull/13510) risc-v: Add a new option to control exception reason
|
||||
* [#12722](https://github.com/apache/nuttx/pull/12722) risc-v/bl808, sg2000: Configure MMU to cache Kernel Text, Data and Heap (T-Head C906)
|
||||
* [#12571](https://github.com/apache/nuttx/pull/12571) risc-v/bl808: Add GPIO Driver
|
||||
* [#12621](https://github.com/apache/nuttx/pull/12621) risc-v/bl808: Add GPADC character driver
|
||||
* [#12663](https://github.com/apache/nuttx/pull/12663) risc-v/bl808: Add SPI driver
|
||||
* [#12771](https://github.com/apache/nuttx/pull/12771) risc-v/bl808: Add watchdog driver
|
||||
* [#12752](https://github.com/apache/nuttx/pull/12752) risc-v/bl808: Add timer driver
|
||||
* [#12614](https://github.com/apache/nuttx/pull/12614) risc-v/ox64: Add LED Driver
|
||||
* [#12762](https://github.com/apache/nuttx/pull/12762) risc-v/qemu-rv: Add LED Driver for QEMU RISC-V 32-bit and 64-bit
|
||||
xtensa
|
||||
* [#13223](https://github.com/apache/nuttx/pull/13223) Add spi slave dev to esp32 xtensa
|
||||
* [#13225](https://github.com/apache/nuttx/pull/13225) espressif: Fix build with RTC
|
||||
* [#13255](https://github.com/apache/nuttx/pull/13255) espressif: Fix deadlock in RT timer caused by critical section
|
||||
* [#12560](https://github.com/apache/nuttx/pull/12560) espressif: Fix error while evaluating Wi-Fi task ID
|
||||
* [#13368](https://github.com/apache/nuttx/pull/13368) espressif: Update external libraries to fix GPIO interrupt bug
|
||||
* [#13236](https://github.com/apache/nuttx/pull/13236) espressif: Update HAL library reference to include debug assert
|
||||
* [#13022](https://github.com/apache/nuttx/pull/13022) espressif: Update internal libraries reference
|
||||
* [#12551](https://github.com/apache/nuttx/pull/12551) xtensa: add support for capture driver on ESP32 and ESP32|S3|
|
||||
* [#12781](https://github.com/apache/nuttx/pull/12781) xtensa: add support for motor control driver
|
||||
* [#12967](https://github.com/apache/nuttx/pull/12967) xtensa_cache:add up_get_cachesize api
|
||||
* [#12865](https://github.com/apache/nuttx/pull/12865) xtensa/esp32: replace nxsig_usleep() with up_udelay()
|
||||
* [#12750](https://github.com/apache/nuttx/pull/12750) xtensa/esp32s3: Add peripheral DMA request return value and optimize DMA initialization
|
||||
* [#13277](https://github.com/apache/nuttx/pull/13277) xtensa/esp32s3: Add timing delay set interface for QSPI
|
||||
* [#13291](https://github.com/apache/nuttx/pull/13291) xtensa/esp32s2: add WiFi support
|
||||
* [#13454](https://github.com/apache/nuttx/pull/13454) xtensa/esp32s3: Adjust I2C clock timing
|
||||
* [#12720](https://github.com/apache/nuttx/pull/12720) xtensa/esp32s3: Deinitialize ESP32-S3 QSPI GDMA engine.
|
||||
* [#12871](https://github.com/apache/nuttx/pull/12871) xtensa/esp32s3: Update the rtc code to fix system blocking issue
|
||||
* [#12919](https://github.com/apache/nuttx/pull/12919) xtensa/esp32s3: partition name duplicate and free
|
||||
* [#12918](https://github.com/apache/nuttx/pull/12918) xtensa/esp32s3: reserve memory for a mutex struct depending on the OS
|
||||
* [#12932](https://github.com/apache/nuttx/pull/12932) xtensa/esp32s3: Separate address and command flag for QSPI DMA transfer
|
||||
* [#13165](https://github.com/apache/nuttx/pull/13165) xtensa/esp32s3/esp32s3_sdmmc.c: wait for command done event also on error response
|
||||
x86_64
|
||||
* [#13391](https://github.com/apache/nuttx/pull/13391) Add MSI/MSI-X support for intel64
|
||||
* [#12583](https://github.com/apache/nuttx/pull/12583) arch/intel64: add cpu specific data and per-cpu interrupt stacks
|
||||
* [#12803](https://github.com/apache/nuttx/pull/12803) arch/intel64: add support for HPET as system clock
|
||||
* [#12588](https://github.com/apache/nuttx/pull/12588) arch/intel64: add support for inter-processor signaling
|
||||
* [#12570](https://github.com/apache/nuttx/pull/12570) arch/intel64: get TSC frequency only when not provided from Kconfig
|
||||
* [#12801](https://github.com/apache/nuttx/pull/12801) arch/intel64/irq.h: rename rdtsc macros
|
||||
* [#13392](https://github.com/apache/nuttx/pull/13392) intel64: Improvements for HPET
|
||||
* [#12567](https://github.com/apache/nuttx/pull/12567) arch/x86_64: addrenv should add offset only for RAM region
|
||||
* [#12577](https://github.com/apache/nuttx/pull/12577) arch/x86_64/intel64/intel64_rtc.c: fix compilation
|
||||
* [#12591](https://github.com/apache/nuttx/pull/12591) arch/x86_64: add SMP support
|
||||
* [#13417](https://github.com/apache/nuttx/pull/13417) arch/x86_64: Add ARCH_INTEL64_DISABLE_CET
|
||||
* [#13409](https://github.com/apache/nuttx/pull/13409) arch/x86_64: Add ARCH_X86_64_IDLE_NOP and ARCH_X86_64_IDLE_MWAIT
|
||||
* [#13436](https://github.com/apache/nuttx/pull/13436) arch/x86_64: add basic support for R_X86_64_REX_GOTPCRELX relocation
|
||||
* [#13422](https://github.com/apache/nuttx/pull/13422) arch/x86_64: Add elf32 multiboot1 wrapper for NuttX binary
|
||||
* [#13313](https://github.com/apache/nuttx/pull/13313) arch/x86_64: convert all asm() to __asm__
|
||||
* [#13317](https://github.com/apache/nuttx/pull/13317) arch/x86_64: Fix wrong RDTSCP implementation
|
||||
* [#13316](https://github.com/apache/nuttx/pull/13316) arch/x86_64: Support QEMU PVH ELF loader
|
||||
* [#13426](https://github.com/apache/nuttx/pull/13426) arch/x86_64/intel64: fix compilation errors in intel64_oneshot_lower.c
|
||||
* [#12800](https://github.com/apache/nuttx/pull/12800) arch/x86_64/intel64/intel64_cpu.c: remove workaround for spin_lock
|
||||
* [#13390](https://github.com/apache/nuttx/pull/13390) qemu-intel64: restore functionality of PCI test configs
|
||||
* [#13315](https://github.com/apache/nuttx/pull/13315) qemu-intel64: simplify linker script
|
||||
* [#12597](https://github.com/apache/nuttx/pull/12597) x86_64: add AVX support
|
||||
* [#12613](https://github.com/apache/nuttx/pull/12613) x86_64: addrenv support
|
||||
* [#12569](https://github.com/apache/nuttx/pull/12569) x86_64: hide --whole-archive behind Kconfig option
|
||||
Driver Support
|
||||
New Driver Support
|
||||
* [#12829](https://github.com/apache/nuttx/pull/12829) Add amg88xx driver
|
||||
* [#13396](https://github.com/apache/nuttx/pull/13396) Add Intel e1000 and igc support
|
||||
* [#13393](https://github.com/apache/nuttx/pull/13393) Add support for 16550 compatible PCI serial cards
|
||||
* [#12715](https://github.com/apache/nuttx/pull/12715) Add support for the Sensirion SHT4x temperature and humidity sensor
|
||||
* [#12824](https://github.com/apache/nuttx/pull/12824) Add thermal framework
|
||||
* [#11605](https://github.com/apache/nuttx/pull/11605) Coresight: add init coresight driver framework
|
||||
* [#13082](https://github.com/apache/nuttx/pull/13082) driver/mem: add Mem Driver.
|
||||
* [#12834](https://github.com/apache/nuttx/pull/12834) driver/ssd1680: Add support for 1.54 inch e-paper display
|
||||
* [#12938](https://github.com/apache/nuttx/pull/12938) drivers/video: add goldfish gpu fb
|
||||
* [#13470](https://github.com/apache/nuttx/pull/13470) drivers/pinctl: add pinctrl framework
|
||||
* [#13471](https://github.com/apache/nuttx/pull/13471) drivers/goldfish-pipe: implement goldfish pipe
|
||||
* [#13553](https://github.com/apache/nuttx/pull/13553) Pci ep framework
|
||||
Drivers Improvements
|
||||
* [#12998](https://github.com/apache/nuttx/pull/12998) [driver][bcm43xxx] reset tx_seq of sido-bus when ifdown wlan-if
|
||||
* [#13154](https://github.com/apache/nuttx/pull/13154) can/sja1000: drop driver dependency on __builtin functions
|
||||
* [#13524](https://github.com/apache/nuttx/pull/13524) can: Add g_ prefix to can_dlc_to_len and len_to_can_dlc.
|
||||
* [#13141](https://github.com/apache/nuttx/pull/13141) can: Merge netpacket/can.h into nuttx/can.h
|
||||
* [#12676](https://github.com/apache/nuttx/pull/12676) driver/net/lan9250: Add lan9250_ioctl and lan9250_uninitialize APIs
|
||||
* [#13464](https://github.com/apache/nuttx/pull/13464) driver/ftl: Read the consecutive eraseblocks
|
||||
* [#13320](https://github.com/apache/nuttx/pull/13320) driver/usbdev: support userspace to access ep0
|
||||
* [#12641](https://github.com/apache/nuttx/pull/12641) drivers: add API for drivers early initialization
|
||||
* [#13492](https://github.com/apache/nuttx/pull/13492) drivers: fix gcc14 errors for virtio
|
||||
* [#13107](https://github.com/apache/nuttx/pull/13107) drivers/audio: fix samp rate conversion issue
|
||||
* [#13323](https://github.com/apache/nuttx/pull/13323) drivers/bch: fix uint32 overflow issue
|
||||
* [#12564](https://github.com/apache/nuttx/pull/12564) drivers/net/ksz9477: Add port mirroring support
|
||||
* [#12765](https://github.com/apache/nuttx/pull/12765) drivers/drivers_initialize.c: check if only one console is selected
|
||||
* [#13411](https://github.com/apache/nuttx/pull/13411) drivers/fb: add panbuffer clear ioctl
|
||||
* [#13468](https://github.com/apache/nuttx/pull/13468) drivers/gpio: support poll gpio device and optimize code to save memory
|
||||
* [#12976](https://github.com/apache/nuttx/pull/12976) drivers/input: enable touch/kbd/mouse for virtio input
|
||||
* [#13060](https://github.com/apache/nuttx/pull/13060) drivers/modem/alt1250: Disable the PIN feature in ALT1250
|
||||
* [#13327](https://github.com/apache/nuttx/pull/13327) drivers/mtd/bch: fix size_t overflow when offset > 4GB
|
||||
* [#13480](https://github.com/apache/nuttx/pull/13480) drivers/pty: support pty write to kill signal, like serial driver
|
||||
* [#12830](https://github.com/apache/nuttx/pull/12830) drivers/serial: Make the 16550 rx trigger level configurable
|
||||
* [#13202](https://github.com/apache/nuttx/pull/13202) drivers/regmap: add exit function interface.
|
||||
* [#13469](https://github.com/apache/nuttx/pull/13469) drivers/reset: support rpmsg reset
|
||||
* [#13328](https://github.com/apache/nuttx/pull/13328) drivers/rwbuffer: Bug fix: Set nblocks 0 after direct using wrflush
|
||||
* [#13434](https://github.com/apache/nuttx/pull/13434) drivers/serial
|
||||
* [#13576](https://github.com/apache/nuttx/pull/13576) drivers/syslog: compile syslog_device.c if console/char/file channel enabled
|
||||
* [#12857](https://github.com/apache/nuttx/pull/12857) drivers/touchscreen: add grab for touchscreen
|
||||
* [#13481](https://github.com/apache/nuttx/pull/13481) drivers/usbdev: minor update for cdcacm
|
||||
* [#12930](https://github.com/apache/nuttx/pull/12930) drivers/virtio-net: Support VIRTIO_F_ANY_LAYOUT
|
||||
* [#13170](https://github.com/apache/nuttx/pull/13170) drivers: Fix goldfish events x64 unresponsive interrupt issue
|
||||
* [#13531](https://github.com/apache/nuttx/pull/13531) Fix build error of drivers/sensors/usensor.c
|
||||
* [#13325](https://github.com/apache/nuttx/pull/13325) Input/ff: new driver frameworks for vibrator(haptic)
|
||||
* [#13078](https://github.com/apache/nuttx/pull/13078) video: fix warning & update sim camera
|
||||
* [#12760](https://github.com/apache/nuttx/pull/12760) virtio/serial: initial CONSOLE support
|
||||
* [#12971](https://github.com/apache/nuttx/pull/12971) mmcsd_sdio:Fix performing read and write in irq
|
||||
* [#12949](https://github.com/apache/nuttx/pull/12949) mmcsd: add support of getting ext_csd reg data
|
||||
* [#13157](https://github.com/apache/nuttx/pull/13157) mmcsd: add write ext csd reg support
|
||||
* [#13528](https://github.com/apache/nuttx/pull/13528) mmcsd: fix a logic error
|
||||
* [#13215](https://github.com/apache/nuttx/pull/13215) mmcsd: make a compatibility change for cmd12 and cmd23
|
||||
* [#13380](https://github.com/apache/nuttx/pull/13380) mtd:ramtron MB85RS256B address length is 2
|
||||
* [#13136](https://github.com/apache/nuttx/pull/13136) mtd:use part->name as partition name when CONFIG_MTD_PARTITION_NAMES set
|
||||
* [#12796](https://github.com/apache/nuttx/pull/12796) mtd/Kconfig: fix W25_SLOWREAD menu item.
|
||||
* [#13252](https://github.com/apache/nuttx/pull/13252) mtd/nvs: fix align size
|
||||
* [#13219](https://github.com/apache/nuttx/pull/13219) nuttx/drivers:Modify errcode returned by relay_ioctl
|
||||
* [#12848](https://github.com/apache/nuttx/pull/12848) Optimize iic and spi parts and add iic slave drivers
|
||||
* [#13344](https://github.com/apache/nuttx/pull/13344) pci ivshmem related driveres support
|
||||
* [#13337](https://github.com/apache/nuttx/pull/13337) Revert "Fix unwanted flush in the SPI slave driver"
|
||||
* [#13251](https://github.com/apache/nuttx/pull/13251) rndis: correct usb descriptor
|
||||
* [#13538](https://github.com/apache/nuttx/pull/13538) sensor:Fixed the problem of user information lag in cross-core communication "stublist".
|
||||
* [#13539](https://github.com/apache/nuttx/pull/13539) sensor_rpmsg.c:Fix that "stub" will be created when local core only has subscribers.
|
||||
* [#12927](https://github.com/apache/nuttx/pull/12927) serial/uart_16550: include stdint.h in uart_16550.h
|
||||
* [#13383](https://github.com/apache/nuttx/pull/13383) serial/uart_16550: remove up_putc spinlock
|
||||
* [#13384](https://github.com/apache/nuttx/pull/13384) serial/uart_pl011: default syslog needs to check flow control in up_putc
|
||||
* [#13509](https://github.com/apache/nuttx/pull/13509) serial/pci_16550: make sure that interrupts are disabled during init
|
||||
* [#13102](https://github.com/apache/nuttx/pull/13102) syslog_rpmsg: Ensure the syslog ept is ready when rpmsg_send
|
||||
* [#13184](https://github.com/apache/nuttx/pull/13184) timer driver:support poll.
|
||||
* [#13075](https://github.com/apache/nuttx/pull/13075) usb_cdcmbim: add mbim device driver
|
||||
* [#13367](https://github.com/apache/nuttx/pull/13367) usbdev: Add fastboot boardctl
|
||||
* [#12914](https://github.com/apache/nuttx/pull/12914) usbdev: add USB cdcncm device driver
|
||||
* [#12745](https://github.com/apache/nuttx/pull/12745) usbdev: delete unsigned comparison with 0
|
||||
* [#13216](https://github.com/apache/nuttx/pull/13216) usbdev: extend the usb req len to unit32_t
|
||||
* [#13190](https://github.com/apache/nuttx/pull/13190) USB 3.0 device side suppor
|
||||
|
||||
Board Support
|
||||
New Boards
|
||||
* [#13248](https://github.com/apache/nuttx/pull/13248) arm: Add support for CSK6011A SOC and CSK6011A-NANO board
|
||||
* [#11709](https://github.com/apache/nuttx/pull/11709) at32uc3a0: Initial work for SimpleMachines' Mizar32-A
|
||||
* [#12813](https://github.com/apache/nuttx/pull/12813) boards/esp32s3: Add initial support to the ESP32-S3-Korvo-2 board
|
||||
* [#13467](https://github.com/apache/nuttx/pull/13467) boards/esp32s3: add support to esp32s3-lhcbit board
|
||||
Boards Improvements
|
||||
* [#13532](https://github.com/apache/nuttx/pull/13532) [Bugfix]Kconfig:ensure compatibility between kconfig-frontend and kconfiglib in kernel build
|
||||
* [#12698](https://github.com/apache/nuttx/pull/12698) Add defconfig to use the ws2812 driver
|
||||
* [#12878](https://github.com/apache/nuttx/pull/12878) arm/stm32f103-minimum: Use common board MFRC522
|
||||
* [#12922](https://github.com/apache/nuttx/pull/12922) arm64: Initial implementation of CONFIG_BUILD_KERNEL
|
||||
* [#13376](https://github.com/apache/nuttx/pull/13376) arm64/Kconfig: Make the ARM64_PA/VA_BITS a true Kconfig variable
|
||||
* [#12973](https://github.com/apache/nuttx/pull/12973) board/arm/rp2040/seeed-xiao-studio-rp2040 GPIO configuration
|
||||
* [#12738](https://github.com/apache/nuttx/pull/12738) board/linum-stm32h753bi: Add support to external sdram
|
||||
* [#12882](https://github.com/apache/nuttx/pull/12882) board/lm3s6965-ek: restore 128K kflash
|
||||
* [#12699](https://github.com/apache/nuttx/pull/12699) board/stm32f401rc-rs485: Add support to Device Configuration over Telnet
|
||||
* [#12737](https://github.com/apache/nuttx/pull/12737) board/stm32f401rc-rs485: Add support to MAX7219 8x8 LED Matrix
|
||||
* [#13516](https://github.com/apache/nuttx/pull/13516) boards: Update EXAMPLES_SOTEST_DEVMINOR to EXAMPLES_SOTEST_DEVMINOR_MAX
|
||||
* [#12743](https://github.com/apache/nuttx/pull/12743) boards/arm/rp2040: Userled configuration to Seeed-Stdio RP2040
|
||||
* [#13142](https://github.com/apache/nuttx/pull/13142) boards/arm/stm32/stm32f4discovery: Add support to RFID MFRC522
|
||||
* [#13440](https://github.com/apache/nuttx/pull/13440) boards/arm/stm32h7/stm32h745i-disco: Add RPTUN support
|
||||
* [#12825](https://github.com/apache/nuttx/pull/12825) boards/armv5: Make ARMv5 boards work again
|
||||
* [#12593](https://github.com/apache/nuttx/pull/12593) boards/stm32: DRV8825 driver
|
||||
* [#12673](https://github.com/apache/nuttx/pull/12673) boards/esp32[c3|c6|h2|s2|s3]: Ignore etctmp in common board
|
||||
* [#13124](https://github.com/apache/nuttx/pull/13124) boards/esp32s3_lan9250: deinitialize the ethernet device lan9250
|
||||
* [#12716](https://github.com/apache/nuttx/pull/12716) boards/esp32s3: Increse the default stack size for usbnsh
|
||||
* [#12763](https://github.com/apache/nuttx/pull/12763) boards/imx93-evk: add sdimage cleanup
|
||||
* [#12876](https://github.com/apache/nuttx/pull/12876) boards/lm3s6965-ek: fix memory.ld for PROTECTED
|
||||
* [#12598](https://github.com/apache/nuttx/pull/12598) boards/MIMXRT1020-EVK: Fix board I2C code to adapt to last IMXRT I2C/pi…
|
||||
* [#13137](https://github.com/apache/nuttx/pull/13137) boards/risc-v/esp32c6/esp32c6-devkitm: Add support to RFID MFRC522
|
||||
* [#12869](https://github.com/apache/nuttx/pull/12869) boards/rv-virt: unify RV32 config names
|
||||
* [#13226](https://github.com/apache/nuttx/pull/13226) boards/sim: Defconfigs for nand and mnemofs
|
||||
* [#12898](https://github.com/apache/nuttx/pull/12898) boards/xtensa/esp32s3: ESP32S3 Emmc Support
|
||||
* [#13478](https://github.com/apache/nuttx/pull/13478) boardctl: add board control api to start slave core
|
||||
* [#13273](https://github.com/apache/nuttx/pull/13273) boardcrtl: change BOARDCTL_TESTSET to BOARDIOC_SPINLOCK
|
||||
* [#12747](https://github.com/apache/nuttx/pull/12747) Change nucleof429zi nsh defconfig
|
||||
* [#13059](https://github.com/apache/nuttx/pull/13059) defconfig: add SYSTEM_TELNETD related config
|
||||
* [#13334](https://github.com/apache/nuttx/pull/13334) esp32: fix a way to test a config
|
||||
* [#13563](https://github.com/apache/nuttx/pull/13563) esp32s3: Fix faulty `esp32s3-devkit:stack` example
|
||||
* [#13234](https://github.com/apache/nuttx/pull/13234) imx9_usdhc.c: Fix build error when CONFIG_ARM64_DCACHE_DISABLE=y
|
||||
* [#12867](https://github.com/apache/nuttx/pull/12867) LTDC for Linum board
|
||||
* [#12780](https://github.com/apache/nuttx/pull/12780) nrf9160-dk: disable FPU for modem example
|
||||
* [#13476](https://github.com/apache/nuttx/pull/13476) nucleo-h745zi: fix potential bl jump to app failed issue
|
||||
* [#13069](https://github.com/apache/nuttx/pull/13069) nucleo-l432kc: Revert the USART2 config to be use by virtual COM port
|
||||
* [#12987](https://github.com/apache/nuttx/pull/12987) nuttx/boards:Uniform initialization format for init_array.
|
||||
* [#13208](https://github.com/apache/nuttx/pull/13208) risc-v/bl808: Configure MMU to cache User Text, Data and Heap
|
||||
* [#13199](https://github.com/apache/nuttx/pull/13199) risc-v/mmu: Configure T-Head MMU to cache User Text, Data and Heap
|
||||
* [#12862](https://github.com/apache/nuttx/pull/12862) risc-v/qemu-rv: Add Build Config for leds64_rust
|
||||
* [#13186](https://github.com/apache/nuttx/pull/13186) risc-v/qemu-rv: Add Build Config for leds64_zig
|
||||
* [#12896](https://github.com/apache/nuttx/pull/12896) risc-v/qemu-rv: add cluster PLIC/CLINT configs
|
||||
* [#12544](https://github.com/apache/nuttx/pull/12544) riscv/nuttsbi: add MTVAL argument
|
||||
* [#12645](https://github.com/apache/nuttx/pull/12645) stm32h7/linum-stm32h753bi: add support to qencoder
|
||||
* [#12739](https://github.com/apache/nuttx/pull/12739) stm32f777zit6-meadow: Add support for two USB CDC/ACM
|
||||
* [#12637](https://github.com/apache/nuttx/pull/12637) Usbnsh to seed-xiao-rp2040 board
|
||||
* [#12713](https://github.com/apache/nuttx/pull/12713) zynq_mpsoc/zcu111: add support for gpio and board auto led
|
||||
* [#12806](https://github.com/apache/nuttx/pull/12806) zynq-mpsoc/zcu111: independent JTAG configs from normal nsh configs
|
||||
* [#12797](https://github.com/apache/nuttx/pull/12797) w25c: add W25_DEBUG sub-menu config option and update debug traces.
|
||||
File System
|
||||
New FS
|
||||
* [#13001](https://github.com/apache/nuttx/pull/13001) V9FS For NuttX
|
||||
FS Improvements
|
||||
* [#13514](https://github.com/apache/nuttx/pull/13514) add sched note for littlefs/romfs/rpmsgfs
|
||||
* [#12863](https://github.com/apache/nuttx/pull/12863) Fix the location of tmpfs pwrite write and Fixed some code check warnings
|
||||
* [#13500](https://github.com/apache/nuttx/pull/13500) fs.h: fix a comment in file_operations
|
||||
* [#12532](https://github.com/apache/nuttx/pull/12532) fs: add backtrace to where file opens
|
||||
* [#13150](https://github.com/apache/nuttx/pull/13150) fs: add fs_heap, support shm/tmpfs/pseudofile with indepent heap
|
||||
* [#12587](https://github.com/apache/nuttx/pull/12587) Fs: backtrace tweak
|
||||
* [#13512](https://github.com/apache/nuttx/pull/13512) fs: Dump the list of files when the file description runs out
|
||||
* [#13194](https://github.com/apache/nuttx/pull/13194) fs: nfs: Fix nfsmount error
|
||||
* [#12978](https://github.com/apache/nuttx/pull/12978) fs: Rename node with inode.
|
||||
* [#12969](https://github.com/apache/nuttx/pull/12969) Fslock optimize
|
||||
* [#12937](https://github.com/apache/nuttx/pull/12937) fs/mnemofs: Fix journal log rw issue, rw size issue
|
||||
* [#12945](https://github.com/apache/nuttx/pull/12945) fs/hostfs: Replace strcpy with memcpy
|
||||
* [#13443](https://github.com/apache/nuttx/pull/13443) fs_inode:Change the type of i_crefs to atomic_int
|
||||
* [#13458](https://github.com/apache/nuttx/pull/13458) fs_dup2 bug fix, memleak
|
||||
* [#13573](https://github.com/apache/nuttx/pull/13573) fs/chmod/fchmod/lchmod: only set permissions by mode_t and ignore othjer bits
|
||||
* [#12931](https://github.com/apache/nuttx/pull/12931) fs/epoll: Optimize implementation details
|
||||
* [#12615](https://github.com/apache/nuttx/pull/12615) fs/fat: Fix Fseek Bug When File Size Is Multiple of Cluster Size
|
||||
* [#12548](https://github.com/apache/nuttx/pull/12548) fs/fat/fs_fat32.c Return EOF when reading past the end of the file.
|
||||
* [#13521](https://github.com/apache/nuttx/pull/13521) fs/dump: correct SCHED_DUMP_ON_EXIT to DUMP_ON_EXIT
|
||||
* [#12990](https://github.com/apache/nuttx/pull/12990) fs/mmap: Fix build warning with [-Wmaybe-uninitialized].
|
||||
* [#13132](https://github.com/apache/nuttx/pull/13132) fs/procfs: Supports any number of thread displays
|
||||
* [#13123](https://github.com/apache/nuttx/pull/13123) fs/shmfs:Avoid an integer overflow
|
||||
* [#12790](https://github.com/apache/nuttx/pull/12790) fs/spiffs: Return OK on `spiffs_fstat` success
|
||||
* [#13407](https://github.com/apache/nuttx/pull/13407) fs/mmap: Add MADV_HUGEPAGE definitions
|
||||
* [#13406](https://github.com/apache/nuttx/pull/13406) fs/mmap: Ensure anonymous pages are initialized to zero
|
||||
* [#12661](https://github.com/apache/nuttx/pull/12661) fs/mnemofs: Adds Block Allocator
|
||||
* [#12668](https://github.com/apache/nuttx/pull/12668) fs/mnemofs: Add parent iterator and path methods.
|
||||
* [#12680](https://github.com/apache/nuttx/pull/12680) fs/mnemofs: Add LRU and CTZ methods
|
||||
* [#12683](https://github.com/apache/nuttx/pull/12683) fs/mnemofs: Add journal methods.
|
||||
* [#12702](https://github.com/apache/nuttx/pull/12702) fs/mnemofs: Add master node and r/w methods
|
||||
* [#12943](https://github.com/apache/nuttx/pull/12943) fs/mnemofs: Autoformat
|
||||
* [#12808](https://github.com/apache/nuttx/pull/12808) fs/mnemofs: Refactoring path logic, direntry size bug fix, open free bug fix
|
||||
* [#12658](https://github.com/apache/nuttx/pull/12658) fs/mnemofs: Setup and VFS methods
|
||||
* [#13475](https://github.com/apache/nuttx/pull/13475) fs/mount: add ftl proxy to mount block filesystem on mtd device
|
||||
* [#13258](https://github.com/apache/nuttx/pull/13258) fs/mq_open: revise comments
|
||||
* [#13326](https://github.com/apache/nuttx/pull/13326) fs/files_extend: Bug Fix
|
||||
* [#13331](https://github.com/apache/nuttx/pull/13331) fs/inode: using inode reference to indicate unlink and simply code
|
||||
* [#13077](https://github.com/apache/nuttx/pull/13077) Fsnotify
|
||||
* [#12942](https://github.com/apache/nuttx/pull/12942) Hostfs support get filepath by ioctl
|
||||
* [#12817](https://github.com/apache/nuttx/pull/12817) procfs/meminfo: free delaylist before reporting
|
||||
* [#13058](https://github.com/apache/nuttx/pull/13058) procfs/mempool: fix did not remove when pool not enabled
|
||||
* [#13092](https://github.com/apache/nuttx/pull/13092) rpmsgfs: fix out of bounds access caused by data transmission farmat
|
||||
* [#13063](https://github.com/apache/nuttx/pull/13063) rpmsgfs: set fs type to rpmsgfs when mount through rpmsgfs
|
||||
* [#13348](https://github.com/apache/nuttx/pull/13348) smartfs procfs: fix double declare g_smartfs_operations
|
||||
* [#12939](https://github.com/apache/nuttx/pull/12939) rpmsgfs_client:Fix error return exception
|
||||
* [#12941](https://github.com/apache/nuttx/pull/12941) rpmsgfs: support filelock
|
||||
* [#13098](https://github.com/apache/nuttx/pull/13098) tmpfs: old data was loaded when SEEK_SET beyond end of the file
|
||||
* [#13490](https://github.com/apache/nuttx/pull/13490) vfs:fix a type mismatch issue and a typo
|
||||
Networking
|
||||
Improvements
|
||||
* [#13385](https://github.com/apache/nuttx/pull/13385) Fix the bug that netlink receive wait does not hang up
|
||||
* [#13053](https://github.com/apache/nuttx/pull/13053) icmp:add net_lock to protect icmp connection
|
||||
* [#13336](https://github.com/apache/nuttx/pull/13336) local_socket: add SO_SNDBUF & SO_RCVBUF support
|
||||
* [#13045](https://github.com/apache/nuttx/pull/13045) localsocket improvment
|
||||
* [#12639](https://github.com/apache/nuttx/pull/12639) net: Enable ICMP by default if IPv4 is enabled
|
||||
* [#13028](https://github.com/apache/nuttx/pull/13028) net_chksum.c:mod process of generating sum to solve checksum error
|
||||
* [#12991](https://github.com/apache/nuttx/pull/12991) net/icmpv6/icmpv6_input.c: fix undefined build error
|
||||
* [#13093](https://github.com/apache/nuttx/pull/13093) net/netdev: Add periodic log for netdev statistics
|
||||
* [#12689](https://github.com/apache/nuttx/pull/12689) net/netfilter: fix windows compile error
|
||||
* [#12688](https://github.com/apache/nuttx/pull/12688) net/pkt: correct PF_PACKET family sending errors
|
||||
* [#12995](https://github.com/apache/nuttx/pull/12995) net/pkt: fix issue that set nonblock by fcntl does not take effect
|
||||
* [#13010](https://github.com/apache/nuttx/pull/13010) net/pkt: fix raw socket send data length is insufficient
|
||||
* [#13120](https://github.com/apache/nuttx/pull/13120) net/tcp_timer: fix tcp_timer idle loop and retransmission bug
|
||||
* [#13051](https://github.com/apache/nuttx/pull/13051) net/tcp: reset the dupack counter.
|
||||
* [#12899](https://github.com/apache/nuttx/pull/12899) net/tun: Remove unused variables in read & write
|
||||
* [#13191](https://github.com/apache/nuttx/pull/13191) net/tun: Support changing carrier state of TUN/TAP
|
||||
* [#13350](https://github.com/apache/nuttx/pull/13350) net/udp: Fixed the issue of sending ICMP error when the destination address is broadcast/multicast.
|
||||
* [#13037](https://github.com/apache/nuttx/pull/13037) netdev_upperhalf: add polling mode support for tx/rx
|
||||
* [#13046](https://github.com/apache/nuttx/pull/13046) netdev/ioctl: Setting log level to warning on SIOCGIFHWADDR failure
|
||||
* [#13007](https://github.com/apache/nuttx/pull/13007) netdev/lower: Add reclaim callback and use it in virtio-net
|
||||
* [#13343](https://github.com/apache/nuttx/pull/13343) netdev/statistics: Add bytes for netdev statistics
|
||||
* [#13008](https://github.com/apache/nuttx/pull/13008) netdev/upper: Delay replied packets to prevent TX quota become negated
|
||||
* [#12992](https://github.com/apache/nuttx/pull/12992) netinet/in.h: add macro definitions to resolve compilation errors
|
||||
* [#12994](https://github.com/apache/nuttx/pull/12994) netlib/route: add length for add/del route-func to reduce caller stack usage
|
||||
* [#13335](https://github.com/apache/nuttx/pull/13335) netdb: Make NETDB_DNSSERVER_NAMESERVERS effective for NETDB_RESOLVCONF
|
||||
* [#13038](https://github.com/apache/nuttx/pull/13038) netdb: netdb code support ffmpeg rtsp(getaddrinfo & getnameinfo)
|
||||
* [#13049](https://github.com/apache/nuttx/pull/13049) Modify the IPV6 address acquisition method and the gateway settings.
|
||||
* [#13125](https://github.com/apache/nuttx/pull/13125) modify for offload checksum and add macro with tcp/icmp/icmpv6/igmp checksum
|
||||
* [#13026](https://github.com/apache/nuttx/pull/13026) modify the type of the ipv6 parameters to solve runtime error
|
||||
* [#13029](https://github.com/apache/nuttx/pull/13029) solve Problem of tcp parameter calculation exceeding the boundary
|
||||
* [#13156](https://github.com/apache/nuttx/pull/13156) sys/socket: implement compiler agnostic sockaddr_storage alignment
|
||||
* [#13158](https://github.com/apache/nuttx/pull/13158) tcp_close.c:when tcp socket stays in TCP_FIN_WAIT_1 or TCP_FIN_WAIT_2,calling tcp_close_eventhandler releases received packets
|
||||
* [#12999](https://github.com/apache/nuttx/pull/12999) tcp_input: if tcp->req > recvreq, send ack only when state is TCP_ESTABLISHED
|
||||
|
||||
Unsorted
|
||||
Improvements
|
||||
* [#13448](https://github.com/apache/nuttx/pull/13448) [Bug-Fix] Resource leaks
|
||||
* [#13100](https://github.com/apache/nuttx/pull/13100) [BugFix]Command "critmon" error
|
||||
* [#13002](https://github.com/apache/nuttx/pull/13002) 12K sample rate support
|
||||
* [#13486](https://github.com/apache/nuttx/pull/13486) Accelerate access to interrupt status
|
||||
* [#12980](https://github.com/apache/nuttx/pull/12980) add fb_vsync_pollnotify
|
||||
* [#12959](https://github.com/apache/nuttx/pull/12959) Add goldfish events
|
||||
* [#12951](https://github.com/apache/nuttx/pull/12951) Add irq disable func
|
||||
* [#13130](https://github.com/apache/nuttx/pull/13130) Add memory pressure monitoring
|
||||
* [#13089](https://github.com/apache/nuttx/pull/13089) api:add lib_realpath function
|
||||
* [#12947](https://github.com/apache/nuttx/pull/12947) assert: add compile_assert macro
|
||||
* [#13020](https://github.com/apache/nuttx/pull/13020) assert: check COMPILE_TIME_ASSERT before define
|
||||
* [#13087](https://github.com/apache/nuttx/pull/13087) Audio upstream
|
||||
* [#13044](https://github.com/apache/nuttx/pull/13044) Basic Atomic for NuttX
|
||||
* [#13099](https://github.com/apache/nuttx/pull/13099) bch: alloc bch->buffer when offset not aligned
|
||||
* [#13513](https://github.com/apache/nuttx/pull/13513) BCH: Add readonly configuration for BCH devices
|
||||
* [#12853](https://github.com/apache/nuttx/pull/12853) binfmt/elf_loadfile: Set sh_addr even if SHF_ALLOC == 0
|
||||
* [#12965](https://github.com/apache/nuttx/pull/12965) boot: fix potential bl jump to app failed issue
|
||||
* [#13094](https://github.com/apache/nuttx/pull/13094) Bugfix hcreate
|
||||
* [#13300](https://github.com/apache/nuttx/pull/13300) can: Before we use pstate, we should check if it is NULL.
|
||||
* [#13570](https://github.com/apache/nuttx/pull/13570) can: Add g_ prefix to can_dlc_to_len and len_to_can_dlc.
|
||||
* [#13048](https://github.com/apache/nuttx/pull/13048) can: CAN code optimization
|
||||
* [#12656](https://github.com/apache/nuttx/pull/12656) can: fixes and tweaks for CAN FD support
|
||||
* [#13126](https://github.com/apache/nuttx/pull/13126) Capture adds the function of edges counting
|
||||
* [#12934](https://github.com/apache/nuttx/pull/12934) clk: fix reg operation not compatible with 64bit
|
||||
* [#13210](https://github.com/apache/nuttx/pull/13210) cdcacm: align cdcacm_epconfigure function parameters
|
||||
* [#13189](https://github.com/apache/nuttx/pull/13189) Controlling rgb led bp
|
||||
* [#12889](https://github.com/apache/nuttx/pull/12889) Coredump enhancement, optimized prompt statements
|
||||
* [#13474](https://github.com/apache/nuttx/pull/13474) coredump: just save latest core file
|
||||
* [#12958](https://github.com/apache/nuttx/pull/12958) coredump: refine coredump info analyse
|
||||
* [#13066](https://github.com/apache/nuttx/pull/13066) crypto: import the ability to clone session
|
||||
* [#13109](https://github.com/apache/nuttx/pull/13109) crypto/bn: Provide software algorithms to calculate inverse elements and greatest common divisor
|
||||
* [#13431](https://github.com/apache/nuttx/pull/13431) crypto/rsa: add exp mod in software crypto
|
||||
* [#12970](https://github.com/apache/nuttx/pull/12970) Disable clean/flush optimization in case of SMP restriction
|
||||
* [#12777](https://github.com/apache/nuttx/pull/12777) dlfcn: Add stub for dladdr
|
||||
* [#12779](https://github.com/apache/nuttx/pull/12779) dlfcn: Fix indent issue in lib_dlclose.c
|
||||
* [#13159](https://github.com/apache/nuttx/pull/13159) dynamically create work queues
|
||||
* [#13489](https://github.com/apache/nuttx/pull/13489) enable O_CLOEXEC explicitly to avoid fd leak
|
||||
* [#13118](https://github.com/apache/nuttx/pull/13118) Enhance ASSERT
|
||||
* [#13424](https://github.com/apache/nuttx/pull/13424) Enhance Kasan
|
||||
* [#13559](https://github.com/apache/nuttx/pull/13559) Enhance Kasan's global variable out of bounds detection
|
||||
* [#13388](https://github.com/apache/nuttx/pull/13388) Expose IPTOS_xxx to the application layer
|
||||
* [#12963](https://github.com/apache/nuttx/pull/12963) fdcheck: fix race condition in fdcheck
|
||||
* [#13096](https://github.com/apache/nuttx/pull/13096) fb:add select overlay FB_NO_OVERLAY
|
||||
* [#13296](https://github.com/apache/nuttx/pull/13296) filep Reference count
|
||||
* [#12578](https://github.com/apache/nuttx/pull/12578) Fix allocated memory test
|
||||
* [#13461](https://github.com/apache/nuttx/pull/13461) Fix dev_mem related
|
||||
* [#13555](https://github.com/apache/nuttx/pull/13555) Fix greater-than-or-equal-to-zero issue
|
||||
* [#12741](https://github.com/apache/nuttx/pull/12741) Fix pin LTDC_B0, should be PJ12 instead of PF0
|
||||
* [#13129](https://github.com/apache/nuttx/pull/13129) Fix task_setup race condition
|
||||
* [#13054](https://github.com/apache/nuttx/pull/13054) Fix the compilation warnings
|
||||
* [#12955](https://github.com/apache/nuttx/pull/12955) fix the potential bug of putwc, fgetwc, ungetwc, wcsstr, fputwc
|
||||
* [#13095](https://github.com/apache/nuttx/pull/13095) fix:uart_rpmsg_dmareceive
|
||||
* [#13477](https://github.com/apache/nuttx/pull/13477) ftl: should pre-allocate eblock for car case
|
||||
* [#13000](https://github.com/apache/nuttx/pull/13000) getrlimit: implement RLIMIT_STACK return limit stack size
|
||||
* [#13459](https://github.com/apache/nuttx/pull/13459) GNSS: Add support for constellation, measurement, clock and geofence
|
||||
* [#13504](https://github.com/apache/nuttx/pull/13504) goldfish:add kernel mode support
|
||||
* [#13330](https://github.com/apache/nuttx/pull/13330) group/filelist: add reference to protect filelist of group
|
||||
* [#13554](https://github.com/apache/nuttx/pull/13554) i2c: Optimize access to private data
|
||||
* [#13233](https://github.com/apache/nuttx/pull/13233) Increase the chance for _assert to work early in the boot
|
||||
* [#13306](https://github.com/apache/nuttx/pull/13306) init: add OSINIT_TASK_READY
|
||||
* [#13228](https://github.com/apache/nuttx/pull/13228) inline restore_critical_section and add parameters to restore_critical_section
|
||||
* [#12981](https://github.com/apache/nuttx/pull/12981) input: fix goldfish input and lvgl input device name mismatch problem
|
||||
* [#13108](https://github.com/apache/nuttx/pull/13108) input: fix touchevent race condition
|
||||
* [#13073](https://github.com/apache/nuttx/pull/13073) inode: call inode_release when close success
|
||||
* [#13198](https://github.com/apache/nuttx/pull/13198) Introduce new PCI framework
|
||||
* [#13442](https://github.com/apache/nuttx/pull/13442) input/ff: modify FF_MAX to support 64-bit machine
|
||||
* [#13387](https://github.com/apache/nuttx/pull/13387) ipfrag: fix warnig
|
||||
* [#13163](https://github.com/apache/nuttx/pull/13163) ipfrag: remove assert for actual product reasons
|
||||
* [#13012](https://github.com/apache/nuttx/pull/13012) irq: add [enter|leave]_critical_section_nonirq
|
||||
* [#13018](https://github.com/apache/nuttx/pull/13018) irq: add isr thread
|
||||
* [#13242](https://github.com/apache/nuttx/pull/13242) irq: dynaminc create g_irqmap
|
||||
* [#13256](https://github.com/apache/nuttx/pull/13256) irq: irq with the same priority share the same wqueue
|
||||
* [#12595](https://github.com/apache/nuttx/pull/12595) irq: remove g_cpu_nestcount in restore_critical_section
|
||||
* [#12935](https://github.com/apache/nuttx/pull/12935) irq: remove restore_critical_section in irq
|
||||
* [#12596](https://github.com/apache/nuttx/pull/12596) irq: remove restore_critical_section in irq
|
||||
* [#13369](https://github.com/apache/nuttx/pull/13369) irq: simplify code by using OSINIT_TASK_READY
|
||||
* [#13119](https://github.com/apache/nuttx/pull/13119) Kasan enhance
|
||||
* [#12893](https://github.com/apache/nuttx/pull/12893) kasan:fix bug write error is recognized as read error
|
||||
* [#13133](https://github.com/apache/nuttx/pull/13133) Keep the log level consistent with assert
|
||||
* [#12590](https://github.com/apache/nuttx/pull/12590) libmetal/atomic: enable 64-bit atomic by toolchain builtin flags
|
||||
* [#13543](https://github.com/apache/nuttx/pull/13543) lilygo_tbeam_lora_gps/gps: Enable GNSSUTILS_MINMEA_LIB for EXAMPLES_GPS
|
||||
* [#13549](https://github.com/apache/nuttx/pull/13549) lzf:Add macro judgment to header file reference.
|
||||
* [#12929](https://github.com/apache/nuttx/pull/12929) make/disassembly: generate disassembly file
|
||||
* [#13179](https://github.com/apache/nuttx/pull/13179) memset:optimizate speed.
|
||||
* [#12985](https://github.com/apache/nuttx/pull/12985) minidumpserver: fix parsing bug
|
||||
* [#13287](https://github.com/apache/nuttx/pull/13287) mksymtab.c support for structure
|
||||
* [#13452](https://github.com/apache/nuttx/pull/13452) modify BUILD_LOADABLE to MODULES which backwards-compatible Kernel
|
||||
* [#12968](https://github.com/apache/nuttx/pull/12968) MPU update
|
||||
* [#13460](https://github.com/apache/nuttx/pull/13460) New Rpmsg Transports: Rpmsg Port SPI, Rpmsg Port Uart and Rpmsg Router Transport Support
|
||||
* [#13104](https://github.com/apache/nuttx/pull/13104) nxmutex api enhance
|
||||
* [#13047](https://github.com/apache/nuttx/pull/13047) nuttx-names.in:add popen & pclose assign to glibc interface
|
||||
* [#13006](https://github.com/apache/nuttx/pull/13006) nuttx/audio: add AUDIOIOC_GETPOSITION ioctl
|
||||
* [#13005](https://github.com/apache/nuttx/pull/13005) nuttx/audio: add offload buffer size config
|
||||
* [#13340](https://github.com/apache/nuttx/pull/13340) nuttx/crypto: export asymmetric algorithms about ecdh and ecc256 via /dev/crypto
|
||||
* [#13138](https://github.com/apache/nuttx/pull/13138) nuttx/crypto: fix wrong implementation in crypto module
|
||||
* [#13173](https://github.com/apache/nuttx/pull/13173) nuttx/crypto: support new algorithm about crc32 and aes-cmac
|
||||
* [#13084](https://github.com/apache/nuttx/pull/13084) nuttx/crypto: support poly1305 and ripemd160 algorithm
|
||||
* [#12986](https://github.com/apache/nuttx/pull/12986) nuttx/note: fix missing the last character when printing custom labels.
|
||||
* [#12730](https://github.com/apache/nuttx/pull/12730) NVS: fix align size
|
||||
* [#13187](https://github.com/apache/nuttx/pull/13187) nvs: modify nvs block size and block numbers
|
||||
* [#12601](https://github.com/apache/nuttx/pull/12601) queue: inline queue
|
||||
* [#13435](https://github.com/apache/nuttx/pull/13435) pci/pci_uio_ivshmem: pci uio ivshmem msix interrupt support
|
||||
* [#13178](https://github.com/apache/nuttx/pull/13178) pl031:change mktime to timegm.
|
||||
* [#13057](https://github.com/apache/nuttx/pull/13057) pm_runtime: fix missing header
|
||||
* [#13064](https://github.com/apache/nuttx/pull/13064) pm_activity: fix deadlock with spinlock and critcal_section
|
||||
* [#13055](https://github.com/apache/nuttx/pull/13055) pm: add pm_idle, up_idle only handle pm state execution
|
||||
* [#12933](https://github.com/apache/nuttx/pull/12933) pm: add debug_assert for cb register/unregister api
|
||||
* [#13072](https://github.com/apache/nuttx/pull/13072) pm: update document, add pm_idle interface for not-smp case
|
||||
* [#13279](https://github.com/apache/nuttx/pull/13279) poll: fix thread_cancel() caused poll used after free
|
||||
* [#13074](https://github.com/apache/nuttx/pull/13074) Private requirement for wapi
|
||||
* [#13168](https://github.com/apache/nuttx/pull/13168) protected build: userspace threads will unexpectly work in privileged mode after syscall
|
||||
* [#13153](https://github.com/apache/nuttx/pull/13153) pty: use mutex to protect alloc minor
|
||||
* [#13295](https://github.com/apache/nuttx/pull/13295) psram_cache_init: remove cosmetic differences between PRO/APP
|
||||
* [#13438](https://github.com/apache/nuttx/pull/13438) ramlog bug fix
|
||||
* [#13283](https://github.com/apache/nuttx/pull/13283) Refactor wdog module
|
||||
* [#12891](https://github.com/apache/nuttx/pull/12891) Reimplemented the mempool traversal function and fixed some existing bugs in the mempool
|
||||
* [#13463](https://github.com/apache/nuttx/pull/13463) rename, strtoul & sscanf
|
||||
* [#13309](https://github.com/apache/nuttx/pull/13309) Restore ASSERT/VERIFY semantics
|
||||
* [#13485](https://github.com/apache/nuttx/pull/13485) Revert "irq: add [enter|leave]_critical_section_nonirq"
|
||||
* [#12607](https://github.com/apache/nuttx/pull/12607) Revert "irq: remove restore_critical_section in irq"
|
||||
* [#13432](https://github.com/apache/nuttx/pull/13432) Rpmsg VirtIO Transport support and releated patches
|
||||
* [#13183](https://github.com/apache/nuttx/pull/13183) rpmsg_rtc:Update g_basetime from rpmsg.
|
||||
* [#13169](https://github.com/apache/nuttx/pull/13169) rpmsg.c: move onceinit judge logic to common part
|
||||
* [#13404](https://github.com/apache/nuttx/pull/13404) rpmsgblk: split multi_cmd only when it is too large to be placed into…
|
||||
* [#13465](https://github.com/apache/nuttx/pull/13465) rpmsgdev: Support server export and oneway polling
|
||||
* [#13172](https://github.com/apache/nuttx/pull/13172) rptun.c: fix rptun.c format follow rpmsg virtio
|
||||
* [#13203](https://github.com/apache/nuttx/pull/13203) rtc alarm:fix doesn't call nxsig_notification
|
||||
* [#13515](https://github.com/apache/nuttx/pull/13515) shm: remove useless macro
|
||||
* [#13280](https://github.com/apache/nuttx/pull/13280) smp: smp call handler add up_cpu_paused_[save|restore]
|
||||
* [#13405](https://github.com/apache/nuttx/pull/13405) spi_slave: change length to nwords
|
||||
* [#12599](https://github.com/apache/nuttx/pull/12599) spin_lock: inline spin_lock
|
||||
* [#12837](https://github.com/apache/nuttx/pull/12837) spinlock: add support of spin_trylock_irqsave()
|
||||
* [#12836](https://github.com/apache/nuttx/pull/12836) spinlock: inline no trace implement to remove duplicate logic
|
||||
* [#13272](https://github.com/apache/nuttx/pull/13272) spinlock: spin_initialize should add memory barrier
|
||||
* [#13457](https://github.com/apache/nuttx/pull/13457) stack recored bug fix
|
||||
* [#13386](https://github.com/apache/nuttx/pull/13386) stream/syslograw: remove support for iob buffer in syslog
|
||||
* [#13511](https://github.com/apache/nuttx/pull/13511) Support msync
|
||||
* [#13196](https://github.com/apache/nuttx/pull/13196) support rss/arfs with device
|
||||
* [#13106](https://github.com/apache/nuttx/pull/13106) suppress libasan checks
|
||||
* [#13031](https://github.com/apache/nuttx/pull/13031) Synchronize the modification of the WiFi problems in QEMU.
|
||||
* [#13113](https://github.com/apache/nuttx/pull/13113) Swift embedded support
|
||||
* [#12820](https://github.com/apache/nuttx/pull/12820) task_fork.c: Fix vfork for BUILD_KERNEL
|
||||
* [#12754](https://github.com/apache/nuttx/pull/12754) up_backtrace: fix maybe backtrace the exiting thread
|
||||
* [#13293](https://github.com/apache/nuttx/pull/13293) Update clock speed
|
||||
* [#13410](https://github.com/apache/nuttx/pull/13410) Update posix timer
|
||||
* [#12611](https://github.com/apache/nuttx/pull/12611) Upgrade Segger SystemView to V3.54
|
||||
* [#12705](https://github.com/apache/nuttx/pull/12705) V4l2m2m openh264 x264 to builtin
|
||||
* [#13030](https://github.com/apache/nuttx/pull/13030) video/fb: changed circbuf_write assert to warning
|
||||
* [#13433](https://github.com/apache/nuttx/pull/13433) VirtIO PCI Transport Support for NuttX
|
||||
* [#13338](https://github.com/apache/nuttx/pull/13338) virtio-blk: support called read/write in interrupt
|
||||
* [#13437](https://github.com/apache/nuttx/pull/13437) wqueue bug fix
|
||||
* [#13241](https://github.com/apache/nuttx/pull/13241) wqueue: add interface work_queue_priority_wq and work_queue_priority
|
|
@ -1,3 +1,35 @@
|
|||
==========================
|
||||
IO Expander Device Drivers
|
||||
==========================
|
||||
|
||||
- ``include/nuttx/ioexpander/ioexpander.h`` and ``include/nuttx/ioexpander/gpio.h``.
|
||||
All structures and APIs needed to work with ioexpander drivers are provided in
|
||||
this header file.
|
||||
|
||||
- ``struct ioexpander_ops_s``. Each ioexpand device driver must implement
|
||||
an instance of ``struct ioexpander_ops_s``. That structure defines a
|
||||
call table with the methods, and we also provide macros to help access methods.
|
||||
|
||||
- we also provide method ``gpio_lower_half`` to make ioexpander compatible with normal gpio.
|
||||
|
||||
- **Binding ioexpander Drivers**. ioexpander drivers are not normally directly
|
||||
accessed by user code, we should always get lower level drivers, for example I2C,
|
||||
and map extended gpio feature same asa normal gpio. See for example,
|
||||
``int nrf52_sx1509_initialize(void)``
|
||||
in ``boards/arm/nrf52/thingy52/src/nrf52_sx1509.c``. In general, the binding
|
||||
sequence is:
|
||||
|
||||
#. Get an instance of ``struct i2c_master_s`` from the
|
||||
hardware-specific I2C device driver, and
|
||||
#. Provide that instance and configurations to the ioexpander initialization method
|
||||
to get the ``struct ioexpander_dev_s`` ioe device instance.
|
||||
#. Then use ioe device instance to do ioexpander operations, or use ``gpio_lower_half``
|
||||
to make ioexpand compatible with normal gpio.
|
||||
|
||||
|
||||
- **Examples**: ``drivers/ioexpander/pca9555.c``,
|
||||
``drivers/input/aw86225.c``,
|
||||
``drivers/analog/lmp92001.c``,
|
||||
``drivers/ioexpander/ioe_rpmsg.c``,
|
||||
``boards/sim/sim/sim/src/sim_ioexpander.c``,
|
||||
``boards/arm/nrf52/thingy52/src/nrf52_sx1509.c`` etc.
|
||||
|
|
|
@ -17,7 +17,7 @@ Supported Segger drivers:
|
|||
Segger SystemView
|
||||
=================
|
||||
|
||||
Steps to enable SystemView support:
|
||||
1. Steps to enable SystemView support:
|
||||
|
||||
#. Make sure your architecture supports a high-performance counter.
|
||||
In most cases it will be:
|
||||
|
@ -62,3 +62,14 @@ Steps to enable SystemView support:
|
|||
|
||||
In case SystemView returns buffer overflow errors, you should increase
|
||||
``CONFIG_NOTE_RTT_BUFFER_SIZE_UP``.
|
||||
|
||||
2. Use SystemView for heap tracing:
|
||||
|
||||
Refer to example configuration at ``stm32f429i-disco/configs/systemview``.
|
||||
Make sure that ``CONFIG_SCHED_INSTRUMENTATION_HEAP`` is enabled.
|
||||
|
||||
Example of screenshot from SystemView:
|
||||
|
||||
.. image:: sysview.png
|
||||
:width: 800px
|
||||
:align: center
|
||||
|
|
BIN
Documentation/components/drivers/special/sysview.png
Normal file
BIN
Documentation/components/drivers/special/sysview.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 606 KiB |
|
@ -1,6 +1,6 @@
|
|||
=========================================
|
||||
High Performance, Zero Latency Interrupts
|
||||
=========================================
|
||||
=====================================================================
|
||||
High Performance: Zero Latency Interrupts, Maskable nested interrupts
|
||||
=====================================================================
|
||||
|
||||
Generic Interrupt Handling
|
||||
==========================
|
||||
|
@ -111,6 +111,62 @@ between the high priority interrupt handler and *PendSV* interrupt
|
|||
handler. A detailed discussion of that custom logic is beyond the
|
||||
scope of this Wiki page.
|
||||
|
||||
The following table shows the priority levels of the Cortex-M family:
|
||||
|
||||
.. code-block::
|
||||
|
||||
IRQ type Priority
|
||||
Dataabort 0x00
|
||||
High prio IRQ1 0x20 (Zero-latency interrupt)
|
||||
High prio IRQ2 0x30 (Can't call OS API in ISR)
|
||||
SVC 0x70
|
||||
Disable IRQ 0x80
|
||||
(critical-section)
|
||||
Low prio IRQ 0xB0
|
||||
PendSV 0xE0
|
||||
|
||||
As you can see, the priority levels of the zero-latency interrupts can
|
||||
beyond the critical section and SVC.
|
||||
But High prio IRQ can't call OS API.
|
||||
|
||||
|
||||
Maskable Nested Interrupts
|
||||
==========================
|
||||
|
||||
The ARM Cortex-M family supports a feature called *BASEPRI* that can be
|
||||
used to disable interrupts at a priority level below a certain level.
|
||||
This feature can be used to support maskable nested interrupts.
|
||||
|
||||
Maskable nested interrupts differ from zero-latency interrupts in
|
||||
that they obey the interrupt masking mechanisms of the system.
|
||||
For example, setting the BASEPRI register to a specific threshold will
|
||||
block all interrupts of a lower or equal priority.
|
||||
However, high-priority interrupts (such as Non-Maskable Interrupts
|
||||
or zero-latency interrupts) are unaffected by these masks.
|
||||
|
||||
This is useful when you have a high-priority interrupt that needs to
|
||||
be able to interrupt the system, but you also have lower-priority
|
||||
interrupts that you want to be able to mask.
|
||||
|
||||
The following table shows the priority levels of the Cortex-M family:
|
||||
|
||||
.. code-block::
|
||||
|
||||
IRQ type Priority
|
||||
Dataabort 0x00
|
||||
SVC 0x70
|
||||
Disable IRQ 0x80
|
||||
(critical-section)
|
||||
High prio IRQ1 0x90 (Maskable nested interrupt)
|
||||
High prio IRQ2 0xA0 (Can call OS API in ISR)
|
||||
Low prio IRQ 0xB0
|
||||
PendSV 0xE0
|
||||
|
||||
As you can see, the priority levels of the maskable nested interrupts
|
||||
are between the critical section and the low-priority interrupts.
|
||||
And High prio IRQ can call OS API in ISR.
|
||||
|
||||
|
||||
Nested Interrupt Handling
|
||||
=========================
|
||||
|
||||
|
|
|
@ -695,7 +695,8 @@ MCAN1 Loopback Test
|
|||
|
||||
Device Drivers -> CAN Driver support
|
||||
CONFIG_CAN=y # Enable the upper-half CAN driver
|
||||
CONFIG_CAN_FIFOSIZE=8
|
||||
CONFIG_CAN_TXFIFOSIZE=8
|
||||
CONFIG_CAN_RXFIFOSIZE=8
|
||||
CONFIG_CAN_NPENDINGRTR=4
|
||||
|
||||
System Type -> SAMV7 Peripheral Selections
|
||||
|
|
|
@ -1288,7 +1288,8 @@ MCAN1 Loopback Test
|
|||
|
||||
Device Drivers -> CAN Driver support
|
||||
CONFIG_CAN=y # Enable the upper-half CAN driver
|
||||
CONFIG_CAN_FIFOSIZE=8
|
||||
CONFIG_CAN_TXFIFOSIZE=8
|
||||
CONFIG_CAN_RXFIFOSIZE=8
|
||||
CONFIG_CAN_NPENDINGRTR=4
|
||||
|
||||
System Type -> SAMV7 Peripheral Selections
|
||||
|
|
|
@ -385,7 +385,11 @@ Cloudctrl-specific Configuration Options
|
|||
|
||||
CONFIG_CAN - Enables CAN support (one or both of CONFIG_STM32_CAN1 or
|
||||
CONFIG_STM32_CAN2 must also be defined)
|
||||
CONFIG_CAN_FIFOSIZE - The size of the circular buffer of CAN messages.
|
||||
CONFIG_CAN_TXFIFOSIZE - The size of the circular tx buffer
|
||||
of CAN messages.
|
||||
Default: 8
|
||||
CONFIG_CAN_RXFIFOSIZE - The size of the circular rx buffer
|
||||
of CAN messages.
|
||||
Default: 8
|
||||
CONFIG_CAN_NPENDINGRTR - The size of the list of pending RTR requests.
|
||||
Default: 4
|
||||
|
|
|
@ -501,7 +501,11 @@ M3 Wildfire-specific Configuration Options
|
|||
CONFIG_STM32_CAN2 must also be defined)
|
||||
CONFIG_CAN_EXTID - Enables support for the 29-bit extended ID. Default
|
||||
Standard 11-bit IDs.
|
||||
CONFIG_CAN_FIFOSIZE - The size of the circular buffer of CAN messages.
|
||||
CONFIG_CAN_TXFIFOSIZE - The size of the circular tx buffer
|
||||
of CAN messages.
|
||||
Default: 8
|
||||
CONFIG_CAN_RXFIFOSIZE - The size of the circular rx buffer
|
||||
of CAN messages.
|
||||
Default: 8
|
||||
CONFIG_CAN_NPENDINGRTR - The size of the list of pending RTR requests.
|
||||
Default: 4
|
||||
|
|
|
@ -282,7 +282,11 @@ HY-Mini specific Configuration Options
|
|||
CONFIG_STM32_CAN2 must also be defined)
|
||||
CONFIG_CAN_EXTID - Enables support for the 29-bit extended ID. Default
|
||||
Standard 11-bit IDs.
|
||||
CONFIG_CAN_FIFOSIZE - The size of the circular buffer of CAN messages.
|
||||
CONFIG_CAN_TXFIFOSIZE - The size of the circular tx buffer
|
||||
of CAN messages.
|
||||
Default: 8
|
||||
CONFIG_CAN_RXFIFOSIZE - The size of the circular rx buffer
|
||||
of CAN messages.
|
||||
Default: 8
|
||||
CONFIG_CAN_NPENDINGRTR - The size of the list of pending RTR requests.
|
||||
Default: 4
|
||||
|
|
|
@ -395,7 +395,11 @@ Shenzhou-specific Configuration Options
|
|||
|
||||
CONFIG_CAN - Enables CAN support (one or both of CONFIG_STM32_CAN1 or
|
||||
CONFIG_STM32_CAN2 must also be defined)
|
||||
CONFIG_CAN_FIFOSIZE - The size of the circular buffer of CAN messages.
|
||||
CONFIG_CAN_TXFIFOSIZE - The size of the circular tx buffer
|
||||
of CAN messages.
|
||||
Default: 8
|
||||
CONFIG_CAN_RXFIFOSIZE - The size of the circular rx buffer
|
||||
of CAN messages.
|
||||
Default: 8
|
||||
CONFIG_CAN_NPENDINGRTR - The size of the list of pending RTR requests.
|
||||
Default: 4
|
||||
|
|
|
@ -444,7 +444,11 @@ STM3210E-EVAL-specific Configuration Options
|
|||
CONFIG_STM32_CAN2 must also be defined)
|
||||
CONFIG_CAN_EXTID - Enables support for the 29-bit extended ID. Default
|
||||
Standard 11-bit IDs.
|
||||
CONFIG_CAN_FIFOSIZE - The size of the circular buffer of CAN messages.
|
||||
CONFIG_CAN_TXFIFOSIZE - The size of the circular tx buffer
|
||||
of CAN messages.
|
||||
Default: 8
|
||||
CONFIG_CAN_RXFIFOSIZE - The size of the circular rx buffer
|
||||
of CAN messages.
|
||||
Default: 8
|
||||
CONFIG_CAN_NPENDINGRTR - The size of the list of pending RTR requests.
|
||||
Default: 4
|
||||
|
|
|
@ -231,7 +231,11 @@ STM32 Tiny - specific Configuration Options
|
|||
CONFIG_STM32_CAN2 must also be defined)
|
||||
CONFIG_CAN_EXTID - Enables support for the 29-bit extended ID. Default
|
||||
Standard 11-bit IDs.
|
||||
CONFIG_CAN_FIFOSIZE - The size of the circular buffer of CAN messages.
|
||||
CONFIG_CAN_TXFIFOSIZE - The size of the circular tx buffer
|
||||
of CAN messages.
|
||||
Default: 8
|
||||
CONFIG_CAN_RXFIFOSIZE - The size of the circular rx buffer
|
||||
of CAN messages.
|
||||
Default: 8
|
||||
CONFIG_CAN_NPENDINGRTR - The size of the list of pending RTR requests.
|
||||
Default: 4
|
||||
|
|
|
@ -740,7 +740,11 @@ STM32F103 Minimum - specific Configuration Options
|
|||
CONFIG_STM32_CAN2 must also be defined)
|
||||
CONFIG_CAN_EXTID - Enables support for the 29-bit extended ID. Default
|
||||
Standard 11-bit IDs.
|
||||
CONFIG_CAN_FIFOSIZE - The size of the circular buffer of CAN messages.
|
||||
CONFIG_CAN_TXFIFOSIZE - The size of the circular tx buffer
|
||||
of CAN messages.
|
||||
Default: 8
|
||||
CONFIG_CAN_RXFIFOSIZE - The size of the circular rx buffer
|
||||
of CAN messages.
|
||||
Default: 8
|
||||
CONFIG_CAN_NPENDINGRTR - The size of the list of pending RTR requests.
|
||||
Default: 4
|
||||
|
|
|
@ -93,7 +93,12 @@ CAN
|
|||
- CONFIG_CAN_EXTID - Enables support for the 29-bit extended ID.
|
||||
Default Standard 11-bit IDs.
|
||||
|
||||
- CONFIG_CAN_FIFOSIZE - The size of the circular buffer of CAN messages.
|
||||
- CONFIG_CAN_TXFIFOSIZE - The size of the circular tx buffer
|
||||
of CAN messages.
|
||||
Default: 8
|
||||
|
||||
- CONFIG_CAN_RXFIFOSIZE - The size of the circular rx buffer
|
||||
of CAN messages.
|
||||
Default: 8
|
||||
|
||||
- CONFIG_CAN_NPENDINGRTR - The size of the list of pending RTR requests.
|
||||
|
|
|
@ -140,7 +140,12 @@ CAN character device
|
|||
- CONFIG_CAN_EXTID - Enables support for the 29-bit extended ID. Default
|
||||
Standard 11-bit IDs.
|
||||
|
||||
- CONFIG_CAN_FIFOSIZE - The size of the circular buffer of CAN messages.
|
||||
- CONFIG_CAN_TXFIFOSIZE - The size of the circular tx buffer
|
||||
of CAN messages.
|
||||
Default: 8
|
||||
|
||||
- CONFIG_CAN_RXFIFOSIZE - The size of the circular rx buffer
|
||||
of CAN messages.
|
||||
Default: 8
|
||||
|
||||
- CONFIG_CAN_NPENDINGRTR - The size of the list of pending RTR requests.
|
||||
|
|
|
@ -144,7 +144,12 @@ CAN
|
|||
- CONFIG_CAN_EXTID - Enables support for the 29-bit extended ID. Default
|
||||
Standard 11-bit IDs.
|
||||
|
||||
- CONFIG_CAN_FIFOSIZE - The size of the circular buffer of CAN messages.
|
||||
- CONFIG_CAN_TXFIFOSIZE - The size of the circular tx buffer
|
||||
of CAN messages.
|
||||
Default: 8
|
||||
|
||||
- CONFIG_CAN_RXFIFOSIZE - The size of the circular rx buffer
|
||||
of CAN messages.
|
||||
Default: 8
|
||||
|
||||
- CONFIG_CAN_NPENDINGRTR - The size of the list of pending RTR requests.
|
||||
|
|
|
@ -189,7 +189,13 @@ CAN
|
|||
|
||||
- CONFIG_CAN_EXTID - Enables support for the 29-bit extended ID. Default Standard 11-bit IDs.
|
||||
|
||||
- CONFIG_CAN_FIFOSIZE - The size of the circular buffer of CAN messages. Default: 8
|
||||
- CONFIG_CAN_TXFIFOSIZE - The size of the circular tx buffer
|
||||
of CAN messages.
|
||||
Default: 8
|
||||
|
||||
- CONFIG_CAN_RXFIFOSIZE - The size of the circular rx buffer
|
||||
of CAN messages.
|
||||
Default: 8
|
||||
|
||||
- CONFIG_CAN_NPENDINGRTR - The size of the list of pending RTR requests. Default: 4
|
||||
|
||||
|
|
|
@ -670,6 +670,14 @@ config ARCH_USE_DATA_HEAP
|
|||
This option enables architecture-specific memory allocator
|
||||
for dynamic data loading.
|
||||
|
||||
config ARCH_USE_SEPARATED_SECTION
|
||||
bool "Enable separate section allocation for dynamic loading"
|
||||
default n
|
||||
depends on ARCH_USE_TEXT_HEAP || ARCH_USE_DATA_HEAP
|
||||
---help---
|
||||
This option enables loading different sections into different
|
||||
memory areas, allowing for different speeds.
|
||||
|
||||
menuconfig ARCH_ADDRENV
|
||||
bool "Address environments"
|
||||
default n
|
||||
|
|
|
@ -103,6 +103,23 @@ config ARCH_CHIP_C5471
|
|||
---help---
|
||||
TI TMS320 C5471, A180, or DA180 (ARM7TDMI)
|
||||
|
||||
config ARCH_CHIP_CSK6
|
||||
bool "LISTEANAI CSK6 6001A/6011B/6012"
|
||||
select ARCH_HAVE_MPU
|
||||
select ARCH_HAVE_FETCHADD
|
||||
select ARCH_HAVE_I2CRESET
|
||||
select ARCH_HAVE_HEAPCHECK
|
||||
select ARCH_HAVE_PROGMEM
|
||||
select ARCH_HAVE_SPI_BITORDER
|
||||
select ARCH_HAVE_TICKLESS
|
||||
select ARCH_HAVE_TIMEKEEPING
|
||||
select ARM_HAVE_MPU_UNIFIED
|
||||
select ARMV8M_HAVE_STACKCHECK
|
||||
select ARCH_HAVE_ADJTIME
|
||||
select ARCH_CORTEXM33
|
||||
---help---
|
||||
LISTEANAI CSK6 architectures (ARM Cortex-M33).
|
||||
|
||||
config ARCH_CHIP_DM320
|
||||
bool "TMS320 DM320"
|
||||
select ARCH_ARM926EJS
|
||||
|
@ -441,23 +458,6 @@ config ARCH_CHIP_STM32
|
|||
---help---
|
||||
STMicro STM32 architectures (ARM Cortex-M3/4).
|
||||
|
||||
config ARCH_CHIP_CSK6
|
||||
bool "STMicro STM6 6001A/6011B/6012"
|
||||
select ARCH_HAVE_MPU
|
||||
select ARCH_HAVE_FETCHADD
|
||||
select ARCH_HAVE_I2CRESET
|
||||
select ARCH_HAVE_HEAPCHECK
|
||||
select ARCH_HAVE_PROGMEM
|
||||
select ARCH_HAVE_SPI_BITORDER
|
||||
select ARCH_HAVE_TICKLESS
|
||||
select ARCH_HAVE_TIMEKEEPING
|
||||
select ARM_HAVE_MPU_UNIFIED
|
||||
select ARMV8M_HAVE_STACKCHECK
|
||||
select ARCH_HAVE_ADJTIME
|
||||
select ARCH_CORTEXM33
|
||||
---help---
|
||||
LISTEANAI CSK6architectures (ARM Cortex-M33).
|
||||
|
||||
config ARCH_CHIP_STM32F0
|
||||
bool "STMicro STM32 F0"
|
||||
select ARCH_CORTEXM0
|
||||
|
@ -817,6 +817,7 @@ config ARCH_CORTEXM0
|
|||
select ARM_THUMB
|
||||
select ARCH_ARMV6M
|
||||
select ARCH_HAVE_IRQPRIO
|
||||
select ARCH_HAVE_IRQTRIGGER
|
||||
select ARCH_HAVE_RAMVECTORS
|
||||
select ARCH_HAVE_RESET
|
||||
select ARCH_HAVE_HARDFAULT_DEBUG
|
||||
|
|
|
@ -127,12 +127,6 @@
|
|||
#ifndef __ASSEMBLY__
|
||||
struct xcptcontext
|
||||
{
|
||||
/* The following function pointer is non-zero if there
|
||||
* are pending signals to be processed.
|
||||
*/
|
||||
|
||||
void *sigdeliver; /* Actual type is sig_deliver_t */
|
||||
|
||||
/* These are saved copies of the context used during
|
||||
* signal processing.
|
||||
*/
|
||||
|
|
|
@ -152,12 +152,6 @@ struct xcpt_syscall_s
|
|||
|
||||
struct xcptcontext
|
||||
{
|
||||
/* The following function pointer is non-zero if there
|
||||
* are pending signals to be processed.
|
||||
*/
|
||||
|
||||
void *sigdeliver; /* Actual type is sig_deliver_t */
|
||||
|
||||
/* These are saved copies of the context used during
|
||||
* signal processing.
|
||||
*/
|
||||
|
|
|
@ -253,12 +253,6 @@ struct xcpt_syscall_s
|
|||
|
||||
struct xcptcontext
|
||||
{
|
||||
/* The following function pointer is non-zero if there are pending signals
|
||||
* to be processed.
|
||||
*/
|
||||
|
||||
void *sigdeliver; /* Actual type is sig_deliver_t */
|
||||
|
||||
/* These are saved copies of the context used during
|
||||
* signal processing.
|
||||
*/
|
||||
|
|
|
@ -212,12 +212,6 @@ struct xcpt_syscall_s
|
|||
|
||||
struct xcptcontext
|
||||
{
|
||||
/* The following function pointer is non-zero if there
|
||||
* are pending signals to be processed.
|
||||
*/
|
||||
|
||||
void *sigdeliver; /* Actual type is sig_deliver_t */
|
||||
|
||||
/* These are saved copies of the context used during
|
||||
* signal processing.
|
||||
*/
|
||||
|
@ -446,7 +440,7 @@ static inline void up_irq_enable(void)
|
|||
{
|
||||
/* In this case, we are always retaining or lowering the priority value */
|
||||
|
||||
setbasepri(NVIC_SYSH_PRIORITY_MIN);
|
||||
setbasepri(0);
|
||||
__asm__ __volatile__ ("\tcpsie i\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -253,12 +253,6 @@ struct xcpt_syscall_s
|
|||
|
||||
struct xcptcontext
|
||||
{
|
||||
/* The following function pointer is non-zero if there are pending signals
|
||||
* to be processed.
|
||||
*/
|
||||
|
||||
void *sigdeliver; /* Actual type is sig_deliver_t */
|
||||
|
||||
/* These are saved copies of the context used during
|
||||
* signal processing.
|
||||
*/
|
||||
|
|
|
@ -223,12 +223,6 @@ struct xcpt_syscall_s
|
|||
|
||||
struct xcptcontext
|
||||
{
|
||||
/* The following function pointer is non-zero if there
|
||||
* are pending signals to be processed.
|
||||
*/
|
||||
|
||||
void *sigdeliver; /* Actual type is sig_deliver_t */
|
||||
|
||||
/* These are saved copies of the context used during
|
||||
* signal processing.
|
||||
*/
|
||||
|
@ -419,7 +413,7 @@ static inline void up_irq_enable(void)
|
|||
{
|
||||
/* In this case, we are always retaining or lowering the priority value */
|
||||
|
||||
setbasepri(NVIC_SYSH_PRIORITY_MIN);
|
||||
setbasepri(0);
|
||||
__asm__ __volatile__ ("\tcpsie i\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -253,12 +253,6 @@ struct xcpt_syscall_s
|
|||
|
||||
struct xcptcontext
|
||||
{
|
||||
/* The following function pointer is non-zero if there are pending signals
|
||||
* to be processed.
|
||||
*/
|
||||
|
||||
void *sigdeliver; /* Actual type is sig_deliver_t */
|
||||
|
||||
/* These are saved copies of the context used during
|
||||
* signal processing.
|
||||
*/
|
||||
|
|
|
@ -100,19 +100,17 @@ typedef enum
|
|||
|
||||
typedef struct
|
||||
{
|
||||
struct timespec ts; /* timestamp */
|
||||
fault_flags_t flags; /* What is in the dump */
|
||||
uintptr_t current_regs; /* Used to validate the dump */
|
||||
int lineno; /* __LINE__ to up_assert */
|
||||
pid_t pid; /* Process ID */
|
||||
uint32_t regs[XCPTCONTEXT_REGS]; /* Interrupt register save area */
|
||||
crash_stack_t stacks; /* Stack info */
|
||||
#if CONFIG_TASK_NAME_SIZE > 0
|
||||
char name[CONFIG_TASK_NAME_SIZE + 1]; /* Task name (with NULL
|
||||
* terminator) */
|
||||
#endif
|
||||
char filename[MAX_FILE_PATH_LENGTH]; /* the Last of chars in
|
||||
* __FILE__ to up_assert */
|
||||
struct timespec ts; /* timestamp */
|
||||
fault_flags_t flags; /* What is in the dump */
|
||||
uintptr_t current_regs; /* Used to validate the dump */
|
||||
int lineno; /* __LINE__ to up_assert */
|
||||
pid_t pid; /* Process ID */
|
||||
uint32_t regs[XCPTCONTEXT_REGS]; /* Interrupt register save area */
|
||||
crash_stack_t stacks; /* Stack info */
|
||||
char name[CONFIG_TASK_NAME_SIZE + 1]; /* Task name (with NULL
|
||||
* terminator) */
|
||||
char filename[MAX_FILE_PATH_LENGTH]; /* the Last of chars in
|
||||
* __FILE__ to up_assert */
|
||||
} info_t;
|
||||
|
||||
typedef struct
|
||||
|
|
|
@ -158,7 +158,7 @@
|
|||
#define CXD56_IRQ_SPH13 (CXD56_IRQ_EXTINT+93) /* SPH13 IRQ number */
|
||||
#define CXD56_IRQ_SPH14 (CXD56_IRQ_EXTINT+94) /* SPH14 IRQ number */
|
||||
#define CXD56_IRQ_SPH15 (CXD56_IRQ_EXTINT+95) /* SPH15 IRQ number */
|
||||
#define CXD56_IRQ_SW_INT (CXD56_IRQ_EXTINT+96) /* SW_INT IRQ number */
|
||||
#define CXD56_IRQ_SMP_CALL (CXD56_IRQ_EXTINT+96) /* SMP_CALL IRQ number */
|
||||
#define CXD56_IRQ_TIMER0 (CXD56_IRQ_EXTINT+97) /* TIMER0 IRQ number */
|
||||
#define CXD56_IRQ_TIMER1 (CXD56_IRQ_EXTINT+98) /* TIMER1 IRQ number */
|
||||
#define CXD56_IRQ_TIMER2 (CXD56_IRQ_EXTINT+99) /* TIMER2 IRQ number */
|
||||
|
|
|
@ -59,11 +59,11 @@
|
|||
#define LC823450_IRQ_INTERRUPTS (16) /* Vector number of the first external interrupt */
|
||||
|
||||
#define LC823450_IRQ_CTXM3_00 (LC823450_IRQ_INTERRUPTS+0) /* 16: CortexM3_00 interrupt */
|
||||
#define LC823450_IRQ_CTXM3_01 (LC823450_IRQ_INTERRUPTS+1) /* 17: CortexM3_01 interrupt */
|
||||
#define LC823450_IRQ_SMP_CALL_01 (LC823450_IRQ_INTERRUPTS+1) /* 17: CortexM3_01 interrupt */
|
||||
#define LC823450_IRQ_CTXM3_02 (LC823450_IRQ_INTERRUPTS+2) /* 18: CortexM3_02 interrupt */
|
||||
#define LC823450_IRQ_CTXM3_03 (LC823450_IRQ_INTERRUPTS+3) /* 19: CortexM3_03 interrupt */
|
||||
#define LC823450_IRQ_CTXM3_10 (LC823450_IRQ_INTERRUPTS+4) /* 20: CortexM3_00 interrupt */
|
||||
#define LC823450_IRQ_CTXM3_11 (LC823450_IRQ_INTERRUPTS+5) /* 21: CortexM3_01 interrupt */
|
||||
#define LC823450_IRQ_SMP_CALL_11 (LC823450_IRQ_INTERRUPTS+5) /* 21: CortexM3_01 interrupt */
|
||||
#define LC823450_IRQ_CTXM3_12 (LC823450_IRQ_INTERRUPTS+6) /* 22: CortexM3_02 interrupt */
|
||||
#define LC823450_IRQ_CTXM3_13 (LC823450_IRQ_INTERRUPTS+7) /* 23: CortexM3_03 interrupt */
|
||||
#define LC823450_IRQ_LPDSP0 (LC823450_IRQ_INTERRUPTS+8) /* 24: LPDSP0 interrupt */
|
||||
|
|
|
@ -75,8 +75,8 @@
|
|||
#define RP2040_DMA_IRQ_1 (RP2040_IRQ_EXTINT+12)
|
||||
#define RP2040_IO_IRQ_BANK0 (RP2040_IRQ_EXTINT+13)
|
||||
#define RP2040_IO_IRQ_QSPI (RP2040_IRQ_EXTINT+14)
|
||||
#define RP2040_SIO_IRQ_PROC0 (RP2040_IRQ_EXTINT+15)
|
||||
#define RP2040_SIO_IRQ_PROC1 (RP2040_IRQ_EXTINT+16)
|
||||
#define RP2040_SMP_CALL_PROC0 (RP2040_IRQ_EXTINT+15)
|
||||
#define RP2040_SMP_CALL_PROC1 (RP2040_IRQ_EXTINT+16)
|
||||
#define RP2040_CLOCKS_IRQ (RP2040_IRQ_EXTINT+17)
|
||||
#define RP2040_SPI0_IRQ (RP2040_IRQ_EXTINT+18)
|
||||
#define RP2040_SPI1_IRQ (RP2040_IRQ_EXTINT+19)
|
||||
|
|
|
@ -114,7 +114,7 @@
|
|||
#define SAM_IRQ_TC5 (SAM_IRQ_EXTINT+SAM_PID_TC5) /* PID 28: Timer Counter 5 */
|
||||
#define SAM_IRQ_ADC (SAM_IRQ_EXTINT+SAM_PID_ADC) /* PID 29: Analog To Digital Converter */
|
||||
#define SAM_IRQ_ARM (SAM_IRQ_EXTINT+SAM_PID_ARM) /* PID 30: FPU signals (only on CM4P1 core): FPIXC, FPOFC, FPUFC, FPIOC, FPDZC, FPIDC, FPIXC */
|
||||
#define SAM_IRQ_IPC0 (SAM_IRQ_EXTINT+SAM_PID_IPC0) /* PID 31: Interprocessor communication 0 */
|
||||
#define SAM_IRQ_SMP_CALL0 (SAM_IRQ_EXTINT+SAM_PID_IPC0) /* PID 31: Interprocessor communication 0 */
|
||||
#define SAM_IRQ_SLCDC (SAM_IRQ_EXTINT+SAM_PID_SLCDC) /* PID 32: Segment LCD Controller */
|
||||
#define SAM_IRQ_TRNG (SAM_IRQ_EXTINT+SAM_PID_TRNG) /* PID 33: True Random Generator */
|
||||
#define SAM_IRQ_ICM (SAM_IRQ_EXTINT+SAM_PID_ICM) /* PID 34: Integrity Check Module */
|
||||
|
@ -122,7 +122,7 @@
|
|||
#define SAM_IRQ_AES (SAM_IRQ_EXTINT+SAM_PID_AES) /* PID 36: Advanced Enhanced Standard */
|
||||
#define SAM_IRQ_PIOC (SAM_IRQ_EXTINT+SAM_PID_PIOC) /* PID 37: Parallel I/O Controller C */
|
||||
#define SAM_IRQ_UART1 (SAM_IRQ_EXTINT+SAM_PID_UART1) /* PID 38: Universal Asynchronous Receiver Transmitter 1 */
|
||||
#define SAM_IRQ_IPC1 (SAM_IRQ_EXTINT+SAM_PID_IPC1) /* PID 39: Interprocessor communication 1 */
|
||||
#define SAM_IRQ_SMP_CALL1 (SAM_IRQ_EXTINT+SAM_PID_IPC1) /* PID 39: Interprocessor communication 1 */
|
||||
#define SAM_IRQ_RESERVED_40 (SAM_IRQ_EXTINT+SAM_PID_RESERVED_40) /* PID 40: Reserved */
|
||||
#define SAM_IRQ_PWM (SAM_IRQ_EXTINT+SAM_PID_PWM) /* PID 41: Pulse Width Modulation */
|
||||
#define SAM_IRQ_SRAM (SAM_IRQ_EXTINT+SAM_PID_SRAM) /* PID 42: SRAM1 (I/D Code bus of CM4P1), SRAM2 (Systembus of CM4P1) */
|
||||
|
|
|
@ -158,12 +158,6 @@
|
|||
#ifndef __ASSEMBLY__
|
||||
struct xcptcontext
|
||||
{
|
||||
/* The following function pointer is non-zero if there
|
||||
* are pending signals to be processed.
|
||||
*/
|
||||
|
||||
void *sigdeliver; /* Actual type is sig_deliver_t */
|
||||
|
||||
/* These are saved register array pointer used during
|
||||
* signal processing.
|
||||
*/
|
||||
|
|
|
@ -58,6 +58,8 @@
|
|||
|
||||
uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
board_autoled_on(LED_INIRQ);
|
||||
#ifdef CONFIG_SUPPRESS_INTERRUPTS
|
||||
PANIC();
|
||||
|
@ -71,6 +73,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
|||
*/
|
||||
|
||||
up_set_current_regs(regs);
|
||||
tcb->xcp.regs = regs;
|
||||
|
||||
/* Acknowledge the interrupt */
|
||||
|
||||
|
@ -79,6 +82,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
|||
/* Deliver the IRQ */
|
||||
|
||||
irq_dispatch(irq, regs);
|
||||
tcb = this_task();
|
||||
|
||||
/* Check for a context switch. If a context switch occurred, then
|
||||
* current_regs will have a different value than it did on entry. If an
|
||||
|
@ -87,7 +91,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
|||
* returning from the interrupt.
|
||||
*/
|
||||
|
||||
if (regs != up_current_regs())
|
||||
if (regs != tcb->xcp.regs)
|
||||
{
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
/* Make sure that the address environment for the previously
|
||||
|
@ -99,14 +103,19 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
|||
addrenv_switch(NULL);
|
||||
#endif
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(g_running_tasks[this_cpu()]);
|
||||
nxsched_resume_scheduler(tcb);
|
||||
|
||||
/* Record the new "running" task when context switch occurred.
|
||||
* g_running_tasks[] is only used by assertion logic for reporting
|
||||
* crashes.
|
||||
*/
|
||||
|
||||
g_running_tasks[this_cpu()] = this_task();
|
||||
g_running_tasks[this_cpu()] = tcb;
|
||||
|
||||
regs = up_current_regs();
|
||||
regs = tcb->xcp.regs;
|
||||
}
|
||||
|
||||
/* Set current_regs to NULL to indicate that we are no longer in an
|
||||
|
|
|
@ -75,125 +75,61 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
void up_schedule_sigaction(struct tcb_s *tcb)
|
||||
{
|
||||
sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
|
||||
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(),
|
||||
this_task()->xcp.regs);
|
||||
|
||||
/* Refuse to handle nested signal actions */
|
||||
/* First, handle some special cases when the signal is
|
||||
* being delivered to the currently executing task.
|
||||
*/
|
||||
|
||||
if (!tcb->xcp.sigdeliver)
|
||||
if (tcb == this_task() && !up_interrupt_context())
|
||||
{
|
||||
tcb->xcp.sigdeliver = sigdeliver;
|
||||
/* In this case just deliver the signal now. */
|
||||
|
||||
/* First, handle some special cases when the signal is
|
||||
* being delivered to the currently executing task.
|
||||
(tcb->sigdeliver)(tcb);
|
||||
tcb->sigdeliver = NULL;
|
||||
}
|
||||
|
||||
/* Otherwise, we are (1) signaling a task is not running
|
||||
* from an interrupt handler or (2) we are not in an
|
||||
* interrupt handler and the running task is signalling
|
||||
* some non-running task.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the return lr and cpsr and one scratch register
|
||||
* These will be restored by the signal trampoline after
|
||||
* the signals have been delivered.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
/* Save the current register context location */
|
||||
|
||||
if (tcb == this_task())
|
||||
{
|
||||
/* CASE 1: We are not in an interrupt handler and
|
||||
* a task is signalling itself for some reason.
|
||||
*/
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
|
||||
if (!up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now. */
|
||||
|
||||
sigdeliver(tcb);
|
||||
tcb->xcp.sigdeliver = NULL;
|
||||
}
|
||||
|
||||
/* CASE 2: We are in an interrupt handler AND the
|
||||
* interrupted task is the same as the one that
|
||||
* must receive the signal, then we will have to modify
|
||||
* the return state as well as the state in the TCB.
|
||||
*
|
||||
* Hmmm... there looks like a latent bug here: The following
|
||||
* logic would fail in the strange case where we are in an
|
||||
* interrupt handler, the thread is signalling itself, but
|
||||
* a context switch to another task has occurred so that
|
||||
* current_regs does not refer to the thread of this_task()!
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the return lr and cpsr and one scratch register
|
||||
* These will be restored by the signal trampoline after
|
||||
* the signals have been delivered.
|
||||
*/
|
||||
|
||||
/* And make sure that the saved context in the TCB
|
||||
* is the same as the interrupt return context.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.saved_regs);
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
|
||||
memcpy(up_current_regs(), tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() +
|
||||
XCPTCONTEXT_REGS);
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
up_current_regs()[REG_CPSR] = PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT;
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
up_current_regs()[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, we are (1) signaling a task is not running
|
||||
* from an interrupt handler or (2) we are not in an
|
||||
* interrupt handler and the running task is signalling
|
||||
* some non-running task.
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the return lr and cpsr and one scratch register
|
||||
* These will be restored by the signal trampoline after
|
||||
* the signals have been delivered.
|
||||
*/
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
|
||||
|
||||
/* Save the current register context location */
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
|
||||
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
tcb->xcp.regs[REG_CPSR] = PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT;
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
tcb->xcp.regs[REG_CPSR] = PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT;
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
||||
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,8 +59,8 @@ void arm_sigdeliver(void)
|
|||
board_autoled_on(LED_SIGNAL);
|
||||
|
||||
sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n",
|
||||
rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head);
|
||||
DEBUGASSERT(rtcb->xcp.sigdeliver != NULL);
|
||||
rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head);
|
||||
DEBUGASSERT(rtcb->sigdeliver != NULL);
|
||||
|
||||
#ifndef CONFIG_SUPPRESS_INTERRUPTS
|
||||
/* Then make sure that interrupts are enabled. Signal handlers must always
|
||||
|
@ -72,7 +72,7 @@ void arm_sigdeliver(void)
|
|||
|
||||
/* Deliver the signal */
|
||||
|
||||
((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb);
|
||||
(rtcb->sigdeliver)(rtcb);
|
||||
|
||||
/* Output any debug messages BEFORE restoring errno (because they may
|
||||
* alter errno), then disable interrupts again and restore the original
|
||||
|
@ -92,7 +92,7 @@ void arm_sigdeliver(void)
|
|||
* could be modified by a hostile program.
|
||||
*/
|
||||
|
||||
rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */
|
||||
rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */
|
||||
|
||||
/* Then restore the correct state for this thread of execution. */
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
|
||||
uint32_t *arm_syscall(uint32_t *regs)
|
||||
{
|
||||
struct tcb_s *tcb;
|
||||
struct tcb_s *tcb = this_task();
|
||||
uint32_t cmd;
|
||||
int cpu;
|
||||
|
||||
|
@ -66,6 +66,7 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||
* current_regs is also used to manage interrupt level context switches.
|
||||
*/
|
||||
|
||||
tcb->xcp.regs = regs;
|
||||
up_set_current_regs(regs);
|
||||
|
||||
/* The SYSCALL command is in R0 on entry. Parameters follow in R1..R7 */
|
||||
|
@ -94,7 +95,7 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||
* set will determine the restored context.
|
||||
*/
|
||||
|
||||
up_set_current_regs((uint32_t *)regs[REG_R1]);
|
||||
tcb->xcp.regs = (uint32_t *)regs[REG_R1];
|
||||
DEBUGASSERT(up_current_regs());
|
||||
}
|
||||
break;
|
||||
|
@ -133,15 +134,9 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||
break;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
/* Check for a context switch. If a context switch occurred, then
|
||||
* current_regs will have a different value than it did on entry. If an
|
||||
* interrupt level context switch has occurred, then establish the correct
|
||||
* address environment before returning from the interrupt.
|
||||
*/
|
||||
|
||||
if (regs != up_current_regs())
|
||||
if (regs != tcb->xcp.regs)
|
||||
{
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
/* Make sure that the address environment for the previously
|
||||
* running task is closed down gracefully (data caches dump,
|
||||
* MMU flushed) and set up the address environment for the new
|
||||
|
@ -149,13 +144,8 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||
*/
|
||||
|
||||
addrenv_switch(NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Restore the cpu lock */
|
||||
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
/* Record the new "running" task. g_running_tasks[] is only used by
|
||||
* assertion logic for reporting crashes.
|
||||
*/
|
||||
|
@ -181,5 +171,5 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||
* SYS_context_switch system call.
|
||||
*/
|
||||
|
||||
return regs;
|
||||
return tcb->xcp.regs;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ set(SRCS
|
|||
arm_svcall.c
|
||||
arm_systemreset.c
|
||||
arm_tcbinfo.c
|
||||
arm_trigger_irq.c
|
||||
arm_vectors.c)
|
||||
|
||||
if(CONFIG_DEBUG_FEATURES)
|
||||
|
|
|
@ -27,6 +27,7 @@ CMN_ASRCS += arm_exception.S arm_saveusercontext.S
|
|||
CMN_CSRCS += arm_cpuinfo.c arm_doirq.c arm_hardfault.c arm_initialstate.c
|
||||
CMN_CSRCS += arm_schedulesigaction.c arm_sigdeliver.c arm_svcall.c
|
||||
CMN_CSRCS += arm_systemreset.c arm_tcbinfo.c arm_vectors.c
|
||||
CMN_CSRCS += arm_trigger_irq.c
|
||||
|
||||
ifeq ($(CONFIG_DEBUG_FEATURES),y)
|
||||
CMN_CSRCS += arm_dumpnvic.c
|
||||
|
|
|
@ -35,30 +35,60 @@
|
|||
|
||||
#include "arm_internal.h"
|
||||
#include "exc_return.h"
|
||||
#include "nvic.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
void exception_direct(void)
|
||||
{
|
||||
int irq = getipsr();
|
||||
|
||||
arm_ack_irq(irq);
|
||||
irq_dispatch(irq, NULL);
|
||||
|
||||
if (g_running_tasks[this_cpu()] != this_task())
|
||||
{
|
||||
up_trigger_irq(NVIC_IRQ_PENDSV, 0);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
board_autoled_on(LED_INIRQ);
|
||||
#ifdef CONFIG_SUPPRESS_INTERRUPTS
|
||||
PANIC();
|
||||
#else
|
||||
|
||||
if (regs[REG_EXC_RETURN] & EXC_RETURN_THREAD_MODE)
|
||||
{
|
||||
up_set_current_regs(regs);
|
||||
}
|
||||
|
||||
/* Acknowledge the interrupt */
|
||||
|
||||
arm_ack_irq(irq);
|
||||
|
||||
/* Deliver the IRQ */
|
||||
/* Set current regs for crash dump */
|
||||
|
||||
irq_dispatch(irq, regs);
|
||||
up_set_current_regs(regs);
|
||||
|
||||
if (irq == NVIC_IRQ_PENDSV)
|
||||
{
|
||||
#ifdef CONFIG_ARCH_HIPRI_INTERRUPT
|
||||
/* Dispatch the PendSV interrupt */
|
||||
|
||||
irq_dispatch(irq, regs);
|
||||
#endif
|
||||
|
||||
up_irq_save();
|
||||
g_running_tasks[this_cpu()]->xcp.regs = regs;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Dispatch irq */
|
||||
|
||||
tcb->xcp.regs = regs;
|
||||
irq_dispatch(irq, regs);
|
||||
}
|
||||
|
||||
/* If a context switch occurred while processing the interrupt then
|
||||
* current_regs may have change value. If we return any value different
|
||||
|
@ -66,27 +96,27 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
|||
* switch occurred during interrupt processing.
|
||||
*/
|
||||
|
||||
if (regs[REG_EXC_RETURN] & EXC_RETURN_THREAD_MODE)
|
||||
{
|
||||
/* Restore the cpu lock */
|
||||
tcb = this_task();
|
||||
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
/* Record the new "running" task when context switch occurred.
|
||||
* g_running_tasks[] is only used by assertion logic for reporting
|
||||
* crashes.
|
||||
*/
|
||||
/* Update scheduler parameters */
|
||||
|
||||
g_running_tasks[this_cpu()] = this_task();
|
||||
regs = up_current_regs();
|
||||
}
|
||||
nxsched_suspend_scheduler(g_running_tasks[this_cpu()]);
|
||||
nxsched_resume_scheduler(tcb);
|
||||
|
||||
/* Update the current_regs to NULL. */
|
||||
/* Record the new "running" task when context switch occurred.
|
||||
* g_running_tasks[] is only used by assertion logic for reporting
|
||||
* crashes.
|
||||
*/
|
||||
|
||||
up_set_current_regs(NULL);
|
||||
}
|
||||
g_running_tasks[this_cpu()] = tcb;
|
||||
regs = tcb->xcp.regs;
|
||||
#endif
|
||||
|
||||
/* Clear current regs */
|
||||
|
||||
up_set_current_regs(NULL);
|
||||
|
||||
board_autoled_off(LED_INIRQ);
|
||||
|
||||
return regs;
|
||||
}
|
||||
|
|
|
@ -78,333 +78,60 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
void up_schedule_sigaction(struct tcb_s *tcb)
|
||||
{
|
||||
sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
|
||||
DEBUGASSERT(tcb != NULL && sigdeliver != NULL);
|
||||
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(),
|
||||
this_task()->xcp.regs);
|
||||
|
||||
/* Refuse to handle nested signal actions */
|
||||
/* First, handle some special cases when the signal is
|
||||
* being delivered to the currently executing task.
|
||||
*/
|
||||
|
||||
if (tcb->xcp.sigdeliver == NULL)
|
||||
if (tcb == this_task() && !up_interrupt_context())
|
||||
{
|
||||
tcb->xcp.sigdeliver = sigdeliver;
|
||||
|
||||
/* First, handle some special cases when the signal is being delivered
|
||||
* to the currently executing task.
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handle will run in a critical section!
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb == this_task())
|
||||
{
|
||||
/* CASE 1: We are not in an interrupt handler and a task is
|
||||
* signaling itself for some reason.
|
||||
*/
|
||||
|
||||
if (!up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handle will run in a critical section!
|
||||
*/
|
||||
|
||||
sigdeliver(tcb);
|
||||
tcb->xcp.sigdeliver = NULL;
|
||||
}
|
||||
|
||||
/* CASE 2: We are in an interrupt handler AND the interrupted
|
||||
* task is the same as the one that must receive the signal, then
|
||||
* we will have to modify the return state as well as the state in
|
||||
* the TCB.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the return PC, CPSR and PRIMASK
|
||||
* registers (and perhaps also the LR). These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
/* And make sure that the saved context in the TCB is the same
|
||||
* as the interrupt return context.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.saved_regs);
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
|
||||
memcpy(up_current_regs(), tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() +
|
||||
XCPTCONTEXT_REGS);
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled. The kernel-space trampoline must run in
|
||||
* privileged thread mode.
|
||||
*/
|
||||
|
||||
up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
up_current_regs()[REG_PRIMASK] = 1;
|
||||
up_current_regs()[REG_XPSR] = ARMV6M_XPSR_T;
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
up_current_regs()[REG_LR] = EXC_RETURN_THREAD;
|
||||
up_current_regs()[REG_EXC_RETURN] = EXC_RETURN_THREAD;
|
||||
up_current_regs()[REG_CONTROL] = getcontrol() &
|
||||
~CONTROL_NPRIV;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, we are (1) signaling a task is not running from an
|
||||
* interrupt handler or (2) we are not in an interrupt handler and the
|
||||
* running task is signaling* some non-running task.
|
||||
(tcb->sigdeliver)(tcb);
|
||||
tcb->sigdeliver = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Save the return PC, CPSR and either the BASEPRI or PRIMASK
|
||||
* registers (and perhaps also the LR). These will be restored
|
||||
* by the signal trampoline after the signal has been delivered.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the return PC, CPSR and PRIMASK
|
||||
* registers (and perhaps also the LR). These will be restored
|
||||
* by the signal trampoline after the signal has been delivered.
|
||||
*/
|
||||
/* Save the current register context location */
|
||||
|
||||
/* Save the current register context location */
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
|
||||
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled. We must already be in privileged thread mode to be
|
||||
* here.
|
||||
*/
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled. We must already be in privileged thread mode to be
|
||||
* here.
|
||||
*/
|
||||
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
tcb->xcp.regs[REG_PRIMASK] = 1;
|
||||
tcb->xcp.regs[REG_XPSR] = ARMV6M_XPSR_T;
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
tcb->xcp.regs[REG_PRIMASK] = 1;
|
||||
tcb->xcp.regs[REG_XPSR] = ARMV6M_XPSR_T;
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD;
|
||||
tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
|
||||
tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD;
|
||||
tcb->xcp.regs[REG_EXC_RETURN] = EXC_RETURN_THREAD;
|
||||
tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* !CONFIG_SMP */
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
{
|
||||
int cpu;
|
||||
int me;
|
||||
|
||||
sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
|
||||
|
||||
/* Refuse to handle nested signal actions */
|
||||
|
||||
if (!tcb->xcp.sigdeliver)
|
||||
{
|
||||
tcb->xcp.sigdeliver = sigdeliver;
|
||||
|
||||
/* First, handle some special cases when the signal is being delivered
|
||||
* to task that is currently executing on any CPU.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb->task_state == TSTATE_TASK_RUNNING)
|
||||
{
|
||||
me = this_cpu();
|
||||
cpu = tcb->cpu;
|
||||
|
||||
/* CASE 1: We are not in an interrupt handler and a task is
|
||||
* signaling itself for some reason.
|
||||
*/
|
||||
|
||||
if (cpu == me && !up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handler will run in a critical section!
|
||||
*/
|
||||
|
||||
sigdeliver(tcb);
|
||||
tcb->xcp.sigdeliver = NULL;
|
||||
}
|
||||
|
||||
/* CASE 2: The task that needs to receive the signal is running.
|
||||
* This could happen if the task is running on another CPU OR if
|
||||
* we are in an interrupt handler and the task is running on this
|
||||
* CPU. In the former case, we will have to PAUSE the other CPU
|
||||
* first. But in either case, we will have to modify the return
|
||||
* state as well as the state in the TCB.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* If we signaling a task running on the other CPU, we have
|
||||
* to PAUSE the other CPU.
|
||||
*/
|
||||
|
||||
if (cpu != me)
|
||||
{
|
||||
/* Pause the CPU */
|
||||
|
||||
up_cpu_pause(cpu);
|
||||
|
||||
/* Now tcb on the other CPU can be accessed safely */
|
||||
|
||||
/* Copy tcb->xcp.regs to tcp.xcp.saved. These will be
|
||||
* restored by the signal trampoline after the signal has
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
/* Save the current register context location */
|
||||
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
|
||||
/* Then set up vector to the trampoline with interrupts
|
||||
* disabled. We must already be in privileged thread mode
|
||||
* to be here.
|
||||
*/
|
||||
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
tcb->xcp.regs[REG_PRIMASK] = 1;
|
||||
tcb->xcp.regs[REG_XPSR] = ARMV6M_XPSR_T;
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD;
|
||||
tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
/* tcb is running on the same CPU */
|
||||
|
||||
/* Save the return PC, CPSR and either the BASEPRI or
|
||||
* PRIMASK registers (and perhaps also the LR). These
|
||||
* will be restored by the signal trampoline after the
|
||||
* signal has been delivered.
|
||||
*/
|
||||
|
||||
/* And make sure that the saved context in the TCB is the
|
||||
* same as the interrupt return context.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.saved_regs);
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
|
||||
memcpy(up_current_regs(), tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
up_current_regs()[REG_SP] = (uint32_t)(up_current_regs()
|
||||
+ XCPTCONTEXT_REGS);
|
||||
|
||||
/* Then set up vector to the trampoline with interrupts
|
||||
* disabled. The kernel-space trampoline must run in
|
||||
* privileged thread mode.
|
||||
*/
|
||||
|
||||
up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
up_current_regs()[REG_PRIMASK] = 1;
|
||||
up_current_regs()[REG_XPSR] = ARMV6M_XPSR_T;
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
up_current_regs()[REG_LR] = EXC_RETURN_THREAD;
|
||||
up_current_regs()[REG_CONTROL] = getcontrol() &
|
||||
~CONTROL_NPRIV;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* NOTE: If the task runs on another CPU(cpu), adjusting
|
||||
* global IRQ controls will be done in the pause handler
|
||||
* on the CPU(cpu) by taking a critical section.
|
||||
* If the task is scheduled on this CPU(me), do nothing
|
||||
* because this CPU already took a critical section
|
||||
*/
|
||||
|
||||
/* RESUME the other CPU if it was PAUSED */
|
||||
|
||||
if (cpu != me)
|
||||
{
|
||||
up_cpu_resume(cpu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, we are (1) signaling a task is not running from an
|
||||
* interrupt handler or (2) we are not in an interrupt handler and the
|
||||
* running task is signaling some other non-running task.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the return PC, CPSR and either the BASEPRI or PRIMASK
|
||||
* registers (and perhaps also the LR). These will be restored
|
||||
* by the signal trampoline after the signal has been delivered.
|
||||
*/
|
||||
|
||||
/* Save the current register context location */
|
||||
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
|
||||
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled. We must already be in privileged thread mode to be
|
||||
* here.
|
||||
*/
|
||||
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
tcb->xcp.regs[REG_PRIMASK] = 1;
|
||||
tcb->xcp.regs[REG_XPSR] = ARMV6M_XPSR_T;
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD;
|
||||
tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_SMP */
|
||||
|
|
|
@ -68,8 +68,8 @@ void arm_sigdeliver(void)
|
|||
board_autoled_on(LED_SIGNAL);
|
||||
|
||||
sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n",
|
||||
rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head);
|
||||
DEBUGASSERT(rtcb->xcp.sigdeliver != NULL);
|
||||
rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head);
|
||||
DEBUGASSERT(rtcb->sigdeliver != NULL);
|
||||
|
||||
retry:
|
||||
#ifdef CONFIG_SMP
|
||||
|
@ -101,7 +101,7 @@ retry:
|
|||
|
||||
/* Deliver the signal */
|
||||
|
||||
((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb);
|
||||
(rtcb->sigdeliver)(rtcb);
|
||||
|
||||
/* Output any debug messages BEFORE restoring errno (because they may
|
||||
* alter errno), then disable interrupts again and restore the original
|
||||
|
@ -148,7 +148,7 @@ retry:
|
|||
* could be modified by a hostile program.
|
||||
*/
|
||||
|
||||
rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */
|
||||
rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */
|
||||
|
||||
/* Then restore the correct state for this thread of
|
||||
* execution.
|
||||
|
|
|
@ -117,10 +117,10 @@ static void dispatch_syscall(void)
|
|||
|
||||
int arm_svcall(int irq, void *context, void *arg)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
uint32_t *regs = (uint32_t *)context;
|
||||
uint32_t cmd;
|
||||
|
||||
DEBUGASSERT(regs && regs == up_current_regs());
|
||||
cmd = regs[REG_R0];
|
||||
|
||||
/* The SVCall software interrupt is called with R0 = system call command
|
||||
|
@ -167,7 +167,7 @@ int arm_svcall(int irq, void *context, void *arg)
|
|||
case SYS_restore_context:
|
||||
{
|
||||
DEBUGASSERT(regs[REG_R1] != 0);
|
||||
up_set_current_regs((uint32_t *)regs[REG_R1]);
|
||||
tcb->xcp.regs = (uint32_t *)regs[REG_R1];
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -192,7 +192,7 @@ int arm_svcall(int irq, void *context, void *arg)
|
|||
{
|
||||
DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
|
||||
*(uint32_t **)regs[REG_R1] = regs;
|
||||
up_set_current_regs((uint32_t *)regs[REG_R2]);
|
||||
tcb->xcp.regs = (uint32_t *)regs[REG_R2];
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -450,23 +450,20 @@ int arm_svcall(int irq, void *context, void *arg)
|
|||
# ifndef CONFIG_DEBUG_SVCALL
|
||||
if (cmd > SYS_switch_context)
|
||||
# else
|
||||
if (regs != up_current_regs())
|
||||
if (regs != tcb->xcp.regs)
|
||||
# endif
|
||||
{
|
||||
regs = (uint32_t *)tcb->xcp.regs;
|
||||
|
||||
svcinfo("SVCall Return:\n");
|
||||
svcinfo(" R0: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
up_current_regs()[REG_R0], up_current_regs()[REG_R1],
|
||||
up_current_regs()[REG_R2], up_current_regs()[REG_R3],
|
||||
up_current_regs()[REG_R4], up_current_regs()[REG_R5],
|
||||
up_current_regs()[REG_R6], up_current_regs()[REG_R7]);
|
||||
regs[REG_R0], regs[REG_R1], regs[REG_R2], regs[REG_R3],
|
||||
regs[REG_R4], regs[REG_R5], regs[REG_R6], regs[REG_R7]);
|
||||
svcinfo(" R8: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
up_current_regs()[REG_R8], up_current_regs()[REG_R9],
|
||||
up_current_regs()[REG_R10], up_current_regs()[REG_R11],
|
||||
up_current_regs()[REG_R12], up_current_regs()[REG_R13],
|
||||
up_current_regs()[REG_R14], up_current_regs()[REG_R15]);
|
||||
svcinfo(" PSR: %08x PRIMASK: %08x EXC_RETURN: %08x\n",
|
||||
up_current_regs()[REG_XPSR], up_current_regs()[REG_PRIMASK],
|
||||
up_current_regs()[REG_EXC_RETURN]);
|
||||
regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11],
|
||||
regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]);
|
||||
svcinfo(" PSR: %08x EXC_RETURN: %08x CONTROL: %08x\n",
|
||||
regs[REG_XPSR], regs[REG_EXC_RETURN], regs[REG_CONTROL]);
|
||||
}
|
||||
# ifdef CONFIG_DEBUG_SVCALL
|
||||
else
|
||||
|
|
87
arch/arm/src/armv6-m/arm_trigger_irq.c
Normal file
87
arch/arm/src/armv6-m/arm_trigger_irq.c
Normal file
|
@ -0,0 +1,87 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/armv6-m/arm_trigger_irq.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <arch/irq.h>
|
||||
|
||||
#include "arm_internal.h"
|
||||
#include "nvic.h"
|
||||
|
||||
#ifdef CONFIG_ARCH_HAVE_IRQTRIGGER
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_trigger_irq
|
||||
*
|
||||
* Description:
|
||||
* Trigger an IRQ by software.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_trigger_irq(int irq, cpu_set_t cpuset)
|
||||
{
|
||||
uint32_t pend_bit = 0;
|
||||
|
||||
DEBUGASSERT(irq >= NVIC_IRQ_NMI && irq < NR_IRQS);
|
||||
|
||||
if (irq >= NVIC_IRQ_FIRST)
|
||||
{
|
||||
putreg32(irq - NVIC_IRQ_FIRST, ARMV6M_NVIC2_BASE);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (irq)
|
||||
{
|
||||
case NVIC_IRQ_PENDSV:
|
||||
pend_bit = SYSCON_ICSR_PENDSVSET;
|
||||
break;
|
||||
|
||||
case NVIC_IRQ_NMI:
|
||||
pend_bit = SYSCON_ICSR_NMIPENDSET;
|
||||
break;
|
||||
|
||||
case NVIC_IRQ_SYSTICK:
|
||||
pend_bit = SYSCON_ICSR_PENDSTSET;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (pend_bit)
|
||||
{
|
||||
modifyreg32(ARMV6M_SYSCON_ICSR, 0, pend_bit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARCH_HAVE_IRQTRIGGER */
|
|
@ -45,6 +45,8 @@
|
|||
|
||||
#include "chip.h"
|
||||
#include "arm_internal.h"
|
||||
#include "ram_vectors.h"
|
||||
#include "nvic.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
@ -81,6 +83,7 @@ static void start(void)
|
|||
/* Common exception entrypoint */
|
||||
|
||||
extern void exception_common(void);
|
||||
extern void exception_direct(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Public data
|
||||
|
@ -92,7 +95,7 @@ extern void exception_common(void);
|
|||
* As all exceptions (interrupts) are routed via exception_common, we just
|
||||
* need to fill this array with pointers to it.
|
||||
*
|
||||
* Note that the [ ... ] designated initialiser is a GCC extension.
|
||||
* Note that the [ ... ] designated initializer is a GCC extension.
|
||||
*/
|
||||
|
||||
const void * const _vectors[] locate_data(".vectors") =
|
||||
|
@ -107,5 +110,7 @@ const void * const _vectors[] locate_data(".vectors") =
|
|||
|
||||
/* Vectors 2 - n point directly at the generic handler */
|
||||
|
||||
[2 ... (15 + ARMV6M_PERIPHERAL_INTERRUPTS)] = exception_common
|
||||
[2 ... NVIC_IRQ_PENDSV] = &exception_common,
|
||||
[(NVIC_IRQ_PENDSV + 1) ... (15 + ARMV6M_PERIPHERAL_INTERRUPTS)]
|
||||
= &exception_direct
|
||||
};
|
||||
|
|
|
@ -32,6 +32,31 @@
|
|||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Exception/interrupt vector numbers ***************************************/
|
||||
|
||||
/* Vector 0: Reset stack
|
||||
* pointer value
|
||||
*/
|
||||
|
||||
/* Vector 1: Reset */
|
||||
#define NVIC_IRQ_NMI (2) /* Vector 2: Non-Maskable Interrupt (NMI) */
|
||||
#define NVIC_IRQ_HARDFAULT (3) /* Vector 3: Hard fault */
|
||||
#define NVIC_IRQ_MEMFAULT (4) /* Vector 4: Memory management (MPU) */
|
||||
#define NVIC_IRQ_BUSFAULT (5) /* Vector 5: Bus fault */
|
||||
#define NVIC_IRQ_USAGEFAULT (6) /* Vector 6: Usage fault */
|
||||
/* Vectors 7-10: Reserved */
|
||||
#define NVIC_IRQ_SVCALL (11) /* Vector 11: SVC call */
|
||||
#define NVIC_IRQ_DBGMONITOR (12) /* Vector 12: Debug Monitor */
|
||||
/* Vector 13: Reserved */
|
||||
#define NVIC_IRQ_PENDSV (14) /* Vector 14: Pendable system service request */
|
||||
#define NVIC_IRQ_SYSTICK (15) /* Vector 15: System tick */
|
||||
|
||||
/* External interrupts (vectors >= 16).
|
||||
* These definitions are chip-specific
|
||||
*/
|
||||
|
||||
#define NVIC_IRQ_FIRST (16) /* Vector number of the first interrupt */
|
||||
|
||||
/* Base addresses ***********************************************************/
|
||||
|
||||
#define ARMV6M_SYSCON1_BASE 0xe000e008 /* 0xe000e008-0xe000e00f System Control Block */
|
||||
|
|
|
@ -52,6 +52,10 @@ if(CONFIG_ARCH_PERF_EVENTS)
|
|||
list(APPEND SRCS arm_perf.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_ARMV7A_GICv2M)
|
||||
list(APPEND SRCS arm_gicv2m.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_ARMV7A_HAVE_PTM)
|
||||
list(APPEND SRCS arm_timer.c)
|
||||
endif()
|
||||
|
@ -105,7 +109,7 @@ if(CONFIG_ARCH_FPU)
|
|||
endif()
|
||||
|
||||
if(CONFIG_SMP)
|
||||
list(APPEND SRCS arm_cpustart.c arm_cpupause.c arm_cpuidlestack.c arm_scu.c)
|
||||
list(APPEND SRCS arm_cpustart.c arm_smpcall.c arm_cpuidlestack.c arm_scu.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_ARCH_HAVE_PSCI)
|
||||
|
|
|
@ -24,6 +24,17 @@ config ARMV7A_GIC_EOIMODE
|
|||
Enable GICC_CTLR.EOImode, this will separates the priority drop and interrupt
|
||||
deactivation operations.
|
||||
|
||||
config ARMV7A_GICV2_LEGACY_IRQ0
|
||||
int "pci legacy irq0 default val"
|
||||
default 35
|
||||
---help---
|
||||
The qemu pci lagacy irq0 default is 35. -1 mean disable
|
||||
|
||||
config ARMV7A_GICv2M
|
||||
bool "gic support msi irq"
|
||||
depends on PCI_MSIX
|
||||
default n
|
||||
|
||||
endif # ARMV7A_HAVE_GICv2
|
||||
|
||||
config ARMV7A_HAVE_GTM
|
||||
|
|
|
@ -47,7 +47,11 @@ CMN_CSRCS += arm_schedulesigaction.c arm_sigdeliver.c
|
|||
CMN_CSRCS += arm_syscall.c arm_tcbinfo.c arm_undefinedinsn.c
|
||||
CMN_CSRCS += arm_perf.c cp15_cacheops.c
|
||||
|
||||
ifeq ($(CONFIG_ARMV7A_HAVE_PTM), y)
|
||||
ifeq ($(CONFIG_ARMV7A_GICv2M),y)
|
||||
CMN_CSRCS += arm_gicv2m.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARMV7A_HAVE_PTM),y)
|
||||
CMN_CSRCS += arm_timer.c
|
||||
endif
|
||||
|
||||
|
@ -90,7 +94,7 @@ ifeq ($(CONFIG_ARCH_FPU),y)
|
|||
endif
|
||||
|
||||
ifeq ($(CONFIG_SMP),y)
|
||||
CMN_CSRCS += arm_cpustart.c arm_cpupause.c arm_cpuidlestack.c
|
||||
CMN_CSRCS += arm_cpustart.c arm_smpcall.c arm_cpuidlestack.c
|
||||
CMN_CSRCS += arm_scu.c
|
||||
endif
|
||||
|
||||
|
|
|
@ -1,381 +0,0 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/armv7-a/arm_cpupause.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/sched.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/sched_note.h>
|
||||
|
||||
#include "arm_internal.h"
|
||||
#include "gic.h"
|
||||
#include "sched/sched.h"
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* These spinlocks are used in the SMP configuration in order to implement
|
||||
* up_cpu_pause(). The protocol for CPUn to pause CPUm is as follows
|
||||
*
|
||||
* 1. The up_cpu_pause() implementation on CPUn locks both g_cpu_wait[m]
|
||||
* and g_cpu_paused[m]. CPUn then waits spinning on g_cpu_paused[m].
|
||||
* 2. CPUm receives the interrupt it (1) unlocks g_cpu_paused[m] and
|
||||
* (2) locks g_cpu_wait[m]. The first unblocks CPUn and the second
|
||||
* blocks CPUm in the interrupt handler.
|
||||
*
|
||||
* When CPUm resumes, CPUn unlocks g_cpu_wait[m] and the interrupt handler
|
||||
* on CPUm continues. CPUm must, of course, also then unlock g_cpu_wait[m]
|
||||
* so that it will be ready for the next pause operation.
|
||||
*/
|
||||
|
||||
static volatile spinlock_t g_cpu_wait[CONFIG_SMP_NCPUS];
|
||||
static volatile spinlock_t g_cpu_paused[CONFIG_SMP_NCPUS];
|
||||
static volatile spinlock_t g_cpu_resumed[CONFIG_SMP_NCPUS];
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_pausereq
|
||||
*
|
||||
* Description:
|
||||
* Return true if a pause request is pending for this CPU.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cpu - The index of the CPU to be queried
|
||||
*
|
||||
* Returned Value:
|
||||
* true = a pause request is pending.
|
||||
* false = no pasue request is pending.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
bool up_cpu_pausereq(int cpu)
|
||||
{
|
||||
return spin_is_locked(&g_cpu_paused[cpu]);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_save
|
||||
*
|
||||
* Description:
|
||||
* Handle a pause request from another CPU. Normally, this logic is
|
||||
* executed from interrupt handling logic within the architecture-specific
|
||||
* However, it is sometimes necessary to perform the pending
|
||||
* pause operation in other contexts where the interrupt cannot be taken
|
||||
* in order to avoid deadlocks.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_save(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(tcb);
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we are paused */
|
||||
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at current_regs into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.regs);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused
|
||||
*
|
||||
* Description:
|
||||
* Handle a pause request from another CPU. Normally, this logic is
|
||||
* executed from interrupt handling logic within the architecture-specific
|
||||
* However, it is sometimes necessary to perform the pending
|
||||
* pause operation in other contexts where the interrupt cannot be taken
|
||||
* in order to avoid deadlocks.
|
||||
*
|
||||
* This function performs the following operations:
|
||||
*
|
||||
* 1. It saves the current task state at the head of the current assigned
|
||||
* task list.
|
||||
* 2. It waits on a spinlock, then
|
||||
* 3. Returns from interrupt, restoring the state of the new task at the
|
||||
* head of the ready to run list.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cpu - The index of the CPU to be paused
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused(int cpu)
|
||||
{
|
||||
/* Release the g_cpu_paused spinlock to synchronize with the
|
||||
* requesting CPU.
|
||||
*/
|
||||
|
||||
spin_unlock(&g_cpu_paused[cpu]);
|
||||
|
||||
/* Ensure the CPU has been resumed to avoid causing a deadlock */
|
||||
|
||||
spin_lock(&g_cpu_resumed[cpu]);
|
||||
|
||||
/* Wait for the spinlock to be released. The requesting CPU will release
|
||||
* the spinlock when the CPU is resumed.
|
||||
*/
|
||||
|
||||
spin_lock(&g_cpu_wait[cpu]);
|
||||
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_restore
|
||||
*
|
||||
* Description:
|
||||
* Restore the state of the CPU after it was paused via up_cpu_pause(),
|
||||
* and resume normal tasking.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_restore(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we have resumed */
|
||||
|
||||
sched_note_cpu_resumed(tcb);
|
||||
#endif
|
||||
|
||||
/* Reset scheduler parameters */
|
||||
|
||||
nxsched_resume_scheduler(tcb);
|
||||
|
||||
/* Then switch contexts. Any necessary address environment changes
|
||||
* will be made when the interrupt returns.
|
||||
*/
|
||||
|
||||
arm_restorestate(tcb->xcp.regs);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_pause_handler
|
||||
*
|
||||
* Description:
|
||||
* This is the handler for SGI2. It performs the following operations:
|
||||
*
|
||||
* 1. It saves the current task state at the head of the current assigned
|
||||
* task list.
|
||||
* 2. It waits on a spinlock, then
|
||||
* 3. Returns from interrupt, restoring the state of the new task at the
|
||||
* head of the ready to run list.
|
||||
*
|
||||
* Input Parameters:
|
||||
* Standard interrupt handling
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int arm_pause_handler(int irq, void *context, void *arg)
|
||||
{
|
||||
int cpu = this_cpu();
|
||||
|
||||
/* Check for false alarms. Such false could occur as a consequence of
|
||||
* some deadlock breaking logic that might have already serviced the SG2
|
||||
* interrupt by calling up_cpu_paused(). If the pause event has already
|
||||
* been processed then g_cpu_paused[cpu] will not be locked.
|
||||
*/
|
||||
|
||||
if (up_cpu_pausereq(cpu))
|
||||
{
|
||||
/* NOTE: The following enter_critical_section() will call
|
||||
* up_cpu_paused() to process a pause request to break a deadlock
|
||||
* because the caller held a critical section. Once up_cpu_paused()
|
||||
* finished, the caller will proceed and release the g_cpu_irqlock.
|
||||
* Then this CPU will acquire g_cpu_irqlock in the function.
|
||||
*/
|
||||
|
||||
irqstate_t flags = enter_critical_section();
|
||||
|
||||
/* NOTE: the pause request should not exist here */
|
||||
|
||||
DEBUGVERIFY(!up_cpu_pausereq(cpu));
|
||||
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_pause
|
||||
*
|
||||
* Description:
|
||||
* Save the state of the current task at the head of the
|
||||
* g_assignedtasks[cpu] task list and then pause task execution on the
|
||||
* CPU.
|
||||
*
|
||||
* This function is called by the OS when the logic executing on one CPU
|
||||
* needs to modify the state of the g_assignedtasks[cpu] list for another
|
||||
* CPU.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cpu - The index of the CPU to be stopped
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_pause(int cpu)
|
||||
{
|
||||
DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify of the pause event */
|
||||
|
||||
sched_note_cpu_pause(this_task(), cpu);
|
||||
#endif
|
||||
|
||||
/* Take the both spinlocks. The g_cpu_wait spinlock will prevent the SGI2
|
||||
* handler from returning until up_cpu_resume() is called; g_cpu_paused
|
||||
* is a handshake that will prefent this function from returning until
|
||||
* the CPU is actually paused.
|
||||
* Note that we might spin before getting g_cpu_wait, this just means that
|
||||
* the other CPU still hasn't finished responding to the previous resume
|
||||
* request.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(!spin_is_locked(&g_cpu_paused[cpu]));
|
||||
|
||||
spin_lock(&g_cpu_wait[cpu]);
|
||||
spin_lock(&g_cpu_paused[cpu]);
|
||||
|
||||
/* Execute SGI2 */
|
||||
|
||||
arm_cpu_sgi(GIC_SMP_CPUPAUSE, (1 << cpu));
|
||||
|
||||
/* Wait for the other CPU to unlock g_cpu_paused meaning that
|
||||
* it is fully paused and ready for up_cpu_resume();
|
||||
*/
|
||||
|
||||
spin_lock(&g_cpu_paused[cpu]);
|
||||
spin_unlock(&g_cpu_paused[cpu]);
|
||||
|
||||
/* On successful return g_cpu_wait will be locked, the other CPU will be
|
||||
* spinning on g_cpu_wait and will not continue until g_cpu_resume() is
|
||||
* called. g_cpu_paused will be unlocked in any case.
|
||||
*/
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_resume
|
||||
*
|
||||
* Description:
|
||||
* Restart the cpu after it was paused via up_cpu_pause(), restoring the
|
||||
* state of the task at the head of the g_assignedtasks[cpu] list, and
|
||||
* resume normal tasking.
|
||||
*
|
||||
* This function is called after up_cpu_pause in order resume operation of
|
||||
* the CPU after modifying its g_assignedtasks[cpu] list.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cpu - The index of the CPU being re-started.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_resume(int cpu)
|
||||
{
|
||||
DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify of the resume event */
|
||||
|
||||
sched_note_cpu_resume(this_task(), cpu);
|
||||
#endif
|
||||
|
||||
/* Release the spinlock. Releasing the spinlock will cause the SGI2
|
||||
* handler on 'cpu' to continue and return from interrupt to the newly
|
||||
* established thread.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(spin_is_locked(&g_cpu_wait[cpu]) &&
|
||||
!spin_is_locked(&g_cpu_paused[cpu]));
|
||||
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
|
||||
/* Ensure the CPU has been resumed to avoid causing a deadlock */
|
||||
|
||||
spin_lock(&g_cpu_resumed[cpu]);
|
||||
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SMP */
|
|
@ -79,18 +79,8 @@ int arm_start_handler(int irq, void *context, void *arg)
|
|||
|
||||
nxsched_resume_scheduler(tcb);
|
||||
|
||||
/* Dump registers so that we can see what is going to happen on return */
|
||||
UNUSED(tcb);
|
||||
|
||||
#if 0
|
||||
up_dump_register(tcb->xcp.regs);
|
||||
#endif
|
||||
|
||||
/* Then switch contexts. This instantiates the exception context of the
|
||||
* tcb at the head of the assigned task list. In this case, this should
|
||||
* be the CPUs NULL task.
|
||||
*/
|
||||
|
||||
arm_restorestate(tcb->xcp.regs);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,8 @@
|
|||
|
||||
uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
board_autoled_on(LED_INIRQ);
|
||||
#ifdef CONFIG_SUPPRESS_INTERRUPTS
|
||||
PANIC();
|
||||
|
@ -61,6 +63,18 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
|||
|
||||
DEBUGASSERT(up_current_regs() == NULL);
|
||||
|
||||
/* if irq == GIC_SMP_CPUSTART
|
||||
* We are initiating the multi-core jumping state to up_idle,
|
||||
* and we will use this_task(). Therefore, it cannot be overridden.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
if (irq != GIC_SMP_CPUSTART)
|
||||
#endif
|
||||
{
|
||||
tcb->xcp.regs = regs;
|
||||
}
|
||||
|
||||
/* Current regs non-zero indicates that we are processing an interrupt;
|
||||
* current_regs is also used to manage interrupt level context switches.
|
||||
*/
|
||||
|
@ -70,10 +84,9 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
|||
/* Deliver the IRQ */
|
||||
|
||||
irq_dispatch(irq, regs);
|
||||
tcb = this_task();
|
||||
|
||||
/* Restore the cpu lock */
|
||||
|
||||
if (regs != up_current_regs())
|
||||
if (regs != tcb->xcp.regs)
|
||||
{
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
/* Make sure that the address environment for the previously
|
||||
|
@ -85,13 +98,18 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
|||
addrenv_switch(NULL);
|
||||
#endif
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(g_running_tasks[this_cpu()]);
|
||||
nxsched_resume_scheduler(tcb);
|
||||
|
||||
/* Record the new "running" task when context switch occurred.
|
||||
* g_running_tasks[] is only used by assertion logic for reporting
|
||||
* crashes.
|
||||
*/
|
||||
|
||||
g_running_tasks[this_cpu()] = this_task();
|
||||
regs = up_current_regs();
|
||||
g_running_tasks[this_cpu()] = tcb;
|
||||
regs = tcb->xcp.regs;
|
||||
}
|
||||
|
||||
/* Set current_regs to NULL to indicate that we are no longer in an
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <errno.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/pci/pci.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <arch/irq.h>
|
||||
|
||||
|
@ -210,13 +211,16 @@ void arm_gic0_initialize(void)
|
|||
putreg32(0x01010101, GIC_ICDIPTR(irq)); /* SPI on CPU0 */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARMV7A_GICv2M
|
||||
gic_v2m_initialize();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* Attach SGI interrupt handlers. This attaches the handler to all CPUs. */
|
||||
|
||||
DEBUGVERIFY(irq_attach(GIC_SMP_CPUSTART, arm_start_handler, NULL));
|
||||
DEBUGVERIFY(irq_attach(GIC_SMP_CPUPAUSE, arm_pause_handler, NULL));
|
||||
DEBUGVERIFY(irq_attach(GIC_SMP_CPUCALL,
|
||||
nxsched_smp_call_handler, NULL));
|
||||
DEBUGVERIFY(irq_attach(GIC_SMP_SCHED, arm_smp_sched_handler, NULL));
|
||||
DEBUGVERIFY(irq_attach(GIC_SMP_CALL, nxsched_smp_call_handler, NULL));
|
||||
#endif
|
||||
|
||||
arm_gic_dump("Exit arm_gic0_initialize", true, 0);
|
||||
|
@ -749,24 +753,27 @@ void arm_cpu_sgi(int sgi, unsigned int cpuset)
|
|||
putreg32(regval, GIC_ICDSGIR);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/****************************************************************************
|
||||
* Name: up_send_smp_call
|
||||
* Name: up_get_legacy_irq
|
||||
*
|
||||
* Description:
|
||||
* Send smp call to target cpu.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cpuset - The set of CPUs to receive the SGI.
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
* Reserve vector for legacy
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_send_smp_call(cpu_set_t cpuset)
|
||||
int up_get_legacy_irq(uint32_t devfn, uint8_t line, uint8_t pin)
|
||||
{
|
||||
up_trigger_irq(GIC_SMP_CPUCALL, cpuset);
|
||||
}
|
||||
#if CONFIG_ARMV7A_GICV2_LEGACY_IRQ0 >= 0
|
||||
uint8_t slot;
|
||||
uint8_t tmp;
|
||||
|
||||
UNUSED(line);
|
||||
slot = PCI_SLOT(devfn);
|
||||
tmp = (pin - 1 + slot) % 4;
|
||||
return CONFIG_ARMV7A_GICV2_LEGACY_IRQ0 + tmp;
|
||||
#else
|
||||
return -ENOTSUP;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARMV7A_HAVE_GICv2 */
|
||||
|
|
139
arch/arm/src/armv7-a/arm_gicv2m.c
Normal file
139
arch/arm/src/armv7-a/arm_gicv2m.c
Normal file
|
@ -0,0 +1,139 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/armv7-a/arm_gicv2m.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/bits.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/pci/pci.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include "arm_internal.h"
|
||||
#include "gic.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct gic_v2m_s
|
||||
{
|
||||
spinlock_t lock;
|
||||
uint32_t spi_start;
|
||||
uint32_t spi_number;
|
||||
unsigned long *spi_bitmap;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static struct gic_v2m_s g_v2m =
|
||||
{
|
||||
SP_LOCKED
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static bool is_valid_spi(uint32_t base, uint32_t number)
|
||||
{
|
||||
if (base < GIC_IRQ_SPI)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (number == 0 || base + number > NR_IRQS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
int gic_v2m_initialize(void)
|
||||
{
|
||||
uint32_t typer;
|
||||
|
||||
typer = getreg32(GIC_V2MTYPER);
|
||||
g_v2m.spi_start = GIC_V2MTYPES_BASE(typer);
|
||||
g_v2m.spi_number = GIC_V2MTYPES_NUMBER(typer);
|
||||
|
||||
if (!is_valid_spi(g_v2m.spi_start, g_v2m.spi_number))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
g_v2m.spi_bitmap = kmm_zalloc(BITS_TO_LONGS(g_v2m.spi_number));
|
||||
if (g_v2m.spi_bitmap == NULL)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int up_alloc_irq_msi(int *num)
|
||||
{
|
||||
irqstate_t flags;
|
||||
int offset;
|
||||
int irq;
|
||||
int i;
|
||||
|
||||
flags = spin_lock_irqsave(&g_v2m.lock);
|
||||
offset = bitmap_find_free_region(g_v2m.spi_bitmap, g_v2m.spi_number, *num);
|
||||
spin_unlock_irqrestore(&g_v2m.lock, flags);
|
||||
irq = g_v2m.spi_start + offset;
|
||||
for (i = 0; i < *num; i++)
|
||||
{
|
||||
arm_gic_irq_trigger(i + irq, true);
|
||||
}
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
void up_release_irq_msi(int *irq, int num)
|
||||
{
|
||||
irqstate_t flags;
|
||||
|
||||
flags = spin_lock_irqsave(&g_v2m.lock);
|
||||
bitmap_release_region(g_v2m.spi_bitmap, *irq - g_v2m.spi_start, num);
|
||||
spin_unlock_irqrestore(&g_v2m.lock, flags);
|
||||
}
|
||||
|
||||
int up_connect_irq(int *irq, int num,
|
||||
uintptr_t *mar, uint32_t *mdr)
|
||||
{
|
||||
*mar = GIC_V2MSETSPI;
|
||||
*mdr = *irq;
|
||||
return 0;
|
||||
}
|
|
@ -77,324 +77,56 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
void up_schedule_sigaction(struct tcb_s *tcb)
|
||||
{
|
||||
sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
|
||||
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(),
|
||||
this_task()->xcp.regs);
|
||||
|
||||
/* Refuse to handle nested signal actions */
|
||||
/* First, handle some special cases when the signal is
|
||||
* being delivered to the currently executing task.
|
||||
*/
|
||||
|
||||
if (!tcb->xcp.sigdeliver)
|
||||
if (tcb == this_task() && !up_interrupt_context())
|
||||
{
|
||||
tcb->xcp.sigdeliver = sigdeliver;
|
||||
|
||||
/* First, handle some special cases when the signal is being delivered
|
||||
* to task that is currently executing on this CPU.
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handler will run in a critical section!
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb == this_task())
|
||||
{
|
||||
/* CASE 1: We are not in an interrupt handler and a task is
|
||||
* signaling itself for some reason.
|
||||
*/
|
||||
|
||||
if (!up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handler will run in a critical section!
|
||||
*/
|
||||
|
||||
sigdeliver(tcb);
|
||||
tcb->xcp.sigdeliver = NULL;
|
||||
}
|
||||
|
||||
/* CASE 2: We are in an interrupt handler AND the interrupted
|
||||
* task is the same as the one that must receive the signal, then
|
||||
* we will have to modify the return state as well as the state
|
||||
* in the TCB.
|
||||
*
|
||||
* Hmmm... there looks like a latent bug here: The following logic
|
||||
* would fail in the strange case where we are in an interrupt
|
||||
* handler, the thread is signaling itself, but a context switch
|
||||
* to another task has occurred so that current_regs does not
|
||||
* refer to the thread of this_task()!
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the return lr and cpsr and one scratch register
|
||||
* These will be restored by the signal trampoline after
|
||||
* the signals have been delivered.
|
||||
*/
|
||||
|
||||
/* And make sure that the saved context in the TCB is the same
|
||||
* as the interrupt return context.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.saved_regs);
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
|
||||
|
||||
memcpy(up_current_regs(), tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() +
|
||||
XCPTCONTEXT_REGS);
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
up_current_regs()[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
up_current_regs()[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, we are (1) signaling a task is not running from an
|
||||
* interrupt handler or (2) we are not in an interrupt handler and the
|
||||
* running task is signaling some other non-running task.
|
||||
(tcb->sigdeliver)(tcb);
|
||||
tcb->sigdeliver = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Save the return lr and cpsr and one scratch register. These
|
||||
* will be restored by the signal trampoline after the signals
|
||||
* have been delivered.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the return lr and cpsr and one scratch register. These
|
||||
* will be restored by the signal trampoline after the signals
|
||||
* have been delivered.
|
||||
*/
|
||||
/* Save the current register context location */
|
||||
|
||||
/* Save the current register context location */
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
|
||||
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT);
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
||||
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* !CONFIG_SMP */
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
{
|
||||
int cpu;
|
||||
int me;
|
||||
|
||||
sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
|
||||
|
||||
/* Refuse to handle nested signal actions */
|
||||
|
||||
if (!tcb->xcp.sigdeliver)
|
||||
{
|
||||
tcb->xcp.sigdeliver = sigdeliver;
|
||||
|
||||
/* First, handle some special cases when the signal is being delivered
|
||||
* to task that is currently executing on any CPU.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb->task_state == TSTATE_TASK_RUNNING)
|
||||
{
|
||||
me = this_cpu();
|
||||
cpu = tcb->cpu;
|
||||
|
||||
/* CASE 1: We are not in an interrupt handler and a task is
|
||||
* signaling itself for some reason.
|
||||
*/
|
||||
|
||||
if (cpu == me && !up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handler will run in a critical section!
|
||||
*/
|
||||
|
||||
sigdeliver(tcb);
|
||||
tcb->xcp.sigdeliver = NULL;
|
||||
}
|
||||
|
||||
/* CASE 2: The task that needs to receive the signal is running.
|
||||
* This could happen if the task is running on another CPU OR if
|
||||
* we are in an interrupt handler and the task is running on this
|
||||
* CPU. In the former case, we will have to PAUSE the other CPU
|
||||
* first. But in either case, we will have to modify the return
|
||||
* state as well as the state in the TCB.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* If we signaling a task running on the other CPU, we have
|
||||
* to PAUSE the other CPU.
|
||||
*/
|
||||
|
||||
if (cpu != me)
|
||||
{
|
||||
/* Pause the CPU */
|
||||
|
||||
up_cpu_pause(cpu);
|
||||
|
||||
/* Now tcb on the other CPU can be accessed safely */
|
||||
|
||||
/* Copy tcb->xcp.regs to tcp.xcp.saved. These will be
|
||||
* restored by the signal trampoline after the signal has
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
/* Save the current register context location */
|
||||
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
/* tcb is running on the same CPU */
|
||||
|
||||
/* Save the return PC, CPSR and either the BASEPRI or
|
||||
* PRIMASK registers (and perhaps also the LR). These will
|
||||
* be restored by the signal trampoline after the signal
|
||||
* has been delivered.
|
||||
*/
|
||||
|
||||
/* And make sure that the saved context in the TCB is the
|
||||
* same as the interrupt return context.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.saved_regs);
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
|
||||
memcpy(up_current_regs(), tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
up_current_regs()[REG_SP] = (uint32_t)(up_current_regs()
|
||||
+ XCPTCONTEXT_REGS);
|
||||
|
||||
/* Then set up vector to the trampoline with interrupts
|
||||
* disabled. The kernel-space trampoline must run in
|
||||
* privileged thread mode.
|
||||
*/
|
||||
|
||||
up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
up_current_regs()[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
up_current_regs()[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* NOTE: If the task runs on another CPU(cpu), adjusting
|
||||
* global IRQ controls will be done in the pause handler
|
||||
* on the CPU(cpu) by taking a critical section.
|
||||
* If the task is scheduled on this CPU(me), do nothing
|
||||
* because this CPU already took a critical section
|
||||
*/
|
||||
|
||||
/* RESUME the other CPU if it was PAUSED */
|
||||
|
||||
if (cpu != me)
|
||||
{
|
||||
up_cpu_resume(cpu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, we are (1) signaling a task is not running from an
|
||||
* interrupt handler or (2) we are not in an interrupt handler and the
|
||||
* running task is signaling some other non-running task.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the return lr and cpsr and one scratch register. These
|
||||
* will be restored by the signal trampoline after the signals
|
||||
* have been delivered.
|
||||
*/
|
||||
|
||||
/* Save the current register context location */
|
||||
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
|
||||
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_SMP */
|
||||
|
|
|
@ -68,8 +68,8 @@ void arm_sigdeliver(void)
|
|||
board_autoled_on(LED_SIGNAL);
|
||||
|
||||
sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n",
|
||||
rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head);
|
||||
DEBUGASSERT(rtcb->xcp.sigdeliver != NULL);
|
||||
rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head);
|
||||
DEBUGASSERT(rtcb->sigdeliver != NULL);
|
||||
|
||||
retry:
|
||||
#ifdef CONFIG_SMP
|
||||
|
@ -101,7 +101,7 @@ retry:
|
|||
|
||||
/* Deliver the signal */
|
||||
|
||||
((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb);
|
||||
(rtcb->sigdeliver)(rtcb);
|
||||
|
||||
/* Output any debug messages BEFORE restoring errno (because they may
|
||||
* alter errno), then disable interrupts again and restore the original
|
||||
|
@ -148,7 +148,7 @@ retry:
|
|||
* could be modified by a hostile program.
|
||||
*/
|
||||
|
||||
rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */
|
||||
rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */
|
||||
|
||||
/* Then restore the correct state for this thread of execution. */
|
||||
|
||||
|
|
122
arch/arm/src/armv7-a/arm_smpcall.c
Normal file
122
arch/arm/src/armv7-a/arm_smpcall.c
Normal file
|
@ -0,0 +1,122 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/armv7-a/arm_smpcall.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/sched.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/sched_note.h>
|
||||
|
||||
#include "arm_internal.h"
|
||||
#include "gic.h"
|
||||
#include "sched/sched.h"
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_smp_sched_handler
|
||||
*
|
||||
* Description:
|
||||
* This is the handler for sched.
|
||||
*
|
||||
* 1. It saves the current task state at the head of the current assigned
|
||||
* task list.
|
||||
* 2. It porcess g_delivertasks
|
||||
* 3. Returns from interrupt, restoring the state of the new task at the
|
||||
* head of the ready to run list.
|
||||
*
|
||||
* Input Parameters:
|
||||
* Standard interrupt handling
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int arm_smp_sched_handler(int irq, void *context, void *arg)
|
||||
{
|
||||
int cpu = this_cpu();
|
||||
|
||||
nxsched_process_delivered(cpu);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_send_smp_sched
|
||||
*
|
||||
* Description:
|
||||
* pause task execution on the CPU
|
||||
* check whether there are tasks delivered to specified cpu
|
||||
* and try to run them.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cpu - The index of the CPU to be paused.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
* Assumptions:
|
||||
* Called from within a critical section;
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_send_smp_sched(int cpu)
|
||||
{
|
||||
arm_cpu_sgi(GIC_SMP_SCHED, (1 << cpu));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_send_smp_call
|
||||
*
|
||||
* Description:
|
||||
* Send smp call to target cpu.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cpuset - The set of CPUs to receive the SGI.
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_send_smp_call(cpu_set_t cpuset)
|
||||
{
|
||||
up_trigger_irq(GIC_SMP_CALL, cpuset);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SMP */
|
|
@ -160,7 +160,7 @@ static void dispatch_syscall(void)
|
|||
|
||||
uint32_t *arm_syscall(uint32_t *regs)
|
||||
{
|
||||
struct tcb_s *tcb;
|
||||
struct tcb_s *tcb = this_task();
|
||||
uint32_t cmd;
|
||||
int cpu;
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
|
@ -171,6 +171,8 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||
|
||||
DEBUGASSERT(up_current_regs() == NULL);
|
||||
|
||||
tcb->xcp.regs = regs;
|
||||
|
||||
/* Current regs non-zero indicates that we are processing an interrupt;
|
||||
* current_regs is also used to manage interrupt level context switches.
|
||||
*/
|
||||
|
@ -272,7 +274,7 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||
* set will determine the restored context.
|
||||
*/
|
||||
|
||||
up_set_current_regs((uint32_t *)regs[REG_R1]);
|
||||
tcb->xcp.regs = (uint32_t *)regs[REG_R1];
|
||||
DEBUGASSERT(up_current_regs());
|
||||
}
|
||||
break;
|
||||
|
@ -298,7 +300,7 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||
{
|
||||
DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
|
||||
*(uint32_t **)regs[REG_R1] = regs;
|
||||
up_set_current_regs((uint32_t *)regs[REG_R2]);
|
||||
tcb->xcp.regs = (uint32_t *)regs[REG_R2];
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -428,7 +430,7 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||
|
||||
/* Copy "info" into user stack */
|
||||
|
||||
if (rtcb->xcp.sigdeliver)
|
||||
if (rtcb->sigdeliver)
|
||||
{
|
||||
usp = rtcb->xcp.saved_regs[REG_SP];
|
||||
}
|
||||
|
@ -565,15 +567,9 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||
break;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
/* Check for a context switch. If a context switch occurred, then
|
||||
* current_regs will have a different value than it did on entry. If an
|
||||
* interrupt level context switch has occurred, then establish the correct
|
||||
* address environment before returning from the interrupt.
|
||||
*/
|
||||
|
||||
if (regs != up_current_regs())
|
||||
if (regs != tcb->xcp.regs)
|
||||
{
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
/* Make sure that the address environment for the previously
|
||||
* running task is closed down gracefully (data caches dump,
|
||||
* MMU flushed) and set up the address environment for the new
|
||||
|
@ -581,25 +577,26 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||
*/
|
||||
|
||||
addrenv_switch(NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Restore the cpu lock */
|
||||
cpu = this_cpu();
|
||||
tcb = current_task(cpu);
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(g_running_tasks[cpu]);
|
||||
nxsched_resume_scheduler(tcb);
|
||||
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
/* Record the new "running" task. g_running_tasks[] is only used by
|
||||
* assertion logic for reporting crashes.
|
||||
*/
|
||||
|
||||
cpu = this_cpu();
|
||||
tcb = current_task(cpu);
|
||||
g_running_tasks[cpu] = tcb;
|
||||
|
||||
/* Restore the cpu lock */
|
||||
|
||||
restore_critical_section(tcb, cpu);
|
||||
regs = up_current_regs();
|
||||
regs = tcb->xcp.regs;
|
||||
}
|
||||
|
||||
/* Report what happened */
|
||||
|
|
|
@ -136,6 +136,11 @@
|
|||
/* 0x0020-0x003c: Implementation defined */
|
||||
/* 0x0040-0x007c: Reserved */
|
||||
|
||||
/* V2M Registers */
|
||||
|
||||
#define GIC_V2MTYPER_OFFSET 0x008
|
||||
#define GIC_V2MSETSPI_OFFSET 0x040
|
||||
|
||||
/* Interrupt Security Registers: 0x0080-0x009c */
|
||||
|
||||
#define GIC_ICDISR_OFFSET(n) (0x0080 + GIC_OFFSET32(n))
|
||||
|
@ -277,6 +282,11 @@
|
|||
#define GIC_ICDPIDR(n) (MPCORE_ICD_VBASE+GIC_ICDPIDR_OFFSET(n))
|
||||
#define GIC_ICDCIDR(n) (MPCORE_ICD_VBASE+GIC_ICDCIDR_OFFSET(n))
|
||||
|
||||
/* V2M Registers */
|
||||
|
||||
#define GIC_V2MTYPER (MPCORE_V2M_VBASE + GIC_V2MTYPER_OFFSET)
|
||||
#define GIC_V2MSETSPI (MPCORE_V2M_VBASE + GIC_V2MSETSPI_OFFSET)
|
||||
|
||||
/* GIC Register Bit Definitions *********************************************/
|
||||
|
||||
/* CPU Interface registers */
|
||||
|
@ -557,6 +567,14 @@
|
|||
# define GIC_ICDSGIR_TGTFILTER_THIS (2 << GIC_ICDSGIR_TGTFILTER_SHIFT) /* Interrupt is sent to requesting CPU only */
|
||||
/* Bits 26-31: Reserved */
|
||||
|
||||
/* V2M Registers */
|
||||
|
||||
#define GIC_V2MTYPES_BASE_SHIFT 16
|
||||
#define GIC_V2MTYPES_BASE_MASK 0x3FF
|
||||
#define GIC_V2MTYPES_NUMBER_MASK 0x3FF
|
||||
#define GIC_V2MTYPES_BASE(x) (((x) >> GIC_V2MTYPES_BASE_SHIFT) & GIC_V2MTYPES_BASE_MASK)
|
||||
#define GIC_V2MTYPES_NUMBER(x) ((x) & GIC_V2MTYPES_NUMBER_MASK)
|
||||
|
||||
/* Interrupt IDs ************************************************************/
|
||||
|
||||
/* The Global Interrupt Controller (GIC) collects up to 224 interrupt
|
||||
|
@ -617,12 +635,12 @@
|
|||
|
||||
#ifdef CONFIG_ARCH_TRUSTZONE_SECURE
|
||||
# define GIC_SMP_CPUSTART GIC_IRQ_SGI9
|
||||
# define GIC_SMP_CPUPAUSE GIC_IRQ_SGI10
|
||||
# define GIC_SMP_CPUCALL GIC_IRQ_SGI11
|
||||
# define GIC_SMP_CALL GIC_IRQ_SGI10
|
||||
# define GIC_SMP_SCHED GIC_IRQ_SGI11
|
||||
#else
|
||||
# define GIC_SMP_CPUSTART GIC_IRQ_SGI1
|
||||
# define GIC_SMP_CPUPAUSE GIC_IRQ_SGI2
|
||||
# define GIC_SMP_CPUCALL GIC_IRQ_SGI3
|
||||
# define GIC_SMP_CALL GIC_IRQ_SGI2
|
||||
# define GIC_SMP_SCHED GIC_IRQ_SGI3
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -816,14 +834,14 @@ int arm_start_handler(int irq, void *context, void *arg);
|
|||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_pause_handler
|
||||
* Name: arm_smp_sched_handler
|
||||
*
|
||||
* Description:
|
||||
* This is the handler for SGI2. It performs the following operations:
|
||||
* This is the handler for sched.
|
||||
*
|
||||
* 1. It saves the current task state at the head of the current assigned
|
||||
* task list.
|
||||
* 2. It waits on a spinlock, then
|
||||
* 2. It porcess g_delivertasks
|
||||
* 3. Returns from interrupt, restoring the state of the new task at the
|
||||
* head of the ready to run list.
|
||||
*
|
||||
|
@ -836,9 +854,8 @@ int arm_start_handler(int irq, void *context, void *arg);
|
|||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
int arm_pause_handler(int irq, void *context, void *arg);
|
||||
int arm_smp_sched_handler(int irq, void *context, void *arg);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_gic_dump
|
||||
*
|
||||
|
@ -861,6 +878,10 @@ void arm_gic_dump(const char *msg, bool all, int irq);
|
|||
# define arm_gic_dump(msg, all, irq)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARMV7A_GICv2M
|
||||
int gic_v2m_initialize(void);
|
||||
#endif
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -73,5 +73,6 @@
|
|||
#define MPCORE_GTM_VBASE (CHIP_MPCORE_VBASE+MPCORE_GTM_OFFSET)
|
||||
#define MPCORE_PTM_VBASE (CHIP_MPCORE_VBASE+MPCORE_PTM_OFFSET)
|
||||
#define MPCORE_ICD_VBASE (CHIP_MPCORE_VBASE+MPCORE_ICD_OFFSET)
|
||||
#define MPCORE_V2M_VBASE (CHIP_MPCORE_VBASE+MPCORE_V2M_OFFSET)
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_ARMV7_A_MPCORE_H */
|
||||
|
|
|
@ -35,30 +35,60 @@
|
|||
|
||||
#include "arm_internal.h"
|
||||
#include "exc_return.h"
|
||||
#include "nvic.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
void exception_direct(void)
|
||||
{
|
||||
int irq = getipsr();
|
||||
|
||||
arm_ack_irq(irq);
|
||||
irq_dispatch(irq, NULL);
|
||||
|
||||
if (g_running_tasks[this_cpu()] != this_task())
|
||||
{
|
||||
up_trigger_irq(NVIC_IRQ_PENDSV, 0);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
board_autoled_on(LED_INIRQ);
|
||||
#ifdef CONFIG_SUPPRESS_INTERRUPTS
|
||||
PANIC();
|
||||
#else
|
||||
|
||||
if (regs[REG_EXC_RETURN] & EXC_RETURN_THREAD_MODE)
|
||||
{
|
||||
up_set_current_regs(regs);
|
||||
}
|
||||
|
||||
/* Acknowledge the interrupt */
|
||||
|
||||
arm_ack_irq(irq);
|
||||
|
||||
/* Deliver the IRQ */
|
||||
/* Set current regs for crash dump */
|
||||
|
||||
irq_dispatch(irq, regs);
|
||||
up_set_current_regs(regs);
|
||||
|
||||
if (irq == NVIC_IRQ_PENDSV)
|
||||
{
|
||||
#ifdef CONFIG_ARCH_HIPRI_INTERRUPT
|
||||
/* Dispatch the PendSV interrupt */
|
||||
|
||||
irq_dispatch(irq, regs);
|
||||
#endif
|
||||
|
||||
up_irq_save();
|
||||
g_running_tasks[this_cpu()]->xcp.regs = regs;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Dispatch irq */
|
||||
|
||||
tcb->xcp.regs = regs;
|
||||
irq_dispatch(irq, regs);
|
||||
}
|
||||
|
||||
/* If a context switch occurred while processing the interrupt then
|
||||
* current_regs may have change value. If we return any value different
|
||||
|
@ -66,27 +96,27 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
|||
* switch occurred during interrupt processing.
|
||||
*/
|
||||
|
||||
if (regs[REG_EXC_RETURN] & EXC_RETURN_THREAD_MODE)
|
||||
{
|
||||
/* Restore the cpu lock */
|
||||
tcb = this_task();
|
||||
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
/* Record the new "running" task when context switch occurred.
|
||||
* g_running_tasks[] is only used by assertion logic for reporting
|
||||
* crashes.
|
||||
*/
|
||||
/* Update scheduler parameters */
|
||||
|
||||
g_running_tasks[this_cpu()] = this_task();
|
||||
regs = up_current_regs();
|
||||
}
|
||||
nxsched_suspend_scheduler(g_running_tasks[this_cpu()]);
|
||||
nxsched_resume_scheduler(tcb);
|
||||
|
||||
/* Update the current_regs to NULL. */
|
||||
/* Record the new "running" task when context switch occurred.
|
||||
* g_running_tasks[] is only used by assertion logic for reporting
|
||||
* crashes.
|
||||
*/
|
||||
|
||||
up_set_current_regs(NULL);
|
||||
}
|
||||
g_running_tasks[this_cpu()] = tcb;
|
||||
regs = tcb->xcp.regs;
|
||||
#endif
|
||||
|
||||
/* Clear current regs */
|
||||
|
||||
up_set_current_regs(NULL);
|
||||
|
||||
board_autoled_off(LED_INIRQ);
|
||||
|
||||
return regs;
|
||||
}
|
||||
|
|
|
@ -163,7 +163,7 @@ void up_initial_state(struct tcb_s *tcb)
|
|||
#else /* CONFIG_SUPPRESS_INTERRUPTS */
|
||||
|
||||
#ifdef CONFIG_ARMV7M_USEBASEPRI
|
||||
xcp->regs[REG_BASEPRI] = NVIC_SYSH_PRIORITY_MIN;
|
||||
xcp->regs[REG_BASEPRI] = 0;
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_SUPPRESS_INTERRUPTS */
|
||||
|
|
|
@ -79,355 +79,64 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
void up_schedule_sigaction(struct tcb_s *tcb)
|
||||
{
|
||||
sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
|
||||
DEBUGASSERT(tcb != NULL && sigdeliver != NULL);
|
||||
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(),
|
||||
this_task()->xcp.regs);
|
||||
|
||||
/* Refuse to handle nested signal actions */
|
||||
/* First, handle some special cases when the signal is
|
||||
* being delivered to the currently executing task.
|
||||
*/
|
||||
|
||||
if (tcb->xcp.sigdeliver == NULL)
|
||||
if (tcb == this_task() && !up_interrupt_context())
|
||||
{
|
||||
tcb->xcp.sigdeliver = sigdeliver;
|
||||
|
||||
/* First, handle some special cases when the signal is being delivered
|
||||
* to the currently executing task.
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handle will run in a critical section!
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb == this_task())
|
||||
{
|
||||
/* CASE 1: We are not in an interrupt handler and a task is
|
||||
* signaling itself for some reason.
|
||||
*/
|
||||
|
||||
if (!up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handle will run in a critical section!
|
||||
*/
|
||||
|
||||
sigdeliver(tcb);
|
||||
tcb->xcp.sigdeliver = NULL;
|
||||
}
|
||||
|
||||
/* CASE 2: We are in an interrupt handler AND the interrupted
|
||||
* task is the same as the one that must receive the signal, then
|
||||
* we will have to modify the return state as well as the state in
|
||||
* the TCB.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the return PC, CPSR and either the BASEPRI or PRIMASK
|
||||
* registers (and perhaps also the LR). These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
/* And make sure that the saved context in the TCB is the same
|
||||
* as the interrupt return context.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.saved_regs);
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
|
||||
memcpy(up_current_regs(), tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() +
|
||||
XCPTCONTEXT_REGS);
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled. The kernel-space trampoline must run in
|
||||
* privileged thread mode.
|
||||
*/
|
||||
|
||||
up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
#ifdef CONFIG_ARMV7M_USEBASEPRI
|
||||
up_current_regs()[REG_BASEPRI] =
|
||||
NVIC_SYSH_DISABLE_PRIORITY;
|
||||
#else
|
||||
up_current_regs()[REG_PRIMASK] = 1;
|
||||
#endif
|
||||
up_current_regs()[REG_XPSR] = ARMV7M_XPSR_T;
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
up_current_regs()[REG_LR] = EXC_RETURN_THREAD;
|
||||
up_current_regs()[REG_EXC_RETURN] = EXC_RETURN_THREAD;
|
||||
up_current_regs()[REG_CONTROL] = getcontrol() &
|
||||
~CONTROL_NPRIV;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, we are (1) signaling a task is not running from an
|
||||
* interrupt handler or (2) we are not in an interrupt handler and the
|
||||
* running task is signaling* some non-running task.
|
||||
(tcb->sigdeliver)(tcb);
|
||||
tcb->sigdeliver = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Save the return PC, CPSR and either the BASEPRI or PRIMASK
|
||||
* registers (and perhaps also the LR). These will be restored
|
||||
* by the signal trampoline after the signal has been delivered.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the return PC, CPSR and either the BASEPRI or PRIMASK
|
||||
* registers (and perhaps also the LR). These will be restored
|
||||
* by the signal trampoline after the signal has been delivered.
|
||||
*/
|
||||
/* Save the current register context location */
|
||||
|
||||
/* Save the current register context location */
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
|
||||
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled. We must already be in privileged thread mode to be
|
||||
* here.
|
||||
*/
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled. We must already be in privileged thread mode to be
|
||||
* here.
|
||||
*/
|
||||
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
#ifdef CONFIG_ARMV7M_USEBASEPRI
|
||||
tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY;
|
||||
tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY;
|
||||
#else
|
||||
tcb->xcp.regs[REG_PRIMASK] = 1;
|
||||
tcb->xcp.regs[REG_PRIMASK] = 1;
|
||||
#endif
|
||||
tcb->xcp.regs[REG_XPSR] = ARMV7M_XPSR_T;
|
||||
tcb->xcp.regs[REG_XPSR] = ARMV7M_XPSR_T;
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD;
|
||||
tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
|
||||
tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD;
|
||||
tcb->xcp.regs[REG_EXC_RETURN] = EXC_RETURN_THREAD;
|
||||
tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* !CONFIG_SMP */
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
{
|
||||
int cpu;
|
||||
int me;
|
||||
|
||||
sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
|
||||
|
||||
/* Refuse to handle nested signal actions */
|
||||
|
||||
if (!tcb->xcp.sigdeliver)
|
||||
{
|
||||
tcb->xcp.sigdeliver = sigdeliver;
|
||||
|
||||
/* First, handle some special cases when the signal is being delivered
|
||||
* to task that is currently executing on any CPU.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb->task_state == TSTATE_TASK_RUNNING)
|
||||
{
|
||||
me = this_cpu();
|
||||
cpu = tcb->cpu;
|
||||
|
||||
/* CASE 1: We are not in an interrupt handler and a task is
|
||||
* signaling itself for some reason.
|
||||
*/
|
||||
|
||||
if (cpu == me && !up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handler will run in a critical section!
|
||||
*/
|
||||
|
||||
sigdeliver(tcb);
|
||||
tcb->xcp.sigdeliver = NULL;
|
||||
}
|
||||
|
||||
/* CASE 2: The task that needs to receive the signal is running.
|
||||
* This could happen if the task is running on another CPU OR if
|
||||
* we are in an interrupt handler and the task is running on this
|
||||
* CPU. In the former case, we will have to PAUSE the other CPU
|
||||
* first. But in either case, we will have to modify the return
|
||||
* state as well as the state in the TCB.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* If we signaling a task running on the other CPU, we have
|
||||
* to PAUSE the other CPU.
|
||||
*/
|
||||
|
||||
if (cpu != me)
|
||||
{
|
||||
/* Pause the CPU */
|
||||
|
||||
up_cpu_pause(cpu);
|
||||
|
||||
/* Now tcb on the other CPU can be accessed safely */
|
||||
|
||||
/* Copy tcb->xcp.regs to tcp.xcp.saved. These will be
|
||||
* restored by the signal trampoline after the signal has
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
/* Save the current register context location */
|
||||
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
|
||||
/* Then set up vector to the trampoline with interrupts
|
||||
* disabled. We must already be in privileged thread mode
|
||||
* to be here.
|
||||
*/
|
||||
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
#ifdef CONFIG_ARMV7M_USEBASEPRI
|
||||
tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY;
|
||||
#else
|
||||
tcb->xcp.regs[REG_PRIMASK] = 1;
|
||||
#endif
|
||||
tcb->xcp.regs[REG_XPSR] = ARMV7M_XPSR_T;
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD;
|
||||
tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
/* tcb is running on the same CPU */
|
||||
|
||||
/* Save the return PC, CPSR and either the BASEPRI or
|
||||
* PRIMASK registers (and perhaps also the LR). These
|
||||
* will be restored by the signal trampoline after the
|
||||
* signal has been delivered.
|
||||
*/
|
||||
|
||||
/* And make sure that the saved context in the TCB is the
|
||||
* same as the interrupt return context.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.saved_regs);
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
|
||||
memcpy(up_current_regs(), tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
up_current_regs()[REG_SP] = (uint32_t)(up_current_regs()
|
||||
+ XCPTCONTEXT_REGS);
|
||||
|
||||
/* Then set up vector to the trampoline with interrupts
|
||||
* disabled. The kernel-space trampoline must run in
|
||||
* privileged thread mode.
|
||||
*/
|
||||
|
||||
up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
#ifdef CONFIG_ARMV7M_USEBASEPRI
|
||||
up_current_regs()[REG_BASEPRI] =
|
||||
NVIC_SYSH_DISABLE_PRIORITY;
|
||||
#else
|
||||
up_current_regs()[REG_PRIMASK] = 1;
|
||||
#endif
|
||||
up_current_regs()[REG_XPSR] = ARMV7M_XPSR_T;
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
up_current_regs()[REG_LR] = EXC_RETURN_THREAD;
|
||||
up_current_regs()[REG_CONTROL] = getcontrol() &
|
||||
~CONTROL_NPRIV;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* NOTE: If the task runs on another CPU(cpu), adjusting
|
||||
* global IRQ controls will be done in the pause handler
|
||||
* on the CPU(cpu) by taking a critical section.
|
||||
* If the task is scheduled on this CPU(me), do nothing
|
||||
* because this CPU already took a critical section
|
||||
*/
|
||||
|
||||
/* RESUME the other CPU if it was PAUSED */
|
||||
|
||||
if (cpu != me)
|
||||
{
|
||||
up_cpu_resume(cpu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, we are (1) signaling a task is not running from an
|
||||
* interrupt handler or (2) we are not in an interrupt handler and the
|
||||
* running task is signaling some other non-running task.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the return PC, CPSR and either the BASEPRI or PRIMASK
|
||||
* registers (and perhaps also the LR). These will be restored
|
||||
* by the signal trampoline after the signal has been delivered.
|
||||
*/
|
||||
|
||||
/* Save the current register context location */
|
||||
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
|
||||
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled. We must already be in privileged thread mode to be
|
||||
* here.
|
||||
*/
|
||||
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
#ifdef CONFIG_ARMV7M_USEBASEPRI
|
||||
tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY;
|
||||
#else
|
||||
tcb->xcp.regs[REG_PRIMASK] = 1;
|
||||
#endif
|
||||
tcb->xcp.regs[REG_XPSR] = ARMV7M_XPSR_T;
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD;
|
||||
tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_SMP */
|
||||
|
|
|
@ -68,8 +68,8 @@ void arm_sigdeliver(void)
|
|||
board_autoled_on(LED_SIGNAL);
|
||||
|
||||
sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n",
|
||||
rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head);
|
||||
DEBUGASSERT(rtcb->xcp.sigdeliver != NULL);
|
||||
rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head);
|
||||
DEBUGASSERT(rtcb->sigdeliver != NULL);
|
||||
|
||||
retry:
|
||||
#ifdef CONFIG_SMP
|
||||
|
@ -105,7 +105,7 @@ retry:
|
|||
|
||||
/* Deliver the signal */
|
||||
|
||||
((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb);
|
||||
(rtcb->sigdeliver)(rtcb);
|
||||
|
||||
/* Output any debug messages BEFORE restoring errno (because they may
|
||||
* alter errno), then disable interrupts again and restore the original
|
||||
|
@ -156,7 +156,7 @@ retry:
|
|||
* could be modified by a hostile program.
|
||||
*/
|
||||
|
||||
rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */
|
||||
rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */
|
||||
|
||||
/* Then restore the correct state for this thread of
|
||||
* execution.
|
||||
|
|
|
@ -125,10 +125,10 @@ static void dispatch_syscall(void)
|
|||
|
||||
int arm_svcall(int irq, void *context, void *arg)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
uint32_t *regs = (uint32_t *)context;
|
||||
uint32_t cmd;
|
||||
|
||||
DEBUGASSERT(regs && regs == up_current_regs());
|
||||
cmd = regs[REG_R0];
|
||||
|
||||
/* The SVCall software interrupt is called with R0 = system call command
|
||||
|
@ -176,7 +176,7 @@ int arm_svcall(int irq, void *context, void *arg)
|
|||
case SYS_restore_context:
|
||||
{
|
||||
DEBUGASSERT(regs[REG_R1] != 0);
|
||||
up_set_current_regs((uint32_t *)regs[REG_R1]);
|
||||
tcb->xcp.regs = (uint32_t *)regs[REG_R1];
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -201,7 +201,7 @@ int arm_svcall(int irq, void *context, void *arg)
|
|||
{
|
||||
DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
|
||||
*(uint32_t **)regs[REG_R1] = regs;
|
||||
up_set_current_regs((uint32_t *)regs[REG_R2]);
|
||||
tcb->xcp.regs = (uint32_t *)regs[REG_R2];
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -298,8 +298,9 @@ int arm_svcall(int irq, void *context, void *arg)
|
|||
* At this point, the following values are saved in context:
|
||||
*
|
||||
* R0 = SYS_pthread_start
|
||||
* R1 = entrypt
|
||||
* R2 = arg
|
||||
* R1 = startup (trampoline)
|
||||
* R2 = entrypt
|
||||
* R3 = arg
|
||||
*/
|
||||
|
||||
#if !defined(CONFIG_BUILD_FLAT) && !defined(CONFIG_DISABLE_PTHREAD)
|
||||
|
@ -459,24 +460,20 @@ int arm_svcall(int irq, void *context, void *arg)
|
|||
# ifndef CONFIG_DEBUG_SVCALL
|
||||
if (cmd > SYS_switch_context)
|
||||
# else
|
||||
if (regs != up_current_regs())
|
||||
if (regs != tcb->xcp.regs)
|
||||
# endif
|
||||
{
|
||||
regs = (uint32_t *)tcb->xcp.regs;
|
||||
|
||||
svcinfo("SVCall Return:\n");
|
||||
svcinfo(" R0: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
up_current_regs()[REG_R0], up_current_regs()[REG_R1],
|
||||
up_current_regs()[REG_R2], up_current_regs()[REG_R3],
|
||||
up_current_regs()[REG_R4], up_current_regs()[REG_R5],
|
||||
up_current_regs()[REG_R6], up_current_regs()[REG_R7]);
|
||||
regs[REG_R0], regs[REG_R1], regs[REG_R2], regs[REG_R3],
|
||||
regs[REG_R4], regs[REG_R5], regs[REG_R6], regs[REG_R7]);
|
||||
svcinfo(" R8: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
up_current_regs()[REG_R8], up_current_regs()[REG_R9],
|
||||
up_current_regs()[REG_R10], up_current_regs()[REG_R11],
|
||||
up_current_regs()[REG_R12], up_current_regs()[REG_R13],
|
||||
up_current_regs()[REG_R14], up_current_regs()[REG_R15]);
|
||||
svcinfo(" PSR: %08x EXC_RETURN: %08x, CONTROL: %08x\n",
|
||||
up_current_regs()[REG_XPSR],
|
||||
up_current_regs()[REG_EXC_RETURN],
|
||||
up_current_regs()[REG_CONTROL]);
|
||||
regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11],
|
||||
regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]);
|
||||
svcinfo(" PSR: %08x EXC_RETURN: %08x CONTROL: %08x\n",
|
||||
regs[REG_XPSR], regs[REG_EXC_RETURN], regs[REG_CONTROL]);
|
||||
}
|
||||
# ifdef CONFIG_DEBUG_SVCALL
|
||||
else
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "chip.h"
|
||||
#include "arm_internal.h"
|
||||
#include "ram_vectors.h"
|
||||
#include "nvic.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
@ -71,6 +72,7 @@ static void start(void)
|
|||
/* Common exception entrypoint */
|
||||
|
||||
extern void exception_common(void);
|
||||
extern void exception_direct(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Public data
|
||||
|
@ -98,5 +100,7 @@ const void * const _vectors[] locate_data(".vectors")
|
|||
|
||||
/* Vectors 2 - n point directly at the generic handler */
|
||||
|
||||
[2 ... (15 + ARMV7M_PERIPHERAL_INTERRUPTS)] = exception_common
|
||||
[2 ... NVIC_IRQ_PENDSV] = &exception_common,
|
||||
[(NVIC_IRQ_PENDSV + 1) ... (15 + ARMV7M_PERIPHERAL_INTERRUPTS)]
|
||||
= &exception_direct
|
||||
};
|
||||
|
|
|
@ -71,7 +71,7 @@ if(CONFIG_SMP)
|
|||
SRCS
|
||||
arm_cpuhead.S
|
||||
arm_cpustart.c
|
||||
arm_cpupause.c
|
||||
arm_smpcall.c
|
||||
arm_cpuidlestack.c
|
||||
arm_scu.c)
|
||||
endif()
|
||||
|
|
|
@ -59,6 +59,6 @@ endif
|
|||
|
||||
ifeq ($(CONFIG_SMP),y)
|
||||
CMN_ASRCS += arm_cpuhead.S
|
||||
CMN_CSRCS += arm_cpustart.c arm_cpupause.c
|
||||
CMN_CSRCS += arm_cpustart.c arm_smpcall.c
|
||||
CMN_CSRCS += arm_cpuidlestack.c arm_scu.c
|
||||
endif
|
||||
|
|
|
@ -1,381 +0,0 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/armv7-r/arm_cpupause.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/sched.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/sched_note.h>
|
||||
|
||||
#include "arm_internal.h"
|
||||
#include "gic.h"
|
||||
#include "sched/sched.h"
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* These spinlocks are used in the SMP configuration in order to implement
|
||||
* up_cpu_pause(). The protocol for CPUn to pause CPUm is as follows
|
||||
*
|
||||
* 1. The up_cpu_pause() implementation on CPUn locks both g_cpu_wait[m]
|
||||
* and g_cpu_paused[m]. CPUn then waits spinning on g_cpu_paused[m].
|
||||
* 2. CPUm receives the interrupt it (1) unlocks g_cpu_paused[m] and
|
||||
* (2) locks g_cpu_wait[m]. The first unblocks CPUn and the second
|
||||
* blocks CPUm in the interrupt handler.
|
||||
*
|
||||
* When CPUm resumes, CPUn unlocks g_cpu_wait[m] and the interrupt handler
|
||||
* on CPUm continues. CPUm must, of course, also then unlock g_cpu_wait[m]
|
||||
* so that it will be ready for the next pause operation.
|
||||
*/
|
||||
|
||||
static volatile spinlock_t g_cpu_wait[CONFIG_SMP_NCPUS];
|
||||
static volatile spinlock_t g_cpu_paused[CONFIG_SMP_NCPUS];
|
||||
static volatile spinlock_t g_cpu_resumed[CONFIG_SMP_NCPUS];
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_pausereq
|
||||
*
|
||||
* Description:
|
||||
* Return true if a pause request is pending for this CPU.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cpu - The index of the CPU to be queried
|
||||
*
|
||||
* Returned Value:
|
||||
* true = a pause request is pending.
|
||||
* false = no pasue request is pending.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
bool up_cpu_pausereq(int cpu)
|
||||
{
|
||||
return spin_is_locked(&g_cpu_paused[cpu]);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_save
|
||||
*
|
||||
* Description:
|
||||
* Handle a pause request from another CPU. Normally, this logic is
|
||||
* executed from interrupt handling logic within the architecture-specific
|
||||
* However, it is sometimes necessary to perform the pending
|
||||
* pause operation in other contexts where the interrupt cannot be taken
|
||||
* in order to avoid deadlocks.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_save(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(tcb);
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we are paused */
|
||||
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at current_regs into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.regs);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused
|
||||
*
|
||||
* Description:
|
||||
* Handle a pause request from another CPU. Normally, this logic is
|
||||
* executed from interrupt handling logic within the architecture-specific
|
||||
* However, it is sometimes necessary to perform the pending
|
||||
* pause operation in other contexts where the interrupt cannot be taken
|
||||
* in order to avoid deadlocks.
|
||||
*
|
||||
* This function performs the following operations:
|
||||
*
|
||||
* 1. It saves the current task state at the head of the current assigned
|
||||
* task list.
|
||||
* 2. It waits on a spinlock, then
|
||||
* 3. Returns from interrupt, restoring the state of the new task at the
|
||||
* head of the ready to run list.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cpu - The index of the CPU to be paused
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused(int cpu)
|
||||
{
|
||||
/* Release the g_cpu_paused spinlock to synchronize with the
|
||||
* requesting CPU.
|
||||
*/
|
||||
|
||||
spin_unlock(&g_cpu_paused[cpu]);
|
||||
|
||||
/* Ensure the CPU has been resumed to avoid causing a deadlock */
|
||||
|
||||
spin_lock(&g_cpu_resumed[cpu]);
|
||||
|
||||
/* Wait for the spinlock to be released. The requesting CPU will release
|
||||
* the spinlock when the CPU is resumed.
|
||||
*/
|
||||
|
||||
spin_lock(&g_cpu_wait[cpu]);
|
||||
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_restore
|
||||
*
|
||||
* Description:
|
||||
* Restore the state of the CPU after it was paused via up_cpu_pause(),
|
||||
* and resume normal tasking.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_restore(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we have resumed */
|
||||
|
||||
sched_note_cpu_resumed(tcb);
|
||||
#endif
|
||||
|
||||
/* Reset scheduler parameters */
|
||||
|
||||
nxsched_resume_scheduler(tcb);
|
||||
|
||||
/* Then switch contexts. Any necessary address environment changes
|
||||
* will be made when the interrupt returns.
|
||||
*/
|
||||
|
||||
arm_restorestate(tcb->xcp.regs);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_pause_handler
|
||||
*
|
||||
* Description:
|
||||
* This is the handler for SGI2. It performs the following operations:
|
||||
*
|
||||
* 1. It saves the current task state at the head of the current assigned
|
||||
* task list.
|
||||
* 2. It waits on a spinlock, then
|
||||
* 3. Returns from interrupt, restoring the state of the new task at the
|
||||
* head of the ready to run list.
|
||||
*
|
||||
* Input Parameters:
|
||||
* Standard interrupt handling
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int arm_pause_handler(int irq, void *context, void *arg)
|
||||
{
|
||||
int cpu = this_cpu();
|
||||
|
||||
/* Check for false alarms. Such false could occur as a consequence of
|
||||
* some deadlock breaking logic that might have already serviced the SG2
|
||||
* interrupt by calling up_cpu_paused(). If the pause event has already
|
||||
* been processed then g_cpu_paused[cpu] will not be locked.
|
||||
*/
|
||||
|
||||
if (up_cpu_pausereq(cpu))
|
||||
{
|
||||
/* NOTE: The following enter_critical_section() will call
|
||||
* up_cpu_paused() to process a pause request to break a deadlock
|
||||
* because the caller held a critical section. Once up_cpu_paused()
|
||||
* finished, the caller will proceed and release the g_cpu_irqlock.
|
||||
* Then this CPU will acquire g_cpu_irqlock in the function.
|
||||
*/
|
||||
|
||||
irqstate_t flags = enter_critical_section();
|
||||
|
||||
/* NOTE: the pause request should not exist here */
|
||||
|
||||
DEBUGVERIFY(!up_cpu_pausereq(cpu));
|
||||
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_pause
|
||||
*
|
||||
* Description:
|
||||
* Save the state of the current task at the head of the
|
||||
* g_assignedtasks[cpu] task list and then pause task execution on the
|
||||
* CPU.
|
||||
*
|
||||
* This function is called by the OS when the logic executing on one CPU
|
||||
* needs to modify the state of the g_assignedtasks[cpu] list for another
|
||||
* CPU.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cpu - The index of the CPU to be stopped
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_pause(int cpu)
|
||||
{
|
||||
DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify of the pause event */
|
||||
|
||||
sched_note_cpu_pause(this_task(), cpu);
|
||||
#endif
|
||||
|
||||
/* Take the both spinlocks. The g_cpu_wait spinlock will prevent the SGI2
|
||||
* handler from returning until up_cpu_resume() is called; g_cpu_paused
|
||||
* is a handshake that will prefent this function from returning until
|
||||
* the CPU is actually paused.
|
||||
* Note that we might spin before getting g_cpu_wait, this just means that
|
||||
* the other CPU still hasn't finished responding to the previous resume
|
||||
* request.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(!spin_is_locked(&g_cpu_paused[cpu]));
|
||||
|
||||
spin_lock(&g_cpu_wait[cpu]);
|
||||
spin_lock(&g_cpu_paused[cpu]);
|
||||
|
||||
/* Execute SGI2 */
|
||||
|
||||
arm_cpu_sgi(GIC_SMP_CPUPAUSE, (1 << cpu));
|
||||
|
||||
/* Wait for the other CPU to unlock g_cpu_paused meaning that
|
||||
* it is fully paused and ready for up_cpu_resume();
|
||||
*/
|
||||
|
||||
spin_lock(&g_cpu_paused[cpu]);
|
||||
spin_unlock(&g_cpu_paused[cpu]);
|
||||
|
||||
/* On successful return g_cpu_wait will be locked, the other CPU will be
|
||||
* spinning on g_cpu_wait and will not continue until g_cpu_resume() is
|
||||
* called. g_cpu_paused will be unlocked in any case.
|
||||
*/
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_resume
|
||||
*
|
||||
* Description:
|
||||
* Restart the cpu after it was paused via up_cpu_pause(), restoring the
|
||||
* state of the task at the head of the g_assignedtasks[cpu] list, and
|
||||
* resume normal tasking.
|
||||
*
|
||||
* This function is called after up_cpu_pause in order resume operation of
|
||||
* the CPU after modifying its g_assignedtasks[cpu] list.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cpu - The index of the CPU being re-started.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_resume(int cpu)
|
||||
{
|
||||
DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify of the resume event */
|
||||
|
||||
sched_note_cpu_resume(this_task(), cpu);
|
||||
#endif
|
||||
|
||||
/* Release the spinlock. Releasing the spinlock will cause the SGI2
|
||||
* handler on 'cpu' to continue and return from interrupt to the newly
|
||||
* established thread.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(spin_is_locked(&g_cpu_wait[cpu]) &&
|
||||
!spin_is_locked(&g_cpu_paused[cpu]));
|
||||
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
|
||||
/* Ensure the CPU has been resumed to avoid causing a deadlock */
|
||||
|
||||
spin_lock(&g_cpu_resumed[cpu]);
|
||||
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SMP */
|
|
@ -79,12 +79,8 @@ int arm_start_handler(int irq, void *context, void *arg)
|
|||
|
||||
nxsched_resume_scheduler(tcb);
|
||||
|
||||
/* Then switch contexts. This instantiates the exception context of the
|
||||
* tcb at the head of the assigned task list. In this case, this should
|
||||
* be the CPUs NULL task.
|
||||
*/
|
||||
UNUSED(tcb);
|
||||
|
||||
arm_restorestate(tcb->xcp.regs);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
|
||||
uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
board_autoled_on(LED_INIRQ);
|
||||
|
||||
#ifdef CONFIG_SUPPRESS_INTERRUPTS
|
||||
|
@ -50,6 +52,18 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
|||
|
||||
DEBUGASSERT(up_current_regs() == NULL);
|
||||
|
||||
/* if irq == GIC_SMP_CPUSTART
|
||||
* We are initiating the multi-core jumping state to up_idle,
|
||||
* and we will use this_task(). Therefore, it cannot be overridden.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
if (irq != GIC_SMP_CPUSTART)
|
||||
#endif
|
||||
{
|
||||
tcb->xcp.regs = regs;
|
||||
}
|
||||
|
||||
/* Current regs non-zero indicates that we are processing an interrupt;
|
||||
* current_regs is also used to manage interrupt level context switches.
|
||||
*/
|
||||
|
@ -59,18 +73,22 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
|||
/* Deliver the IRQ */
|
||||
|
||||
irq_dispatch(irq, regs);
|
||||
tcb = this_task();
|
||||
|
||||
/* Restore the cpu lock */
|
||||
|
||||
if (regs != up_current_regs())
|
||||
if (regs != tcb->xcp.regs)
|
||||
{
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(g_running_tasks[this_cpu()]);
|
||||
nxsched_resume_scheduler(tcb);
|
||||
|
||||
/* Record the new "running" task when context switch occurred.
|
||||
* g_running_tasks[] is only used by assertion logic for reporting
|
||||
* crashes.
|
||||
*/
|
||||
|
||||
g_running_tasks[this_cpu()] = this_task();
|
||||
regs = up_current_regs();
|
||||
g_running_tasks[this_cpu()] = tcb;
|
||||
regs = tcb->xcp.regs;
|
||||
}
|
||||
|
||||
/* Set current_regs to NULL to indicate that we are no longer in an
|
||||
|
|
|
@ -160,9 +160,8 @@ void arm_gic0_initialize(void)
|
|||
/* Attach SGI interrupt handlers. This attaches the handler to all CPUs. */
|
||||
|
||||
DEBUGVERIFY(irq_attach(GIC_SMP_CPUSTART, arm_start_handler, NULL));
|
||||
DEBUGVERIFY(irq_attach(GIC_SMP_CPUPAUSE, arm_pause_handler, NULL));
|
||||
DEBUGVERIFY(irq_attach(GIC_SMP_CPUCALL,
|
||||
nxsched_smp_call_handler, NULL));
|
||||
DEBUGVERIFY(irq_attach(GIC_SMP_SCHED, arm_smp_sched_handler, NULL));
|
||||
DEBUGVERIFY(irq_attach(GIC_SMP_CALL, nxsched_smp_call_handler, NULL));
|
||||
#endif
|
||||
|
||||
arm_gic_dump("Exit arm_gic0_initialize", true, 0);
|
||||
|
@ -659,24 +658,4 @@ int arm_gic_irq_trigger(int irq, bool edge)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
# ifdef CONFIG_SMP
|
||||
/****************************************************************************
|
||||
* Name: up_send_smp_call
|
||||
*
|
||||
* Description:
|
||||
* Send smp call to target cpu.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cpuset - The set of CPUs to receive the SGI.
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_send_smp_call(cpu_set_t cpuset)
|
||||
{
|
||||
up_trigger_irq(GIC_SMP_CPUCALL, cpuset);
|
||||
}
|
||||
# endif
|
||||
#endif /* CONFIG_ARMV7R_HAVE_GICv2 */
|
||||
|
|
|
@ -75,328 +75,56 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
void up_schedule_sigaction(struct tcb_s *tcb)
|
||||
{
|
||||
sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
|
||||
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(),
|
||||
this_task()->xcp.regs);
|
||||
|
||||
/* Refuse to handle nested signal actions */
|
||||
/* First, handle some special cases when the signal is
|
||||
* being delivered to the currently executing task.
|
||||
*/
|
||||
|
||||
if (!tcb->xcp.sigdeliver)
|
||||
if (tcb == this_task() && !up_interrupt_context())
|
||||
{
|
||||
tcb->xcp.sigdeliver = sigdeliver;
|
||||
|
||||
/* First, handle some special cases when the signal is being delivered
|
||||
* to the currently executing task.
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handler will run in a critical section!
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb == this_task())
|
||||
{
|
||||
/* CASE 1: We are not in an interrupt handler and a task is
|
||||
* signalling itself for some reason.
|
||||
*/
|
||||
|
||||
if (!up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now. */
|
||||
|
||||
sigdeliver(tcb);
|
||||
tcb->xcp.sigdeliver = NULL;
|
||||
}
|
||||
|
||||
/* CASE 2: We are in an interrupt handler AND the interrupted
|
||||
* task is the same as the one that must receive the signal, then
|
||||
* we will have to modify the return state as well as the state
|
||||
* in the TCB.
|
||||
*
|
||||
* Hmmm... there looks like a latent bug here: The following logic
|
||||
* would fail in the strange case where we are in an interrupt
|
||||
* handler, the thread is signalling itself, but a context switch
|
||||
* to another task has occurred so that current_regs does not
|
||||
* refer to the thread of this_task()!
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the return lr and cpsr and one scratch register
|
||||
* These will be restored by the signal trampoline after
|
||||
* the signals have been delivered.
|
||||
*/
|
||||
|
||||
/* And make sure that the saved context in the TCB is the same
|
||||
* as the interrupt return context.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.saved_regs);
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
|
||||
memcpy(up_current_regs(), tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() +
|
||||
XCPTCONTEXT_REGS);
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
up_current_regs()[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
up_current_regs()[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ENDIAN_BIG
|
||||
up_current_regs()[REG_CPSR] |= PSR_E_BIT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, we are (1) signaling a task is not running from an
|
||||
* interrupt handler or (2) we are not in an interrupt handler and the
|
||||
* running task is signalling some non-running task.
|
||||
(tcb->sigdeliver)(tcb);
|
||||
tcb->sigdeliver = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Save the return lr and cpsr and one scratch register. These
|
||||
* will be restored by the signal trampoline after the signals
|
||||
* have been delivered.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the return lr and cpsr and one scratch register. These
|
||||
* will be restored by the signal trampoline after the signals
|
||||
* have been delivered.
|
||||
*/
|
||||
/* Save the current register context location */
|
||||
|
||||
/* Save the current register context location */
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
|
||||
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT);
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
||||
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ENDIAN_BIG
|
||||
tcb->xcp.regs[REG_CPSR] |= PSR_E_BIT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
{
|
||||
int cpu;
|
||||
int me;
|
||||
|
||||
sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
|
||||
|
||||
/* Refuse to handle nested signal actions */
|
||||
|
||||
if (!tcb->xcp.sigdeliver)
|
||||
{
|
||||
tcb->xcp.sigdeliver = sigdeliver;
|
||||
|
||||
/* First, handle some special cases when the signal is being delivered
|
||||
* to task that is currently executing on any CPU.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb->task_state == TSTATE_TASK_RUNNING)
|
||||
{
|
||||
me = this_cpu();
|
||||
cpu = tcb->cpu;
|
||||
|
||||
/* CASE 1: We are not in an interrupt handler and a task is
|
||||
* signaling itself for some reason.
|
||||
*/
|
||||
|
||||
if (cpu == me && !up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handler will run in a critical section!
|
||||
*/
|
||||
|
||||
sigdeliver(tcb);
|
||||
tcb->xcp.sigdeliver = NULL;
|
||||
}
|
||||
|
||||
/* CASE 2: The task that needs to receive the signal is running.
|
||||
* This could happen if the task is running on another CPU OR if
|
||||
* we are in an interrupt handler and the task is running on this
|
||||
* CPU. In the former case, we will have to PAUSE the other CPU
|
||||
* first. But in either case, we will have to modify the return
|
||||
* state as well as the state in the TCB.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* If we signaling a task running on the other CPU, we have
|
||||
* to PAUSE the other CPU.
|
||||
*/
|
||||
|
||||
if (cpu != me)
|
||||
{
|
||||
/* Pause the CPU */
|
||||
|
||||
up_cpu_pause(cpu);
|
||||
|
||||
/* Now tcb on the other CPU can be accessed safely */
|
||||
|
||||
/* Copy tcb->xcp.regs to tcp.xcp.saved. These will be
|
||||
* restored by the signal trampoline after the signal has
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
/* Save the current register context location */
|
||||
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
/* tcb is running on the same CPU */
|
||||
|
||||
/* Save the return PC, CPSR and either the BASEPRI or
|
||||
* PRIMASK registers (and perhaps also the LR). These will
|
||||
* be restored by the signal trampoline after the signal
|
||||
* has been delivered.
|
||||
*/
|
||||
|
||||
/* And make sure that the saved context in the TCB is the
|
||||
* same as the interrupt return context.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.saved_regs);
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
|
||||
memcpy(up_current_regs(), tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
up_current_regs()[REG_SP] = (uint32_t)(up_current_regs()
|
||||
+ XCPTCONTEXT_REGS);
|
||||
|
||||
/* Then set up vector to the trampoline with interrupts
|
||||
* disabled. The kernel-space trampoline must run in
|
||||
* privileged thread mode.
|
||||
*/
|
||||
|
||||
up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
up_current_regs()[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
up_current_regs()[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* NOTE: If the task runs on another CPU(cpu), adjusting
|
||||
* global IRQ controls will be done in the pause handler
|
||||
* on the CPU(cpu) by taking a critical section.
|
||||
* If the task is scheduled on this CPU(me), do nothing
|
||||
* because this CPU already took a critical section
|
||||
*/
|
||||
|
||||
/* RESUME the other CPU if it was PAUSED */
|
||||
|
||||
if (cpu != me)
|
||||
{
|
||||
up_cpu_resume(cpu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, we are (1) signaling a task is not running from an
|
||||
* interrupt handler or (2) we are not in an interrupt handler and the
|
||||
* running task is signaling some other non-running task.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the return lr and cpsr and one scratch register. These
|
||||
* will be restored by the signal trampoline after the signals
|
||||
* have been delivered.
|
||||
*/
|
||||
|
||||
/* Save the current register context location */
|
||||
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
|
||||
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -68,8 +68,8 @@ void arm_sigdeliver(void)
|
|||
board_autoled_on(LED_SIGNAL);
|
||||
|
||||
sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n",
|
||||
rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head);
|
||||
DEBUGASSERT(rtcb->xcp.sigdeliver != NULL);
|
||||
rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head);
|
||||
DEBUGASSERT(rtcb->sigdeliver != NULL);
|
||||
|
||||
retry:
|
||||
#ifdef CONFIG_SMP
|
||||
|
@ -101,7 +101,7 @@ retry:
|
|||
|
||||
/* Deliver the signal */
|
||||
|
||||
((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb);
|
||||
(rtcb->sigdeliver)(rtcb);
|
||||
|
||||
/* Output any debug messages BEFORE restoring errno (because they may
|
||||
* alter errno), then disable interrupts again and restore the original
|
||||
|
@ -145,7 +145,7 @@ retry:
|
|||
* could be modified by a hostile program.
|
||||
*/
|
||||
|
||||
rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */
|
||||
rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */
|
||||
|
||||
/* Then restore the correct state for this thread of execution. */
|
||||
|
||||
|
|
122
arch/arm/src/armv7-r/arm_smpcall.c
Normal file
122
arch/arm/src/armv7-r/arm_smpcall.c
Normal file
|
@ -0,0 +1,122 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/armv7-r/arm_smpcall.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/sched.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/sched_note.h>
|
||||
|
||||
#include "arm_internal.h"
|
||||
#include "gic.h"
|
||||
#include "sched/sched.h"
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_smp_sched_handler
|
||||
*
|
||||
* Description:
|
||||
* This is the handler for sched.
|
||||
*
|
||||
* 1. It saves the current task state at the head of the current assigned
|
||||
* task list.
|
||||
* 2. It porcess g_delivertasks
|
||||
* 3. Returns from interrupt, restoring the state of the new task at the
|
||||
* head of the ready to run list.
|
||||
*
|
||||
* Input Parameters:
|
||||
* Standard interrupt handling
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int arm_smp_sched_handler(int irq, void *context, void *arg)
|
||||
{
|
||||
int cpu = this_cpu();
|
||||
|
||||
nxsched_process_delivered(cpu);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_send_smp_sched
|
||||
*
|
||||
* Description:
|
||||
* pause task execution on the CPU
|
||||
* check whether there are tasks delivered to specified cpu
|
||||
* and try to run them.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cpu - The index of the CPU to be paused.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
* Assumptions:
|
||||
* Called from within a critical section;
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_send_smp_sched(int cpu)
|
||||
{
|
||||
arm_cpu_sgi(GIC_SMP_SCHED, (1 << cpu));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_send_smp_call
|
||||
*
|
||||
* Description:
|
||||
* Send smp call to target cpu.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cpuset - The set of CPUs to receive the SGI.
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_send_smp_call(cpu_set_t cpuset)
|
||||
{
|
||||
up_trigger_irq(GIC_SMP_CALL, cpuset);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SMP */
|
|
@ -156,7 +156,8 @@ static void dispatch_syscall(void)
|
|||
|
||||
uint32_t *arm_syscall(uint32_t *regs)
|
||||
{
|
||||
struct tcb_s *tcb;
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
uint32_t cmd;
|
||||
int cpu;
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
|
@ -167,6 +168,8 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||
|
||||
DEBUGASSERT(up_current_regs() == NULL);
|
||||
|
||||
tcb->xcp.regs = regs;
|
||||
|
||||
/* Current regs non-zero indicates that we are processing an interrupt;
|
||||
* current_regs is also used to manage interrupt level context switches.
|
||||
*/
|
||||
|
@ -268,7 +271,7 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||
* set will determine the restored context.
|
||||
*/
|
||||
|
||||
up_set_current_regs((uint32_t *)regs[REG_R1]);
|
||||
tcb->xcp.regs = (uint32_t *)regs[REG_R1];
|
||||
DEBUGASSERT(up_current_regs());
|
||||
}
|
||||
break;
|
||||
|
@ -294,7 +297,7 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||
{
|
||||
DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
|
||||
*(uint32_t **)regs[REG_R1] = regs;
|
||||
up_set_current_regs((uint32_t *)regs[REG_R2]);
|
||||
tcb->xcp.regs = (uint32_t *)regs[REG_R2];
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -424,7 +427,7 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||
|
||||
/* Copy "info" into user stack */
|
||||
|
||||
if (rtcb->xcp.sigdeliver)
|
||||
if (rtcb->sigdeliver)
|
||||
{
|
||||
usp = rtcb->xcp.saved_regs[REG_SP];
|
||||
}
|
||||
|
@ -561,22 +564,25 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||
break;
|
||||
}
|
||||
|
||||
/* Restore the cpu lock */
|
||||
|
||||
if (regs != up_current_regs())
|
||||
if (regs != tcb->xcp.regs)
|
||||
{
|
||||
cpu = this_cpu();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(g_running_tasks[cpu]);
|
||||
nxsched_resume_scheduler(tcb);
|
||||
|
||||
/* Record the new "running" task. g_running_tasks[] is only used by
|
||||
* assertion logic for reporting crashes.
|
||||
*/
|
||||
|
||||
cpu = this_cpu();
|
||||
tcb = current_task(cpu);
|
||||
g_running_tasks[cpu] = tcb;
|
||||
|
||||
/* Restore the cpu lock */
|
||||
|
||||
restore_critical_section(tcb, cpu);
|
||||
regs = up_current_regs();
|
||||
regs = tcb->xcp.regs;
|
||||
}
|
||||
|
||||
/* Report what happened */
|
||||
|
|
|
@ -608,12 +608,12 @@
|
|||
|
||||
#ifdef CONFIG_ARCH_TRUSTZONE_SECURE
|
||||
# define GIC_SMP_CPUSTART GIC_IRQ_SGI9
|
||||
# define GIC_SMP_CPUPAUSE GIC_IRQ_SGI10
|
||||
# define GIC_SMP_CPUCALL GIC_IRQ_SGI11
|
||||
# define GIC_SMP_CALL GIC_IRQ_SGI10
|
||||
# define GIC_SMP_SCHED GIC_IRQ_SGI11
|
||||
#else
|
||||
# define GIC_SMP_CPUSTART GIC_IRQ_SGI1
|
||||
# define GIC_SMP_CPUPAUSE GIC_IRQ_SGI2
|
||||
# define GIC_SMP_CPUCALL GIC_IRQ_SGI3
|
||||
# define GIC_SMP_CALL GIC_IRQ_SGI2
|
||||
# define GIC_SMP_SCHED GIC_IRQ_SGI3
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -804,14 +804,14 @@ int arm_start_handler(int irq, void *context, void *arg);
|
|||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_pause_handler
|
||||
* Name: arm_smp_sched_handler
|
||||
*
|
||||
* Description:
|
||||
* This is the handler for SGI2. It performs the following operations:
|
||||
* This is the handler for sched.
|
||||
*
|
||||
* 1. It saves the current task state at the head of the current assigned
|
||||
* task list.
|
||||
* 2. It waits on a spinlock, then
|
||||
* 2. It porcess g_delivertasks
|
||||
* 3. Returns from interrupt, restoring the state of the new task at the
|
||||
* head of the ready to run list.
|
||||
*
|
||||
|
@ -824,7 +824,7 @@ int arm_start_handler(int irq, void *context, void *arg);
|
|||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
int arm_pause_handler(int irq, void *context, void *arg);
|
||||
int arm_smp_sched_handler(int irq, void *context, void *arg);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
@ -35,79 +35,60 @@
|
|||
|
||||
#include "arm_internal.h"
|
||||
#include "exc_return.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Inline Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_from_thread
|
||||
*
|
||||
* Description:
|
||||
* If not defined CONFIG_ARCH_HAVE_TRUSTZONE
|
||||
* Return true if interrupt return to thread mode, false otherwise.
|
||||
*
|
||||
* If defined CONFIG_ARCH_HAVE_TRUSTZONE
|
||||
* Return true if interrupt return to thread mode, or if it is the first
|
||||
* interrupt from TEE to REE, or REE to TEE, false otherwise.
|
||||
*
|
||||
* Interrupt nesting between TEE and REE can be determined based
|
||||
* on the S and ES bits of EXC_RETURN
|
||||
* If TEE interrupts REE, then EXC_RETURN.S=0, EXC_RETURN.ES=1;
|
||||
* Conversely, EXC_RETURN.S=1, EXC_RETURN.ES=0.
|
||||
*
|
||||
* But only one level nesting between TEE and REE is supported, and
|
||||
* recursive nesting between TEE and REE is not supported.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline bool arm_from_thread(uint32_t excret)
|
||||
{
|
||||
if (excret & EXC_RETURN_THREAD_MODE)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ARCH_TRUSTZONE_SECURE)
|
||||
if (!(excret & EXC_RETURN_SECURE_STACK) &&
|
||||
(excret & EXC_RETURN_EXC_SECURE))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(excret & EXC_RETURN_EXC_SECURE) &&
|
||||
(excret & EXC_RETURN_SECURE_STACK))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
#include "nvic.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
void exception_direct(void)
|
||||
{
|
||||
int irq = getipsr();
|
||||
|
||||
arm_ack_irq(irq);
|
||||
irq_dispatch(irq, NULL);
|
||||
|
||||
if (g_running_tasks[this_cpu()] != this_task())
|
||||
{
|
||||
up_trigger_irq(NVIC_IRQ_PENDSV, 0);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
board_autoled_on(LED_INIRQ);
|
||||
#ifdef CONFIG_SUPPRESS_INTERRUPTS
|
||||
PANIC();
|
||||
#else
|
||||
|
||||
if (arm_from_thread(regs[REG_EXC_RETURN]))
|
||||
{
|
||||
up_set_current_regs(regs);
|
||||
}
|
||||
|
||||
/* Acknowledge the interrupt */
|
||||
|
||||
arm_ack_irq(irq);
|
||||
|
||||
/* Deliver the IRQ */
|
||||
/* Set current regs for crash dump */
|
||||
|
||||
irq_dispatch(irq, regs);
|
||||
up_set_current_regs(regs);
|
||||
|
||||
if (irq == NVIC_IRQ_PENDSV)
|
||||
{
|
||||
#ifdef CONFIG_ARCH_HIPRI_INTERRUPT
|
||||
/* Dispatch the PendSV interrupt */
|
||||
|
||||
irq_dispatch(irq, regs);
|
||||
#endif
|
||||
|
||||
up_irq_save();
|
||||
g_running_tasks[this_cpu()]->xcp.regs = regs;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Dispatch irq */
|
||||
|
||||
tcb->xcp.regs = regs;
|
||||
irq_dispatch(irq, regs);
|
||||
}
|
||||
|
||||
/* If a context switch occurred while processing the interrupt then
|
||||
* current_regs may have change value. If we return any value different
|
||||
|
@ -115,27 +96,26 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
|||
* switch occurred during interrupt processing.
|
||||
*/
|
||||
|
||||
if (arm_from_thread(regs[REG_EXC_RETURN]))
|
||||
{
|
||||
/* Restore the cpu lock */
|
||||
tcb = this_task();
|
||||
|
||||
if (regs != up_current_regs())
|
||||
{
|
||||
/* Record the new "running" task when context switch occurred.
|
||||
* g_running_tasks[] is only used by assertion logic for reporting
|
||||
* crashes.
|
||||
*/
|
||||
/* Update scheduler parameters */
|
||||
|
||||
g_running_tasks[this_cpu()] = this_task();
|
||||
regs = up_current_regs();
|
||||
}
|
||||
nxsched_suspend_scheduler(g_running_tasks[this_cpu()]);
|
||||
nxsched_resume_scheduler(tcb);
|
||||
|
||||
/* Update the current_regs to NULL. */
|
||||
/* Record the new "running" task when context switch occurred.
|
||||
* g_running_tasks[] is only used by assertion logic for reporting
|
||||
* crashes.
|
||||
*/
|
||||
|
||||
up_set_current_regs(NULL);
|
||||
}
|
||||
g_running_tasks[this_cpu()] = tcb;
|
||||
regs = tcb->xcp.regs;
|
||||
#endif
|
||||
|
||||
/* Clear current regs */
|
||||
|
||||
up_set_current_regs(NULL);
|
||||
|
||||
board_autoled_off(LED_INIRQ);
|
||||
|
||||
#ifdef CONFIG_ARMV8M_TRUSTZONE_HYBRID
|
||||
|
|
|
@ -169,7 +169,7 @@ void up_initial_state(struct tcb_s *tcb)
|
|||
#else /* CONFIG_SUPPRESS_INTERRUPTS */
|
||||
|
||||
#ifdef CONFIG_ARMV8M_USEBASEPRI
|
||||
xcp->regs[REG_BASEPRI] = NVIC_SYSH_PRIORITY_MIN;
|
||||
xcp->regs[REG_BASEPRI] = 0;
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_SUPPRESS_INTERRUPTS */
|
||||
|
|
|
@ -79,348 +79,64 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
void up_schedule_sigaction(struct tcb_s *tcb)
|
||||
{
|
||||
sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
|
||||
DEBUGASSERT(tcb != NULL && sigdeliver != NULL);
|
||||
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(),
|
||||
this_task()->xcp.regs);
|
||||
|
||||
/* Refuse to handle nested signal actions */
|
||||
/* First, handle some special cases when the signal is
|
||||
* being delivered to the currently executing task.
|
||||
*/
|
||||
|
||||
if (tcb->xcp.sigdeliver == NULL)
|
||||
if (tcb == this_task() && !up_interrupt_context())
|
||||
{
|
||||
tcb->xcp.sigdeliver = sigdeliver;
|
||||
|
||||
/* First, handle some special cases when the signal is being delivered
|
||||
* to the currently executing task.
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handle will run in a critical section!
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb == this_task())
|
||||
{
|
||||
/* CASE 1: We are not in an interrupt handler and a task is
|
||||
* signaling itself for some reason.
|
||||
*/
|
||||
|
||||
if (!up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handle will run in a critical section!
|
||||
*/
|
||||
|
||||
sigdeliver(tcb);
|
||||
tcb->xcp.sigdeliver = NULL;
|
||||
}
|
||||
|
||||
/* CASE 2: We are in an interrupt handler AND the interrupted
|
||||
* task is the same as the one that must receive the signal, then
|
||||
* we will have to modify the return state as well as the state in
|
||||
* the TCB.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the return PC, CPSR and either the BASEPRI or PRIMASK
|
||||
* registers (and perhaps also the LR). These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
/* And make sure that the saved context in the TCB is the same
|
||||
* as the interrupt return context.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.saved_regs);
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
|
||||
memcpy(up_current_regs(), tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() +
|
||||
XCPTCONTEXT_REGS);
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled. The kernel-space trampoline must run in
|
||||
* privileged thread mode.
|
||||
*/
|
||||
|
||||
up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
#ifdef CONFIG_ARMV8M_USEBASEPRI
|
||||
up_current_regs()[REG_BASEPRI] =
|
||||
NVIC_SYSH_DISABLE_PRIORITY;
|
||||
#else
|
||||
up_current_regs()[REG_PRIMASK] = 1;
|
||||
#endif
|
||||
up_current_regs()[REG_XPSR] = ARMV8M_XPSR_T;
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
up_current_regs()[REG_LR] = EXC_RETURN_THREAD;
|
||||
up_current_regs()[REG_EXC_RETURN] = EXC_RETURN_THREAD;
|
||||
up_current_regs()[REG_CONTROL] = getcontrol() &
|
||||
~CONTROL_NPRIV;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, we are (1) signaling a task is not running from an
|
||||
* interrupt handler or (2) we are not in an interrupt handler and the
|
||||
* running task is signaling* some non-running task.
|
||||
(tcb->sigdeliver)(tcb);
|
||||
tcb->sigdeliver = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Save the return PC, CPSR and either the BASEPRI or PRIMASK
|
||||
* registers (and perhaps also the LR). These will be restored
|
||||
* by the signal trampoline after the signal has been delivered.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the return PC, CPSR and either the BASEPRI or PRIMASK
|
||||
* registers (and perhaps also the LR). These will be restored
|
||||
* by the signal trampoline after the signal has been delivered.
|
||||
*/
|
||||
/* Save the current register context location */
|
||||
|
||||
/* Save the current register context location */
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
|
||||
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled. We must already be in privileged thread mode to be
|
||||
* here.
|
||||
*/
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled. We must already be in privileged thread mode to be
|
||||
* here.
|
||||
*/
|
||||
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
#ifdef CONFIG_ARMV8M_USEBASEPRI
|
||||
tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY;
|
||||
tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY;
|
||||
#else
|
||||
tcb->xcp.regs[REG_PRIMASK] = 1;
|
||||
tcb->xcp.regs[REG_PRIMASK] = 1;
|
||||
#endif
|
||||
tcb->xcp.regs[REG_XPSR] = ARMV8M_XPSR_T;
|
||||
tcb->xcp.regs[REG_XPSR] = ARMV8M_XPSR_T;
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD;
|
||||
tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
|
||||
tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD;
|
||||
tcb->xcp.regs[REG_EXC_RETURN] = EXC_RETURN_THREAD;
|
||||
tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* !CONFIG_SMP */
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
{
|
||||
int cpu;
|
||||
int me;
|
||||
|
||||
sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
|
||||
|
||||
/* Refuse to handle nested signal actions */
|
||||
|
||||
if (!tcb->xcp.sigdeliver)
|
||||
{
|
||||
tcb->xcp.sigdeliver = sigdeliver;
|
||||
|
||||
/* First, handle some special cases when the signal is being delivered
|
||||
* to task that is currently executing on any CPU.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb->task_state == TSTATE_TASK_RUNNING)
|
||||
{
|
||||
me = this_cpu();
|
||||
cpu = tcb->cpu;
|
||||
|
||||
/* CASE 1: We are not in an interrupt handler and a task is
|
||||
* signaling itself for some reason.
|
||||
*/
|
||||
|
||||
if (cpu == me && !up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handler will run in a critical section!
|
||||
*/
|
||||
|
||||
sigdeliver(tcb);
|
||||
tcb->xcp.sigdeliver = NULL;
|
||||
}
|
||||
|
||||
/* CASE 2: The task that needs to receive the signal is running.
|
||||
* This could happen if the task is running on another CPU OR if
|
||||
* we are in an interrupt handler and the task is running on this
|
||||
* CPU. In the former case, we will have to PAUSE the other CPU
|
||||
* first. But in either case, we will have to modify the return
|
||||
* state as well as the state in the TCB.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* If we signaling a task running on the other CPU, we have
|
||||
* to PAUSE the other CPU.
|
||||
*/
|
||||
|
||||
if (cpu != me)
|
||||
{
|
||||
/* Pause the CPU */
|
||||
|
||||
up_cpu_pause(cpu);
|
||||
|
||||
/* Now tcb on the other CPU can be accessed safely */
|
||||
|
||||
/* Copy tcb->xcp.regs to tcp.xcp.saved. These will be
|
||||
* restored by the signal trampoline after the signal has
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
/* Save the current register context location */
|
||||
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
|
||||
/* Then set up vector to the trampoline with interrupts
|
||||
* disabled. We must already be in privileged thread mode
|
||||
* to be here.
|
||||
*/
|
||||
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
#ifdef CONFIG_ARMV8M_USEBASEPRI
|
||||
tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY;
|
||||
#else
|
||||
tcb->xcp.regs[REG_PRIMASK] = 1;
|
||||
#endif
|
||||
tcb->xcp.regs[REG_XPSR] = ARMV8M_XPSR_T;
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD;
|
||||
tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
/* tcb is running on the same CPU */
|
||||
|
||||
/* Save the return PC, CPSR and either the BASEPRI or
|
||||
* PRIMASK registers (and perhaps also the LR). These
|
||||
* will be restored by the signal trampoline after the
|
||||
* signal has been delivered.
|
||||
*/
|
||||
|
||||
/* And make sure that the saved context in the TCB is the
|
||||
* same as the interrupt return context.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.saved_regs);
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
|
||||
memcpy(up_current_regs(), tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
up_current_regs()[REG_SP] = (uint32_t)(up_current_regs()
|
||||
+ XCPTCONTEXT_REGS);
|
||||
|
||||
/* Then set up vector to the trampoline with interrupts
|
||||
* disabled. The kernel-space trampoline must run in
|
||||
* privileged thread mode.
|
||||
*/
|
||||
|
||||
up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
#ifdef CONFIG_ARMV8M_USEBASEPRI
|
||||
up_current_regs()[REG_BASEPRI] =
|
||||
NVIC_SYSH_DISABLE_PRIORITY;
|
||||
#else
|
||||
up_current_regs()[REG_PRIMASK] = 1;
|
||||
#endif
|
||||
up_current_regs()[REG_XPSR] = ARMV8M_XPSR_T;
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
up_current_regs()[REG_LR] = EXC_RETURN_THREAD;
|
||||
up_current_regs()[REG_CONTROL] = getcontrol() &
|
||||
~CONTROL_NPRIV;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* RESUME the other CPU if it was PAUSED */
|
||||
|
||||
if (cpu != me)
|
||||
{
|
||||
up_cpu_resume(cpu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, we are (1) signaling a task is not running from an
|
||||
* interrupt handler or (2) we are not in an interrupt handler and the
|
||||
* running task is signaling some other non-running task.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the return PC, CPSR and either the BASEPRI or PRIMASK
|
||||
* registers (and perhaps also the LR). These will be restored
|
||||
* by the signal trampoline after the signal has been delivered.
|
||||
*/
|
||||
|
||||
/* Save the current register context location */
|
||||
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
|
||||
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled. We must already be in privileged thread mode to be
|
||||
* here.
|
||||
*/
|
||||
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
#ifdef CONFIG_ARMV8M_USEBASEPRI
|
||||
tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY;
|
||||
#else
|
||||
tcb->xcp.regs[REG_PRIMASK] = 1;
|
||||
#endif
|
||||
tcb->xcp.regs[REG_XPSR] = ARMV8M_XPSR_T;
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD;
|
||||
tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_SMP */
|
||||
|
|
|
@ -68,8 +68,8 @@ void arm_sigdeliver(void)
|
|||
board_autoled_on(LED_SIGNAL);
|
||||
|
||||
sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n",
|
||||
rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head);
|
||||
DEBUGASSERT(rtcb->xcp.sigdeliver != NULL);
|
||||
rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head);
|
||||
DEBUGASSERT(rtcb->sigdeliver != NULL);
|
||||
|
||||
retry:
|
||||
#ifdef CONFIG_SMP
|
||||
|
@ -105,7 +105,7 @@ retry:
|
|||
|
||||
/* Deliver the signal */
|
||||
|
||||
((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb);
|
||||
(rtcb->sigdeliver)(rtcb);
|
||||
|
||||
/* Output any debug messages BEFORE restoring errno (because they may
|
||||
* alter errno), then disable interrupts again and restore the original
|
||||
|
@ -156,7 +156,7 @@ retry:
|
|||
* could be modified by a hostile program.
|
||||
*/
|
||||
|
||||
rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */
|
||||
rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */
|
||||
|
||||
/* Then restore the correct state for this thread of
|
||||
* execution.
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
@ -124,10 +125,10 @@ static void dispatch_syscall(void)
|
|||
|
||||
int arm_svcall(int irq, void *context, void *arg)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
uint32_t *regs = (uint32_t *)context;
|
||||
uint32_t cmd;
|
||||
|
||||
DEBUGASSERT(regs && regs == up_current_regs());
|
||||
cmd = regs[REG_R0];
|
||||
|
||||
/* The SVCall software interrupt is called with R0 = system call command
|
||||
|
@ -175,7 +176,7 @@ int arm_svcall(int irq, void *context, void *arg)
|
|||
case SYS_restore_context:
|
||||
{
|
||||
DEBUGASSERT(regs[REG_R1] != 0);
|
||||
up_set_current_regs((uint32_t *)regs[REG_R1]);
|
||||
tcb->xcp.regs = (uint32_t *)regs[REG_R1];
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -200,7 +201,7 @@ int arm_svcall(int irq, void *context, void *arg)
|
|||
{
|
||||
DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
|
||||
*(uint32_t **)regs[REG_R1] = regs;
|
||||
up_set_current_regs((uint32_t *)regs[REG_R2]);
|
||||
tcb->xcp.regs = (uint32_t *)regs[REG_R2];
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -397,7 +398,6 @@ int arm_svcall(int irq, void *context, void *arg)
|
|||
/* Return privileged mode */
|
||||
|
||||
regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
|
||||
|
||||
rtcb->xcp.sigreturn = 0;
|
||||
}
|
||||
break;
|
||||
|
@ -446,7 +446,7 @@ int arm_svcall(int irq, void *context, void *arg)
|
|||
|
||||
rtcb->flags |= TCB_FLAG_SYSCALL;
|
||||
#else
|
||||
svcerr("ERROR: Bad SYS call: %d\n", (int)regs[REG_R0]);
|
||||
svcerr("ERROR: Bad SYS call: %" PRId32 "\n", regs[REG_R0]);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
@ -460,24 +460,20 @@ int arm_svcall(int irq, void *context, void *arg)
|
|||
# ifndef CONFIG_DEBUG_SVCALL
|
||||
if (cmd > SYS_switch_context)
|
||||
# else
|
||||
if (regs != up_current_regs())
|
||||
if (regs != tcb->xcp.regs)
|
||||
# endif
|
||||
{
|
||||
regs = (uint32_t *)tcb->xcp.regs;
|
||||
|
||||
svcinfo("SVCall Return:\n");
|
||||
svcinfo(" R0: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
up_current_regs()[REG_R0], up_current_regs()[REG_R1],
|
||||
up_current_regs()[REG_R2], up_current_regs()[REG_R3],
|
||||
up_current_regs()[REG_R4], up_current_regs()[REG_R5],
|
||||
up_current_regs()[REG_R6], up_current_regs()[REG_R7]);
|
||||
regs[REG_R0], regs[REG_R1], regs[REG_R2], regs[REG_R3],
|
||||
regs[REG_R4], regs[REG_R5], regs[REG_R6], regs[REG_R7]);
|
||||
svcinfo(" R8: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
up_current_regs()[REG_R8], up_current_regs()[REG_R9],
|
||||
up_current_regs()[REG_R10], up_current_regs()[REG_R11],
|
||||
up_current_regs()[REG_R12], up_current_regs()[REG_R13],
|
||||
up_current_regs()[REG_R14], up_current_regs()[REG_R15]);
|
||||
regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11],
|
||||
regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]);
|
||||
svcinfo(" PSR: %08x EXC_RETURN: %08x CONTROL: %08x\n",
|
||||
up_current_regs()[REG_XPSR],
|
||||
up_current_regs()[REG_EXC_RETURN],
|
||||
up_current_regs()[REG_CONTROL]);
|
||||
regs[REG_XPSR], regs[REG_EXC_RETURN], regs[REG_CONTROL]);
|
||||
}
|
||||
# ifdef CONFIG_DEBUG_SVCALL
|
||||
else
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
|
||||
#include "chip.h"
|
||||
#include "arm_internal.h"
|
||||
#include "ram_vectors.h"
|
||||
#include "nvic.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
@ -74,12 +76,13 @@ static void start(void)
|
|||
/* Common exception entrypoint */
|
||||
|
||||
extern void exception_common(void);
|
||||
extern void exception_direct(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Public data
|
||||
****************************************************************************/
|
||||
|
||||
/* The v7m vector table consists of an array of function pointers, with the
|
||||
/* The v8m vector table consists of an array of function pointers, with the
|
||||
* first slot (vector zero) used to hold the initial stack pointer.
|
||||
*
|
||||
* As all exceptions (interrupts) are routed via exception_common, we just
|
||||
|
@ -100,5 +103,7 @@ const void * const _vectors[] locate_data(".vectors") =
|
|||
|
||||
/* Vectors 2 - n point directly at the generic handler */
|
||||
|
||||
[2 ... (15 + ARMV8M_PERIPHERAL_INTERRUPTS)] = &exception_common
|
||||
[2 ... NVIC_IRQ_PENDSV] = &exception_common,
|
||||
[(NVIC_IRQ_PENDSV + 1) ... (15 + ARMV8M_PERIPHERAL_INTERRUPTS)]
|
||||
= &exception_direct
|
||||
};
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
|
||||
uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
board_autoled_on(LED_INIRQ);
|
||||
|
||||
#ifdef CONFIG_SUPPRESS_INTERRUPTS
|
||||
|
@ -51,6 +53,16 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
|||
|
||||
DEBUGASSERT(up_current_regs() == NULL);
|
||||
|
||||
/* if irq == GIC_SMP_CPUSTART
|
||||
* We are initiating the multi-core jumping state to up_idle,
|
||||
* and we will use this_task(). Therefore, it cannot be overridden.
|
||||
*/
|
||||
|
||||
if (irq != GIC_SMP_CPUSTART)
|
||||
{
|
||||
tcb->xcp.regs = regs;
|
||||
}
|
||||
|
||||
/* Current regs non-zero indicates that we are processing an interrupt;
|
||||
* current_regs is also used to manage interrupt level context switches.
|
||||
*/
|
||||
|
@ -61,17 +73,22 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
|||
|
||||
irq_dispatch(irq, regs);
|
||||
|
||||
/* Restore the cpu lock */
|
||||
|
||||
if (regs != up_current_regs())
|
||||
if (regs != tcb->xcp.regs)
|
||||
{
|
||||
tcb = this_task();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(g_running_tasks[this_cpu()]);
|
||||
nxsched_resume_scheduler(tcb);
|
||||
|
||||
/* Record the new "running" task when context switch occurred.
|
||||
* g_running_tasks[] is only used by assertion logic for reporting
|
||||
* crashes.
|
||||
*/
|
||||
|
||||
g_running_tasks[this_cpu()] = this_task();
|
||||
regs = up_current_regs();
|
||||
regs = tcb->xcp.regs;
|
||||
}
|
||||
|
||||
/* Set current_regs to NULL to indicate that we are no longer in an
|
||||
|
|
|
@ -311,12 +311,12 @@
|
|||
|
||||
#ifdef CONFIG_ARCH_TRUSTZONE_SECURE
|
||||
# define GIC_SMP_CPUSTART GIC_IRQ_SGI9
|
||||
# define GIC_SMP_CPUPAUSE GIC_IRQ_SGI10
|
||||
# define GIC_SMP_CPUCALL GIC_IRQ_SGI11
|
||||
# define GIC_SMP_CALL GIC_IRQ_SGI10
|
||||
# define GIC_SMP_SCHED GIC_IRQ_SGI11
|
||||
#else
|
||||
# define GIC_SMP_CPUSTART GIC_IRQ_SGI1
|
||||
# define GIC_SMP_CPUPAUSE GIC_IRQ_SGI2
|
||||
# define GIC_SMP_CPUCALL GIC_IRQ_SGI3
|
||||
# define GIC_SMP_CALL GIC_IRQ_SGI2
|
||||
# define GIC_SMP_SCHED GIC_IRQ_SGI3
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -333,28 +333,7 @@ int arm_gic_raise_sgi(unsigned int sgi_id, uint16_t target_list);
|
|||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_pause_handler
|
||||
*
|
||||
* Description:
|
||||
* This is the handler for SGI2. It performs the following operations:
|
||||
*
|
||||
* 1. It saves the current task state at the head of the current assigned
|
||||
* task list.
|
||||
* 2. It waits on a spinlock, then
|
||||
* 3. Returns from interrupt, restoring the state of the new task at the
|
||||
* head of the ready to run list.
|
||||
*
|
||||
* Input Parameters:
|
||||
* Standard interrupt handling
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int arm_pause_handler(int irq, void *context, void *arg);
|
||||
|
||||
int arm_smp_sched_handler(int irq, void *context, void *arg);
|
||||
void arm_gic_secondary_init(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -567,9 +567,8 @@ static void gicv3_dist_init(void)
|
|||
#ifdef CONFIG_SMP
|
||||
/* Attach SGI interrupt handlers. This attaches the handler to all CPUs. */
|
||||
|
||||
DEBUGVERIFY(irq_attach(GIC_SMP_CPUPAUSE, arm64_pause_handler, NULL));
|
||||
DEBUGVERIFY(irq_attach(GIC_SMP_CPUCALL,
|
||||
nxsched_smp_call_handler, NULL));
|
||||
DEBUGVERIFY(irq_attach(GIC_SMP_SCHED, arm64_smp_sched_handler, NULL));
|
||||
DEBUGVERIFY(irq_attach(GIC_SMP_CALL, nxsched_smp_call_handler, NULL));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -813,7 +812,8 @@ static void arm_gic_init(void)
|
|||
gicv3_cpuif_init();
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
up_enable_irq(GIC_SMP_CPUPAUSE);
|
||||
up_enable_irq(GIC_SMP_CALL);
|
||||
up_enable_irq(GIC_SMP_SCHED);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -841,24 +841,4 @@ void arm_gic_secondary_init(void)
|
|||
arm_gic_init();
|
||||
}
|
||||
|
||||
# ifdef CONFIG_SMP
|
||||
/***************************************************************************
|
||||
* Name: up_send_smp_call
|
||||
*
|
||||
* Description:
|
||||
* Send smp call to target cpu.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cpuset - The set of CPUs to receive the SGI.
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
void up_send_smp_call(cpu_set_t cpuset)
|
||||
{
|
||||
up_trigger_irq(GIC_SMP_CPUCALL, cpuset);
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
|
|
@ -75,342 +75,56 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
void up_schedule_sigaction(struct tcb_s *tcb)
|
||||
{
|
||||
sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
|
||||
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(),
|
||||
this_task()->xcp.regs);
|
||||
|
||||
/* Refuse to handle nested signal actions */
|
||||
/* First, handle some special cases when the signal is
|
||||
* being delivered to the currently executing task.
|
||||
*/
|
||||
|
||||
if (!tcb->xcp.sigdeliver)
|
||||
if (tcb == this_task() && !up_interrupt_context())
|
||||
{
|
||||
tcb->xcp.sigdeliver = sigdeliver;
|
||||
|
||||
/* First, handle some special cases when the signal is being delivered
|
||||
* to the currently executing task.
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handler will run in a critical section!
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb == this_task())
|
||||
{
|
||||
/* CASE 1: We are not in an interrupt handler and a task is
|
||||
* signalling itself for some reason.
|
||||
*/
|
||||
|
||||
if (!up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now. */
|
||||
|
||||
sigdeliver(tcb);
|
||||
tcb->xcp.sigdeliver = NULL;
|
||||
}
|
||||
|
||||
/* CASE 2: We are in an interrupt handler AND the interrupted
|
||||
* task is the same as the one that must receive the signal, then
|
||||
* we will have to modify the return state as well as the state
|
||||
* in the TCB.
|
||||
*
|
||||
* Hmmm... there looks like a latent bug here: The following logic
|
||||
* would fail in the strange case where we are in an interrupt
|
||||
* handler, the thread is signalling itself, but a context switch
|
||||
* to another task has occurred so that current_regs does not
|
||||
* refer to the thread of this_task()!
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the return lr and cpsr and one scratch register
|
||||
* These will be restored by the signal trampoline after
|
||||
* the signals have been delivered.
|
||||
*/
|
||||
|
||||
/* And make sure that the saved context in the TCB is the same
|
||||
* as the interrupt return context.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.saved_regs);
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
|
||||
memcpy(up_current_regs(), tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() +
|
||||
XCPTCONTEXT_REGS);
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
up_current_regs()[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
up_current_regs()[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ENDIAN_BIG
|
||||
up_current_regs()[REG_CPSR] |= PSR_E_BIT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, we are (1) signaling a task is not running from an
|
||||
* interrupt handler or (2) we are not in an interrupt handler and the
|
||||
* running task is signalling some non-running task.
|
||||
(tcb->sigdeliver)(tcb);
|
||||
tcb->sigdeliver = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Save the return lr and cpsr and one scratch register. These
|
||||
* will be restored by the signal trampoline after the signals
|
||||
* have been delivered.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the return lr and cpsr and one scratch register. These
|
||||
* will be restored by the signal trampoline after the signals
|
||||
* have been delivered.
|
||||
*/
|
||||
/* Save the current register context location */
|
||||
|
||||
/* Save the current register context location */
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
|
||||
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT);
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
||||
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ENDIAN_BIG
|
||||
tcb->xcp.regs[REG_CPSR] |= PSR_E_BIT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
{
|
||||
int cpu;
|
||||
int me;
|
||||
|
||||
sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
|
||||
|
||||
/* Refuse to handle nested signal actions */
|
||||
|
||||
if (!tcb->xcp.sigdeliver)
|
||||
{
|
||||
tcb->xcp.sigdeliver = sigdeliver;
|
||||
|
||||
/* First, handle some special cases when the signal is being delivered
|
||||
* to task that is currently executing on any CPU.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
|
||||
|
||||
if (tcb->task_state == TSTATE_TASK_RUNNING)
|
||||
{
|
||||
me = this_cpu();
|
||||
cpu = tcb->cpu;
|
||||
|
||||
/* CASE 1: We are not in an interrupt handler and a task is
|
||||
* signaling itself for some reason.
|
||||
*/
|
||||
|
||||
if (cpu == me && !up_current_regs())
|
||||
{
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handler will run in a critical section!
|
||||
*/
|
||||
|
||||
sigdeliver(tcb);
|
||||
tcb->xcp.sigdeliver = NULL;
|
||||
}
|
||||
|
||||
/* CASE 2: The task that needs to receive the signal is running.
|
||||
* This could happen if the task is running on another CPU OR if
|
||||
* we are in an interrupt handler and the task is running on this
|
||||
* CPU. In the former case, we will have to PAUSE the other CPU
|
||||
* first. But in either case, we will have to modify the return
|
||||
* state as well as the state in the TCB.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* If we signaling a task running on the other CPU, we have
|
||||
* to PAUSE the other CPU.
|
||||
*/
|
||||
|
||||
if (cpu != me)
|
||||
{
|
||||
/* Pause the CPU */
|
||||
|
||||
up_cpu_pause(cpu);
|
||||
|
||||
/* Now tcb on the other CPU can be accessed safely */
|
||||
|
||||
/* Copy tcb->xcp.regs to tcp.xcp.saved. These will be
|
||||
* restored by the signal trampoline after the signal has
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
/* Save the current register context location */
|
||||
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
/* tcb is running on the same CPU */
|
||||
|
||||
/* Save the return PC, CPSR and either the BASEPRI or
|
||||
* PRIMASK registers (and perhaps also the LR). These will
|
||||
* be restored by the signal trampoline after the signal
|
||||
* has been delivered.
|
||||
*/
|
||||
|
||||
/* And make sure that the saved context in the TCB is the
|
||||
* same as the interrupt return context.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.saved_regs);
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
|
||||
memcpy(up_current_regs(), tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
up_current_regs()[REG_SP] = (uint32_t)(up_current_regs()
|
||||
+ XCPTCONTEXT_REGS);
|
||||
|
||||
/* Then set up vector to the trampoline with interrupts
|
||||
* disabled. The kernel-space trampoline must run in
|
||||
* privileged thread mode.
|
||||
*/
|
||||
|
||||
up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
up_current_regs()[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
up_current_regs()[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Increment the IRQ lock count so that when the task is
|
||||
* restarted, it will hold the IRQ spinlock.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(tcb->irqcount < INT16_MAX);
|
||||
tcb->irqcount++;
|
||||
|
||||
/* NOTE: If the task runs on another CPU(cpu), adjusting
|
||||
* global IRQ controls will be done in the pause handler
|
||||
* on the CPU(cpu) by taking a critical section.
|
||||
* If the task is scheduled on this CPU(me), do nothing
|
||||
* because this CPU already took a critical section
|
||||
*/
|
||||
|
||||
/* RESUME the other CPU if it was PAUSED */
|
||||
|
||||
if (cpu != me)
|
||||
{
|
||||
up_cpu_resume(cpu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, we are (1) signaling a task is not running from an
|
||||
* interrupt handler or (2) we are not in an interrupt handler and the
|
||||
* running task is signaling some other non-running task.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the return lr and cpsr and one scratch register. These
|
||||
* will be restored by the signal trampoline after the signals
|
||||
* have been delivered.
|
||||
*/
|
||||
|
||||
/* Save the current register context location */
|
||||
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
|
||||
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
|
||||
/* Increment the IRQ lock count so that when the task is restarted,
|
||||
* it will hold the IRQ spinlock.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(tcb->irqcount < INT16_MAX);
|
||||
tcb->irqcount++;
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -68,8 +68,8 @@ void arm_sigdeliver(void)
|
|||
board_autoled_on(LED_SIGNAL);
|
||||
|
||||
sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n",
|
||||
rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head);
|
||||
DEBUGASSERT(rtcb->xcp.sigdeliver != NULL);
|
||||
rtcb, rtcb->sigdeliver, rtcb->sigpendactionq.head);
|
||||
DEBUGASSERT(rtcb->sigdeliver != NULL);
|
||||
|
||||
retry:
|
||||
#ifdef CONFIG_SMP
|
||||
|
@ -101,7 +101,7 @@ retry:
|
|||
|
||||
/* Deliver the signal */
|
||||
|
||||
((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb);
|
||||
(rtcb->sigdeliver)(rtcb);
|
||||
|
||||
/* Output any debug messages BEFORE restoring errno (because they may
|
||||
* alter errno), then disable interrupts again and restore the original
|
||||
|
@ -145,7 +145,7 @@ retry:
|
|||
* could be modified by a hostile program.
|
||||
*/
|
||||
|
||||
rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */
|
||||
rtcb->sigdeliver = NULL; /* Allows next handler to be scheduled */
|
||||
|
||||
/* Then restore the correct state for this thread of execution. */
|
||||
|
||||
|
|
|
@ -156,7 +156,7 @@ static void dispatch_syscall(void)
|
|||
|
||||
uint32_t *arm_syscall(uint32_t *regs)
|
||||
{
|
||||
struct tcb_s *tcb;
|
||||
struct tcb_s *tcb = this_task();
|
||||
uint32_t cmd;
|
||||
int cpu;
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
|
@ -167,6 +167,8 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||
|
||||
DEBUGASSERT(up_current_regs() == NULL);
|
||||
|
||||
tcb->xcp.regs = regs;
|
||||
|
||||
/* Current regs non-zero indicates that we are processing an interrupt;
|
||||
* current_regs is also used to manage interrupt level context switches.
|
||||
*/
|
||||
|
@ -268,7 +270,7 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||
* set will determine the restored context.
|
||||
*/
|
||||
|
||||
up_set_current_regs((uint32_t *)regs[REG_R1]);
|
||||
tcb->xcp.regs = (uint32_t *)regs[REG_R1];
|
||||
DEBUGASSERT(up_current_regs());
|
||||
}
|
||||
break;
|
||||
|
@ -294,7 +296,7 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||
{
|
||||
DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
|
||||
*(uint32_t **)regs[REG_R1] = regs;
|
||||
up_set_current_regs((uint32_t *)regs[REG_R2]);
|
||||
tcb->xcp.regs = (uint32_t *)regs[REG_R2];
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -424,7 +426,7 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||
|
||||
/* Copy "info" into user stack */
|
||||
|
||||
if (rtcb->xcp.sigdeliver)
|
||||
if (rtcb->sigdeliver)
|
||||
{
|
||||
usp = rtcb->xcp.saved_regs[REG_SP];
|
||||
}
|
||||
|
@ -561,22 +563,25 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||
break;
|
||||
}
|
||||
|
||||
/* Restore the cpu lock */
|
||||
|
||||
if (regs != up_current_regs())
|
||||
if (regs != tcb->xcp.regs)
|
||||
{
|
||||
cpu = this_cpu();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(g_running_tasks[cpu]);
|
||||
nxsched_resume_scheduler(tcb);
|
||||
|
||||
/* Record the new "running" task. g_running_tasks[] is only used by
|
||||
* assertion logic for reporting crashes.
|
||||
*/
|
||||
|
||||
cpu = this_cpu();
|
||||
tcb = current_task(cpu);
|
||||
g_running_tasks[cpu] = tcb;
|
||||
|
||||
/* Restore the cpu lock */
|
||||
|
||||
restore_critical_section(tcb, cpu);
|
||||
regs = up_current_regs();
|
||||
regs = tcb->xcp.regs;
|
||||
}
|
||||
|
||||
/* Report what happened */
|
||||
|
|
|
@ -1586,7 +1586,7 @@ static int at32can_rxinterrupt(struct can_dev_s *dev, int rxmb)
|
|||
#ifdef CONFIG_CAN_ERRORS
|
||||
hdr.ch_error = 0; /* Error reporting not supported */
|
||||
#endif
|
||||
hdr.ch_unused = 0;
|
||||
hdr.ch_tcf = 0;
|
||||
|
||||
/* Extract the RTR bit */
|
||||
|
||||
|
@ -1895,7 +1895,7 @@ static int at32can_sceinterrupt(int irq, void *context, void *arg)
|
|||
#ifdef CONFIG_CAN_EXTID
|
||||
hdr.ch_extid = 0;
|
||||
#endif
|
||||
hdr.ch_unused = 0;
|
||||
hdr.ch_tcf = 0;
|
||||
|
||||
/* And provide the error report to the upper half logic */
|
||||
|
||||
|
|
|
@ -56,12 +56,6 @@ void up_exit(int status)
|
|||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
/* Make sure that we are in a critical section with local interrupts.
|
||||
* The IRQ state will be restored when the next task is started.
|
||||
*/
|
||||
|
||||
enter_critical_section();
|
||||
|
||||
/* Destroy the task at the head of the ready to run list. */
|
||||
|
||||
nxtask_exit();
|
||||
|
|
|
@ -96,11 +96,6 @@
|
|||
|
||||
#define INTSTACK_SIZE (CONFIG_ARCH_INTERRUPTSTACK & ~STACK_ALIGN_MASK)
|
||||
|
||||
/* Macros to handle saving and restoring interrupt state. */
|
||||
|
||||
#define arm_savestate(regs) (regs = up_current_regs())
|
||||
#define arm_restorestate(regs) up_set_current_regs(regs)
|
||||
|
||||
/* Toolchain dependent, linker defined section addresses */
|
||||
|
||||
#if defined(__ICCARM__)
|
||||
|
|
|
@ -55,39 +55,10 @@
|
|||
|
||||
void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb)
|
||||
{
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(rtcb);
|
||||
|
||||
/* Are we in an interrupt handler? */
|
||||
|
||||
if (up_current_regs())
|
||||
if (!up_interrupt_context())
|
||||
{
|
||||
/* Yes, then we have to do things differently.
|
||||
* Just copy the current_regs into the OLD rtcb.
|
||||
*/
|
||||
|
||||
arm_savestate(rtcb->xcp.regs);
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_resume_scheduler(tcb);
|
||||
|
||||
/* Then switch contexts. Any necessary address environment
|
||||
* changes will be made when the interrupt returns.
|
||||
*/
|
||||
|
||||
arm_restorestate(tcb->xcp.regs);
|
||||
}
|
||||
|
||||
/* No, then we will need to perform the user context switch */
|
||||
|
||||
else
|
||||
{
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_resume_scheduler(tcb);
|
||||
|
||||
/* Switch context to the context of the task at the head of the
|
||||
* ready to run list.
|
||||
*/
|
||||
|
|
|
@ -42,7 +42,7 @@ set(SRCS
|
|||
if(CONFIG_SMP)
|
||||
list(APPEND SRCS cxd56_cpuidlestack.c)
|
||||
list(APPEND SRCS cxd56_cpuindex.c)
|
||||
list(APPEND SRCS cxd56_cpupause.c)
|
||||
list(APPEND SRCS cxd56_smpcall.c)
|
||||
list(APPEND SRCS cxd56_cpustart.c)
|
||||
if(CONFIG_CXD56_TESTSET)
|
||||
list(APPEND SRCS cxd56_testset.c)
|
||||
|
|
|
@ -41,7 +41,7 @@ CHIP_CSRCS += cxd56_sysctl.c
|
|||
ifeq ($(CONFIG_SMP), y)
|
||||
CHIP_CSRCS += cxd56_cpuidlestack.c
|
||||
CHIP_CSRCS += cxd56_cpuindex.c
|
||||
CHIP_CSRCS += cxd56_cpupause.c
|
||||
CHIP_CSRCS += cxd56_smpcall.c
|
||||
CHIP_CSRCS += cxd56_cpustart.c
|
||||
ifeq ($(CONFIG_CXD56_TESTSET),y)
|
||||
CHIP_CSRCS += cxd56_testset.c
|
||||
|
|
|
@ -1,584 +0,0 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/cxd56xx/cxd56_cpupause.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/sched_note.h>
|
||||
|
||||
#include "sched/sched.h"
|
||||
#include "arm_internal.h"
|
||||
#include "hardware/cxd5602_memorymap.h"
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#if 0
|
||||
# define DPRINTF(fmt, args...) _err(fmt, ##args)
|
||||
#else
|
||||
# define DPRINTF(fmt, args...) do {} while (0)
|
||||
#endif
|
||||
|
||||
#define CXD56_CPU_P2_INT (CXD56_SWINT_BASE + 0x8) /* for APP_DSP0 */
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* These spinlocks are used in the SMP configuration in order to implement
|
||||
* up_cpu_pause(). The protocol for CPUn to pause CPUm is as follows
|
||||
*
|
||||
* 1. The up_cpu_pause() implementation on CPUn locks both g_cpu_wait[m]
|
||||
* and g_cpu_paused[m]. CPUn then waits spinning on g_cpu_paused[m].
|
||||
* 2. CPUm receives the interrupt it (1) unlocks g_cpu_paused[m] and
|
||||
* (2) locks g_cpu_wait[m]. The first unblocks CPUn and the second
|
||||
* blocks CPUm in the interrupt handler.
|
||||
*
|
||||
* When CPUm resumes, CPUn unlocks g_cpu_wait[m] and the interrupt handler
|
||||
* on CPUm continues. CPUm must, of course, also then unlock g_cpu_wait[m]
|
||||
* so that it will be ready for the next pause operation.
|
||||
*/
|
||||
|
||||
static volatile spinlock_t g_cpu_wait[CONFIG_SMP_NCPUS];
|
||||
static volatile spinlock_t g_cpu_paused[CONFIG_SMP_NCPUS];
|
||||
static volatile spinlock_t g_cpu_resumed[CONFIG_SMP_NCPUS];
|
||||
|
||||
static volatile int g_irq_to_handle[CONFIG_SMP_NCPUS][2];
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: handle_irqreq
|
||||
*
|
||||
* Description:
|
||||
* If an irq handling request is found on cpu, call up_enable_irq() or
|
||||
* up_disable_irq(), then return true.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cpu - The index of the CPU to be queried
|
||||
*
|
||||
* Returned Value:
|
||||
* true = an irq handling request is found
|
||||
* false = no irq handling request is found
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static bool handle_irqreq(int cpu)
|
||||
{
|
||||
int i;
|
||||
bool handled = false;
|
||||
|
||||
/* Check both cases */
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
int irqreq = g_irq_to_handle[cpu][i];
|
||||
|
||||
if (irqreq)
|
||||
{
|
||||
/* Unlock the spinlock first */
|
||||
|
||||
spin_unlock(&g_cpu_paused[cpu]);
|
||||
|
||||
/* Then wait for the spinlock to be released */
|
||||
|
||||
spin_lock(&g_cpu_wait[cpu]);
|
||||
|
||||
/* Clear g_irq_to_handle[cpu][i] */
|
||||
|
||||
g_irq_to_handle[cpu][i] = 0;
|
||||
|
||||
if (0 == i)
|
||||
{
|
||||
up_enable_irq(irqreq);
|
||||
}
|
||||
else
|
||||
{
|
||||
up_disable_irq(irqreq);
|
||||
}
|
||||
|
||||
/* Finally unlock the spinlock */
|
||||
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
handled = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_pausereq
|
||||
*
|
||||
* Description:
|
||||
* Return true if a pause request is pending for this CPU.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cpu - The index of the CPU to be queried
|
||||
*
|
||||
* Returned Value:
|
||||
* true = a pause request is pending.
|
||||
* false = no pasue request is pending.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
bool up_cpu_pausereq(int cpu)
|
||||
{
|
||||
return spin_is_locked(&g_cpu_paused[cpu]);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_save
|
||||
*
|
||||
* Description:
|
||||
* Handle a pause request from another CPU. Normally, this logic is
|
||||
* executed from interrupt handling logic within the architecture-specific
|
||||
* However, it is sometimes necessary to perform the pending
|
||||
* pause operation in other contexts where the interrupt cannot be taken
|
||||
* in order to avoid deadlocks.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_save(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
/* Update scheduler parameters */
|
||||
|
||||
nxsched_suspend_scheduler(tcb);
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we are paused */
|
||||
|
||||
sched_note_cpu_paused(tcb);
|
||||
#endif
|
||||
|
||||
/* Save the current context at current_regs into the TCB at the head
|
||||
* of the assigned task list for this CPU.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.regs);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused
|
||||
*
|
||||
* Description:
|
||||
* Handle a pause request from another CPU. Normally, this logic is
|
||||
* executed from interrupt handling logic within the architecture-specific
|
||||
* However, it is sometimes necessary to perform the pending
|
||||
* pause operation in other contexts where the interrupt cannot be taken
|
||||
* in order to avoid deadlocks.
|
||||
*
|
||||
* This function performs the following operations:
|
||||
*
|
||||
* 1. It saves the current task state at the head of the current assigned
|
||||
* task list.
|
||||
* 2. It waits on a spinlock, then
|
||||
* 3. Returns from interrupt, restoring the state of the new task at the
|
||||
* head of the ready to run list.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cpu - The index of the CPU to be paused
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused(int cpu)
|
||||
{
|
||||
/* Fistly, check if this IPI is to enable/disable IRQ */
|
||||
|
||||
if (handle_irqreq(cpu))
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Wait for the spinlock to be released */
|
||||
|
||||
spin_unlock(&g_cpu_paused[cpu]);
|
||||
|
||||
/* Ensure the CPU has been resumed to avoid causing a deadlock */
|
||||
|
||||
spin_lock(&g_cpu_resumed[cpu]);
|
||||
|
||||
spin_lock(&g_cpu_wait[cpu]);
|
||||
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_paused_restore
|
||||
*
|
||||
* Description:
|
||||
* Restore the state of the CPU after it was paused via up_cpu_pause(),
|
||||
* and resume normal tasking.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, OK is returned. Otherwise, a negated errno value indicating
|
||||
* the nature of the failure is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_paused_restore(void)
|
||||
{
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify that we have resumed */
|
||||
|
||||
sched_note_cpu_resumed(tcb);
|
||||
#endif
|
||||
|
||||
/* Reset scheduler parameters */
|
||||
|
||||
nxsched_resume_scheduler(tcb);
|
||||
|
||||
/* Then switch contexts. Any necessary address environment changes
|
||||
* will be made when the interrupt returns.
|
||||
*/
|
||||
|
||||
arm_restorestate(tcb->xcp.regs);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_pause_handler
|
||||
*
|
||||
* Description:
|
||||
* Inter-CPU interrupt handler
|
||||
*
|
||||
* Input Parameters:
|
||||
* Standard interrupt handler inputs
|
||||
*
|
||||
* Returned Value:
|
||||
* Should always return OK
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int arm_pause_handler(int irq, void *c, void *arg)
|
||||
{
|
||||
int cpu = this_cpu();
|
||||
int ret = OK;
|
||||
|
||||
nxsched_smp_call_handler(irq, c, arg);
|
||||
|
||||
DPRINTF("cpu%d will be paused\n", cpu);
|
||||
|
||||
/* Clear SW_INT for APP_DSP(cpu) */
|
||||
|
||||
putreg32(0, CXD56_CPU_P2_INT + (4 * cpu));
|
||||
|
||||
/* Check for false alarms. Such false could occur as a consequence of
|
||||
* some deadlock breaking logic that might have already serviced the SG2
|
||||
* interrupt by calling up_cpu_paused.
|
||||
*/
|
||||
|
||||
if (up_cpu_pausereq(cpu))
|
||||
{
|
||||
/* NOTE: The following enter_critical_section() would call
|
||||
* up_cpu_paused() to process a pause request to break a deadlock
|
||||
* because the caller held a critical section. Once up_cpu_paused()
|
||||
* finished, the caller will proceed and release the g_cpu_irqlock.
|
||||
* Then this CPU will acquire g_cpu_irqlock in the function.
|
||||
*/
|
||||
|
||||
irqstate_t flags = enter_critical_section();
|
||||
|
||||
/* NOTE: Normally, we do not call up_cpu_paused() here because
|
||||
* the above enter_critical_setion() would call up_cpu_paused()
|
||||
* inside because the caller holds a crtical section.
|
||||
* However, cxd56's remote IRQ control logic also uses this handler
|
||||
* and a caller might not take a critical section to avoid a deadlock
|
||||
* during up_enable_irq() and up_disable_irq(). This is allowed
|
||||
* because IRQ control logic does not interact wtih the scheduler.
|
||||
* This means that if the request was not handled above, we need
|
||||
* to call up_cpu_paused() here again.
|
||||
*/
|
||||
|
||||
if (up_cpu_pausereq(cpu))
|
||||
{
|
||||
ret = up_cpu_paused(cpu);
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_pause_async
|
||||
*
|
||||
* Description:
|
||||
* pause task execution on the CPU
|
||||
* check whether there are tasks delivered to specified cpu
|
||||
* and try to run them.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cpu - The index of the CPU to be paused.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
* Assumptions:
|
||||
* Called from within a critical section;
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
inline_function int up_cpu_pause_async(int cpu)
|
||||
{
|
||||
/* Generate IRQ for CPU(cpu) */
|
||||
|
||||
putreg32(1, CXD56_CPU_P2_INT + (4 * cpu));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_send_smp_call
|
||||
*
|
||||
* Description:
|
||||
* Send smp call to target cpu.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cpuset - The set of CPUs to receive the SGI.
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_send_smp_call(cpu_set_t cpuset)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
for (; cpuset != 0; cpuset &= ~(1 << cpu))
|
||||
{
|
||||
cpu = ffs(cpuset) - 1;
|
||||
up_cpu_pause_async(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_pause
|
||||
*
|
||||
* Description:
|
||||
* Save the state of the current task at the head of the
|
||||
* g_assignedtasks[cpu] task list and then pause task execution on the
|
||||
* CPU.
|
||||
*
|
||||
* This function is called by the OS when the logic executing on one CPU
|
||||
* needs to modify the state of the g_assignedtasks[cpu] list for another
|
||||
* CPU.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cpu - The index of the CPU to be stopped/
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_pause(int cpu)
|
||||
{
|
||||
DPRINTF("cpu=%d\n", cpu);
|
||||
|
||||
DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify of the pause event */
|
||||
|
||||
sched_note_cpu_pause(this_task(), cpu);
|
||||
#endif
|
||||
|
||||
/* Take the both spinlocks. The g_cpu_wait spinlock will prevent the
|
||||
* handler from returning until up_cpu_resume() is called; g_cpu_paused
|
||||
* is a handshake that will prefent this function from returning until
|
||||
* the CPU is actually paused.
|
||||
* Note that we might spin before getting g_cpu_wait, this just means that
|
||||
* the other CPU still hasn't finished responding to the previous resume
|
||||
* request.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(!spin_is_locked(&g_cpu_paused[cpu]));
|
||||
|
||||
spin_lock(&g_cpu_wait[cpu]);
|
||||
spin_lock(&g_cpu_paused[cpu]);
|
||||
|
||||
/* Generate IRQ for CPU(cpu) */
|
||||
|
||||
up_cpu_pause_async(cpu);
|
||||
|
||||
/* Wait for the other CPU to unlock g_cpu_paused meaning that
|
||||
* it is fully paused and ready for up_cpu_resume();
|
||||
*/
|
||||
|
||||
spin_lock(&g_cpu_paused[cpu]);
|
||||
spin_unlock(&g_cpu_paused[cpu]);
|
||||
|
||||
/* On successful return g_cpu_wait will be locked, the other CPU will be
|
||||
* spinning on g_cpu_wait and will not continue until g_cpu_resume() is
|
||||
* called. g_cpu_paused will be unlocked in any case.
|
||||
*/
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_cpu_resume
|
||||
*
|
||||
* Description:
|
||||
* Restart the cpu after it was paused via up_cpu_pause(), restoring the
|
||||
* state of the task at the head of the g_assignedtasks[cpu] list, and
|
||||
* resume normal tasking.
|
||||
*
|
||||
* This function is called after up_cpu_pause in order resume operation of
|
||||
* the CPU after modifying its g_assignedtasks[cpu] list.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cpu - The index of the CPU being re-started.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_resume(int cpu)
|
||||
{
|
||||
DPRINTF("cpu=%d\n", cpu);
|
||||
|
||||
DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||
/* Notify of the resume event */
|
||||
|
||||
sched_note_cpu_resume(this_task(), cpu);
|
||||
#endif
|
||||
|
||||
/* Release the spinlock. Releasing the spinlock will cause the SGI2
|
||||
* handler on 'cpu' to continue and return from interrupt to the newly
|
||||
* established thread.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(spin_is_locked(&g_cpu_wait[cpu]) &&
|
||||
!spin_is_locked(&g_cpu_paused[cpu]));
|
||||
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
|
||||
/* Ensure the CPU has been resumed to avoid causing a deadlock */
|
||||
|
||||
spin_lock(&g_cpu_resumed[cpu]);
|
||||
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_send_irqreq()
|
||||
*
|
||||
* Description:
|
||||
* Send up_enable_irq() / up_disable_irq() request to the specified cpu
|
||||
*
|
||||
* This function is called from up_enable_irq() or up_disable_irq()
|
||||
* to be handled on specified CPU. Locking protocol in the sequence is
|
||||
* the same as up_pause_cpu() plus up_resume_cpu().
|
||||
*
|
||||
* Input Parameters:
|
||||
* idx - The request index (0: enable, 1: disable)
|
||||
* irq - The IRQ number to be handled
|
||||
* cpu - The index of the CPU which will handle the request
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_send_irqreq(int idx, int irq, int cpu)
|
||||
{
|
||||
DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
|
||||
|
||||
/* Wait for the spinlocks to be released */
|
||||
|
||||
spin_lock(&g_cpu_wait[cpu]);
|
||||
spin_lock(&g_cpu_paused[cpu]);
|
||||
|
||||
/* Set irq for the cpu */
|
||||
|
||||
g_irq_to_handle[cpu][idx] = irq;
|
||||
|
||||
/* Generate IRQ for CPU(cpu) */
|
||||
|
||||
putreg32(1, CXD56_CPU_P2_INT + (4 * cpu));
|
||||
|
||||
/* Wait for the handler is executed on cpu */
|
||||
|
||||
spin_lock(&g_cpu_paused[cpu]);
|
||||
spin_unlock(&g_cpu_paused[cpu]);
|
||||
|
||||
/* Finally unlock the spinlock to proceed the handler */
|
||||
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
|
||||
/* Ensure the CPU has been resumed to avoid causing a deadlock */
|
||||
|
||||
spin_lock(&g_cpu_resumed[cpu]);
|
||||
|
||||
spin_unlock(&g_cpu_resumed[cpu]);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SMP */
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue