Home » Eclipse Projects » Eclipse Titan » Getting Started with the SocketCAN J1939 Test Port on the example of Isobus(Test port, SocketCAN, J1939, ISOBUS, NMEA2000,etc.)
Getting Started with the SocketCAN J1939 Test Port on the example of Isobus [message #1831598] |
Mon, 24 August 2020 15:22 |
Michael Josenhans Messages: 99 Registered: February 2016 |
Member |
|
|
Hi,
after implementing the SocketCAN test port, the "can-J1939" kernel module had been published. While the CAN-protocol is mainly a protocol providing 8 bit broadcast messages between different CAN-nodes, the "can-J1939" kernel module provides a network management and a segmentation / reassembly (TP-Protocol and ETP-Protocol) on top of the CAN protocol. It is for example possible to transport messages of up to 11 MByte.
Hereyou find further information on the CAN-J1939 protocol:
https://www.kvaser.com/about-can/higher-layer-protocols/j1939-standards-overview/
https://www.amazon.de/Comprehensible-Guide-J1939-Wilfried-Voss/dp/0976511630
The J1939 Test Port, which is part of the SocketCAN test port, is implemented closely to the "can-J1939" SocketCAN kernel module interface, which is described here:
https://github.com/torvalds/linux/blob/master/Documentation/networking/j1939.rst
In general there 3 different things:
- J1939 Address
- J1939 NAME
- J1939 PGN
The J1939 address:
The address is a 1-byte value, addressing a J1939-node. The address 'FF'O (J1939_NO_ADDR) is the broadcast address. Anything sent to the broadcast address is sent to all nodes.
The J1939 name:
The name, which is a 8-byte octet string, is sent during the address claim procedure. If 2 nodes have the same address, the one with the node with the higher priority (higher name value) wins and the other one has to choose a new address and start the address claim procedure again.
The nice thing with the J1939-kernel module is, that the kernel tracks the name to address mapping and the user has not to care for it. In order to do address claim, the address claim procedure has to be implemented in user-space. For this purpose we start here one address claim demon with the nodes name per J1939 node. (j1939acd)
After that the node can be registered and listen for messages and send messages.
The J1939 PGN:
The PGN is a unique message discriminator, which destingishes e.g. address claim messages from isobus messages or other messages sending e.g. engine rpm.
This way dynamic addressing can be used and messages can just be sent to a name, the kernel cares for the address mapping, as long as the name is not '000000000000000'O (J1939_NO_NAME). If the name is set, the address given is ignored.
Example:
In the following is now an example of the Isobus protocol.
Here the Virual Terminal (VT) node sends a VTStatus message as broadcast cyclically each second as broadcast message to all nodes and the ECU listens for the VTStatus message and responds cyclically each second with a WorkingSetMaintenance message as keep alive. It shall stop, if the VTStatus message stops. Also the ECU and the VT exchange some messages and finally the ECU upload a bogous object pool to the VT.
In order to simulate this with TTCN, both sides have been implemened as TTCN test cases. (One of those can be replaced, by a real VT resp. ECU. While the test case is written in such a manner, that it can only cope with one VT and one ECU node.
When receiving a message, the name of the sender is taken and set as the receivers name in the response sent.
The main message handling (function: f_ptc_J1939ECUApplication):
alt
{
....
[]pt_j1939PDU.receive(J1939PDU_with_NAME:{addr:= ?, name:=?,
pdu:=t_VTStatusInd(?, ?, ?, ?, ?)}) -> value v_pgn_and_pdu_with_name
{
v_peeraddr := v_pgn_and_pdu_with_name.addr
v_peername := v_pgn_and_pdu_with_name.name
// store peer name
//log incoming message
log("SocketCan:Expected message VTStatusReq received!", v_pgn_and_pdu_with_name)
pt_VTStatusTick.send( true );
}
[] pt_WorkingSetMaintenance.receive(t_WorkingSetMaintenanceTick(?)) {
pt_j1939PDU.send(t_J1939PDU_with_NAME(
J1939_NO_ADDR, /* set addr 0xFF, applies as name is set */
v_peername, /* set peername */
t_WorkingSetMaintenanceInd(true, compliantWithVTVersion4)
))
}
...
}
Here the Isobus message t_VTStatusInd(?, ?, ?, ?, ?) is recived, with the J1939 address and the J1939 name. The template t_VTStatusInd() is defined as :
template Isobus.J1939_messageWithPGN t_VTStatusInd(
template OCT1 p_sourceAddressOfActiveWorkingSetMaster,
template OCT2 p_objectIDOfTheVisibleDataAlarmMaskOfTheActiveWorkingSet,
template OCT2 p_objectIDOfTheVisibleSoftKeyMaskOfTheActiveWorkingSet,
template e_BusyCodes p_vtBusyCodes,
template OCT1 p_vtFunctionCode) := {pgn := '00E600'O,
pdu := {vt2ecu := {vtStatusInd := {
vtfunction := 254,
sourceAddressOfActiveWorkingSetMaster := p_sourceAddressOfActiveWorkingSetMaster,
objectIDOfTheVisibleDataAlarmMaskOfTheActiveWorkingSet := p_objectIDOfTheVisibleDataAlarmMaskOfTheActiveWorkingSet,
objectIDOfTheVisibleSoftKeyMaskOfTheActiveWorkingSet := p_objectIDOfTheVisibleSoftKeyMaskOfTheActiveWorkingSet,
vtBusyCodes := p_vtBusyCodes,
vtFunctionCode := p_vtFunctionCode
}}}
}
It can be seen that the PGN of the VTStatus message is '00E600'O and the VTStatusInd is defined with the protocol discriminator vtfunction as following;
type union VT2ECU
{
// put all VT2ECU messages here
SoftKeyActivationReq softKeyActivationReq,
ButtonActivationReq buttonActivationReq,
......
ExtendedGetVersionsRes extendedGetVersionsRes,
ExtendedStoreVersionRes extendedStoreVersionRes,
ExtendedLoadVersionRes extendedLoadVersionRes,
ExtendedDeleteVersionRes extendedDeleteVersionRes,
GetVersionsRes getVersionsRes,
VTUnsupportedVTFunctionInd vtUnsupportedVTFunctionInd,
VTStatusInd vtStatusInd
}
with {variant "TAG (
// put all VT2ECU messages here
softKeyActivationReq, vtfunction = 0;
buttonActivationReq, vtfunction = 1;
....
extendedGetVersionsRes, vtfunction = 211;
extendedStoreVersionRes, vtfunction = 212;
extendedLoadVersionRes, vtfunction = 213;
extendedDeleteVersionRes, vtfunction = 214;
getVersionsRes, vtfunction = 224;
vtUnsupportedVTFunctionInd, vtfunction = 253;
vtStatusInd, vtfunction = 254;)"
}
and:
type record VTStatusInd
{
VTfunction vtfunction (254),
OCT1 sourceAddressOfActiveWorkingSetMaster,
OCT2 objectIDOfTheVisibleDataAlarmMaskOfTheActiveWorkingSet,
OCT2 objectIDOfTheVisibleSoftKeyMaskOfTheActiveWorkingSet,
e_BusyCodes vtBusyCodes,
OCT1 vtFunctionCode
} with { variant "" };
Sending of the template t_WorkingSetMaintenanceInd() is analogous.
Running the example:
1. The kernel module "can-j1939" needs to be enabled and provided by the kernel. This is e.g. the case for Ubuntu 20.04.
2. Enablung the kernel module:
sudo modprobe vcan
sudo ip link add vcan0 type vcan
sudo ip link set vcan0 up
sudo modprobe can-j1939
If the last one fails, the "can-1939" kernel module is not available.
Install titan core as described here:
https://github.com/eclipse/titan.core
git clone https://github.com/eclipse/titan.core.git
Install as described in Readme.linux
Clone the latest version of can-utils:
git clone https://github.com/linux-can/can-utils.git
Compile it with make and put it to the path or ad "./" to the can-utils commands below: (Current version of ubuntu can-utils is not up-to-date.)
Open a terminal and enter for can traces:
Open another therminal and enter for can-j1939 traces:
j1939spy -td -P -b 4193977 "vcan0"
Start the j1939 address claining demon for the ECU name in a new terminal:
j1939acd -r 100,80-120 -c /tmp/A00081002E0003E7.jacd A00081002E0003E7 vcan0
Start the j1939 address claining demon for the VT name in a new terminal:
j1939acd -r 100,80-120 -c /tmp/A00080002E0003E6.jacd A00080002E0003E6 vcan0
Open a terminal and clone the titan SocketCAN test port:
https://git.eclipse.org/c/titan/titan.TestPorts.SocketCANasp
git clone git://git.eclipse.org/gitroot/titan/titan.TestPorts.SocketCANasp.git
cd titan.TestPorts.SocketCANasp/demo
make
In order to simulate the VT, run in a terminal in the demo directory of the SocketCAN test port:
rm *.log;
make;
ttcn3_start SocketCAN J1939.cfg J1939_Isobus_test.tc_can_j1939_IsobusVtSimulation
The above starts the test case tc_can_j1939_IsobusVtSimulation located in the file J1939_Isobus_test.
In order to simulate the ECU, run in a terminal in the demo directory of the SocketCAN test port within 50 seconds:
ttcn3_start SocketCAN J1939.cfg J1939_Isobus_test.tc_can_j1939_IsobusEcuSimulation
The above starts the test case tc_can_j1939_IsobusEcuSimulation located in the file J1939_Isobus_test.
The file J1939.cfg above in the test case call specifies the CAN interface used: "vcan0":
J1939.cfg:
[LOGGING]
FileMask := LOG_ALL | DEBUG | MATCHING
ConsoleMask := LOG_ALL | DEBUG | MATCHING
LogSourceInfo := Yes
SourceInfoFormat:= Single // Single or Stack
LogEntityName:= Yes
LogEventTypes:= Yes
[TESTPORT_PARAMETERS]
// Syntax:
// <component_name>.<port_name>.<parameter_name> := <parameter_value>
*.pt_socketCAN.SocketCAN_can_interface_name := "vcan0"
*.pt_socketCAN.SocketCAN_debugging := "YES"
[EXECUTE]
//CAN J1939 tests
SocketCAN_J1939_test.tc_can_j1939_send_and_receive_message
SocketCAN_J1939_test.tc_can_j1939_send_and_receive_message_parallel
J1939_Isobus_test.tc_can_j1939_IsobusVtEcuSimulation
J1939_Isobus_test.tc_can_j1939_IsobusEcuSimulation
Run in a termal in the SocketCAN test port demo directory:
ttcn3_logmerge -o log_merged.log *.log;ttcn3_logformat -o log_merged_format.log log_merged.log;
Open the log file in a text editor, e.g. kate:
kate log_merged_format.log
Instead of running the 2 test cases at the same time, you may run a real VT or ECU instead of the corresponding test case.
[Updated on: Mon, 21 September 2020 12:26] Report message to a moderator
|
|
|
Goto Forum:
Current Time: Thu Oct 10 17:29:35 GMT 2024
Powered by FUDForum. Page generated in 0.03407 seconds
|