diff --git a/drivers/lora/sx126x.c b/drivers/lora/sx126x.c index 477e417bd9f..8b295dc940b 100644 --- a/drivers/lora/sx126x.c +++ b/drivers/lora/sx126x.c @@ -470,6 +470,7 @@ static int sx126x_lora_init(const struct device *dev) static const struct lora_driver_api sx126x_lora_api = { .config = sx12xx_lora_config, .send = sx12xx_lora_send, + .send_async = sx12xx_lora_send_async, .recv = sx12xx_lora_recv, .test_cw = sx12xx_lora_test_cw, }; diff --git a/drivers/lora/sx127x.c b/drivers/lora/sx127x.c index 5cac0bab4b4..7424ef1b0ec 100644 --- a/drivers/lora/sx127x.c +++ b/drivers/lora/sx127x.c @@ -658,6 +658,7 @@ static int sx127x_lora_init(const struct device *dev) static const struct lora_driver_api sx127x_lora_api = { .config = sx12xx_lora_config, .send = sx12xx_lora_send, + .send_async = sx12xx_lora_send_async, .recv = sx12xx_lora_recv, .test_cw = sx12xx_lora_test_cw, }; diff --git a/drivers/lora/sx12xx_common.c b/drivers/lora/sx12xx_common.c index 5baa69da364..28debdbd1f9 100644 --- a/drivers/lora/sx12xx_common.c +++ b/drivers/lora/sx12xx_common.c @@ -142,17 +142,48 @@ static void sx12xx_ev_rx_done(uint8_t *payload, uint16_t size, int16_t rssi, static void sx12xx_ev_tx_done(void) { + struct k_poll_signal *sig = dev_data.operation_done; + modem_release(&dev_data); + + /* Raise signal if provided */ + if (sig) { + k_poll_signal_raise(sig, 0); + } } int sx12xx_lora_send(const struct device *dev, uint8_t *data, uint32_t data_len) { - /* Ensure available, decremented by sx12xx_ev_tx_done */ + struct k_poll_signal done = K_POLL_SIGNAL_INITIALIZER(done); + struct k_poll_event evt = K_POLL_EVENT_INITIALIZER( + K_POLL_TYPE_SIGNAL, + K_POLL_MODE_NOTIFY_ONLY, + &done); + int ret; + + ret = sx12xx_lora_send_async(dev, data, data_len, &done); + if (ret < 0) { + return ret; + } + + /* Wait for transmission to complete */ + k_poll(&evt, 1, K_FOREVER); + + return 0; +} + +int sx12xx_lora_send_async(const struct device *dev, uint8_t *data, + uint32_t data_len, struct k_poll_signal *async) +{ + /* Ensure available, freed by sx12xx_ev_tx_done */ if (!modem_acquire(&dev_data)) { return -EBUSY; } + /* Store signal */ + dev_data.operation_done = async; + Radio.SetMaxPayloadLength(MODEM_LORA, data_len); Radio.Send(data, data_len); diff --git a/drivers/lora/sx12xx_common.h b/drivers/lora/sx12xx_common.h index c66467dfa3d..0d11545cb62 100644 --- a/drivers/lora/sx12xx_common.h +++ b/drivers/lora/sx12xx_common.h @@ -28,6 +28,9 @@ int __sx12xx_configure_pin(const struct device * *dev, const char *controller, int sx12xx_lora_send(const struct device *dev, uint8_t *data, uint32_t data_len); +int sx12xx_lora_send_async(const struct device *dev, uint8_t *data, + uint32_t data_len, struct k_poll_signal *async); + int sx12xx_lora_recv(const struct device *dev, uint8_t *data, uint8_t size, k_timeout_t timeout, int16_t *rssi, int8_t *snr); diff --git a/include/drivers/lora.h b/include/drivers/lora.h index f13bef70720..8c63d68a613 100644 --- a/include/drivers/lora.h +++ b/include/drivers/lora.h @@ -70,6 +70,16 @@ typedef int (*lora_api_config)(const struct device *dev, typedef int (*lora_api_send)(const struct device *dev, uint8_t *data, uint32_t data_len); +/** + * @typedef lora_api_send_async() + * @brief Callback API for sending data asynchronously over LoRa + * + * @see lora_send_async() for argument descriptions. + */ +typedef int (*lora_api_send_async)(const struct device *dev, + uint8_t *data, uint32_t data_len, + struct k_poll_signal *async); + /** * @typedef lora_api_recv() * @brief Callback API for receiving data over LoRa @@ -91,8 +101,9 @@ typedef int (*lora_api_test_cw)(const struct device *dev, uint32_t frequency, struct lora_driver_api { lora_api_config config; - lora_api_send send; - lora_api_recv recv; + lora_api_send send; + lora_api_send_async send_async; + lora_api_recv recv; lora_api_test_cw test_cw; }; @@ -116,7 +127,7 @@ static inline int lora_config(const struct device *dev, /** * @brief Send data over LoRa * - * @note This is a non-blocking call. + * @note This blocks until transmission is complete. * * @param dev LoRa device * @param data Data to be sent @@ -132,6 +143,30 @@ static inline int lora_send(const struct device *dev, return api->send(dev, data, data_len); } +/** + * @brief Asynchronously send data over LoRa + * + * @note This returns immediately after starting transmission, and locks + * the LoRa modem until the transmission completes. + * + * @param dev LoRa device + * @param data Data to be sent + * @param data_len Length of the data to be sent + * @param async A pointer to a valid and ready to be signaled + * struct k_poll_signal. (Note: if NULL this function will not + * notify the end of the transmission). + * @return 0 on success, negative on error + */ +static inline int lora_send_async(const struct device *dev, + uint8_t *data, uint32_t data_len, + struct k_poll_signal *async) +{ + const struct lora_driver_api *api = + (const struct lora_driver_api *)dev->api; + + return api->send_async(dev, data, data_len, async); +} + /** * @brief Receive data over LoRa *