Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/test-spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@
- "tests/subsys/suit/**/*"

"CI-test-low-level":
- "applications/sw_io_devices/**/*"
- "applications/sdp/**/*"
- "drivers/gpio/**/*"
- "dts/bindings/gpio/**/*"
- "include/drivers/gpio/**/*"
Expand Down
2 changes: 1 addition & 1 deletion CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@
/applications/matter_weather_station/ @nrfconnect/ncs-matter
/applications/nrf5340_audio/ @nrfconnect/ncs-audio
/applications/nrf_desktop/ @nrfconnect/ncs-si-bluebagel
/applications/sdp/ @masz-nordic
/applications/serial_lte_modem/ @nrfconnect/ncs-co-networking @nrfconnect/ncs-iot-oulu
/applications/serial_lte_modem/src/lwm2m_carrier/ @nrfconnect/ncs-carrier
/applications/sw_io_devices/ @masz-nordic
/applications/zigbee_weather_station/ @milewr
/applications/**/*.rst @nrfconnect/ncs-doc-owners

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(emulated_gpio)

target_sources_ifdef(CONFIG_GPIO_NRFE_EGPIO_BACKEND_ICMSG app PRIVATE src/nrfe_icmsg.c)
target_sources_ifdef(CONFIG_GPIO_NRFE_EGPIO_BACKEND_MBOX app PRIVATE src/nrfe_mbox.c)
target_sources(app PRIVATE src/main.c)
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,6 @@
};
};
};

ipc {
ipc0: ipc0 {
compatible = "zephyr,ipc-icmsg";
tx-region = <&sram_tx>;
rx-region = <&sram_rx>;
mboxes = <&cpuflpr_vevif_rx 16>, <&cpuflpr_vevif_tx 15>;
mbox-names = "rx", "tx";
status = "okay";
};
};
};

&cpuflpr_vevif_rx {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

/ {
ipc {
ipc0: ipc0 {
compatible = "zephyr,ipc-icmsg";
tx-region = <&sram_tx>;
rx-region = <&sram_rx>;
mboxes = <&cpuflpr_vevif_rx 21>, <&cpuflpr_vevif_tx 20>;
mbox-names = "rx", "tx";
status = "okay";
};
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

/ {
mbox_consumer: mbox_consumer {
compatible = "vnd,mbox-consumer";
mboxes = <&cpuflpr_vevif_rx 21>, <&cpuflpr_vevif_tx 20>;
mbox-names = "rx", "tx";
};
};
20 changes: 20 additions & 0 deletions applications/sdp/gpio/include/main.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

#ifndef MAIN_H__
#define MAIN_H__

#include <zephyr/kernel.h>
#include <drivers/gpio/nrfe_gpio.h>

#if !defined(CONFIG_GPIO_NRFE_EGPIO_BACKEND_ICMSG) && !defined(CONFIG_GPIO_NRFE_EGPIO_BACKEND_MBOX)
#error "Define communication backend type"
#endif

void process_packet(nrfe_gpio_data_packet_t *packet);
int backend_init(void);

#endif /* MAIN_H__ */
1 change: 1 addition & 0 deletions applications/sdp/gpio/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CONFIG_MBOX=y
28 changes: 28 additions & 0 deletions applications/sdp/gpio/sample.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
sample:
name: eGPIO application
description: SW-defined GPIO application
common:
integration_platforms:
- nrf54l15dk/nrf54l15/cpuflpr
tests:
applications.sdp.egpio_mbox:
build_only: true
sysbuild: true
platform_allow: nrf54l15dk/nrf54l15/cpuflpr
tags: ci_build sysbuild gpio
extra_args:
EXTRA_DTC_OVERLAY_FILE="./boards/nrf54l15dk_nrf54l15_cpuflpr_mbox.overlay"
extra_configs:
- CONFIG_GPIO_NRFE_EGPIO_BACKEND_MBOX=y

applications.sdp.egpio_icmsg:
build_only: true
sysbuild: true
platform_allow: nrf54l15dk/nrf54l15/cpuflpr
tags: ci_build sysbuild gpio
extra_args:
EXTRA_DTC_OVERLAY_FILE="./boards/nrf54l15dk_nrf54l15_cpuflpr_icmsg.overlay"
extra_configs:
- CONFIG_GPIO_NRFE_EGPIO_BACKEND_ICMSG=y
- CONFIG_IPC_SERVICE=y
- CONFIG_IPC_SERVICE_BACKEND_ICMSG=y
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,14 @@
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

#include "../include/main.h"

#include <zephyr/drivers/gpio.h>
#include <zephyr/dt-bindings/gpio/nordic-nrf-gpio.h>
#include <zephyr/ipc/ipc_service.h>

#include <drivers/gpio/nrfe_gpio.h>

#include <hal/nrf_vpr_csr.h>
#include <hal/nrf_vpr_csr_vio.h>
#include <haly/nrfy_gpio.h>

static struct ipc_ept ep;

volatile uint32_t bound_sem = 1;

static void ep_bound(void *priv)
{
bound_sem = 0;
}

static nrf_gpio_pin_pull_t get_pull(gpio_flags_t flags)
{
if (flags & GPIO_PULL_UP) {
Expand Down Expand Up @@ -122,10 +111,8 @@ 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)
void process_packet(nrfe_gpio_data_packet_t *packet)
{
nrfe_gpio_data_packet_t *packet = (nrfe_gpio_data_packet_t *)data;

if (packet->port != 2) {
return;
}
Expand Down Expand Up @@ -153,42 +140,15 @@ static void ep_recv(const void *data, size_t len, void *priv)
}
}

static struct ipc_ept_cfg ep_cfg = {
.cb = {
.bound = ep_bound,
.received = ep_recv,
},
};

int main(void)
{
int ret;
const struct device *ipc0_instance;
volatile uint32_t delay = 0;

#if !defined(CONFIG_SYS_CLOCK_EXISTS)
/* Wait a little bit for IPC service to be ready on APP side */
while (delay < 1000) {
delay++;
}
#endif

ipc0_instance = DEVICE_DT_GET(DT_NODELABEL(ipc0));
int ret = 0;

ret = ipc_service_open_instance(ipc0_instance);
if ((ret < 0) && (ret != -EALREADY)) {
return ret;
}

ret = ipc_service_register_endpoint(ipc0_instance, &ep, &ep_cfg);
ret = backend_init();
if (ret < 0) {
return ret;
return 0;
}

/* Wait for endpoint to be bound */
while (bound_sem != 0) {
};

if (!nrf_vpr_csr_rtperiph_enable_check()) {
nrf_vpr_csr_rtperiph_enable_set(true);
}
Expand Down
64 changes: 64 additions & 0 deletions applications/sdp/gpio/src/nrfe_icmsg.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

#include "../include/main.h"
#include <zephyr/ipc/ipc_service.h>

static struct ipc_ept ep;

volatile uint32_t bound_sem = 1;

static void ep_bound(void *priv)
{
bound_sem = 0;
}

static void ep_recv(const void *data, size_t len, void *priv)
{
(void)len;
(void)priv;

process_packet((nrfe_gpio_data_packet_t *)data);
}

static struct ipc_ept_cfg ep_cfg = {
.cb = {
.bound = ep_bound,
.received = ep_recv,
},
};

int backend_init(void)
{
int ret = 0;
const struct device *ipc0_instance;
volatile uint32_t delay = 0;

#if !defined(CONFIG_SYS_CLOCK_EXISTS)
/* Wait a little bit for IPC service to be ready on APP side */
while (delay < 1000) {
delay++;
}
#endif

ipc0_instance = DEVICE_DT_GET(DT_NODELABEL(ipc0));

ret = ipc_service_open_instance(ipc0_instance);
if ((ret < 0) && (ret != -EALREADY)) {
return ret;
}

ret = ipc_service_register_endpoint(ipc0_instance, &ep, &ep_cfg);
if (ret < 0) {
return ret;
}

/* Wait for endpoint to be bound */
while (bound_sem != 0) {
};

return 0;
}
93 changes: 93 additions & 0 deletions applications/sdp/gpio/src/nrfe_mbox.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

#include "../include/main.h"
#include <zephyr/drivers/mbox.h>

static const struct mbox_dt_spec rx_channel = MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), rx);

/**
* @brief Callback function for when a message is received from the mailbox
* @param instance Pointer to the mailbox device instance
* @param channel Unused, but required by the mailbox API
* @param user_data Pointer to the received message
* @param msg_data Unused, but required by the mailbox API
*
* This function is called when a message is received from the mailbox.
* It is responsible for handling the received data and logging any errors.
*/
static void mbox_callback(const struct device *instance, uint32_t channel, void *user_data,
struct mbox_msg *msg_data)
{
/* Unused parameters */
(void)msg_data;

/* Check for invalid arguments */
if (user_data == NULL) {
return;
}

nrfe_gpio_mbox_data_t *rx_data = (nrfe_gpio_mbox_data_t *)user_data;

/* Try and get lock for the shared data structure */
if (atomic_flag_test_and_set(&rx_data->lock.locked)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use zephyr's atomic_set_bit with zephyr's primitve atomic_t

/* Return in case lock is not acquired (used by other core)*/
return;
}

nrfe_gpio_data_packet_t *packet = (nrfe_gpio_data_packet_t *)&rx_data->data;

process_packet(packet);

/* Clear shared_data.buffer_size (there is no more data available)
* This is necessary so that the other core knows that the data has been read
*/
rx_data->lock.data_size = 0;

/* We are finished with the shared data structure, so we can release the lock */
atomic_flag_clear(&rx_data->lock.locked);
}

/**
* @brief Initialize the mailbox driver.
*
* This function sets up the mailbox receive channel with the callback
* function specified in the DT node.
*
* @return 0 on success, negative error code on failure.
*/
static int mbox_init(void *shared_data)
{
int ret;

/* Register the callback function for the mailbox receive channel */
ret = mbox_register_callback_dt(&rx_channel, mbox_callback, shared_data);
if (ret < 0) {
return ret;
}

/* Enable the mailbox receive channel */
return mbox_set_enabled_dt(&rx_channel, true);
}

int backend_init(void)
{
int ret = 0;

static nrfe_gpio_mbox_data_t *rx_data =
(nrfe_gpio_mbox_data_t *)((uint8_t *)(DT_REG_ADDR(DT_NODELABEL(sram_rx))));

ret = mbox_init((void *)rx_data);
if (ret < 0) {
return ret;
}

/* clear the buffer locks and their size holders */
atomic_flag_clear(&rx_data->lock.locked);
rx_data->lock.data_size = 0;

return 0;
}
Loading
Loading