A CAN node can be copied byte for byte and still fail on the bus. The reason is that half of what makes it work is not code — it is a timing constant, a filter mask and a node address that live in three different places.
The PIC18F4580 is a 40-pin enhanced-flash part from the PIC18F2480/2580/4480/4580 family, documented in DS39637. It has 32 KB of program memory, 1,536 bytes of RAM, 256 bytes of data EEPROM, an ECAN module conforming to CAN 2.0B Active, an 11-channel 10-bit ADC, one CCP and one ECCP, a parallel slave port, and it runs at 40 MHz for 10 MIPS. It is the part that appears in pump controllers, HVAC sub-buses, battery chargers and small industrial I/O blocks — equipment where the CAN interface is the product.
Bit Timing Is a Constant, and It Lives in Flash
Every ECAN node has to agree with the rest of the bus on one number: the time quantum. Firmware computes it from the oscillator frequency at build time and writes it into BRGCON1, BRGCON2 and BRGCON3 at start-up. On a 40 MHz part with a 4× PLL, a 500 kbit/s bus usually lands on a prescaler of one and eight time quanta per bit.
That constant is compiled into the image and it is correct for exactly one clock frequency. Copy the flash faithfully but lose the configuration words that set the oscillator and the PLL, and the part runs from its internal oscillator at 8 MHz. The CAN registers are then programmed with a prescaler computed for 40 MHz, the actual bit time comes out five times too long, and the node transmits error frames into a bus it can no longer join. The image is perfect. The board is silent.
This is why a configuration block missing from a delivered file is not a cosmetic omission on CAN hardware: it changes the electrical behaviour of the network.
256 Bytes That Name the Node
Data EEPROM on a 4580 is usually the identity of the unit. Node address, baud-rate override, calibration offset, a serial number, sometimes a copy of the acceptance filter table that the host can rewrite over CAN. It is separate memory with its own protection bit, CPD, in CONFIG5H at 0x300009.
CPD is independent of the four flash bits. A device with full flash readable and CPD set reads 0x00 for all 256 bytes, and the pattern is easy to mistake for an erased EEPROM. It is not erased: an erased byte reads 0xFF. When a recovered EEPROM comes back all zeros, the correct conclusion is that it was protected, and the recovery scope has to include it.
The Array in Four Pieces
| Block | Byte range | Words | Bit |
|---|---|---|---|
| 0 | 0x000000–0x001FFF |
4,096 | CP0 |
| 1 | 0x002000–0x003FFF |
4,096 | CP1 |
| 2 | 0x004000–0x005FFF |
4,096 | CP2 |
| 3 | 0x006000–0x007FFF |
4,096 | CP3 |
All four sit in CONFIG5L at 0x300008; CPB and CPD share CONFIG5H at 0x300009. Protection is per block, so a product with a bootloader sometimes protects only the top block and leaves the application readable. That produces a file that looks half-complete and is actually fully readable — worth knowing before anyone quotes a full die attack.
The Sibling With Half the Array
The PIC18F4480 shares the datasheet, the pinout, the peripherals and the package, and has 16 KB of flash. It is a legitimate donor for a 4580 board as long as the application fits in the low half. If it does not, the failure is not a dead board: the part boots, initialises CAN, answers the first few frames, and then faults the first time execution reaches an address above 0x3FFF. Intermittent faults that depend on which command the master sends are the signature of a donor with the wrong array size.
The PIC18F2585 is the same trap from the other direction: same 48 KB class, 28-pin, same ECAN block, different pin count and different flash size. Same family name, different image.
Three Checks Before You Trust the File
1. Zero-run shape. A run of 0x0000 that begins and ends on an 8 KB boundary is a protected block. 0x0000 is NOP on PIC18, so it disassembles cleanly and passes a naive sanity check. 2. Device ID at 0x3FFFFE. It separates a 4580 from a 4480 and from the 28-pin parts. Read it before comparing anything else. 3. Seams. Disassemble across 0x1FFF, 0x3FFF and 0x5FFF. A branch that lands mid-instruction at a boundary means a word was dropped while the blocks were being stitched back together.
Send the marking photo, the board photo and a note on which protection bits were set, and the scope — flash only, or flash plus CPD plus code protection work — can be settled before anything is quoted. The services page lists what each route delivers.