Compare commits

...

88 Commits

Author SHA1 Message Date
Keith Short
65402def79 posix: c_lib_ext: fnmatch: fix llvm warning
The tolower() function takes an int parameter. LLVM compilers generate a
warning if a char is passed instead.

Signed-off-by: Keith Short <keithshort@google.com>
2026-01-15 15:14:41 +00:00
Chris Friedt
2a079897bb posix: c_lib_ext: fnmatch: fix character class support
A couple of tests were inconsistent with glibc and picolibc.

Significant rework done to the `fnmatch()` implementation which included
refreshing that and the `rangematch()` implementations from commit

0a3b2e376d150258c8294c12a85bec99546ab84b

in https://github.com/lattera/freebsd

Removed `match_posix_class()` and implemented that functionality as
`rangematch_cc()`, which uses 64-bit integer comparison for matching
`[:alnum:]` et al instead of string comparison. That likely only works
for the "C" locale.

Signed-off-by: Chris Friedt <cfriedt@tenstorrent.com>
Signed-off-by: Harun Spago <harun.spago.code@gmail.com>
(cherry picked from commit de2d0c9563)
2026-01-15 15:14:41 +00:00
Chris Friedt
be5cae2111 posix: c_lib_ext: fnmatch: fix escape-oriented regression
A regression in 936d0278bd introduced a
subtle bug in the way that escaped expressions were handled.

The regression originated with the assumption that test data (originally
adapted from a 3rd-party testsuite) was correct when it was in fact
flawed.

Specifically, `fnmatch("[[?*\\]", "\\", 0)` should fail (`FNM_NOMATCH`),
since the "\\" sequence (a single backslash after compilation) escapes
the following ']' character, thus leaving the bracket expression
incomplete.

As @keith-packard  has pointed out,
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/\
V3_chap02.html#tag_18_13_01 says that a bracket expression is only
interpreted as a bracket expression, when a proper bracket expression
is formed.

Therefore, the pattern is interpreted as the sequence
`'['`, `'['`, `'?'`, `*` (wildcard), `']'` and the call should return
`FNM_NOMATCH` to indicate failure rather than 0 to indicate success.

Added new test cases from #98827 and some commentary for subsequent
reviewers.

This change does not completely fix #55186 but is related to it.

Signed-off-by: Chris Friedt <cfriedt@tenstorrent.com>
(cherry picked from commit 637080e7ec)
2026-01-15 15:14:41 +00:00
Chris Friedt
daaf54ca4b libc: minimal: add missing ctype.h functions
Add the functions below to the minimal libc ctype.h since they are
missing, and are required as of C89 (C99 for `isblank()`)

* `isblank()`
* `islower()`
* `ispunct()`

Signed-off-by: Chris Friedt <cfriedt@tenstorrent.com>
2026-01-15 15:14:41 +00:00
Chris Friedt
42d8b98765 libc: minimal: ctype: remove unnecessary casts
A review comment in the PR below requested that unnecessary casts were
removed from ctype.h in the PR below.

https://github.com/zephyrproject-rtos/zephyr/pull/99451

Tested with manual compilation in C and C++ mode with the arguments
```shell
gcc -Wconversion -Werror -Wall -Wextra -Wint-conversion
clang -Wconversion -Werror -Wall -Wextra -Wint-conversion
gcc -Wconversion -Werror -Wall -Wimplicit--Wextra
clang++ -Wconversion -Werror -Wall -Wextra
```

and also with `-- -DCONFIG_COMPILER_WARNINGS_AS_ERRORS=y`

Signed-off-by: Chris Friedt <cfriedt@tenstorrent.com>
2026-01-15 15:14:41 +00:00
Chris Friedt
a8ea50bed3 libc: minimal: ctype: express ctype limits in more direct fashion
Based on review feedback, it was suggested to express ctype
character checks in a more direct fashion, rather than using
arithmetic, and allow the compiler to optimize as it sees fit.

https://github.com/zephyrproject-rtos/zephyr/pull/99451#\
discussion_r2530339430

Signed-off-by: Chris Friedt <cfriedt@tenstorrent.com>
2026-01-15 15:14:40 +00:00
Chris Friedt
223e2822f9 libc: minimal: ctype: use unsigned int instead of unsigned
The "check warns" workflow in CI warned over the use of `unsigned` as a
shorthand for `unsigned int` in several locations in
`lib/libc/minimal/include/ctype.h`.

```
 UNSPECIFIED_INT: Prefer 'unsigned int' to bare use of 'unsigned'
File:lib/libc/minimal/include/ctype.h
```

Adjust `unsigned` to `unsigned int` to avoid linter warnings.

Signed-off-by: Chris Friedt <cfriedt@tenstorrent.com>
2026-01-15 15:14:40 +00:00
Fabio Baltieri
0ffde735ae ci: twister: download only the arm toolchain
Looks like this workflow is running out of space too. Only install the
arm toolchain.

Signed-off-by: Fabio Baltieri <fabiobaltieri@google.com>
2026-01-15 07:57:01 -05:00
Anas Nashif
bd91f219af ci: update action-zephyr-setup action version to v1.0.11
Use latest version of action-zephyr-setup action.

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-01-15 07:56:15 -05:00
Fabio Baltieri
57f48e6e8c ci: doc-build: download only the arm toolchain
Sync up the doc-build toolchain in the branch to only use the arm one,
should save some disk space on backport PRs.

Signed-off-by: Fabio Baltieri <fabiobaltieri@google.com>
2026-01-15 11:46:18 +00:00
Mathieu Choplain
915f7bb781 drivers: udc: stm32: fix clock configuration for STM32F7 w/ USBPHYC
OTGHS using the USBPHYC on STM32F723 and some STM32F730 requires
special clock configuration to work.

Signed-off-by: Mathieu Choplain <mathieu.choplain-ext@st.com>
2026-01-13 09:42:20 -08:00
Mathieu Choplain
697706d295 drivers: usb: dc: stm32: fix clock configuration for STM32F7 w/ USBPHYC
OTGHS using the USBPHYC on STM32F723 and some STM32F730 requires
special clock configuration to work.

Signed-off-by: Mathieu Choplain <mathieu.choplain-ext@st.com>
2026-01-13 09:42:20 -08:00
Robert Lubos
69947f64a2 tests: net: dns_resolve: Add tests for dns_unpack_name()
Verify that dns_unpack_name() generates a valid DNS name when unpacking
records and that it returns an error in case of overflow.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
(cherry picked from commit 7a9ca8e410)
2025-11-29 13:17:12 -08:00
Robert Lubos
635d5c00e3 net: dns: Fix potential buffer overflow when unpacking labels
As the loop unpacking the DNS name from records checks the current
label length on each iteration, it's also needed to update the remaining
buffer length on each iteration, otherwise the buffer length checks
doesn't work as expected.

Additionally, the remaining buffer checks while technically worked, they
were conceptually wrong and unintuitive. The buf->data pointer doesn't
move, so comparing against this pointer when adding new labels doesn't
make sense. It's more intuitive to simply compare the label size vs
the remaining buffer space.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
(cherry picked from commit 7bd45cd39b)
2025-11-29 13:17:12 -08:00
Sudan Landge
53f776a934 tests: arm: exclude mps2/an385 on user stack test
Temporarily disable running the user stack tests on mps2/an385 to
unblock ci issues reported in #98494.

Signed-off-by: Sudan Landge <sudan.landge@arm.com>
(cherry picked from commit 2408b808d2)
2025-11-17 11:40:11 -08:00
Sudan Landge
bf194b3d43 tests: fix arch.arm.user.stack test failure
Fixes #97473 by:
- Marking the test as passed if the hardware executes user threads for a
  while without triggering a stack corruption, instead of waiting
    indefinitely.
- Adding a timeout to ensure the test exists gracefully if the issue is
  not reproduced.

Also fixes a stack corruption issue on QEMU targets, caused by
insufficient stack size and revealed by the timer change.

Signed-off-by: Sudan Landge <sudan.landge@arm.com>
(cherry picked from commit a55053b216)
2025-11-17 11:40:11 -08:00
Alberto Escolar Piedras
cb7ce14654 drivers/ethernet/eth_native_tap: Fix use of deprecated kconfig
In 200b886d3c a deprecated kconfig
option was brought back into the driver.
Let's fix it.

Signed-off-by: Alberto Escolar Piedras <alberto.escolar.piedras@nordicsemi.no>
(cherry picked from commit 0528554720)
2025-11-14 11:48:42 -08:00
Ali Hozhabri
22f0033e60 drivers: bluetooth: hci: Fix the issue about the TRNG peripheral instance
Fix the issue regarding passing the TRNG peripheral instance to the driver.

Increase the SYSTEM_WORKQUEUE_STACK_SIZE when CONFIG_BT is set.
According to the log of thread analyzer for beacon sample, 1048 bytes
are needed. So, it's been increased to a safer value.

Signed-off-by: Ali Hozhabri <ali.hozhabri@st.com>
(cherry picked from commit 7a593ede3e)
2025-11-14 11:47:35 -08:00
Ali Hozhabri
674a54ce39 drivers: entropy: Modify the recover_seed_error function for WB0x
Exclude the WB0x series from discarding data 12 times from the RNG data
register.

Add a comment to the recover_seed_error function explaining the reason
for reading and discarding data from the RNG data register 12 times.

Signed-off-by: Ali Hozhabri <ali.hozhabri@st.com>
(cherry picked from commit 57ebf79d87)
2025-11-14 11:47:35 -08:00
Ali Hozhabri
f4dc776671 drivers: entropy: Fix non-stop RNG ISR firing for STM32WB09
Fix the TRNG driver issue regarding non-stop ISR firing for STM32WB09 by
clearing RNG_IRQ_SR_ERROR_IRQ flag.

Fix a typo related to a function input parameter.

Signed-off-by: Ali Hozhabri <ali.hozhabri@st.com>
2025-11-14 11:47:35 -08:00
Tomi Fontanilles
1ee1798f50 doc: release-notes-4.2: fix up TF-M version update entry
TF-M had already been updated to 2.2.0 by the time 4.2 was released.
(https://github.com/zephyrproject-rtos/zephyr/pull/91169)

Signed-off-by: Tomi Fontanilles <tomi.fontanilles@nordicsemi.no>
(cherry picked from commit 8b032af664)
2025-11-14 11:32:00 -08:00
Robert Lubos
636ad05950 tests: net: icmp: Add test cases for ICMP family mismatch
Add test cases that respective ICMPv4/ICMPv6 handlers are not called for
packets where address family doesn't match (i.e. malformed ICMPv4 packet
imitating ICMPv6 one).

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
(cherry picked from commit 486e8247c6)
2025-11-10 09:04:40 -08:00
Robert Lubos
81ab4dedbe net: icmp: Verify the address family before calling the callback
Check the address family of the packet before passing it to a ICMP
handler, to avoid scenarios where ICMPv4 packet is paseed to a ICMPv6
handler and vice versa.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
(cherry picked from commit 587d9e6a4a)
2025-11-10 09:04:40 -08:00
Guotao Zhang
57ab471c3a drivers: bluetooth: h4: Fix check for sufficient buffer size
When alloc the evt buffer,such as the adv report, only compare the
remaining data len, should aslo consider the hdr_len, because the
hdr also copy to alloced buffer.if not consider the hdr, then
hdr + remaining data may larger than alloced buffer, because the
alloced buffer is not enough,then will assert when receive the
remaining data.

Signed-off-by: Guotao Zhang <guotao.zhang@nxp.com>
(cherry picked from commit ec970a635e)
2025-11-03 10:35:01 -08:00
Fabian Blatz
0b8771d299 modules: lvgl: Fix stdlib usage
LVGL already provides an implementation wrapping a C standard library into
its own lv_* functions. Add them to the CMakeLists and set the appropriate
defines for them.

Signed-off-by: Fabian Blatz <fabianblatz@gmail.com>
(cherry picked from commit 076994f492)
2025-10-27 15:11:46 -07:00
Sudan Landge
13dd5cb1ae arch: arm: start threads on privileged stack
Use the privileged stack when starting K_USER threads in arch_new_thread().
Threads entering user mode with k_thread_user_mode_enter() keep their
existing flow. To support both cases, z_arm_userspace_enter() now takes an
internal ABI flag (sp_is_priv) indicating whether PSP already points to
the privileged stack.

Also fix calculation of the privileged stack top: use priv_stack_end
directly instead of priv_stack_start + CONFIG_PRIVILEGED_STACK_SIZE, which
failed to account for guard/FPU offsets applied to priv_stack_start.

Signed-off-by: Sudan Landge <sudan.landge@arm.com>
(cherry picked from commit 0438b9f29e)
2025-10-27 15:11:34 -07:00
Rory Piper
be61610d3f drivers: flash_stm32h7: Fix REAL_FLASH_SIZE_KB size
For devices other than the stm32h745/747/755/757 that use
dual-core cortex-M4/cortex-M7, do not multiply flash
controller size by 2. Single-core stm32h7x devices define
their flash-controllers dtsi as a single area, not two banks.
Use the presence of the bank2-flash-size prop to determine if
this is a dual-core stm3h7x or not.

Signed-off-by: Rory Piper <rory.piper@signal-fire.com>
(cherry picked from commit ea1245eb92)
2025-10-27 09:31:42 -07:00
Josuah Demangeon
2c317b081d usb: uvc: respect setup->wLength in responses
Due to the alignment and granularity requirements of memory allocation,
setup->wLength is shorter than the allocated buffer size.
This lead to responses larger than what the host requested, which it
rejected. Fix it by using the minimum between the allocated size, the
struct size, and the wLength requested.

Signed-off-by: Josuah Demangeon <me@josuah.net>
(cherry picked from commit 366c64eca0)
2025-10-09 14:47:53 -07:00
Josuah Demangeon
d7b09179c3 usb: uvc: allow the host to use short probe/commit messages
Some OSes like MacOS use shorter UVC 1.1 probe/commit messages even when
UVC 1.5 is supported, without bUsage, bBitDepthLuma, bmSettings,
bMaxNumberOfRefFramesPlus1, bmRateControlModes bmLayoutPerStream.
Accept messages of arbitrary size to safely be processed, ignoring all
missing fields, improving standard compliance.

Signed-off-by: Josuah Demangeon <me@josuah.net>
(cherry picked from commit ed9327dec2)
2025-10-09 14:47:53 -07:00
Daniel DeGrasse
64e98eb527 release: Zephyr v4.2.1
Set the version to v4.2.1

Signed-off-by: Daniel DeGrasse <ddegrasse@tenstorrent.com>
Signed-off-by: Dan Kalowsky <dkalowsky@amperecomputing.com>
2025-10-07 17:42:43 -05:00
Daniel DeGrasse
4d44e3280b doc: release_notes: add 4.2.1 release notes
Add 4.2.1 release notes, summarizing the issues addressed since 4.2 was
released.

Signed-off-by: Daniel DeGrasse <ddegrasse@tenstorrent.com>
2025-10-07 17:31:48 -05:00
Julien Racki
6da1cbcb06 drivers: ethernet: stm32: Move the Ethernet API V1 init
Move the Ethernet API v1 Initialization in eth_init_api_v1()
helper function to match the V2 implementation.

Signed-off-by: Julien Racki <julien.racki-ext@st.com>
2025-10-07 16:29:52 -05:00
Julien Racki
1e5f5af4eb drivers: ethernet: stm32: Fix the init call order
Fix the init call order for V2 API to be able to configure PTP
as PTP initialization happens before iface initialization.

Signed-off-by: Julien Racki <julien.racki-ext@st.com>
2025-10-07 16:29:52 -05:00
Khaoula Bidani
ee29ea2a20 drivers: gpio: stm32: Fix gpio_pin_get_config
This commit updates the function to only set output-related flags
(GPIO_OUTPUT_INIT_HIGH, GPIO_OUTPUT_INIT_LOW) when the pin
is actually configured as output. For input pins, only GPIO_INPUT and
other relevant flags are set.

Signed-off-by: Khaoula Bidani <khaoula.bidani-ext@st.com>
(cherry picked from commit e803a10b91)
2025-10-06 14:38:58 -05:00
Detlev Zundel
3d4204036a samples: modules: lvgl: demos: Increase memory pool on native
Due to the added overhead on 64 bit native, we also need to increase
the memory pool size to fix crashes as described in here:

https://github.com/lvgl/lvgl/issues/7648

Signed-off-by: Detlev Zundel <dzu@member.fsf.org>
(cherry picked from commit abd0919bc9)
2025-10-06 14:38:25 -05:00
Detlev Zundel
c60a870b1c samples: modules: lvgl: demos: Increase main stack to fix crash
The increased complexity of the LVGL code now overruns the 4 KiB stack
of the main thread. Increase it to 6 KiB to fix the error.

Fixes: #94473

Signed-off-by: Detlev Zundel <dzu@member.fsf.org>
(cherry picked from commit e05a272817)
2025-10-06 14:38:25 -05:00
Pieter De Gendt
d26b221f53 arch: common: nocache.ld: One nocache MPU region
Combine the load and noload cache regions for a single MPU aligned block.
This is required to have an MPU region with a size that is a power of 2.

Signed-off-by: Pieter De Gendt <pieter.degendt@basalte.be>
(cherry picked from commit 8f7908694a)
2025-10-06 13:00:31 -05:00
Pieter De Gendt
9cb7b9e4ec linker: Split nocache memory sections into loadable and non-loadable
Commit f9168ae464 made all non-cached memory
loadable by default.

However as nocache memory is typically used for reserving larger buffers to
be shared between peripherals, this comes at fairly large cost towards ROM
usage.

This commit creates two distinct sections for both loadable and
non-loadable nocache memory sections.

Signed-off-by: Pieter De Gendt <pieter.degendt@basalte.be>
(cherry picked from commit 294f7e52c5)
2025-10-06 13:00:31 -05:00
Benjamin Cabé
e395a9a649 doc: _scripts: ensure twister.yaml file is considered in board catalog
Boards may use twister.yaml file to define Twister platforms, so
board catalog should also parse them.

Fixes: zephyrproject-rtos/zephyr#95721.

Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
(cherry picked from commit 9f181b6711)
2025-10-06 09:57:10 -07:00
Alen Karnil
9526404c65 dts: arm: st: stm32f303: fix I2C3 address in nodename
Correct stm32f303 I2C3 address in nodename.

Signed-off-by: Alen Karnil <alankarnil@gmail.com>
(cherry picked from commit 4363d14bef)
2025-10-02 16:40:18 -05:00
Samuel Tsai
116c4a9e40 Bluetooth: host: adv: revert 39cb574 to fix spurious error log
Commit 39cb574 changed the log level from LOG_DBG to LOG_ERR in
bt_le_adv_resume(). This causes the error log
"No valid legacy adv to resume" to appear during normal connection
establishment when using bt_le_ext_adv_start(), even though the
system is functioning correctly.

Revert the change to restore the original LOG_DBG level.

Fixes: #94954

Signed-off-by: Samuel Tsai <stsai@atmosic.com>
(cherry picked from commit 07dc0ad40d)
2025-09-30 15:05:15 -07:00
Robert Lubos
46292d748d net: tcp: Fix ACK processing when FIN packet is received
In case FIN packed also acknowledged most recently sent data, not all
ack-related TCP context variables were updated, resulting in invalid SEQ
number values sent in consecutive packets.

Fix this by refactoring the FIN handling in TCP_ESTABLISHED state.
Instead of having a separate block strictly for FIN packet processing,
let the packet be processed by common code responsible for regular
data/ack processing. This should be less error-prone for any future
modifications or not-yet-discovered issues. Only after the common
processing of data/ack is done, we check whether FIN flag was present in
the packet, and mark the connection for closing.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
(cherry picked from commit 178150590c)
2025-09-30 15:04:27 -07:00
Robert Lubos
51e1f38026 tests: net: tcp: Add test for FIN,ACK received after final data
Add a test case for a scenario where the final data sent by one peer is
acknowledged in the FIN,ACK response from the other peer. Verify that
the acknowledgment is handled correctly, and a consecutive sequence
number sent by the TCP stack in such case is set correctly.

This complements the other existing test for FIN packet handling, which
verified that data received in a FIN packet is handled correctly. With
those tests in place it should be safer to update any logic related to
FIN packet handling.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
(cherry picked from commit 99b435788e)
2025-09-30 15:04:27 -07:00
Robert Lubos
87b06394e6 net: tcp: Preallocate TX packet for TCP context
TCP context cannot operate w/o a TX packet for buffering transmitted
data. So far this net_pkt was allocated at runtime from the common
packet pool, but this created some not-obvious memory requirement on TCP
and could lead to TX packet starvation in case many TCP connections are
open in parallel. Therefore, allocate this packet structure statically,
as a part of the TCP context instead.

This increases the memory requirement of the TCP context by ~64 bytes,
however if that's a concern for the application, the maximum number of
TX packets can be lowered instead. In return, we get a clear separation
between the number of TCP connections opened, and the amount of packets
that can be transmitted.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
(cherry picked from commit eda76ad21b)
2025-09-30 15:02:50 -07:00
Robert Lubos
9800d46c69 net: pkt: Add helper function to initialize TX packet
Add helper function to initialize externally allocated TX packet. It's
especially important to configure net_buf slab for the packet so that
net buffers are allocated from a correct pool for the packet.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
(cherry picked from commit b8c7984099)
2025-09-30 15:02:50 -07:00
Robert Lubos
ac91402f71 net: tcp: Use net_buf pointer directly for out-of-order recv queue
Using net_pkt for TCP out-of-order recv queue was an overshot, as the
mechanism mostly used net_buf operations directly anyway. It can be
easily replaced with a direct net_buf pointer, so that it's not longer
needed to hog one net_pkt per TCP context anymore.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
(cherry picked from commit aca511c91f)
2025-09-30 15:02:50 -07:00
Sudan Landge
e58bca83de arch: arm: switch to privilege stack in SVC handler
Initialize the privilege stack and switch PSP to it early in the SVC
handler to ensure `z_arm_do_syscall` does not start on a user-accessible
stack frame.

Signed-off-by: Sudan Landge <sudan.landge@arm.com>
(cherry picked from commit 319c697286)
2025-09-30 15:01:53 -07:00
Sudan Landge
91d1416460 boards: arm: mps2: Add dependency to empty_cpu0 for an521/cpu1's app
`west build` does not build the `empty_cpu0` application making
`west build -b mps2/an521/cpu1 -t run` fail because of the missing
empty_cpu0's binary.

Signed-off-by: Sudan Landge <sudan.landge@arm.com>
(cherry picked from commit 52151d0b23)
2025-09-30 15:01:53 -07:00
Sudan Landge
cbb43bee3d tests: overwrite return address of stack frame
Introduce a test to overwrite the return address in the exception
stack frame of a lower-priority thread performing an SVC call.

Signed-off-by: Sudan Landge <sudan.landge@arm.com>
(cherry picked from commit f80bef31ef)
2025-09-30 15:01:53 -07:00
Jukka Rissanen
989499c8f4 net: context: Make sure TCP allocation is not leaked
If we have allocated a TCP connection, and if after that
we get an error like EADDRINUSE, then we must de-allocate
the TCP connection otherwise there is a buffer leak.

Signed-off-by: Jukka Rissanen <jukka.rissanen@nordicsemi.no>
(cherry picked from commit 909710b598)
2025-09-30 15:01:25 -07:00
Jamie McCrae
6eebe0acf0 cmake: mcuboot: Add dependency to keys
Adds a dependency that causes CMake to re-configure if the input
key files for MCUboot signing/encryption have changed

Signed-off-by: Jamie McCrae <jamie.mccrae@nordicsemi.no>
(cherry picked from commit 271dbb4015)
2025-09-21 20:29:28 -07:00
Mickael Bosch
1ea8bb2e0f drivers: i2c: stm32: fix compilation with DMA
fixes:
- implicit declaration of function 'stm32_buf_in_nocache'
- undefined reference to 'stm32_buf_in_nocache'

Signed-off-by: Mickael Bosch <mickael.bosch@linux.com>
(cherry picked from commit 6e018bbf04)
2025-09-12 14:23:09 -04:00
Etienne Carriere
4217df505a drivers: i2c: stm32: exclude stm32f7 family for PM in RTIO driver
Exclude STM32F7 SoC series from PM support since that SoC doees not
yet manage power management in Zephyr and HAL API functions
LL_I2C_EnableWakeUpFromStop() and LL_I2C_DisableWakeUpFromStop()
are not implemented in the H7 HAL/LL drivers.

This change ports into the STM32 RTIO driver the change made in the
non-RTIO driver through commit 1804eb7bc3 ("drivers: i2c: stm32:
exclude stm32f7 family for PM").

Back ported from commit 5ff3dbeeee ("drivers: i2c: stm32: exclude
stm32f7 family for PM in RTIO driver").

Signed-off-by: Etienne Carriere <etienne.carriere@st.com>
2025-09-08 14:43:41 -07:00
Etienne Carriere
d1a9ef6b0b drivers: i2c: stm32: sync stm32_v2 RTIO on PM runtime state
Always call pm_device_runtime_get() when registering a target
even if the device is not wakeup capable to prevent I2C target not being
function if the device goes into a SoC Stop mode.

This change ports into the STM32 v2 RTIO driver the change made in the
non-RTIO driver through commit 67f80e35b8 ("i2c: stm32: always call
runtime_get when registering targets").

Signed-off-by: Etienne Carriere <etienne.carriere@st.com>
(cherry picked from commit 181e544550)
2025-09-08 14:43:41 -07:00
Stephanos Ioannidis
bf9345a1ec SDK_VERSION: Use Zephyr SDK 0.17.4
This commit updates ZEPHYR_SDK to point to the Zephyr SDK 0.17.4 release.

Signed-off-by: Stephanos Ioannidis <root@stephanos.io>
(cherry picked from commit 59a5909abb)
2025-09-07 15:41:24 -07:00
Stephanos Ioannidis
7f89472f14 ci: Switch to CI image v0.28.4
This commit updates the CI workflows to use the CI image v0.28.4, which
includes Zephyr SDK 0.17.4.

Signed-off-by: Stephanos Ioannidis <root@stephanos.io>
(cherry picked from commit 13ba04fd1f)
2025-09-07 15:41:24 -07:00
Andreas Schmidt
e3a55c96ef dts: arm: st: u5: fix wkup-pin@8 referencing non-existent port gpiof
With commit d280d89 the gpiof port got moved from file stm32u5.dtsi to
file stm32u5_extra.dtsi. stm32u5_extra.dtsi is not included for
STM32U535/545. In same file stm32u5.dtsi still node wkup-pin@8 references
non-existent port gpiof.

Fixes #93445

Signed-off-by: Andreas Schmidt <andreas.schmidt@dormakaba.com>
(cherry picked from commit 528ab9d9c2)
2025-09-07 15:39:28 -07:00
Johann Fischer
663da2302b doc: update pyOCD repository links
The repository has been moved to a new organization, see
https://pyocd.io/. Update links to the pyOCD repository.

Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
(cherry picked from commit 617b71bc17)
2025-09-02 22:15:47 -07:00
Robin Kastberg
4670cb27c7 iar: ltorg directive not supported
Currently this directive is not supported in EWARM 9.70.1,
it will be in future versions, but we want Zephyr 4.2
to work with IAR EWARM 9.70.1.

Signed-off-by: Robin Kastberg <robin.kastberg@iar.com>
(cherry picked from commit fa165da667)
2025-08-22 18:50:36 -05:00
Tim Pambor
a55b5444c6 twister: Fix race condition in try_making_symlink
Replaces the check-then-create pattern for symlinks with
opportunistic creation. Instead of checking for existence
before creating the symlink, the code now attempts to
create it directly and gracefully handles the case
where it already exists.

Signed-off-by: Tim Pambor <tim.pambor@codewrights.de>
(cherry picked from commit dff24c8c00)
2025-08-22 16:49:22 -07:00
Keith Packard
c1adc507d7 west: Update picolibc to version being proposed for SDK 0.17.4
We're trying to re-synchronize picolibc bits across Zephyr and the Zephyr
SDK. At this point, SDK 0.17.3 is missing some minor updates found in the
module and the module is missing a commit from the SDK.

Signed-off-by: Keith Packard <keithp@keithp.com>
2025-08-21 13:33:13 -07:00
Bas van Loon
e918bdac38 fs/ext2: Fix NULL dereference when fs_stat queries root.
When fs_stat() queries the root / mountpoint it should return its root
i_node but instead it tries to return the parent i_node which does not
exist. Fix this by checking if parent is set otherwise return the root
i_node.

Fixes https://github.com/zephyrproject-rtos/zephyr/issues/94000.

Signed-off-by: Bas van Loon <bas@arch-embedded.com>
(cherry picked from commit 1dcf123e2d)
2025-08-21 13:32:22 -07:00
Pieter De Gendt
8b5e0388cf drivers: ethernet: nxp_imx_netc: Fix LAA bit location
The Locally Administered Address (LAA) bit should be set on the first
octet of the MAC address.

Signed-off-by: Pieter De Gendt <pieter.degendt@basalte.be>
(cherry picked from commit f1b4c7c992)
2025-08-20 18:11:35 -07:00
Pieter De Gendt
3b7610ec5f drivers: ethernet: stm32: Set LAA bit on MAC address based on device ID
The MAC addressed derived from the device ID is not assigned by the
manufacturer and therefor the Locally Administered Address (LAA) bit should
be set.

Signed-off-by: Pieter De Gendt <pieter.degendt@basalte.be>
(cherry picked from commit 300016c801)
2025-08-20 18:09:50 -07:00
Daniel Flodin
2b0f179079 cmake: assembler optimization options
Commit f499ea0 made it so that the compiler optimization flags are also
passed to the assembler. However, this breaks for the IAR toolchain
since it uses the GNU assembler which does not have the same
optimization flags as the IAR compiler.

This commit separates the compiler and assembler optimizations to make
it possible to specify appropriate flags in a toolchains corresponding
`compiler_flags.cmake`

Signed-off-by: Daniel Flodin <daniel.flodin@iar.com>
(cherry picked from commit a4b66f9214)
2025-08-20 18:03:03 -07:00
Ofir Shemesh
ff9fb454c6 misc: flexram: allow RAM type node to be disabled in DT
Use DT_NODE_HAS_COMPAT_STATUS to skip disabled child nodes. This
avoids build errors when setting a RAM type to 0 banks.

Signed-off-by: Ofir Shemesh <ofirshemesh777@gmail.com>
(cherry picked from commit 169b47ce38)
2025-08-19 13:28:40 -05:00
Marc Lasch
5282c9fdc8 drivers: net: ppp: Fix link-layer address configuration
Restore setting the ppp link-local address either to CONFIG_PPP_MAC_ADDR or
to a random value 00:00:5e:00:53:XX instead of leaving it uninitialized.

Recently the memory handling for the link-layer addresses was changed from
an approach of copying pointers to managing the memory as a member of the
`net_linkaddr` struct (ref ac3cb9dac0).

The piece of code this patch touches however, relied on the use of the
pointers to function properly.

With the recent change, the MAC address was copied to the new member
location before it was even set (either from Kconfig or selected randomly).
As a result, the link-layer address was kept initialized to zero, which
resulted in a IPv6 address of fe80::ff:fe00:0 which is exactly the
link-local EUI-64 representation of the MAC address 00:00:00:00:00:00
(without flipping the "universal/local" bit).

Signed-off-by: Marc Lasch <marc.lasch@husqvarnagroup.com>
(cherry picked from commit 15048337c4)
2025-08-18 11:09:20 -05:00
Fabrice DJIATSA
ee0aecc953 boards: st: nucleo_u385rg_q: update clock domain source for rng
Several tests failed due to a low clock frequency for
the RNG peripheral.
Increase the RNG clock frequency by providing MSIK with
96 MHz as the domain source.

Signed-off-by: Fabrice DJIATSA <fabrice.djiatsa-ext@st.com>
(cherry picked from commit ac733b1ae9)
2025-08-18 11:08:56 -05:00
Pieter De Gendt
21c942f18c drivers: regulator: shell: Fix regulator parent name completion
Shell functions targeting regulator parents used the auto-completion of
regulator devices instead.

Signed-off-by: Pieter De Gendt <pieter.degendt@basalte.be>
(cherry picked from commit 576b3daffa)
2025-08-11 10:56:54 -05:00
Maureen Helm
f017af445e drivers: udc: Fix max32 driver high speed support
High speed support has been broken for the max32 driver since commit
faeabc63c9.

Signed-off-by: Maureen Helm <maureen.helm@analog.com>
(cherry picked from commit a4c757adc2)
2025-08-11 10:56:19 -05:00
Tahsin Mutlugun
01949d478d tests: drivers: spi: spi_loopback: Update slow rates for MAX32 boards
The requested SPI clock rate and the actual rate that is set can be
different depending on the peripheral clock and divisors available to
the SPI peripheral. For some MAX32 SoCs, actual rate ended up being
higher than the devicetree setting. This would then cause latency tests
to fail as transfers finish earlier than minimum expected duration.

Update the test frequency values in several MAX32 board overlays to pass
latency tests.

Signed-off-by: Tahsin Mutlugun <Tahsin.Mutlugun@analog.com>
(cherry picked from commit 3de5883fc1)
2025-08-11 10:55:53 -05:00
Tahsin Mutlugun
0dbc00a63b drivers: spi: spi_max32: Return proper error codes in spi_configure
spi_configure was returning HAL error codes that are incompatible with
Zephyr error definitions straight back to the caller. Replace these with
error codes that Zephyr can correctly interpret.

Signed-off-by: Tahsin Mutlugun <Tahsin.Mutlugun@analog.com>
(cherry picked from commit edc9ff951d)
2025-08-11 10:55:53 -05:00
Tahsin Mutlugun
94b74dbd89 drivers: spi: spi_max32: Fix word size support
Driver was not handling SPI word sizes other than 8 bits. Apply DFS
shift wherever necessary to support non 8-bit transfers.

DMA mode cannot support word sizes that are less than 8 bits so return
-ENOTSUP if word size less than 8-bits is required.

Signed-off-by: Tahsin Mutlugun <Tahsin.Mutlugun@analog.com>
(cherry picked from commit f47449e7e9)
2025-08-11 10:55:53 -05:00
Robert Lubos
4c362f1aec tests: net: socket: tcp: Add test for keepalive connection upkeep
Add test verifying that if keep-alive messages are exchanged, the
connection remains alive.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
(cherry picked from commit dcbd1ed5fc)
2025-08-11 10:54:29 -05:00
Robert Lubos
bafc9f2a66 net: tcp: Fix handling of keep-alive probes
Keep-alive probes have seq number set to SND.NXT - 1 and may or may not
contain an octet of data. The latter case was not handled properly
therefore add a special case when validating seq number to response to
keep-alive probes.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
(cherry picked from commit d93c5d6072)
2025-08-11 10:54:29 -05:00
Henrik Brix Andersen
30de5e8a2c drivers: console: posix_arch_console: remove build warning
Remove build warning when building the posix_arch_console driver with
CONFIG_PRINTK=n and CONFIG_STDOUT_CONSOLE=n.

Fixes: #93790

Signed-off-by: Henrik Brix Andersen <henrik@brixandersen.dk>
(cherry picked from commit 3eedebe031)
2025-08-04 12:05:41 -05:00
Anas Nashif
ff6295f930 tests: llext: disable debug logging
disable debug in general as it is too verbose and hides test output.
However, this now fixes an issue in the test itself after 4.2 release.

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
(cherry picked from commit 94e0e5ae85)
2025-08-04 10:32:43 -05:00
Armando Visconti
738e159ede drivers/sensor/: lis2dux12: fix ODR setting
In lis2dux12_freq_to_odr_val, the loop through the array of possible ODR
frequencies can break sooner than expected if power-mode is
set to High Performance mode and the requested ODR is less than or
equal to 25Hz.

Moreover, move the "odr |= 0x10" statement used for HP mode in the
chip_api set_odr_raw() API, so that we enter the HP mode even when the
ODR is set from DT only.

Signed-off-by: Armando Visconti <armando.visconti@st.com>
(cherry picked from commit 0d38a88666)
2025-07-30 11:05:12 -05:00
IBEN EL HADJ MESSAOUD Marwa
183444eed4 drivers: usb: udc: prevent USB clock disable in sleep mode
Prevent disabling OTG HS and USBPHY clocks
during sleep on STM32U5 series

Disabling these clocks during sleep mode
was causing USB device initialization issues

Signed-off-by: IBEN EL HADJ MESSAOUD Marwa <marwa.ibenelhadjmessaoud-ext@st.com>
(cherry picked from commit 8b355e9306)
2025-07-29 12:23:36 -07:00
IBEN EL HADJ MESSAOUD Marwa
e2efcf7cb6 drivers: usb: device: prevent USB clock disable in sleep mode
Prevent disabling OTG HS and USBPHY clocks
during sleep on STM32U5 series

Disabling these clocks during sleep mode
was causing USB device initialization issues

Signed-off-by: IBEN EL HADJ MESSAOUD Marwa <marwa.ibenelhadjmessaoud-ext@st.com>
(cherry picked from commit d4b2808b68)
2025-07-29 12:23:36 -07:00
Luis Ubieda
a494c09fcb i3c: stm32: Prevent mutex deadlock on DAA failure
Make sure this function always unlocks bus_mutex.

Signed-off-by: Luis Ubieda <luisf@croxel.com>
(cherry picked from commit ef41627f81)
2025-07-29 12:23:20 -07:00
Martin Stumpf
fb8687a492 spi_nxp_lpspi: Fix underflow in lpspi sck calculation
If `desired_delay_ns` is `0`, it is much saner to set the delay to `0x00`
than to underflow and set it to `0xff`, which is the current behavior.

Signed-off-by: Martin Stumpf <finomnis@gmail.com>
(cherry picked from commit 860f9c8ef5)
2025-07-29 12:51:34 -05:00
Tomislav Milkovic
7abcf05115 doc: connectivity: networking: api: tftp: Fix Kconfig option
Instead of CONFIG_MQTT_SN_LIB, correct Kconfig option to
enable TFTP client library is CONFIG_TFTP_LIB

Signed-off-by: Tomislav Milkovic <tomislav.milkovic95@gmail.com>
(cherry picked from commit 5410f74664)
2025-07-29 12:50:31 -05:00
Bjarki Arge Andreasen
2ff7f15e5f drivers: can: nrf: fix invalid pointer leading to undef behavior
The can_nrf device driver incorrectly passes its own device
driver pointer to a call to clock_control_get_rate() to get the
rate of the auxpll. The actual device driver which should be passed
to clock_control_get_rate() is the auxpll.

Without this fix, the call jumps to the can_nrf_api and returns
garbage (unfortunately it does not hardfault, which is why this
issue has not been discovered yet).

Signed-off-by: Bjarki Arge Andreasen <bjarki.andreasen@nordicsemi.no>
(cherry picked from commit f5ee52ecf3)
2025-07-29 12:43:56 -05:00
Axel Utech
d1f998909d dts: arm: st: u0: fix lpuart1/2 interrupts
Interrupt vectors for lpuart1 and lpuart2 are swapped according to the
reference manual RM0503 table 54.
Fixes the usage of the interrupt-driven uart API.

Signed-off-by: Axel Utech <utech@sofiha.de>
(cherry picked from commit 4664f600d6)
2025-07-27 12:09:37 -07:00
Benjamin Cabé
a9f222b9a7 boards: arduino: nicla_vision: fix VL53L1X I2C address
Nicla Vision datasheet is referring to the 8-bit wire address (0x52) for
the VL53L1X sensor, so that's likely what ended up being used in the
board's devicetree. However, it's the 7-bit I2C address that should be
used so fix that by changing the I2C address to 0x29. Successfully
tested on actual hardware.

Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
(cherry picked from commit a663b2b374)
2025-07-27 10:58:16 -07:00
Florian La Roche
58be950216 net: sockets: add missing break
Add a missing break to socket handling.

Signed-off-by: Florian La Roche <Florian.LaRoche@gmail.com>
(cherry picked from commit d933e0301e)
2025-07-27 10:56:20 -07:00
Pieter De Gendt
02f511bb93 doc: release: 4.2: Fix entry in new APIs
Add a missing newline to fix the formatting of the LoRaWAN entry.

Signed-off-by: Pieter De Gendt <pieter.degendt@basalte.be>
(cherry picked from commit 4867d45647)
2025-07-27 10:56:05 -07:00
124 changed files with 2197 additions and 826 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1 +1 @@
0.17.2
0.17.4

View File

@@ -1,5 +1,5 @@
VERSION_MAJOR = 4
VERSION_MINOR = 2
PATCHLEVEL = 0
PATCHLEVEL = 1
VERSION_TWEAK = 0
EXTRAVERSION =

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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";
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -42,7 +42,7 @@
};
};
i2c3: i2c@4007800 {
i2c3: i2c@40007800 {
compatible = "st,stm32-i2c-v2";
clock-frequency = <I2C_BITRATE_STANDARD>;
#address-cells = <1>;

View File

@@ -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";
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -77,6 +77,7 @@
#ifdef CONFIG_NOCACHE_MEMORY
#define _NOCACHE_SECTION_NAME nocache
#define _NOCACHE_LOAD_SECTION_NAME nocache_load
#endif
/* Symbol table section */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
CONFIG_MAIN_STACK_SIZE=4096
CONFIG_MAIN_STACK_SIZE=6144
CONFIG_LOG=y
CONFIG_SHELL=y

View File

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

View File

@@ -10,6 +10,9 @@ config NUM_IRQS
if BT
config SYSTEM_WORKQUEUE_STACK_SIZE
default 1152
config BT_AUTO_PHY_UPDATE
default n

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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