diff --git a/samples/basic/blinky/CMakeLists.txt b/samples/basic/blinky/CMakeLists.txt index 4de34fbd81e7dc9..84e0afb794b32a3 100644 --- a/samples/basic/blinky/CMakeLists.txt +++ b/samples/basic/blinky/CMakeLists.txt @@ -2,6 +2,13 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +if(NOT CONFIG_BOARD_NRF54L15PDK_NRF54L15_CPUAPP) + message(FATAL_ERROR "${BOARD} is not supported for this sample") +endif() + project(blinky) target_sources(app PRIVATE src/main.c) + +include(ExternalProject) diff --git a/samples/basic/blinky/Kconfig.sysbuild b/samples/basic/blinky/Kconfig.sysbuild new file mode 100644 index 000000000000000..70a2f7380e80b23 --- /dev/null +++ b/samples/basic/blinky/Kconfig.sysbuild @@ -0,0 +1,9 @@ +# Copyright 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 + +source "share/sysbuild/Kconfig" + +config REMOTE_BOARD +string + default "nrf54l15pdk/nrf54l15/cpuflpr" if $(BOARD) = "nrf54l15pdk" diff --git a/samples/basic/blinky/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay b/samples/basic/blinky/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay new file mode 100644 index 000000000000000..5ccd69b667537c7 --- /dev/null +++ b/samples/basic/blinky/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + soc { + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + + sram_rx: memory@20018000 { + reg = <0x20018000 0x0800>; + }; + + sram_tx: memory@20020000 { + reg = <0x20020000 0x0800>; + }; + }; + }; + + ipc { + ipc0: ipc0 { + compatible = "zephyr,ipc-icmsg"; + tx-region = <&sram_tx>; + rx-region = <&sram_rx>; + mboxes = <&mbox_cpuapp_rx_cpuflpr 15>, <&mbox_cpuapp_tx_cpuflpr 16>; + mbox-names = "rx", "tx"; + status = "okay"; + }; + }; + + leds { + compatible = "gpio-leds"; + led4: led_4 { + gpios = <&egpio2 7 GPIO_ACTIVE_HIGH>; + label = "Test LED 4"; + }; + }; + + aliases { + led4 = &led4; + }; + + egpio2: egpio2 { + compatible = "nordic,nrf-egpio"; + gpio-reserved-ranges = <0 6>, <8 4>; + #gpio-cells = <2>; + ngpios = <11>; + status = "okay"; + port = <2>; + }; +}; + +&mbox_cpuapp_rx_cpuflpr { + status = "okay"; +}; + +&mbox_cpuapp_tx_cpuflpr { + status = "okay"; +}; + +&gpio0 { + status = "disabled"; +}; + +&gpio1 { + status = "disabled"; +}; + +&gpio2 { + status = "disabled"; +}; + +&gpiote20 { + status = "disabled"; +}; + +&gpiote30 { + status = "disabled"; +}; diff --git a/samples/basic/blinky/prj.conf b/samples/basic/blinky/prj.conf index 91c3c15b37d1ee4..eda0f08d2241858 100644 --- a/samples/basic/blinky/prj.conf +++ b/samples/basic/blinky/prj.conf @@ -1 +1,7 @@ CONFIG_GPIO=y + +CONFIG_IPC_SERVICE=y +CONFIG_IPC_SERVICE_BACKEND_ICMSG=y +CONFIG_MBOX=y + +CONFIG_MULTITHREADING=n diff --git a/samples/basic/blinky/remote/CMakeLists.txt b/samples/basic/blinky/remote/CMakeLists.txt new file mode 100644 index 000000000000000..ec6affa1e1a00d2 --- /dev/null +++ b/samples/basic/blinky/remote/CMakeLists.txt @@ -0,0 +1,14 @@ +# +# Copyright (c) 2022 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(ipc_service_remote) + +target_include_directories(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../common) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/basic/blinky/remote/boards/nrf54l15pdk_nrf54l15_cpuflpr.conf b/samples/basic/blinky/remote/boards/nrf54l15pdk_nrf54l15_cpuflpr.conf new file mode 100644 index 000000000000000..3f40e856c8812e2 --- /dev/null +++ b/samples/basic/blinky/remote/boards/nrf54l15pdk_nrf54l15_cpuflpr.conf @@ -0,0 +1 @@ +CONFIG_MULTITHREADING=n diff --git a/samples/basic/blinky/remote/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay b/samples/basic/blinky/remote/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay new file mode 100644 index 000000000000000..03cdc4d5140abd5 --- /dev/null +++ b/samples/basic/blinky/remote/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + soc { + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + + sram_tx: memory@20018000 { + reg = <0x20018000 0x0800>; + }; + + sram_rx: memory@20020000 { + reg = <0x20020000 0x0800>; + }; + }; + }; + + ipc { + ipc0: ipc0 { + compatible = "zephyr,ipc-icmsg"; + tx-region = <&sram_tx>; + rx-region = <&sram_rx>; + mboxes = <&mbox_cpuflpr_rx_cpuapp 16>, <&mbox_cpuflpr_tx_cpuapp 15>; + mbox-names = "rx", "tx"; + status = "okay"; + }; + }; +}; + +&mbox_cpuflpr_rx_cpuapp { + status = "okay"; +}; + +&mbox_cpuflpr_tx_cpuapp { + status = "okay"; +}; + +&gpio0 { + status = "disabled"; +}; + +&gpio1 { + status = "disabled"; +}; + +&gpio2 { + status = "disabled"; +}; + +&gpiote20 { + status = "disabled"; +}; + +&gpiote30 { + status = "disabled"; +}; diff --git a/samples/basic/blinky/remote/prj.conf b/samples/basic/blinky/remote/prj.conf new file mode 100644 index 000000000000000..530e6ab86604200 --- /dev/null +++ b/samples/basic/blinky/remote/prj.conf @@ -0,0 +1,3 @@ +CONFIG_IPC_SERVICE=y +CONFIG_IPC_SERVICE_BACKEND_ICMSG=y +CONFIG_MBOX=y diff --git a/samples/basic/blinky/remote/src/main.c b/samples/basic/blinky/remote/src/main.c new file mode 100644 index 000000000000000..559ebeb1453f78b --- /dev/null +++ b/samples/basic/blinky/remote/src/main.c @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifdef CONFIG_MULTITHREADING +#include +#endif +#include +#include +#include +#include + +#include +#include +#include +#include + +static struct ipc_ept ep; + +#ifdef CONFIG_MULTITHREADING +K_SEM_DEFINE(bound_sem, 0, 1); +#else +volatile uint32_t bound_sem = 1; +#endif + +static void ep_bound(void *priv) +{ +#ifdef CONFIG_MULTITHREADING + k_sem_give(&bound_sem); +#else + bound_sem = 0; +#endif + printf("Ep bounded\n"); +} + +static nrf_gpio_pin_pull_t get_pull(gpio_flags_t flags) +{ + if (flags & GPIO_PULL_UP) { + return NRF_GPIO_PIN_PULLUP; + } else if (flags & GPIO_PULL_DOWN) { + return NRF_GPIO_PIN_PULLDOWN; + } + + return NRF_GPIO_PIN_NOPULL; +} + +static int gpio_nrfe_pin_configure(uint8_t port, uint16_t pin, uint32_t flags) +{ + __ASSERT(port == 2, "Invalid port. Only port 2 is supported"); + + uint32_t abs_pin = NRF_GPIO_PIN_MAP(port, pin); + nrf_gpio_pin_pull_t pull = get_pull(flags); + nrf_gpio_pin_drive_t drive; + + switch (flags & (NRF_GPIO_DRIVE_MSK | GPIO_OPEN_DRAIN)) { + case NRF_GPIO_DRIVE_S0S1: + drive = NRF_GPIO_PIN_S0S1; + break; + case NRF_GPIO_DRIVE_S0H1: + drive = NRF_GPIO_PIN_S0H1; + break; + case NRF_GPIO_DRIVE_H0S1: + drive = NRF_GPIO_PIN_H0S1; + break; + case NRF_GPIO_DRIVE_H0H1: + drive = NRF_GPIO_PIN_H0H1; + break; + case NRF_GPIO_DRIVE_S0 | GPIO_OPEN_DRAIN: + drive = NRF_GPIO_PIN_S0D1; + break; + case NRF_GPIO_DRIVE_H0 | GPIO_OPEN_DRAIN: + drive = NRF_GPIO_PIN_H0D1; + break; + case NRF_GPIO_DRIVE_S1 | GPIO_OPEN_SOURCE: + drive = NRF_GPIO_PIN_D0S1; + break; + case NRF_GPIO_DRIVE_H1 | GPIO_OPEN_SOURCE: + drive = NRF_GPIO_PIN_D0H1; + break; + default: + return -EINVAL; + } + + if (flags & GPIO_OUTPUT_INIT_HIGH) { + uint16_t outs = nrf_vpr_csr_vio_out_get(); + nrf_vpr_csr_vio_out_set(outs | (BIT(pin))); + } else if (flags & GPIO_OUTPUT_INIT_LOW) { + uint16_t outs = nrf_vpr_csr_vio_out_get(); + nrf_vpr_csr_vio_out_set(outs & ~(BIT(pin))); + } + + nrf_gpio_pin_dir_t dir = (flags & GPIO_OUTPUT) + ? NRF_GPIO_PIN_DIR_OUTPUT + : NRF_GPIO_PIN_DIR_INPUT; + nrf_gpio_pin_input_t input = (flags & GPIO_INPUT) + ? NRF_GPIO_PIN_INPUT_CONNECT + : NRF_GPIO_PIN_INPUT_DISCONNECT; + + /* Reconfigure the GPIO pin with the specified pull-up/pull-down configuration and drive strength. */ + nrfy_gpio_reconfigure(abs_pin, &dir, &input, &pull, &drive, NULL); + + if (dir == NRF_GPIO_PIN_DIR_OUTPUT) { + nrf_vpr_csr_vio_dir_set(nrf_vpr_csr_vio_dir_get() | (BIT(pin))); + } + + /* Take control of the pin */ + nrfy_gpio_pin_control_select(abs_pin, NRF_GPIO_PIN_SEL_VPR); + + return 0; +} + +static void gpio_nrfe_port_set_bits_raw(uint16_t set_mask) +{ + uint16_t outs = nrf_vpr_csr_vio_out_get(); + + nrf_vpr_csr_vio_out_set(outs | set_mask); +} + +static void gpio_nrfe_port_clear_bits_raw(uint16_t clear_mask) +{ + uint16_t outs = nrf_vpr_csr_vio_out_get(); + + nrf_vpr_csr_vio_out_set(outs & ~clear_mask); +} + +static void gpio_nrfe_port_toggle_bits(uint16_t toggle_mask) +{ + nrf_vpr_csr_vio_out_toggle_set(toggle_mask); +} + +static void ep_recv(const void *data, size_t len, void *priv) +{ + struct nrfe_gpio_data_packet_t *packet = (struct nrfe_gpio_data_packet_t *)data; + + switch (packet->opcode) { + case NRFE_GPIO_CONFIGURE: + { + printf("Configuring GPIO%d pin: %d\n", packet->port, packet->pin); + gpio_nrfe_pin_configure(packet->port, packet->pin, packet->flags); + + struct nrfe_gpio_data_packet_t msg = { + .opcode = NRFE_GPIO_CONFIRM}; + + (void)ipc_service_send(&ep, (void *)(&msg), sizeof(struct nrfe_gpio_data_packet_t)); + break; + } + case NRFE_GPIO_CLEAR: + { + printf("Clearing GPIO%d, pin 0x%04x\n", packet->port, packet->pin); + gpio_nrfe_port_clear_bits_raw(packet->pin); + + struct nrfe_gpio_data_packet_t msg = { + .opcode = NRFE_GPIO_CONFIRM}; + + (void)ipc_service_send(&ep, (void *)(&msg), sizeof(struct nrfe_gpio_data_packet_t)); + break; + } + case NRFE_GPIO_SET: + { + printf("Setting GPIO%d, pin 0x%04x\n", packet->port, packet->pin); + gpio_nrfe_port_set_bits_raw(packet->pin); + + struct nrfe_gpio_data_packet_t msg = { + .opcode = NRFE_GPIO_CONFIRM}; + + (void)ipc_service_send(&ep, (void *)(&msg), sizeof(struct nrfe_gpio_data_packet_t)); + break; + } + case NRFE_GPIO_TOGGLE: + { + printf("Toggling GPIO%d, pin 0x%04x\n", packet->port, packet->pin); + gpio_nrfe_port_toggle_bits(packet->pin); + + struct nrfe_gpio_data_packet_t msg = { + .opcode = NRFE_GPIO_CONFIRM}; + + (void)ipc_service_send(&ep, (void *)(&msg), sizeof(struct nrfe_gpio_data_packet_t)); + break; + } + default: + { + printf("Unknown opcode %d\n", packet->opcode); + break; + } + } +} + +static struct ipc_ept_cfg ep_cfg = { + .cb = { + .bound = ep_bound, + .received = ep_recv, + }, +}; + +int main(void) +{ + int ret; + const struct device *ipc0_instance; + + ipc0_instance = DEVICE_DT_GET(DT_NODELABEL(ipc0)); + + ret = ipc_service_open_instance(ipc0_instance); + if ((ret < 0) && (ret != -EALREADY)) { + printf("ipc_service_open_instance() failure\n"); + return ret; + } + + ret = ipc_service_register_endpoint(ipc0_instance, &ep, &ep_cfg); + if (ret < 0) { + printf("ipc_service_register_endpoint() failure\n"); + return ret; + } + + /* Wait for endpoint to be bound */ +#ifdef CONFIG_MULTITHREADING + k_sem_take(&bound_sem, K_FOREVER); +#else + while (bound_sem != 0) { + }; +#endif + + if (!nrf_vpr_csr_rtperiph_enable_check()) + { + nrf_vpr_csr_rtperiph_enable_set(true); + } + + while (true) {}; + + return 0; +} diff --git a/samples/basic/blinky/src/main.c b/samples/basic/blinky/src/main.c index 4cab4969d94b5fc..7c3d026a53e5a43 100644 --- a/samples/basic/blinky/src/main.c +++ b/samples/basic/blinky/src/main.c @@ -12,7 +12,7 @@ #define SLEEP_TIME_MS 1000 /* The devicetree node identifier for the "led0" alias. */ -#define LED0_NODE DT_ALIAS(led0) +#define LED0_NODE DT_ALIAS(led4) /* * A build error on this line means your board is unsupported. @@ -42,7 +42,11 @@ int main(void) led_state = !led_state; printf("LED state: %s\n", led_state ? "ON" : "OFF"); +#ifdef CONFIG_MULTITHREADING k_msleep(SLEEP_TIME_MS); +#else + k_busy_wait(SLEEP_TIME_MS*1000); +#endif } return 0; } diff --git a/samples/basic/blinky/sysbuild.cmake b/samples/basic/blinky/sysbuild.cmake new file mode 100644 index 000000000000000..62c9e931d60f11b --- /dev/null +++ b/samples/basic/blinky/sysbuild.cmake @@ -0,0 +1,14 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if ("${SB_CONFIG_REMOTE_BOARD}" STREQUAL "") + message(FATAL_ERROR + "Target ${BOARD} not supported for this sample. " + "There is no remote board selected in Kconfig.sysbuild") +endif() + +ExternalZephyrProject_Add( + APPLICATION remote + SOURCE_DIR ${APP_DIR}/remote + BOARD ${SB_CONFIG_REMOTE_BOARD} +)