PIC18F4431 Read-Out: One Config Bit Changes the Mnemonics

A hex file is not a program listing. On a PIC18F4431, one bit in CONFIG4L decides whether the instruction decoder treats a group of words as legacy instructions or as indexed-literal offsets. Disassemble without it and you get a listing that is wrong in a way that still looks like assembly.

The device is a 16 KB part — 8,192 instruction words — with 768 bytes of SRAM, 256 bytes of data EEPROM, 36 I/O pins, a 14-bit power control PWM module with eight channels and programmable dead-time insertion, a motion feedback module with a quadrature encoder interface, and a nine-channel 10-bit ADC running at 200 ksps. It shares DS39616 with the 28-pin 2331 and 2431 and with the 8 KB PIC18F4331.

XINST Is Not an Optimisation Flag

CONFIG4L bit 0 is XINST, the extended instruction set enable. Erased devices ship with it clear, which is why most firmware on this family uses the legacy set and most disassemblers assume it.

When XINST is set, the core adds indexed literal offset addressing: ADDFSR, SUBFSR, PUSHL, and a reinterpretation of the MOVLB/literal-offset encoding. The encoding space is shared with legacy instructions. That is the trap — a word that means one thing with XINST clear means something different with it set, and both decodings are *valid instructions*. No illegal-opcode warning appears. The disassembler produces a listing full of plausible operations that do not match what the hardware executes.

This is why a recovered image should arrive with its configuration words, not just its flash. The four blocks of CONFIG1L–CONFIG5H at 0x300000 are not a formality to be filled in later. For a motor control part, CONFIG4L is the key that says how to read the other 16 KB.

Why It Matters Most on a Power Control Part

On a part whose job is to switch a half-bridge, a misread branch is not an academic error. The listing is used to answer “what dead-time is this design using” and “what does this table index”. Assume XINST wrong and the address arithmetic around a lookup table decodes into instructions that appear to compute an index differently from what the silicon does.

The dead-time itself is a runtime value: it is written into the PDC registers from a constant, or from a table indexed by bus voltage or temperature. The constant is in flash. It comes out with the read. What does not come out with a plain dump is the *meaning* of the table it sits in, and that meaning depends on correctly decoded addressing modes.

The Read-Out Sequence That Avoids This

A defensible sequence for this family:

1. Read the config block first, before the flash. 0x300000–0x30000B, then 0x3FFFFE for the device ID and 0x3FFFFF for the revision. 2. Record XINST explicitly in the delivery note. One line: extended instruction set enabled or disabled. 3. Disassemble twice if the listing looks inconsistent — once with each setting — and keep the version that agrees with the observed hardware behaviour. 4. Cross-check against the peripheral map. The 4431’s PTCON, PTPER, PDC0–PDC3 and QEI registers are at fixed addresses. If the listing’s writes land on those addresses and produce sane values, the decode is probably right. If they land on reserved addresses, it is definitely wrong.

Step 4 is the cheapest and most often skipped: the SFR addresses are public, so a listing that writes its PWM period to an address that is not PTPER is a decode error, not a firmware quirk.

What “Content” Includes

A read-out of this part is four things, and only one of them is the flash:

  • 16 KB of program memory at 0x000000–0x003FFF, in four 4 KB code protection blocks
  • Twelve configuration bytes at 0x300000
  • 256 bytes of data EEPROM at 0xF00000
  • Device and revision ID at 0x3FFFFE and 0x3FFFFF

Files that omit the second and fourth are extremely common, because a programmer that only knows the flash range will not emit them. They program, and the board does not run, and the conclusion drawn is that the recovery failed. It did not; the file was short.

If the array is fully closed, the route runs through the die rather than through the programming interface, and the resulting image still has to clear the same checks. That is the chip extraction analysis step, and it produces a file that is only as good as its configuration block.

The practical version: ask for the config bytes in writing before the work starts. Everything downstream — extract firmware, rebuild, verification — depends on those twelve bytes. If you are unsure which blocks were locked, say so; it changes the plan more than the part number does. The contact us page takes the marking photograph and board picture together, which is enough to scope most jobs.