Run a full ECU diagnostic check with no hardware
Category: Whitepaper
EcuReset last because the ECU reboots after EcuReset.
Automotive diagnostic tests are difficult. You want to test the diagnostics of your ECU. A workshop tool communicates with the UDS services. A rig that flashes ECU firmware communicates with the UDS services. The test needs an ECU on a bench. The test needs a CAN interface. The CAN interface can be PCAN, a Vector box, or a similar tool. The test needs wires and power. The tester controls the other end.
These items do not fit in a CI pipeline. You test the diagnostics by hand on hardware. The regression coverage is limited.
The goal was a full test in software. The test uses a real ECU, a real tester, and a real CAN bus. The test runs headless on a free CI runner.
The test setup
LabWired contains two virtual STM32H5 microcontrollers. A virtual FDCAN bus connects the two microcontrollers. One microcontroller runs a UDS tester. The tester is the client. The other microcontroller runs a UDS ECU. The ECU is the server. The ECU registers all 27 ISO-14229 services. Both microcontrollers run real udslib firmware. udslib is the open-source ISO-14229 stack. You can compile the same stack for a part. The test uses no mocks.
The tester sends a genuine request for every service. The request crosses the virtual bus. The real handler of the ECU runs. The response returns to the tester. The tester checks the bytes.
firmware.elf builds.
The builds run on modelled H563 silicon.
The ECU build is stock udslib.
The gate makes only one assertion.
The assertion is the results word of the tester.
The results word is memory_value @ 0x20010000 == 0x07FFFFFF.
At the end, the tester sets one bit for each service in a results word. A CI job reads the results word. The CI job asserts that the results word equals 0x07FFFFFF. All 27 services answered correctly across the bus. The result is 27/27. The exit code is 0. The test has no hardware in the loop.
An abridged trace from a real run follows. Each line is one UDS exchange. The exchange crosses the virtual CAN bus. The test checks the exchange.
10DiagnosticSessionControl
29Authentication
27SecurityAccess
3ETesterPresent
22ReadDataByIdentifier
2EWriteDataByIdentifier
3DWriteMemoryByAddress
23ReadMemoryByAddress
24ReadScalingDataByIdentifier
2CDynamicallyDefineDataIdentifier
2AReadDataByPeriodicIdentifier
2FInputOutputControlByIdentifier
19ReadDTCInformation
85ControlDTCSetting
14ClearDiagnosticInformation
86ResponseOnEvent
31RoutineControl
34RequestDownload
36TransferData
37RequestTransferExit
35RequestUpload
38RequestFileTransfer
28CommunicationControl
83AccessTimingParameter
87LinkControl
84SecuredDataTransmission
11EcuReset, last
EcuReset until the very end so the reboot cannot erase the other 26 results.
The same gate runs on a clean GitHub Actions runner. The runner installs the toolchain. The runner builds both firmwares. The runner builds the emulator. The runner runs the gate. The run is successful from start to end. See the CI run. Also see LabWired for CI.
The next figure shows the udslib ECU on a virtual STM32H5.
ReadDataByIdentifier request over CAN-FD. The firmware is real udslib firmware. This run uses no hardware. Open the full-screen viewThe test works. The test runs nightly on free GitHub runners. The test finds real bugs. Note which bugs the test found. Every bug was in the emulator. The bugs were not in udslib. All of the bugs are fixed and released.
The result
You get a full 27-service UDS diagnostic check. The check includes session control and security access. The check includes read by identifier and write by identifier. The check includes DTCs and routine control. The check includes the full sequence that programs the ECU and transfers the data. The check ends with ECU reset. The check runs across two virtual MCUs. The MCUs use a simulated CAN network. The check runs headless in CI. The cost is the cost of a GitHub runner minute. The ECU firmware uses udslib completely unmodified.
The CPU model runs your actual firmware. The model can show real bugs before a bench test.
Run the test and see the proof
- The gate and the nightly CI are merged and live in udslib at examples/h5_uds_tester. The gate closed issue #58.
- The successful CI run shows a full build and a 27/27 result on a clean runner. See actions/runs/29379477389.
- udslib is the open ISO-14229 stack under test. The test uses udslib 100% unmodified. See w1ne/udslib.
- Run the ECU. Open the STM32H5 UDS ECU in the LabWired playground.