Compare commits

...

59 Commits

Author SHA1 Message Date
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
82 changed files with 1284 additions and 475 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

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

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

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

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

@@ -560,7 +560,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 +630,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

@@ -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
*
@@ -308,9 +309,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 +328,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 +339,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 +347,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,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

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

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

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

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

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;

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

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

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

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

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

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

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

@@ -0,0 +1,8 @@
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(arm_user_stack_test)
target_sources(app PRIVATE src/main.c)

View File

@@ -0,0 +1 @@
CONFIG_ARM_MPU=y

View File

@@ -0,0 +1 @@
CONFIG_ARM_MPU=y

View File

@@ -0,0 +1 @@
CONFIG_ZTEST=y

View File

@@ -0,0 +1,104 @@
/*
* Copyright The Zephyr Project Contributors
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifdef CONFIG_FPU_SHARING
#include <math.h>
#endif
#include <zephyr/ztest.h>
#include <zephyr/ztest_error_hook.h>
#include <zephyr/syscall_list.h>
struct k_thread th0, th1;
K_THREAD_STACK_DEFINE(stk0, 2048);
K_THREAD_STACK_DEFINE(stk1, 2048);
ZTEST_BMEM int attack_stack[128];
ZTEST_BMEM uint64_t sys_ret; /* 64 syscalls take result address in r0 */
volatile int kernel_secret;
volatile int *const attack_sp = &attack_stack[128];
const int sysno = K_SYSCALL_K_UPTIME_TICKS;
k_tid_t low_tid, hi_tid;
void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *pEsf)
{
ztest_test_pass();
k_thread_abort(low_tid);
/* This check is to handle a case where low prio thread has started and
* resulted in a fault while changing the sp but
* the high prio thread is not created yet
*/
if (hi_tid) {
k_thread_abort(hi_tid);
}
}
void attack_entry(void)
{
printf("Call %s from %s\n", __func__, k_is_user_context() ? "user" : "kernel");
/* kernel_secret can only be updated in privilege mode so updating it here should result in
* a fault. If it doesn't we fail the test.
*/
kernel_secret = 1;
printf("Changed the kernel_secret so marking test as failed\n");
ztest_test_fail();
k_thread_abort(low_tid);
k_thread_abort(hi_tid);
}
void low_fn(void *arg1, void *arg2, void *arg3)
{
#ifdef CONFIG_FPU_SHARING
double x = 1.2345;
double y = 6.789;
/* some random fp stuff so that an extended stack frame is saved on svc */
zassert_equal(x, 1.2345);
zassert_equal(y, 6.789);
#endif
printf("Call %s from %s\n", __func__, k_is_user_context() ? "user" : "kernel");
attack_stack[0] = 1;
__asm__ volatile("mov sp, %0;"
"1:;"
"ldr r0, =sys_ret;"
"ldr r6, =sysno;"
"ldr r6, [r6];"
"svc 3;"
"b 1b;" ::"r"(attack_sp));
}
void hi_fn(void *arg1, void *arg2, void *arg3)
{
printf("Call %s from %s\n", __func__, k_is_user_context() ? "user" : "kernel");
while (1) {
attack_sp[-2] = (int)attack_entry;
k_msleep(1);
}
}
ZTEST(arm_user_stack_test, test_arm_user_stack_corruption)
{
low_tid = k_thread_create(&th0, stk0, K_THREAD_STACK_SIZEOF(stk0), low_fn, NULL, NULL, NULL,
2,
#ifdef CONFIG_FPU_SHARING
K_INHERIT_PERMS | K_USER | K_FP_REGS,
#else
K_INHERIT_PERMS | K_USER,
#endif
K_NO_WAIT);
k_msleep(6); /* let low_fn start looping */
hi_tid = k_thread_create(&th1, stk1, K_THREAD_STACK_SIZEOF(stk1), hi_fn, NULL, NULL, NULL,
1, K_INHERIT_PERMS | K_USER, K_NO_WAIT);
k_thread_join(&th0, K_FOREVER);
k_thread_join(&th1, K_FOREVER);
}
ZTEST_SUITE(arm_user_stack_test, NULL, NULL, NULL, NULL, NULL);

View File

@@ -0,0 +1,14 @@
common:
tags:
- arm
tests:
arch.arm.user.stack:
filter: CONFIG_CPU_CORTEX_M
extra_configs:
- CONFIG_USERSPACE=y
arch.arm.user.stack.float:
filter: CONFIG_CPU_CORTEX_M and CONFIG_CPU_HAS_FPU
extra_configs:
- CONFIG_USERSPACE=y
- CONFIG_FPU=y
- CONFIG_FPU_SHARING=y

View File

@@ -11,7 +11,7 @@
slow@0 {
compatible = "test-spi-loopback-slow";
reg = <0>;
spi-max-frequency = <128000>;
spi-max-frequency = <150000>;
};
fast@0 {
compatible = "test-spi-loopback-fast";

View File

@@ -11,7 +11,7 @@
slow@0 {
compatible = "test-spi-loopback-slow";
reg = <0>;
spi-max-frequency = <128000>;
spi-max-frequency = <125000>;
};
fast@0 {
compatible = "test-spi-loopback-fast";

View File

@@ -11,7 +11,7 @@
slow@0 {
compatible = "test-spi-loopback-slow";
reg = <0>;
spi-max-frequency = <128000>;
spi-max-frequency = <125000>;
};
fast@0 {
compatible = "test-spi-loopback-fast";

View File

@@ -11,7 +11,7 @@
slow@0 {
compatible = "test-spi-loopback-slow";
reg = <0>;
spi-max-frequency = <128000>;
spi-max-frequency = <125000>;
};
fast@0 {
compatible = "test-spi-loopback-fast";

View File

@@ -2349,7 +2349,7 @@ ZTEST(net_socket_tcp, test_connect_and_wait_for_v4_poll)
zassert_equal(ret, 0, "close failed, %d", errno);
}
ZTEST(net_socket_tcp, test_so_keepalive)
ZTEST(net_socket_tcp, test_so_keepalive_opt)
{
struct sockaddr_in bind_addr4;
int sock, ret;
@@ -2430,55 +2430,92 @@ ZTEST(net_socket_tcp, test_so_keepalive)
test_context_cleanup();
}
ZTEST(net_socket_tcp, test_keepalive_timeout)
static void test_prepare_keepalive_socks(int *c_sock, int *s_sock, int *new_sock)
{
struct sockaddr_in c_saddr, s_saddr;
int c_sock, s_sock, new_sock;
uint8_t rx_buf;
int optval;
int ret;
prepare_sock_tcp_v4(MY_IPV4_ADDR, ANY_PORT, &c_sock, &c_saddr);
prepare_sock_tcp_v4(MY_IPV4_ADDR, SERVER_PORT, &s_sock, &s_saddr);
prepare_sock_tcp_v4(MY_IPV4_ADDR, ANY_PORT, c_sock, &c_saddr);
prepare_sock_tcp_v4(MY_IPV4_ADDR, SERVER_PORT, s_sock, &s_saddr);
/* Enable keep-alive on both ends and set timeouts/retries to minimum */
optval = 1;
ret = zsock_setsockopt(c_sock, SOL_SOCKET, SO_KEEPALIVE,
ret = zsock_setsockopt(*c_sock, SOL_SOCKET, SO_KEEPALIVE,
&optval, sizeof(optval));
zassert_equal(ret, 0, "setsockopt failed (%d)", errno);
ret = zsock_setsockopt(s_sock, SOL_SOCKET, SO_KEEPALIVE,
ret = zsock_setsockopt(*s_sock, SOL_SOCKET, SO_KEEPALIVE,
&optval, sizeof(optval));
zassert_equal(ret, 0, "setsockopt failed (%d)", errno);
optval = 1;
ret = zsock_setsockopt(c_sock, IPPROTO_TCP, TCP_KEEPIDLE,
ret = zsock_setsockopt(*c_sock, IPPROTO_TCP, TCP_KEEPIDLE,
&optval, sizeof(optval));
zassert_equal(ret, 0, "setsockopt failed (%d)", errno);
ret = zsock_setsockopt(s_sock, IPPROTO_TCP, TCP_KEEPIDLE,
ret = zsock_setsockopt(*s_sock, IPPROTO_TCP, TCP_KEEPIDLE,
&optval, sizeof(optval));
zassert_equal(ret, 0, "setsockopt failed (%d)", errno);
optval = 1;
ret = zsock_setsockopt(c_sock, IPPROTO_TCP, TCP_KEEPINTVL,
ret = zsock_setsockopt(*c_sock, IPPROTO_TCP, TCP_KEEPINTVL,
&optval, sizeof(optval));
zassert_equal(ret, 0, "setsockopt failed (%d)", errno);
ret = zsock_setsockopt(s_sock, IPPROTO_TCP, TCP_KEEPINTVL,
ret = zsock_setsockopt(*s_sock, IPPROTO_TCP, TCP_KEEPINTVL,
&optval, sizeof(optval));
zassert_equal(ret, 0, "setsockopt failed (%d)", errno);
optval = 1;
ret = zsock_setsockopt(c_sock, IPPROTO_TCP, TCP_KEEPCNT,
ret = zsock_setsockopt(*c_sock, IPPROTO_TCP, TCP_KEEPCNT,
&optval, sizeof(optval));
zassert_equal(ret, 0, "setsockopt failed (%d)", errno);
ret = zsock_setsockopt(s_sock, IPPROTO_TCP, TCP_KEEPCNT,
ret = zsock_setsockopt(*s_sock, IPPROTO_TCP, TCP_KEEPCNT,
&optval, sizeof(optval));
zassert_equal(ret, 0, "setsockopt failed (%d)", errno);
/* Establish connection */
test_bind(s_sock, (struct sockaddr *)&s_saddr, sizeof(s_saddr));
test_listen(s_sock);
test_connect(c_sock, (struct sockaddr *)&s_saddr, sizeof(s_saddr));
test_accept(s_sock, &new_sock, NULL, NULL);
test_bind(*s_sock, (struct sockaddr *)&s_saddr, sizeof(s_saddr));
test_listen(*s_sock);
test_connect(*c_sock, (struct sockaddr *)&s_saddr, sizeof(s_saddr));
test_accept(*s_sock, new_sock, NULL, NULL);
}
ZTEST(net_socket_tcp, test_keepalive)
{
int c_sock, s_sock, new_sock;
struct timeval optval = {
.tv_sec = 2,
.tv_usec = 500000,
};
uint8_t rx_buf;
int ret;
test_prepare_keepalive_socks(&c_sock, &s_sock, &new_sock);
ret = zsock_setsockopt(c_sock, SOL_SOCKET, SO_RCVTIMEO, &optval,
sizeof(optval));
zassert_equal(ret, 0, "setsockopt failed (%d)", errno);
/* recv() should fail, but due to receive timeout (no data), not
* connection timeout (keepalive).
*/
ret = zsock_recv(c_sock, &rx_buf, sizeof(rx_buf), 0);
zassert_equal(ret, -1, "recv() should've failed");
zassert_equal(errno, EAGAIN, "wrong errno value, %d", errno);
test_close(c_sock);
test_close(new_sock);
test_close(s_sock);
test_context_cleanup();
}
ZTEST(net_socket_tcp, test_keepalive_timeout)
{
int c_sock, s_sock, new_sock;
uint8_t rx_buf;
int ret;
test_prepare_keepalive_socks(&c_sock, &s_sock, &new_sock);
/* Kill communication - expect that connection will be closed after
* a timeout period.

View File

@@ -116,6 +116,7 @@ static enum test_case_no {
TEST_CLIENT_FIN_ACK_WITH_DATA = 18,
TEST_CLIENT_SEQ_VALIDATION = 19,
TEST_SERVER_ACK_VALIDATION = 20,
TEST_SERVER_FIN_ACK_AFTER_DATA = 21,
} test_case_no;
static enum test_state t_state;
@@ -142,6 +143,7 @@ static void handle_syn_invalid_ack(sa_family_t af, struct tcphdr *th);
static void handle_client_fin_ack_with_data_test(sa_family_t af, struct tcphdr *th);
static void handle_client_seq_validation_test(sa_family_t af, struct tcphdr *th);
static void handle_server_ack_validation_test(struct net_pkt *pkt);
static void handle_server_fin_ack_after_data_test(sa_family_t af, struct tcphdr *th);
static void verify_flags(struct tcphdr *th, uint8_t flags,
const char *fun, int line)
@@ -494,6 +496,9 @@ static int tester_send(const struct device *dev, struct net_pkt *pkt)
case TEST_SERVER_ACK_VALIDATION:
handle_server_ack_validation_test(pkt);
break;
case TEST_SERVER_FIN_ACK_AFTER_DATA:
handle_server_fin_ack_after_data_test(net_pkt_family(pkt), &th);
break;
default:
zassert_true(false, "Undefined test case");
}
@@ -3002,4 +3007,204 @@ ZTEST(net_tcp, test_server_ack_validation)
net_context_put(accepted_ctx);
}
#define TEST_FIN_ACK_AFTER_DATA_REQ "request"
#define TEST_FIN_ACK_AFTER_DATA_RSP "test data response"
/* In this test we check that FIN,ACK packet acknowledging latest data is
* handled correctly by the TCP stack.
*/
static void handle_server_fin_ack_after_data_test(sa_family_t af, struct tcphdr *th)
{
struct net_pkt *reply = NULL;
zassert_false(th == NULL && t_state != T_SYN,
"NULL pkt only expected in T_SYN state");
switch (t_state) {
case T_SYN:
reply = prepare_syn_packet(af, htons(MY_PORT), htons(PEER_PORT));
seq++;
t_state = T_SYN_ACK;
break;
case T_SYN_ACK:
test_verify_flags(th, SYN | ACK);
zassert_equal(ntohl(th->th_ack), seq,
"Unexpected ACK in T_SYN_ACK, got %d, expected %d",
ntohl(th->th_ack), seq);
device_initial_seq = ntohl(th->th_seq);
ack = ntohl(th->th_seq) + 1U;
t_state = T_DATA_ACK;
/* Dummy "request" packet */
reply = prepare_data_packet(af, htons(MY_PORT), htons(PEER_PORT),
TEST_FIN_ACK_AFTER_DATA_REQ,
sizeof(TEST_FIN_ACK_AFTER_DATA_REQ) - 1);
seq += sizeof(TEST_FIN_ACK_AFTER_DATA_REQ) - 1;
break;
case T_DATA_ACK:
test_verify_flags(th, ACK);
t_state = T_DATA;
zassert_equal(ntohl(th->th_seq), ack,
"Unexpected SEQ in T_DATA_ACK, got %d, expected %d",
get_rel_seq(th), ack);
zassert_equal(ntohl(th->th_ack), seq,
"Unexpected ACK in T_DATA_ACK, got %d, expected %d",
ntohl(th->th_ack), seq);
break;
case T_DATA:
test_verify_flags(th, PSH | ACK);
zassert_equal(ntohl(th->th_seq), ack,
"Unexpected SEQ in T_DATA, got %d, expected %d",
get_rel_seq(th), ack);
zassert_equal(ntohl(th->th_ack), seq,
"Unexpected ACK in T_DATA, got %d, expected %d",
ntohl(th->th_ack), seq);
ack += sizeof(TEST_FIN_ACK_AFTER_DATA_RSP) - 1;
t_state = T_FIN_ACK;
reply = prepare_fin_ack_packet(af, htons(MY_PORT), htons(PEER_PORT));
seq++;
break;
case T_FIN_ACK:
test_verify_flags(th, FIN | ACK);
zassert_equal(ntohl(th->th_seq), ack,
"Unexpected SEQ in T_FIN_ACK, got %d, expected %d",
get_rel_seq(th), ack);
zassert_equal(ntohl(th->th_ack), seq,
"Unexpected ACK in T_FIN_ACK, got %d, expected %d",
ntohl(th->th_ack), seq);
ack++;
t_state = T_CLOSING;
reply = prepare_ack_packet(af, htons(MY_PORT), htons(PEER_PORT));
seq++;
break;
case T_CLOSING:
zassert_true(false, "Should not receive anything after final ACK");
break;
default:
zassert_true(false, "%s unexpected state", __func__);
return;
}
if (reply != NULL) {
zassert_ok(net_recv_data(net_iface, reply), "%s failed", __func__);
}
}
/* Receive callback to be installed in the accept handler */
static void test_fin_ack_after_data_recv_cb(struct net_context *context,
struct net_pkt *pkt,
union net_ip_header *ip_hdr,
union net_proto_header *proto_hdr,
int status,
void *user_data)
{
zassert_ok(status, "failed to recv the data");
if (pkt != NULL) {
uint8_t buf[sizeof(TEST_FIN_ACK_AFTER_DATA_REQ)] = { 0 };
int data_len = net_pkt_remaining_data(pkt);
zassert_equal(data_len, sizeof(TEST_FIN_ACK_AFTER_DATA_REQ) - 1,
"Invalid packet length, %d", data_len);
zassert_ok(net_pkt_read(pkt, buf, data_len));
zassert_mem_equal(buf, TEST_FIN_ACK_AFTER_DATA_REQ, data_len);
net_pkt_unref(pkt);
}
test_sem_give();
}
static void test_fin_ack_after_data_accept_cb(struct net_context *ctx,
struct sockaddr *addr,
socklen_t addrlen,
int status,
void *user_data)
{
int ret;
zassert_ok(status, "failed to accept the conn");
/* set callback on newly created context */
accepted_ctx = ctx;
ret = net_context_recv(ctx, test_fin_ack_after_data_recv_cb,
K_NO_WAIT, NULL);
zassert_ok(ret, "Failed to recv data from peer");
/* Ref the context on the app behalf. */
net_context_ref(ctx);
}
/* Verify that the TCP stack replies with a valid FIN,ACK after the peer
* acknowledges the latest data in the FIN packet.
* Test case scenario IPv4
* send SYN,
* expect SYN ACK,
* send ACK with Data,
* expect ACK,
* expect Data,
* send FIN,ACK
* expect FIN,ACK
* send ACK
* any failures cause test case to fail.
*/
ZTEST(net_tcp, test_server_fin_ack_after_data)
{
struct net_context *ctx;
int ret;
test_case_no = TEST_SERVER_FIN_ACK_AFTER_DATA;
t_state = T_SYN;
seq = ack = 0;
ret = net_context_get(AF_INET, SOCK_STREAM, IPPROTO_TCP, &ctx);
zassert_ok(ret, "Failed to get net_context");
net_context_ref(ctx);
ret = net_context_bind(ctx, (struct sockaddr *)&my_addr_s,
sizeof(struct sockaddr_in));
zassert_ok(ret, "Failed to bind net_context");
/* Put context into listening mode and install accept cb */
ret = net_context_listen(ctx, 1);
zassert_ok(ret, "Failed to listen on net_context");
ret = net_context_accept(ctx, test_fin_ack_after_data_accept_cb,
K_NO_WAIT, NULL);
zassert_ok(ret, "Failed to set accept on net_context");
/* Trigger the peer to send SYN */
handle_server_fin_ack_after_data_test(AF_INET, NULL);
/* test_fin_ack_after_data_recv_cb will release the semaphore after
* dummy request is read.
*/
test_sem_take(K_MSEC(100), __LINE__);
/* Send dummy "response" */
ret = net_context_send(accepted_ctx, TEST_FIN_ACK_AFTER_DATA_RSP,
sizeof(TEST_FIN_ACK_AFTER_DATA_RSP) - 1, NULL,
K_NO_WAIT, NULL);
zassert_equal(ret, sizeof(TEST_FIN_ACK_AFTER_DATA_RSP) - 1,
"Failed to send data to peer %d", ret);
/* test_fin_ack_after_data_recv_cb will release the semaphore after
* the connection is marked closed.
*/
test_sem_take(K_MSEC(100), __LINE__);
net_context_put(ctx);
net_context_put(accepted_ctx);
/* Connection is in TIME_WAIT state, context will be released
* after K_MSEC(CONFIG_NET_TCP_TIME_WAIT_DELAY), so wait for it.
*/
k_sleep(K_MSEC(CONFIG_NET_TCP_TIME_WAIT_DELAY));
}
ZTEST_SUITE(net_tcp, NULL, presetup, NULL, NULL, NULL);

View File

@@ -4,7 +4,6 @@ CONFIG_LOG=y
CONFIG_LLEXT=y
CONFIG_LLEXT_HEAP_SIZE=64
CONFIG_LLEXT_EXPORT_DEVICES=y
CONFIG_LLEXT_LOG_LEVEL_DBG=y
CONFIG_APPLICATION_DEFINED_SYSCALL=y

View File

@@ -343,7 +343,7 @@ manifest:
- debug
- name: picolibc
path: modules/lib/picolibc
revision: 560946f26db075c296beea5b39d99e6de43c9010
revision: ca8b6ebba5226a75545e57a140443168a26ba664
- name: segger
revision: cf56b1d9c80f81a26e2ac5727c9cf177116a4692
path: modules/debug/segger