Attacking a PIC16CR84: Why Mask ROM Changes the Entire Problem
Most microcontrollers discussed in recovery work are flash or EPROM devices, and their protection is a bit that can in principle be defeated. The PIC16CR84 is not one of those. Its program memory is mask ROM — written at the factory by the diffusion mask itself. There is no erase operation, no configuration lock to clear, and no programming interface that could ever return the contents. Understanding that difference is the entire basis for reasoning about this part.

First, decode the part number
The PIC16C8x family is one of the most frequently misread in the whole PIC range, and the letters before the number are the reason. Four device types share the same 18-pin package, the same core, and the same pinout:
| Prefix | Program memory | Voltage range | Erasable |
| C (e.g. PIC16C84) | EEPROM | Standard | Yes, electrically |
| F (e.g. PIC16F84) | Flash | Standard | Yes, electrically |
| LF (e.g. PIC16LF84) | Flash | Extended | Yes, electrically |
| CR (e.g. PIC16CR84) | Masked ROM | Standard | No — never |
| LCR (e.g. PIC16LCR84) | Masked ROM | Extended | No — never |
So the CR prefix is not a revision or a temperature code. It denotes a device whose program was fixed at the wafer stage and cannot be changed by any means afterward. Any statement about “unlocking” a CR84 that assumes an erasable array is describing the wrong device.
The part in context
| Property | PIC16CR84 |
| Program memory | 1K × 14 words, mask ROM |
| Data memory (RAM) | 68 bytes |
| Data EEPROM | 64 bytes |
| I/O pins | 13 |
| Package | 18-pin PDIP/SOIC |
| Interrupt sources | 4 |
| Program memory type | Factory mask ROM |
The 64 bytes of data EEPROM are worth pausing on. They are a separate, electrically writable region — masking the program did not remove them. In real products that block holds serial numbers, calibration offsets, or user settings written during test. A recovery effort that reaches the ROM array and stops there produces a program image with no idea what belonged in the EEPROM.
How mask ROM is programmed
There is no programmer involved. The customer supplies a code image to the manufacturer, and that image is converted into a photomask used during wafer fabrication. Each bit in the array is defined by whether a contact, via, or implant is present at that location.
That physical difference is exactly what makes the part recoverable at all, and it is also why the recovery is destructive. A programmed cell and an unprogrammed cell look different under a microscope — the presence or absence of a contact or an implant region produces a visible contrast. The information is not hidden behind a logic gate; it is written into the geometry of the silicon.
What “protection” means here
On a flash or EPROM part, the code-protect bit is a control that a read attempt hits and fails. On a mask ROM part, there is no read path to protect. The manufacturer’s masked devices were offered with code-protection options at mask time, but the practical outcome is the same as having no protection at all in one respect and stronger protection in another:
- No electrical route exists. No programming interface, no in-circuit serial programming, no debug access returns anything from the ROM array. There is nothing to glitch, because there is no gate evaluating a permission.
- No erasure is possible. The documented escape hatch on other parts — erase, accept the loss, start over — does not exist. A CR84 cannot be blanked, reused, or repurposed.
This inverts the usual asymmetry. Elsewhere, the temptation is that clearing protection destroys the code. Here there is no protection to clear and no code to destroy; the device is simply a read-only object, and the only question is whether someone images it.
The actual routes
Decapsulation and optical read. Remove the package, expose the die, and image the ROM array. Because the bit state is geometric rather than stored as charge, this is a visual problem: contrast between programmed and unprogrammed cells, resolved at the array’s pitch. For a 1K × 14 array this is a modest imaging task.
Microprobing. Where optical contrast is insufficient — for instance on a process where the implant difference is faint — the array’s sense amplifiers or bit lines can be probed directly, reading the array electrically from the inside.
Find a flash sibling. This is the route that is underused. Many products shipped in more than one variant, and the flash-based PIC16F84 carries the same core, the same instruction set, and often the same firmware. If a programmed F84 from the same product exists, reading it is far cheaper than imaging a ROM die. Related work on the flash side: PIC16F84 code recovery and PIC16F84 protection.
Reconstruct from behaviour. With 13 I/O and 1K words, a functional characterisation is plausible for simple control firmware, though it yields behaviour rather than code.
The mask-ROM sibling at half the array size is covered in PIC16CR83 recovery, and the flash-based smaller variant in PIC16F83 EEPROM recovery.
Why a CR84 is still worth recovering
Mask ROM parts were chosen for one reason: unit cost in volume. That means they are concentrated in exactly the products that shipped in the largest numbers — appliances, consumer electronics, simple industrial controls — designed through the 1990s and early 2000s. Those products have long service lives and long repair tails.
When such a unit fails and no spare exists, the mask ROM die is the only record of the firmware. Nothing was ever written down that could reconstruct it, because there was never a file to archive: the code went to the factory as a mask order and stopped existing as an artifact after the wafers were made.
Limits worth stating upfront
- Destructive by nature. Optical read requires removing the package; the device does not survive as a working part.
- No fallback. Unlike an EPROM part, there is no erase-and-retry cycle and no way to verify by reprogramming.
- The EEPROM block is separate. 64 bytes of data EEPROM must be captured independently, or the rebuild will be missing its calibration.
- 1K words caps complexity. A large state machine will not fit, which bounds what behavioural reconstruction can achieve.
FAQ
Can a PIC16CR84 be erased and reprogrammed? No. The program is defined by a fabrication mask. There is no erase mechanism and no programming interface for the array.
Is there a code-protect bit to defeat? Not in any practically meaningful sense. There is no read-back path to guard, so fault injection has no target on this part.
How is the code read, then? By exposing the die and imaging the ROM array, where programmed and unprogrammed cells differ geometrically, or by probing the array electrically.
Why do I also need the 64 bytes of EEPROM? Because that block is separately writable and typically holds calibration or identification written during production. The ROM image alone is incomplete.
Conclusion
The PIC16CR84 is the case that makes the difference between protecting code and never storing it in a readable form concrete. There is no lock to pick, because there is no lock — the code exists as geometry on the die, and the only way to it is to look. That makes the problem simpler to reason about and harder to solve: simpler because the route is unambiguous, harder because it always costs the device.