Driver for connecting RIOT devices using a single bus wire. More...
Driver for connecting RIOT devices using a single bus wire.
This driver enables RIOT nodes to communicate by Ethernet over a serial bus. This enables them to interact in an easy and cheap manner using a single bus wire with very low hardware requirements: The used microcontrollers just need to feature at least one UART and one optional GPIO that is able to raise interrupts.
For bus access, you need a CAN transceiver, since the DOSE uses the PHY layer of CAN for the electrical connection of the nodes. Every transceiver IC operating with the right voltage levels should do. (If you are on a 3.3V MCU, 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 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.
Some technical details for those interested: The Ethernet frames are sent onto the bus using uart_write()
while observing the received echo from the bus. This way collisions are detected (received echo != transmitted octet) and retransmissions are scheduled. The frames are appended with a CRC16 to protect the system from transmission errors.
When using high UART data rates (1 MBit/s and above) per-byte overhead becomes significant. A major factor here is setting (software) timers which are used to catch error conditions. To speed up the TX path it is therefore recommended to implement hardware collision detection (if available) to avoid the need for setting a timeout for each byte transmitted.
To speed up the more critical RX path, enable the dose_watchdog
module. This requires a dedicated hardware timer DOSE_TIMER_DEV
to be configured in e.g. board.h
. The timer is shared between all DOSE interfaces and will periodically check if any interface does not make progress with receiving a frame (payload marker did not advance between two timer periods) and abort the RX process.
Modules | |
Differentially Operated Serial Ethernet (DOSE) driver compile configuration | |
Files | |
file | dose_params.h |
Default configuration for the Differentially Operated Serial Ethernet driver. | |
file | dose.h |
Driver for the Differentially Operated Serial Ethernet module. | |
Data Structures | |
struct | dose_t |
DOSE netdev device. More... | |
struct | dose_params_t |
Struct containing the required configuration. More... | |
Macros | |
#define | DOSE_FRAME_CRC_LEN (2) |
CRC16 is used. | |
#define | CONFIG_DOSE_RX_BUF_LEN (ETHERNET_FRAME_LEN + DOSE_FRAME_CRC_LEN) |
DOSE RX buffer length Should be large enough to fit at least one Ethernet frame. | |
#define | DOSE_TIMER_DEV TIMER_DEV(…) |
Hardware timer to use with the dose_watchdog module. | |
Functions | |
void | dose_setup (dose_t *dev, const dose_params_t *params, uint8_t index) |
Setup a DOSE based device state. | |
State definitions | |
The drivers internal state that is hold in dose_t.state | |
enum | dose_state_t { DOSE_STATE_INIT = 0x00 , DOSE_STATE_BLOCKED = 0x01 , DOSE_STATE_IDLE = 0x02 , DOSE_STATE_RECV = 0x03 , DOSE_STATE_SEND = 0x04 , DOSE_STATE_STANDBY = 0x05 , DOSE_STATE_SLEEP = 0x06 , DOSE_STATE_ANY = 0x0F } |
Signal definitions | |
A signal controls the state machine and may cause a state transition | |
enum | dose_signal_t { DOSE_SIGNAL_NONE = 0x00 , DOSE_SIGNAL_INIT = 0x10 , DOSE_SIGNAL_GPIO = 0x20 , DOSE_SIGNAL_UART = 0x30 , DOSE_SIGNAL_ZTIMER = 0x40 , DOSE_SIGNAL_SEND = 0x50 , DOSE_SIGNAL_END = 0x60 } |
Escape octet definitions | |
#define | DOSE_OCTET_END (0xFF) |
Magic octet indicating the end of frame. | |
#define | DOSE_OCTET_ESC (0xFE) |
Magic octet escaping 0xFF in byte stream. | |
Flag definitions | |
Hold in dose_t.flags | |
#define | DOSE_FLAG_RECV_BUF_DIRTY (BIT0) |
Receive buffer contains a complete unhandled frame. | |
#define | DOSE_FLAG_END_RECEIVED (BIT1) |
END octet has been received. | |
#define | DOSE_FLAG_ESC_RECEIVED (BIT2) |
ESC octet has been received. | |
#define | DOSE_FLAG_SEND_PENDING (BIT3) |
A send operation is pending. | |
Opt definitions | |
Hold in dose_t.opts | |
#define | DOSE_OPT_PROMISCUOUS (BIT0) |
Don't check the destination MAC - pass every frame to upper layers. | |
#define CONFIG_DOSE_RX_BUF_LEN (ETHERNET_FRAME_LEN + DOSE_FRAME_CRC_LEN) |
#define DOSE_FLAG_END_RECEIVED (BIT1) |
#define DOSE_FLAG_ESC_RECEIVED (BIT2) |
#define DOSE_FLAG_RECV_BUF_DIRTY (BIT0) |
#define DOSE_FLAG_SEND_PENDING (BIT3) |
#define DOSE_OCTET_END (0xFF) |
#define DOSE_OCTET_ESC (0xFE) |
#define DOSE_OPT_PROMISCUOUS (BIT0) |
#define DOSE_TIMER_DEV TIMER_DEV(…) |
enum dose_signal_t |
Enumerator | |
---|---|
DOSE_SIGNAL_NONE | No signal ... |
DOSE_SIGNAL_INIT | Init the state machine. |
DOSE_SIGNAL_GPIO | Sense GPIO detected a falling edge. |
DOSE_SIGNAL_UART | Octet has been received. |
DOSE_SIGNAL_ZTIMER | Timer timed out. |
DOSE_SIGNAL_SEND | Enter send state. |
DOSE_SIGNAL_END | Leave send state. |
enum dose_state_t |
void dose_setup | ( | dose_t * | dev, |
const dose_params_t * | params, | ||
uint8_t | index | ||
) |
Setup a DOSE based device state.
[out] | dev | Handle of the device to initialize |
[in] | params | Parameters for device initialization |
[in] | index | Index of params in a global parameter struct array. If initialized manually, pass a unique identifier instead. |