Skip to main content

Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
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 is currently offline Michael JosenhansFriend
Messages: 99
Registered: February 2016

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:

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:

In general there 3 different things:

  1. J1939 Address
  2. J1939 NAME
  3. 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.


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):

      []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 :=
        // 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(?)) {
            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;)"

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:

git clone

Install as described in Readme.linux

Clone the latest version of can-utils:

git clone

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:
candump -td -d "vcan0"

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:

git clone git://
cd titan.TestPorts.SocketCANasp/demo

In order to simulate the VT, run in a terminal in the demo directory of the SocketCAN test port:
rm *.log;
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":

LogSourceInfo := Yes
SourceInfoFormat:= Single // Single or Stack
LogEntityName:= Yes
LogEventTypes:= Yes

// Syntax:
// <component_name>.<port_name>.<parameter_name> := <parameter_value>
*.pt_socketCAN.SocketCAN_can_interface_name := "vcan0"
*.pt_socketCAN.SocketCAN_debugging := "YES"

//CAN J1939 tests

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

Previous Topic:Porting 3gpp test suites to Titan
Next Topic:Eclipse Titan Issue The executable file does not exist
Goto Forum:

Current Time: Sat Jun 19 23:01:01 GMT 2021

Powered by FUDForum. Page generated in 0.02113 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top