From d48f673597c827b1344fe595256f2e4879f5d55b Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Thu, 27 May 2021 22:20:53 +0200 Subject: [PATCH] drivers/dose: make use of periph_uart_rx_start feature --- drivers/dose/Makefile.dep | 1 + drivers/dose/dose.c | 60 ++++++++++++++++++++++-------- drivers/dose/include/dose_params.h | 5 +++ drivers/include/dose.h | 7 +++- 4 files changed, 57 insertions(+), 16 deletions(-) diff --git a/drivers/dose/Makefile.dep b/drivers/dose/Makefile.dep index 07fc6ad171..a2b81d4233 100644 --- a/drivers/dose/Makefile.dep +++ b/drivers/dose/Makefile.dep @@ -1,5 +1,6 @@ FEATURES_REQUIRED += periph_gpio_irq FEATURES_REQUIRED += periph_uart +FEATURES_OPTIONAL += periph_uart_rxstart_irq USEMODULE += eui_provider USEMODULE += iolist diff --git a/drivers/dose/dose.c b/drivers/dose/dose.c index e4e882fdd1..4cc207adbf 100644 --- a/drivers/dose/dose.c +++ b/drivers/dose/dose.c @@ -60,6 +60,42 @@ static uint16_t crc16_update(uint16_t crc, uint8_t octet) return crc; } +static void _init_sense(dose_t *ctx, const dose_params_t *params) +{ +#ifdef MODULE_PERIPH_UART_RXSTART_IRQ + (void)params; + uart_rxstart_irq_configure(ctx->uart, _isr_gpio, ctx); +#else + ctx->sense_pin = params->sense_pin; + if (gpio_is_valid(ctx->sense_pin)) { + gpio_init_int(ctx->sense_pin, GPIO_IN, GPIO_FALLING, _isr_gpio, ctx); + gpio_irq_disable(ctx->sense_pin); + } +#endif +} + +static inline void _enable_sense(dose_t *ctx) +{ +#ifdef MODULE_PERIPH_UART_RXSTART_IRQ + uart_rxstart_irq_enable(ctx->uart); +#else + if (gpio_is_valid(ctx->sense_pin)) { + gpio_irq_enable(ctx->sense_pin); + } +#endif +} + +static inline void _disable_sense(dose_t *ctx) +{ +#ifdef MODULE_PERIPH_UART_RXSTART_IRQ + uart_rxstart_irq_disable(ctx->uart); +#else + if (gpio_is_valid(ctx->sense_pin)) { + gpio_irq_disable(ctx->sense_pin); + } +#endif +} + static dose_signal_t state_transit_blocked(dose_t *ctx, dose_signal_t signal) { uint32_t backoff; @@ -73,10 +109,8 @@ static dose_signal_t state_transit_blocked(dose_t *ctx, dose_signal_t signal) netdev_trigger_event_isr((netdev_t *) ctx); } - if (gpio_is_valid(ctx->sense_pin)) { - /* Enable GPIO interrupt for start bit sensing */ - gpio_irq_enable(ctx->sense_pin); - } + /* Enable interrupt for start bit sensing */ + _enable_sense(ctx); /* The timeout will bring us back into IDLE state by a random time. * If we entered this state from RECV state, the random time lays @@ -107,10 +141,10 @@ static dose_signal_t state_transit_recv(dose_t *ctx, dose_signal_t signal) { dose_signal_t rc = DOSE_SIGNAL_NONE; - if (ctx->state != DOSE_STATE_RECV && gpio_is_valid(ctx->sense_pin)) { + if (ctx->state != DOSE_STATE_RECV) { /* We freshly entered this state. Thus, no start bit sensing is required - * anymore. Disable GPIO IRQs during the transmission. */ - gpio_irq_disable(ctx->sense_pin); + * anymore. Disable RX Start IRQs during the transmission. */ + _disable_sense(ctx); } if (signal == DOSE_SIGNAL_UART) { @@ -149,9 +183,9 @@ static dose_signal_t state_transit_send(dose_t *ctx, dose_signal_t signal) { (void) signal; - if (ctx->state != DOSE_STATE_SEND && gpio_is_valid(ctx->sense_pin)) { - /* Disable GPIO IRQs during the transmission. */ - gpio_irq_disable(ctx->sense_pin); + if (ctx->state != DOSE_STATE_SEND) { + /* Disable RX Start IRQs during the transmission. */ + _disable_sense(ctx); } /* Don't trace any END octets ... the timeout or the END signal @@ -550,11 +584,7 @@ void dose_setup(dose_t *ctx, const dose_params_t *params, uint8_t index) ctx->uart = params->uart; uart_init(ctx->uart, params->baudrate, _isr_uart, (void *) ctx); - ctx->sense_pin = params->sense_pin; - if (gpio_is_valid(ctx->sense_pin)) { - gpio_init_int(ctx->sense_pin, GPIO_IN, GPIO_FALLING, _isr_gpio, (void *) ctx); - gpio_irq_disable(ctx->sense_pin); - } + _init_sense(ctx, params); netdev_register(&ctx->netdev, NETDEV_DOSE, index); diff --git a/drivers/dose/include/dose_params.h b/drivers/dose/include/dose_params.h index e91c01b5b6..f493f41365 100644 --- a/drivers/dose/include/dose_params.h +++ b/drivers/dose/include/dose_params.h @@ -40,10 +40,15 @@ extern "C" { #endif #ifndef DOSE_PARAMS +#ifdef MODULE_PERIPH_UART_RXSTART_IRQ +#define DOSE_PARAMS { .uart = DOSE_PARAM_UART, \ + .baudrate = DOSE_PARAM_BAUDRATE } +#else #define DOSE_PARAMS { .uart = DOSE_PARAM_UART, \ .baudrate = DOSE_PARAM_BAUDRATE, \ .sense_pin = DOSE_PARAM_SENSE_PIN } #endif +#endif /**@}*/ /** diff --git a/drivers/include/dose.h b/drivers/include/dose.h index 0fad35cc69..7a3479d29b 100644 --- a/drivers/include/dose.h +++ b/drivers/include/dose.h @@ -31,7 +31,8 @@ * you could use an IC such as the SN65HVD233.) * * Basically, UART TX and RX are connected to respective pins of the - * transceiver. In addition, the RX pin can also be connected to the sense GPIO. + * transceiver. In addition, the RX pin can also be connected to the sense GPIO + * if the UART does not implement the `periph_uart_rxstart_irq` feature. * In this case, the bus allocation can be detected more precisely and * collisions are less likely. * @@ -157,7 +158,9 @@ typedef struct { size_t recv_buf_ptr; /**< Index of the next empty octet of the recveive buffer */ uart_t uart; /**< UART device to use */ uint8_t uart_octet; /**< Last received octet */ +#if !defined(MODULE_PERIPH_UART_RXSTART_IRQ) || DOXYGEN gpio_t sense_pin; /**< GPIO to sense for start bits on the UART's rx line */ +#endif xtimer_t timeout; /**< Timeout timer ensuring always to get back to IDLE state */ uint32_t timeout_base; /**< Base timeout in us */ } dose_t; @@ -167,7 +170,9 @@ typedef struct { */ typedef struct { uart_t uart; /**< UART device to use */ +#if !defined(MODULE_PERIPH_UART_RXSTART_IRQ) || DOXYGEN gpio_t sense_pin; /**< GPIO to sense for start bits on the UART's rx line */ +#endif uint32_t baudrate; /**< Baudrate to UART device */ } dose_params_t;