LabWired The easy way to build hardware
Whitepaper

Catching a CAN bug that only shows up on real hardware — with LabWired

A udslib (my small ISO-14229 stack) user reported a UDS bug that wouldn't reproduce in any test and only appeared on a particular STM32F103 setup.

Single-frame UDS requests work, multi-frame ones don't. The ECU just goes quiet. His PCAN trace showed the tester sending the FirstFrame, ECU answers with a FlowControl, tester sends the ConsecutiveFrame… and then nothing comes back.

Reporter's PCAN trace
The bug as reported. 111h is the tester, 222h the ECU: FirstFrame 10 0B 27 01 5A 11 22 33, the ECU's FlowControl 30 08 00…, the ConsecutiveFrame 21 44 55 66 77 88… — and then no response.
SecurityAccess request in the tester GUI
The request itself: SecurityAccess (0x27), sub-function 1, an 11-byte payload  - too big for a single frame, so it goes out as FF + CF.

His own theory was a length-calculation bug. Reasonable guess for multi-frame length math. It turned out to be something else, and the interesting part. It doesn't reproduce in a normal test, and only shows up on a particular kind of real-hardware setup.

First: it doesn't reproduce

I didn't touch the STM32. I took the exact bytes from his trace and replayed them straight through the current udslib, into the real dispatch layer. It worked. The ECU reassembled the 11 bytes and answered. But I also didn’t have an STM32 on my bench to reproduce the bug — that’s where LabWired comes in.

Watching it happen in LabWired

I built the real udslib firmware for the F103's bxCAN controller and ran it in the simulator in LabWired. Then I built a second copy with the user code bug wired in, and put them side by side as two labs you open in the LabWired playground and press Run.

The F103 UDS lab in LabWired with the logic analyzer open
The reproduction in LabWired: an emulated STM32F103, a CAN transceiver, a virtual UDS tester, and a logic analyzer decoding the bxCAN bus. 

The full exchange the analyzer decodes:

DirectionCAN IDBytesISO-TP / UDS
tester → ECU0x11110 0B 27 01 5A 11 22 33FirstFrame — SecurityAccess requestSeed, 11 bytes
ECU → tester0x22230 08 00 …FlowControl — ClearToSend
tester → ECU0x11121 44 55 66 77 88ConsecutiveFrame
ECU → tester0x22206 67 01 DE AD BE EFPositive response — seed

Run them right here

Both labs are embedded below — press Run in each, then open the Logic tab (or the floating logic-analyzer panel) to watch the analyzer decode the FirstFrame → FlowControl → ConsecutiveFrame → response exchange. The fixed ECU reassembles the multi-frame request and returns the SecurityAccess seed; the broken one shows the FirstFrame and the FlowControl, then goes quiet.

Fixed — the ECU answers 06 67 01 DE AD BE EF. Open full-screen ↗
Broken — FirstFrame + FlowControl, then silence (the N_Cr clock bug). Open full-screen ↗

The actual bug: two different clocks

ISO-TP has a timer called N_Cr: "if I got a FirstFrame and I'm waiting for the ConsecutiveFrame, give up if it doesn't come in time." The trouble is which clock you measure against. In his port the timer was armed from a source that read 0 (an unset get_time_ms), but the code that checks it was fed HAL_GetTick(), already thousands of milliseconds in. So the check was effectively:

if (HAL_GetTick() - 0 >= N_Cr)   // (large number) - 0 is always "expired"

The instant the FirstFrame arrived and the timer armed, the next service tick decided it had already timed out, tore down the multi-frame session, and threw away the ConsecutiveFrame. Single frames don't use N_Cr, so they were fine. It's a clock-source mismatch, not length math. With LabWired I was able to reproduce and debug the bug not even touching the silicon.

Closing the loop on silicon

Then I flashed the same firmware onto a real F103 over the ST-Link and read its result back out of RAM over SWD:

Simulator:  DIFF_RESP = 67 01 DE AD BE EF
Real F103:  0x20000400 -> 5eed0067 00000006 adde0167 0000efbe  ->  67 01 DE AD BE EF
sim == silicon: PASS

Byte-for-byte identical, exact simulation in LabWired.

Andrii Shylenko
Andrii Shylenko

Founder, LabWired.