Concepts

Informative

The model behind the LIN driver: its per-channel state machine, how a frame transaction is processed, and how events are handled. Non-binding; the normative rules live in Lin — Requirements.

State machine

The driver has a driver-wide state and, within the initialized state, a per-channel power state.

Driver state

        stateDiagram-v2
   [*] --> LIN_DRV_STATE_UNINIT : Reset
   LIN_DRV_STATE_UNINIT --> LIN_DRV_STATE_INIT : Lin_Init()
   LIN_DRV_STATE_INIT --> LIN_DRV_STATE_UNINIT : Lin_DeInit()
    

Driver state

Meaning

API calls accepted

LIN_DRV_STATE_UNINIT

Not initialized (state after reset/startup)

Only Lin_Init()

LIN_DRV_STATE_INIT

Initialized; service APIs are accepted and every channel has a power state

All

Channel state

After Lin_Init every channel starts in SLEEP. The upper layer drives the channel between SLEEP and OPERATIONAL; only in OPERATIONAL does the channel take part in bus traffic. Lin_DeInit returns the whole driver (and its channels) to LIN_DRV_STATE_UNINIT.

        stateDiagram-v2
   direction LR
   [*] --> LIN_CH_STATE_SLEEP : Lin_Init()
   LIN_CH_STATE_SLEEP --> LIN_CH_STATE_OPERATIONAL : Lin_Wakeup() / Lin_WakeupInternal()
   LIN_CH_STATE_OPERATIONAL --> LIN_CH_STATE_SLEEP : Lin_GoToSleepInternal()
    

Channel state

Meaning

Left via

LIN_CH_STATE_SLEEP

Channel initialized, not on the bus; wakeup-pulse detection enabled, hardware in low-power mode where supported

Lin_Wakeup() / Lin_WakeupInternal()OPERATIONAL

LIN_CH_STATE_OPERATIONAL

Channel participates in the cluster; header reception and response TX/RX enabled

Lin_GoToSleepInternal()SLEEP

Note

Lin_Wakeup (which also transmits a wakeup pulse) is only valid in SLEEP; calling it in OPERATIONAL raises a development error. Use Lin_WakeupInternal to go operational without sending a pulse (e.g. after an externally detected wakeup). See Lin — Requirements (CHI-LIN-MUST-04).

Frame processing

A LIN frame has two parts. The header (break field, sync byte, protected identifier) is sent by the commander node; the response (data bytes plus checksum) may be sent by any node. As a responder, the driver receives every header and then acts on the response according to the upper layer’s decision:

  1. The driver evaluates the received PID and passes it to the upper layer via LinIf_OnHeader.

  2. The upper layer fills in the reaction, checksum model, and data length:

    Reaction

    The driver then…

    LIN_REACTION_TX

    transmits the response (data + checksum) provided by the upper layer.

    LIN_REACTION_RX

    receives the response and hands the data to the upper layer.

    LIN_REACTION_IGNORE

    does nothing with the response and waits for the next header.

  3. The checksum model is LIN_CS_CLASSIC (data only) or LIN_CS_ENHANCED (data + PID). Data bytes are mapped byte 0 first (CHI-LIN-MUST-08).

The data buffer passed to/from the callbacks is valid only for the duration of the call — copy what you need to keep (CHI-LIN-MUST-09).

Event handling: interrupt or polling

For each channel, event handling is configured as either interrupt or polling:

  • InterruptLin_Init enables the LIN interrupt; Lin_Interrupt services it.

  • PollingLin_Init disables the interrupt; Lin_PollFunction services the events.

Either way the same upper-layer callbacks are invoked: LinIf_OnHeader, LinIf_OnReception, LinIf_OnTransmission, LinIf_OnError, and LinIf_OnWakeup.

State transition sequence

The sequence below shows initialization, the internal and external wakeup paths, and going back to sleep. This is the informative view of CHI-LIN-MUST-02, CHI-LIN-MUST-03, and CHI-LIN-MUST-11.

        sequenceDiagram
   participant ENV as Integration code
   participant UPL as Upper layer
   participant DRV as  LinDrv
   participant TRCV as LIN transceiver
   participant HW as LIN HW
   participant BUS as LIN BUS

   Note over ENV,BUS: LIN_DRV_STATE_UNINIT -> LIN_DRV_STATE_INIT


   activate UPL
   UPL ->> DRV: Lin_Init ()
   activate DRV
   DRV->> HW : Initialization (configuration)
   opt IF LIN HW supports a low power mode
      DRV->> HW: Set into a low power mode
   end
   opt IF "wakeup detection" is enabled
      DRV->> HW: Setup to detect wakeup pulse
   end

   DRV->> DRV: Channel state to LIN_CH_STATE_SLEEP
   DRV-->> UPL: ;
   deactivate DRV
   deactivate UPL

   Note over ENV,BUS: LIN_CH_STATE_SLEEP -> LIN_CH_STATE_OPERATIONAL
   alt IF Internal (Top-Down) wakeup

      activate UPL
      UPL ->> DRV: Lin_Wakeup(channel)
      activate DRV
      DRV ->> HW: Enable interrupt (wakeup pulse detection or wakeup pulse TX completion)
      DRV ->> HW: Send wakeup pulse
      HW ->> BUS: wakeup pulse
      DRV->> DRV: Channel state to LIN_CH_STATE_OPERATIONAL
      DRV -->> UPL: return Std_ReturnType
      deactivate DRV

      deactivate UPL

      note left of HW: If HW supports receiving back of wakeup pulse, use it.<br/> Otherwise, use wakeup pulse TX completion.

      HW ->> DRV : Lin_Interrupt (wakeup pulse detection or wakeup pulse TX completion)
      activate DRV
      opt IF HW settting change after wakeup pulse transmission is needed
         DRV ->> HW: Change HW setting to enable header reception
      end
      DRV ->> UPL: LinIf_OnWakeup(channel)
      activate UPL
      UPL -->> DRV : return
      deactivate UPL
      DRV -->> HW : return from interrupt
      deactivate DRV
      note left of UPL: In case of re-transmission of wakeup pulse.<br/> (e.g. commander does not start scheduler within the specific time period)<br/> In this case, the upper layer should call Lin_GoToSleepInternal(),<br/> then call Lin_Wakeup() again.
   else IF External (Bottom-Up) wakeup
      opt IF use wakeup detetion by transceiver
         BUS -) TRCV: wakeup pulse
         TRCV -) ENV: Interrupt handler (typically edge detection)
         activate ENV
         ENV ->> UPL: A related interface
         activate UPL
         UPL ->> DRV: Lin_WakeupInternal(channel)
         activate DRV
         DRV ->> HW: Change HW setting to enable header reception
         DRV->> DRV: Channel state to LIN_CH_STATE_OPERATIONAL
         DRV -->> UPL: return Std_ReturnType
         deactivate DRV
         UPL -->> ENV: ;
         deactivate UPL
         ENV --) TRCV : return from interrupt
         deactivate ENV
      end
      opt IF "wakeup detection" is enabled (detect by LinDrv)
         BUS -) HW: wakeup pulse
         HW ->> DRV: Lin_Interrupt
         activate DRV
         DRV ->> UPL: LinIf_OnWakeup(channel)
         activate UPL
         UPL ->> DRV: Lin_WakeupInternal(channel)
         activate DRV
         DRV ->> HW: Change HW setting to enable header reception
         DRV->> DRV: Channel state to LIN_CH_STATE_OPERATIONAL
         DRV -->> UPL: return Std_ReturnType
         deactivate DRV
         UPL -->> DRV: ;
         deactivate UPL
         DRV -->> HW : return from interrupt
         deactivate DRV
      end
   end

   Note over ENV,BUS: LIN_CH_STATE_OPERATIONAL -> LIN_CH_STATE_SLEEP

   activate UPL
   UPL ->> DRV: Lin_GoToSleepInternal (channel)
   activate DRV
   opt IF LIN HW supports a low power mode
      DRV->> HW: Set into a low power mode
   end
   opt IF "wakeup detection" is enabled
      DRV->> HW: Setup to detect wakeup pulse
   end
   DRV->> DRV: Channel state to LIN_CH_STATE_SLEEP
   DRV-->> UPL: return Std_ReturnType
   deactivate DRV

   deactivate UPL
    

Transaction sequence

Once a channel is OPERATIONAL, each Lin_Interrupt (or Lin_PollFunction call) fans out by event type. This is the informative view of CHI-LIN-MUST-12 and CHI-LIN-MUST-13.

        sequenceDiagram
   participant UPL as  Upper layer
   participant DRV as LinDrv
   participant HW as LIN HW
   participant BUS as LIN BUS

   Note over UPL,BUS: In LIN_CH_STATE_OPERATIONAL state

   HW ->> DRV: Lin_Interrupt
   activate DRV
   alt IF error has been detected
      DRV ->> HW: Setup for next header reception if HW setup is needed
      DRV ->> UPL: LinIf_OnError(channel, error)
      activate UPL
      UPL -->> DRV: ;
      deactivate UPL
   else IF header reception
      DRV ->> HW: Get PID
      DRV ->> DRV: Setup pduInfoPtr (pid=PID, sduPtr=Internal buffer)
      DRV ->> UPL: LinIf_OnHeader(channel, pduInfoPtr)
      activate UPL
      UPL ->> UPL: Setup pduInfoPtr (cs, reaction, dl)
      UPL ->> UPL: Setup TX data in pduInfoPtr.sduPtr (in case of TX)
      UPL -->> DRV: ;
      deactivate UPL
      alt IF pduInfoPtr->>reaction == TX
         DRV ->> HW: Send response
         HW ->> BUS: response
      else IF pduInfoPtr->>reaction == RX
         DRV ->> HW: Setup HW to receive response
      else IF pduInfoPtr->>reaction == IGNORE
         DRV ->> HW: Setup for next header reception if HW setup is needed
      end
   else IF RX response
      DRV ->> HW : Get response and store it to buffer pointed by sduPtr
      DRV ->> HW: Setup for next header reception if HW setup is needed
      DRV ->> UPL: LinIf_OnReception(channel, sduPtr)
      activate UPL
      UPL -->> DRV: ;
      deactivate UPL
   else IF TX response completion
      DRV ->> HW: Setup for next header reception if HW setup is needed
      DRV ->> UPL: LinIf_OnTransmission(channel)
      activate UPL
      UPL -->> DRV: ;
      deactivate UPL
   end
DRV -->> HW: return from interrupt
deactivate DRV
    

Key terms

For LIN glossary terms — commander/responder node, header, response, protected identifier (PID), checksum model, reaction, wakeup pulse — see the glossary in the appendix.