NetBurner 3.5.8
PDF Version
CAN Error Counter Monitoring and Bus-Off Recovery

Example Path: examples/PlatformSpecific/SAME70/MODM7AE70/CAN_ErrorRecovery

Supported Platforms: MODM7AE70

Demonstrates how to monitor the MCAN error counters and recover the controller from a bus-off condition.

The MODM7AE70 uses Atmel's MCAN (Bosch M_CAN) peripheral. Two registers report controller health:

  • MCAN_ECR – Error Count Register, exposing the Transmit Error Counter (TEC) and Receive Error Counter (REC).
  • MCAN_PSR – Protocol Status Register, with explicit flags for Bus-Off (BO), Error-Passive (EP) and Error-Warning (EW).

Both registers are read through the public methods mcan_module::read_error_count() and mcan_module::read_protocol_status(). When a bus-off is detected, the example issues stop() followed by start() to toggle the CCCR.INIT bit and bring the controller back onto the bus – the M_CAN equivalent of the FRZ/HALT debug-mode reset used on the legacy MOD5282 FlexCAN peripheral.

What the example does:

  • Configures MCAN1 on pins P2[30] (TX) and P2[6] (RX).
  • Spawns a monitor task that polls the error counters and protocol status once per second, prints any state change, and automatically restarts the controller on bus-off.
  • Provides a serial menu to send frames, print the current counter and status values on demand, and force a restart manually.

Hardware notes:

  • A CAN transceiver is required for normal bus traffic. To deliberately drive the controller into error-passive and bus-off, run the example with the transceiver disconnected (or with no other node on the bus) and press 'S' repeatedly: every transmit fails with no acknowledgement and increments TEC by 8 until bus-off is reached.
  • Bus-off recovery requires the controller to observe 128 occurrences of 11 consecutive recessive bits on the bus before the protocol allows it to leave bus-off. On an idle bus that is effectively immediate; on a busy bus it can take noticeably longer.

WARNING – MOD-DEV-70 DIP switch configuration: On the MOD-DEV-70 development board, the MCAN1 RX pin (P2[6] / J2_6) routes through a DIP switch. In the OFF position the pin is pulled to ground through a 1 k resistor; in the ON position it is tied to VCC. Because the CAN controller interprets RX-low as a continuously dominant bus, leaving the switch OFF holds the controller in bus integration and the demo will appear inert – no error counters move and transmitted frames never leave the TX FIFO. Set the J2_6 DIP switch to the ON (VCC) position before running this example without a transceiver. See the "MOD-DEV-70 operation without a transceiver" section below for the full explanation.

MOD-DEV-70 operation without a transceiver:

Recap of CAN_RX semantics: On the MCU side, RX HIGH = recessive (idle bus), RX LOW = dominant. Integration out of init requires the controller to observe 11 consecutive recessive bits before it will go operational.

DIP switch OFF (1 k pull-down – P2[6] held LOW = continuous dominant)

The controller never gets to operational state at all:

  • start() puts the controller into bus integration. It waits to see 11 consecutive recessive bits. With RX nailed low, it never does, so the controller sits in synchronizing state forever.
  • TEC and REC stay at 0; the monitor prints the initial OK line and then nothing changes.
  • Pressing 'S' queues a message in the TX FIFO but it is never transmitted – the controller hasn't joined the bus.
  • Bus-off never occurs and the auto-recovery path never executes.
  • Pressing 'R' (manual stop/start) just re-enters the same stuck integration state.

End result: the example looks broken / inert. None of the educational behavior described above is visible.

DIP switch ON (P2[6] tied to VCC = continuous recessive)

This is the configuration the example's "no transceiver" demo actually needs:

  • Integration completes immediately (11 recessive bits trivially satisfied), controller goes operational.
  • Pressing 'S' triggers a transmit. The controller drives TX low for the Start-of-Frame dominant bit and reads back its own RX to verify. But RX is hard-wired to VCC, so it reads recessive instead of dominant – bit error on the very first transmitted bit, TEC += 8.
  • ~16 presses reach ERR-WARNING then ERR-PASSIVE (TEC >= 128). ~32 presses reach BUS-OFF (TEC >= 256).
  • Monitor sees PSR.BO, prints "*** Restarting MCAN controller ***", calls stop() / start(). The 128 x 11-recessive-bits idle-bus requirement is satisfied instantly because RX is permanently recessive, so the controller comes back with TEC = REC = 0.
  • Receive never produces anything – the 0x123 filter and CanRxTask print nothing – because RX never actually toggles.

End result: the example operates exactly as described above, including the auto-recovery cycle.

Optional: routing CANRX1 to P2[23]:

If you prefer to route CANRX1 to P2[23] (CPU port PD28, Peripheral B mux) – for example, to free P2[6] for one of its other peripheral functions (TIOB8) or for GPIO use, or because your custom board brings CANRX1 out on a different header pin. The MCAN1 controller instance does not change; only the pin-function call moves.

To switch, in main.cpp comment out: P2[6].function(PINP2_6_CANRX1); and uncomment: P2[23].function(PINP2_23_CANRX1);

The underlying pin-function macro PINP2_23_CANRX1 is defined in platform/MODM7AE70/include/pinconstant.h.

The notes below describe the MOD-DEV-70 development board, which wires P2[23] through R10 (330 ohm) to the cathode of an LED whose anode sits at 3.3V. Other development boards may load P2[23] differently or not at all – consult the schematic for your specific board before relying on the behavior described here.

CAUTION – on the MOD-DEV-70, R10 must be removed for the no-transceiver demo mode: Before P2[23] can be used reliably for CANRX1 in the no-transceiver demo mode described earlier in this ReadMe, the MOD-DEV-70's R10 must be removed. With R10 and the LED in place and no transceiver driving the pin, the LED clamps the pin to roughly 3.3V minus the LED forward drop (around 1.3V), which lands in the SAME70 input indeterminate zone. The MCAN controller will not complete bus integration and the example will appear inert – the same symptom described above for the DIP-switch-OFF case on P2[6]. To repeat the bus-off demonstration without a transceiver on the MOD-DEV-70, remove R10 (or lift the LED), or jumper P2[23] directly to 3.3V the way the J2_6 DIP switch does for P2[6].

Free CAN-RX activity indicator (MOD-DEV-70, transceiver attached):

On the MOD-DEV-70, if R10 and the LED are left in place and a CAN transceiver is wired to P2[23], the LED becomes a free CAN-RX activity indicator. Each dominant bit on the bus pulls the pin low and draws roughly 4 mA through R10 and the LED – well within any standard CAN transceiver RXD sink capability and with negligible effect on edge rates at 500 kbit/s. The LED lights or flickers with bus traffic and is off when the bus is idle. On other development boards this behavior depends entirely on what (if anything) is wired to P2[23].