4.4 KiB
4.4 KiB
LIN Interface Call Flow
This document explains how LIN operations flow through the abstraction for the Mock, MUM, and legacy BabyLIN adapters.
Contract (base)
File: ecu_framework/lin/base.py
connect()/disconnect()send(frame: LinFrame)receive(id: int | None = None, timeout: float = 1.0) -> LinFrame | Nonerequest(id: int, length: int, timeout: float = 1.0) -> LinFrame | Noneflush()
LinFrame validates:
- ID is 0x00–0x3F (6-bit LIN ID)
- Data length ≤ 8 bytes
Mock adapter flow
File: ecu_framework/lin/mock.py
connect(): initialize buffers and statesend(frame): enqueues the frame and (for echo behavior) schedules it for RXreceive(timeout): waits up to timeout for a frame in RX bufferrequest(id, length, timeout): synthesizes a deterministic response of the given length for predictabilitydisconnect(): clears state
Use cases:
- Fast local dev, deterministic responses, no hardware
- Timeout and boundary behavior validation
MUM adapter flow (Melexis Universal Master)
File: ecu_framework/lin/mum.py
The MUM is a networked LIN master (default IP 192.168.7.2) with built-in
power control on power_out0. It is master-driven: there is no passive
listen — to read a slave-published frame, the master triggers a header on
that frame ID. Diagnostic frames (BSM-SNPD, service ID 0xB5) require LIN 1.x
Classic checksum and are sent through the transport layer's
ld_put_raw, not the regular send_message.
connect(): lazy-importspymumclient+pylin; opens MUM (MelexisUniversalMaster.open_all(host)), gets the LIN device (linmaster) and power device (power_control), runslinmaster.setup(), buildsLinBusManager+LinDevice22, setslin_dev.baudrate, fetches the transport layer (get_device("bus/transport_layer")), and finallypower_control.power_up()followed by aboot_settle_secondssleepsend(frame):lin_dev.send_message(master_to_slave=True, frame_id, data_length, data)receive(id, timeout):lin_dev.send_message(master_to_slave=False, frame_id=id, data_length=frame_lengths.get(id, default_data_length))— pylin returns the response bytes (or raises on timeout, which we treat asNone).id=NoneraisesNotImplementedErrorbecause the MUM cannot listen passively.disconnect(): best-effortpower_control.power_down()followed bylinmaster.teardown()- MUM-only extras:
send_raw(bytes)(Classic checksum viald_put_raw),power_up(),power_down(),power_cycle(wait)
Configuration:
interface.hostis required;interface.lin_deviceandinterface.power_devicedefault to MUM conventionsinterface.bitrateis the actual LIN baudrate the MUM drivesinterface.frame_lengthslets you map slave frame IDs to their fixed data lengths soreceive(id)can fetch the correct number of bytes; built-in defaults cover ALM_Status (4) and ALM_Req_A (8)
BabyLIN adapter flow (SDK wrapper)
File: ecu_framework/lin/babylin.py
connect(): import SDKBabyLIN_library.py, discover ports, open first, optionallyBLC_loadSDF, get channel handle, andBLC_sendCommand("start schedule N;")send(frame): callsBLC_mon_set_xmit(channelHandle, frameId, data, slotTime=0)receive(timeout): callsBLC_getNextFrameTimeout(channelHandle, timeout_ms)and converts returnedBLC_FRAMEtoLinFramerequest(id, length, timeout): prefersBLC_sendRawMasterRequest(channel, id, length); falls back to(channel, id, bytes); if unavailable, sends a header and waits onreceive()disconnect(): callsBLC_closeAll()- Error handling: uses
BLC_getDetailedErrorString(if available)
Configuration:
interface.sdf_pathlocates the SDF to loadinterface.schedule_nrsets the schedule to start upon connectinterface.channelselects the channel index
Edge considerations
- Ensure the correct architecture (x86/x64) of the DLL matches Python
- Channel/bitrate must match your network configuration
- Some SDKs require initialization/scheduling steps before transmit/receive
- Time synchronization and timestamp units vary per SDK — convert as needed
Note on master requests:
- Our mock wrapper returns a deterministic byte pattern when called with the
lengthsignature. - When only the bytes signature is available, zeros of the requested length are used in tests.