Skip to content

esp32_twai

TWAI (CAN 2.0): the ESP32’s CAN controller, an SJA1000-style core.

This driver covers the self-test loopback path: the controller transmits a frame and receives its own copy, with no second node and no bus.

How the loopback works, without a wire or a transceiver

Section titled “How the loopback works, without a wire or a transceiver”

Two mechanisms combine:

  • Self-test mode (MODE.STM) lets a transmission complete with no acknowledgement — normally another node must ACK or the frame is retried forever. A self-reception request (CMD.SRR) transmits and receives the same frame at once.
  • The transmitted bits still have to reach the RX input. Routed through the GPIO matrix, the controller’s TX output and RX input signals land on the same pad, so what it drives it reads back. Real analog path (pad → pad), no internal register loopback.

So a single ESP32, one pin, tests the whole controller: bit timing, framing, CRC, the TX and RX buffers.

A real bus, arbitration against another node, and acknowledgement by a second controller. Those need a transceiver and a peer (issue #27). This is the on-chip functional test, fixed at 125 kbit/s — the rate is immaterial when a node talks only to itself.

DR_REG_CAN_BASE = 0x3FF6B000, from esp-idf soc/soc.h. The register layout is soc/twai_struct.h (each 8-bit SJA1000 register in the low byte of a 32-bit word); the sequences are hal/twai_ll.h.

Register Offset Fields
MODE 0x00 RM 0, LOM 1, STM 2, AFM 3
CMD 0x04 TR 0, AT 1, RRB 2, CDO 3, SRR 4
STATUS 0x08 RBS 0, DOS 1, TBS 2, TCS 3, RS 4, TS 5, ES 6, BS 7
INT_ENA 0x10 interrupt enables, all cleared
BUS_TIMING_0 0x18 BRP [5:0], SJW [7:6]
BUS_TIMING_1 0x1C TSEG1 [3:0], TSEG2 [6:4], SAM 7
DATA[0..13] 0x40..0x74 TX/RX buffer; ACR/AMR in reset mode
CLOCK_DIVIDER 0x7C CD [2:0], CO 3, CM 7 (PeliCAN)
struct Frame {
pub id: u16,
pub len: u8,
pub data: [u8; 8],
}

A standard (11-bit identifier) CAN frame.

Implements: Clone, Copy, Debug, Eq, PartialEq, StructuralPartialEq

struct Twai { /* private fields */ }

The TWAI controller.

enum Mode {
Normal,
SelfTest,
ListenOnly,
}

Operating mode.

Implements: Clone, Copy, Debug, Eq, PartialEq, StructuralPartialEq

enum TwaiError {
Timeout,
}

Why a self-reception failed.

Implements: Clone, Copy, Debug, Eq, From, PartialEq, StructuralPartialEq