Frequently Asked Question
Yes. Typhoon HIL supports XCP on CAN protocol.
1. Introduction
XCP (short for Universal Measurement and Calibration Protocol) is a communication protocol that enables efficient and standardized access to electronic control units (ECUs) in vehicles. One of the transport layers that XCP can operate on is the CAN (Controller Area Network) communication protocol. CAN is a widely used network protocol in automotive and industrial applications due to its robustness, low cost, and ability to handle high-speed data transmission. When combined with XCP, it provides a powerful tool for measuring, calibrating, and diagnosing electronic systems in real-time, enabling automotive engineers to develop and optimize complex systems quickly and efficiently.
XCP on CAN communication protocol typically operates in a master-slave configuration. The master device (such as a diagnostic tool or calibration software) initiates the communication and sends requests to the slave device (such as an ECU) to perform specific functions, such as reading or writing data. The slave device then responds with the requested information or confirmation of the action performed. This master-slave configuration allows for efficient and secure communication between the devices, with the master having full control over the communication and the slave only responding to valid requests.
In the XCP communication protocol, the A2L (short for ASAP2) file is a critical component that provides a standardized description of an electronic control unit (ECU) and its internal variables. The A2L file contains information such as the names, data types, scaling factors, and memory locations of the ECU's internal variables, allowing measurement and calibration tools to communicate with the ECU effectively.
The A2L file is typically generated by the ECU manufacturer and included in the software that is delivered with the ECU. It acts as a bridge between the measurement and calibration tools and the ECU, providing a common language for communication and enabling the tools to access and modify the ECU's internal variables safely and efficiently.
2. XCP in the Typhoon HIL toolchain
XCP master is supported in the Typhoon HIL toolchain in HIL SCADA, via the Python library pyxcp, while the parsing and importing of the a2l file is supported via the Python library pya2l. XCP slave is not supported in the Typhoon HIL toolchain.
Attached below is an example HIL SCADA panel file, where you can open the widget properties and write the Python code you want to execute.
First, import the libraries and modules for XCP communication and other libraries.
import os.path import json, os, struct, sys from time import sleep from pyxcp.dllif import getKey from pyxcp.master import Master from pya2l import DB import pya2l.model as model
To access additional Python scripts in your simulation, you will need to append the path for the script to the system path.
sys.path.append(“d:/path/to/python/file”) from xcp_script import XCPclass
One way to initialize the master is with the function: with Master(transportName="can", config=json.load(f)) as xm:
where f is the JSON file that describes the transport type, master and slave ID, and bitrate.
# Initialize the master with the JSON file f = open(r"”d:/path/to/JSON/file/conf_can.json”) with Master(transportName="”can"”, config=json.load(f)) as xm:
After that, you can use the functions defined in the pyxcp library (connect, disconnect, upload, download) to connect and get additional info about the slave device. For unlocking a slave resource, its DLL file must be in the same folder as the SCADA file. If not, the slave resource’s path must be appended to the system path.
In order to parse the a2l file to retrieve the necessary information, the a2l file must be imported into an opened database. Then, after a session is opened, it needs to be closed when the needed operations are done in order to use the database again.
Here is an example code implemented in the xcp_script:
db = DB() db_file_path = a2l_file_path + "db" if os.path.exists(db_file_path): session = db.open_existing(db_file_path) else: session = db.import_a2l(a2l_file_path) # # # # characteristic_dict = session.query(model.Characteristic).all() session.close()
This part of code is an example of how to use the functions defined in pyxcp and implement the xcp_script. The function get_seed_and_unlock gets the XCP seedkey and unlocks the specified resource.
# Initalize the XCP class xcp = XCP_class(master=xm) # Callback function to get data when DAQ lists are started imestamp_enable = False xm.transport.cro_callback = xcp.my_callback conn = xm.connect() mode_info = xm.getCommModeInfo() gid = xm.getId(0x1) status = xm.getStatus() xm.synch() xcp.get_seed_and_unlock(master=xm, resource=0x04) DAQ_proc_info = xm.getDaqProcessorInfo() DAQ_res_info = xm.getDaqResolutionInfo() DAQ_info = xm.getDaqInfo() for i in range(0, len(DAQ_info["channels"])): DAQ_event_info = xm.getDaqEventInfo(i) upload_rcv = xm.upload(DAQ_event_info.eventChannelNameLength) xcp.get_seed_and_unlock(master=xm, resource=0x01) scp = xm.setCalPage(0x83, 0, 0) xcp.build_checksum_for_slave(master=xm, a2l_file_path=a2l_file_path) xcp.set_mta_and_build_checksum(master=xm, a2l_file_path=a2l_file_path)
for i in range(0, DAQ_proc_info.maxEventChannel-1): DAQ_event_info = xm.getDaqEventInfo(i) upload_rcv = xm.upload(DAQ_event_info.eventChannelNameLength)
The next part of the code is to set and get values from the slave specific characteristics and measurements:
pwm = xcp.get_measurement(master=xm, name="PWM", a2l_file_path=a2l_file_path) pwm_filter = xcp.get_measurement(master=xm, name="PWMFiltered", a2l_file_path=a2l_file_path) value = 5 PWM_Level = xcp.get_characteristic_value(master=xm, name="PWM_Level", a2l_file_path=a2l_file_path) xcp.set_characteristic_value(master=xm, value=value, name="PWM_Level", a2l_file_path=a2l_file_path) PWM_Level = xcp.get_characteristic_value(master=xm, name="PWM_Level", a2l_file_path=a2l_file_path) measurement_names = ["channel_d", "TestDWord_501", "TestDWord_502", "TestWord_992", "TestWord_991", "TestWord_989"]
common_dict, data_dict = xcp.create_measurement_list( xm, 2, measurement_names, timestamp_enable, a2l_file_path)
xm.getDaqClock() xm.startStopSynch(0x01)
sleep(1)
xm.getDaqClock() xm.startStopSynch(0x00) xm.disconnect()
get_measurement uploads the specified measurement value from slave to master.
set_characteristic_value downloads the specified characteristic value from master to slave.
get_characteristic_value uploads the specified characteristic value from slave to master.
Also, the create_measurement_list function creates a DAQ (Synchronous Data Acquisition) sequence. When DAQ mode is used for data measurement, the master must first configure the ECU accordingly. In this function you must first specify the event channel, the measurements. and whether the timestamp is enabled.
Once the DAQ sequence is started, the results are stored in the two dictionaries initialized before: common_dict and data_dict.
The XCP_script is also attached. Feel free to adapt the scripts provided to your needs.