This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
<Introduction>
XCP is a common requirement from automotive OEMs. I’ve found that Implementing XCP-on-CAN for a C2000 device is far from straightforward and there doesn’t seem to be much information publicly available so this post is to improve on that situation. The complicating factor is the C2000 Minimum Addressable Unit (MAU) of 16 bits. XCP has a setting called ADDRESS_GRANULARITY (AG) which can be set to WORD instead of the usual BYTE. The intention behind this (I think) was to make XCP adaptable to architectures where the MAU is not 8bits. The problem is that the MCD (Measurement Calibration, Diagnostic) tools I have tried do not support AG=WORD. For example, Vector CANape.
https://support.vector.com/kb?id=kb_article_view&sysparm_article=KB0012595
MathWorks have implemented XCP with CANape but this is only of use when your entire project is MATLAB/Simulink based such that Simulink generates the A2L file and updates its addresses from the ELF file.
https://uk.mathworks.com/help/ti-c2000/ug/calibrate-ecu-can-example.html
That’s fine for individual developers but no good for a large collaborative project consisting of auto-coded and hand coded modules with multiple toolchains.
There’s probably other ways to solve this but here’s how I got XCP-on-CAN to work on F2800039C, although this should be applicable to any C2000 device. Feel free to post a simpler solution or challenge any of the following.
<Implementation Background>
By default, XCP A2L address n and address n+1 differs by 8 bits (AG=BYTE). For the C2000 device, address n and n+1 differs by 16 bits (AG=WORD). The question then is how the C2000 XCP slave (AG=WORD) can emulate AG=BYTE in order to talk to the XCP master? The general solution (not my invention) is to multiply all physical device addresses by 2 such that:
Historically CANape supports this addressing scheme through an expert setting called DSP_MODE, presumably in lieu of XCP AG=WORD mode. CANape DSP_MODE stored all addresses in its ASAP2 database as 2 x the physical device address. When CCP sent a CRO containing an address to the slave it would first divide the A2L database address by 2 before sending the CRO. The C2000 slave therefore receives a meaningful physical address which can be dereferenced without further processing. However, CANape DSP_MODE is only available for a CCP device, the setting is not there for an XCP device. Furthermore address update in CANape is only possible with the legacy COFF linker output, EABI doesn’t work.
So the XCP solution (Vector CANape CCP DSP_MODE emulation) described here has three practical aspects:
The benefit of this scheme is that it is totally hidden from the XCP Master so is portable to any MCD tool with the same A2L file. I happen to be using CANape but if you want a free of charge MCD tool for basic XCP testing, I recommend checking out ASAP2Demo. https://jnachbaur.de/ASAP2Demo/ASAP2.html
<Example Address Mapping>
Source declarations:
Uint16_t XCP_TEST_UBYTE1 = 0x0011; Uint16_t XCP_TEST_UBYTE2 = 0x0022; uint16_t XCP_TEST_UWORD = 0x4433; uint32_t XCP_TEST_ULONG = 0x88776655; uint64_t XCP_TEST_UINT64 = 0x10FFEEDDCCBBAA99;
The example CHARACTERISTICS are being placed in GSRAM0 starting at address 0x0000C000 by the linker.
Device and A2L Address Mapping After Linking and A2L Creation:
View in CANape:
<Suggested Implementation Steps>
Step 1) Get Vector’s XCP Sample Implementation.
Step 2) Make XCP slave source modifications for halving addresses. See attached patch file.
Step 3) Integrate into your application and CAN transport layer code.
Step 4) Make your A2L file as usual but arrange for the addresses in the A2L file to be double the addresses in the linker .out file. This is the trickiest part for which I wrote a Python script.
Step 5) Use your MCD tool with a regular XCP-on-CAN device (AG=BYTE). As far as the MCD tool is concerned, the slave will behave like a device where MAU=8bits like most other ECUs.
<Detailed Steps>
Python Script
# Python program to double the addresses (starting "0x") of MEASUREMENTs and CHARACTERISTICS # in an A2L file. # Tested with Python 3.10. import sys # Use Regex pattern matching. import re def main(): try: in_file = open(sys.argv[1], "r") out_file = open(sys.argv[2], "w") # Read the input file line by line. lines = in_file.readlines() new_list = [] idx = 0 found_IF_DATA = False # Loop through each line for line in lines: # Only start parsing after the IF_DATA section where the # MEASUREMENTs, CHARACTERISTICs etc. are located. if "/end IF_DATA" in line: found_IF_DATA = True if found_IF_DATA == True: # From here, treat all strings beginning "0x" as addresses. if "0x" in line: # For debugging console output. new_list.insert(idx, line) idx += 1 # Get all instances of likely hex numbers in the line. hex_num_str_list = re.findall(r'0x[0-9A-Fa-f]+', line, re.I) # TODO : Handle occasions where more than one 0x is found in a line. # Otherwise just process the first. # Convert string to a number, e.g. '0xA5' -> 165. hex_num = int(hex_num_str_list[0], 16) # Double the address number. e.g. 165 -> 330. hex_num = int(hex_num * 2) # Convert address number to a string. e.g. 330 -> '0x14a'. # TODO : Capitalize the alpha chars apart from 'x'. hex_num_str = hex(hex_num) # Replace the original address. e.g. '0xA5' -> '0x14a' line = line.replace(hex_num_str_list[0], hex_num_str) # Write the line to the output file, modified or not. out_file.write(line) in_file.close() out_file.close() # Debugging console output. if len(new_list)==0: print("\n\"" +"0x"+ "\" is not found!") else: # Print the lines containing "0x" lineLen = len(new_list) print("\n**** Lines containing \"" + "0x" + "\" ****\n") for i in range(lineLen): print(end=new_list[i]) print() except : print("\nInput file not found!") if (len(sys.argv) != 3): print("Usage:") print("python.exe A2LAddressUpdate.py InputFile.A2L OutputFile.A2L") else: InputFile = sys.argv[1] OutputFile = sys.argv[2] main()
Jay Amlani and Arjan Oskam, tagging you here to draw your attention since you posted relatively recently on the XCP topic.
Thanks, looks interesting.
I don't have this particular problem because I have done an XCP on TCP/IP implementation on the F28388D CM core (ARM Cortex M4), where the MAU is the usual 8 bits. But it may get interesting for me later because I plan to forward XCP messages via Inter Processor Communication to Simulink applications running on CPU1 and CPU2.