From 1ef458a701fea88326a19fc686fc27012f2090b2 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Thu, 11 Nov 2021 14:32:42 +0100 Subject: [PATCH 1/3] cpu/sam0_common: uart: wait for synchronisation done after powerup Otherwise we lose settings if we write to it right after uart_poweron() --- cpu/sam0_common/periph/uart.c | 1 + 1 file changed, 1 insertion(+) diff --git a/cpu/sam0_common/periph/uart.c b/cpu/sam0_common/periph/uart.c index dc8fb6a224..7dfe786dae 100644 --- a/cpu/sam0_common/periph/uart.c +++ b/cpu/sam0_common/periph/uart.c @@ -314,6 +314,7 @@ void uart_poweron(uart_t uart) { sercom_clk_en(dev(uart)); dev(uart)->CTRLA.reg |= SERCOM_USART_CTRLA_ENABLE; + _syncbusy(dev(uart)); } void uart_poweroff(uart_t uart) From 32c29bf062055ddc79838b7f8ed186a675d3faf0 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Thu, 11 Nov 2021 14:33:55 +0100 Subject: [PATCH 2/3] drivers/dose: fix standby mode Previously we would not disable the sense pin, this meant that a node could still wake up if the standby pin is not connected. Properly disable sensing when in standby and wait for a state transition to IDLE to avoid aborting a reception and messing up the DOSE internal state. --- drivers/dose/dose.c | 53 ++++++++++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/drivers/dose/dose.c b/drivers/dose/dose.c index 470db77406..3be9a0b942 100644 --- a/drivers/dose/dose.c +++ b/drivers/dose/dose.c @@ -48,8 +48,9 @@ static int send_octet(dose_t *ctx, uint8_t c); static int _send(netdev_t *dev, const iolist_t *iolist); static int _get(netdev_t *dev, netopt_t opt, void *value, size_t max_len); static int _set(netdev_t *dev, netopt_t opt, const void *value, size_t len); -static int _set_state(dose_t *ctx, netopt_state_t state); static int _init(netdev_t *dev); +static void _poweron(dose_t *dev); +static void _poweroff(dose_t *dev, dose_state_t sleep_state); static uint16_t crc16_update(uint16_t crc, uint8_t octet) { @@ -446,7 +447,7 @@ static int _send(netdev_t *dev, const iolist_t *iolist) /* sending data wakes the interface from STANDBY */ if (ctx->state == DOSE_STATE_STANDBY) { - _set_state(ctx, NETOPT_STATE_IDLE); + _poweron(ctx); } send: @@ -537,37 +538,55 @@ static int _get(netdev_t *dev, netopt_t opt, void *value, size_t max_len) return 0; } -static void _gpio_try_set(gpio_t pin) +static void _poweron(dose_t *ctx) { - if (gpio_is_valid(pin)) { - gpio_set(pin); + /* interface is already powered on - do nothing */ + if (ctx->state != DOSE_STATE_STANDBY && + ctx->state != DOSE_STATE_SLEEP) { + return; } + + if (gpio_is_valid(ctx->standby_pin)) { + gpio_clear(ctx->standby_pin); + } + + uart_poweron(ctx->uart); + _enable_sense(ctx); + + ctx->state = DOSE_STATE_IDLE; } -static void _gpio_try_clear(gpio_t pin) +static void _poweroff(dose_t *ctx, dose_state_t sleep_state) { - if (gpio_is_valid(pin)) { - gpio_clear(pin); + /* interface is already powered off - do nothing */ + if (ctx->state == DOSE_STATE_STANDBY || + ctx->state == DOSE_STATE_SLEEP) { + return; } + + wait_for_state(ctx, DOSE_STATE_IDLE); + + if (gpio_is_valid(ctx->standby_pin)) { + gpio_set(ctx->standby_pin); + } + + _disable_sense(ctx); + uart_poweroff(ctx->uart); + + ctx->state = sleep_state; } static int _set_state(dose_t *ctx, netopt_state_t state) { switch (state) { case NETOPT_STATE_STANDBY: - _gpio_try_set(ctx->standby_pin); - uart_poweroff(ctx->uart); - ctx->state = DOSE_STATE_STANDBY; + _poweroff(ctx, DOSE_STATE_STANDBY); return sizeof(netopt_state_t); case NETOPT_STATE_SLEEP: - _gpio_try_set(ctx->standby_pin); - uart_poweroff(ctx->uart); - ctx->state = DOSE_STATE_SLEEP; + _poweroff(ctx, DOSE_STATE_SLEEP); return sizeof(netopt_state_t); case NETOPT_STATE_IDLE: - uart_poweron(ctx->uart); - _gpio_try_clear(ctx->standby_pin); - ctx->state = DOSE_STATE_IDLE; + _poweron(ctx); return sizeof(netopt_state_t); default: break; From 965fa3ef10a3b8a28f2486bd19b0a7566b45bc06 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Thu, 11 Nov 2021 14:43:07 +0100 Subject: [PATCH 3/3] drivers/dose: clarify timeout calculation --- drivers/dose/dose.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/dose/dose.c b/drivers/dose/dose.c index 3be9a0b942..38b0e4f290 100644 --- a/drivers/dose/dose.c +++ b/drivers/dose/dose.c @@ -680,7 +680,10 @@ void dose_setup(dose_t *ctx, const dose_params_t *params, uint8_t index) /* The timeout base is the minimal timeout base used for this driver. * We have to ensure it is above the XTIMER_BACKOFF. Otherwise state * transitions are triggered from another state transition setting up the - * timeout. */ + * timeout. + * To calculate how long it takes to transfer one byte we assume + * 8 data bits + 1 start bit + 1 stop bit per byte. + */ ctx->timeout_base = CONFIG_DOSE_TIMEOUT_BYTES * 10UL * US_PER_SEC / params->baudrate; if (ctx->timeout_base < xtimer_usec_from_ticks(min_timeout)) { ctx->timeout_base = xtimer_usec_from_ticks(min_timeout);