From 74efaa920aed601440a40855f5934a82a9c27449 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Sat, 3 Jul 2021 19:06:31 +0100 Subject: [PATCH] drivers: sx126x: refactor few functions for stm32wl support Move few functions around in preparation of adding the STM32WL variant of the driver. Signed-off-by: Fabio Baltieri --- drivers/lora/CMakeLists.txt | 1 + drivers/lora/sx126x.c | 89 ++++++-------------------------- drivers/lora/sx126x_common.h | 79 ++++++++++++++++++++++++++++ drivers/lora/sx126x_standalone.c | 72 ++++++++++++++++++++++++++ 4 files changed, 167 insertions(+), 74 deletions(-) create mode 100644 drivers/lora/sx126x_common.h create mode 100644 drivers/lora/sx126x_standalone.c diff --git a/drivers/lora/CMakeLists.txt b/drivers/lora/CMakeLists.txt index 4173f6c8edd..2ba69692e98 100644 --- a/drivers/lora/CMakeLists.txt +++ b/drivers/lora/CMakeLists.txt @@ -14,3 +14,4 @@ zephyr_library_sources_ifdef(CONFIG_HAS_SEMTECH_RADIO_DRIVERS hal_common.c) zephyr_library_sources_ifdef(CONFIG_HAS_SEMTECH_RADIO_DRIVERS sx12xx_common.c) zephyr_library_sources_ifdef(CONFIG_LORA_SX127X sx127x.c) zephyr_library_sources_ifdef(CONFIG_LORA_SX126X sx126x.c) +zephyr_library_sources_ifdef(CONFIG_LORA_SX126X sx126x_standalone.c) diff --git a/drivers/lora/sx126x.c b/drivers/lora/sx126x.c index a949e2f7dc0..3136138356f 100644 --- a/drivers/lora/sx126x.c +++ b/drivers/lora/sx126x.c @@ -13,41 +13,15 @@ #include #include "sx12xx_common.h" +#include "sx126x_common.h" #include LOG_MODULE_REGISTER(sx126x, CONFIG_LORA_LOG_LEVEL); -#if DT_HAS_COMPAT_STATUS_OKAY(semtech_sx1261) -#define DT_DRV_COMPAT semtech_sx1261 -#define SX126X_DEVICE_ID SX1261 -#elif DT_HAS_COMPAT_STATUS_OKAY(semtech_sx1262) -#define DT_DRV_COMPAT semtech_sx1262 -#define SX126X_DEVICE_ID SX1262 -#else -#error No SX126x instance in device tree. -#endif - BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(semtech_sx1261) + DT_NUM_INST_STATUS_OKAY(semtech_sx1262) <= 1, "Multiple SX126x instances in DT"); -#define HAVE_GPIO_CS DT_INST_SPI_DEV_HAS_CS_GPIOS(0) -#define HAVE_GPIO_ANTENNA_ENABLE \ - DT_INST_NODE_HAS_PROP(0, antenna_enable_gpios) -#define HAVE_GPIO_TX_ENABLE DT_INST_NODE_HAS_PROP(0, tx_enable_gpios) -#define HAVE_GPIO_RX_ENABLE DT_INST_NODE_HAS_PROP(0, rx_enable_gpios) - -#define GPIO_CS_LABEL DT_INST_SPI_DEV_CS_GPIOS_LABEL(0) -#define GPIO_CS_PIN DT_INST_SPI_DEV_CS_GPIOS_PIN(0) -#define GPIO_CS_FLAGS DT_INST_SPI_DEV_CS_GPIOS_FLAGS(0) - -#define GPIO_RESET_PIN DT_INST_GPIO_PIN(0, reset_gpios) -#define GPIO_BUSY_PIN DT_INST_GPIO_PIN(0, busy_gpios) -#define GPIO_DIO1_PIN DT_INST_GPIO_PIN(0, dio1_gpios) -#define GPIO_ANTENNA_ENABLE_PIN DT_INST_GPIO_PIN(0, antenna_enable_gpios) -#define GPIO_TX_ENABLE_PIN DT_INST_GPIO_PIN(0, tx_enable_gpios) -#define GPIO_RX_ENABLE_PIN DT_INST_GPIO_PIN(0, rx_enable_gpios) - #define DIO2_TX_ENABLE DT_INST_PROP(0, dio2_tx_enable) #define HAVE_DIO3_TCXO DT_INST_NODE_HAS_PROP(0, dio3_tcxo_voltage) @@ -64,30 +38,7 @@ BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(semtech_sx1261) + #define SX126X_CALIBRATION_ALL 0x7f -struct sx126x_data { - const struct device *reset; - const struct device *busy; - const struct device *dio1; - struct gpio_callback dio1_irq_callback; - struct k_work dio1_irq_work; - DioIrqHandler *radio_dio_irq; -#if HAVE_GPIO_ANTENNA_ENABLE - const struct device *antenna_enable; -#endif -#if HAVE_GPIO_TX_ENABLE - const struct device *tx_enable; -#endif -#if HAVE_GPIO_RX_ENABLE - const struct device *rx_enable; -#endif - const struct device *spi; - struct spi_config spi_cfg; -#if HAVE_GPIO_CS - struct spi_cs_control spi_cs; -#endif - RadioOperatingModes_t mode; -} dev_data; - +static struct sx126x_data dev_data; void SX126xWaitOnBusy(void); @@ -333,8 +284,7 @@ void SX126xSetOperatingMode(RadioOperatingModes_t mode) case MODE_SLEEP: /* Additionally disable the DIO1 interrupt to save power */ - gpio_pin_interrupt_configure(dev_data.dio1, GPIO_DIO1_PIN, - GPIO_INT_DISABLE); + sx126x_dio1_irq_disable(&dev_data); __fallthrough; default: sx126x_set_rx_enable(0); @@ -386,10 +336,9 @@ void SX126xIoRfSwitchInit(void) void SX126xReset(void) { LOG_DBG("Resetting radio"); - gpio_pin_set(dev_data.reset, GPIO_RESET_PIN, 1); - k_sleep(K_MSEC(20)); - gpio_pin_set(dev_data.reset, GPIO_RESET_PIN, 0); - k_sleep(K_MSEC(10)); + + sx126x_reset(&dev_data); + /* Device transitions to standby on reset */ dev_data.mode = MODE_STDBY_RC; } @@ -402,7 +351,7 @@ void SX126xSetRfTxPower(int8_t power) void SX126xWaitOnBusy(void) { - while (gpio_pin_get(dev_data.busy, GPIO_BUSY_PIN)) { + while (sx126x_is_busy(&dev_data)) { k_sleep(K_MSEC(1)); } } @@ -412,8 +361,7 @@ void SX126xWakeup(void) int ret; /* Reenable DIO1 when waking up */ - gpio_pin_interrupt_configure(dev_data.dio1, GPIO_DIO1_PIN, - GPIO_INT_EDGE_TO_ACTIVE); + sx126x_dio1_irq_enable(&dev_data); uint8_t req[] = { RADIO_GET_STATUS, 0 }; const struct spi_buf tx_buf = { @@ -445,7 +393,7 @@ void SX126xWakeup(void) uint32_t SX126xGetDio1PinState(void) { - return gpio_pin_get(dev_data.dio1, GPIO_DIO1_PIN) > 0 ? 1U : 0U; + return sx126x_get_dio1_pin_state(&dev_data); } static void sx126x_dio1_irq_work_handler(struct k_work *work) @@ -460,14 +408,8 @@ static void sx126x_dio1_irq_work_handler(struct k_work *work) if (Radio.IrqProcess) { Radio.IrqProcess(); } -} -static void sx126x_dio1_irq_callback(const struct device *dev, - struct gpio_callback *cb, uint32_t pins) -{ - if (pins & BIT(GPIO_DIO1_PIN)) { - k_work_submit(&dev_data.dio1_irq_work); - } + sx126x_dio1_irq_enable(&dev_data); } static int sx126x_lora_init(const struct device *dev) @@ -487,11 +429,10 @@ static int sx126x_lora_init(const struct device *dev) k_work_init(&dev_data.dio1_irq_work, sx126x_dio1_irq_work_handler); - gpio_init_callback(&dev_data.dio1_irq_callback, - sx126x_dio1_irq_callback, BIT(GPIO_DIO1_PIN)); - if (gpio_add_callback(dev_data.dio1, &dev_data.dio1_irq_callback) < 0) { - LOG_ERR("Could not set GPIO callback for DIO1 interrupt."); - return -EIO; + ret = sx126x_variant_init(dev); + if (ret) { + LOG_ERR("Variant initialization failed"); + return ret; } dev_data.spi = device_get_binding(DT_INST_BUS_LABEL(0)); @@ -535,6 +476,6 @@ static const struct lora_driver_api sx126x_lora_api = { .test_cw = sx12xx_lora_test_cw, }; -DEVICE_DT_INST_DEFINE(0, &sx126x_lora_init, NULL, NULL, +DEVICE_DT_INST_DEFINE(0, &sx126x_lora_init, NULL, &dev_data, NULL, POST_KERNEL, CONFIG_LORA_INIT_PRIORITY, &sx126x_lora_api); diff --git a/drivers/lora/sx126x_common.h b/drivers/lora/sx126x_common.h new file mode 100644 index 00000000000..120b987390c --- /dev/null +++ b/drivers/lora/sx126x_common.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2019 Manivannan Sadhasivam + * Copyright (c) 2020 Andreas Sandberg + * Copyright (c) 2021 Fabio Baltieri + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SX126X_COMMON_H_ +#define ZEPHYR_DRIVERS_SX126X_COMMON_H_ + +#include +#include +#include +#include + +#include + +#if DT_HAS_COMPAT_STATUS_OKAY(semtech_sx1261) +#define DT_DRV_COMPAT semtech_sx1261 +#define SX126X_DEVICE_ID SX1261 +#elif DT_HAS_COMPAT_STATUS_OKAY(semtech_sx1262) +#define DT_DRV_COMPAT semtech_sx1262 +#define SX126X_DEVICE_ID SX1262 +#else +#error No SX126x instance in device tree. +#endif + +#define HAVE_GPIO_CS DT_INST_SPI_DEV_HAS_CS_GPIOS(0) +#define HAVE_GPIO_ANTENNA_ENABLE \ + DT_INST_NODE_HAS_PROP(0, antenna_enable_gpios) +#define HAVE_GPIO_TX_ENABLE DT_INST_NODE_HAS_PROP(0, tx_enable_gpios) +#define HAVE_GPIO_RX_ENABLE DT_INST_NODE_HAS_PROP(0, rx_enable_gpios) + +#define GPIO_CS_LABEL DT_INST_SPI_DEV_CS_GPIOS_LABEL(0) +#define GPIO_CS_PIN DT_INST_SPI_DEV_CS_GPIOS_PIN(0) +#define GPIO_CS_FLAGS DT_INST_SPI_DEV_CS_GPIOS_FLAGS(0) + +#define GPIO_ANTENNA_ENABLE_PIN DT_INST_GPIO_PIN(0, antenna_enable_gpios) +#define GPIO_TX_ENABLE_PIN DT_INST_GPIO_PIN(0, tx_enable_gpios) +#define GPIO_RX_ENABLE_PIN DT_INST_GPIO_PIN(0, rx_enable_gpios) + +struct sx126x_data { + const struct device *reset; + const struct device *busy; + const struct device *dio1; + struct gpio_callback dio1_irq_callback; + struct k_work dio1_irq_work; + DioIrqHandler *radio_dio_irq; +#if HAVE_GPIO_ANTENNA_ENABLE + const struct device *antenna_enable; +#endif +#if HAVE_GPIO_TX_ENABLE + const struct device *tx_enable; +#endif +#if HAVE_GPIO_RX_ENABLE + const struct device *rx_enable; +#endif + const struct device *spi; + struct spi_config spi_cfg; +#if HAVE_GPIO_CS + struct spi_cs_control spi_cs; +#endif + RadioOperatingModes_t mode; +}; + +void sx126x_reset(struct sx126x_data *dev_data); + +bool sx126x_is_busy(struct sx126x_data *dev_data); + +uint32_t sx126x_get_dio1_pin_state(struct sx126x_data *dev_data); + +void sx126x_dio1_irq_enable(struct sx126x_data *dev_data); + +void sx126x_dio1_irq_disable(struct sx126x_data *dev_data); + +int sx126x_variant_init(const struct device *dev); + +#endif /* ZEPHYR_DRIVERS_SX126X_COMMON_H_ */ diff --git a/drivers/lora/sx126x_standalone.c b/drivers/lora/sx126x_standalone.c new file mode 100644 index 00000000000..c39532cada3 --- /dev/null +++ b/drivers/lora/sx126x_standalone.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2019 Manivannan Sadhasivam + * Copyright (c) 2020 Andreas Sandberg + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "sx126x_common.h" + +#include +LOG_MODULE_DECLARE(sx126x, CONFIG_LORA_LOG_LEVEL); + +#define GPIO_RESET_PIN DT_INST_GPIO_PIN(0, reset_gpios) +#define GPIO_BUSY_PIN DT_INST_GPIO_PIN(0, busy_gpios) +#define GPIO_DIO1_PIN DT_INST_GPIO_PIN(0, dio1_gpios) + +void sx126x_reset(struct sx126x_data *dev_data) +{ + gpio_pin_set(dev_data->reset, GPIO_RESET_PIN, 1); + k_sleep(K_MSEC(20)); + gpio_pin_set(dev_data->reset, GPIO_RESET_PIN, 0); + k_sleep(K_MSEC(10)); +} + +bool sx126x_is_busy(struct sx126x_data *dev_data) +{ + return gpio_pin_get(dev_data->busy, GPIO_BUSY_PIN); +} + +uint32_t sx126x_get_dio1_pin_state(struct sx126x_data *dev_data) +{ + return gpio_pin_get(dev_data->dio1, GPIO_DIO1_PIN) > 0 ? 1U : 0U; +} + +void sx126x_dio1_irq_enable(struct sx126x_data *dev_data) +{ + gpio_pin_interrupt_configure(dev_data->dio1, GPIO_DIO1_PIN, + GPIO_INT_EDGE_TO_ACTIVE); +} + +void sx126x_dio1_irq_disable(struct sx126x_data *dev_data) +{ + gpio_pin_interrupt_configure(dev_data->dio1, GPIO_DIO1_PIN, + GPIO_INT_DISABLE); +} + +static void sx126x_dio1_irq_callback(const struct device *dev, + struct gpio_callback *cb, uint32_t pins) +{ + struct sx126x_data *dev_data = dev->data; + + if (pins & BIT(GPIO_DIO1_PIN)) { + k_work_submit(&dev_data->dio1_irq_work); + } +} + +int sx126x_variant_init(const struct device *dev) +{ + struct sx126x_data *dev_data = dev->data; + + gpio_init_callback(&dev_data->dio1_irq_callback, + sx126x_dio1_irq_callback, BIT(GPIO_DIO1_PIN)); + if (gpio_add_callback(dev_data->dio1, &dev_data->dio1_irq_callback) < 0) { + LOG_ERR("Could not set GPIO callback for DIO1 interrupt."); + return -EIO; + } + + return 0; +}