drivers: openthread: nxp: Add a HDLC RCP communication
Add a HDLC RCP communication with its hdlc_api interface APIs and a NXP driver. Signed-off-by: Jamel Arbi <jamel.arbi@nxp.com>
This commit is contained in:
parent
69b3ccf061
commit
70add85f9f
11 changed files with 287 additions and 5 deletions
|
@ -45,6 +45,7 @@ add_subdirectory_ifdef(CONFIG_FUEL_GAUGE fuel_gauge)
|
||||||
add_subdirectory_ifdef(CONFIG_GNSS gnss)
|
add_subdirectory_ifdef(CONFIG_GNSS gnss)
|
||||||
add_subdirectory_ifdef(CONFIG_GPIO gpio)
|
add_subdirectory_ifdef(CONFIG_GPIO gpio)
|
||||||
add_subdirectory_ifdef(CONFIG_HAPTICS haptics)
|
add_subdirectory_ifdef(CONFIG_HAPTICS haptics)
|
||||||
|
add_subdirectory_ifdef(CONFIG_HDLC_RCP_IF hdlc_rcp_if)
|
||||||
add_subdirectory_ifdef(CONFIG_HWINFO hwinfo)
|
add_subdirectory_ifdef(CONFIG_HWINFO hwinfo)
|
||||||
add_subdirectory_ifdef(CONFIG_HWSPINLOCK hwspinlock)
|
add_subdirectory_ifdef(CONFIG_HWSPINLOCK hwspinlock)
|
||||||
add_subdirectory_ifdef(CONFIG_I2C i2c)
|
add_subdirectory_ifdef(CONFIG_I2C i2c)
|
||||||
|
|
|
@ -38,6 +38,7 @@ source "drivers/fuel_gauge/Kconfig"
|
||||||
source "drivers/gnss/Kconfig"
|
source "drivers/gnss/Kconfig"
|
||||||
source "drivers/gpio/Kconfig"
|
source "drivers/gpio/Kconfig"
|
||||||
source "drivers/haptics/Kconfig"
|
source "drivers/haptics/Kconfig"
|
||||||
|
source "drivers/hdlc_rcp_if/Kconfig"
|
||||||
source "drivers/hwinfo/Kconfig"
|
source "drivers/hwinfo/Kconfig"
|
||||||
source "drivers/hwspinlock/Kconfig"
|
source "drivers/hwspinlock/Kconfig"
|
||||||
source "drivers/i2c/Kconfig"
|
source "drivers/i2c/Kconfig"
|
||||||
|
|
5
drivers/hdlc_rcp_if/CMakeLists.txt
Normal file
5
drivers/hdlc_rcp_if/CMakeLists.txt
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
zephyr_library()
|
||||||
|
|
||||||
|
zephyr_library_sources_ifdef(CONFIG_HDLC_RCP_IF_NXP hdlc_rcp_if_nxp.c)
|
29
drivers/hdlc_rcp_if/Kconfig
Normal file
29
drivers/hdlc_rcp_if/Kconfig
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
# Configuration options for HDLC RCP communication Interface
|
||||||
|
|
||||||
|
# Copyright (c) 2024 NXP
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
#
|
||||||
|
# HDLC communication Interface used by Zephyr running Openthread RCP host
|
||||||
|
#
|
||||||
|
|
||||||
|
menuconfig HDLC_RCP_IF
|
||||||
|
bool "HDLC interface for a Zephyr Openthread RCP host"
|
||||||
|
depends on NET_L2_OPENTHREAD && !OPENTHREAD_COPROCESSOR
|
||||||
|
|
||||||
|
if HDLC_RCP_IF
|
||||||
|
|
||||||
|
source "drivers/hdlc_rcp_if/Kconfig.nxp"
|
||||||
|
|
||||||
|
config HDLC_RCP_IF_DRV_NAME
|
||||||
|
string "HDLC RCP Interface Driver's name"
|
||||||
|
default "hdlc_rcp_if"
|
||||||
|
help
|
||||||
|
This option sets the driver name
|
||||||
|
|
||||||
|
module = HDLC_RCP_IF_DRIVER
|
||||||
|
module-str = HDLC driver for Openthread RCP host
|
||||||
|
module-help = Sets log level for Openthread HDLC RCP host interface Device Drivers.
|
||||||
|
source "subsys/logging/Kconfig.template.log_config"
|
||||||
|
|
||||||
|
endif # HDLC_RCP_IF
|
13
drivers/hdlc_rcp_if/Kconfig.nxp
Normal file
13
drivers/hdlc_rcp_if/Kconfig.nxp
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# Configuration options for NXP HDLC RCP communication Interface
|
||||||
|
|
||||||
|
# Copyright (c) 2024 NXP
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
#
|
||||||
|
# HDLC communication Interface used by Zephyr running Openthread RCP host
|
||||||
|
#
|
||||||
|
|
||||||
|
config HDLC_RCP_IF_NXP
|
||||||
|
bool "NXP HDLC interface for Zephyr Openthread RCP host"
|
||||||
|
default y
|
||||||
|
depends on DT_HAS_NXP_HDLC_RCP_IF_ENABLED
|
136
drivers/hdlc_rcp_if/hdlc_rcp_if_nxp.c
Normal file
136
drivers/hdlc_rcp_if/hdlc_rcp_if_nxp.c
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024, NXP
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* IEEE 802.15.4 HDLC RCP interface. This is meant for network connectivity
|
||||||
|
* between a host and a RCP radio device.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* Includes */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
#include <fwk_platform_hdlc.h>
|
||||||
|
#include <fwk_platform_ot.h>
|
||||||
|
#include <openthread/platform/radio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <zephyr/init.h>
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
#include <zephyr/net/hdlc_rcp_if/hdlc_rcp_if.h>
|
||||||
|
#include <zephyr/net/ieee802154_radio.h>
|
||||||
|
#include <zephyr/net/openthread.h>
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* Definitions */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#define DT_DRV_COMPAT nxp_hdlc_rcp_if
|
||||||
|
|
||||||
|
#define LOG_MODULE_NAME hdlc_rcp_if_nxp
|
||||||
|
#define LOG_LEVEL CONFIG_HDLC_RCP_IF_DRIVER_LOG_LEVEL
|
||||||
|
LOG_MODULE_REGISTER(LOG_MODULE_NAME);
|
||||||
|
|
||||||
|
#define HDLC_RCP_IF_IRQ_N DT_INST_IRQ_BY_NAME(0, hdlc_rcp_if_int, irq)
|
||||||
|
#define HDLC_RCP_IF_IRQ_P DT_INST_IRQ_BY_NAME(0, hdlc_rcp_if_int, priority)
|
||||||
|
#define HDLC_RCP_IF_WAKEUP_IRQ_N DT_INST_IRQ_BY_NAME(0, wakeup_int, irq)
|
||||||
|
#define HDLC_RCP_IF_WAKEUP_IRQ_P DT_INST_IRQ_BY_NAME(0, wakeup_int, priority)
|
||||||
|
|
||||||
|
struct ot_hdlc_rcp_context {
|
||||||
|
struct net_if *iface;
|
||||||
|
struct openthread_context *ot_context;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* Private prototypes */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
extern int32_t hdlc_rcp_if_handler(void);
|
||||||
|
extern int32_t hdlc_rcp_if_wakeup_done_handler(void);
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* Private functions */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static void hdlc_iface_init(struct net_if *iface)
|
||||||
|
{
|
||||||
|
struct ot_hdlc_rcp_context *ctx = net_if_get_device(iface)->data;
|
||||||
|
otExtAddress eui64;
|
||||||
|
|
||||||
|
/* HDLC RCP interface Interrupt */
|
||||||
|
IRQ_CONNECT(HDLC_RCP_IF_IRQ_N, HDLC_RCP_IF_IRQ_P, hdlc_rcp_if_handler, 0, 0);
|
||||||
|
irq_enable(HDLC_RCP_IF_IRQ_N);
|
||||||
|
|
||||||
|
/* Wake up done interrupt */
|
||||||
|
IRQ_CONNECT(HDLC_RCP_IF_WAKEUP_IRQ_N, HDLC_RCP_IF_WAKEUP_IRQ_P,
|
||||||
|
hdlc_rcp_if_wakeup_done_handler, 0, 0);
|
||||||
|
irq_enable(HDLC_RCP_IF_WAKEUP_IRQ_N);
|
||||||
|
|
||||||
|
ctx->iface = iface;
|
||||||
|
|
||||||
|
ieee802154_init(iface);
|
||||||
|
|
||||||
|
ctx->ot_context = net_if_l2_data(iface);
|
||||||
|
|
||||||
|
otPlatRadioGetIeeeEui64(ctx->ot_context->instance, eui64.m8);
|
||||||
|
net_if_set_link_addr(iface, eui64.m8, OT_EXT_ADDRESS_SIZE, NET_LINK_IEEE802154);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hdlc_register_rx_cb(hdlc_rx_callback_t hdlc_rx_callback, void *param)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = PLATFORM_InitHdlcInterface(hdlc_rx_callback, param);
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_ERR("HDLC RX callback registration failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hdlc_send(const uint8_t *frame, uint16_t length)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = PLATFORM_SendHdlcMessage((uint8_t *)frame, length);
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_ERR("HDLC send frame failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hdlc_deinit(void)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = PLATFORM_TerminateHdlcInterface();
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_ERR("Failed to shutdown OpenThread controller");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct hdlc_api nxp_hdlc_api = {
|
||||||
|
.iface_api.init = hdlc_iface_init,
|
||||||
|
.register_rx_cb = hdlc_register_rx_cb,
|
||||||
|
.send = hdlc_send,
|
||||||
|
.deinit = hdlc_deinit,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define L2_CTX_TYPE NET_L2_GET_CTX_TYPE(OPENTHREAD_L2)
|
||||||
|
|
||||||
|
#define MTU 1280
|
||||||
|
|
||||||
|
NET_DEVICE_DT_INST_DEFINE(0, NULL, /* Initialization Function */
|
||||||
|
NULL, /* No PM API support */
|
||||||
|
NULL, /* No context data */
|
||||||
|
NULL, /* Configuration info */
|
||||||
|
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, /* Initial priority */
|
||||||
|
&nxp_hdlc_api, /* API interface functions */
|
||||||
|
OPENTHREAD_L2, /* Openthread L2 */
|
||||||
|
NET_L2_GET_CTX_TYPE(OPENTHREAD_L2), /* Openthread L2 context type */
|
||||||
|
MTU); /* MTU size */
|
|
@ -17,6 +17,7 @@
|
||||||
chosen {
|
chosen {
|
||||||
zephyr,entropy = &trng;
|
zephyr,entropy = &trng;
|
||||||
zephyr,bt-hci = &hci;
|
zephyr,bt-hci = &hci;
|
||||||
|
zephyr,hdlc-rcp-if = &hdlc_rcp_if;
|
||||||
};
|
};
|
||||||
|
|
||||||
cpus {
|
cpus {
|
||||||
|
@ -521,6 +522,14 @@
|
||||||
interrupt-names = "hci_int", "wakeup_int";
|
interrupt-names = "hci_int", "wakeup_int";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
hdlc_rcp_if: hdlc_rcp_if {
|
||||||
|
compatible = "nxp,hdlc-rcp-if";
|
||||||
|
/* first index is the hdlc_rcp_if interrupt */
|
||||||
|
/* the second is the wake up done interrupt */
|
||||||
|
interrupts = <90 2>, <82 2>;
|
||||||
|
interrupt-names = "hdlc_rcp_if_int", "wakeup_int";
|
||||||
|
};
|
||||||
|
|
||||||
enet: enet@138000 {
|
enet: enet@138000 {
|
||||||
compatible = "nxp,enet";
|
compatible = "nxp,enet";
|
||||||
reg = <0x138000 0x700>;
|
reg = <0x138000 0x700>;
|
||||||
|
|
8
dts/bindings/hdlc_rcp_if/nxp,hdlc-rcp-if.yaml
Normal file
8
dts/bindings/hdlc_rcp_if/nxp,hdlc-rcp-if.yaml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# Copyright (c) 2024, NXP
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
description: NXP HDLC RCP interface node
|
||||||
|
|
||||||
|
compatible: "nxp,hdlc-rcp-if"
|
||||||
|
|
||||||
|
include: base.yaml
|
77
include/zephyr/net/hdlc_rcp_if/hdlc_rcp_if.h
Normal file
77
include/zephyr/net/hdlc_rcp_if/hdlc_rcp_if.h
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024, NXP
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Public APIs of HDLC RCP communication Interface
|
||||||
|
*
|
||||||
|
* This file provide the HDLC APIs to be used by an RCP host
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zephyr/sys/util.h>
|
||||||
|
#include <zephyr/net/net_if.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief OT RCP HDLC RX callback function.
|
||||||
|
*
|
||||||
|
* @note This function is called in the radio spinel HDLC level
|
||||||
|
*/
|
||||||
|
typedef void (*hdlc_rx_callback_t)(uint8_t *data, uint16_t len, void *param);
|
||||||
|
|
||||||
|
/** HDLC interface configuration data. */
|
||||||
|
struct hdlc_api {
|
||||||
|
/**
|
||||||
|
* @brief HDLC interface API
|
||||||
|
*/
|
||||||
|
struct net_if_api iface_api;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register the Spinel HDLC RX callback.
|
||||||
|
*
|
||||||
|
* @param hdlc_rx_callback pointer to the spinel HDLC RX callback
|
||||||
|
* @param param pointer to the spinel HDLC interface
|
||||||
|
*
|
||||||
|
* @retval 0 The callback was successfully registered.
|
||||||
|
* @retval -EIO The callback could not be registered.
|
||||||
|
*/
|
||||||
|
int (*register_rx_cb)(hdlc_rx_callback_t hdlc_rx_callback, void *param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Transmit a HDLC frame
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param frame pointer to the HDLC frame to be transmitted.
|
||||||
|
* @param length length of the HDLC frame to be transmitted.
|
||||||
|
|
||||||
|
* @retval 0 The frame was successfully sent.
|
||||||
|
* @retval -EIO The frame could not be sent due to some unspecified
|
||||||
|
* interface error (e.g. the interface being busy).
|
||||||
|
*/
|
||||||
|
int (*send)(const uint8_t *frame, uint16_t length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deinitialize the device.
|
||||||
|
*
|
||||||
|
* @param none
|
||||||
|
*
|
||||||
|
* @retval 0 The interface was successfully stopped.
|
||||||
|
* @retval -EIO The interface could not be stopped.
|
||||||
|
*/
|
||||||
|
int (*deinit)(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Make sure that the interface API is properly setup inside
|
||||||
|
* HDLC interface API struct (it is the first one).
|
||||||
|
*/
|
||||||
|
BUILD_ASSERT(offsetof(struct hdlc_api, iface_api) == 0);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -19,6 +19,9 @@
|
||||||
#define ble_hci_handler BLE_MCI_WAKEUP0_DriverIRQHandler
|
#define ble_hci_handler BLE_MCI_WAKEUP0_DriverIRQHandler
|
||||||
#define ble_wakeup_done_handler BLE_MCI_WAKEUP_DONE0_DriverIRQHandler
|
#define ble_wakeup_done_handler BLE_MCI_WAKEUP_DONE0_DriverIRQHandler
|
||||||
|
|
||||||
|
#define hdlc_rcp_if_handler BLE_MCI_WAKEUP0_DriverIRQHandler
|
||||||
|
#define hdlc_rcp_if_wakeup_done_handler BLE_MCI_WAKEUP_DONE0_DriverIRQHandler
|
||||||
|
|
||||||
/* Wrapper Function to deal with SDK differences in power API */
|
/* Wrapper Function to deal with SDK differences in power API */
|
||||||
static inline void EnableDeepSleepIRQ(IRQn_Type irq)
|
static inline void EnableDeepSleepIRQ(IRQn_Type irq)
|
||||||
{
|
{
|
||||||
|
@ -29,5 +32,4 @@ static inline void EnableDeepSleepIRQ(IRQn_Type irq)
|
||||||
int flexspi_clock_set_freq(uint32_t clock_name, uint32_t rate);
|
int flexspi_clock_set_freq(uint32_t clock_name, uint32_t rate);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif /* _SOC__H_ */
|
#endif /* _SOC__H_ */
|
||||||
|
|
|
@ -101,7 +101,7 @@ LOG_MODULE_REGISTER(net_l2_openthread, CONFIG_OPENTHREAD_L2_LOG_LEVEL);
|
||||||
#define OT_POLL_PERIOD 0
|
#define OT_POLL_PERIOD 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PACKAGE_NAME "Zephyr"
|
#define ZEPHYR_PACKAGE_NAME "Zephyr"
|
||||||
#define PACKAGE_VERSION KERNEL_VERSION_STRING
|
#define PACKAGE_VERSION KERNEL_VERSION_STRING
|
||||||
|
|
||||||
extern void platformShellInit(otInstance *aInstance);
|
extern void platformShellInit(otInstance *aInstance);
|
||||||
|
@ -159,12 +159,14 @@ static int ncp_hdlc_send(const uint8_t *buf, uint16_t len)
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_HDLC_RCP_IF
|
||||||
void otPlatRadioGetIeeeEui64(otInstance *instance, uint8_t *ieee_eui64)
|
void otPlatRadioGetIeeeEui64(otInstance *instance, uint8_t *ieee_eui64)
|
||||||
{
|
{
|
||||||
ARG_UNUSED(instance);
|
ARG_UNUSED(instance);
|
||||||
|
|
||||||
memcpy(ieee_eui64, ll_addr->addr, ll_addr->len);
|
memcpy(ieee_eui64, ll_addr->addr, ll_addr->len);
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_HDLC_RCP_IF */
|
||||||
|
|
||||||
void otTaskletsSignalPending(otInstance *instance)
|
void otTaskletsSignalPending(otInstance *instance)
|
||||||
{
|
{
|
||||||
|
@ -451,9 +453,8 @@ int openthread_start(struct openthread_context *ot_context)
|
||||||
/* No dataset - initiate network join procedure. */
|
/* No dataset - initiate network join procedure. */
|
||||||
NET_DBG("Starting OpenThread join procedure.");
|
NET_DBG("Starting OpenThread join procedure.");
|
||||||
|
|
||||||
error = otJoinerStart(ot_instance, OT_JOINER_PSKD, NULL,
|
error = otJoinerStart(ot_instance, OT_JOINER_PSKD, NULL, ZEPHYR_PACKAGE_NAME,
|
||||||
PACKAGE_NAME, OT_PLATFORM_INFO,
|
OT_PLATFORM_INFO, PACKAGE_VERSION, NULL,
|
||||||
PACKAGE_VERSION, NULL,
|
|
||||||
&ot_joiner_start_handler, ot_context);
|
&ot_joiner_start_handler, ot_context);
|
||||||
|
|
||||||
if (error != OT_ERROR_NONE) {
|
if (error != OT_ERROR_NONE) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue