1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-26 23:11:19 +01:00

Merge pull request #16752 from benpicco/drivers/dose-standby

drivers/dose: enable standby pin
This commit is contained in:
benpicco 2021-11-09 18:20:17 +01:00 committed by GitHub
commit 12ade5a8b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 85 additions and 9 deletions

View File

@ -48,6 +48,7 @@ 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 uint16_t crc16_update(uint16_t crc, uint8_t octet)
@ -60,6 +61,15 @@ static uint16_t crc16_update(uint16_t crc, uint8_t octet)
return crc;
}
static void _init_standby(dose_t *ctx, const dose_params_t *params)
{
ctx->standby_pin = params->standby_pin;
if (gpio_is_valid(ctx->standby_pin) &&
gpio_init(ctx->standby_pin, GPIO_OUT)) {
gpio_clear(ctx->standby_pin);
}
}
static void _init_sense(dose_t *ctx, const dose_params_t *params)
{
#ifdef MODULE_PERIPH_UART_RXSTART_IRQ
@ -389,8 +399,8 @@ static int send_octet(dose_t *ctx, uint8_t c)
uart_write(ctx->uart, (uint8_t *) &c, sizeof(c));
/* Wait for a state transition */
uint8_t state = wait_for_state(ctx, DOSE_STATE_ANY);
if (state != DOSE_STATE_SEND) {
uint8_t new_state = wait_for_state(ctx, DOSE_STATE_ANY);
if (new_state != DOSE_STATE_SEND) {
/* Timeout */
DEBUG("dose send_octet(): timeout\n");
return -2;
@ -429,6 +439,16 @@ static int _send(netdev_t *dev, const iolist_t *iolist)
size_t pktlen;
uint16_t crc;
/* discard data when interface is in SLEEP mode */
if (ctx->state == DOSE_STATE_SLEEP) {
return -ENETDOWN;
}
/* sending data wakes the interface from STANDBY */
if (ctx->state == DOSE_STATE_STANDBY) {
_set_state(ctx, NETOPT_STATE_IDLE);
}
send:
crc = 0xffff;
pktlen = 0;
@ -517,6 +537,45 @@ 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)
{
if (gpio_is_valid(pin)) {
gpio_set(pin);
}
}
static void _gpio_try_clear(gpio_t pin)
{
if (gpio_is_valid(pin)) {
gpio_clear(pin);
}
}
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;
return sizeof(netopt_state_t);
case NETOPT_STATE_SLEEP:
_gpio_try_set(ctx->standby_pin);
uart_poweroff(ctx->uart);
ctx->state = 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;
return sizeof(netopt_state_t);
default:
break;
}
return -ENOTSUP;
}
static int _set(netdev_t *dev, netopt_t opt, const void *value, size_t len)
{
dose_t *ctx = container_of(dev, dose_t, netdev);
@ -539,6 +598,9 @@ static int _set(netdev_t *dev, netopt_t opt, const void *value, size_t len)
CLRBIT(ctx->opts, DOSE_OPT_PROMISCUOUS);
}
return sizeof(netopt_enable_t);
case NETOPT_STATE:
assert(len <= sizeof(netopt_state_t));
return _set_state(ctx, *((const netopt_state_t *)value));
default:
return netdev_eth_set(dev, opt, value, len);
}
@ -585,6 +647,7 @@ void dose_setup(dose_t *ctx, const dose_params_t *params, uint8_t index)
uart_init(ctx->uart, params->baudrate, _isr_uart, (void *) ctx);
_init_sense(ctx, params);
_init_standby(ctx, params);
netdev_register(&ctx->netdev, NETDEV_DOSE, index);

View File

@ -38,16 +38,25 @@ extern "C" {
#ifndef DOSE_PARAM_SENSE_PIN
#define DOSE_PARAM_SENSE_PIN (GPIO_UNDEF)
#endif
#ifndef DOSE_PARAM_STANDBY_PIN
#define DOSE_PARAM_STANDBY_PIN (GPIO_UNDEF) /**< Standby/Silent mode */
#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
#define DOSE_PARAMS { \
.uart = DOSE_PARAM_UART, \
.baudrate = DOSE_PARAM_BAUDRATE, \
.standby_pin = DOSE_PARAM_STANDBY_PIN, \
}
#else /* MODULE_PERIPH_UART_RXSTART_IRQ */
#define DOSE_PARAMS { \
.uart = DOSE_PARAM_UART, \
.baudrate = DOSE_PARAM_BAUDRATE, \
.standby_pin = DOSE_PARAM_STANDBY_PIN, \
.sense_pin = DOSE_PARAM_SENSE_PIN, \
}
#endif /* !MODULE_PERIPH_UART_RXSTART_IRQ */
#endif
/**@}*/

View File

@ -87,6 +87,8 @@ typedef enum {
DOSE_STATE_IDLE = 0x02, /**< Frames will be received or sent */
DOSE_STATE_RECV = 0x03, /**< Currently receiving a frame */
DOSE_STATE_SEND = 0x04, /**< Currently sending a frame */
DOSE_STATE_STANDBY = 0x05, /**< Receiver is turned off, but send will wake it up */
DOSE_STATE_SLEEP = 0x06, /**< Receiver is turned off and send will be discarded */
DOSE_STATE_ANY = 0x0F /**< Special state filter used internally to observe any state transition */
} dose_state_t;
@ -158,6 +160,7 @@ typedef struct {
#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
gpio_t standby_pin; /**< GPIO to put the CAN transceiver in standby mode */
xtimer_t timeout; /**< Timeout timer ensuring always to get back to IDLE state */
uint32_t timeout_base; /**< Base timeout in us */
} dose_t;
@ -170,6 +173,7 @@ typedef struct {
#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
gpio_t standby_pin; /**< GPIO to put the CAN transceiver in standby mode */
uint32_t baudrate; /**< Baudrate to UART device */
} dose_params_t;