Concepts
Informative
The model behind the CAN driver: its two-level state machine, timing model, and event handling. Non-binding; the normative rules live in Can — Requirements.
State machine
The driver has a driver-wide state and, independently, a per-channel state.
Driver state
stateDiagram-v2
[*] --> CAN_DRV_STATE_UNINIT : Reset
CAN_DRV_STATE_UNINIT --> CAN_DRV_STATE_INIT : Can_Init()
CAN_DRV_STATE_INIT --> CAN_DRV_STATE_UNINIT : Can_DeInit()
Driver state |
Meaning |
API calls accepted |
|---|---|---|
|
Not yet initialized (state after reset/startup) |
Only |
|
Initialized; service APIs are accepted |
All |
Channel state
After Can_Init, every channel starts in STOPPED. The upper layer drives transitions with
Can_SetChannelState; hardware events (bus-off) can force a channel back to STOPPED.
All upper-layer channel transitions go through the single Can_SetChannelState API; the argument
is the requested target state. The three operational states are grouped below as Initialized —
Can_Init enters the group and Can_DeInit leaves it from any of them.
stateDiagram-v2
direction LR
[*] --> CAN_CH_STATE_UNINIT : Reset
state "Initialized" as INIT {
direction TB
[*] --> CAN_CH_STATE_STOPPED
CAN_CH_STATE_STOPPED --> CAN_CH_STATE_STARTED : SetChannelState(STARTED)
CAN_CH_STATE_STARTED --> CAN_CH_STATE_STOPPED : SetChannelState(STOPPED)<br/>bus-off / unrecoverable error
CAN_CH_STATE_STOPPED --> CAN_CH_STATE_SLEEP : SetChannelState(SLEEP)
CAN_CH_STATE_SLEEP --> CAN_CH_STATE_STOPPED : SetChannelState(STOPPED)
}
CAN_CH_STATE_UNINIT --> INIT : Can_Init()
INIT --> CAN_CH_STATE_UNINIT : Can_DeInit()
Channel state |
Meaning |
Valid transitions requested via |
|---|---|---|
|
Hardware not configured |
|
|
Initialized, not participating on the bus |
|
|
Actively participating; TX/RX enabled |
|
|
Logical sleep (no wakeup detection) |
|
Note
A requested transition may not take effect immediately if the hardware needs status-register
polling to confirm it. In that case Can_SetChannelState does not block; completion is
detected later by Can_CyclicFunction and reported via CanIf_OnChannelState. See
Can — Requirements (CHI-CAN-MUST-03).
State transition sequence
The sequence below shows the two-step transition model: Can_SetChannelState requests a change,
and — when the hardware cannot confirm it synchronously — Can_CyclicFunction later observes
completion and reports it via CanIf_OnChannelState. This is the informative view of CHI-CAN-MUST-03.
sequenceDiagram
participant A as UpperLayer
participant B as CanDrv
participant C as CAN HW
Note over A,C: Init time
A->>B: Can_Init(&CanConfig)
activate B
B->>C: Initialize the hardware
B-->>A: return
deactivate B
Note over A,C: Channel state change via Can_SetChannelState()
A->>B: Can_SetChannelState(channelId, channelState)
activate A
activate B
alt a development error is detected
B-->>A: E_NOT_OK
else
B->>C: Set up HW registers / message objects
opt HW transitions without delay
B->>A: CanIf_OnChannelState(channel, channelState)
activate A
A-->>B: return
deactivate A
end
B-->>A: E_OK
end
deactivate A
deactivate B
alt transition not yet complete in Can_SetChannelState()
A->>B: Can_CyclicFunction()
activate A
activate B
B->>C: Get HW status
C-->>B: HW status
opt HW has reached the requested state
B->>A: CanIf_OnChannelState(channel, channelState)
activate A
A-->>B: return
deactivate A
end
B-->>A: return
deactivate A
deactivate B
end
Mailboxes and hardware objects
CAN hardware exposes a set of message objects, each holding an ID, a DLC, and the SDU data. The driver groups these into mailboxes: a mailbox is backed by one or more hardware object handles (HOHs), and both TX and RX mailboxes are configurable (CHI-CAN-MUST-17). How many hardware objects a mailbox uses determines its behavior:
Mailbox |
Hardware objects |
Meaning |
|---|---|---|
RX |
one |
A single message object receives into the mailbox. |
RX |
several (same setup) |
A hardware FIFO or several identically-configured objects (shadow buffer) back one RX mailbox, so a burst of frames is not lost (CHI-CAN-MUST-16). |
TX |
one |
A single message object transmits the mailbox’s frames. |
TX |
several |
Multiple hardware objects assigned to one TX mailbox for multiplexed transmission — an optional feature (CHI-CAN-MAY-01). |
Not every hardware object has to be assigned; unused objects simply carry no mailbox.
Timing model: two scheduling functions
Polling-mode work is split across two functions by their timing needs:
Function |
Typical period |
Handles (when configured for polling) |
|---|---|---|
|
sub-millisecond / high frequency |
TX-completion and RX events — the fast data path |
|
≥ 1 ms |
Bus-off, other unrecoverable errors, and channel state-transition completion |
Either may be an empty function if the corresponding events are all handled by interrupt.
Event handling: interrupt or polling
For each channel, TX, RX, and bus-off/error handling is independently configured as either interrupt or polling:
Interrupt —
Can_Initenables the corresponding interrupt;Can_Interruptservices it.Polling —
Can_Initdisables the interrupt;Can_PollFunction/Can_CyclicFunctionservice the event.
Either way, the same upper-layer callbacks are invoked (CanIf_OnReception,
CanIf_OnTransmission, CanIf_OnError, CanIf_OnChannelState).
Event handling sequence
The sequence below traces a transmission request and the subsequent event handling for both modes.
In interrupt mode, Can_Interrupt services the hardware event; in polling mode, the same
handling is driven from Can_PollFunction / Can_CyclicFunction. Either path fans out into the
TX-completion, RX, bus-off, and error branches and invokes the same upper-layer callbacks.
sequenceDiagram
participant INTEG as Integration code
participant UPL as UpperLayer
participant DRV as CanDrv
participant HW as CAN HW
Note over INTEG,HW: TX L-PDU
UPL->>DRV: Can_Transmit(mailboxId, &pdu)
activate DRV
activate UPL
alt a development error is detected
DRV-->>UPL: E_NOT_OK
else HW buffer for the mailbox is BUSY
DRV-->>UPL: CAN_BUSY
else HW buffer is available
DRV->>HW: Set up HW registers / message objects
DRV->>HW: Initiate transmission
DRV-->>UPL: E_OK
end
deactivate DRV
deactivate UPL
Note over INTEG,HW: Event handling
alt event handling mode = interrupt
HW->>DRV: Can_Interrupt()
activate DRV
opt unrecoverable error other than bus-off
DRV->>HW: Cancel pending messages
DRV->>HW: Reset / disable channel if needed
DRV->>INTEG: LogM_Report(..., CAN_RTERR_UNRECOVERABLE)
activate INTEG
INTEG-->>DRV: return
deactivate INTEG
end
opt bus-off detection
DRV->>HW: Cancel pending messages
DRV->>HW: Reset / disable channel if needed
DRV->>UPL: CanIf_OnError(channel, CAN_ERR_BUS_OFF)
activate UPL
UPL-->>DRV: return
deactivate UPL
end
opt TX L-PDU completion
DRV->>UPL: CanIf_OnTransmission(canTxPduId)
activate UPL
UPL-->>DRV: return
deactivate UPL
end
opt lost L-PDU
DRV->>INTEG: LogM_Report(..., CAN_RTERR_DATALOST)
activate INTEG
INTEG-->>DRV: return
deactivate INTEG
end
opt RX L-PDU
DRV->>HW: Interpret mailbox, extract L-PDU
DRV->>UPL: CanIf_OnReception(messageInfo, &pdu)
activate UPL
UPL-->>DRV: return
deactivate UPL
end
DRV-->>HW: return from interrupt
deactivate DRV
else event handling mode = polling
UPL->>DRV: Can_PollFunction() / Can_CyclicFunction()
activate UPL
activate DRV
DRV->>HW: Get HW status
Note left of DRV: Same handling as interrupt mode
DRV-->>UPL: return
deactivate DRV
deactivate UPL
end
Wakeup and sleep
A typical CAN transceiver can detect bus wakeup, but the CanDrv deliberately omits wakeup
detection. Consequently SLEEP is a logical state: the channel stops participating but the
driver does not arm any wakeup source.
Key terms
For CAN glossary terms — CAN controller, CAN channel, Hardware Object Handle (HOH), Hardware Object, Receive/Transmit Mailbox, CAN L-PDU / L-SDU — see the glossary in the appendix.