Skip to Content
UDS Simulator 2.0 Released

Docs baseline actions

Copy this page URLOpen support page for feedback
DocsECU Flashing & Reprogramming
Maintained by the UDS Simulator TeamLast updated Referenced against ISO 14229-1
Flash Programming

ECU Flashing & Reprogramming

The complete ISO 14229 reprogramming ladder — every stage, every byte on the wire — and how to drive it in the simulator’s Flashing Wizard.

Overview

ISO 14229-1

”The RequestDownload service is used by the client to initiate a data transfer from the client to the server (ECU).”

info _entry

Flashing is not a service — it is a choreography. ISO 14229 defines no “flash” request. Reprogramming an ECU means driving eight different services in a fixed order: 0x10 to reach PROGRAMMING, 0x27 to unlock, 0x31 to erase and verify, 0x34/0x36/0x37 to move the bytes, 0x3E to keep the session alive throughout, and 0x11 to boot what you just wrote. Get the order wrong and the ECU says no; get it half-right and the ECU is a brick.

warning _entry

This is the one irreversible operation in UDS. Erase is destructive and happens before the first payload byte arrives. If the run stops between erase and verify, the region stays erased or invalid and the next reset boots the bootloader instead of the application. That failure mode is not a bug in the simulator — it is exactly what happens on a real bench, which is why the flow re-erases on every attempt and needs no resume state.

The Reprogramming Ladder

Fifteen stages for a bootloader image, eleven for an application image. Toggle the image type to see the four driver-staging stages appear and disappear, then open any stage for the frames it puts on the wire.

Reprogramming Ladder

Every stage the orchestrator runs, in send order. Select a stage to see the bytes on the wire.

Executor → target

The resident bootloader stages a flash driver into RAM, then programs the Bootloader partition through it — a sector cannot erase itself while executing from it.

RegionBootloader
Address0x00400000
Size32 KB
0x36 blocks9
0 / 15

Percentages are the simulator’s fixed progress weights, normalised over the stages actually present — which is why an erase appears to stall at the same point on every run.

The full ladder, in send order. The four driver* stages run only for a BSW (bootloader) image — an application image is programmed directly by the resident bootloader, so those stages are skipped entirely.

#StageBytes sentWeightBSW only
1Connecting10 0310 02 — session control3
2Unlocking security27 01 / 27 02 — seed & key2
3Preflight checks31 01 0203 — programming dependencies2
4Requesting driver34 — RequestDownload (flash driver)3
5Transferring driver36 — TransferData (driver blocks)10
6Committing driver37 — RequestTransferExit2
7Activating driver31 01 FF03 — activate flash driver3
8Erasing31 01 FF00 — erase memory15
9Requesting download34 — RequestDownload (image)1
10Transferring data36 — TransferData blocks44
11Committing image37 — RequestTransferExit2
12Integrity check31 01 FF01 + 31 03 — CRC324
13Verify programming31 01 FF02 — mark region valid7
14ECU reset11 01 — hard reset2
15CompleteApplication running
tip _entry

Weights are fixed, not measured. The progress bar uses the weights above, normalised over the stages actually present. That is why an erase always appears to stall at the same percentage — the ECU reports no fraction for a routine, only “in progress” and “done”. Only the block-transfer stages report real fractional progress, because only they have a byte count to divide by.

Byte-Exact Walkthrough

A complete bootloader-image run against the simulator’s mock ECU. Addresses and sizes come from the real memory map; an application run swaps the target for Flash Code at 0x00001000.

tx_packet

Step 1 — Enter EXTENDED

10 03

> PROGRAMMING is not reachable from DEFAULT. The ladder always climbs through EXTENDED first.

rx_packet

EXTENDED active

50 03 00 64 01 F4

> P2 = 0x0064 (100 ms). P2* = 0x01F4, encoded at 10 ms resolution = 5000 ms.

tx_packet

Step 9 — Erase memory

31 01 FF 00 44 00 40 00 00 00 00 80 00

> RID 0xFF00 with the shared option record: ALFID 0x44, address 0x00400000, size 0x8000.

rx_packet

Deferred — then a pushed 71 01 FF 00 01 00

7F 31 78

> Erase does not answer synchronously. The ECU sends 0x78 responsePending, then pushes the final response when the routine finishes.

tx_packet

Step 15 — Hard reset

11 01

> Boot mode is recomputed from the programming states. A valid application boots the application; anything else boots the bootloader.

rx_packet

Resetting

51 01

> The keep-alive has already stopped — the run is terminal.

The complete frame log for a 32 KB bootloader image. An application run skips steps 5–8 and targets Flash Code instead.

StepRequestResponseMeaning
110 0350 03 00 64 01 F4EXTENDED — P2 100 ms, P2* 5000 ms
210 0250 02 00 32 01 F4PROGRAMMING — only reachable from EXTENDED
3E 80(suppressed)Keep-alive starts, repeating every 2000 ms
327 0167 01 12 34 56 78Seed request, security level 1
427 02 B7 6E A6 7767 02Key accepted — unlocked
534 00 44 00 30 00 00 00 00 20 0074 20 10 00Driver → RAM 0x00300000, 8 KB; maxBlock 0x1000
636 0136 0376 0176 038 KB = 2 × 4094 + 4 bytes
73777Driver bytes committed to RAM
831 01 FF 03 44 00 30 00 00 00 00 20 00 CC CC CC CC7F 31 7871 01 FF 03 01 00Driver hash verified — flashDriverActive
931 01 FF 00 44 00 40 00 00 00 00 80 007F 31 7871 01 FF 00 01 00Region blanked to 0xFF, state → erased
1034 00 44 00 40 00 00 00 00 80 0074 20 10 00Image → 0x00400000, 32 KB
1136 0136 0976 0176 0932 KB = 8 × 4094 + 16 bytes
123777Bytes land in the Bootloader region
1331 01 FF 01 44 00 40 00 00 00 00 80 00 CC CC CC CC71 01 FF 01 00CRC32 check starts — fast routine
1331 03 FF 0171 03 FF 01 01 00 CC CC CC CCResults read back — CRC pass
1431 01 FF 02 44 00 40 00 00 00 00 80 00 CC CC CC CC7F 31 7871 01 FF 02 01 00 CC CC CC CCprogrammingState → valid; keep-alive stops
1511 0151 01Boot mode recomputed → application
warning _entry

TesterPresent is load-bearing here, not belt-and-braces. During a ten-second erase the tester sends no requests at all. The pushed 0x78 frames travel ECU → tester and do not reset S3, which only resets on requests the ECU receives. Without the 2000 ms keep-alive the session collapses mid-routine and the run dies with the region already erased.

The Shared Option Record

All four flash routines take the same option record, deliberately shaped like the address/size pair in a SID 0x34 request. Learn it once and every routine in the ladder reads the same way.

[ALFID = 0x44] [memoryAddress : 4 bytes BE] [memorySize : 4 bytes BE] ([crc32 : 4 bytes BE])

The 0x44 prefix is an addressAndLengthFormatIdentifier: high nibble = the length of the size field, low nibble = the length of the address field. Both are 4, so both fields are four bytes big-endian. The trailing CRC32 is present only on the routines that verify content. A malformed record is answered with NRC 0x13.

RIDRoutineOption recordAnswersNotes
0x0203checkProgrammingDependenciesnonesynchronousThe one standard ISO routine in the ladder
0xFF00eraseFlashMemoryaddress + sizedeferred 0x78 → pushedBlanks the partition to 0xFF, state → erased
0xFF01checkMemoryIntegrityaddress + size + CRC32synchronousThe only fast flash routine — computes at START
0xFF02verifyProgrammingaddress + size + CRC32deferred 0x78 → pushedThe commit point — promotes the region to valid
0xFF03activateFlashDriveraddress + size + CRC32deferred 0x78 → pushedAuthenticates the staged driver against the ECU’s manifest
info _entry

0xFF00–0xFF03 are manufacturer-defined, not ISO. ISO 14229-1 reserves the RID range 0xF200–0xFFFF for the vehicle manufacturer and defines only 0x0202 eraseMemory and 0x0203 checkProgrammingDependencies as standard programming routines. Real OEMs each pick their own numbers in that range; the four above are this simulator’s choice. What transfers between programs is the shape — erase, check, commit, and a driver-activation gate — not the identifiers.

Deferred Routines & NRC 0x78

An erase takes seconds; P2 is 50 milliseconds. Three of the four flash routines resolve this the way real ECUs do — they answer 0x78 and push the real answer later.

tip _entry

The tester never polls. Each repeated 7F 31 78 refreshes the deadline to now + P2* (5000 ms), and the routine resolves only when the ECU pushes its 71 01 <RID> … frame. A full P2* window with neither a 0x78 nor a final response is a timeout. The overall budget is the routine’s execution time plus 10 seconds. A manual 31 03 <RID> results request still works from the console — the orchestrator simply never needs it.

warning _entry

0x78 is not an error. It is the only negative response code that means “still working”. Treating it as a failure is the single most common mistake in a hand-written flash client — the run aborts three seconds into a ten-second erase, leaving the region blank.

Deferred erase — 0x78 then a pushed final response

8 steps
Tester
ECU

Block Transfer Math

The 0x74 response names the largest block the ECU will accept. Every off-by-one in a flash client lives in the two bytes between that number and the payload you may actually send.

maxNumberOfBlockLength includes the 0x36 service ID and the block-sequence-counter byte. A reported 0x1000 therefore permits 4094 payload bytes, not 4096.

QuantityValueDerivation
maxNumberOfBlockLength0x1000 = 4096From the 74 20 10 00 response
Usable payload per block4094maxBlockLength − 2 (SID + BSC)
Bootloader image, 32 KB9 blocks8 × 4094 + 16 remaining
Application image, 64 KB17 blocks16 × 4094 + 32 remaining
Flash driver, 8 KB3 blocks2 × 4094 + 4 remaining
Block-sequence counter0x010xFF0x01Starts at 1, wraps back to 1
warning _entry

The counter wraps to 0x01, not 0x00. After block 255 the next block is 36 01 again. ISO wraps through 0x00; this simulator skips it, matching a common real-world implementation quirk. A mismatched counter is answered with NRC 0x73 — and because the negative response carries no expected-counter byte, there is nothing to resynchronise against. The only recovery is a fresh run, which is safe precisely because every run erases first.

ECU Software Architecture

Two questions decide the shape of every flash run: which layer is being written, and which layer is doing the writing. They are never the same layer.

ECU Software Architecture

Which layer runs the flash, and which layer it writes to, depends entirely on the image type.

Data pathBootloaderstagesFlash Drivererasing · writing · verifyingBootloader
  • ASW
    Flash Code
    Valid
    Application image slot — the flash target for an ASW image0x00001000 – 0x00011000 · 64 KB
  • RAM
    Flash Driverexecuting
    Active in RAM
    Transient helper staged into RAM to program protected flash0x00300000 – 0x00302000 · 8 KB
  • BSW
    Bootloadertarget — being written
    Programmed — pending verify
    Resident recovery loader — drives the UDS flash sequence0x00400000 – 0x00408000 · 32 KB
  • HW
    Microcontroller · Flash memory
    Hardware
    Physical non-volatile memory7 mapped regions

A bootloader cannot erase the sector it is executing from, so a BSW run stages a flash driver into RAM first and programs through it. The driver is transient — a reset releases it.

AnimationTX — write to ECURX — read backERASECTRL — handshakeERROR

A microcontroller cannot erase the flash sector it is currently executing from. That single hardware constraint produces the whole two-stage BSW sequence:

Image typeTarget — being writtenExecutor — doing the writingDriver staged
ASW (application)Flash Code, 0x00001000, 64 KBBootloader (resident)No
BSW (bootloader)Bootloader, 0x00400000, 32 KBFlash Driver in RAM, 0x00300000Yes — 8 KB

The flash driver is transient: it lives in RAM, is authenticated by hash before it is trusted, and does not survive a reset. That is also why you cannot supply your own driver — routine 0xFF03 compares the staged bytes against the ECU’s own flash-driver manifest, and only the matching image passes.

A region’s programmingState is what the layer panel colours itself from, and what boot mode is computed from after a reset:

StatePanel labelMeaning
erasedErasedBlanked to 0xFF, no valid content
programmedProgrammed — pending verifyBytes written, 0xFF02 has not yet confirmed them
validValidVerified and bootable
invalidInvalidVerification failed — will boot to the bootloader

When It Goes Wrong

Not every negative response is fatal. A flash client that treats them all the same either gives up on a recoverable hiccup or grinds on through a real failure — both leave an unbootable ECU.

ResponseClassificationBehaviour
0x78 responsePendingin-flightExtends the wait to now + P2* on each repetition. Never fails the run
0x21 busyRepeatRequestretryableSame frame retried 3×, backing off 200 / 500 / 1000 ms
0x92 / 0x93 voltageretryable, pausedHolds the phase, surfaces “voltage out of range”, auto-retries every 1 s up to 10×
0x37 requiredTimeDelayNotExpiredretryable, timedWaits out the 10 s security penalty once, then re-requests the seed. A second failure is fatal
0x73 wrongBlockSequenceCounterfatalNo expected-counter byte is returned, so there is nothing to resync to. Restart the run
0x33 / 0x7F / 0x7E after setupfatal — session lostS3 expired or the session dropped mid-flash
0x24 / 0x31 / 0x70 / 0x13 / 0x22fatalSequence or configuration error. The message names the phase and the NRC
0x72, or a 0xFF01/0xFF02 verdict of 0x01fatal — verify mismatchThe region is now invalid. Re-flash from the top
info _entry

Retryable means the ECU asked you to wait, not that the write went wrong. Busy and voltage faults are transient conditions on the ECU side and the same frame is safe to resend. A CRC mismatch or a bad block counter means the two sides disagree about what was written — no amount of retrying reconciles that, and the only honest recovery is to erase and start again.

Flashing Wizard Walkthrough

The simulator runs the entire ladder against a mock ECU, one gated stage at a time. Nothing here is a mock-up of a flash tool — the frames in the log are the frames the engine actually processed.

Flashing Wizard

Three steps, at udssimulator.com/flashing.

Step 1Select image

Pick a firmware image — either one of the synthetic catalog images sized to exactly fill its partition, or your own file. The image type you choose (ASW or BSW) decides the whole shape of the run.

Image catalog
Pre-built ASW and BSW images. Each is sized to fill its target partition exactly, so the erase, download and verify records are correct by construction.
Upload firmware
File input, drag-and-drop, or a paste-hex textarea. Accepts .hex, .ihex, .s19, .s28, .s37, .srec, .mot and .bin up to 1 MB.
Target partition picker
Appears only for address-less input — raw binary and pasted hex carry no load address, so you name the target partition yourself.
Firmware preview
Detected format, byte count, target address and CRC32, shown before you commit to flashing anything.
tip _entry

Turn on “Show raw protocol bytes”. It is off by default, which keeps the log readable as a narrative — but with it on, every stage grows a TX/RX frame row carrying the exact request and response hex, truncated to 16 bytes with the full length appended. That is the view worth keeping open the first few times you step through a run.

info _entry

Manual mode is the default, and that is the point. On a real bench a flash run is thirty seconds of unreadable scrolling. Here the wizard arms one stage, waits, and shows you what it is about to send before it sends it — which is the only way to actually watch an erase turn a region from valid to erased, or a verify promote it back.

Recovery & Abort

Abort stops after the current command, never in the middle of one, then drops the session back to DEFAULT. Returning to DEFAULT clears the download state, the active transfer, security access and the staged flash driver in one move.

warning _entry

Aborting mid-run leaves the ECU in bootloader mode, and it should. If the target had already been erased, its programmingState stays erased or invalid — so the next 11 01 boots the bootloader rather than an application that is no longer there. The simulator does not paper over this. It is the exact behaviour that makes a bootloader worth having.

info _entry

Recovery is simply a fresh run. There is no resume-from-block, and none is needed: every run starts from the session ladder and re-erases before transferring, so re-flashing is idempotent. Restart after a failure and the second attempt is byte-for-byte the first one.

Firmware Images

The catalog images are sized to fill their target partition exactly, so the erase, download and verify records are correct by construction. You can also supply your own file.

FormatExtensionsCarries a load address
Intel HEX.hex, .ihexYes — from the record set
Motorola S-record.s19, .s28, .s37, .srec, .motYes — from the record set
Raw binary.binNo — pick the target partition yourself
Pasted hexNo — pick the target partition yourself

Uploads are capped at 1 MB. Address-less input reveals a target-partition picker, because a raw byte array says nothing about where it belongs. Before anything is flashed, a preview reports the detected format, byte count, resolved target address and CRC32.

info _entry

Only partitioned regions are flashable. Calibration regions define no flash partition, so a calibration-addressed image is rejected at parse time rather than routed into the sequence — an erase against a partitionless region would take NRC 0x31 anyway. Calibration data is written the free-form way, with SID 0x3D WriteMemoryByAddress.

ISO 14229-1 References

info _entry

Standard: ISO 14229-1:2020. Session control §9.2 · ECU reset §9.3 · Security access §9.4 · Routine control §13.2 · RequestDownload §14.2 · TransferData §14.4 · RequestTransferExit §14.5.

Key points

  • ISO defines no “flash” service — reprogramming is a fixed composition of eight existing services
  • addressAndLengthFormatIdentifier: high nibble = memorySize length, low nibble = memoryAddress length
  • maxNumberOfBlockLength includes the 0x36 SID and the block-sequence-counter byte
  • NRC 0x78 means “still working” and refreshes the P2* deadline — it never fails a run
  • ISO reserves RIDs 0xF200–0xFFFF for the manufacturer; only 0x0202 and 0x0203 are standard programming routines
  • PROGRAMMING is reachable only from EXTENDED, and every session change clears security access