diff --git a/samples/boards/nordic/spis_wakeup/CMakeLists.txt b/samples/boards/nordic/spis_wakeup/CMakeLists.txt new file mode 100644 index 00000000000..db945ce39f5 --- /dev/null +++ b/samples/boards/nordic/spis_wakeup/CMakeLists.txt @@ -0,0 +1,18 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 +# + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +if(NOT SYSBUILD) + message(FATAL_ERROR + " This is a multi-image application that should be built using sysbuild.\n" + " Add --sysbuild argument to west build command to prepare all the images.") +endif() + +project(spis_wakeup) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/boards/nordic/spis_wakeup/README.rst b/samples/boards/nordic/spis_wakeup/README.rst new file mode 100644 index 00000000000..a008f89918f --- /dev/null +++ b/samples/boards/nordic/spis_wakeup/README.rst @@ -0,0 +1,73 @@ +.. zephyr:code-sample:: spis-wakeup + :name: SPIS wake up + :relevant-api: spi_interface + + Reduce current consumption by handling the wake line while using an SPIS. + +Overview +******** + +Sample showing how to use the additional wake line in nrf-spis driver. The application, configured +as a SPIS, is put to sleep while waiting for an SPI transmission. An external device (other core in +this sample) working as a SPIM and also handling the wake line wakes the application up just before +the transmission starts. To simulate two separate devices the Nordic Semiconductor nRF54H20 DK has +been used and SPIS / SPIM drivers are controlled by two independent cores: + +- nrf54h20dk/nrf54h20/cpuapp works as a SPIS controller device +- nrf54h20dk/nrf54h20/cpurad works as a SPIM controller device + + +Requirements +************ + +This sample can be run on multicore SoCs like nRF54H20 and requires additional wiring as below. + +Wiring +****** + +Wires (jumpers) for connecting SPIS and SPIM devices are needed: + +- SPIS WAKE <-> WAKE SPIM +- SPIS CS <-----> CS SPIM +- SPIS SCK <---> SCK SPIM +- SPIS MOSI <-> MOSI SPIM +- SPIS MISO <-> MISO SPIM + +Building and Running +******************** + +The code can be found in :zephyr_file:`samples/boards/nordic/spis_wakeup`. + +To build and flash the application: + +.. zephyr-app-commands:: + :zephyr-app: samples/boards/nordic/spis_wakeup + :board: nrf54h20dk/nrf54h20/cpuapp + :goals: build flash + :compact: + +Sample Output +============= + +nrf54h20/cpuapp: + +.. code-block:: console + + [00:00:00.272,217] spi_wakeup: Hello world from nrf54h20dk@0.9.0/nrf54h20/cpuapp + [00:00:00.272,241] spi_wakeup: SPIS: waiting for SPI transfer; going to sleep... + [00:00:02.274,192] spi_wakeup: SPIS: woken up by nrf54h20/cpurad + [00:00:02.274,215] spi_wakeup: SPIS: will be active for 500ms after transfer + +nrf54h20/cpurad: + +.. code-block:: console + + [00:00:00.272,195] spi_wakeup: Hello world from nrf54h20dk@0.9.0/nrf54h20/cpurad + [00:00:00.272,219] spi_wakeup: SPIM: going to sleep for 1.5s... + [00:00:01.772,352] spi_wakeup: SPIM: will be active for 500ms before transfer + [00:00:02.273,456] spi_wakeup: SPIM: transferring the CONFIG_BOARD_QUALIFIERS: 'nrf54h20/cpurad' + +References +********** + +:zephyr_file:`dts/bindings/spi/nordic,nrf-spi-common.yaml` diff --git a/samples/boards/nordic/spis_wakeup/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/samples/boards/nordic/spis_wakeup/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 00000000000..40b2ae3d64b --- /dev/null +++ b/samples/boards/nordic/spis_wakeup/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + led = &led0; + spis = &spi130; + /delete-property/ led1; + /delete-property/ sw0; + /delete-property/ sw1; + /delete-property/ sw2; + /delete-property/ sw3; + }; + /delete-node/ buttons; +}; + +/delete-node/ &led1; + +&exmif { + status = "disabled"; +}; + +&gpiote130 { + status = "okay"; + owned-channels = <0>; +}; + +&pinctrl { + spi130_default_alt: spi130_default_alt { + group1 { + psels = , + , + , + ; + }; + }; + + spi130_sleep_alt: spi130_sleep_alt { + group1 { + psels = , + , + , + ; + low-power-enable; + }; + }; +}; + +&spi130 { + compatible = "nordic,nrf-spis"; + status = "okay"; + def-char = <0x00>; + pinctrl-0 = <&spi130_default_alt>; + pinctrl-1 = <&spi130_sleep_alt>; + pinctrl-names = "default", "sleep"; + wake-gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>; + memory-regions = <&cpuapp_dma_region>; + /delete-property/rx-delay-supported; + /delete-property/rx-delay; +}; + +&uart136 { + zephyr,pm-device-runtime-auto; +}; diff --git a/samples/boards/nordic/spis_wakeup/prj.conf b/samples/boards/nordic/spis_wakeup/prj.conf new file mode 100644 index 00000000000..ca92fc6de6a --- /dev/null +++ b/samples/boards/nordic/spis_wakeup/prj.conf @@ -0,0 +1,13 @@ +CONFIG_SPI=y +CONFIG_SPI_SLAVE=y +CONFIG_GPIO=y + +CONFIG_PM=y +CONFIG_PM_S2RAM=y +CONFIG_PM_S2RAM_CUSTOM_MARKING=y +CONFIG_PM_DEVICE=y +CONFIG_PM_DEVICE_RUNTIME=y + +CONFIG_ASSERT=y + +CONFIG_LOG=y diff --git a/samples/boards/nordic/spis_wakeup/sample.yaml b/samples/boards/nordic/spis_wakeup/sample.yaml new file mode 100644 index 00000000000..7bc97eedcb9 --- /dev/null +++ b/samples/boards/nordic/spis_wakeup/sample.yaml @@ -0,0 +1,22 @@ +common: + sysbuild: true + depends_on: spi + +sample: + name: SPI wakeup sample +tests: + sample.drivers.spis.wakeup: + tags: + - spi + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + integration_platforms: + - nrf54h20dk/nrf54h20/cpuapp + harness: console + harness_config: + fixture: spi_loopback + type: multi_line + ordered: true + regex: + - ".*SPIS: waiting for SPI transfer" + - ".*SPIS: woken up by" diff --git a/samples/boards/nordic/spis_wakeup/src/main.c b/samples/boards/nordic/spis_wakeup/src/main.c new file mode 100644 index 00000000000..a3a6c8f3eda --- /dev/null +++ b/samples/boards/nordic/spis_wakeup/src/main.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#define BUF_SIZE 32 +static const struct device *spis_dev = DEVICE_DT_GET(DT_ALIAS(spis)); +static const struct spi_config spis_config = {.operation = SPI_OP_MODE_SLAVE | SPI_WORD_SET(8)}; + +static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(DT_ALIAS(led), gpios); + +LOG_MODULE_REGISTER(spi_wakeup); + +int main(void) +{ + bool status; + static char rx_buffer[BUF_SIZE]; + struct spi_buf rx_spi_bufs = {.buf = rx_buffer, .len = sizeof(rx_buffer)}; + struct spi_buf_set rx_spi_buf_set = {.buffers = &rx_spi_bufs, .count = 1}; + + LOG_INF("Hello world from %s", CONFIG_BOARD_TARGET); + + status = gpio_is_ready_dt(&led); + __ASSERT(status, "Error: GPIO Device not ready"); + + status = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE); + __ASSERT(status == 0, "Could not configure led GPIO"); + + status = device_is_ready(spis_dev); + __ASSERT(status, "Error: SPI device is not ready"); + + while (1) { + memset(rx_buffer, 0x00, sizeof(rx_buffer)); + LOG_INF("SPIS: waiting for SPI transfer; going to sleep..."); + gpio_pin_set_dt(&led, 0); + spi_read(spis_dev, &spis_config, &rx_spi_buf_set); + gpio_pin_set_dt(&led, 1); + LOG_INF("SPIS: woken up by %s", rx_buffer); + LOG_INF("SPIS: will be active for 500ms after transfer"); + k_busy_wait(500000); + } + + return 0; +} diff --git a/samples/boards/nordic/spis_wakeup/sysbuild.cmake b/samples/boards/nordic/spis_wakeup/sysbuild.cmake new file mode 100644 index 00000000000..bbd350fbe63 --- /dev/null +++ b/samples/boards/nordic/spis_wakeup/sysbuild.cmake @@ -0,0 +1,14 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 +# + +if(SB_CONFIG_SOC_NRF54H20) + # Add remote project + ExternalZephyrProject_Add( + APPLICATION wakeup_trigger + SOURCE_DIR ${APP_DIR}/wakeup_trigger + BOARD ${SB_CONFIG_BOARD}/${SB_CONFIG_SOC}/cpurad + BOARD_REVISION ${BOARD_REVISION} + ) +endif() diff --git a/samples/boards/nordic/spis_wakeup/wakeup_trigger/CMakeLists.txt b/samples/boards/nordic/spis_wakeup/wakeup_trigger/CMakeLists.txt new file mode 100644 index 00000000000..ab604e084ef --- /dev/null +++ b/samples/boards/nordic/spis_wakeup/wakeup_trigger/CMakeLists.txt @@ -0,0 +1,12 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 +# + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(wakeup_trigger) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/boards/nordic/spis_wakeup/wakeup_trigger/boards/nrf54h20dk_nrf54h20_cpurad.overlay b/samples/boards/nordic/spis_wakeup/wakeup_trigger/boards/nrf54h20dk_nrf54h20_cpurad.overlay new file mode 100644 index 00000000000..c54fb28742e --- /dev/null +++ b/samples/boards/nordic/spis_wakeup/wakeup_trigger/boards/nrf54h20dk_nrf54h20_cpurad.overlay @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + led = &led1; + }; + + leds { + compatible = "gpio-leds"; + led1: led_1 { + gpios = <&gpio9 1 GPIO_ACTIVE_HIGH>; + label = "Green LED 1"; + }; + }; +}; + +&gpiote130 { + status = "okay"; + owned-channels = <1>; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio9 { + status = "okay"; +}; + +&pinctrl { + spi131_default_alt: spi131_default_alt { + group1 { + psels = , + , + ; + }; + }; + + spi131_sleep_alt: spi131_sleep_alt { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; +}; + +&spi131 { + compatible = "nordic,nrf-spim"; + status = "okay"; + pinctrl-0 = <&spi131_default_alt>; + pinctrl-1 = <&spi131_sleep_alt>; + pinctrl-names = "default", "sleep"; + overrun-character = <0x00>; + cs-gpios = <&gpio0 11 GPIO_ACTIVE_LOW>; + wake-gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>; + zephyr,pm-device-runtime-auto; + memory-regions = <&cpurad_dma_region>; + spim_dt: spi-device@0 { + compatible = "vnd,spi-device"; + reg = <0>; + spi-max-frequency = ; + }; +}; + +&uart135 { + zephyr,pm-device-runtime-auto; +}; diff --git a/samples/boards/nordic/spis_wakeup/wakeup_trigger/prj.conf b/samples/boards/nordic/spis_wakeup/wakeup_trigger/prj.conf new file mode 100644 index 00000000000..1de6459a608 --- /dev/null +++ b/samples/boards/nordic/spis_wakeup/wakeup_trigger/prj.conf @@ -0,0 +1,13 @@ +CONFIG_SPI=y +CONFIG_SPI_NRFX_WAKE_TIMEOUT_US=500 +CONFIG_GPIO=y + +CONFIG_PM=y +CONFIG_PM_S2RAM=y +CONFIG_PM_S2RAM_CUSTOM_MARKING=y +CONFIG_PM_DEVICE=y +CONFIG_PM_DEVICE_RUNTIME=y + +CONFIG_ASSERT=y + +CONFIG_LOG=y diff --git a/samples/boards/nordic/spis_wakeup/wakeup_trigger/src/main.c b/samples/boards/nordic/spis_wakeup/wakeup_trigger/src/main.c new file mode 100644 index 00000000000..6668dc11d9e --- /dev/null +++ b/samples/boards/nordic/spis_wakeup/wakeup_trigger/src/main.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#define SPI_MODE (SPI_OP_MODE_MASTER | SPI_WORD_SET(8)) +static const struct spi_dt_spec spim = SPI_DT_SPEC_GET(DT_NODELABEL(spim_dt), SPI_MODE, 0); + +static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(DT_ALIAS(led), gpios); + +LOG_MODULE_REGISTER(spi_wakeup); + +int main(void) +{ + bool status; + static char tx_buffer[] = CONFIG_BOARD_QUALIFIERS; + struct spi_buf tx_spi_bufs = {.buf = tx_buffer, .len = sizeof(tx_buffer)}; + struct spi_buf_set tx_spi_buf_set = {.buffers = &tx_spi_bufs, .count = 1}; + + LOG_INF("Hello world from %s", CONFIG_BOARD_TARGET); + + status = gpio_is_ready_dt(&led); + __ASSERT(status, "Error: GPIO Device not ready"); + + status = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE); + __ASSERT(status == 0, "Could not configure led GPIO"); + + status = spi_is_ready_dt(&spim); + __ASSERT(status, "Error: SPI device is not ready"); + + while (1) { + LOG_INF("SPIM: going to sleep for 1.5s..."); + gpio_pin_set_dt(&led, 0); + k_msleep(1500); + gpio_pin_set_dt(&led, 1); + LOG_INF("SPIM: will be active for 500ms before transfer"); + k_busy_wait(500000); + LOG_INF("SPIM: transferring the CONFIG_BOARD_QUALIFIERS: '%s'", tx_buffer); + spi_write_dt(&spim, &tx_spi_buf_set); + } + + return 0; +}