Compare commits
88 Commits
main
...
backport-9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
65402def79 | ||
|
|
2a079897bb | ||
|
|
be5cae2111 | ||
|
|
daaf54ca4b | ||
|
|
42d8b98765 | ||
|
|
a8ea50bed3 | ||
|
|
223e2822f9 | ||
|
|
0ffde735ae | ||
|
|
bd91f219af | ||
|
|
57f48e6e8c | ||
|
|
915f7bb781 | ||
|
|
697706d295 | ||
|
|
69947f64a2 | ||
|
|
635d5c00e3 | ||
|
|
53f776a934 | ||
|
|
bf194b3d43 | ||
|
|
cb7ce14654 | ||
|
|
22f0033e60 | ||
|
|
674a54ce39 | ||
|
|
f4dc776671 | ||
|
|
1ee1798f50 | ||
|
|
636ad05950 | ||
|
|
81ab4dedbe | ||
|
|
57ab471c3a | ||
|
|
0b8771d299 | ||
|
|
13dd5cb1ae | ||
|
|
be61610d3f | ||
|
|
2c317b081d | ||
|
|
d7b09179c3 | ||
|
|
64e98eb527 | ||
|
|
4d44e3280b | ||
|
|
6da1cbcb06 | ||
|
|
1e5f5af4eb | ||
|
|
ee29ea2a20 | ||
|
|
3d4204036a | ||
|
|
c60a870b1c | ||
|
|
d26b221f53 | ||
|
|
9cb7b9e4ec | ||
|
|
e395a9a649 | ||
|
|
9526404c65 | ||
|
|
116c4a9e40 | ||
|
|
46292d748d | ||
|
|
51e1f38026 | ||
|
|
87b06394e6 | ||
|
|
9800d46c69 | ||
|
|
ac91402f71 | ||
|
|
e58bca83de | ||
|
|
91d1416460 | ||
|
|
cbb43bee3d | ||
|
|
989499c8f4 | ||
|
|
6eebe0acf0 | ||
|
|
1ea8bb2e0f | ||
|
|
4217df505a | ||
|
|
d1a9ef6b0b | ||
|
|
bf9345a1ec | ||
|
|
7f89472f14 | ||
|
|
e3a55c96ef | ||
|
|
663da2302b | ||
|
|
4670cb27c7 | ||
|
|
a55b5444c6 | ||
|
|
c1adc507d7 | ||
|
|
e918bdac38 | ||
|
|
8b5e0388cf | ||
|
|
3b7610ec5f | ||
|
|
2b0f179079 | ||
|
|
ff9fb454c6 | ||
|
|
5282c9fdc8 | ||
|
|
ee0aecc953 | ||
|
|
21c942f18c | ||
|
|
f017af445e | ||
|
|
01949d478d | ||
|
|
0dbc00a63b | ||
|
|
94b74dbd89 | ||
|
|
4c362f1aec | ||
|
|
bafc9f2a66 | ||
|
|
30de5e8a2c | ||
|
|
ff6295f930 | ||
|
|
738e159ede | ||
|
|
183444eed4 | ||
|
|
e2efcf7cb6 | ||
|
|
a494c09fcb | ||
|
|
fb8687a492 | ||
|
|
7abcf05115 | ||
|
|
2ff7f15e5f | ||
|
|
d1f998909d | ||
|
|
a9f222b9a7 | ||
|
|
58be950216 | ||
|
|
02f511bb93 |
2
.github/workflows/bsim-tests.yaml
vendored
2
.github/workflows/bsim-tests.yaml
vendored
@@ -42,7 +42,7 @@ jobs:
|
||||
runs-on:
|
||||
group: zephyr-runner-v2-linux-x64-4xlarge
|
||||
container:
|
||||
image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.28.1.20250624
|
||||
image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.28.4.20250818
|
||||
options: '--entrypoint /bin/bash'
|
||||
env:
|
||||
ZEPHYR_TOOLCHAIN_VARIANT: zephyr
|
||||
|
||||
2
.github/workflows/clang.yaml
vendored
2
.github/workflows/clang.yaml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
runs-on:
|
||||
group: zephyr-runner-v2-linux-x64-4xlarge
|
||||
container:
|
||||
image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.28.1.20250624
|
||||
image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.28.4.20250818
|
||||
options: '--entrypoint /bin/bash'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
2
.github/workflows/codecov.yaml
vendored
2
.github/workflows/codecov.yaml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
runs-on:
|
||||
group: zephyr-runner-v2-linux-x64-4xlarge
|
||||
container:
|
||||
image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.28.1.20250624
|
||||
image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.28.4.20250818
|
||||
options: '--entrypoint /bin/bash'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
6
.github/workflows/doc-build.yml
vendored
6
.github/workflows/doc-build.yml
vendored
@@ -108,10 +108,10 @@ jobs:
|
||||
cache-dependency-path: doc/requirements.txt
|
||||
|
||||
- name: Setup Zephyr project
|
||||
uses: zephyrproject-rtos/action-zephyr-setup@b2453c72966ee67b1433be22b250348d48283286 # v1.0.7
|
||||
uses: zephyrproject-rtos/action-zephyr-setup@cefbf9086ce2da7d70e7ad9589af8aa1e4bda265 # v1.0.11
|
||||
with:
|
||||
app-path: zephyr
|
||||
toolchains: 'all'
|
||||
toolchains: 'arm-zephyr-eabi'
|
||||
|
||||
- name: install-pip
|
||||
working-directory: zephyr
|
||||
@@ -226,7 +226,7 @@ jobs:
|
||||
echo "/opt/doxygen-${DOXYGEN_VERSION}/bin" >> $GITHUB_PATH
|
||||
|
||||
- name: Setup Zephyr project
|
||||
uses: zephyrproject-rtos/action-zephyr-setup@b2453c72966ee67b1433be22b250348d48283286 # v1.0.7
|
||||
uses: zephyrproject-rtos/action-zephyr-setup@cefbf9086ce2da7d70e7ad9589af8aa1e4bda265 # v1.0.11
|
||||
with:
|
||||
app-path: zephyr
|
||||
toolchains: 'arm-zephyr-eabi'
|
||||
|
||||
2
.github/workflows/errno.yml
vendored
2
.github/workflows/errno.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
check-errno:
|
||||
runs-on: ubuntu-24.04
|
||||
container:
|
||||
image: ghcr.io/zephyrproject-rtos/ci:v0.28.0
|
||||
image: ghcr.io/zephyrproject-rtos/ci:v0.28.4
|
||||
|
||||
steps:
|
||||
- name: Apply container owner mismatch workaround
|
||||
|
||||
2
.github/workflows/footprint-tracking.yml
vendored
2
.github/workflows/footprint-tracking.yml
vendored
@@ -28,7 +28,7 @@ jobs:
|
||||
group: zephyr-runner-v2-linux-x64-4xlarge
|
||||
if: github.repository_owner == 'zephyrproject-rtos'
|
||||
container:
|
||||
image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.28.1.20250624
|
||||
image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.28.4.20250818
|
||||
options: '--entrypoint /bin/bash'
|
||||
defaults:
|
||||
run:
|
||||
|
||||
@@ -59,7 +59,7 @@ jobs:
|
||||
python-version: 3.12
|
||||
|
||||
- name: Setup Zephyr project
|
||||
uses: zephyrproject-rtos/action-zephyr-setup@b2453c72966ee67b1433be22b250348d48283286 # v1.0.7
|
||||
uses: zephyrproject-rtos/action-zephyr-setup@cefbf9086ce2da7d70e7ad9589af8aa1e4bda265 # v1.0.11
|
||||
with:
|
||||
app-path: zephyr
|
||||
toolchains: aarch64-zephyr-elf:arc-zephyr-elf:arc64-zephyr-elf:arm-zephyr-eabi:mips-zephyr-elf:riscv64-zephyr-elf:sparc-zephyr-elf:x86_64-zephyr-elf:xtensa-dc233c_zephyr-elf:xtensa-sample_controller32_zephyr-elf:rx-zephyr-elf
|
||||
|
||||
6
.github/workflows/twister.yaml
vendored
6
.github/workflows/twister.yaml
vendored
@@ -65,10 +65,10 @@ jobs:
|
||||
|
||||
- name: Setup Zephyr project
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: zephyrproject-rtos/action-zephyr-setup@b2453c72966ee67b1433be22b250348d48283286 # v1.0.7
|
||||
uses: zephyrproject-rtos/action-zephyr-setup@cefbf9086ce2da7d70e7ad9589af8aa1e4bda265 # v1.0.11
|
||||
with:
|
||||
app-path: zephyr
|
||||
toolchains: all
|
||||
toolchains: 'arm-zephyr-eabi'
|
||||
|
||||
- name: Environment Setup
|
||||
working-directory: zephyr
|
||||
@@ -127,7 +127,7 @@ jobs:
|
||||
needs: twister-build-prep
|
||||
if: needs.twister-build-prep.outputs.size != 0
|
||||
container:
|
||||
image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.28.1.20250624
|
||||
image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.28.4.20250818
|
||||
options: '--entrypoint /bin/bash'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
2
.github/workflows/twister_tests_blackbox.yml
vendored
2
.github/workflows/twister_tests_blackbox.yml
vendored
@@ -45,7 +45,7 @@ jobs:
|
||||
cache-dependency-path: scripts/requirements-actions.txt
|
||||
|
||||
- name: Setup Zephyr project
|
||||
uses: zephyrproject-rtos/action-zephyr-setup@b2453c72966ee67b1433be22b250348d48283286 # v1.0.7
|
||||
uses: zephyrproject-rtos/action-zephyr-setup@cefbf9086ce2da7d70e7ad9589af8aa1e4bda265 # v1.0.11
|
||||
with:
|
||||
app-path: zephyr
|
||||
toolchains: all
|
||||
|
||||
@@ -214,24 +214,53 @@ endif()
|
||||
# 1) Using EXTRA_CFLAGS which is applied regardless of kconfig choice, or
|
||||
# 2) Rely on override support being implemented by your toolchain_cc_optimize_*()
|
||||
#
|
||||
get_property(OPTIMIZE_FOR_NO_OPTIMIZATIONS_FLAG TARGET compiler PROPERTY no_optimization)
|
||||
get_property(OPTIMIZE_FOR_DEBUG_FLAG TARGET compiler PROPERTY optimization_debug)
|
||||
get_property(OPTIMIZE_FOR_SPEED_FLAG TARGET compiler PROPERTY optimization_speed)
|
||||
get_property(OPTIMIZE_FOR_SIZE_FLAG TARGET compiler PROPERTY optimization_size)
|
||||
get_property(OPTIMIZE_FOR_SIZE_AGGRESSIVE_FLAG TARGET compiler PROPERTY optimization_size_aggressive)
|
||||
get_property(COMPILER_OPTIMIZE_FOR_NO_OPTIMIZATIONS_FLAG TARGET compiler PROPERTY no_optimization)
|
||||
get_property(COMPILER_OPTIMIZE_FOR_DEBUG_FLAG TARGET compiler PROPERTY optimization_debug)
|
||||
get_property(COMPILER_OPTIMIZE_FOR_SPEED_FLAG TARGET compiler PROPERTY optimization_speed)
|
||||
get_property(COMPILER_OPTIMIZE_FOR_SIZE_FLAG TARGET compiler PROPERTY optimization_size)
|
||||
get_property(COMPILER_OPTIMIZE_FOR_SIZE_AGGRESSIVE_FLAG TARGET compiler PROPERTY optimization_size_aggressive)
|
||||
|
||||
get_property(ASM_OPTIMIZE_FOR_NO_OPTIMIZATIONS_FLAG TARGET asm PROPERTY no_optimization)
|
||||
get_property(ASM_OPTIMIZE_FOR_DEBUG_FLAG TARGET asm PROPERTY optimization_debug)
|
||||
get_property(ASM_OPTIMIZE_FOR_SPEED_FLAG TARGET asm PROPERTY optimization_speed)
|
||||
get_property(ASM_OPTIMIZE_FOR_SIZE_FLAG TARGET asm PROPERTY optimization_size)
|
||||
get_property(ASM_OPTIMIZE_FOR_SIZE_AGGRESSIVE_FLAG TARGET asm PROPERTY optimization_size_aggressive)
|
||||
|
||||
# Let the assembler inherit the optimization flags of the compiler if it is
|
||||
# not set explicitly.
|
||||
if(NOT ASM_OPTIMIZE_FOR_NO_OPTIMIZATIONS_FLAG)
|
||||
set(ASM_OPTIMIZE_FOR_NO_OPTIMIZATIONS_FLAG ${COMPILER_OPTIMIZE_FOR_NO_OPTIMIZATIONS_FLAG})
|
||||
endif()
|
||||
if(NOT ASM_OPTIMIZE_FOR_DEBUG_FLAG)
|
||||
set(ASM_OPTIMIZE_FOR_DEBUG_FLAG ${COMPILER_OPTIMIZE_FOR_DEBUG_FLAG})
|
||||
endif()
|
||||
if(NOT ASM_OPTIMIZE_FOR_SPEED_FLAG)
|
||||
set(ASM_OPTIMIZE_FOR_SPEED_FLAG ${COMPILER_OPTIMIZE_FOR_SPEED_FLAG})
|
||||
endif()
|
||||
if(NOT ASM_OPTIMIZE_FOR_SIZE_FLAG)
|
||||
set(ASM_OPTIMIZE_FOR_SIZE_FLAG ${COMPILER_OPTIMIZE_FOR_SIZE_FLAG})
|
||||
endif()
|
||||
if(NOT ASM_OPTIMIZE_FOR_SIZE_AGGRESSIVE_FLAG)
|
||||
set(ASM_OPTIMIZE_FOR_SIZE_AGGRESSIVE_FLAG ${COMPILER_OPTIMIZE_FOR_SIZE_AGGRESSIVE_FLAG})
|
||||
endif()
|
||||
|
||||
# From kconfig choice, pick the actual OPTIMIZATION_FLAG to use.
|
||||
# Kconfig choice ensures only one of these CONFIG_*_OPTIMIZATIONS is set.
|
||||
if(CONFIG_NO_OPTIMIZATIONS)
|
||||
set(OPTIMIZATION_FLAG ${OPTIMIZE_FOR_NO_OPTIMIZATIONS_FLAG})
|
||||
set(COMPILER_OPTIMIZATION_FLAG ${COMPILER_OPTIMIZE_FOR_NO_OPTIMIZATIONS_FLAG})
|
||||
set(ASM_OPTIMIZATION_FLAG ${ASM_OPTIMIZE_FOR_NO_OPTIMIZATIONS_FLAG})
|
||||
elseif(CONFIG_DEBUG_OPTIMIZATIONS)
|
||||
set(OPTIMIZATION_FLAG ${OPTIMIZE_FOR_DEBUG_FLAG})
|
||||
set(COMPILER_OPTIMIZATION_FLAG ${COMPILER_OPTIMIZE_FOR_DEBUG_FLAG})
|
||||
set(ASM_OPTIMIZATION_FLAG ${ASM_OPTIMIZE_FOR_DEBUG_FLAG})
|
||||
elseif(CONFIG_SPEED_OPTIMIZATIONS)
|
||||
set(OPTIMIZATION_FLAG ${OPTIMIZE_FOR_SPEED_FLAG})
|
||||
set(COMPILER_OPTIMIZATION_FLAG ${COMPILER_OPTIMIZE_FOR_SPEED_FLAG})
|
||||
set(ASM_OPTIMIZATION_FLAG ${ASM_OPTIMIZE_FOR_SPEED_FLAG})
|
||||
elseif(CONFIG_SIZE_OPTIMIZATIONS)
|
||||
set(OPTIMIZATION_FLAG ${OPTIMIZE_FOR_SIZE_FLAG}) # Default in kconfig
|
||||
set(COMPILER_OPTIMIZATION_FLAG ${COMPILER_OPTIMIZE_FOR_SIZE_FLAG}) # Default in kconfig
|
||||
set(ASM_OPTIMIZATION_FLAG ${ASM_OPTIMIZE_FOR_SIZE_FLAG})
|
||||
elseif(CONFIG_SIZE_OPTIMIZATIONS_AGGRESSIVE)
|
||||
set(OPTIMIZATION_FLAG ${OPTIMIZE_FOR_SIZE_AGGRESSIVE_FLAG})
|
||||
set(COMPILER_OPTIMIZATION_FLAG ${COMPILER_OPTIMIZE_FOR_SIZE_AGGRESSIVE_FLAG})
|
||||
set(ASM_OPTIMIZATION_FLAG ${ASM_OPTIMIZE_FOR_SIZE_AGGRESSIVE_FLAG})
|
||||
else()
|
||||
message(FATAL_ERROR
|
||||
"Unreachable code. Expected optimization level to have been chosen. See Kconfig.zephyr")
|
||||
@@ -245,9 +274,9 @@ SOC_* symbol.")
|
||||
endif()
|
||||
|
||||
# Apply the final optimization flag(s)
|
||||
zephyr_compile_options($<$<COMPILE_LANGUAGE:ASM>:${OPTIMIZATION_FLAG}>)
|
||||
zephyr_compile_options($<$<COMPILE_LANGUAGE:C>:${OPTIMIZATION_FLAG}>)
|
||||
zephyr_compile_options($<$<COMPILE_LANGUAGE:CXX>:${OPTIMIZATION_FLAG}>)
|
||||
zephyr_compile_options($<$<COMPILE_LANGUAGE:ASM>:${ASM_OPTIMIZATION_FLAG}>)
|
||||
zephyr_compile_options($<$<COMPILE_LANGUAGE:C>:${COMPILER_OPTIMIZATION_FLAG}>)
|
||||
zephyr_compile_options($<$<COMPILE_LANGUAGE:CXX>:${COMPILER_OPTIMIZATION_FLAG}>)
|
||||
|
||||
if(CONFIG_LTO)
|
||||
zephyr_compile_options($<TARGET_PROPERTY:compiler,optimization_lto>)
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.17.2
|
||||
0.17.4
|
||||
|
||||
2
VERSION
2
VERSION
@@ -1,5 +1,5 @@
|
||||
VERSION_MAJOR = 4
|
||||
VERSION_MINOR = 2
|
||||
PATCHLEVEL = 0
|
||||
PATCHLEVEL = 1
|
||||
VERSION_TWEAK = 0
|
||||
EXTRAVERSION =
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2014 Wind River Systems, Inc.
|
||||
* Copyright (c) 2021 Lexmark International, Inc.
|
||||
* Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -37,6 +38,34 @@
|
||||
*/
|
||||
#define DEFAULT_EXC_RETURN 0xFD;
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
static void setup_priv_stack(struct k_thread *thread)
|
||||
{
|
||||
/* Set up privileged stack before entering user mode */
|
||||
thread->arch.priv_stack_start = (uint32_t)z_priv_stack_find(thread->stack_obj);
|
||||
|
||||
/* CONFIG_PRIVILEGED_STACK_SIZE does not account for MPU_GUARD_ALIGN_AND_SIZE or
|
||||
* MPU_GUARD_ALIGN_AND_SIZE_FLOAT. Therefore, we must compute priv_stack_end here before
|
||||
* adjusting priv_stack_start for the mpu guard alignment
|
||||
*/
|
||||
thread->arch.priv_stack_end = thread->arch.priv_stack_start + CONFIG_PRIVILEGED_STACK_SIZE;
|
||||
|
||||
#if defined(CONFIG_MPU_STACK_GUARD)
|
||||
/* Stack guard area reserved at the bottom of the thread's
|
||||
* privileged stack. Adjust the available (writable) stack
|
||||
* buffer area accordingly.
|
||||
*/
|
||||
#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING)
|
||||
thread->arch.priv_stack_start +=
|
||||
((thread->arch.mode & Z_ARM_MODE_MPU_GUARD_FLOAT_Msk) != 0) ?
|
||||
MPU_GUARD_ALIGN_AND_SIZE_FLOAT : MPU_GUARD_ALIGN_AND_SIZE;
|
||||
#else
|
||||
thread->arch.priv_stack_start += MPU_GUARD_ALIGN_AND_SIZE;
|
||||
#endif /* CONFIG_FPU && CONFIG_FPU_SHARING */
|
||||
#endif /* CONFIG_MPU_STACK_GUARD */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* An initial context, to be "restored" by z_arm_pendsv(), is put at the other
|
||||
* end of the stack, and thus reusable by the stack when not needed anymore.
|
||||
*
|
||||
@@ -80,7 +109,10 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
|
||||
|
||||
iframe = Z_STACK_PTR_TO_FRAME(struct __basic_sf, stack_ptr);
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
thread->arch.priv_stack_start = 0;
|
||||
if ((thread->base.user_options & K_USER) != 0) {
|
||||
setup_priv_stack(thread);
|
||||
iframe = Z_STACK_PTR_TO_FRAME(struct __basic_sf, thread->arch.priv_stack_end);
|
||||
iframe->pc = (uint32_t)arch_user_mode_enter;
|
||||
} else {
|
||||
iframe->pc = (uint32_t)z_thread_entry;
|
||||
@@ -122,9 +154,6 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
|
||||
thread->arch.mode |= Z_ARM_MODE_MPU_GUARD_FLOAT_Msk;
|
||||
}
|
||||
#endif
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
thread->arch.priv_stack_start = 0;
|
||||
#endif
|
||||
#endif
|
||||
/*
|
||||
* initial values in all other registers/thread entries are
|
||||
@@ -196,10 +225,8 @@ static inline void z_arm_thread_stack_info_adjust(struct k_thread *thread,
|
||||
FUNC_NORETURN void arch_user_mode_enter(k_thread_entry_t user_entry,
|
||||
void *p1, void *p2, void *p3)
|
||||
{
|
||||
uint32_t sp_is_priv = 1;
|
||||
|
||||
/* Set up privileged stack before entering user mode */
|
||||
_current->arch.priv_stack_start =
|
||||
(uint32_t)z_priv_stack_find(_current->stack_obj);
|
||||
#if defined(CONFIG_MPU_STACK_GUARD)
|
||||
#if defined(CONFIG_THREAD_STACK_INFO)
|
||||
/* We're dropping to user mode which means the guard area is no
|
||||
@@ -216,29 +243,29 @@ FUNC_NORETURN void arch_user_mode_enter(k_thread_entry_t user_entry,
|
||||
_current->stack_info.start -= MPU_GUARD_ALIGN_AND_SIZE;
|
||||
_current->stack_info.size += MPU_GUARD_ALIGN_AND_SIZE;
|
||||
#endif /* CONFIG_THREAD_STACK_INFO */
|
||||
|
||||
/* Stack guard area reserved at the bottom of the thread's
|
||||
* privileged stack. Adjust the available (writable) stack
|
||||
* buffer area accordingly.
|
||||
*/
|
||||
#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING)
|
||||
_current->arch.priv_stack_start +=
|
||||
((_current->arch.mode & Z_ARM_MODE_MPU_GUARD_FLOAT_Msk) != 0) ?
|
||||
MPU_GUARD_ALIGN_AND_SIZE_FLOAT : MPU_GUARD_ALIGN_AND_SIZE;
|
||||
#else
|
||||
_current->arch.priv_stack_start += MPU_GUARD_ALIGN_AND_SIZE;
|
||||
#endif /* CONFIG_FPU && CONFIG_FPU_SHARING */
|
||||
#endif /* CONFIG_MPU_STACK_GUARD */
|
||||
|
||||
#if defined(CONFIG_CPU_AARCH32_CORTEX_R)
|
||||
_current->arch.priv_stack_end =
|
||||
_current->arch.priv_stack_start + CONFIG_PRIVILEGED_STACK_SIZE;
|
||||
#endif
|
||||
/* 2 ways how arch_user_mode_enter is called:
|
||||
* - called as part of context switch from z_arm_pendsv, in this case privileged stack is
|
||||
* already setup and stack pointer points to privileged stack.
|
||||
* - called directly from k_thread_user_mode_enter, in this case privileged stack is not
|
||||
* setup and stack pointer points to user stack.
|
||||
*
|
||||
* When called from k_thread_user_mode_enter, we need to check and setup the privileged
|
||||
* stack and then instruct z_arm_userspace_enter to change the PSP to the privileged stack.
|
||||
* Note that we do not change the PSP in this function to avoid any conflict with compiler's
|
||||
* sequence which has already pushed stuff on the user stack.
|
||||
*/
|
||||
if (0 == _current->arch.priv_stack_start) {
|
||||
setup_priv_stack(_current);
|
||||
sp_is_priv = 0;
|
||||
}
|
||||
|
||||
z_arm_userspace_enter(user_entry, p1, p2, p3,
|
||||
(uint32_t)_current->stack_info.start,
|
||||
_current->stack_info.size -
|
||||
_current->stack_info.delta);
|
||||
_current->stack_info.delta,
|
||||
sp_is_priv);
|
||||
CODE_UNREACHABLE;
|
||||
}
|
||||
|
||||
|
||||
@@ -489,20 +489,219 @@ SECTION_FUNC(TEXT, z_arm_svc)
|
||||
* r8 - saved link register
|
||||
*/
|
||||
.L_do_syscall:
|
||||
/*
|
||||
* Build a privilege stack frame from the user stack frame, then switch PSP
|
||||
* to it. This ensures return from SVC does not rely on the user stack.
|
||||
*
|
||||
* Layout of privilege stack created from user stack:
|
||||
*
|
||||
* +------+-------------------------+------+-------------------------+--------------------------+
|
||||
* | User stack | Privilege stack | Notes |
|
||||
* +------+-------------------------+------+-------------------------+--------------------------+
|
||||
* |Offset| contents |Offset| contents | |
|
||||
* +------+-------------------------+------+-------------------------+--------------------------+
|
||||
* | 0 | R0 -> | 0 | R0 | PSP switches from 0th |
|
||||
* | | | | | offset of user stack to |
|
||||
* | | | | | 0th offset of priv stack |
|
||||
* | 4 | R1 -> | 4 | R1 | |
|
||||
* | 8 | R2 -> | 8 | R2 | |
|
||||
* | 12 | R3 -> |12 | R3 | |
|
||||
* | 16 | R12 -> |16 | R12 | |
|
||||
* | 20 | LR -> |20 | LR | |
|
||||
* | 24 | Return Address -x> |24 | z_arm_do_syscall |return address from user |
|
||||
* | | | | |sf is not copied. Instead,|
|
||||
* | | | | |it is replaced so that |
|
||||
* | | | | |z_arm_svc returns to |
|
||||
* | | | | |z_arm_do_syscall. |
|
||||
* | | | | | |
|
||||
* | 28 | xPSR (w/ or w/o pad) -> |28 | xPSR (pad bit cleared) |This completes the basic |
|
||||
* | | | | |exception sf w/ or w/o pad|
|
||||
* | | | | | |
|
||||
* | -- | FP regs + FPSCR -> |-- | FP regs + FPSCR |For arch supporting fp |
|
||||
* | | (w/ or w/o pad) | | |context an additional |
|
||||
* | | | | |extended sf is copied. |
|
||||
* |________________________________|______|_________________________|__________________________|
|
||||
* | | | | |On returning to |
|
||||
* | | | | |z_arm_do_syscall, the |
|
||||
* | | | | |above sf has already been |
|
||||
* | | | | |unstacked and 8B from the |
|
||||
* | | | | |then sf are used to pass |
|
||||
* | | | | |original pre-svc sp & the |
|
||||
* | | | | |return address. |
|
||||
* | | | | |Note: at the moment |
|
||||
* | | | | |z_arm_do_syscall also |
|
||||
* | | | | |expects the return address|
|
||||
* | | | | |to be set in r8. |
|
||||
* | | | | | |
|
||||
* | | | 0 | address that |z_arm_do_syscall expects |
|
||||
* | | | | z_arm_do_syscall should |the original pre-svc sp at|
|
||||
* | | | | set as PSP before |0th offset i.e. new sp[0] |
|
||||
* | | | | returning from svc. |and, |
|
||||
* | | | | | |
|
||||
* | | | 4 | Address that |the return address at |
|
||||
* | | | | z_arm_do_syscall should |sp[4]. Note that this is |
|
||||
* | | | | return to after handling|the return address copied |
|
||||
* | | | | svc |from user exception sf[24]|
|
||||
* | | | | |which was not copied in |
|
||||
* | | | | |the previous sf. |
|
||||
* +------+-------------------------+------+-------------------------+--------------------------+
|
||||
* "sf" in this function is used as abbreviation for "stack frame".
|
||||
* Note that the "FP regs + FPSCR" are only present if CONFIG_FPU_SHARING=y, and the optional pad
|
||||
* is only present if PSP was not 8-byte aligned when SVC was executed.
|
||||
* Also note that FPU cannot be present in ARMv6-M or ARMv8-M Baseline implementations
|
||||
* (i.e., it may only be present when CONFIG_ARMV7_M_ARMV8_M_MAINLINE is enabled).
|
||||
*/
|
||||
/* Start by fetching the top of privileged stack */
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
movs r3, #24
|
||||
ldr r1, [r0, r3] /* grab address of PC from stack frame */
|
||||
mov r8, r1
|
||||
ldr r1, =_kernel
|
||||
ldr r1, [r1, #_kernel_offset_to_current]
|
||||
adds r1, r1, #_thread_offset_to_priv_stack_start
|
||||
ldr r1, [r1] /* bottom of priv stack */
|
||||
ldr r3, =CONFIG_PRIVILEGED_STACK_SIZE
|
||||
subs r3, #(_EXC_HW_SAVED_BASIC_SF_SIZE+8) /* 8 for original sp and pc */
|
||||
add r1, r3
|
||||
mov ip, r1
|
||||
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
|
||||
ldr r8, [r0, #24] /* grab address of PC from stack frame */
|
||||
ldr ip, =_kernel
|
||||
ldr ip, [ip, #_kernel_offset_to_current]
|
||||
ldr ip, [ip, #_thread_offset_to_priv_stack_start] /* bottom of priv stack */
|
||||
add ip, #CONFIG_PRIVILEGED_STACK_SIZE
|
||||
#ifdef CONFIG_FPU_SHARING
|
||||
/* Assess whether svc calling thread had been using the FP registers. */
|
||||
tst lr, #_EXC_RETURN_FTYPE_Msk
|
||||
ite eq
|
||||
moveq r8, #_EXC_HW_SAVED_EXTENDED_SF_SIZE
|
||||
movne r8, #_EXC_HW_SAVED_BASIC_SF_SIZE
|
||||
#else
|
||||
mov r8, #_EXC_HW_SAVED_BASIC_SF_SIZE
|
||||
#endif
|
||||
sub ip, #8 /* z_arm_do_syscall will use this to get original sp and pc */
|
||||
sub ip, r8 /* 32 for basic sf + 72 for the optional esf */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* At this point:
|
||||
* r0 has PSP i.e. top of user stack
|
||||
* ip has top of privilege stack
|
||||
* r8 has hardware-saved stack frame size (only in case of mainline)
|
||||
*/
|
||||
push {r4-r7}
|
||||
push {r2}
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
mov r2, r0 /* safe to use r2 since it is saved on MSP */
|
||||
|
||||
/* Check for padding in the sf */
|
||||
ldr r1, [r0, #_EXC_HW_SAVED_BASIC_SF_XPSR_OFFSET] /* grab xPSR from sf which has the pad bit */
|
||||
movs r3, #1
|
||||
/* Check if pad bit 9 is set */
|
||||
lsls r3, r3, #9
|
||||
tst r1, r3
|
||||
beq .L_no_padding
|
||||
/* special handling for padded sf */
|
||||
bics r1, r3 /* clear the pad bit (priv stack is aligned and doesn't need it) */
|
||||
adds r2, #4
|
||||
.L_no_padding:
|
||||
/* Calculate original pre-svc user sp which is psp + sf size (+4B if pad bit was set) */
|
||||
adds r2, #_EXC_HW_SAVED_BASIC_SF_SIZE
|
||||
mov r3, ip
|
||||
str r2,[r3, #0]
|
||||
|
||||
/* Store the pre-SVC user SP at the offset expected by z_arm_do_syscall,
|
||||
* as detailed in the table above.
|
||||
*/
|
||||
str r2,[r3, #_EXC_HW_SAVED_BASIC_SF_SIZE]
|
||||
/* sf of priv stack has the same xPSR as user stack but with 9th bit reset */
|
||||
str r1,[r3, #_EXC_HW_SAVED_BASIC_SF_XPSR_OFFSET]
|
||||
|
||||
/* r0-r3, r12, LR from user stack sf are copied to sf of priv stack */
|
||||
mov r1, r0
|
||||
mov r2, r3
|
||||
ldmia r1!, {r4-r7}
|
||||
stmia r2!, {r4-r7}
|
||||
ldmia r1!, {r4-r5}
|
||||
stmia r2!, {r4-r5}
|
||||
|
||||
/* Store the svc return address at the offset expected by z_arm_do_syscall,
|
||||
* as detailed in the table above.
|
||||
*/
|
||||
str r5, [r3, #(_EXC_HW_SAVED_BASIC_SF_SIZE+4)]
|
||||
|
||||
ldr r1, =z_arm_do_syscall
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
str r1, [r0, r3] /* overwrite the PC to point to z_arm_do_syscall */
|
||||
str r1, [r3, #_EXC_HW_SAVED_BASIC_SF_RETADDR_OFFSET] /* Execution return to z_arm_do_syscall */
|
||||
ldr r1, [r0, #_EXC_HW_SAVED_BASIC_SF_RETADDR_OFFSET] /* grab address of PC from stack frame */
|
||||
/* Store the svc return address (i.e. next instr to svc) in r8 as expected by z_arm_do_syscall.
|
||||
*/
|
||||
mov r8, r1
|
||||
|
||||
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
|
||||
str r1, [r0, #24] /* overwrite the PC to point to z_arm_do_syscall */
|
||||
mov r2, r0 /* safe to use r2 since it is saved on MSP */
|
||||
|
||||
/* Calculate original pre-svc user sp without pad which is psp + sf size */
|
||||
add r2, r8
|
||||
|
||||
/* Also, check for padding in the sf */
|
||||
ldr r1, [r0, #_EXC_HW_SAVED_BASIC_SF_XPSR_OFFSET] /* grab xPSR from sf which has the pad bit */
|
||||
tst r1, #(1<<9) /* Check if pad bit 9 is set */
|
||||
beq .L_no_padding
|
||||
bics r1, #(1<<9) /* clear the pad bit (priv stack is aligned and doesn't need it) */
|
||||
/* Calculate original pre-svc user sp with pad */
|
||||
add r2, #4
|
||||
.L_no_padding:
|
||||
str r2,[ip, #0]
|
||||
/* Store the pre-SVC user SP at the offset expected by z_arm_do_syscall,
|
||||
* as detailed in the table above.
|
||||
*/
|
||||
str r2,[ip, r8]
|
||||
str r1,[ip, #_EXC_HW_SAVED_BASIC_SF_XPSR_OFFSET] /* priv sf get user sf xPSR with bit9 reset */
|
||||
|
||||
/* r0-r3, r12, LR from user stack sf are copied to sf of priv stack */
|
||||
mov r1, r0
|
||||
mov r2, ip
|
||||
ldmia r1!, {r4-r7}
|
||||
stmia r2!, {r4-r7}
|
||||
ldmia r1!, {r4-r5}
|
||||
stmia r2!, {r4-r5}
|
||||
|
||||
/* Store the svc return address at the offset expected by z_arm_do_syscall,
|
||||
* as detailed in the table above.
|
||||
*/
|
||||
add r8, #4
|
||||
str r5, [ip, r8]
|
||||
|
||||
ldr r1, =z_arm_do_syscall
|
||||
str r1, [ip, #_EXC_HW_SAVED_BASIC_SF_RETADDR_OFFSET] /* Execution return to z_arm_do_syscall */
|
||||
ldr r1, [r0, #_EXC_HW_SAVED_BASIC_SF_RETADDR_OFFSET] /* grab address of PC from stack frame */
|
||||
/* Store the svc return address (i.e. next instr to svc) in r8 as expected by z_arm_do_syscall.
|
||||
*/
|
||||
mov r8, r1
|
||||
|
||||
/* basic stack frame is copied at this point to privilege stack,
|
||||
* now time to copy the fp context
|
||||
*/
|
||||
#ifdef CONFIG_FPU_SHARING
|
||||
tst lr, #_EXC_RETURN_FTYPE_Msk
|
||||
bne .L_skip_fp_copy
|
||||
add r1, r0, #32
|
||||
add r2, ip, #32
|
||||
|
||||
vldmia r1!, {s0-s15}
|
||||
vstmia r2!, {s0-s15}
|
||||
|
||||
/* copy FPSCR + reserved (8 bytes) */
|
||||
ldmia r1!, {r4, r5}
|
||||
stmia r2!, {r4, r5}
|
||||
.L_skip_fp_copy:
|
||||
#endif
|
||||
|
||||
#endif
|
||||
pop {r2} /* restore CONTROL value */
|
||||
pop {r4-r7}
|
||||
|
||||
/* Point PSP to privilege stack,
|
||||
* note that r0 still has the old PSP
|
||||
*/
|
||||
msr PSP, ip
|
||||
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
ldr r3, =K_SYSCALL_LIMIT
|
||||
cmp r6, r3
|
||||
@@ -556,14 +755,12 @@ SECTION_FUNC(TEXT, z_arm_svc)
|
||||
isb
|
||||
|
||||
#if defined(CONFIG_BUILTIN_STACK_GUARD)
|
||||
/* Thread is now in privileged mode; after returning from SCVall it
|
||||
* will use the default (user) stack before switching to the privileged
|
||||
* stack to execute the system call. We need to protect the user stack
|
||||
* against stack overflows until this stack transition.
|
||||
*/
|
||||
ldr r1, [r0, #_thread_offset_to_stack_info_start] /* stack_info.start */
|
||||
msr PSPLIM, r1
|
||||
#endif /* CONFIG_BUILTIN_STACK_GUARD */
|
||||
/* Set stack pointer limit (needed in privileged mode) */
|
||||
ldr ip, =_kernel
|
||||
ldr ip, [ip, #_kernel_offset_to_current]
|
||||
ldr ip, [ip, #_thread_offset_to_priv_stack_start] /* priv stack ptr */
|
||||
msr PSPLIM, ip
|
||||
#endif
|
||||
|
||||
/* return from SVC to the modified LR - z_arm_do_syscall */
|
||||
bx lr
|
||||
|
||||
@@ -45,6 +45,35 @@
|
||||
K_THREAD_STACK_DECLARE(z_main_stack, CONFIG_MAIN_STACK_SIZE);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
static void setup_priv_stack(struct k_thread *thread)
|
||||
{
|
||||
/* Set up privileged stack before entering user mode */
|
||||
thread->arch.priv_stack_start = (uint32_t)z_priv_stack_find(thread->stack_obj);
|
||||
|
||||
/* CONFIG_PRIVILEGED_STACK_SIZE does not account for MPU_GUARD_ALIGN_AND_SIZE or
|
||||
* MPU_GUARD_ALIGN_AND_SIZE_FLOAT. Therefore, we must compute priv_stack_end here before
|
||||
* adjusting priv_stack_start for the mpu guard alignment
|
||||
*/
|
||||
thread->arch.priv_stack_end = thread->arch.priv_stack_start + CONFIG_PRIVILEGED_STACK_SIZE;
|
||||
|
||||
#if defined(CONFIG_MPU_STACK_GUARD)
|
||||
/* Stack guard area reserved at the bottom of the thread's
|
||||
* privileged stack. Adjust the available (writable) stack
|
||||
* buffer area accordingly.
|
||||
*/
|
||||
#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING)
|
||||
thread->arch.priv_stack_start +=
|
||||
((thread->arch.mode & Z_ARM_MODE_MPU_GUARD_FLOAT_Msk) != 0)
|
||||
? MPU_GUARD_ALIGN_AND_SIZE_FLOAT
|
||||
: MPU_GUARD_ALIGN_AND_SIZE;
|
||||
#else
|
||||
thread->arch.priv_stack_start += MPU_GUARD_ALIGN_AND_SIZE;
|
||||
#endif /* CONFIG_FPU && CONFIG_FPU_SHARING */
|
||||
#endif /* CONFIG_MPU_STACK_GUARD */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* An initial context, to be "restored" by z_arm_pendsv(), is put at the other
|
||||
* end of the stack, and thus reusable by the stack when not needed anymore.
|
||||
*
|
||||
@@ -87,7 +116,10 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, char *sta
|
||||
|
||||
iframe = Z_STACK_PTR_TO_FRAME(struct __basic_sf, stack_ptr);
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
thread->arch.priv_stack_start = 0;
|
||||
if ((thread->base.user_options & K_USER) != 0) {
|
||||
setup_priv_stack(thread);
|
||||
iframe = Z_STACK_PTR_TO_FRAME(struct __basic_sf, thread->arch.priv_stack_end);
|
||||
iframe->pc = (uint32_t)arch_user_mode_enter;
|
||||
} else {
|
||||
iframe->pc = (uint32_t)z_thread_entry;
|
||||
@@ -118,9 +150,6 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, char *sta
|
||||
thread->arch.mode |= Z_ARM_MODE_MPU_GUARD_FLOAT_Msk;
|
||||
}
|
||||
#endif
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
thread->arch.priv_stack_start = 0;
|
||||
#endif
|
||||
#endif
|
||||
/*
|
||||
* initial values in all other registers/thread entries are
|
||||
@@ -215,9 +244,8 @@ uint32_t z_arm_mpu_stack_guard_and_fpu_adjust(struct k_thread *thread)
|
||||
#ifdef CONFIG_USERSPACE
|
||||
FUNC_NORETURN void arch_user_mode_enter(k_thread_entry_t user_entry, void *p1, void *p2, void *p3)
|
||||
{
|
||||
uint32_t sp_is_priv = 1;
|
||||
|
||||
/* Set up privileged stack before entering user mode */
|
||||
_current->arch.priv_stack_start = (uint32_t)z_priv_stack_find(_current->stack_obj);
|
||||
#if defined(CONFIG_MPU_STACK_GUARD)
|
||||
#if defined(CONFIG_THREAD_STACK_INFO)
|
||||
/* We're dropping to user mode which means the guard area is no
|
||||
@@ -234,23 +262,26 @@ FUNC_NORETURN void arch_user_mode_enter(k_thread_entry_t user_entry, void *p1, v
|
||||
_current->stack_info.start -= MPU_GUARD_ALIGN_AND_SIZE;
|
||||
_current->stack_info.size += MPU_GUARD_ALIGN_AND_SIZE;
|
||||
#endif /* CONFIG_THREAD_STACK_INFO */
|
||||
|
||||
/* Stack guard area reserved at the bottom of the thread's
|
||||
* privileged stack. Adjust the available (writable) stack
|
||||
* buffer area accordingly.
|
||||
*/
|
||||
#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING)
|
||||
_current->arch.priv_stack_start +=
|
||||
((_current->arch.mode & Z_ARM_MODE_MPU_GUARD_FLOAT_Msk) != 0)
|
||||
? MPU_GUARD_ALIGN_AND_SIZE_FLOAT
|
||||
: MPU_GUARD_ALIGN_AND_SIZE;
|
||||
#else
|
||||
_current->arch.priv_stack_start += MPU_GUARD_ALIGN_AND_SIZE;
|
||||
#endif /* CONFIG_FPU && CONFIG_FPU_SHARING */
|
||||
#endif /* CONFIG_MPU_STACK_GUARD */
|
||||
|
||||
/* 2 ways how arch_user_mode_enter is called:
|
||||
* - called as part of context switch from z_arm_pendsv, in this case privileged stack is
|
||||
* already setup and stack pointer points to privileged stack.
|
||||
* - called directly from k_thread_user_mode_enter, in this case privileged stack is not
|
||||
* setup and stack pointer points to user stack.
|
||||
*
|
||||
* When called from k_thread_user_mode_enter, we need to check and setup the privileged
|
||||
* stack and then instruct z_arm_userspace_enter to change the PSP to the privileged stack.
|
||||
* Note that we do not change the PSP in this function to avoid any conflict with compiler's
|
||||
* sequence which has already pushed stuff on the user stack.
|
||||
*/
|
||||
if (0 == _current->arch.priv_stack_start) {
|
||||
setup_priv_stack(_current);
|
||||
sp_is_priv = 0;
|
||||
}
|
||||
|
||||
z_arm_userspace_enter(user_entry, p1, p2, p3, (uint32_t)_current->stack_info.start,
|
||||
_current->stack_info.size - _current->stack_info.delta);
|
||||
_current->stack_info.size - _current->stack_info.delta, sp_is_priv);
|
||||
CODE_UNREACHABLE;
|
||||
}
|
||||
|
||||
@@ -560,7 +591,9 @@ void arch_switch_to_main_thread(struct k_thread *main_thread, char *stack_ptr,
|
||||
/* We don’t intend to return, so there is no need to link. */
|
||||
"bx r4\n"
|
||||
/* Force a literal pool placement for the addresses referenced above */
|
||||
#ifndef __IAR_SYSTEMS_ICC__
|
||||
".ltorg\n"
|
||||
#endif
|
||||
:
|
||||
: "r"(_main), "r"(stack_ptr)
|
||||
: "r0", "r1", "r2", "r3", "r4", "ip", "lr", "memory");
|
||||
@@ -628,7 +661,9 @@ FUNC_NORETURN void z_arm_switch_to_main_no_multithreading(k_thread_entry_t main_
|
||||
"blx r0\n"
|
||||
"loop: b loop\n\t" /* while (true); */
|
||||
/* Force a literal pool placement for the addresses referenced above */
|
||||
#ifndef __IAR_SYSTEMS_ICC__
|
||||
".ltorg\n"
|
||||
#endif
|
||||
:
|
||||
: [_p1] "r"(p1), [_p2] "r"(p2), [_p3] "r"(p3), [_psp] "r"(psp),
|
||||
[_main_entry] "r"(main_entry)
|
||||
|
||||
@@ -45,8 +45,9 @@ GEN_OFFSET_SYM(_thread_arch_t, mode_exc_return);
|
||||
#endif
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
GEN_OFFSET_SYM(_thread_arch_t, priv_stack_start);
|
||||
#if defined(CONFIG_CPU_AARCH32_CORTEX_R)
|
||||
GEN_OFFSET_SYM(_thread_arch_t, priv_stack_end);
|
||||
|
||||
#if defined(CONFIG_CPU_AARCH32_CORTEX_R)
|
||||
GEN_OFFSET_SYM(_thread_arch_t, sp_usr);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Userspace and service handler hooks
|
||||
*
|
||||
* Copyright (c) 2017 Linaro Limited
|
||||
* Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
@@ -41,45 +42,41 @@ GDATA(_k_syscall_table)
|
||||
*
|
||||
* The function is invoked as:
|
||||
* z_arm_userspace_enter(user_entry, p1, p2, p3,
|
||||
* stack_info.start, stack_info.size);
|
||||
* stack_info.start, stack_info.size,
|
||||
* sp_is_priv);
|
||||
*/
|
||||
SECTION_FUNC(TEXT,z_arm_userspace_enter)
|
||||
/* move user_entry to lr */
|
||||
mov lr, r0
|
||||
|
||||
/* prepare to set stack to privileged stack */
|
||||
/* load arguments from stack:
|
||||
* r4 = user stack start
|
||||
* r5 = user stack size
|
||||
* r6 = sp_is_priv (1 if already on privileged stack)
|
||||
*/
|
||||
pop {r4, r5, r6}
|
||||
|
||||
/* get current thread pointer */
|
||||
ldr r0, =_kernel
|
||||
ldr r0, [r0, #_kernel_offset_to_current]
|
||||
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
/* move p1 to ip */
|
||||
mov ip, r1
|
||||
ldr r1, =_thread_offset_to_priv_stack_start
|
||||
ldr r0, [r0, r1] /* priv stack ptr */
|
||||
ldr r1, =CONFIG_PRIVILEGED_STACK_SIZE
|
||||
add r0, r0, r1
|
||||
ldr r1, =_thread_offset_to_priv_stack_end
|
||||
ldr r0, [r0, r1]
|
||||
/* Restore p1 from ip */
|
||||
mov r1, ip
|
||||
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
|
||||
ldr r0, [r0, #_thread_offset_to_priv_stack_start] /* priv stack ptr */
|
||||
ldr ip, =CONFIG_PRIVILEGED_STACK_SIZE
|
||||
add r0, r0, ip
|
||||
#elif defined(CONFIG_CPU_AARCH32_CORTEX_R)
|
||||
ldr r0, [r0, #_thread_offset_to_priv_stack_start] /* priv stack ptr */
|
||||
ldr ip, =CONFIG_PRIVILEGED_STACK_SIZE
|
||||
add r0, r0, ip
|
||||
|
||||
ldr ip, =_kernel
|
||||
ldr ip, [ip, #_kernel_offset_to_current]
|
||||
str r0, [ip, #_thread_offset_to_priv_stack_end] /* priv stack end */
|
||||
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) \
|
||||
|| defined(CONFIG_CPU_AARCH32_CORTEX_R)
|
||||
ldr r0, [r0, #_thread_offset_to_priv_stack_end] /* privileged stack ptr */
|
||||
#endif
|
||||
|
||||
/* store current stack pointer to ip
|
||||
* the current stack pointer is needed to retrieve
|
||||
* stack_info.start and stack_info.size
|
||||
*/
|
||||
mov ip, sp
|
||||
/* check if current stack is privileged and switch to it if not */
|
||||
cmp r6, #1
|
||||
beq 1f
|
||||
|
||||
#if defined(CONFIG_CPU_AARCH32_CORTEX_R)
|
||||
#if defined(CONFIG_CPU_AARCH32_CORTEX_R) || defined(CONFIG_CPU_AARCH32_CORTEX_A)
|
||||
mov sp, r0
|
||||
#else
|
||||
/* set stack to privileged stack
|
||||
@@ -93,35 +90,28 @@ SECTION_FUNC(TEXT,z_arm_userspace_enter)
|
||||
msr PSP, r0
|
||||
#endif
|
||||
|
||||
1:
|
||||
/* push thread args and entrypoint to stack */
|
||||
push {r1,r2,r3,lr}
|
||||
|
||||
#if defined(CONFIG_BUILTIN_STACK_GUARD)
|
||||
/* At this point the privileged stack is not yet protected by PSPLIM.
|
||||
* Since we have just switched to the top of the privileged stack, we
|
||||
* Since we have switched to the top of the privileged stack, we
|
||||
* are safe, as long as the stack can accommodate the maximum exception
|
||||
* stack frame.
|
||||
*/
|
||||
|
||||
/* set stack pointer limit to the start of the priv stack */
|
||||
ldr r0, =_kernel
|
||||
ldr r0, [r0, #_kernel_offset_to_current]
|
||||
ldr r0, [r0, #_thread_offset_to_priv_stack_start] /* priv stack ptr */
|
||||
ldr r1, =CONFIG_PRIVILEGED_STACK_SIZE
|
||||
sub r0, r0, r1 /* Calculate start of privileged stack */
|
||||
/* set stack pointer limit to the start of the privileged stack */
|
||||
msr PSPLIM, r0
|
||||
#endif
|
||||
|
||||
/* push args to stack */
|
||||
push {r1,r2,r3,lr}
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
mov r1, ip
|
||||
push {r0,r1}
|
||||
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) \
|
||||
|| defined(CONFIG_CPU_AARCH32_CORTEX_R)
|
||||
push {r0,ip}
|
||||
#endif
|
||||
|
||||
/* Re-program dynamic memory map.
|
||||
*
|
||||
* Important note:
|
||||
* z_arm_configure_dynamic_mpu_regions() may re-program the MPU Stack Guard
|
||||
* to guard the privilege stack for overflows (if building with option
|
||||
* to guard the privileged stack for overflows (if building with option
|
||||
* CONFIG_MPU_STACK_GUARD). There is a risk of actually overflowing the
|
||||
* stack while doing the re-programming. We minimize the risk by placing
|
||||
* this function immediately after we have switched to the privileged stack
|
||||
@@ -135,29 +125,10 @@ SECTION_FUNC(TEXT,z_arm_userspace_enter)
|
||||
ldr r0, [r0, #_kernel_offset_to_current]
|
||||
bl z_arm_configure_dynamic_mpu_regions
|
||||
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
pop {r0,r3}
|
||||
|
||||
/* load up stack info from user stack */
|
||||
ldr r0, [r3]
|
||||
ldr r3, [r3, #4]
|
||||
mov ip, r3
|
||||
|
||||
push {r0,r3}
|
||||
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) \
|
||||
|| defined(CONFIG_CPU_AARCH32_CORTEX_R)
|
||||
pop {r0,ip}
|
||||
|
||||
/* load up stack info from user stack */
|
||||
ldr r0, [ip]
|
||||
ldr ip, [ip, #4]
|
||||
|
||||
push {r0,ip}
|
||||
#endif
|
||||
|
||||
/* clear the user stack area to clean out privileged data */
|
||||
/* from right past the guard right up to the end */
|
||||
mov r2, ip
|
||||
mov r0, r4
|
||||
mov r2, r5
|
||||
#ifdef CONFIG_INIT_STACKS
|
||||
ldr r1,=0xaaaaaaaa
|
||||
#else
|
||||
@@ -165,17 +136,18 @@ SECTION_FUNC(TEXT,z_arm_userspace_enter)
|
||||
#endif
|
||||
bl memset
|
||||
|
||||
/* At this point:
|
||||
* r4 contains user stack start
|
||||
* r5 contains user stack size
|
||||
* calculate top of user stack in r0 (start+size)
|
||||
*/
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
pop {r0, r1}
|
||||
mov ip, r1
|
||||
adds r0, r4, r5
|
||||
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) \
|
||||
|| defined(CONFIG_CPU_AARCH32_CORTEX_R)
|
||||
pop {r0,ip}
|
||||
add r0, r4, r5
|
||||
#endif
|
||||
|
||||
/* r0 contains user stack start, ip contains user stack size */
|
||||
add r0, r0, ip /* calculate top of stack */
|
||||
|
||||
/* pop remaining arguments from stack before switching stacks */
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
/* Use r4 to pop lr, then restore r4 */
|
||||
@@ -188,7 +160,7 @@ SECTION_FUNC(TEXT,z_arm_userspace_enter)
|
||||
pop {r1,r2,r3,lr}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CPU_AARCH32_CORTEX_R)
|
||||
#if defined(CONFIG_CPU_AARCH32_CORTEX_R) || defined(CONFIG_CPU_AARCH32_CORTEX_A)
|
||||
/*
|
||||
* set stack to user stack. We are in SYSTEM state, so r13 and r14 are
|
||||
* shared with USER state
|
||||
@@ -223,10 +195,7 @@ SECTION_FUNC(TEXT,z_arm_userspace_enter)
|
||||
isb
|
||||
|
||||
/* Set PSPLIM to guard the thread's user stack. */
|
||||
ldr r0, =_kernel
|
||||
ldr r0, [r0, #_kernel_offset_to_current]
|
||||
ldr r0, [r0, #_thread_offset_to_stack_info_start]
|
||||
msr PSPLIM, r0
|
||||
msr PSPLIM, r4
|
||||
|
||||
pop {r0, ip}
|
||||
#endif
|
||||
@@ -308,9 +277,8 @@ SECTION_FUNC(TEXT,z_arm_userspace_enter)
|
||||
* This function is used to do system calls from unprivileged code. This
|
||||
* function is responsible for the following:
|
||||
* 1) Fixing up bad syscalls
|
||||
* 2) Configuring privileged stack and loading up stack arguments
|
||||
* 3) Dispatching the system call
|
||||
* 4) Restoring stack and calling back to the caller of the SVC
|
||||
* 2) Dispatching the system call
|
||||
* 3) Restoring stack and calling back to the caller of the SVC
|
||||
*
|
||||
*/
|
||||
SECTION_FUNC(TEXT, z_arm_do_syscall)
|
||||
@@ -328,41 +296,7 @@ SECTION_FUNC(TEXT, z_arm_do_syscall)
|
||||
* At this point PSPLIM is already configured to guard the default (user)
|
||||
* stack, so pushing to the default thread's stack is safe.
|
||||
*/
|
||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||
/* save current stack pointer (user stack) */
|
||||
mov ip, sp
|
||||
/* temporarily push to user stack */
|
||||
push {r0,r1}
|
||||
/* setup privileged stack */
|
||||
ldr r0, =_kernel
|
||||
ldr r0, [r0, #_kernel_offset_to_current]
|
||||
adds r0, r0, #_thread_offset_to_priv_stack_start
|
||||
ldr r0, [r0] /* priv stack ptr */
|
||||
ldr r1, =CONFIG_PRIVILEGED_STACK_SIZE
|
||||
add r0, r1
|
||||
|
||||
/* Store current SP and LR at the beginning of the priv stack */
|
||||
subs r0, #8
|
||||
mov r1, ip
|
||||
str r1, [r0, #0]
|
||||
mov r1, lr
|
||||
str r1, [r0, #4]
|
||||
mov ip, r0
|
||||
/* Restore user stack and original r0, r1 */
|
||||
pop {r0, r1}
|
||||
|
||||
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
|
||||
/* setup privileged stack */
|
||||
ldr ip, =_kernel
|
||||
ldr ip, [ip, #_kernel_offset_to_current]
|
||||
ldr ip, [ip, #_thread_offset_to_priv_stack_start] /* priv stack ptr */
|
||||
add ip, #CONFIG_PRIVILEGED_STACK_SIZE
|
||||
|
||||
/* Store current SP and LR at the beginning of the priv stack */
|
||||
subs ip, #8
|
||||
str sp, [ip, #0]
|
||||
str lr, [ip, #4]
|
||||
#elif defined(CONFIG_CPU_AARCH32_CORTEX_R)
|
||||
#if defined(CONFIG_CPU_AARCH32_CORTEX_R)
|
||||
/*
|
||||
* The SVC handler has already switched to the privileged stack.
|
||||
* Store the user SP and LR at the beginning of the priv stack.
|
||||
@@ -373,11 +307,6 @@ SECTION_FUNC(TEXT, z_arm_do_syscall)
|
||||
push {ip, lr}
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_CPU_AARCH32_CORTEX_R)
|
||||
/* switch to privileged stack */
|
||||
msr PSP, ip
|
||||
#endif
|
||||
|
||||
/* Note (applies when using stack limit checking):
|
||||
* We do not need to lock IRQs after switching PSP to the privileged stack;
|
||||
* PSPLIM is guarding the default (user) stack, which, by design, is
|
||||
@@ -386,14 +315,6 @@ SECTION_FUNC(TEXT, z_arm_do_syscall)
|
||||
* the maximum exception stack frame.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_BUILTIN_STACK_GUARD)
|
||||
/* Set stack pointer limit (needed in privileged mode) */
|
||||
ldr ip, =_kernel
|
||||
ldr ip, [ip, #_kernel_offset_to_current]
|
||||
ldr ip, [ip, #_thread_offset_to_priv_stack_start] /* priv stack ptr */
|
||||
msr PSPLIM, ip
|
||||
#endif
|
||||
|
||||
/*
|
||||
* r0-r5 contain arguments
|
||||
* r6 contains call_id
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Carlo Caione <ccaione@baylibre.com>
|
||||
* Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -77,7 +78,8 @@ static ALWAYS_INLINE void arch_switch(void *switch_to, void **switched_from)
|
||||
extern FUNC_NORETURN void z_arm_userspace_enter(k_thread_entry_t user_entry,
|
||||
void *p1, void *p2, void *p3,
|
||||
uint32_t stack_end,
|
||||
uint32_t stack_start);
|
||||
uint32_t stack_start,
|
||||
uint32_t sp_is_priv);
|
||||
|
||||
extern void z_arm_fatal_error(unsigned int reason, const struct arch_esf *esf);
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Carlo Caione <ccaione@baylibre.com>
|
||||
* Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -75,7 +76,8 @@ extern FUNC_NORETURN void z_arm_switch_to_main_no_multithreading(k_thread_entry_
|
||||
#endif /* !CONFIG_MULTITHREADING */
|
||||
|
||||
extern FUNC_NORETURN void z_arm_userspace_enter(k_thread_entry_t user_entry, void *p1, void *p2,
|
||||
void *p3, uint32_t stack_end, uint32_t stack_start);
|
||||
void *p3, uint32_t stack_end, uint32_t stack_start,
|
||||
uint32_t sp_is_priv);
|
||||
|
||||
extern void z_arm_fatal_error(unsigned int reason, const struct arch_esf *esf);
|
||||
|
||||
|
||||
@@ -45,10 +45,10 @@
|
||||
#define _thread_offset_to_priv_stack_start \
|
||||
(___thread_t_arch_OFFSET + ___thread_arch_t_priv_stack_start_OFFSET)
|
||||
|
||||
#if defined(CONFIG_CPU_AARCH32_CORTEX_R)
|
||||
#define _thread_offset_to_priv_stack_end \
|
||||
(___thread_t_arch_OFFSET + ___thread_arch_t_priv_stack_end_OFFSET)
|
||||
|
||||
#if defined(CONFIG_CPU_AARCH32_CORTEX_R)
|
||||
#define _thread_offset_to_sp_usr \
|
||||
(___thread_t_arch_OFFSET + ___thread_arch_t_sp_usr_OFFSET)
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2019 Intel Corporation
|
||||
* Copyright (c) 2025 Basalte bv
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -8,7 +9,7 @@
|
||||
/* Copied from linker.ld */
|
||||
|
||||
/* Non-cached region of RAM */
|
||||
SECTION_DATA_PROLOGUE(_NOCACHE_SECTION_NAME,,)
|
||||
SECTION_DATA_PROLOGUE(_NOCACHE_SECTION_NAME,(NOLOAD),)
|
||||
{
|
||||
#if defined(CONFIG_MMU)
|
||||
MMU_ALIGN;
|
||||
@@ -16,17 +17,31 @@ SECTION_DATA_PROLOGUE(_NOCACHE_SECTION_NAME,,)
|
||||
MPU_ALIGN(_nocache_ram_size);
|
||||
#endif
|
||||
_nocache_ram_start = .;
|
||||
_nocache_noload_ram_start = .;
|
||||
*(.nocache)
|
||||
*(".nocache.*")
|
||||
|
||||
#include <snippets-nocache-section.ld>
|
||||
|
||||
_nocache_noload_ram_end = .;
|
||||
} GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION)
|
||||
_nocache_noload_ram_size = _nocache_noload_ram_end - _nocache_noload_ram_start;
|
||||
|
||||
/* Non-cached loadable region of RAM and ROM */
|
||||
SECTION_DATA_PROLOGUE(_NOCACHE_LOAD_SECTION_NAME,,)
|
||||
{
|
||||
_nocache_load_ram_start = .;
|
||||
*(.nocache_load)
|
||||
*(".nocache_load.*")
|
||||
|
||||
#if defined(CONFIG_MMU)
|
||||
MMU_ALIGN;
|
||||
#else
|
||||
MPU_ALIGN(_nocache_ram_size);
|
||||
#endif
|
||||
_nocache_load_ram_end = .;
|
||||
_nocache_ram_end = .;
|
||||
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
|
||||
_nocache_load_ram_size = _nocache_load_ram_end - _nocache_load_ram_start;
|
||||
_nocache_load_rom_start = LOADADDR(_NOCACHE_LOAD_SECTION_NAME);
|
||||
_nocache_ram_size = _nocache_ram_end - _nocache_ram_start;
|
||||
_nocache_load_start = LOADADDR(_NOCACHE_SECTION_NAME);
|
||||
|
||||
@@ -311,7 +311,7 @@ You can debug an application in the usual way. Here is an example for the
|
||||
:goals: debug
|
||||
|
||||
.. _pyOCD:
|
||||
https://github.com/mbedmicro/pyOCD
|
||||
https://github.com/pyocd/pyOCD
|
||||
|
||||
.. _CMSIS DAP:
|
||||
https://developer.mbed.org/handbook/CMSIS-DAP
|
||||
@@ -323,7 +323,7 @@ You can debug an application in the usual way. Here is an example for the
|
||||
http://wiki.seeed.cc/BLE_Nitrogen/
|
||||
|
||||
.. _pyOCD issue 259:
|
||||
https://github.com/mbedmicro/pyOCD/issues/259
|
||||
https://github.com/pyocd/pyOCD/issues/259
|
||||
|
||||
.. _96Boards IE Specification:
|
||||
https://linaro.co/ie-specification
|
||||
|
||||
@@ -108,9 +108,9 @@ zephyr_i2c: &i2c1 {
|
||||
pinctrl-names = "default";
|
||||
clock-frequency = <I2C_BITRATE_FAST>;
|
||||
|
||||
vl53l1x: vl53l1x@52 {
|
||||
vl53l1x: vl53l1x@29 {
|
||||
compatible = "st,vl53l1x";
|
||||
reg = <0x52>;
|
||||
reg = <0x29>;
|
||||
status = "okay";
|
||||
xshut-gpios = <&gpiog 10 GPIO_ACTIVE_HIGH>;
|
||||
int-gpios = <&gpiod 8 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
@@ -17,4 +17,5 @@ if(CONFIG_BOARD_MPS2_AN521_CPU1 AND NOT CONFIG_OPENAMP)
|
||||
BUILD_BYPRODUCTS "${CPU0_BINARY_DIR}/${KERNEL_BIN_NAME}"
|
||||
BUILD_ALWAYS True
|
||||
)
|
||||
add_dependencies(app empty_cpu0)
|
||||
endif()
|
||||
|
||||
@@ -33,7 +33,7 @@ config TEST_EXTRA_STACK_SIZE
|
||||
|
||||
endif # COVERAGE_GCOV
|
||||
|
||||
endif
|
||||
endif # BOARD_MPS2_AN383 || BOARD_MPS2_AN385 || BOARD_MPS2_AN386 || BOARD_MPS2_AN500
|
||||
|
||||
if BOARD_MPS2_AN521_CPU0 || BOARD_MPS2_AN521_CPU0_NS || BOARD_MPS2_AN521_CPU1
|
||||
|
||||
@@ -58,4 +58,11 @@ config UART_INTERRUPT_DRIVEN
|
||||
|
||||
endif # SERIAL
|
||||
|
||||
endif # BOARD_MPS2_AN521_CPU0 || BOARD_MPS2_AN521_CPU0_NS || BOARD_MPS2_AN521_CPU1
|
||||
|
||||
if QEMU_TARGET
|
||||
|
||||
config ISR_STACK_SIZE
|
||||
default 4096
|
||||
|
||||
endif
|
||||
|
||||
@@ -110,6 +110,10 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&clk_msik {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&clk_msis {
|
||||
status = "okay";
|
||||
msi-pll-mode;
|
||||
@@ -160,6 +164,8 @@
|
||||
};
|
||||
|
||||
&rng {
|
||||
clocks = <&rcc STM32_CLOCK(AHB2, 18)>,
|
||||
<&rcc STM32_SRC_MSIK RNG_SEL(1)>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
||||
@@ -8,17 +8,20 @@
|
||||
# This section covers flags related to optimization #
|
||||
#####################################################
|
||||
set_compiler_property(PROPERTY no_optimization -On)
|
||||
|
||||
set_compiler_property(PROPERTY optimization_debug -Ol)
|
||||
|
||||
set_compiler_property(PROPERTY optimization_speed -Ohs)
|
||||
|
||||
set_compiler_property(PROPERTY optimization_size -Ohz)
|
||||
|
||||
set_compiler_property(PROPERTY optimization_size_aggressive -Ohz)
|
||||
|
||||
set_compiler_property(PROPERTY optimization_fast --no_size_constraints)
|
||||
|
||||
# IAR uses the GNU assembler so the options differ from the compiler
|
||||
set_property(TARGET asm PROPERTY no_optimization -O0)
|
||||
set_property(TARGET asm PROPERTY optimization_debug -Og)
|
||||
set_property(TARGET asm PROPERTY optimization_speed -O2)
|
||||
set_property(TARGET asm PROPERTY optimization_size -Os)
|
||||
set_property(TARGET asm PROPERTY optimization_size_aggressive -Oz)
|
||||
set_property(TARGET asm PROPERTY optimization_fast -Ofast)
|
||||
|
||||
#######################################################
|
||||
# This section covers flags related to warning levels #
|
||||
#######################################################
|
||||
|
||||
@@ -73,6 +73,9 @@ function(zephyr_mcuboot_tasks)
|
||||
"APPLICATION_CONFIG_DIR=\"${APPLICATION_CONFIG_DIR}\" "
|
||||
"and WEST_TOPDIR=\"${WEST_TOPDIR}\")")
|
||||
endif()
|
||||
|
||||
# Add key file as CMake dependency so a file change will rerun the build
|
||||
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${${file}})
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
include(${ZEPHYR_BASE}/cmake/toolchain/xcc/common.cmake)
|
||||
|
||||
set(COMPILER xcc)
|
||||
set(OPTIMIZE_FOR_DEBUG_FLAG "-O0")
|
||||
set(COMPILER_OPTIMIZE_FOR_DEBUG_FLAG "-O0")
|
||||
set(CC xcc)
|
||||
set(C++ xc++)
|
||||
set(LINKER xt-ld)
|
||||
|
||||
@@ -360,14 +360,14 @@ def get_catalog(generate_hw_features=False, hw_features_vendor_filter=None):
|
||||
# Grab all the twister files for this board and use them to figure out all the archs it
|
||||
# supports.
|
||||
board_archs = set()
|
||||
pattern = f"{board.name}*.yaml"
|
||||
for twister_file in board.dir.glob(pattern):
|
||||
try:
|
||||
with open(twister_file) as f:
|
||||
board_data = yaml.safe_load(f)
|
||||
board_archs.add(board_data.get("arch"))
|
||||
except Exception as e:
|
||||
logger.error(f"Error parsing twister file {twister_file}: {e}")
|
||||
for pattern in (f"{board.name}*.yaml", "twister.yaml"):
|
||||
for twister_file in board.dir.glob(pattern):
|
||||
try:
|
||||
with open(twister_file) as f:
|
||||
board_data = yaml.safe_load(f)
|
||||
board_archs.add(board_data.get("arch"))
|
||||
except Exception as e:
|
||||
logger.error(f"Error parsing twister file {twister_file}: {e}")
|
||||
|
||||
if doc_page and doc_page.is_relative_to(ZEPHYR_BASE):
|
||||
doc_page_path = doc_page.relative_to(ZEPHYR_BASE).as_posix()
|
||||
|
||||
@@ -4,7 +4,7 @@ TFTP
|
||||
####
|
||||
|
||||
Zephyr provides a simple TFTP client library that can enabled with
|
||||
:kconfig:option:`CONFIG_MQTT_SN_LIB` Kconfig option.
|
||||
:kconfig:option:`CONFIG_TFTP_LIB` Kconfig option.
|
||||
|
||||
See :zephyr:code-sample:`TFTP client sample application <tftp-client>` for
|
||||
more information about the library usage.
|
||||
|
||||
@@ -363,4 +363,4 @@ in the log.
|
||||
|
||||
.. _Eclipse IDE for C/C++ Developers: https://www.eclipse.org/downloads/packages/eclipse-ide-cc-developers/oxygen2
|
||||
.. _GNU MCU Eclipse plug-ins: https://gnu-mcu-eclipse.github.io/plugins/install/
|
||||
.. _pyOCD v0.11.0: https://github.com/mbedmicro/pyOCD/releases/tag/v0.11.0
|
||||
.. _pyOCD v0.11.0: https://github.com/pyocd/pyOCD/releases/tag/v0.11.0
|
||||
|
||||
@@ -26,6 +26,57 @@
|
||||
|
||||
.. _zephyr_4.2:
|
||||
|
||||
.. _zephyr_4.2.1:
|
||||
|
||||
Zephyr 4.2.1
|
||||
############
|
||||
|
||||
This is a bugfix release for Zephyr 4.2.0. The following issues are addressed by this release:
|
||||
|
||||
* :github:`96197` gPTP sample does not boot with NUCLEO-H563ZI
|
||||
* :github:`92393` LIS2DUX12 setting incorrect ODR configuration
|
||||
* :github:`93011` stm32u0: interrupt vectors for lpuart1 and lpuart2 are wrong in device tree
|
||||
* :github:`93220` Twister tests with coverage enabled crash during startup
|
||||
* :github:`93265` Stm32u5x: clock disable in sleep mode fix causing USB HS device initialization stalls
|
||||
* :github:`93342` doc: Documentation issue in 'connectivity/networking/api/tftp'
|
||||
* :github:`93350` net: tcp: keep-alive "pings" are no longer acknowledged with v4.2.0
|
||||
* :github:`93364` tests/subsys/llext fails after tagging 4.2
|
||||
* :github:`93424` Missing break after IPV6_MULTICAST_IF option processing
|
||||
* :github:`93445` STM32U535/545: dtc error for node wkup-pin@8 referencing non-existent port gpiof
|
||||
* :github:`93519` drivers: nxp_lpspi: Large performance degradation
|
||||
* :github:`93594` Nicla Vision has bad I2C address for VL53L1X sensor
|
||||
* :github:`93611` doc: Documentation issue in 'releases/release-notes-4.2'
|
||||
* :github:`93790` drivers: console: posix_arch_console: build warning with ``CONFIG_PRINTK=n``
|
||||
* :github:`93792` USB samples not working on ``max32690evkit``
|
||||
* :github:`93831` drivers: can: nrf: fix invalid pointer leading to undef behavior
|
||||
* :github:`93839` I3C: STM32: Has a Mutex deadlock on DAA Failure
|
||||
* :github:`94000` EXT2 fs_stat on mount point fails with a NULL pointer dereference.
|
||||
* :github:`94047` Shell device name tab completion for regulator parents show incorrect names
|
||||
* :github:`94063` SPI loopback tests failing on MAX32 SoCs.
|
||||
* :github:`94083` stm32: u3: low clock frequency for the RNG periphera
|
||||
* :github:`94093` Build error when OCRAM node is disabled in device tree (status = "disabled") [NXP RT1061]
|
||||
* :github:`94107` ppp link-layer address configuration is wrong
|
||||
* :github:`94325` iar: incorrect assembler optimzation flag
|
||||
* :github:`94473` LVGL Widgets Demo stopped working in v4.1 on mimxrt1060_evk@A
|
||||
* :github:`94702` Locally Administered Address (LAA) bit missing for STM32 ethernet driver
|
||||
* :github:`94703` Locally Administered Address (LAA) bit set on wrong index for NXP i.MX ethernet driver
|
||||
* :github:`94774` modules/picolibc: Roll back unnecessary changes, synchronize with SDK 0.17.4
|
||||
* :github:`94812` ``nocache`` data is included in ROM section
|
||||
* :github:`94842` iar: Zephyr 4.2 fails with IAR EWARM 9.70.1
|
||||
* :github:`94954` Spurious error log "No valid legacy adv to resume" in bt_hci_le_enh_conn_complete when using bt_le_ext_adv_start()
|
||||
* :github:`95113` gpio_pin_get_config for STM32 returns wrong flags value for input pins
|
||||
* :github:`95146` i2c: stm32: non-RTIO driver fixes on PM and on STM32F7 from Zephyr v4.3
|
||||
* :github:`95297` Links to the pyOCD repository are outdated
|
||||
* :github:`95456` Zephyr Netstack buffer leaks
|
||||
* :github:`95580` Picolibc module and SDK are not in sync for Zephyr 4.2.0
|
||||
* :github:`95721` Boards documentation: "arm" Architecture not specified at least for STM32MP13 and STM32N6 boards
|
||||
* :github:`95724` drivers: i2c: stm32: build error when using DMAs with st,stm32-i2c-v2 driver
|
||||
* :github:`95768` Possible TCP connection leak when creating a socket
|
||||
* :github:`95850` Applications do not watch MCUboot key file for changes
|
||||
* :github:`96087` TCP connection sends an incorrect seqnum FIN message
|
||||
* :github:`96172` arch: arm: switch to privilege stack in SVC handler
|
||||
* :github:`96768` incorrect i2c3 base address on stm32f303Xe
|
||||
|
||||
Zephyr 4.2.0
|
||||
############
|
||||
|
||||
@@ -317,6 +368,7 @@ New APIs and options
|
||||
* :kconfig:option:`CONFIG_LV_Z_COLOR_MONO_HW_INVERSION`
|
||||
|
||||
* LoRaWAN
|
||||
|
||||
* :c:func:`lorawan_request_link_check`
|
||||
|
||||
* Management
|
||||
@@ -1394,8 +1446,8 @@ Other notable changes
|
||||
* 3.6.3: https://github.com/Mbed-TLS/mbedtls/releases/tag/mbedtls-3.6.3
|
||||
* 3.6.4: https://github.com/Mbed-TLS/mbedtls/releases/tag/mbedtls-3.6.4
|
||||
|
||||
* Updated TF-M to version 2.1.2 (from 2.1.1). The release notes can be found at:
|
||||
https://trustedfirmware-m.readthedocs.io/en/tf-mv2.1.2/releases/2.1.2.html
|
||||
* Updated TF-M to version 2.2.0 (from 2.1.1). The release notes can be found at:
|
||||
https://trustedfirmware-m.readthedocs.io/en/latest/releases/2.2.0.html
|
||||
|
||||
* Updated all boards with an external I2C connectors (Qwiic, Stemma, Grove...)
|
||||
to use the ``zephyr_i2c`` devicetree label. This allows using the existing
|
||||
|
||||
@@ -333,7 +333,7 @@ static inline void read_payload(const struct device *dev)
|
||||
LOG_DBG("Allocated rx.buf %p", h4->rx.buf);
|
||||
|
||||
buf_tailroom = net_buf_tailroom(h4->rx.buf);
|
||||
if (buf_tailroom < h4->rx.remaining) {
|
||||
if (buf_tailroom < (h4->rx.remaining + h4->rx.hdr_len)) {
|
||||
LOG_ERR("Not enough space in buffer %u/%zu", h4->rx.remaining,
|
||||
buf_tailroom);
|
||||
h4->rx.discard = h4->rx.remaining;
|
||||
|
||||
@@ -303,7 +303,7 @@ static void ble_isr_installer(void)
|
||||
|
||||
static void rng_get_random(void *num, size_t size)
|
||||
{
|
||||
const struct device *dev = DEVICE_DT_GET(DT_DRV_INST(0));
|
||||
const struct device *dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_entropy));
|
||||
int res;
|
||||
|
||||
/* try to allocate from pool */
|
||||
|
||||
@@ -147,7 +147,7 @@ static int configure_hsfll(const struct device *dev, bool on)
|
||||
if (on) {
|
||||
int ret;
|
||||
|
||||
ret = clock_control_get_rate(dev, NULL, &spec.frequency);
|
||||
ret = clock_control_get_rate(config->auxpll, NULL, &spec.frequency);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
static char stdout_buff[_STDOUT_BUF_SIZE];
|
||||
static int n_pend; /* Number of pending characters in buffer */
|
||||
|
||||
#if defined(CONFIG_PRINTK) || defined(CONFIG_STDOUT_CONSOLE)
|
||||
static int print_char(int c)
|
||||
{
|
||||
int printnow = 0;
|
||||
@@ -36,6 +37,7 @@ static int print_char(int c)
|
||||
}
|
||||
return c;
|
||||
}
|
||||
#endif /* defined(CONFIG_PRINTK) || defined(CONFIG_STDOUT_CONSOLE) */
|
||||
|
||||
/**
|
||||
* Ensure that whatever was written thru printk is displayed now
|
||||
|
||||
@@ -327,9 +327,14 @@ static int recover_seed_error(RNG_TypeDef *rng)
|
||||
{
|
||||
ll_rng_clear_seis(rng);
|
||||
|
||||
#if !defined(CONFIG_SOC_SERIES_STM32WB0X)
|
||||
/* After a noise source error is detected, 12 words must be read from the RNG_DR register
|
||||
* and discarded to restart the entropy generation.
|
||||
*/
|
||||
for (int i = 0; i < 12; ++i) {
|
||||
(void)ll_rng_read_rand_data(rng);
|
||||
}
|
||||
#endif /* !CONFIG_SOC_SERIES_STM32WB0X */
|
||||
|
||||
if (ll_rng_is_active_seis(rng) != 0) {
|
||||
return -EIO;
|
||||
@@ -445,7 +450,7 @@ static uint16_t generate_from_isr(uint8_t *buf, uint16_t len)
|
||||
ret = random_sample_get(&rnd_sample);
|
||||
#if !IRQLESS_TRNG
|
||||
NVIC_ClearPendingIRQ(IRQN);
|
||||
#endif /* IRQLESS_TRNG */
|
||||
#endif /* !IRQLESS_TRNG */
|
||||
|
||||
if (ret < 0) {
|
||||
continue;
|
||||
|
||||
@@ -54,6 +54,7 @@ static inline void ll_rng_clear_seis(RNG_TypeDef *RNGx)
|
||||
{
|
||||
#if defined(CONFIG_SOC_STM32WB09XX)
|
||||
LL_RNG_SetResetHealthErrorFlags(RNGx, 1);
|
||||
WRITE_REG(RNGx->IRQ_SR, RNG_IRQ_SR_ERROR_IRQ);
|
||||
#elif defined(CONFIG_SOC_SERIES_STM32WB0X)
|
||||
/* STM32WB05 / STM32WB06 / STM32WB07 */
|
||||
LL_RNG_ClearFlag_FAULT(RNGx);
|
||||
@@ -109,7 +110,7 @@ static inline rng_sample_t ll_rng_read_rand_data(RNG_TypeDef *RNGx)
|
||||
* Raw register access is performed because STM32CubeWB0 v1.0.0
|
||||
* package is lacking the LL function to clear IRQ flags.
|
||||
*/
|
||||
WRITE_REG(RNG->IRQ_SR, RNG_IRQ_SR_FF_FULL_IRQ);
|
||||
WRITE_REG(RNGx->IRQ_SR, RNG_IRQ_SR_FF_FULL_IRQ);
|
||||
|
||||
return rnd;
|
||||
#elif defined(CONFIG_SOC_SERIES_STM32WB0X)
|
||||
|
||||
@@ -400,7 +400,7 @@ static void eth_iface_init(struct net_if *iface)
|
||||
}
|
||||
#endif
|
||||
|
||||
ctx->dev_fd = eth_iface_create(CONFIG_ETH_NATIVE_POSIX_DEV_NAME, ctx->if_name, false);
|
||||
ctx->dev_fd = eth_iface_create(CONFIG_ETH_NATIVE_TAP_DEV_NAME, ctx->if_name, false);
|
||||
if (ctx->dev_fd < 0) {
|
||||
LOG_ERR("Cannot create %s (%d/%s)", ctx->if_name, ctx->dev_fd,
|
||||
strerror(-ctx->dev_fd));
|
||||
|
||||
@@ -815,6 +815,12 @@ static void generate_mac(uint8_t *mac_addr)
|
||||
result_mac_32_bits = crc32_ieee((uint8_t *)unique_device_ID_12_bytes, 12);
|
||||
memcpy(&mac_addr[3], &result_mac_32_bits, 3);
|
||||
|
||||
/**
|
||||
* Set MAC address locally administered bit (LAA) as this is not assigned by the
|
||||
* manufacturer
|
||||
*/
|
||||
mac_addr[0] |= 0x02;
|
||||
|
||||
#endif /* NODE_HAS_VALID_MAC_ADDR(DT_DRV_INST(0))) */
|
||||
#endif
|
||||
}
|
||||
@@ -845,6 +851,108 @@ static void RISAF_Config(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ETH_STM32_HAL_API_V1)
|
||||
static int eth_init_api_v1(const struct device *dev)
|
||||
{
|
||||
HAL_StatusTypeDef hal_ret = HAL_OK;
|
||||
struct eth_stm32_hal_dev_data *dev_data = dev->data;
|
||||
ETH_HandleTypeDef *heth = &dev_data->heth;
|
||||
|
||||
if (!ETH_STM32_AUTO_NEGOTIATION_ENABLE) {
|
||||
struct phy_link_state state;
|
||||
|
||||
phy_get_link_state(eth_stm32_phy_dev, &state);
|
||||
|
||||
heth->Init.DuplexMode = PHY_LINK_IS_FULL_DUPLEX(state.speed) ? ETH_MODE_FULLDUPLEX
|
||||
: ETH_MODE_HALFDUPLEX;
|
||||
heth->Init.Speed =
|
||||
PHY_LINK_IS_SPEED_100M(state.speed) ? ETH_SPEED_100M : ETH_SPEED_10M;
|
||||
}
|
||||
|
||||
hal_ret = HAL_ETH_Init(heth);
|
||||
if (hal_ret == HAL_TIMEOUT) {
|
||||
/* HAL Init time out. This could be linked to
|
||||
* a recoverable error. Log the issue and continue
|
||||
* driver initialization.
|
||||
*/
|
||||
LOG_WRN("HAL_ETH_Init timed out (cable not connected?)");
|
||||
} else if (hal_ret != HAL_OK) {
|
||||
LOG_ERR("HAL_ETH_Init failed: %d", hal_ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Initialize semaphores */
|
||||
k_mutex_init(&dev_data->tx_mutex);
|
||||
k_sem_init(&dev_data->rx_int_sem, 0, K_SEM_MAX_LIMIT);
|
||||
|
||||
HAL_ETH_DMATxDescListInit(heth, dma_tx_desc_tab, &dma_tx_buffer[0][0], ETH_TXBUFNB);
|
||||
HAL_ETH_DMARxDescListInit(heth, dma_rx_desc_tab, &dma_rx_buffer[0][0], ETH_RXBUFNB);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#elif defined(CONFIG_ETH_STM32_HAL_API_V2)
|
||||
static int eth_init_api_v2(const struct device *dev)
|
||||
{
|
||||
HAL_StatusTypeDef hal_ret = HAL_OK;
|
||||
struct eth_stm32_hal_dev_data *dev_data = dev->data;
|
||||
ETH_HandleTypeDef *heth = &dev_data->heth;
|
||||
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32n6_ethernet)
|
||||
for (int ch = 0; ch < ETH_DMA_CH_CNT; ch++) {
|
||||
heth->Init.TxDesc[ch] = dma_tx_desc_tab[ch];
|
||||
heth->Init.RxDesc[ch] = dma_rx_desc_tab[ch];
|
||||
}
|
||||
#else
|
||||
heth->Init.TxDesc = dma_tx_desc_tab;
|
||||
heth->Init.RxDesc = dma_rx_desc_tab;
|
||||
#endif
|
||||
heth->Init.RxBuffLen = ETH_STM32_RX_BUF_SIZE;
|
||||
|
||||
hal_ret = HAL_ETH_Init(heth);
|
||||
if (hal_ret == HAL_TIMEOUT) {
|
||||
/* HAL Init time out. This could be linked to
|
||||
* a recoverable error. Log the issue and continue
|
||||
* driver initialization.
|
||||
*/
|
||||
LOG_ERR("HAL_ETH_Init Timed out");
|
||||
} else if (hal_ret != HAL_OK) {
|
||||
LOG_ERR("HAL_ETH_Init failed: %d", hal_ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PTP_CLOCK_STM32_HAL)
|
||||
/* Enable timestamping of RX packets. We enable all packets to be
|
||||
* timestamped to cover both IEEE 1588 and gPTP.
|
||||
*/
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet)
|
||||
heth->Instance->MACTSCR |= ETH_MACTSCR_TSENALL;
|
||||
#else
|
||||
heth->Instance->PTPTSCR |= ETH_PTPTSCR_TSSARFE;
|
||||
#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet) */
|
||||
#endif /* CONFIG_PTP_CLOCK_STM32_HAL */
|
||||
|
||||
/* Initialize semaphores */
|
||||
k_mutex_init(&dev_data->tx_mutex);
|
||||
k_sem_init(&dev_data->rx_int_sem, 0, K_SEM_MAX_LIMIT);
|
||||
k_sem_init(&dev_data->tx_int_sem, 0, K_SEM_MAX_LIMIT);
|
||||
|
||||
/* Tx config init: */
|
||||
memset(&tx_config, 0, sizeof(ETH_TxPacketConfig));
|
||||
tx_config.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD;
|
||||
tx_config.ChecksumCtrl = IS_ENABLED(CONFIG_ETH_STM32_HW_CHECKSUM)
|
||||
? ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC
|
||||
: ETH_CHECKSUM_DISABLE;
|
||||
tx_config.CRCPadCtrl = ETH_CRC_PAD_INSERT;
|
||||
|
||||
/* prepare tx buffer header */
|
||||
for (uint16_t i = 0; i < ETH_TXBUFNB; ++i) {
|
||||
dma_tx_buffer_header[i].tx_buff.buffer = dma_tx_buffer[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_ETH_STM32_HAL_API_V2 */
|
||||
|
||||
static int eth_initialize(const struct device *dev)
|
||||
{
|
||||
struct eth_stm32_hal_dev_data *dev_data = dev->data;
|
||||
@@ -891,41 +999,17 @@ static int eth_initialize(const struct device *dev)
|
||||
heth->Init.MACAddr = dev_data->mac_addr;
|
||||
|
||||
#if defined(CONFIG_ETH_STM32_HAL_API_V1)
|
||||
HAL_StatusTypeDef hal_ret = HAL_OK;
|
||||
ret = eth_init_api_v1(dev);
|
||||
#elif defined(CONFIG_ETH_STM32_HAL_API_V2)
|
||||
ret = eth_init_api_v2(dev);
|
||||
#else
|
||||
ret = 0;
|
||||
#endif /* CONFIG_ETH_STM32_HAL_API_V1 */
|
||||
|
||||
if (!ETH_STM32_AUTO_NEGOTIATION_ENABLE) {
|
||||
struct phy_link_state state;
|
||||
|
||||
phy_get_link_state(eth_stm32_phy_dev, &state);
|
||||
|
||||
heth->Init.DuplexMode = PHY_LINK_IS_FULL_DUPLEX(state.speed) ? ETH_MODE_FULLDUPLEX
|
||||
: ETH_MODE_HALFDUPLEX;
|
||||
heth->Init.Speed =
|
||||
PHY_LINK_IS_SPEED_100M(state.speed) ? ETH_SPEED_100M : ETH_SPEED_10M;
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
hal_ret = HAL_ETH_Init(heth);
|
||||
if (hal_ret == HAL_TIMEOUT) {
|
||||
/* HAL Init time out. This could be linked to */
|
||||
/* a recoverable error. Log the issue and continue */
|
||||
/* driver initialisation */
|
||||
LOG_WRN("HAL_ETH_Init timed out (cable not connected?)");
|
||||
} else if (hal_ret != HAL_OK) {
|
||||
LOG_ERR("HAL_ETH_Init failed: %d", hal_ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Initialize semaphores */
|
||||
k_mutex_init(&dev_data->tx_mutex);
|
||||
k_sem_init(&dev_data->rx_int_sem, 0, K_SEM_MAX_LIMIT);
|
||||
|
||||
HAL_ETH_DMATxDescListInit(heth, dma_tx_desc_tab,
|
||||
&dma_tx_buffer[0][0], ETH_TXBUFNB);
|
||||
HAL_ETH_DMARxDescListInit(heth, dma_rx_desc_tab,
|
||||
&dma_rx_buffer[0][0], ETH_RXBUFNB);
|
||||
|
||||
#endif /* !CONFIG_ETH_STM32_HAL_API_V1 */
|
||||
|
||||
LOG_DBG("MAC %02x:%02x:%02x:%02x:%02x:%02x",
|
||||
dev_data->mac_addr[0], dev_data->mac_addr[1],
|
||||
dev_data->mac_addr[2], dev_data->mac_addr[3],
|
||||
@@ -982,68 +1066,6 @@ static void eth_stm32_mcast_filter(const struct device *dev, const struct ethern
|
||||
|
||||
#endif /* CONFIG_ETH_STM32_MULTICAST_FILTER */
|
||||
|
||||
#if defined(CONFIG_ETH_STM32_HAL_API_V2)
|
||||
static int eth_init_api_v2(const struct device *dev)
|
||||
{
|
||||
HAL_StatusTypeDef hal_ret = HAL_OK;
|
||||
struct eth_stm32_hal_dev_data *dev_data = dev->data;
|
||||
ETH_HandleTypeDef *heth = &dev_data->heth;
|
||||
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32n6_ethernet)
|
||||
for (int ch = 0; ch < ETH_DMA_CH_CNT; ch++) {
|
||||
heth->Init.TxDesc[ch] = dma_tx_desc_tab[ch];
|
||||
heth->Init.RxDesc[ch] = dma_rx_desc_tab[ch];
|
||||
}
|
||||
#else
|
||||
heth->Init.TxDesc = dma_tx_desc_tab;
|
||||
heth->Init.RxDesc = dma_rx_desc_tab;
|
||||
#endif
|
||||
heth->Init.RxBuffLen = ETH_STM32_RX_BUF_SIZE;
|
||||
|
||||
hal_ret = HAL_ETH_Init(heth);
|
||||
if (hal_ret == HAL_TIMEOUT) {
|
||||
/* HAL Init time out. This could be linked to */
|
||||
/* a recoverable error. Log the issue and continue */
|
||||
/* driver initialisation */
|
||||
LOG_ERR("HAL_ETH_Init Timed out");
|
||||
} else if (hal_ret != HAL_OK) {
|
||||
LOG_ERR("HAL_ETH_Init failed: %d", hal_ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PTP_CLOCK_STM32_HAL)
|
||||
/* Enable timestamping of RX packets. We enable all packets to be
|
||||
* timestamped to cover both IEEE 1588 and gPTP.
|
||||
*/
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet)
|
||||
heth->Instance->MACTSCR |= ETH_MACTSCR_TSENALL;
|
||||
#else
|
||||
heth->Instance->PTPTSCR |= ETH_PTPTSCR_TSSARFE;
|
||||
#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet) */
|
||||
#endif /* CONFIG_PTP_CLOCK_STM32_HAL */
|
||||
|
||||
/* Initialize semaphores */
|
||||
k_mutex_init(&dev_data->tx_mutex);
|
||||
k_sem_init(&dev_data->rx_int_sem, 0, K_SEM_MAX_LIMIT);
|
||||
k_sem_init(&dev_data->tx_int_sem, 0, K_SEM_MAX_LIMIT);
|
||||
|
||||
/* Tx config init: */
|
||||
memset(&tx_config, 0, sizeof(ETH_TxPacketConfig));
|
||||
tx_config.Attributes = ETH_TX_PACKETS_FEATURES_CSUM |
|
||||
ETH_TX_PACKETS_FEATURES_CRCPAD;
|
||||
tx_config.ChecksumCtrl = IS_ENABLED(CONFIG_ETH_STM32_HW_CHECKSUM) ?
|
||||
ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC : ETH_CHECKSUM_DISABLE;
|
||||
tx_config.CRCPadCtrl = ETH_CRC_PAD_INSERT;
|
||||
|
||||
/* prepare tx buffer header */
|
||||
for (uint16_t i = 0; i < ETH_TXBUFNB; ++i) {
|
||||
dma_tx_buffer_header[i].tx_buff.buffer = dma_tx_buffer[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_ETH_STM32_HAL_API_V2 */
|
||||
|
||||
static void set_mac_config(const struct device *dev, struct phy_link_state *state)
|
||||
{
|
||||
struct eth_stm32_hal_dev_data *dev_data = dev->data;
|
||||
@@ -1164,14 +1186,6 @@ static void eth_iface_init(struct net_if *iface)
|
||||
|
||||
ethernet_init(iface);
|
||||
|
||||
#if defined(CONFIG_ETH_STM32_HAL_API_V2)
|
||||
/* This function requires the Ethernet interface to be
|
||||
* properly initialized. In auto-negotiation mode, it reads the speed
|
||||
* and duplex settings to configure the driver accordingly.
|
||||
*/
|
||||
eth_init_api_v2(dev);
|
||||
#endif
|
||||
|
||||
setup_mac_filter(heth);
|
||||
|
||||
net_if_carrier_off(iface);
|
||||
|
||||
@@ -62,10 +62,10 @@
|
||||
do { \
|
||||
uint32_t id = 0x001100; \
|
||||
\
|
||||
mac_addr[0] = FREESCALE_OUI_B0; \
|
||||
mac_addr[1] = FREESCALE_OUI_B1; \
|
||||
/* Set MAC address locally administered bit (LAA) */ \
|
||||
mac_addr[2] = FREESCALE_OUI_B2 | 0x02; \
|
||||
mac_addr[0] = FREESCALE_OUI_B0 | 0x02; \
|
||||
mac_addr[1] = FREESCALE_OUI_B1; \
|
||||
mac_addr[2] = FREESCALE_OUI_B2; \
|
||||
mac_addr[3] = (id >> 16) & 0xff; \
|
||||
mac_addr[4] = (id >> 8) & 0xff; \
|
||||
mac_addr[5] = (id + n) & 0xff; \
|
||||
|
||||
@@ -37,6 +37,7 @@ LOG_MODULE_REGISTER(LOG_DOMAIN);
|
||||
/* No information in documentation about that. */
|
||||
#define STM32H7_FLASH_OPT_TIMEOUT_MS 800
|
||||
|
||||
#if DT_NODE_HAS_PROP(DT_INST(0, st_stm32_nv_flash), bank2_flash_size)
|
||||
#define STM32H7_M4_FLASH_SIZE DT_PROP_OR(DT_INST(0, st_stm32_nv_flash), bank2_flash_size, 0)
|
||||
#ifdef CONFIG_CPU_CORTEX_M4
|
||||
#if STM32H7_M4_FLASH_SIZE == 0
|
||||
@@ -45,12 +46,11 @@ LOG_MODULE_REGISTER(LOG_DOMAIN);
|
||||
#define REAL_FLASH_SIZE_KB (KB(STM32H7_M4_FLASH_SIZE * 2))
|
||||
#endif
|
||||
#else
|
||||
#if defined(DUAL_BANK)
|
||||
#define REAL_FLASH_SIZE_KB (DT_REG_SIZE(DT_INST(0, st_stm32_nv_flash)) * 2)
|
||||
#endif
|
||||
#else
|
||||
#define REAL_FLASH_SIZE_KB DT_REG_SIZE(DT_INST(0, st_stm32_nv_flash))
|
||||
#endif
|
||||
#endif
|
||||
#define SECTOR_PER_BANK ((REAL_FLASH_SIZE_KB / FLASH_SECTOR_SIZE) / 2)
|
||||
#if defined(DUAL_BANK)
|
||||
#define STM32H7_SERIES_MAX_FLASH_KB KB(2048)
|
||||
|
||||
@@ -126,6 +126,12 @@ static int gpio_stm32_pincfg_to_flags(struct gpio_stm32_pin pin_cfg,
|
||||
if (pin_cfg.type == LL_GPIO_OUTPUT_OPENDRAIN) {
|
||||
flags |= GPIO_OPEN_DRAIN;
|
||||
}
|
||||
|
||||
if (pin_cfg.out_state == 0) {
|
||||
flags |= GPIO_OUTPUT_INIT_LOW;
|
||||
} else {
|
||||
flags |= GPIO_OUTPUT_INIT_HIGH;
|
||||
}
|
||||
} else if (pin_cfg.mode == LL_GPIO_MODE_INPUT) {
|
||||
flags |= GPIO_INPUT;
|
||||
#ifdef CONFIG_SOC_SERIES_STM32F1X
|
||||
@@ -142,12 +148,6 @@ static int gpio_stm32_pincfg_to_flags(struct gpio_stm32_pin pin_cfg,
|
||||
flags |= GPIO_PULL_DOWN;
|
||||
}
|
||||
|
||||
if (pin_cfg.out_state != 0) {
|
||||
flags |= GPIO_OUTPUT_HIGH;
|
||||
} else {
|
||||
flags |= GPIO_OUTPUT_LOW;
|
||||
}
|
||||
|
||||
*out_flags = flags;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <zephyr/sys/util.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <soc.h>
|
||||
#include <stm32_cache.h>
|
||||
#include <stm32_ll_i2c.h>
|
||||
#include <errno.h>
|
||||
#include <zephyr/drivers/i2c.h>
|
||||
|
||||
@@ -210,13 +210,16 @@ int i2c_stm32_target_register(const struct device *dev,
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PM_DEVICE_RUNTIME)
|
||||
/* Mark device as active */
|
||||
(void)pm_device_runtime_get(dev);
|
||||
|
||||
#if !defined(CONFIG_SOC_SERIES_STM32F7X)
|
||||
if (pm_device_wakeup_is_capable(dev)) {
|
||||
/* Mark device as active */
|
||||
(void)pm_device_runtime_get(dev);
|
||||
/* Enable wake-up from stop */
|
||||
LOG_DBG("i2c: enabling wakeup from stop");
|
||||
LL_I2C_EnableWakeUpFromStop(cfg->i2c);
|
||||
}
|
||||
#endif /* !CONFIG_SOC_SERIES_STM32F7X */
|
||||
#endif /* defined(CONFIG_PM_DEVICE_RUNTIME) */
|
||||
|
||||
LL_I2C_Enable(i2c);
|
||||
@@ -299,15 +302,18 @@ int i2c_stm32_target_unregister(const struct device *dev,
|
||||
LL_I2C_Disable(i2c);
|
||||
|
||||
#if defined(CONFIG_PM_DEVICE_RUNTIME)
|
||||
#if !defined(CONFIG_SOC_SERIES_STM32F7X)
|
||||
if (pm_device_wakeup_is_capable(dev)) {
|
||||
/* Disable wake-up from STOP */
|
||||
LOG_DBG("i2c: disabling wakeup from stop");
|
||||
LL_I2C_DisableWakeUpFromStop(i2c);
|
||||
/* Release the device */
|
||||
(void)pm_device_runtime_put(dev);
|
||||
}
|
||||
#endif /* !CONFIG_SOC_SERIES_STM32F7X */
|
||||
#endif /* defined(CONFIG_PM_DEVICE_RUNTIME) */
|
||||
|
||||
/* Release the device */
|
||||
(void)pm_device_runtime_put(dev);
|
||||
|
||||
data->slave_attached = false;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1047,6 +1047,7 @@ static int i3c_stm32_do_daa(const struct device *dev)
|
||||
const struct i3c_stm32_config *config = dev->config;
|
||||
struct i3c_stm32_data *data = dev->data;
|
||||
I3C_TypeDef *i3c = config->i3c;
|
||||
int ret = 0;
|
||||
|
||||
k_mutex_lock(&data->bus_mutex, K_FOREVER);
|
||||
|
||||
@@ -1068,7 +1069,8 @@ static int i3c_stm32_do_daa(const struct device *dev)
|
||||
|
||||
/* Wait for DAA to finish */
|
||||
if (k_sem_take(&data->device_sync_sem, STM32_I3C_TRANSFER_TIMEOUT) != 0) {
|
||||
return -ETIMEDOUT;
|
||||
ret = -ETIMEDOUT;
|
||||
goto i3c_stm32_do_daa_ending;
|
||||
}
|
||||
|
||||
if (data->msg_state == STM32_I3C_MSG_ERR) {
|
||||
@@ -1076,12 +1078,14 @@ static int i3c_stm32_do_daa(const struct device *dev)
|
||||
/* Enable TXFNF interrupt in case an error occurred before it was enabled by RXFNE
|
||||
*/
|
||||
LL_I3C_EnableIT_TXFNF(i3c);
|
||||
return -EIO;
|
||||
ret = -EIO;
|
||||
goto i3c_stm32_do_daa_ending;
|
||||
}
|
||||
|
||||
i3c_stm32_do_daa_ending:
|
||||
k_mutex_unlock(&data->bus_mutex);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_I3C_STM32_DMA
|
||||
|
||||
@@ -23,7 +23,7 @@ BUILD_ASSERT(DT_PROP(FLEXRAM_DT_NODE, flexram_has_magic_addr),
|
||||
#define BANK_SIZE (DT_PROP(FLEXRAM_DT_NODE, flexram_bank_size) * 1024)
|
||||
#define NUM_BANKS DT_PROP(FLEXRAM_DT_NODE, flexram_num_ram_banks)
|
||||
|
||||
#define IS_CHILD_RAM_TYPE(node_id, compat) DT_NODE_HAS_COMPAT(node_id, compat)
|
||||
#define IS_CHILD_RAM_TYPE(node_id, compat) DT_NODE_HAS_COMPAT_STATUS(node_id, compat, okay)
|
||||
#define DOES_RAM_TYPE_EXIST(compat) \
|
||||
DT_FOREACH_CHILD_SEP_VARGS(FLEXRAM_DT_NODE, IS_CHILD_RAM_TYPE, (+), compat)
|
||||
|
||||
|
||||
@@ -974,17 +974,9 @@ static int ppp_driver_init(const struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct net_linkaddr *ppp_get_mac(struct ppp_driver_context *ppp)
|
||||
{
|
||||
(void)net_linkaddr_set(&ppp->ll_addr, ppp->mac_addr, sizeof(ppp->mac_addr));
|
||||
|
||||
return &ppp->ll_addr;
|
||||
}
|
||||
|
||||
static void ppp_iface_init(struct net_if *iface)
|
||||
{
|
||||
struct ppp_driver_context *ppp = net_if_get_device(iface)->data;
|
||||
struct net_linkaddr *ll_addr;
|
||||
|
||||
LOG_DBG("[%p] iface %p", ppp, iface);
|
||||
|
||||
@@ -997,11 +989,6 @@ static void ppp_iface_init(struct net_if *iface)
|
||||
ppp->init_done = true;
|
||||
ppp->iface = iface;
|
||||
|
||||
/* The mac address is not really used but network interface expects
|
||||
* to find one.
|
||||
*/
|
||||
ll_addr = ppp_get_mac(ppp);
|
||||
|
||||
if (CONFIG_PPP_MAC_ADDR[0] != 0) {
|
||||
if (net_bytes_from_str(ppp->mac_addr, sizeof(ppp->mac_addr),
|
||||
CONFIG_PPP_MAC_ADDR) < 0) {
|
||||
@@ -1018,7 +1005,10 @@ use_random_mac:
|
||||
ppp->mac_addr[5] = sys_rand8_get();
|
||||
}
|
||||
|
||||
net_if_set_link_addr(iface, ll_addr->addr, ll_addr->len,
|
||||
/* The MAC address is not really used, but the network interface expects to find one. */
|
||||
(void)net_linkaddr_set(&ppp->ll_addr, ppp->mac_addr, sizeof(ppp->mac_addr));
|
||||
|
||||
net_if_set_link_addr(iface, ppp->ll_addr.addr, ppp->ll_addr.len,
|
||||
NET_LINK_ETHERNET);
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_PPP_CAPTURE)) {
|
||||
|
||||
@@ -527,7 +527,12 @@ static bool device_is_regulator(const struct device *dev)
|
||||
return DEVICE_API_IS(regulator, dev);
|
||||
}
|
||||
|
||||
static void device_name_get(size_t idx, struct shell_static_entry *entry)
|
||||
static bool device_is_regulator_parent(const struct device *dev)
|
||||
{
|
||||
return DEVICE_API_IS(regulator_parent, dev);
|
||||
}
|
||||
|
||||
static void device_name_get_regulator(size_t idx, struct shell_static_entry *entry)
|
||||
{
|
||||
const struct device *dev = shell_device_filter(idx, device_is_regulator);
|
||||
|
||||
@@ -537,7 +542,18 @@ static void device_name_get(size_t idx, struct shell_static_entry *entry)
|
||||
entry->subcmd = NULL;
|
||||
}
|
||||
|
||||
SHELL_DYNAMIC_CMD_CREATE(dsub_device_name, device_name_get);
|
||||
static void device_name_get_regulator_parent(size_t idx, struct shell_static_entry *entry)
|
||||
{
|
||||
const struct device *dev = shell_device_filter(idx, device_is_regulator_parent);
|
||||
|
||||
entry->syntax = (dev != NULL) ? dev->name : NULL;
|
||||
entry->handler = NULL;
|
||||
entry->help = NULL;
|
||||
entry->subcmd = NULL;
|
||||
}
|
||||
|
||||
SHELL_DYNAMIC_CMD_CREATE(dsub_device_name, device_name_get_regulator);
|
||||
SHELL_DYNAMIC_CMD_CREATE(dsub_device_name_parent, device_name_get_regulator_parent);
|
||||
|
||||
SHELL_STATIC_SUBCMD_SET_CREATE(
|
||||
sub_regulator_cmds,
|
||||
@@ -579,12 +595,12 @@ SHELL_STATIC_SUBCMD_SET_CREATE(
|
||||
2, 0),
|
||||
SHELL_CMD_ARG(errors, &dsub_device_name, SHELL_HELP("Get active errors", "<device>"),
|
||||
cmd_errors, 2, 0),
|
||||
SHELL_CMD_ARG(dvsset, &dsub_device_name,
|
||||
SHELL_CMD_ARG(dvsset, &dsub_device_name_parent,
|
||||
SHELL_HELP("Set dynamic voltage scaling state",
|
||||
"<device> <state identifier>"),
|
||||
cmd_dvsset, 3, 0),
|
||||
SHELL_CMD_ARG(shipmode, &dsub_device_name, SHELL_HELP("Enable ship mode", "<device>"),
|
||||
cmd_shipmode, 2, 0),
|
||||
SHELL_CMD_ARG(shipmode, &dsub_device_name_parent,
|
||||
SHELL_HELP("Enable ship mode", "<device>"), cmd_shipmode, 2, 0),
|
||||
SHELL_SUBCMD_SET_END);
|
||||
|
||||
SHELL_CMD_REGISTER(regulator, &sub_regulator_cmds, "Regulator playground",
|
||||
|
||||
@@ -55,6 +55,19 @@ static int lis2dux12_freq_to_odr_val(const struct device *dev, uint16_t freq)
|
||||
int odr;
|
||||
|
||||
for (odr = LIS2DUX12_DT_ODR_OFF; odr < LIS2DUX12_DT_ODR_END; odr++) {
|
||||
/*
|
||||
* In case power-mode is HP, skip the ULP odrs in order to
|
||||
* avoid to erroneously break the loop sooner than expected.
|
||||
* In HP mode the correct ODRs must be found from
|
||||
* LIS2DUX12_DT_ODR_6Hz on.
|
||||
*/
|
||||
if ((cfg->pm == LIS2DUX12_OPER_MODE_HIGH_PERFORMANCE) &&
|
||||
((odr == LIS2DUX12_DT_ODR_1Hz_ULP) ||
|
||||
(odr == LIS2DUX12_DT_ODR_3Hz_ULP) ||
|
||||
(odr == LIS2DUX12_DT_ODR_25Hz_ULP))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (freq <= lis2dux12_odr_map[odr]) {
|
||||
break;
|
||||
}
|
||||
@@ -69,15 +82,6 @@ static int lis2dux12_freq_to_odr_val(const struct device *dev, uint16_t freq)
|
||||
return LIS2DUX12_DT_ODR_OFF;
|
||||
}
|
||||
|
||||
/* handle high performance mode */
|
||||
if (cfg->pm == LIS2DUX12_OPER_MODE_HIGH_PERFORMANCE) {
|
||||
if (odr < LIS2DUX12_DT_ODR_6Hz) {
|
||||
odr = LIS2DUX12_DT_ODR_6Hz;
|
||||
}
|
||||
|
||||
odr |= 0x10;
|
||||
}
|
||||
|
||||
return odr;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,19 @@ static int32_t st_lis2dux12_set_odr_raw(const struct device *dev, uint8_t odr)
|
||||
struct lis2dux12_data *data = dev->data;
|
||||
const struct lis2dux12_config *cfg = dev->config;
|
||||
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
|
||||
lis2dux12_md_t mode = {.odr = odr, .fs = data->range};
|
||||
lis2dux12_md_t mode;
|
||||
|
||||
/* handle high performance mode */
|
||||
if (cfg->pm == LIS2DUX12_OPER_MODE_HIGH_PERFORMANCE) {
|
||||
if (odr < LIS2DUX12_DT_ODR_6Hz) {
|
||||
odr = LIS2DUX12_DT_ODR_6Hz;
|
||||
}
|
||||
|
||||
odr |= 0x10;
|
||||
}
|
||||
|
||||
mode.odr = odr;
|
||||
mode.fs = data->range;
|
||||
|
||||
data->odr = odr;
|
||||
return lis2dux12_mode_set(ctx, &mode);
|
||||
|
||||
@@ -17,7 +17,19 @@ static int32_t st_lis2duxs12_set_odr_raw(const struct device *dev, uint8_t odr)
|
||||
struct lis2dux12_data *data = dev->data;
|
||||
const struct lis2dux12_config *cfg = dev->config;
|
||||
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
|
||||
lis2duxs12_md_t mode = {.odr = odr, .fs = data->range};
|
||||
lis2duxs12_md_t mode;
|
||||
|
||||
/* handle high performance mode */
|
||||
if (cfg->pm == LIS2DUX12_OPER_MODE_HIGH_PERFORMANCE) {
|
||||
if (odr < LIS2DUX12_DT_ODR_6Hz) {
|
||||
odr = LIS2DUX12_DT_ODR_6Hz;
|
||||
}
|
||||
|
||||
odr |= 0x10;
|
||||
}
|
||||
|
||||
mode.odr = odr;
|
||||
mode.fs = data->range;
|
||||
|
||||
data->odr = odr;
|
||||
return lis2duxs12_mode_set(ctx, &mode);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Analog Devices, Inc.
|
||||
* Copyright (c) 2024-2025 Analog Devices, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -27,6 +27,9 @@
|
||||
LOG_MODULE_REGISTER(spi_max32, CONFIG_SPI_LOG_LEVEL);
|
||||
#include "spi_context.h"
|
||||
|
||||
#define SPI_MAX32_MIN_WORD_BITS 2
|
||||
#define SPI_MAX32_MAX_WORD_BITS 16
|
||||
|
||||
#ifdef CONFIG_SPI_MAX32_DMA
|
||||
struct max32_spi_dma_config {
|
||||
const struct device *dev;
|
||||
@@ -87,9 +90,11 @@ static int spi_configure(const struct device *dev, const struct spi_config *conf
|
||||
mxc_spi_regs_t *regs = cfg->regs;
|
||||
struct max32_spi_data *data = dev->data;
|
||||
|
||||
#ifndef CONFIG_SPI_RTIO
|
||||
if (spi_context_configured(&data->ctx, config)) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (SPI_OP_MODE_GET(config->operation) & SPI_OP_MODE_SLAVE) {
|
||||
return -ENOTSUP;
|
||||
@@ -103,7 +108,7 @@ static int spi_configure(const struct device *dev, const struct spi_config *conf
|
||||
|
||||
ret = Wrap_MXC_SPI_Init(regs, master_mode, quad_mode, num_slaves, ss_polarity, spi_speed);
|
||||
if (ret) {
|
||||
return ret;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int cpol = (SPI_MODE_GET(config->operation) & SPI_MODE_CPOL) ? 1 : 0;
|
||||
@@ -119,12 +124,12 @@ static int spi_configure(const struct device *dev, const struct spi_config *conf
|
||||
ret = MXC_SPI_SetMode(regs, SPI_MODE_0);
|
||||
}
|
||||
if (ret) {
|
||||
return ret;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = MXC_SPI_SetDataSize(regs, SPI_WORD_SIZE_GET(config->operation));
|
||||
if (ret) {
|
||||
return ret;
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SPI_EXTENDED_MODES)
|
||||
@@ -145,7 +150,7 @@ static int spi_configure(const struct device *dev, const struct spi_config *conf
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
return ret;
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -163,7 +168,7 @@ static inline int spi_max32_get_dfs_shift(const struct spi_context *ctx)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void spi_max32_setup(mxc_spi_regs_t *spi, mxc_spi_req_t *req)
|
||||
static void spi_max32_setup(mxc_spi_regs_t *spi, mxc_spi_req_t *req, uint8_t dfs_shift)
|
||||
{
|
||||
req->rxCnt = 0;
|
||||
req->txCnt = 0;
|
||||
@@ -172,9 +177,10 @@ static void spi_max32_setup(mxc_spi_regs_t *spi, mxc_spi_req_t *req)
|
||||
MXC_SPI_SetSlave(spi, req->ssIdx);
|
||||
}
|
||||
|
||||
/* SPI_CTRL1 holds the number of words so apply dfs_shift first */
|
||||
if (req->rxData && req->rxLen) {
|
||||
MXC_SETFIELD(spi->ctrl1, MXC_F_SPI_CTRL1_RX_NUM_CHAR,
|
||||
req->rxLen << MXC_F_SPI_CTRL1_RX_NUM_CHAR_POS);
|
||||
(req->rxLen >> dfs_shift) << MXC_F_SPI_CTRL1_RX_NUM_CHAR_POS);
|
||||
spi->dma |= MXC_F_SPI_DMA_RX_FIFO_EN;
|
||||
} else {
|
||||
spi->ctrl1 &= ~MXC_F_SPI_CTRL1_RX_NUM_CHAR;
|
||||
@@ -183,7 +189,7 @@ static void spi_max32_setup(mxc_spi_regs_t *spi, mxc_spi_req_t *req)
|
||||
|
||||
if (req->txLen) {
|
||||
MXC_SETFIELD(spi->ctrl1, MXC_F_SPI_CTRL1_TX_NUM_CHAR,
|
||||
req->txLen << MXC_F_SPI_CTRL1_TX_NUM_CHAR_POS);
|
||||
(req->txLen >> dfs_shift) << MXC_F_SPI_CTRL1_TX_NUM_CHAR_POS);
|
||||
spi->dma |= MXC_F_SPI_DMA_TX_FIFO_EN;
|
||||
} else {
|
||||
spi->ctrl1 &= ~MXC_F_SPI_CTRL1_TX_NUM_CHAR;
|
||||
@@ -206,8 +212,8 @@ static int spi_max32_transceive_sync(mxc_spi_regs_t *spi, struct max32_spi_data
|
||||
MXC_SPI_ClearTXFIFO(spi);
|
||||
MXC_SPI_ClearRXFIFO(spi);
|
||||
|
||||
tx_len = req->txLen << dfs_shift;
|
||||
rx_len = req->rxLen << dfs_shift;
|
||||
tx_len = req->txLen;
|
||||
rx_len = req->rxLen;
|
||||
do {
|
||||
remain = tx_len - req->txCnt;
|
||||
if (remain > 0) {
|
||||
@@ -251,8 +257,6 @@ static int spi_max32_transceive(const struct device *dev)
|
||||
uint32_t len;
|
||||
uint8_t dfs_shift;
|
||||
|
||||
MXC_SPI_ClearTXFIFO(cfg->regs);
|
||||
|
||||
dfs_shift = spi_max32_get_dfs_shift(ctx);
|
||||
|
||||
len = spi_context_max_continuous_chunk(ctx);
|
||||
@@ -263,48 +267,64 @@ static int spi_max32_transceive(const struct device *dev)
|
||||
len = sqe->rx.buf_len;
|
||||
data->req.rxData = sqe->rx.buf;
|
||||
data->req.rxLen = sqe->rx.buf_len;
|
||||
if (data->req.rxData == NULL) {
|
||||
data->req.rxData = data->dummy;
|
||||
data->req.rxLen = 0;
|
||||
}
|
||||
data->req.txData = NULL;
|
||||
data->req.txLen = len >> dfs_shift;
|
||||
data->req.txLen = len;
|
||||
break;
|
||||
case RTIO_OP_TX:
|
||||
len = sqe->tx.buf_len;
|
||||
data->req.rxLen = 0;
|
||||
data->req.rxData = data->dummy;
|
||||
data->req.txData = (uint8_t *)sqe->tx.buf;
|
||||
data->req.txLen = len >> dfs_shift;
|
||||
data->req.txLen = len;
|
||||
break;
|
||||
case RTIO_OP_TINY_TX:
|
||||
len = sqe->tiny_tx.buf_len;
|
||||
data->req.txData = (uint8_t *)sqe->tiny_tx.buf;
|
||||
data->req.rxData = data->dummy;
|
||||
data->req.txLen = len >> dfs_shift;
|
||||
data->req.txLen = len;
|
||||
data->req.rxLen = 0;
|
||||
break;
|
||||
case RTIO_OP_TXRX:
|
||||
len = sqe->txrx.buf_len;
|
||||
data->req.txData = (uint8_t *)sqe->txrx.tx_buf;
|
||||
data->req.rxData = sqe->txrx.rx_buf;
|
||||
data->req.txLen = len >> dfs_shift;
|
||||
data->req.rxLen = len >> dfs_shift;
|
||||
data->req.txLen = len;
|
||||
data->req.rxLen = len;
|
||||
if (data->req.rxData == NULL) {
|
||||
data->req.rxData = data->dummy;
|
||||
data->req.rxLen = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#else
|
||||
data->req.txLen = len >> dfs_shift;
|
||||
data->req.txLen = len;
|
||||
data->req.txData = (uint8_t *)ctx->tx_buf;
|
||||
data->req.rxLen = len >> dfs_shift;
|
||||
data->req.rxLen = len;
|
||||
data->req.rxData = ctx->rx_buf;
|
||||
|
||||
data->req.rxData = ctx->rx_buf;
|
||||
|
||||
data->req.rxLen = len >> dfs_shift;
|
||||
if (!data->req.rxData) {
|
||||
/* Pass a dummy buffer to HAL if receive buffer is NULL, otherwise
|
||||
* corrupt data is read during subsequent transactions.
|
||||
*/
|
||||
data->req.rxData = data->dummy;
|
||||
data->req.rxLen = 0;
|
||||
|
||||
if (!data->req.txData && !data->req.txLen) {
|
||||
/* Both RX and TX are NULL, nothing to do */
|
||||
spi_context_update_tx(&data->ctx, dfs_shift ? 2 : 1, len);
|
||||
spi_context_update_rx(&data->ctx, dfs_shift ? 2 : 1, len);
|
||||
if (!spi_context_tx_on(ctx) && !spi_context_rx_on(ctx)) {
|
||||
spi_context_complete(ctx, dev, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
data->req.spi = cfg->regs;
|
||||
@@ -312,15 +332,17 @@ static int spi_max32_transceive(const struct device *dev)
|
||||
data->req.ssDeassert = 0;
|
||||
data->req.txCnt = 0;
|
||||
data->req.rxCnt = 0;
|
||||
spi_max32_setup(cfg->regs, &data->req);
|
||||
spi_max32_setup(cfg->regs, &data->req, dfs_shift);
|
||||
#ifdef CONFIG_SPI_MAX32_INTERRUPT
|
||||
MXC_SPI_SetTXThreshold(cfg->regs, 1);
|
||||
MXC_SPI_SetTXThreshold(cfg->regs, 1 << dfs_shift);
|
||||
if (data->req.rxLen) {
|
||||
MXC_SPI_SetRXThreshold(cfg->regs, 2);
|
||||
MXC_SPI_SetRXThreshold(cfg->regs, 2 << dfs_shift);
|
||||
MXC_SPI_EnableInt(cfg->regs, ADI_MAX32_SPI_INT_EN_RX_THD);
|
||||
}
|
||||
MXC_SPI_EnableInt(cfg->regs, ADI_MAX32_SPI_INT_EN_TX_THD | ADI_MAX32_SPI_INT_EN_MST_DONE);
|
||||
|
||||
MXC_SPI_ClearTXFIFO(cfg->regs);
|
||||
MXC_SPI_ClearRXFIFO(cfg->regs);
|
||||
if (!data->req.txData) {
|
||||
data->req.txCnt =
|
||||
MXC_SPI_WriteTXFIFO(cfg->regs, data->dummy, MIN(len, sizeof(data->dummy)));
|
||||
@@ -334,8 +356,8 @@ static int spi_max32_transceive(const struct device *dev)
|
||||
if (ret) {
|
||||
ret = -EIO;
|
||||
} else {
|
||||
spi_context_update_tx(ctx, 1, len);
|
||||
spi_context_update_rx(ctx, 1, len);
|
||||
spi_context_update_tx(ctx, dfs_shift ? 2 : 1, len);
|
||||
spi_context_update_rx(ctx, dfs_shift ? 2 : 1, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -366,7 +388,7 @@ static int transceive(const struct device *dev, const struct spi_config *config,
|
||||
ret = spi_configure(dev, config);
|
||||
if (ret != 0) {
|
||||
spi_context_release(ctx, ret);
|
||||
return -EIO;
|
||||
return ret;
|
||||
}
|
||||
|
||||
spi_context_buffers_setup(ctx, tx_bufs, rx_bufs, 1);
|
||||
@@ -418,9 +440,20 @@ static int transceive(const struct device *dev, const struct spi_config *config,
|
||||
}
|
||||
}
|
||||
#else
|
||||
struct spi_rtio *rtio_ctx = data->rtio_ctx;
|
||||
/* Guard against unsupported word lengths here, as spi_configure is
|
||||
* called at a later stage
|
||||
*/
|
||||
if ((SPI_WORD_SIZE_GET(config->operation) < SPI_MAX32_MIN_WORD_BITS) ||
|
||||
(SPI_WORD_SIZE_GET(config->operation) > SPI_MAX32_MAX_WORD_BITS)) {
|
||||
ret = -ENOTSUP;
|
||||
} else {
|
||||
if (tx_bufs || rx_bufs) {
|
||||
struct spi_rtio *rtio_ctx = data->rtio_ctx;
|
||||
|
||||
ret = spi_rtio_transceive(rtio_ctx, config, tx_bufs, rx_bufs);
|
||||
}
|
||||
}
|
||||
|
||||
ret = spi_rtio_transceive(rtio_ctx, config, tx_bufs, rx_bufs);
|
||||
#endif
|
||||
spi_context_release(ctx, ret);
|
||||
return ret;
|
||||
@@ -434,9 +467,10 @@ static void spi_max32_dma_callback(const struct device *dev, void *arg, uint32_t
|
||||
const struct device *spi_dev = data->dev;
|
||||
const struct max32_spi_config *config = spi_dev->config;
|
||||
uint32_t len;
|
||||
uint8_t dfs = spi_max32_get_dfs_shift(&data->ctx) ? 2 : 1;
|
||||
|
||||
if (status < 0) {
|
||||
LOG_ERR("DMA callback error with channel %d.", channel);
|
||||
LOG_ERR("DMA callback error for channel %u: %d", channel, status);
|
||||
} else {
|
||||
/* identify the origin of this callback */
|
||||
if (channel == config->tx_dma.channel) {
|
||||
@@ -447,14 +481,14 @@ static void spi_max32_dma_callback(const struct device *dev, void *arg, uint32_t
|
||||
}
|
||||
if ((data->dma_stat & SPI_MAX32_DMA_DONE_FLAG) == SPI_MAX32_DMA_DONE_FLAG) {
|
||||
len = spi_context_max_continuous_chunk(&data->ctx);
|
||||
spi_context_update_tx(&data->ctx, 1, len);
|
||||
spi_context_update_rx(&data->ctx, 1, len);
|
||||
spi_context_update_tx(&data->ctx, dfs, len);
|
||||
spi_context_update_rx(&data->ctx, dfs, len);
|
||||
spi_context_complete(&data->ctx, spi_dev, status == 0 ? 0 : -EIO);
|
||||
}
|
||||
}
|
||||
|
||||
static int spi_max32_tx_dma_load(const struct device *dev, const uint8_t *buf, uint32_t len,
|
||||
uint8_t word_shift)
|
||||
uint8_t dfs_shift)
|
||||
{
|
||||
int ret;
|
||||
const struct max32_spi_config *config = dev->config;
|
||||
@@ -467,9 +501,9 @@ static int spi_max32_tx_dma_load(const struct device *dev, const uint8_t *buf, u
|
||||
dma_cfg.user_data = (void *)data;
|
||||
dma_cfg.dma_slot = config->tx_dma.slot;
|
||||
dma_cfg.block_count = 1;
|
||||
dma_cfg.source_data_size = 1U << word_shift;
|
||||
dma_cfg.source_burst_length = 1U;
|
||||
dma_cfg.dest_data_size = 1U << word_shift;
|
||||
dma_cfg.source_data_size = 1U << dfs_shift;
|
||||
dma_cfg.source_burst_length = 1U << dfs_shift;
|
||||
dma_cfg.dest_data_size = 1U << dfs_shift;
|
||||
dma_cfg.head_block = &dma_blk;
|
||||
dma_blk.block_size = len;
|
||||
if (buf) {
|
||||
@@ -489,7 +523,7 @@ static int spi_max32_tx_dma_load(const struct device *dev, const uint8_t *buf, u
|
||||
}
|
||||
|
||||
static int spi_max32_rx_dma_load(const struct device *dev, const uint8_t *buf, uint32_t len,
|
||||
uint8_t word_shift)
|
||||
uint8_t dfs_shift)
|
||||
{
|
||||
int ret;
|
||||
const struct max32_spi_config *config = dev->config;
|
||||
@@ -502,9 +536,9 @@ static int spi_max32_rx_dma_load(const struct device *dev, const uint8_t *buf, u
|
||||
dma_cfg.user_data = (void *)data;
|
||||
dma_cfg.dma_slot = config->rx_dma.slot;
|
||||
dma_cfg.block_count = 1;
|
||||
dma_cfg.source_data_size = 1U << word_shift;
|
||||
dma_cfg.source_burst_length = 1U;
|
||||
dma_cfg.dest_data_size = 1U << word_shift;
|
||||
dma_cfg.source_data_size = 1U << dfs_shift;
|
||||
dma_cfg.source_burst_length = 1U << dfs_shift;
|
||||
dma_cfg.dest_data_size = 1U << dfs_shift;
|
||||
dma_cfg.head_block = &dma_blk;
|
||||
dma_blk.block_size = len;
|
||||
if (buf) {
|
||||
@@ -540,6 +574,7 @@ static int transceive_dma(const struct device *dev, const struct spi_config *con
|
||||
spi_context_lock(ctx, async, cb, userdata, config);
|
||||
|
||||
MXC_SPI_ClearTXFIFO(spi);
|
||||
MXC_SPI_ClearRXFIFO(spi);
|
||||
|
||||
ret = dma_get_status(cfg->tx_dma.dev, cfg->tx_dma.channel, &status);
|
||||
if (ret < 0 || status.busy) {
|
||||
@@ -553,9 +588,14 @@ static int transceive_dma(const struct device *dev, const struct spi_config *con
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/* Word sizes less than 8-bits are not supported in DMA mode */
|
||||
if (SPI_WORD_SIZE_GET(config->operation) < 8) {
|
||||
ret = -ENOTSUP;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = spi_configure(dev, config);
|
||||
if (ret != 0) {
|
||||
ret = -EIO;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
@@ -581,12 +621,17 @@ static int transceive_dma(const struct device *dev, const struct spi_config *con
|
||||
dfs_shift = spi_max32_get_dfs_shift(ctx);
|
||||
word_count = len >> dfs_shift;
|
||||
|
||||
if (word_count == 0) {
|
||||
/* Nothing to do, continue */
|
||||
continue;
|
||||
}
|
||||
|
||||
MXC_SETFIELD(spi->ctrl1, MXC_F_SPI_CTRL1_RX_NUM_CHAR,
|
||||
word_count << MXC_F_SPI_CTRL1_RX_NUM_CHAR_POS);
|
||||
spi->dma |= ADI_MAX32_SPI_DMA_RX_FIFO_CLEAR;
|
||||
spi->dma |= MXC_F_SPI_DMA_RX_FIFO_EN;
|
||||
spi->dma |= ADI_MAX32_SPI_DMA_RX_DMA_EN;
|
||||
MXC_SPI_SetRXThreshold(spi, 0);
|
||||
MXC_SPI_SetRXThreshold(spi, dfs_shift ? 1 : 0);
|
||||
|
||||
ret = spi_max32_rx_dma_load(dev, ctx->rx_buf, len, dfs_shift);
|
||||
if (ret < 0) {
|
||||
@@ -598,7 +643,7 @@ static int transceive_dma(const struct device *dev, const struct spi_config *con
|
||||
spi->dma |= ADI_MAX32_SPI_DMA_TX_FIFO_CLEAR;
|
||||
spi->dma |= MXC_F_SPI_DMA_TX_FIFO_EN;
|
||||
spi->dma |= ADI_MAX32_SPI_DMA_TX_DMA_EN;
|
||||
MXC_SPI_SetTXThreshold(spi, 1);
|
||||
MXC_SPI_SetTXThreshold(spi, 2);
|
||||
|
||||
ret = spi_max32_tx_dma_load(dev, ctx->tx_buf, len, dfs_shift);
|
||||
if (ret < 0) {
|
||||
@@ -754,6 +799,7 @@ static void spi_max32_callback(mxc_spi_req_t *req, int error)
|
||||
struct spi_context *ctx = &data->ctx;
|
||||
const struct device *dev = data->dev;
|
||||
uint32_t len;
|
||||
uint8_t dfs;
|
||||
|
||||
#ifdef CONFIG_SPI_RTIO
|
||||
struct spi_rtio *rtio_ctx = data->rtio_ctx;
|
||||
@@ -762,9 +808,10 @@ static void spi_max32_callback(mxc_spi_req_t *req, int error)
|
||||
spi_max32_iodev_complete(data->dev, 0);
|
||||
}
|
||||
#endif
|
||||
dfs = spi_max32_get_dfs_shift(ctx) ? 2 : 1;
|
||||
len = spi_context_max_continuous_chunk(ctx);
|
||||
spi_context_update_tx(ctx, 1, len);
|
||||
spi_context_update_rx(ctx, 1, len);
|
||||
spi_context_update_tx(ctx, dfs, len);
|
||||
spi_context_update_rx(ctx, dfs, len);
|
||||
#ifdef CONFIG_SPI_ASYNC
|
||||
if (ctx->asynchronous && ((spi_context_tx_on(ctx) || spi_context_rx_on(ctx)))) {
|
||||
k_work_submit(&data->async_work);
|
||||
@@ -804,12 +851,11 @@ static void spi_max32_isr(const struct device *dev)
|
||||
mxc_spi_req_t *req = &data->req;
|
||||
mxc_spi_regs_t *spi = cfg->regs;
|
||||
uint32_t flags, remain;
|
||||
uint8_t dfs_shift = spi_max32_get_dfs_shift(&data->ctx);
|
||||
|
||||
flags = MXC_SPI_GetFlags(spi);
|
||||
MXC_SPI_ClearFlags(spi);
|
||||
|
||||
remain = (req->txLen << dfs_shift) - req->txCnt;
|
||||
remain = req->txLen - req->txCnt;
|
||||
if (flags & ADI_MAX32_SPI_INT_FL_TX_THD) {
|
||||
if (remain) {
|
||||
if (!data->req.txData) {
|
||||
@@ -824,10 +870,10 @@ static void spi_max32_isr(const struct device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
remain = (req->rxLen << dfs_shift) - req->rxCnt;
|
||||
remain = req->rxLen - req->rxCnt;
|
||||
if (remain) {
|
||||
req->rxCnt += MXC_SPI_ReadRXFIFO(spi, &req->rxData[req->rxCnt], remain);
|
||||
remain = (req->rxLen << dfs_shift) - req->rxCnt;
|
||||
remain = req->rxLen - req->rxCnt;
|
||||
if (remain >= MXC_SPI_FIFO_DEPTH) {
|
||||
MXC_SPI_SetRXThreshold(spi, 2);
|
||||
} else {
|
||||
|
||||
@@ -132,7 +132,10 @@ static uint8_t lpspi_calc_delay_scaler(uint32_t desired_delay_ns,
|
||||
delay_cycles = (uint64_t)prescaled_clock * desired_delay_ns;
|
||||
delay_cycles = DIV_ROUND_UP(delay_cycles, NSEC_PER_SEC);
|
||||
|
||||
/* what the min_cycles parameter is about is that
|
||||
/* clamp to minimally possible cycles to avoid underflow */
|
||||
delay_cycles = MAX(delay_cycles, min_cycles);
|
||||
|
||||
/* what the min_cycles parameter is about is that
|
||||
* PCSSCK and SCKPSC are +1 cycles of the programmed value,
|
||||
* while DBT is +2 cycles of the programmed value.
|
||||
* So this calculates the value to program to the register.
|
||||
|
||||
@@ -429,9 +429,6 @@ static int usb_dc_stm32_clock_enable(void)
|
||||
LL_AHB1_GRP1_DisableClockSleep(LL_AHB1_GRP1_PERIPH_USB1OTGHSULPI);
|
||||
#elif defined(CONFIG_SOC_SERIES_STM32U5X)
|
||||
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_USBPHY);
|
||||
/* Both OTG HS and USBPHY sleep clock MUST be disabled here at the same time */
|
||||
LL_AHB2_GRP1_DisableClockStopSleep(LL_AHB2_GRP1_PERIPH_OTG_HS |
|
||||
LL_AHB2_GRP1_PERIPH_USBPHY);
|
||||
#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32n6_otghs)
|
||||
/* Reset specific configuration bits before setting new values */
|
||||
USB1_HS_PHYC->USBPHYC_CR &= ~USB_USBPHYC_CR_FSEL_Msk;
|
||||
@@ -450,6 +447,12 @@ static int usb_dc_stm32_clock_enable(void)
|
||||
|
||||
#if USB_OTG_HS_EMB_PHYC
|
||||
#if !DT_HAS_COMPAT_STATUS_OKAY(st_stm32n6_otghs)
|
||||
/*
|
||||
* STM32F723 and STM32F730 embedded HS PHY requires ULPI
|
||||
* clock to be enabled (RUN and LP) in addition to USBPHYC.
|
||||
*/
|
||||
LL_AHB1_GRP1_EnableClockLowPower(LL_AHB1_GRP1_PERIPH_OTGHSULPI);
|
||||
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_OTGHSULPI);
|
||||
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_OTGPHYC);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,7 @@ config UDC_MAX32
|
||||
bool "MAX32 USB device controller driver"
|
||||
default y
|
||||
depends on DT_HAS_ADI_MAX32_USBHS_ENABLED
|
||||
select UDC_DRIVER_HAS_HIGH_SPEED_SUPPORT
|
||||
help
|
||||
MAX32 USB device controller driver.
|
||||
|
||||
|
||||
@@ -1143,9 +1143,6 @@ static int priv_clock_enable(void)
|
||||
LL_AHB1_GRP1_DisableClockSleep(LL_AHB1_GRP1_PERIPH_USB1OTGHSULPI);
|
||||
#elif defined(CONFIG_SOC_SERIES_STM32U5X)
|
||||
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_USBPHY);
|
||||
/* Both OTG HS and USBPHY sleep clock MUST be disabled here at the same time */
|
||||
LL_AHB2_GRP1_DisableClockStopSleep(LL_AHB2_GRP1_PERIPH_OTG_HS |
|
||||
LL_AHB2_GRP1_PERIPH_USBPHY);
|
||||
#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32n6_otghs)
|
||||
/* Reset specific configuration bits before setting new values */
|
||||
USB1_HS_PHYC->USBPHYC_CR &= ~USB_USBPHYC_CR_FSEL_Msk;
|
||||
@@ -1164,6 +1161,12 @@ static int priv_clock_enable(void)
|
||||
|
||||
#if USB_OTG_HS_EMB_PHY
|
||||
#if !DT_HAS_COMPAT_STATUS_OKAY(st_stm32n6_otghs)
|
||||
/*
|
||||
* STM32F723 and STM32F730 embedded HS PHY requires ULPI
|
||||
* clock to be enabled (RUN and LP) in addition to USBPHYC.
|
||||
*/
|
||||
LL_AHB1_GRP1_EnableClockLowPower(LL_AHB1_GRP1_PERIPH_OTGHSULPI);
|
||||
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_OTGHSULPI);
|
||||
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_OTGPHYC);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
};
|
||||
};
|
||||
|
||||
i2c3: i2c@4007800 {
|
||||
i2c3: i2c@40007800 {
|
||||
compatible = "st,stm32-i2c-v2";
|
||||
clock-frequency = <I2C_BITRATE_STANDARD>;
|
||||
#address-cells = <1>;
|
||||
|
||||
@@ -252,7 +252,7 @@
|
||||
reg = <0x40008000 0x400>;
|
||||
clocks = <&rcc STM32_CLOCK(APB1, 20U)>;
|
||||
resets = <&rctl STM32_RESET(APB1L, 20U)>;
|
||||
interrupts = <28 0>;
|
||||
interrupts = <29 0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
@@ -261,7 +261,7 @@
|
||||
reg = <0x40008400 0x400>;
|
||||
clocks = <&rcc STM32_CLOCK(APB1, 7U)>;
|
||||
resets = <&rctl STM32_RESET(APB1L, 7U)>;
|
||||
interrupts = <29 0>;
|
||||
interrupts = <28 0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
||||
@@ -881,8 +881,7 @@
|
||||
|
||||
wkup-pin@8 {
|
||||
reg = <0x8>;
|
||||
wkup-gpios = <&gpiof 2 STM32_PWR_WKUP_EVT_SRC_0>,
|
||||
<&gpioa 7 STM32_PWR_WKUP_EVT_SRC_1>,
|
||||
wkup-gpios = <&gpioa 7 STM32_PWR_WKUP_EVT_SRC_1>,
|
||||
<&gpiob 10 STM32_PWR_WKUP_EVT_SRC_2>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -77,3 +77,11 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&pwr {
|
||||
wkup-pin@8 {
|
||||
wkup-gpios = <&gpiof 2 STM32_PWR_WKUP_EVT_SRC_0>,
|
||||
<&gpioa 7 STM32_PWR_WKUP_EVT_SRC_1>,
|
||||
<&gpiob 10 STM32_PWR_WKUP_EVT_SRC_2>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -26,6 +26,41 @@
|
||||
#define _EXC_RETURN_SPSEL_Msk (1 << 2)
|
||||
#define _EXC_RETURN_FTYPE_Msk (1 << 4)
|
||||
|
||||
/*
|
||||
* Cortex-M Exception Stack Frame Layouts
|
||||
*
|
||||
* When an exception is taken, the processor automatically pushes
|
||||
* registers to the current stack. The layout depends on whether
|
||||
* the FPU is active.
|
||||
*/
|
||||
|
||||
/* Basic hardware-saved exception stack frame (no FPU context):
|
||||
* R0-R3 (4 x 4B = 16B)
|
||||
* R12 (4B)
|
||||
* LR (4B)
|
||||
* Return address (4B)
|
||||
* RETPSR (4B)
|
||||
*--------------------------
|
||||
* Total: 32 bytes
|
||||
*/
|
||||
#define _EXC_HW_SAVED_BASIC_SF_SIZE (32)
|
||||
#define _EXC_HW_SAVED_BASIC_SF_RETADDR_OFFSET (24)
|
||||
#define _EXC_HW_SAVED_BASIC_SF_XPSR_OFFSET (28)
|
||||
|
||||
/* Extended hardware saved stack frame consists of:
|
||||
* R0-R3 (16B)
|
||||
* R12 (4B)
|
||||
* LR (R14) (4B)
|
||||
* Return address (4B)
|
||||
* RETPSR (4B)
|
||||
* S0-S15 (16 x 4B = 64B)
|
||||
* FPSCR (4B)
|
||||
* Reserved (4B)
|
||||
*--------------------------
|
||||
* Total: 104 bytes
|
||||
*/
|
||||
#define _EXC_HW_SAVED_EXTENDED_SF_SIZE (104)
|
||||
|
||||
#else
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
@@ -128,8 +128,8 @@ struct _thread_arch {
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
uint32_t priv_stack_start;
|
||||
#if defined(CONFIG_CPU_AARCH32_CORTEX_R)
|
||||
uint32_t priv_stack_end;
|
||||
#if defined(CONFIG_CPU_AARCH32_CORTEX_R)
|
||||
uint32_t sp_usr;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -237,14 +237,21 @@ extern char __sg_size[];
|
||||
* with a MPU. Start and end will be aligned for memory management/protection
|
||||
* hardware for the target architecture.
|
||||
*
|
||||
* All the functions with '__nocache' keyword will be placed into this
|
||||
* section.
|
||||
* All the variables with '__nocache' keyword will be placed into the nocache
|
||||
* section, variables with '__nocache_load' keyword will be placed into the
|
||||
* nocache section that is loaded from ROM.
|
||||
*/
|
||||
#ifdef CONFIG_NOCACHE_MEMORY
|
||||
extern char _nocache_ram_start[];
|
||||
extern char _nocache_ram_end[];
|
||||
extern char _nocache_ram_size[];
|
||||
extern char _nocache_load_start[];
|
||||
extern char _nocache_noload_ram_start[];
|
||||
extern char _nocache_noload_ram_end[];
|
||||
extern char _nocache_noload_ram_size[];
|
||||
extern char _nocache_load_ram_start[];
|
||||
extern char _nocache_load_ram_end[];
|
||||
extern char _nocache_load_ram_size[];
|
||||
extern char _nocache_load_rom_start[];
|
||||
#endif /* CONFIG_NOCACHE_MEMORY */
|
||||
|
||||
/* Memory owned by the kernel. Start and end will be aligned for memory
|
||||
|
||||
@@ -53,9 +53,11 @@
|
||||
|
||||
#if defined(CONFIG_NOCACHE_MEMORY)
|
||||
#define __nocache __in_section_unique(_NOCACHE_SECTION_NAME)
|
||||
#define __nocache_load __in_section_unique(_NOCACHE_LOAD_SECTION_NAME)
|
||||
#define __nocache_noinit __nocache
|
||||
#else
|
||||
#define __nocache
|
||||
#define __nocache_load
|
||||
#define __nocache_noinit __noinit
|
||||
#endif /* CONFIG_NOCACHE_MEMORY */
|
||||
|
||||
|
||||
@@ -77,6 +77,7 @@
|
||||
|
||||
#ifdef CONFIG_NOCACHE_MEMORY
|
||||
#define _NOCACHE_SECTION_NAME nocache
|
||||
#define _NOCACHE_LOAD_SECTION_NAME nocache_load
|
||||
#endif
|
||||
|
||||
/* Symbol table section */
|
||||
|
||||
@@ -93,6 +93,9 @@ struct net_icmp_ctx {
|
||||
/** Opaque user supplied data */
|
||||
void *user_data;
|
||||
|
||||
/** Address family the handler is registered for */
|
||||
uint8_t family;
|
||||
|
||||
/** ICMP type of the response we are waiting */
|
||||
uint8_t type;
|
||||
|
||||
@@ -157,12 +160,13 @@ struct net_icmp_ping_params {
|
||||
* system.
|
||||
*
|
||||
* @param ctx ICMP context used in this request.
|
||||
* @param family Address family the context is using.
|
||||
* @param type Type of ICMP message we are handling.
|
||||
* @param code Code of ICMP message we are handling.
|
||||
* @param handler Callback function that is called when a response is received.
|
||||
*/
|
||||
int net_icmp_init_ctx(struct net_icmp_ctx *ctx, uint8_t type, uint8_t code,
|
||||
net_icmp_handler_t handler);
|
||||
int net_icmp_init_ctx(struct net_icmp_ctx *ctx, uint8_t family, uint8_t type,
|
||||
uint8_t code, net_icmp_handler_t handler);
|
||||
|
||||
/**
|
||||
* @brief Cleanup the ICMP context structure. This will unregister the ICMP handler
|
||||
|
||||
@@ -248,9 +248,8 @@ void z_bss_zero(void)
|
||||
((uintptr_t) &__gcov_bss_end - (uintptr_t) &__gcov_bss_start));
|
||||
#endif /* CONFIG_COVERAGE_GCOV */
|
||||
#ifdef CONFIG_NOCACHE_MEMORY
|
||||
z_early_memset(&_nocache_ram_start, 0,
|
||||
(uintptr_t) &_nocache_ram_end
|
||||
- (uintptr_t) &_nocache_ram_start);
|
||||
z_early_memset(&_nocache_ram_start, 0,
|
||||
(uintptr_t)&_nocache_ram_end - (uintptr_t)&_nocache_ram_start);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -33,8 +33,8 @@ void z_data_copy(void)
|
||||
#endif /* CONFIG_ARCH_HAS_RAMFUNC_SUPPORT */
|
||||
#ifdef CONFIG_ARCH_HAS_NOCACHE_MEMORY_SUPPORT
|
||||
#if CONFIG_NOCACHE_MEMORY
|
||||
z_early_memcpy(&_nocache_ram_start, &_nocache_load_start,
|
||||
(uintptr_t) &_nocache_ram_size);
|
||||
z_early_memcpy(&_nocache_load_ram_start, &_nocache_load_rom_start,
|
||||
(uintptr_t) &_nocache_load_ram_size);
|
||||
#endif /* CONFIG_NOCACHE_MEMORY */
|
||||
#endif /* CONFIG_ARCH_HAS_NOCACHE_MEMORY_SUPPORT */
|
||||
#if DT_NODE_HAS_STATUS_OKAY(DT_CHOSEN(zephyr_ccm))
|
||||
|
||||
@@ -15,63 +15,82 @@ extern "C" {
|
||||
|
||||
static inline int isupper(int a)
|
||||
{
|
||||
return (int)(((unsigned)(a)-(unsigned)'A') < 26U);
|
||||
return (('A' <= a) && (a <= 'Z'));
|
||||
}
|
||||
|
||||
static inline int isalpha(int c)
|
||||
{
|
||||
return (int)((((unsigned)c|32u)-(unsigned)'a') < 26U);
|
||||
/* force to lowercase */
|
||||
c |= 32;
|
||||
|
||||
return (('a' <= c) && (c <= 'z'));
|
||||
}
|
||||
|
||||
static inline int isblank(int c)
|
||||
{
|
||||
return ((c == ' ') || (c == '\t'));
|
||||
}
|
||||
|
||||
static inline int isspace(int c)
|
||||
{
|
||||
return (int)(c == (int)' ' || ((unsigned)c-(unsigned)'\t') < 5U);
|
||||
return ((c == ' ') || (('\t' <= c) && (c <= '\r')));
|
||||
}
|
||||
|
||||
static inline int isgraph(int c)
|
||||
{
|
||||
return (int)((((unsigned)c) > ' ') &&
|
||||
(((unsigned)c) <= (unsigned)'~'));
|
||||
return ((' ' < c) && (c <= '~'));
|
||||
}
|
||||
|
||||
static inline int isprint(int c)
|
||||
{
|
||||
return (int)((((unsigned)c) >= ' ') &&
|
||||
(((unsigned)c) <= (unsigned)'~'));
|
||||
return ((' ' <= c) && (c <= '~'));
|
||||
}
|
||||
|
||||
static inline int isdigit(int a)
|
||||
{
|
||||
return (int)(((unsigned)(a)-(unsigned)'0') < 10U);
|
||||
return (('0' <= a) && (a <= '9'));
|
||||
}
|
||||
|
||||
static inline int islower(int c)
|
||||
{
|
||||
return (('a' <= c) && (c <= 'z'));
|
||||
}
|
||||
|
||||
static inline int isxdigit(int a)
|
||||
{
|
||||
unsigned int ua = (unsigned int)a;
|
||||
if (isdigit(a) != 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return (int)(((ua - (unsigned)'0') < 10U) ||
|
||||
((ua | 32U) - (unsigned)'a' < 6U));
|
||||
/* force to lowercase */
|
||||
a |= 32;
|
||||
|
||||
return (('a' <= a) && (a <= 'f'));
|
||||
}
|
||||
|
||||
static inline int tolower(int chr)
|
||||
{
|
||||
return (chr >= (int)'A' && chr <= (int)'Z') ? (chr + 32) : (chr);
|
||||
return (chr >= 'A' && chr <= 'Z') ? (chr + 32) : (chr);
|
||||
}
|
||||
|
||||
static inline int toupper(int chr)
|
||||
{
|
||||
return (int)((chr >= (int)'a' && chr <=
|
||||
(int)'z') ? (chr - 32) : (chr));
|
||||
return ((chr >= 'a' && chr <= 'z') ? (chr - 32) : (chr));
|
||||
}
|
||||
|
||||
static inline int isalnum(int chr)
|
||||
{
|
||||
return (int)(isalpha(chr) || isdigit(chr));
|
||||
return (isalpha(chr) || isdigit(chr));
|
||||
}
|
||||
|
||||
static inline int ispunct(int c)
|
||||
{
|
||||
return (isgraph(c) && !isalnum(c));
|
||||
}
|
||||
|
||||
static inline int iscntrl(int c)
|
||||
{
|
||||
return (int)((((unsigned int)c) <= 31U) || (((unsigned int)c) == 127U));
|
||||
return ((((unsigned int)c) <= 31U) || (((unsigned int)c) == 127U));
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -9,6 +9,11 @@
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Guido van Rossum.
|
||||
*
|
||||
* Copyright (c) 2011 The FreeBSD Foundation
|
||||
* All rights reserved.
|
||||
* Portions of this software were developed by David Chisnall
|
||||
* under sponsorship from the FreeBSD Foundation.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
@@ -48,26 +53,121 @@
|
||||
|
||||
#define EOS '\0'
|
||||
|
||||
#ifndef FNM_NORES
|
||||
#define FNM_NORES 3
|
||||
#endif
|
||||
|
||||
#ifndef FNM_LEADING_DIR
|
||||
#define FNM_LEADING_DIR 0x08
|
||||
#endif
|
||||
|
||||
#ifndef FNM_CASEFOLD
|
||||
#define FNM_CASEFOLD 0x10
|
||||
#endif
|
||||
|
||||
#define FOLDCASE(ch, flags) foldcase((unsigned char)(ch), (flags))
|
||||
|
||||
#define RANGE_ERROR (-1)
|
||||
#define RANGE_NOMATCH 1
|
||||
#define RANGE_MATCH 0
|
||||
|
||||
/* POSIX character class matching was missing from the BSD version. This was added in 2025 */
|
||||
static int rangematch_cc(const char **pattern, int ch)
|
||||
{
|
||||
typedef unsigned long long ull;
|
||||
|
||||
/*
|
||||
* [:alnum:] et al are 9 characters. [:xdigits:] is 10.
|
||||
* If we first check for the leading "[:", then we have at most 8 remaining characters to
|
||||
* compare. Rather than using string comparison, encode the 8 characters into an integer and
|
||||
* compare to a precomputed constants. This likely only works for the "C" locale.
|
||||
*/
|
||||
#define FNM_CC5(a, b, c, d, e) \
|
||||
(((ull)(a) << 48) | ((ull)(b) << 40) | ((ull)(c) << 32) | ((ull)(d) << 24) | \
|
||||
((ull)(e) << 16) | ((ull)':' << 8) | ((ull)']' << 0))
|
||||
#define FNM_CC6(a, b, c, d, e, f) \
|
||||
(((ull)(a) << 56) | ((ull)(b) << 48) | ((ull)(c) << 40) | ((ull)(d) << 32) | \
|
||||
((ull)(e) << 24) | ((ull)(f) << 16) | ((ull)':' << 8) | ((ull)']' << 0))
|
||||
|
||||
ull key;
|
||||
int ret;
|
||||
const char *p = *pattern;
|
||||
|
||||
/* check the leading "[:" */
|
||||
if ((p[0] != '[') || (p[1] != ':')) {
|
||||
return RANGE_ERROR;
|
||||
}
|
||||
|
||||
/* encode the remaining characters into a 64-bit integer */
|
||||
for (p += 2, key = 0; *p != EOS; ++p) {
|
||||
if (*(p - 1) == ']') {
|
||||
break;
|
||||
}
|
||||
|
||||
key <<= 8;
|
||||
key |= (unsigned char)(*p);
|
||||
}
|
||||
|
||||
switch (key) {
|
||||
case FNM_CC5('a', 'l', 'n', 'u', 'm'):
|
||||
ret = !isalnum(ch);
|
||||
break;
|
||||
case FNM_CC5('a', 'l', 'p', 'h', 'a'):
|
||||
ret = !isalpha(ch);
|
||||
break;
|
||||
case FNM_CC5('b', 'l', 'a', 'n', 'k'):
|
||||
ret = !isblank(ch);
|
||||
break;
|
||||
case FNM_CC5('c', 'n', 't', 'r', 'l'):
|
||||
ret = !iscntrl(ch);
|
||||
break;
|
||||
case FNM_CC5('d', 'i', 'g', 'i', 't'):
|
||||
ret = !isdigit(ch);
|
||||
break;
|
||||
case FNM_CC5('g', 'r', 'a', 'p', 'h'):
|
||||
ret = !isgraph(ch);
|
||||
break;
|
||||
case FNM_CC5('l', 'o', 'w', 'e', 'r'):
|
||||
ret = !islower(ch);
|
||||
break;
|
||||
case FNM_CC5('p', 'r', 'i', 'n', 't'):
|
||||
ret = !isprint(ch);
|
||||
break;
|
||||
case FNM_CC5('p', 'u', 'n', 'c', 't'):
|
||||
ret = !ispunct(ch);
|
||||
break;
|
||||
case FNM_CC5('s', 'p', 'a', 'c', 'e'):
|
||||
ret = !isspace(ch);
|
||||
break;
|
||||
case FNM_CC5('u', 'p', 'p', 'e', 'r'):
|
||||
ret = !isupper(ch);
|
||||
break;
|
||||
case FNM_CC6('x', 'd', 'i', 'g', 'i', 't'):
|
||||
ret = !isxdigit(ch);
|
||||
break;
|
||||
default:
|
||||
return RANGE_ERROR;
|
||||
}
|
||||
|
||||
*pattern = p;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int foldcase(int ch, int flags)
|
||||
{
|
||||
|
||||
if ((flags & FNM_CASEFOLD) != 0 && isupper(ch)) {
|
||||
if (((flags & FNM_CASEFOLD) != 0) && isupper(ch)) {
|
||||
return tolower(ch);
|
||||
}
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
#define FOLDCASE(ch, flags) foldcase((unsigned char)(ch), (flags))
|
||||
|
||||
static const char *rangematch(const char *pattern, int test, int flags)
|
||||
static int rangematch(const char **pattern, char test, int flags)
|
||||
{
|
||||
bool negate, ok, need;
|
||||
char c, c2;
|
||||
|
||||
if (pattern == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
int negate, ok;
|
||||
const char *origpat;
|
||||
const char *pat = *pattern;
|
||||
|
||||
/*
|
||||
* A bracket expression starting with an unquoted circumflex
|
||||
@@ -76,90 +176,113 @@ static const char *rangematch(const char *pattern, int test, int flags)
|
||||
* consistency with the regular expression syntax.
|
||||
* J.T. Conklin (conklin@ngai.kaleida.com)
|
||||
*/
|
||||
negate = *pattern == '!' || *pattern == '^';
|
||||
negate = (*pat == '!' || *pat == '^');
|
||||
if (negate) {
|
||||
++pattern;
|
||||
++pat;
|
||||
}
|
||||
|
||||
for (need = true, ok = false, c = FOLDCASE(*pattern++, flags); c != ']' || need;
|
||||
c = FOLDCASE(*pattern++, flags)) {
|
||||
need = false;
|
||||
test = FOLDCASE(test, flags);
|
||||
|
||||
if (c == '/' && (flags & FNM_PATHNAME)) {
|
||||
return (void *)-1;
|
||||
}
|
||||
|
||||
if (c == '\\' && !(flags & FNM_NOESCAPE)) {
|
||||
if (*pattern != ']' && *pattern != EOS) {
|
||||
c = FOLDCASE(*pattern++, flags);
|
||||
/*
|
||||
* A right bracket shall lose its special meaning and represent
|
||||
* itself in a bracket expression if it occurs first in the list.
|
||||
* -- POSIX.2 2.8.3.2
|
||||
*/
|
||||
ok = 0;
|
||||
origpat = pat;
|
||||
for (;;) {
|
||||
if (*pat == ']' && pat > origpat) {
|
||||
pat++;
|
||||
break;
|
||||
} else if (*pat == '\0') {
|
||||
return RANGE_ERROR;
|
||||
} else if (*pat == '/' && (flags & FNM_PATHNAME)) {
|
||||
return RANGE_NOMATCH;
|
||||
} else if (*pat == '\\' && !(flags & FNM_NOESCAPE)) {
|
||||
pat++;
|
||||
} else {
|
||||
switch (rangematch_cc(&pat, test)) {
|
||||
case RANGE_ERROR:
|
||||
/* not a character class, proceed below */
|
||||
break;
|
||||
case RANGE_MATCH:
|
||||
/* a valid character class that was matched */
|
||||
ok = 1;
|
||||
continue;
|
||||
case RANGE_NOMATCH:
|
||||
/* a valid character class that was not matched */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (c == EOS) {
|
||||
return NULL;
|
||||
}
|
||||
c = FOLDCASE(*pat++, flags);
|
||||
|
||||
if (*pattern == '-') {
|
||||
c2 = FOLDCASE(*(pattern + 1), flags);
|
||||
if (c2 != EOS && c2 != ']') {
|
||||
pattern += 2;
|
||||
if (c2 == '\\' && !(flags & FNM_NOESCAPE)) {
|
||||
c2 = FOLDCASE(*pattern++, flags);
|
||||
if (*pat == '-' && *(pat + 1) != EOS && *(pat + 1) != ']') {
|
||||
if (*++pat == '\\' && !(flags & FNM_NOESCAPE)) {
|
||||
if (*pat != EOS) {
|
||||
pat++;
|
||||
}
|
||||
}
|
||||
c2 = FOLDCASE(*pat, flags);
|
||||
pat++;
|
||||
if (c2 == EOS) {
|
||||
return RANGE_ERROR;
|
||||
}
|
||||
|
||||
if (c2 == EOS) {
|
||||
return NULL;
|
||||
}
|
||||
if (flags & FNM_CASEFOLD) {
|
||||
c2 = tolower((int)c2);
|
||||
}
|
||||
|
||||
if (c <= test && test <= c2) {
|
||||
ok = true;
|
||||
}
|
||||
if (c <= test && test <= c2) {
|
||||
ok = 1;
|
||||
}
|
||||
} else if (c == test) {
|
||||
ok = true;
|
||||
ok = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ok == negate ? NULL : pattern;
|
||||
if (ok != negate) {
|
||||
*pattern = pat;
|
||||
return RANGE_MATCH;
|
||||
}
|
||||
|
||||
return RANGE_NOMATCH;
|
||||
}
|
||||
|
||||
static int fnmatchx(const char *pattern, const char *string, int flags, size_t recursion)
|
||||
static int fnmatchx(const char *pattern, const char *string, const char *stringstart, int flags,
|
||||
size_t recursion)
|
||||
{
|
||||
const char *stringstart, *r;
|
||||
char c, test;
|
||||
|
||||
if (pattern == NULL || string == NULL) {
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
char c;
|
||||
char pc, sc;
|
||||
|
||||
if (recursion-- == 0) {
|
||||
return FNM_NORES;
|
||||
}
|
||||
|
||||
for (stringstart = string;;) {
|
||||
c = FOLDCASE(*pattern++, flags);
|
||||
switch (c) {
|
||||
while (true) {
|
||||
pc = FOLDCASE(*pattern++, flags);
|
||||
sc = FOLDCASE(*string, flags);
|
||||
switch (pc) {
|
||||
case EOS:
|
||||
if ((flags & FNM_LEADING_DIR) && *string == '/') {
|
||||
if (((flags & FNM_LEADING_DIR) != 0) && (sc == '/')) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return *string == EOS ? 0 : FNM_NOMATCH;
|
||||
if (sc == EOS) {
|
||||
return 0;
|
||||
}
|
||||
return FNM_NOMATCH;
|
||||
case '?':
|
||||
if (*string == EOS) {
|
||||
if (sc == EOS) {
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
|
||||
if (*string == '/' && (flags & FNM_PATHNAME)) {
|
||||
if ((sc == '/') && ((flags & FNM_PATHNAME) != 0)) {
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
|
||||
if (*string == '.' && (flags & FNM_PERIOD) &&
|
||||
(string == stringstart ||
|
||||
((flags & FNM_PATHNAME) && *(string - 1) == '/'))) {
|
||||
if ((sc == '.') && ((flags & FNM_PERIOD) != 0) &&
|
||||
((string == stringstart) ||
|
||||
(((flags & FNM_PATHNAME) != 0) && (*(string - 1) == '/')))) {
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
|
||||
++string;
|
||||
break;
|
||||
case '*':
|
||||
@@ -169,107 +292,85 @@ static int fnmatchx(const char *pattern, const char *string, int flags, size_t r
|
||||
c = FOLDCASE(*++pattern, flags);
|
||||
}
|
||||
|
||||
if (*string == '.' && (flags & FNM_PERIOD) &&
|
||||
(string == stringstart ||
|
||||
((flags & FNM_PATHNAME) && *(string - 1) == '/'))) {
|
||||
if ((sc == '.') && ((flags & FNM_PERIOD) != 0) &&
|
||||
((string == stringstart) ||
|
||||
(((flags & FNM_PATHNAME) != 0) && (*(string - 1) == '/')))) {
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
|
||||
/* Optimize for pattern with * at end or before /. */
|
||||
if (c == EOS) {
|
||||
if (flags & FNM_PATHNAME) {
|
||||
return (flags & FNM_LEADING_DIR) ||
|
||||
strchr(string, '/') == NULL
|
||||
? 0
|
||||
: FNM_NOMATCH;
|
||||
} else {
|
||||
if ((flags & FNM_PATHNAME) == 0) {
|
||||
return 0;
|
||||
}
|
||||
} else if (c == '/' && flags & FNM_PATHNAME) {
|
||||
|
||||
if (((flags & FNM_LEADING_DIR) != 0) ||
|
||||
(strchr(string, '/') == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return FNM_NOMATCH;
|
||||
} else if ((c == '/') && ((flags & FNM_PATHNAME) != 0)) {
|
||||
string = strchr(string, '/');
|
||||
if (string == NULL) {
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* General case, use recursion. */
|
||||
do {
|
||||
test = FOLDCASE(*string, flags);
|
||||
if (test == EOS) {
|
||||
while (sc != EOS) {
|
||||
if (fnmatchx(pattern, string, stringstart, flags, recursion) == 0) {
|
||||
return 0;
|
||||
}
|
||||
sc = FOLDCASE(*string, flags);
|
||||
if ((sc == '/') && ((flags & FNM_PATHNAME) != 0)) {
|
||||
break;
|
||||
}
|
||||
|
||||
int e = fnmatchx(pattern, string, flags & ~FNM_PERIOD, recursion);
|
||||
|
||||
if (e != FNM_NOMATCH) {
|
||||
return e;
|
||||
}
|
||||
|
||||
if (test == '/' && flags & FNM_PATHNAME) {
|
||||
break;
|
||||
}
|
||||
|
||||
++string;
|
||||
} while (true);
|
||||
|
||||
}
|
||||
return FNM_NOMATCH;
|
||||
case '[':
|
||||
if (*string == EOS) {
|
||||
if (sc == EOS) {
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
if ((sc == '/') && ((flags & FNM_PATHNAME) != 0)) {
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
if ((sc == '.') && ((flags & FNM_PERIOD) != 0) &&
|
||||
((string == stringstart) ||
|
||||
(((flags & FNM_PATHNAME) != 0) && (*(string - 1) == '/')))) {
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
|
||||
if (*string == '/' && flags & FNM_PATHNAME) {
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
|
||||
if (*string == '.' && (flags & FNM_PERIOD) &&
|
||||
(string == stringstart ||
|
||||
((flags & FNM_PATHNAME) && *(string - 1) == '/'))) {
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
|
||||
r = rangematch(pattern, FOLDCASE(*string, flags), flags);
|
||||
|
||||
if (r == NULL) {
|
||||
if (FOLDCASE('[', flags) != FOLDCASE(*string, flags)) {
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
++string;
|
||||
switch (rangematch(&pattern, sc, flags)) {
|
||||
case RANGE_ERROR:
|
||||
goto norm;
|
||||
case RANGE_MATCH:
|
||||
break;
|
||||
case RANGE_NOMATCH:
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
|
||||
if (r == (void *)-1) {
|
||||
if (*string != '[') {
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
} else {
|
||||
pattern = r;
|
||||
}
|
||||
|
||||
++string;
|
||||
break;
|
||||
case '\\':
|
||||
if (!(flags & FNM_NOESCAPE)) {
|
||||
c = FOLDCASE(*pattern++, flags);
|
||||
if (c == EOS) {
|
||||
c = '\0';
|
||||
--pattern;
|
||||
}
|
||||
if ((flags & FNM_NOESCAPE) == 0) {
|
||||
pc = FOLDCASE(*pattern++, flags);
|
||||
}
|
||||
__fallthrough;
|
||||
default:
|
||||
if (c != FOLDCASE(*string++, flags)) {
|
||||
norm:
|
||||
if (pc != sc) {
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
|
||||
++string;
|
||||
break;
|
||||
}
|
||||
}
|
||||
CODE_UNREACHABLE;
|
||||
}
|
||||
|
||||
int fnmatch(const char *pattern, const char *string, int flags)
|
||||
{
|
||||
return fnmatchx(pattern, string, flags, 64);
|
||||
return fnmatchx(pattern, string, string, flags, 64);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ zephyr_include_directories(${LVGL_DIR}/src/)
|
||||
zephyr_include_directories(include)
|
||||
|
||||
zephyr_compile_definitions(LV_CONF_INCLUDE_SIMPLE=1)
|
||||
zephyr_library_compile_definitions(_POSIX_C_SOURCE=200809L)
|
||||
zephyr_compile_definitions(LV_CONF_PATH="${CMAKE_CURRENT_SOURCE_DIR}/include/lv_conf.h")
|
||||
|
||||
zephyr_library_sources(
|
||||
@@ -309,6 +310,8 @@ zephyr_library_sources(
|
||||
${LVGL_DIR}/src/stdlib/builtin/lv_sprintf_builtin.c
|
||||
${LVGL_DIR}/src/stdlib/builtin/lv_string_builtin.c
|
||||
${LVGL_DIR}/src/stdlib/builtin/lv_tlsf.c
|
||||
${LVGL_DIR}/src/stdlib/clib/lv_string_clib.c
|
||||
${LVGL_DIR}/src/stdlib/clib/lv_sprintf_clib.c
|
||||
|
||||
${LVGL_DIR}/src/stdlib/clib/lv_mem_core_clib.c
|
||||
${LVGL_DIR}/src/stdlib/clib/lv_sprintf_clib.c
|
||||
|
||||
@@ -12,7 +12,9 @@
|
||||
|
||||
/* Memory manager settings */
|
||||
|
||||
#define LV_USE_STDLIB_MALLOC LV_STDLIB_CUSTOM
|
||||
#define LV_USE_STDLIB_MALLOC LV_STDLIB_CUSTOM
|
||||
#define LV_USE_STDLIB_STRING LV_STDLIB_CLIB
|
||||
#define LV_USE_STDLIB_SPRINTF LV_STDLIB_CLIB
|
||||
|
||||
#if defined(CONFIG_LV_Z_MEM_POOL_HEAP_LIB_C)
|
||||
#define LV_STDLIB_INCLUDE "stdlib.h"
|
||||
@@ -26,9 +28,6 @@
|
||||
#define lv_free_core lvgl_free
|
||||
#endif
|
||||
|
||||
/* Misc settings */
|
||||
#define lv_snprintf snprintf
|
||||
#define lv_vsnprintf vsnprintf
|
||||
#define LV_ASSERT_HANDLER __ASSERT_NO_MSG(false);
|
||||
#define LV_ASSERT_HANDLER_INCLUDE "zephyr/sys/__assert.h"
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ zephyr_interface_library_named(mbedTLS)
|
||||
# if address sanitizer is enabled, as such switch default optimization level
|
||||
# to speed
|
||||
set_property(SOURCE ${ZEPHYR_CURRENT_MODULE_DIR}/mbedtls/library/bignum.c APPEND PROPERTY COMPILE_OPTIONS
|
||||
"${OPTIMIZE_FOR_SPEED_FLAG}")
|
||||
"${COMPILER_OPTIMIZE_FOR_SPEED_FLAG}")
|
||||
endif ()
|
||||
|
||||
zephyr_library_link_libraries(mbedTLS)
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
CONFIG_LV_COLOR_DEPTH_32=y
|
||||
CONFIG_LV_Z_MEM_POOL_SIZE=75264
|
||||
CONFIG_LV_Z_MEM_POOL_SIZE=81920
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
CONFIG_MAIN_STACK_SIZE=4096
|
||||
CONFIG_MAIN_STACK_SIZE=6144
|
||||
CONFIG_LOG=y
|
||||
CONFIG_SHELL=y
|
||||
|
||||
|
||||
@@ -518,7 +518,11 @@ def try_making_symlink(source: str, link: str):
|
||||
source (str): The path to the source file.
|
||||
link (str): The path where the symbolic link should be created.
|
||||
"""
|
||||
if os.path.exists(link):
|
||||
symlink_error = None
|
||||
|
||||
try:
|
||||
os.symlink(source, link)
|
||||
except FileExistsError:
|
||||
if os.path.islink(link):
|
||||
if os.readlink(link) == source:
|
||||
# Link is already set up
|
||||
@@ -529,19 +533,24 @@ def try_making_symlink(source: str, link: str):
|
||||
# File contents are the same
|
||||
return
|
||||
|
||||
# link exists, but points to a different file, remove the link. We'll
|
||||
# try to create a new one below
|
||||
os.remove(link)
|
||||
|
||||
# Create the symlink
|
||||
try:
|
||||
os.symlink(source, link)
|
||||
# link exists, but points to a different file. We'll create a new link
|
||||
# and replace it atomically with the old one
|
||||
temp_filename = f"{link}.{os.urandom(8).hex()}"
|
||||
try:
|
||||
os.symlink(source, temp_filename)
|
||||
os.replace(temp_filename, link)
|
||||
except OSError as e:
|
||||
symlink_error = e
|
||||
except OSError as e:
|
||||
logger.error(
|
||||
"Error creating symlink: %s, attempting to copy.", str(e)
|
||||
)
|
||||
shutil.copy(source, link)
|
||||
symlink_error = e
|
||||
|
||||
if symlink_error:
|
||||
logger.error(
|
||||
"Error creating symlink: %s, attempting to copy.", str(symlink_error)
|
||||
)
|
||||
temp_filename = f"{link}.{os.urandom(8).hex()}"
|
||||
shutil.copy(source, temp_filename)
|
||||
os.replace(temp_filename, link)
|
||||
|
||||
def choose_gcov_tool(options, is_system_gcov):
|
||||
gcov_tool = None
|
||||
|
||||
@@ -10,6 +10,9 @@ config NUM_IRQS
|
||||
|
||||
if BT
|
||||
|
||||
config SYSTEM_WORKQUEUE_STACK_SIZE
|
||||
default 1152
|
||||
|
||||
config BT_AUTO_PHY_UPDATE
|
||||
default n
|
||||
|
||||
|
||||
@@ -221,10 +221,10 @@ add_subdirectory_ifdef(
|
||||
|
||||
zephyr_library_compile_options_ifdef(
|
||||
CONFIG_BT_CTLR_OPTIMIZE_FOR_SIZE
|
||||
${OPTIMIZE_FOR_SIZE_FLAG}
|
||||
${COMPILER_OPTIMIZE_FOR_SIZE_FLAG}
|
||||
)
|
||||
|
||||
zephyr_library_compile_options_ifdef(
|
||||
CONFIG_BT_CTLR_OPTIMIZE_FOR_SPEED
|
||||
${OPTIMIZE_FOR_SPEED_FLAG}
|
||||
${COMPILER_OPTIMIZE_FOR_SPEED_FLAG}
|
||||
)
|
||||
|
||||
@@ -122,5 +122,5 @@ zephyr_include_directories(
|
||||
|
||||
zephyr_library_compile_options_ifdef(
|
||||
CONFIG_BT_CTLR_OPTIMIZE_FOR_SPEED
|
||||
${OPTIMIZE_FOR_SPEED_FLAG}
|
||||
${COMPILER_OPTIMIZE_FOR_SPEED_FLAG}
|
||||
)
|
||||
|
||||
@@ -55,5 +55,5 @@ zephyr_library_include_directories(
|
||||
|
||||
zephyr_library_compile_options_ifdef(
|
||||
CONFIG_BT_CTLR_OPTIMIZE_FOR_SPEED
|
||||
${OPTIMIZE_FOR_SPEED_FLAG}
|
||||
${COMPILER_OPTIMIZE_FOR_SPEED_FLAG}
|
||||
)
|
||||
|
||||
@@ -1529,7 +1529,7 @@ void bt_le_adv_resume(void)
|
||||
int err;
|
||||
|
||||
if (!adv) {
|
||||
LOG_ERR("No valid legacy adv to resume");
|
||||
LOG_DBG("No valid legacy adv to resume");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -598,12 +598,11 @@ static int ext2_stat(struct fs_mount_t *mountp, const char *path, struct fs_dire
|
||||
}
|
||||
|
||||
uint32_t offset = args.offset;
|
||||
struct ext2_inode *parent = args.parent;
|
||||
struct ext2_file dir = {.f_inode = parent, .f_off = offset};
|
||||
struct ext2_file dir = {.f_inode = args.parent ? args.parent : args.inode, .f_off = offset};
|
||||
|
||||
rc = ext2_get_direntry(&dir, entry);
|
||||
|
||||
ext2_inode_drop(parent);
|
||||
ext2_inode_drop(args.parent);
|
||||
ext2_inode_drop(args.inode);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -50,16 +50,22 @@ static sys_slist_t offload_handlers = SYS_SLIST_STATIC_INIT(&offload_handlers);
|
||||
|
||||
#define PKT_WAIT_TIME K_SECONDS(1)
|
||||
|
||||
int net_icmp_init_ctx(struct net_icmp_ctx *ctx, uint8_t type, uint8_t code,
|
||||
net_icmp_handler_t handler)
|
||||
int net_icmp_init_ctx(struct net_icmp_ctx *ctx, uint8_t family, uint8_t type,
|
||||
uint8_t code, net_icmp_handler_t handler)
|
||||
{
|
||||
if (ctx == NULL || handler == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (family != AF_INET && family != AF_INET6) {
|
||||
NET_ERR("Wrong address family");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(ctx, 0, sizeof(struct net_icmp_ctx));
|
||||
|
||||
ctx->handler = handler;
|
||||
ctx->family = family;
|
||||
ctx->type = type;
|
||||
ctx->code = code;
|
||||
|
||||
@@ -511,6 +517,10 @@ static int icmp_call_handlers(struct net_pkt *pkt,
|
||||
k_mutex_lock(&lock, K_FOREVER);
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER(&handlers, ctx, node) {
|
||||
if (ip_hdr->family != ctx->family) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ctx->type == icmp_hdr->type &&
|
||||
(ctx->code == icmp_hdr->code || ctx->code == 0U)) {
|
||||
/* Do not use a handler that is expecting data from different
|
||||
|
||||
@@ -766,14 +766,15 @@ void net_icmpv4_init(void)
|
||||
static struct net_icmp_ctx ctx;
|
||||
int ret;
|
||||
|
||||
ret = net_icmp_init_ctx(&ctx, NET_ICMPV4_ECHO_REQUEST, 0, icmpv4_handle_echo_request);
|
||||
ret = net_icmp_init_ctx(&ctx, AF_INET, NET_ICMPV4_ECHO_REQUEST, 0,
|
||||
icmpv4_handle_echo_request);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot register %s handler (%d)", STRINGIFY(NET_ICMPV4_ECHO_REQUEST),
|
||||
ret);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_IPV4_PMTU)
|
||||
ret = net_icmp_init_ctx(&dst_unreach_ctx, NET_ICMPV4_DST_UNREACH, 0,
|
||||
ret = net_icmp_init_ctx(&dst_unreach_ctx, AF_INET, NET_ICMPV4_DST_UNREACH, 0,
|
||||
icmpv4_handle_dst_unreach);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot register %s handler (%d)", STRINGIFY(NET_ICMPV4_DST_UNREACH),
|
||||
|
||||
@@ -394,7 +394,8 @@ void net_icmpv6_init(void)
|
||||
static struct net_icmp_ctx ctx;
|
||||
int ret;
|
||||
|
||||
ret = net_icmp_init_ctx(&ctx, NET_ICMPV6_ECHO_REQUEST, 0, icmpv6_handle_echo_request);
|
||||
ret = net_icmp_init_ctx(&ctx, AF_INET6, NET_ICMPV6_ECHO_REQUEST, 0,
|
||||
icmpv6_handle_echo_request);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot register %s handler (%d)", STRINGIFY(NET_ICMPV6_ECHO_REQUEST),
|
||||
ret);
|
||||
|
||||
@@ -471,7 +471,7 @@ void net_ipv6_mld_init(void)
|
||||
static struct net_icmp_ctx ctx;
|
||||
int ret;
|
||||
|
||||
ret = net_icmp_init_ctx(&ctx, NET_ICMPV6_MLD_QUERY, 0, handle_mld_query);
|
||||
ret = net_icmp_init_ctx(&ctx, AF_INET6, NET_ICMPV6_MLD_QUERY, 0, handle_mld_query);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot register %s handler (%d)", STRINGIFY(NET_ICMPV6_MLD_QUERY),
|
||||
ret);
|
||||
|
||||
@@ -2869,13 +2869,13 @@ void net_ipv6_nbr_init(void)
|
||||
int ret;
|
||||
|
||||
#if defined(CONFIG_NET_IPV6_NBR_CACHE)
|
||||
ret = net_icmp_init_ctx(&ns_ctx, NET_ICMPV6_NS, 0, handle_ns_input);
|
||||
ret = net_icmp_init_ctx(&ns_ctx, AF_INET6, NET_ICMPV6_NS, 0, handle_ns_input);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot register %s handler (%d)", STRINGIFY(NET_ICMPV6_NS),
|
||||
ret);
|
||||
}
|
||||
|
||||
ret = net_icmp_init_ctx(&na_ctx, NET_ICMPV6_NA, 0, handle_na_input);
|
||||
ret = net_icmp_init_ctx(&na_ctx, AF_INET6, NET_ICMPV6_NA, 0, handle_na_input);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot register %s handler (%d)", STRINGIFY(NET_ICMPV6_NA),
|
||||
ret);
|
||||
@@ -2884,7 +2884,7 @@ void net_ipv6_nbr_init(void)
|
||||
k_work_init_delayable(&ipv6_ns_reply_timer, ipv6_ns_reply_timeout);
|
||||
#endif
|
||||
#if defined(CONFIG_NET_IPV6_ND)
|
||||
ret = net_icmp_init_ctx(&ra_ctx, NET_ICMPV6_RA, 0, handle_ra_input);
|
||||
ret = net_icmp_init_ctx(&ra_ctx, AF_INET6, NET_ICMPV6_RA, 0, handle_ra_input);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot register %s handler (%d)", STRINGIFY(NET_ICMPV6_RA),
|
||||
ret);
|
||||
@@ -2895,7 +2895,7 @@ void net_ipv6_nbr_init(void)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6_PMTU)
|
||||
ret = net_icmp_init_ctx(&ptb_ctx, NET_ICMPV6_PACKET_TOO_BIG, 0, handle_ptb_input);
|
||||
ret = net_icmp_init_ctx(&ptb_ctx, AF_INET6, NET_ICMPV6_PACKET_TOO_BIG, 0, handle_ptb_input);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot register %s handler (%d)", STRINGIFY(NET_ICMPV6_PACKET_TOO_BIG),
|
||||
ret);
|
||||
|
||||
@@ -634,6 +634,13 @@ int net_context_get(sa_family_t family, enum net_sock_type type, uint16_t proto,
|
||||
k_sem_give(&contexts_lock);
|
||||
|
||||
if (ret < 0) {
|
||||
if (ret == -EADDRINUSE &&
|
||||
!net_if_is_ip_offloaded(net_if_get_default()) &&
|
||||
proto == IPPROTO_TCP) {
|
||||
/* Free the TCP context that we allocated earlier */
|
||||
net_tcp_put(&contexts[i]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -2354,6 +2354,19 @@ int net_pkt_set_data(struct net_pkt *pkt,
|
||||
return net_pkt_write(pkt, access->data, access->size);
|
||||
}
|
||||
|
||||
void net_pkt_tx_init(struct net_pkt *pkt)
|
||||
{
|
||||
memset(pkt, 0, sizeof(struct net_pkt));
|
||||
|
||||
pkt->atomic_ref = ATOMIC_INIT(1);
|
||||
pkt->slab = &tx_pkts;
|
||||
|
||||
net_pkt_set_ipv6_next_hdr(pkt, 255);
|
||||
net_pkt_set_priority(pkt, TX_DEFAULT_PRIORITY);
|
||||
net_pkt_set_vlan_tag(pkt, NET_VLAN_TAG_UNSPEC);
|
||||
net_pkt_cursor_init(pkt);
|
||||
}
|
||||
|
||||
void net_pkt_init(void)
|
||||
{
|
||||
#if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
|
||||
|
||||
@@ -414,3 +414,10 @@ static inline void net_pkt_print_buffer_info(struct net_pkt *pkt, const char *st
|
||||
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize externally allocated TX packet.
|
||||
*
|
||||
* @param pkt The network packet to initialize.
|
||||
*/
|
||||
void net_pkt_tx_init(struct net_pkt *pkt);
|
||||
|
||||
@@ -794,10 +794,15 @@ static void tcp_conn_release(struct k_work *work)
|
||||
tcp_send_queue_flush(conn);
|
||||
|
||||
(void)k_work_cancel_delayable(&conn->send_data_timer);
|
||||
tcp_pkt_unref(conn->send_data);
|
||||
if (conn->send_data.frags != NULL) {
|
||||
net_pkt_frag_unref(conn->send_data.frags);
|
||||
}
|
||||
|
||||
if (CONFIG_NET_TCP_RECV_QUEUE_TIMEOUT) {
|
||||
tcp_pkt_unref(conn->queue_recv_data);
|
||||
if (conn->queue_recv_data != NULL) {
|
||||
net_buf_unref(conn->queue_recv_data);
|
||||
conn->queue_recv_data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
(void)k_work_cancel_delayable(&conn->timewait_timer);
|
||||
@@ -1136,8 +1141,7 @@ static size_t tcp_check_pending_data(struct tcp *conn, struct net_pkt *pkt,
|
||||
{
|
||||
size_t pending_len = 0;
|
||||
|
||||
if (CONFIG_NET_TCP_RECV_QUEUE_TIMEOUT &&
|
||||
!net_pkt_is_empty(conn->queue_recv_data)) {
|
||||
if (CONFIG_NET_TCP_RECV_QUEUE_TIMEOUT && conn->queue_recv_data != NULL) {
|
||||
/* Some potentential cases:
|
||||
* Note: MI = MAX_INT
|
||||
* Packet | Queued| End off | Gap size | Required handling
|
||||
@@ -1159,10 +1163,10 @@ static size_t tcp_check_pending_data(struct tcp *conn, struct net_pkt *pkt,
|
||||
int32_t gap_size;
|
||||
uint32_t end_offset;
|
||||
|
||||
pending_seq = tcp_get_seq(conn->queue_recv_data->buffer);
|
||||
pending_seq = tcp_get_seq(conn->queue_recv_data);
|
||||
end_offset = expected_seq - pending_seq;
|
||||
gap_size = (int32_t)(pending_seq - th_seq(th) - ((uint32_t)len));
|
||||
pending_len = net_pkt_get_len(conn->queue_recv_data);
|
||||
pending_len = net_buf_frags_len(conn->queue_recv_data);
|
||||
if (end_offset < pending_len) {
|
||||
if (end_offset) {
|
||||
net_pkt_remove_tail(pkt, end_offset);
|
||||
@@ -1173,15 +1177,15 @@ static size_t tcp_check_pending_data(struct tcp *conn, struct net_pkt *pkt,
|
||||
expected_seq, pending_len);
|
||||
|
||||
net_buf_frag_add(pkt->buffer,
|
||||
conn->queue_recv_data->buffer);
|
||||
conn->queue_recv_data->buffer = NULL;
|
||||
conn->queue_recv_data);
|
||||
conn->queue_recv_data = NULL;
|
||||
|
||||
k_work_cancel_delayable(&conn->recv_queue_timer);
|
||||
} else {
|
||||
/* Check if the queued data is just a section of the incoming data */
|
||||
if (gap_size <= 0) {
|
||||
net_buf_unref(conn->queue_recv_data->buffer);
|
||||
conn->queue_recv_data->buffer = NULL;
|
||||
net_buf_unref(conn->queue_recv_data);
|
||||
conn->queue_recv_data = NULL;
|
||||
|
||||
k_work_cancel_delayable(&conn->recv_queue_timer);
|
||||
}
|
||||
@@ -1684,7 +1688,7 @@ static int tcp_send_data(struct tcp *conn)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = tcp_pkt_peek(pkt, conn->send_data, conn->unacked_len, len);
|
||||
ret = tcp_pkt_peek(pkt, &conn->send_data, conn->unacked_len, len);
|
||||
if (ret < 0) {
|
||||
tcp_pkt_unref(pkt);
|
||||
ret = -ENOBUFS;
|
||||
@@ -1770,11 +1774,11 @@ static void tcp_cleanup_recv_queue(struct k_work *work)
|
||||
k_mutex_lock(&conn->lock, K_FOREVER);
|
||||
|
||||
NET_DBG("Cleanup recv queue conn %p len %zd seq %u", conn,
|
||||
net_pkt_get_len(conn->queue_recv_data),
|
||||
tcp_get_seq(conn->queue_recv_data->buffer));
|
||||
net_buf_frags_len(conn->queue_recv_data),
|
||||
tcp_get_seq(conn->queue_recv_data));
|
||||
|
||||
net_buf_unref(conn->queue_recv_data->buffer);
|
||||
conn->queue_recv_data->buffer = NULL;
|
||||
net_buf_unref(conn->queue_recv_data);
|
||||
conn->queue_recv_data = NULL;
|
||||
|
||||
k_mutex_unlock(&conn->lock);
|
||||
}
|
||||
@@ -2021,21 +2025,7 @@ static struct tcp *tcp_conn_alloc(void)
|
||||
}
|
||||
|
||||
memset(conn, 0, sizeof(*conn));
|
||||
|
||||
if (CONFIG_NET_TCP_RECV_QUEUE_TIMEOUT) {
|
||||
conn->queue_recv_data = tcp_rx_pkt_alloc(conn, 0);
|
||||
if (conn->queue_recv_data == NULL) {
|
||||
NET_ERR("Cannot allocate %s queue for conn %p", "recv",
|
||||
conn);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
conn->send_data = tcp_pkt_alloc(conn, 0);
|
||||
if (conn->send_data == NULL) {
|
||||
NET_ERR("Cannot allocate %s queue for conn %p", "send", conn);
|
||||
goto fail;
|
||||
}
|
||||
net_pkt_tx_init(&conn->send_data);
|
||||
|
||||
k_mutex_init(&conn->lock);
|
||||
k_fifo_init(&conn->recv_data);
|
||||
@@ -2087,15 +2077,6 @@ out:
|
||||
NET_DBG("conn: %p", conn);
|
||||
|
||||
return conn;
|
||||
|
||||
fail:
|
||||
if (CONFIG_NET_TCP_RECV_QUEUE_TIMEOUT && conn->queue_recv_data) {
|
||||
tcp_pkt_unref(conn->queue_recv_data);
|
||||
conn->queue_recv_data = NULL;
|
||||
}
|
||||
|
||||
k_mem_slab_free(&tcp_conns_slab, (void *)conn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int net_tcp_get(struct net_context *context)
|
||||
@@ -2545,7 +2526,7 @@ static void tcp_queue_recv_data(struct tcp *conn, struct net_pkt *pkt,
|
||||
NET_DBG("Queuing data: conn %p", conn);
|
||||
}
|
||||
|
||||
if (!net_pkt_is_empty(conn->queue_recv_data)) {
|
||||
if (conn->queue_recv_data != NULL) {
|
||||
/* Place the data to correct place in the list. If the data
|
||||
* would not be sequential, then drop this packet.
|
||||
*
|
||||
@@ -2575,9 +2556,9 @@ static void tcp_queue_recv_data(struct tcp *conn, struct net_pkt *pkt,
|
||||
uint32_t end_offset;
|
||||
size_t pending_len;
|
||||
|
||||
pending_seq = tcp_get_seq(conn->queue_recv_data->buffer);
|
||||
pending_seq = tcp_get_seq(conn->queue_recv_data);
|
||||
end_offset = seq - pending_seq;
|
||||
pending_len = net_pkt_get_len(conn->queue_recv_data);
|
||||
pending_len = net_buf_frags_len(conn->queue_recv_data);
|
||||
if (end_offset < pending_len) {
|
||||
if (end_offset < len) {
|
||||
if (end_offset) {
|
||||
@@ -2586,16 +2567,16 @@ static void tcp_queue_recv_data(struct tcp *conn, struct net_pkt *pkt,
|
||||
|
||||
/* Put new data before the pending data */
|
||||
net_buf_frag_add(pkt->buffer,
|
||||
conn->queue_recv_data->buffer);
|
||||
conn->queue_recv_data);
|
||||
NET_DBG("Adding at before queue, end_offset %i, pending_len %zu",
|
||||
end_offset, pending_len);
|
||||
conn->queue_recv_data->buffer = pkt->buffer;
|
||||
conn->queue_recv_data = pkt->buffer;
|
||||
inserted = true;
|
||||
}
|
||||
} else {
|
||||
struct net_buf *last;
|
||||
|
||||
last = net_buf_frag_last(conn->queue_recv_data->buffer);
|
||||
last = net_buf_frag_last(conn->queue_recv_data);
|
||||
pending_seq = tcp_get_seq(last);
|
||||
|
||||
start_offset = pending_seq - seq_start;
|
||||
@@ -2607,20 +2588,20 @@ static void tcp_queue_recv_data(struct tcp *conn, struct net_pkt *pkt,
|
||||
/* The queued data is irrelevant since the new packet overlaps the
|
||||
* new packet, take the new packet as contents
|
||||
*/
|
||||
net_buf_unref(conn->queue_recv_data->buffer);
|
||||
conn->queue_recv_data->buffer = pkt->buffer;
|
||||
net_buf_unref(conn->queue_recv_data);
|
||||
conn->queue_recv_data = pkt->buffer;
|
||||
inserted = true;
|
||||
} else {
|
||||
if (end_offset < len) {
|
||||
if (end_offset) {
|
||||
net_pkt_remove_tail(conn->queue_recv_data,
|
||||
end_offset);
|
||||
net_buf_remove_mem(conn->queue_recv_data,
|
||||
end_offset);
|
||||
}
|
||||
|
||||
/* Put new data after pending data */
|
||||
NET_DBG("Adding at end of queue, start %i, end %i, len %zu",
|
||||
start_offset, end_offset, len);
|
||||
net_buf_frag_add(conn->queue_recv_data->buffer,
|
||||
net_buf_frag_add(conn->queue_recv_data,
|
||||
pkt->buffer);
|
||||
inserted = true;
|
||||
}
|
||||
@@ -2629,18 +2610,18 @@ static void tcp_queue_recv_data(struct tcp *conn, struct net_pkt *pkt,
|
||||
|
||||
if (inserted) {
|
||||
NET_DBG("All pending data: conn %p", conn);
|
||||
if (check_seq_list(conn->queue_recv_data->buffer) == false) {
|
||||
if (check_seq_list(conn->queue_recv_data) == false) {
|
||||
NET_ERR("Incorrect order in out of order sequence for conn %p",
|
||||
conn);
|
||||
/* error in sequence list, drop it */
|
||||
net_buf_unref(conn->queue_recv_data->buffer);
|
||||
conn->queue_recv_data->buffer = NULL;
|
||||
net_buf_unref(conn->queue_recv_data);
|
||||
conn->queue_recv_data = NULL;
|
||||
}
|
||||
} else {
|
||||
NET_DBG("Cannot add new data to queue");
|
||||
}
|
||||
} else {
|
||||
net_pkt_append_buffer(conn->queue_recv_data, pkt->buffer);
|
||||
conn->queue_recv_data = pkt->buffer;
|
||||
inserted = true;
|
||||
}
|
||||
|
||||
@@ -2657,7 +2638,7 @@ static void tcp_queue_recv_data(struct tcp *conn, struct net_pkt *pkt,
|
||||
}
|
||||
|
||||
static enum net_verdict tcp_data_received(struct tcp *conn, struct net_pkt *pkt,
|
||||
size_t *len, bool psh)
|
||||
size_t *len, bool psh, bool fin)
|
||||
{
|
||||
enum net_verdict ret;
|
||||
|
||||
@@ -2670,6 +2651,13 @@ static enum net_verdict tcp_data_received(struct tcp *conn, struct net_pkt *pkt,
|
||||
net_stats_update_tcp_seg_recv(conn->iface);
|
||||
conn_ack(conn, *len);
|
||||
|
||||
/* In case FIN was received, don't send ACK just yet, FIN,ACK will be
|
||||
* sent instead.
|
||||
*/
|
||||
if (fin) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Delay ACK response in case of small window or missing PSH,
|
||||
* as described in RFC 813.
|
||||
*/
|
||||
@@ -2805,7 +2793,9 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt)
|
||||
/* send ACK for non-RST packet */
|
||||
if (FL(&fl, &, RST)) {
|
||||
net_stats_update_tcp_seg_rsterr(net_pkt_iface(pkt));
|
||||
} else if ((len > 0) || FL(&fl, &, FIN)) {
|
||||
} else if ((len > 0) || FL(&fl, &, FIN) ||
|
||||
/* Keep-alive probe */
|
||||
((len == 0) && FL(&fl, &, ACK))) {
|
||||
tcp_out(conn, ACK);
|
||||
}
|
||||
k_mutex_unlock(&conn->lock);
|
||||
@@ -3078,37 +3068,8 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt)
|
||||
}
|
||||
|
||||
break;
|
||||
case TCP_ESTABLISHED:
|
||||
/* full-close */
|
||||
if (FL(&fl, &, FIN, th_seq(th) == conn->ack)) {
|
||||
if (len) {
|
||||
verdict = tcp_data_get(conn, pkt, &len);
|
||||
if (verdict == NET_OK) {
|
||||
/* net_pkt owned by the recv fifo now */
|
||||
pkt = NULL;
|
||||
}
|
||||
} else {
|
||||
verdict = NET_OK;
|
||||
}
|
||||
|
||||
conn_ack(conn, + len + 1);
|
||||
keep_alive_timer_stop(conn);
|
||||
|
||||
if (net_tcp_seq_cmp(th_ack(th), conn->seq) > 0) {
|
||||
uint32_t len_acked = th_ack(th) - conn->seq;
|
||||
|
||||
conn_seq(conn, + len_acked);
|
||||
}
|
||||
|
||||
tcp_out(conn, FIN | ACK);
|
||||
conn_seq(conn, + 1);
|
||||
tcp_setup_retransmission(conn);
|
||||
|
||||
tcp_setup_last_ack_timer(conn);
|
||||
next = TCP_LAST_ACK;
|
||||
|
||||
break;
|
||||
}
|
||||
case TCP_ESTABLISHED: {
|
||||
bool fin = FL(&fl, &, FIN, th_seq(th) == conn->ack);
|
||||
|
||||
/* Whatever we've received, we know that peer is alive, so reset
|
||||
* the keepalive timer.
|
||||
@@ -3163,7 +3124,7 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt)
|
||||
NET_DBG("conn: %p len_acked=%u", conn, len_acked);
|
||||
|
||||
if ((conn->send_data_total < len_acked) ||
|
||||
(tcp_pkt_pull(conn->send_data,
|
||||
(tcp_pkt_pull(&conn->send_data,
|
||||
len_acked) < 0)) {
|
||||
NET_ERR("conn: %p, Invalid len_acked=%u "
|
||||
"(total=%zu)", conn, len_acked,
|
||||
@@ -3214,11 +3175,21 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt)
|
||||
|
||||
/* We are closing the connection, send a FIN to peer */
|
||||
if (conn->in_close && conn->send_data_total == 0) {
|
||||
next = TCP_FIN_WAIT_1;
|
||||
|
||||
k_work_reschedule_for_queue(&tcp_work_q,
|
||||
&conn->fin_timer,
|
||||
FIN_TIMEOUT);
|
||||
if (fin) {
|
||||
/* If FIN was also present in the processed
|
||||
* packet, acknowledge that and jump directly
|
||||
* to TCP_LAST_ACK.
|
||||
*/
|
||||
conn_ack(conn, + 1);
|
||||
next = TCP_LAST_ACK;
|
||||
tcp_setup_last_ack_timer(conn);
|
||||
} else {
|
||||
/* Otherwise, wait for FIN in TCP_FIN_WAIT_1 */
|
||||
next = TCP_FIN_WAIT_1;
|
||||
k_work_reschedule_for_queue(&tcp_work_q,
|
||||
&conn->fin_timer,
|
||||
FIN_TIMEOUT);
|
||||
}
|
||||
|
||||
tcp_out(conn, FIN | ACK);
|
||||
conn_seq(conn, + 1);
|
||||
@@ -3246,7 +3217,7 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt)
|
||||
if (len > 0) {
|
||||
bool psh = FL(&fl, &, PSH);
|
||||
|
||||
verdict = tcp_data_received(conn, pkt, &len, psh);
|
||||
verdict = tcp_data_received(conn, pkt, &len, psh, fin);
|
||||
if (verdict == NET_OK) {
|
||||
/* net_pkt owned by the recv fifo now */
|
||||
pkt = NULL;
|
||||
@@ -3289,7 +3260,19 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt)
|
||||
k_sem_give(&conn->tx_sem);
|
||||
}
|
||||
|
||||
/* Finally, after all Data/ACK processing, check for FIN flag. */
|
||||
if (fin) {
|
||||
keep_alive_timer_stop(conn);
|
||||
conn_ack(conn, + 1);
|
||||
tcp_out(conn, FIN | ACK);
|
||||
conn_seq(conn, + 1);
|
||||
tcp_setup_retransmission(conn);
|
||||
tcp_setup_last_ack_timer(conn);
|
||||
next = TCP_LAST_ACK;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case TCP_CLOSE_WAIT:
|
||||
/* Half-close is not supported, so do nothing here */
|
||||
break;
|
||||
@@ -3652,7 +3635,7 @@ int net_tcp_queue(struct net_context *context, const void *data, size_t len,
|
||||
for (int i = 0; i < msg->msg_iovlen; i++) {
|
||||
int iovlen = MIN(msg->msg_iov[i].iov_len, len);
|
||||
|
||||
ret = tcp_pkt_append(conn->send_data,
|
||||
ret = tcp_pkt_append(&conn->send_data,
|
||||
msg->msg_iov[i].iov_base,
|
||||
iovlen);
|
||||
if (ret < 0) {
|
||||
@@ -3671,7 +3654,7 @@ int net_tcp_queue(struct net_context *context, const void *data, size_t len,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ret = tcp_pkt_append(conn->send_data, data, len);
|
||||
ret = tcp_pkt_append(&conn->send_data, data, len);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@
|
||||
({ \
|
||||
NET_DBG("conn: %p total=%zd, unacked_len=%d, " \
|
||||
"send_win=%hu, mss=%hu", \
|
||||
(_conn), net_pkt_get_len((_conn)->send_data), \
|
||||
(_conn), net_pkt_get_len(&(_conn)->send_data), \
|
||||
_conn->unacked_len, _conn->send_win, \
|
||||
(uint16_t)conn_mss((_conn))); \
|
||||
NET_DBG("conn: %p send_data_timer=%hu, send_data_retries=%hu", \
|
||||
@@ -258,8 +258,8 @@ typedef void (*net_tcp_closed_cb_t)(struct tcp *conn, void *user_data);
|
||||
struct tcp { /* TCP connection */
|
||||
sys_snode_t next;
|
||||
struct net_context *context;
|
||||
struct net_pkt *send_data;
|
||||
struct net_pkt *queue_recv_data;
|
||||
struct net_pkt send_data;
|
||||
struct net_buf *queue_recv_data;
|
||||
struct net_if *iface;
|
||||
void *recv_user_data;
|
||||
sys_slist_t send_queue;
|
||||
|
||||
@@ -879,7 +879,7 @@ out:
|
||||
|
||||
static int dhcpv4_server_probing_init(struct dhcpv4_server_ctx *ctx)
|
||||
{
|
||||
return net_icmp_init_ctx(&ctx->probe_ctx.icmp_ctx,
|
||||
return net_icmp_init_ctx(&ctx->probe_ctx.icmp_ctx, AF_INET,
|
||||
NET_ICMPV4_ECHO_REPLY, 0,
|
||||
echo_reply_handler);
|
||||
}
|
||||
|
||||
@@ -490,7 +490,6 @@ int mdns_unpack_query_header(struct dns_msg_t *msg, uint16_t *src_id)
|
||||
int dns_unpack_name(const uint8_t *msg, int maxlen, const uint8_t *src,
|
||||
struct net_buf *buf, const uint8_t **eol)
|
||||
{
|
||||
int dest_size = net_buf_tailroom(buf);
|
||||
const uint8_t *end_of_label = NULL;
|
||||
const uint8_t *curr_src = src;
|
||||
int loop_check = 0, len = -1;
|
||||
@@ -529,6 +528,8 @@ int dns_unpack_name(const uint8_t *msg, int maxlen, const uint8_t *src,
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
} else {
|
||||
size_t dest_size = net_buf_tailroom(buf);
|
||||
|
||||
/* Max label length is 64 bytes (because 2 bits are
|
||||
* used for pointer)
|
||||
*/
|
||||
@@ -537,8 +538,7 @@ int dns_unpack_name(const uint8_t *msg, int maxlen, const uint8_t *src,
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
if (((buf->data + label_len + 1) >=
|
||||
(buf->data + dest_size)) ||
|
||||
if ((label_len + 1 >= dest_size) ||
|
||||
((curr_src + label_len) >= (msg + maxlen))) {
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
@@ -456,7 +456,7 @@ static int cmd_net_ping(const struct shell *sh, size_t argc, char *argv[])
|
||||
net_addr_pton(AF_INET6, host, &ping_ctx.addr6.sin6_addr) == 0) {
|
||||
ping_ctx.addr6.sin6_family = AF_INET6;
|
||||
|
||||
ret = net_icmp_init_ctx(&ping_ctx.icmp, NET_ICMPV6_ECHO_REPLY, 0,
|
||||
ret = net_icmp_init_ctx(&ping_ctx.icmp, AF_INET6, NET_ICMPV6_ECHO_REPLY, 0,
|
||||
handle_ipv6_echo_reply);
|
||||
if (ret < 0) {
|
||||
PR_WARNING("Cannot initialize ICMP context for %s\n", "IPv6");
|
||||
@@ -466,7 +466,7 @@ static int cmd_net_ping(const struct shell *sh, size_t argc, char *argv[])
|
||||
net_addr_pton(AF_INET, host, &ping_ctx.addr4.sin_addr) == 0) {
|
||||
ping_ctx.addr4.sin_family = AF_INET;
|
||||
|
||||
ret = net_icmp_init_ctx(&ping_ctx.icmp, NET_ICMPV4_ECHO_REPLY, 0,
|
||||
ret = net_icmp_init_ctx(&ping_ctx.icmp, AF_INET, NET_ICMPV4_ECHO_REPLY, 0,
|
||||
handle_ipv4_echo_reply);
|
||||
if (ret < 0) {
|
||||
PR_WARNING("Cannot initialize ICMP context for %s\n", "IPv4");
|
||||
|
||||
@@ -2106,6 +2106,8 @@ int zsock_getsockopt_ctx(struct net_context *ctx, int level, int optname,
|
||||
return 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case IPV6_MULTICAST_HOPS:
|
||||
ret = net_context_get_option(ctx,
|
||||
NET_OPT_MCAST_HOP_LIMIT,
|
||||
|
||||
@@ -771,7 +771,7 @@ static void send_ping(const struct shell *sh,
|
||||
struct net_icmp_ctx ctx;
|
||||
int ret;
|
||||
|
||||
ret = net_icmp_init_ctx(&ctx, NET_ICMPV6_ECHO_REPLY, 0, ping_handler);
|
||||
ret = net_icmp_init_ctx(&ctx, AF_INET6, NET_ICMPV6_ECHO_REPLY, 0, ping_handler);
|
||||
if (ret < 0) {
|
||||
shell_fprintf(sh, SHELL_WARNING, "Cannot send ping (%d)\n", ret);
|
||||
return;
|
||||
|
||||
@@ -694,7 +694,9 @@ static int uvc_get_vs_probe(const struct device *dev, struct net_buf *const buf,
|
||||
const struct usb_setup_packet *const setup)
|
||||
{
|
||||
struct uvc_data *data = dev->data;
|
||||
size_t size = MIN(sizeof(struct uvc_probe), net_buf_tailroom(buf));
|
||||
const size_t size = MIN(net_buf_tailroom(buf),
|
||||
MIN(sizeof(struct uvc_probe), setup->wLength));
|
||||
struct uvc_probe probe = {0};
|
||||
int ret;
|
||||
|
||||
switch (setup->bRequest) {
|
||||
@@ -702,19 +704,18 @@ static int uvc_get_vs_probe(const struct device *dev, struct net_buf *const buf,
|
||||
if (size < 1) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
net_buf_add_u8(buf, UVC_INFO_SUPPORTS_GET);
|
||||
return 0;
|
||||
case UVC_GET_LEN:
|
||||
if (size < 2) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
net_buf_add_le16(buf, sizeof(struct uvc_probe));
|
||||
return 0;
|
||||
case UVC_GET_DEF:
|
||||
if (size < sizeof(struct uvc_probe)) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
net_buf_add_mem(buf, &data->default_probe, sizeof(data->default_probe));
|
||||
net_buf_add_mem(buf, &data->default_probe, size);
|
||||
return 0;
|
||||
case UVC_GET_MIN:
|
||||
__fallthrough;
|
||||
@@ -723,16 +724,12 @@ static int uvc_get_vs_probe(const struct device *dev, struct net_buf *const buf,
|
||||
case UVC_GET_MAX:
|
||||
__fallthrough;
|
||||
case UVC_GET_CUR:
|
||||
if (size < sizeof(struct uvc_probe)) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
ret = uvc_get_vs_probe_struct(dev, (struct uvc_probe *)buf->data, setup->bRequest);
|
||||
ret = uvc_get_vs_probe_struct(dev, &probe, setup->bRequest);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
net_buf_add(buf, sizeof(struct uvc_probe));
|
||||
net_buf_add_mem(buf, &probe, size);
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@@ -742,45 +739,41 @@ static int uvc_get_vs_probe(const struct device *dev, struct net_buf *const buf,
|
||||
static int uvc_set_vs_probe(const struct device *dev, const struct net_buf *const buf)
|
||||
{
|
||||
struct uvc_data *data = dev->data;
|
||||
struct uvc_probe *probe;
|
||||
const size_t size = MIN(sizeof(struct uvc_probe), buf->len);
|
||||
struct uvc_probe probe = {0};
|
||||
struct uvc_probe max = {0};
|
||||
int ret;
|
||||
|
||||
if (buf->len != sizeof(*probe)) {
|
||||
LOG_ERR("Expected probe message of %u bytes got %u", sizeof(*probe), buf->len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
probe = (struct uvc_probe *)buf->data;
|
||||
memcpy(&probe, buf->data, size);
|
||||
|
||||
ret = uvc_get_vs_probe_struct(dev, &max, UVC_GET_MAX);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (probe->bFrameIndex > max.bFrameIndex) {
|
||||
if (probe.bFrameIndex > max.bFrameIndex) {
|
||||
LOG_WRN("The bFrameIndex %u requested is beyond the max %u",
|
||||
probe->bFrameIndex, max.bFrameIndex);
|
||||
probe.bFrameIndex, max.bFrameIndex);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
if (probe->bFormatIndex > max.bFormatIndex) {
|
||||
if (probe.bFormatIndex > max.bFormatIndex) {
|
||||
LOG_WRN("The bFormatIndex %u requested is beyond the max %u",
|
||||
probe->bFormatIndex, max.bFormatIndex);
|
||||
probe.bFormatIndex, max.bFormatIndex);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
if (probe->dwFrameInterval != 0) {
|
||||
data->video_frmival.numerator = sys_le32_to_cpu(probe->dwFrameInterval);
|
||||
if (probe.dwFrameInterval != 0) {
|
||||
data->video_frmival.numerator = sys_le32_to_cpu(probe.dwFrameInterval);
|
||||
data->video_frmival.denominator = USEC_PER_SEC * 100;
|
||||
}
|
||||
|
||||
if (probe->bFrameIndex != 0) {
|
||||
data->frame_id = probe->bFrameIndex;
|
||||
if (probe.bFrameIndex != 0) {
|
||||
data->frame_id = probe.bFrameIndex;
|
||||
}
|
||||
|
||||
if (probe->bFormatIndex != 0) {
|
||||
data->format_id = probe->bFormatIndex;
|
||||
if (probe.bFormatIndex != 0) {
|
||||
data->format_id = probe.bFormatIndex;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -920,7 +913,8 @@ static int uvc_get_vc_ctrl(const struct device *dev, struct net_buf *const buf,
|
||||
const struct device *video_dev = data->video_dev;
|
||||
struct video_ctrl_query cq = {.id = map->cid, .dev = video_dev};
|
||||
struct video_control ctrl = {.id = map->cid};
|
||||
size_t size = MIN(setup->wLength, net_buf_tailroom(buf));
|
||||
const size_t size = MIN(net_buf_tailroom(buf),
|
||||
MIN(sizeof(struct uvc_probe), setup->wLength));
|
||||
int64_t val64;
|
||||
int ret;
|
||||
|
||||
@@ -1112,7 +1106,8 @@ static int uvc_get_errno(const struct device *dev, struct net_buf *const buf,
|
||||
const struct usb_setup_packet *const setup)
|
||||
{
|
||||
struct uvc_data *data = dev->data;
|
||||
size_t size = MIN(setup->wLength, net_buf_tailroom(buf));
|
||||
const size_t size = MIN(net_buf_tailroom(buf),
|
||||
MIN(sizeof(struct uvc_probe), setup->wLength));
|
||||
|
||||
switch (setup->bRequest) {
|
||||
case UVC_GET_INFO:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user