LIN - Overview¶
API Documentation
Explanation¶
Because LIN differs from any other bus system by the way it sends and receives frames, FERAL has two implemantations for LIN networks:
- The 'LIN'-Module, where the LIN-Master is provided by FERAL and a scheduling table has to be provided either by a LDF (LIN Description File) or during the configuration in the simulation setup.
- The 'LINPhys'-Module, where the master functionality in terms of scheduling is done by the connected component and FERAL only simulates the networking.
This part of the documentation is about the first one. For LINPhys please go to LINPhys. The implementation is based on the official LIN spec, Revision 2.2A (Download link: PDF).
Please pay attention to the information listed on Features.
Usage¶
Unconditional messages simulation setup
This is how a complete simulations setup of a sender (slave) and a receiver (master) transmitting unconditional messages looks like:
public static void main(String[] args) {
// Define a scenario
SimulationScenario simulationScenario = new SimulationScenario();
Director director = new DiscreteEventMOCC("root director", simulationScenario);
// Create some workers to do something
// (NOTE: This would be the components to be tested!)
// -> Create "LIN sender"
SenderEventWorker linSender = new SenderEventWorker(director);
// -> Create "LIN receiver"
ReceiverEventWorker linReceiver = new ReceiverEventWorker(director);
// Setup a simple LIN network with 2 interfaces (master + slave)
LINNetwork network = new DefaultLINNetwork(director, 2);
// -> Bitrate
network.setBitRate(10000);
// -> Time base (see chapter 2.4.1 of the LIN spec)
network.getConfig().setTimeBase(SimulationDuration.MS(10));
// -> Optional start delay
network.getConfig().setScheduleStartDelay(SimulationDuration.MS(120));
// -> Add a schedule for the master
network.addSchedule("defaultSchedule")
// -> Add an unconditional frame to the schedule
.addUnconditionalFrame(
1 /* first slave */ ,
5 /* frame duration = 5 * time base */,
5 /* frame ID */);
// Setup communication interfaces
// -> Messages with ID 5 received from the master interface are 2 bytes long and
// will be forwarded to port "linID5_out"
network.getMasterInterface().addRxMessageType("5", "linID5_out", 2);
// -> Messages with ID 5 send to the port "linID5_in" of this interface
// will get forwarded to the network.
network.getSlaveInterface(0).addTxMessageType("5", "linID5_in", 2);
// Now, link the actual workers to the network by connecting the FERAL ports we just created
// Note that the receiver gets connected to the master interface.
// This can be done, but other slaves also can receive information.
new Link(network.getMasterInterface().getOutputPort( "linID5_out"), linReceiver.getInputPort("comm"));
new Link(linSender.getOutputPort("comm"), network.getSlaveInterface(0).getInputPort("linID5_in"));
// The simulation is read and can be started
simulationScenario.startSimulation(SIMULATION_DURATION_NS);
}
public static void main(String[] args) {
// Define a scenario
SimulationScenario simulationScenario = new SimulationScenario();
Director director = new DiscreteEventMOCC("root director", simulationScenario);
// Create some workers to do something
// (NOTE: This would be the components to be tested!)
// -> Create "LIN sender"
SenderEventWorker linSender = new SenderEventWorker(director);
// -> Create "LIN receiver"
ReceiverEventWorker linReceiver = new ReceiverEventWorker(director);
// - Create "LDF-Parser" and parse the file
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
LDFParser parser = new LDFParser(Paths.get(classloader.getResource("path_to_file/LDF_UnconditionalSchedule.lin").toURI()));
parser.parseLDF();
// Create a LIN network having amount of Interfaces defined in the LDF.
LINNetwork network = parser.createLINNetwork(director);
// Setup network using the LDF
parser.injectLINNetworkParameters(network.getConfig());
network.getConfig().setTimeBase(SimulationDuration.MS(10));
network.getConfig().setScheduleStartDelay(SimulationDuration.MS(120));
parser.instantiateSchedule(network);
// Setup communication interfaces
parser.setupCommunicationInterfaces(network);
// Now, link the actual workers to the network by connecting the FERAL ports we just created
// Note that the receiver gets connected to the master interface.
// This can be done, but other slaves also can receive information.
new Link(network.getMasterInterface().getOutputPort( "linID5_out"), linReceiver.getInputPort("comm"));
new Link(linSender.getOutputPort("comm"), network.getSlaveInterface(0).getInputPort("linID5_in"));
// The simulation is read and can be started
simulationScenario.startSimulation(SIMULATION_DURATION_NS);
}
The LDF file looks like this (see chapter 9.2 of the LIN specification):
LIN_description_file;
LIN_protocol_version = "2.2";
LIN_language_version = "2.2";
LIN_speed = 10.0 kbps;
Nodes {
Master: MasterNode, 10 ms, 0.0 ms;
Slaves: SlaveNode1;
}
Signals {
SignalRequest: 0, 0, SlaveNode1, MasterNode;
}
Frames {
Frm_1: 0x05, SlaveNode1, 2 {
SignalRequest, 0;
}
}
Schedule_tables {
DefaultST {
Frm_1 delay 50 ms;
}
}
import feral
from feral import seconds, MessageType, MessageTypeConfig
from feral.network.lin import LINConfig, LINNodeConfig, LINSchedule
from feral.presets.producer.value_producer import ValueProducer
from feral.presets.sink.sink import Sink
node0 = LINNodeConfig(
name="node0",
message_types=[
MessageTypeConfig(
type=MessageType.TX,
address="5",
simulated_payload_size=2,
port_name="node0_tx"
)]
)
node1 = LINNodeConfig(
name="node1",
message_types=[
MessageTypeConfig(
type=MessageType.RX,
address="5",
simulated_payload_size=2,
port_name="node1_rx"
)]
)
lin_config = LINConfig(
nodes=[node0, node1],
bit_rate=10000,
time_base=feral.millis(10),
log_transmissions=False
)
if __name__ == '__main__':
producer = ValueProducer("producer", interval=feral.millis(50))
sink = Sink(name="Sink")
lin = feral.create_lin(config=lin_config)
schedule = (feral.add_schedule("Schedule Table", lin)
.add_unconditional_frame(0, 5, 5)
feral.link(producer, "output", lin, "node0_tx")
feral.link(lin, "node1_rx", sink, "input")
feral.start(seconds(1))
import pathlib
import feral
from feral import seconds, MessageType, MessageTypeConfig
from feral.network.lin import LINConfig, LINNodeConfig, LINSchedule
from feral.presets.producer.value_producer import ValueProducer
from feral.presets.sink.sink import Sink
if __name__ == '__main__':
producer = ValueProducer("producer", interval=feral.millis(50))
sink = Sink(name="Sink")
lin = feral.lin_from_ldf(str(pathlib.Path("\LDF_UnconditionalSchedule.lin")))
feral.link(producer, "output", lin, "linID5_in")
feral.link(lin, "linID5_out", sink, "input")
feral.start(seconds(1))
The LDF file looks like this (see chapter 9.2 of the LIN specification):
LIN_description_file;
LIN_protocol_version = "2.2";
LIN_language_version = "2.2";
LIN_speed = 10.0 kbps;
Nodes {
Master: MasterNode, 10 ms, 0.0 ms;
Slaves: SlaveNode1;
}
Signals {
SignalRequest: 0, 0, SlaveNode1, MasterNode;
}
Frames {
Frm_1: 0x05, SlaveNode1, 2 {
SignalRequest, 0;
}
}
Schedule_tables {
DefaultST {
Frm_1 delay 50 ms;
}
}