Break IC PIC16C74B Binary
Break IC PIC16C74B by disabling its security fuse bit, this process will refer to MCU cracking and focus ion beam, Binary inside the program memory of Microcontroller can be extracted and rewrite to new Microprocessor PIC16C74B;

Break IC PIC16C74B by disabling its security fuse bit, this process will refer to MCU cracking and focus ion beam, Binary inside the program memory of Microcontroller can be extracted and rewrite to new Microprocessor PIC16C74B
A variety of frequency ranges and packaging options are available. Depending on application and production requirements, the proper device option can be selected using the information in the PIC16C74B Product Identification System section at the end of this data sheet. When placing orders if copy dsp TMS320LF2401AVFA flash memory, please use that page of the data sheet to specify the correct part number.
For the PIC16C7X family, there are two device “types” as indicated in the device number:
1. C, as in PIC16C74. These devices have EPROM type memory and operate over the standard voltage range.
2. LC, as in PIC16LC74. These devices have EPROM type memory and operate over an extended voltage range after Break IC.
The UV erasable version, offered in windowed CERDIP packages, is optimal for prototype development and pilot programs. This version can be erased and reprogrammed to any of the oscillator modes. Microchip’s PICSTART Plus and PRO MATE II programmers both support programming of the PIC16C63A/65B/73B/74B when Break IC.
The availability of OTP devices is especially useful for customers who need the flexibility for frequent code updates and small volume applications.
The OTP devices, packaged in plastic packages, permit the user to program them once. In addition to the program memory, the configuration bits must also be programmed before chip PIC16F73 program copying.
Microchip offers a QTP Programming Service for factory production orders. This service is made available for users who choose not to program a medium to high quantity of units and whose code patterns have stabilized. The devices are identical to the OTP devices but with all EPROM locations and configuration options already programmed by the factory. Certain code and prototype verification procedures apply before production shipments are available. Please contact your local Microchip Technology sales office for more details.
Microchip offers a unique programming service where a few user-defined locations in each device are programmed with different serial numbers. The serial numbers may be random, pseudo-random or sequential.
Serial programming allows each device to have a unique number, which can serve as an entry code, password or ID number.
The high performance of the PIC16CXX family can be attributed to a number of architectural features commonly found in RISC microprocessors. To begin with, the PIC16CXX uses a Harvard architecture, in which program and data are accessed from separate memories using separate buses.
This improves bandwidth over traditional von Neumann architecture, in which program and data are fetched from the same memory using the same bus. Separating program and data buses further allows instructions to be sized differently than the 8-bit wide data word. Instruction opcodes are 14-bits wide, making it possible to have all single word instructions.
A 14-bit wide program memory access bus fetches a 14-bit instruction in a single cycle. A two-stage pipeline overlaps fetch and execution of instructions (Example 3-1). Consequently, most instructions execute in a single cycle (200 ns @ 20 MHz) except for program branches. All devices covered by this data sheet contain 4K x 14-bit program memory and 192 x 8-bit data memory.
ATmega169PA: The Segment Map Behind an On-Chip LCD Driver
Most microcontrollers drive a display through a controller chip. This one drives the glass directly: it generates the backplane waveforms, multiplexes the segments, and holds the pattern in registers that correspond one-to-one with physical connections.
That architecture moves the interesting content of the product into the firmware. What appears on the display is decided by which bits the code writes, and the mapping from a value to a pattern is a table — usually in flash, usually the largest constant structure in the image.
How the driver is organised
The display is driven in a matrix. Several common lines, called backplanes, are strobed in sequence, and each segment line is driven or not driven during each strobe. A character is therefore not a byte of pixels but a set of bits spread across the backplane phases.
Three consequences follow:
The pattern for a digit is not contiguous in memory. Its bits are distributed across the register set according to the multiplexing. The mapping is arbitrary. Which segment line connects to which part of the glass is a PCB decision, recorded nowhere except in the firmware’s table. Contrast is a register setting, not a data value, and it interacts with the supply voltage.
| Element | Where it lives | What it determines |
|---|---|---|
| Backplane count | Configuration register | Multiplex ratio |
| Segment allocation | Firmware table | Which bit lights which segment |
| Digit patterns | Firmware table | The shape of each character |
| Contrast | Register, sometimes fuse | Visibility across temperature |
Why the table is the valuable artefact
A display product’s specification is its display: which digits, which symbols, which annunciators. The code that does the measuring or the timing is comparatively generic; the table that turns a value into a visible pattern is specific to that product.
Recovering that table means recovering the display layout, which means a replacement device can render the same information without reverse-engineering the glass. On a product with custom icons — a battery symbol, a set of unit markers — the table is the only place that layout is written down.
Reading the table out of an image
Four steps:
- Locate the LCD configuration writes in initialisation. They identify the multiplex setting and the frame rate.
- Find the routine that writes the segment registers. It is usually called from the display update path.
- Follow its input: an index that comes from a lookup, which is the table.
- Extract the table and tabulate it by index against the known display layout.
Step 3 is the key. The table is indexed by something the application computes — a measurement, a counter, a state — and the index sequence tells you what the display is showing.
The PA revision and contrast
The picoPower revision changes the display driver’s bias and the contrast control. Firmware written for the earlier die may set a contrast value that is too low on the new one, producing a display that is readable indoors and not in sunlight.
That is a real and frequently reported field complaint, and it is a firmware constant rather than a hardware fault. The setting is in the code, and so is the story.
What the fuse byte adds
Parts with a display driver often have fuses that select the driver’s clock source and initial contrast. Those settings are outside the flash, they interact with the table above, and they are the reason a device can look blank when its firmware is perfect.
Reading them first is not optional on this part. A blank display with a valid image is a configuration problem until proven otherwise.
Reading order
- Signature, fuses, lock byte — including the display-related fuses.
- Array read, verified.
- Initialisation: display configuration, then framing.
- Display update path and its lookup table.
- Tabulate the segment map against the product’s visible layout.
Step 5 produces something a customer can check immediately, because the display is the product. That makes it the fastest possible confirmation that the analysis is on the right track.
Related notes
- ATmega169PV and display fuses — the configuration side of the same driver.
- ATmega169A and the binary image — what the table looks like in a raw file.
- ATmega644 and page buffers — flash mechanics shared with this part.
FAQ
Does this part need an external display controller? No. It drives the glass directly through its own pins.
Is the segment map standardised? No. It depends on how the glass is wired to the pins.
Why does the display look faint after a revision change? The contrast constant was written for the earlier die’s driver characteristics.
Can the display be blank with valid firmware? Yes, if the display fuses are wrong or the driver is not enabled.
Conclusion
An on-chip display driver pushes the product’s identity into its firmware tables. The segment map is the layout, the digit patterns are the typography, and the contrast constant is the readability — all of them recoverable, all of them absent from any schematic, and all of them invisible until the display configuration registers are read.
ATmega128V: The First Hundred Instructions on a Large Part
On a small part, initialisation is short: set the stack pointer, configure a port, start a timer. On a large one there is more to establish before the application can run, and the order in which it is established describes the hardware the firmware expects to find.
The first hundred instructions are therefore the highest-value region of the image, and they are readable without any understanding of the application that follows.
The sequence, and what each step proves
| Step | What it configures | What it proves |
|---|---|---|
| Stack pointer | Where the stack lives | How much RAM the build expects |
| Address extension | High byte for data above 64 KB | Whether large tables are used |
| Memory interface | Wait states, region boundaries | Whether external memory exists |
| Clock | Source and prescaler | The timing basis of everything after |
| Ports | Direction and initial state | The hardware interface |
| Peripherals | Timers, serial, interrupts | What the device talks to |
The third row is the one that answers a question no schematic reading can settle quickly: whether the board has external memory. A build that programs the interface registers is a build that expects it, and the wait-state values describe how fast it is.
Why the order is informative
Runtimes initialise in dependency order. Nothing that uses the stack comes before the stack pointer is set. Nothing that reads a table comes before the address extension is configured. Nothing that depends on time comes before the clock.
So the order is a partial specification of the firmware’s dependencies. If the serial port is initialised before the clock is configured, either the serial port uses an independent clock or the sequence is wrong — and a wrong sequence in a shipping product is worth knowing about.
What the stack pointer says
The value written to the stack pointer is an address in data space. Its position tells you how the linker laid out the build: stack at the top of RAM growing down is conventional, and the exact value reveals how much RAM the design assumes.
On a part with more RAM than a small sibling, a stack pointer set well above the low addresses means the build uses the space, which means there are buffers, which means there is something to buffer. That inference alone often identifies the product’s category.
Port configuration as an interface description
The port direction registers describe the hardware as well as any schematic:
- Pins set as outputs with an initial low state are drivers waiting to be activated.
- Pins set as inputs with pull-ups enabled are switch or open-collector inputs.
- Pins left as inputs without pull-ups are either unused or driven externally.
- Pins toggled immediately after configuration are indicators or handshake lines.
Reading that list against the product’s function usually produces a complete description of the interface before any application code is examined.
The low-voltage grade
V extends the supply range downward, which affects one thing in this region: the clock configuration. A part configured to run at full speed from a low supply is at the edge of its specification, and the prescaler setting is where that trade is recorded.
A build that divides the clock on a low-voltage part is a build that acknowledged the constraint. A build that does not is worth a second look, because it may have been validated at a rail the product does not actually provide.
Reading order
- Read fuses and lock byte before the array.
- Read the array, verified.
- Decode the reset vector; start reading at its target.
- Read the first hundred instructions in full, annotating each group.
- Use the annotated groups as the index for the rest of the analysis.
Step 5 is why this is worth doing first. Initialisation names the subsystems, and the subsystems are the chapters of everything that follows.
Related notes
- ATmega128V and the boundary register — the extension mechanism in detail.
- ATmega128PV and long-read drift — reading this much flash reliably.
- ATmega640 and external memory — the interface these registers configure.
FAQ
Is initialisation always in the same order? Broadly, because dependencies force it. Vendor start-up code establishes the pattern.
What if the stack pointer is set to the very top of RAM? That is conventional and says little; a value below the top suggests reserved space.
Can external memory be detected without the registers? Only by inspecting the board. The firmware tells you what it expects.
Does the clock setting have to come first? Before anything time-dependent, yes.
Conclusion
The reset path is a specification written by the firmware about its own hardware. Stack, address extension, memory interface, clock, ports, peripherals — six groups that name the chapters of the analysis and answer questions a schematic cannot. Reading them first is the highest return per instruction in the entire image.
ATmega128V: The Register That Tells You Where the Boundary Is
A sixteen-bit pointer reaches sixty-four kilobytes. With a flash array larger than that, reading a constant in the upper half requires an extra byte of address, and on this architecture that byte lives in a dedicated register which the code must set before each such access.
The register is therefore a marker. Every write to it is a statement that the next operation addresses something above the line, and a sequence of such writes draws the image’s structure in a way that no disassembly listing makes obvious.
How the access works
Three instructions, in order, for any constant above the boundary:
- Load the high byte into the extended register.
- Load the low word into a register pair.
- Perform the load from program space.
For code below the boundary, step one does not appear. That asymmetry is the marker: a region full of extended-register writes is code that reads data from the upper half, and a region without them is code that does not.
| Pattern | Meaning |
|---|---|
| Extended register written before every table read | Table lives above 64 KB |
| Written once at start-up, never again | Pointer fixed for a single table |
| Written inside a loop with a changing value | Stride over a large structure |
| Never written | All data below the line |
What this gives an analyst
Three things, none available from the file layout alone:
The boundary location. The first address where the pattern appears is where the upper half begins to be used, which is usually where the build ran out of room below.
Table locations. A fixed pointer set at start-up means a single large table, and its address follows from the register and low word values.
Structure of large data. A varying high byte inside a loop means a stride, and the stride is often the size of a record — which identifies what the data is.
Why this matters more than the file format
A hex file records addresses, so the boundary is already visible in the file. A disassembly is different: it presents instructions in address order and a table read looks like any other instruction except for the register load before it.
Reading the file tells you where things are. Reading the register writes tells you what the code thinks is there, which is the more useful of the two when the layout is unfamiliar.
The low-voltage grade and a long read
A 128 KB array takes time to read, and at the bottom of the V range the margin narrows. Two habits make the difference:
- Read in passes, verifying each page against itself before moving on.
- Re-read the first page at the end and compare with the first pass.
The second is the only check that covers the whole session rather than one page. A file that is correct for the first sixty kilobytes and wrong for the second is a real outcome on a marginal setup, and it produces a plausible-looking image.
Reading order
- Signature, fuses, lock byte.
- Array read, verified page by page.
- Decode the vector table and the reset target.
- Locate extended-register writes and record the addresses they precede.
- Interpret tables from the pointer values recorded in step 4.
Step 5 is where the marker becomes a location. The register and the low word together give an address, and that address is where the data actually is — which is frequently a step the file layout alone cannot justify.
Related notes
- ATmega128P and binary layout — the same boundary in a file with no addresses.
- ATmega128PV and long reads — the electrical side of a 128 KB pass.
- ATmega128A and EEPROM wear — the other array on this die.
FAQ
Does every access above 64 KB need the extra register? Yes, for constant data read from program space. Code execution uses the program counter, which is already wide.
Can the register be left set across calls? It can, and firmware often does, which makes the pattern less regular than a rule would suggest.
Is the boundary in the same place in every build? No. It appears wherever the linker placed the first large table.
Does a smaller part in the family have this register? No. It exists because the array is large.
Conclusion
The extended address register is a structural marker that a listing hides. Every write to it points at something above the boundary, and reading those writes before reading the code turns an unfamiliar image into a map of where its data lives — which is exactly the information a file format cannot supply.
ATmega128P: Binary Layout Past the Sixty-Four Kilobyte Line
A binary file is a sequence of bytes with an implied start address and nothing else. For an image smaller than sixty-four kilobytes that is sufficient, because a single sixteen-bit address covers it. Past that point the file has a region the format cannot describe, and every tool resolves it by convention.
The conventions differ, and a file produced under one and read under another is not obviously wrong — it is wrong in a way that only shows up when the upper half is examined.
What the line means
Sixty-four kilobytes is where a sixteen-bit offset wraps. A file that describes more than that must either record addresses (as hex does) or append the excess at a known offset with an agreed meaning.
Three arrangements are common:
| Arrangement | Upper half position | Risk |
|---|---|---|
| Contiguous append | immediately after 64 KB of bytes | misread if the flash is smaller than the file |
| Fixed offset block | at a round boundary well above | misinterpreted as blank padding |
| Separate file | not in this file at all | the upper half silently missing |
The third is the dangerous one, because the resulting file looks complete at sixty-four kilobytes and is half a program.
Why a truncated image can still run
Here is the uncomfortable part: a device whose upper half was not captured may still disassemble and even make sense, because the lower half contains the vectors, the initialisation and the main loop. The functions that live in the upper half appear as unresolved call targets, which looks like missing library code rather than a missing region.
That misreading persists until someone tries to follow a call to an address beyond sixty-four kilobytes and finds the file ends at that point.
The check that reveals it
Two questions, both cheap:
What is the file length? Compare it against the array size reported by the signature. A file substantially shorter than the die’s flash is suspect.
Does the code call addresses beyond the file? Decode a few calls and note their targets. A target that exceeds the file length is a reference to the missing region.
Both are arithmetic and neither requires understanding the program. Doing them first prevents an afternoon of analysis on half an image.
Reading a full 128 KB image
With both halves present, three features need care:
Address arithmetic in the code. The upper half can only be reached through an instruction that carries a high byte, so the code contains visible register loads before jumps and table accesses. Those loads are the map of where the image crosses the line.
Constant tables. Tables that straddle the line are the most fragile part of a relocation, because a corrupted high byte turns a valid pointer into an invalid one without changing the low bytes.
Vector table. Unchanged, and still the anchor. Its targets are the only fixed reference in either half.
The revision and the low-voltage grade
Neither suffix changes the layout. The P marks the picoPower die and the V the extended supply range; both affect the electrical envelope of a read of this size.
A 128 KB read takes long enough that drift matters. Reading in passes with per-page verification, and re-reading the first page at the end, is the practical guard against a file that is correct at the start and wrong at the end.
Related notes
- ATmega128A and EEPROM wear — the other array on this die.
- ATmega1280PV and the three-byte counter — why the counter widens at this size.
- ATmega640PV and binary offsets — the same format below the line.
FAQ
Is a binary ever a complete description of a 128 KB image? Only with a stated convention for the upper half and a file length that matches.
How can I tell if the upper half is missing? By file length and by call targets that exceed it.
Does a hex file avoid this problem? Yes. It records addresses explicitly, so the crossing is visible.
Why keep using binary at all? It is smaller and it is what some tools require. The convention just has to be recorded.
Conclusion
The sixty-four kilobyte line is where a binary stops describing itself. Length and call targets are the two checks that reveal a truncated image, and they cost nothing. Past the line, the work is arithmetic on high bytes — and the vector table remains the only anchor that does not move.
ATmega88PV: The ISP Clock Has a Speed Limit That Follows the Supply
Most interface problems announce themselves. A cable is open, a device does not respond, a programmer reports a timeout. The serial programming interface is different: when it is driven slightly too fast it keeps working, and what it returns is data that is subtly wrong.
Subtly wrong data is worse than no data, because it passes the checks that engineers normally apply. Per-byte parity, file length, and even a whole-image checksum can all agree between two reads taken at the same wrong speed, because both reads made the same mistake.
Why the interface has a limit
Programming happens synchronously: the programmer drives a clock, and the target samples command and data bits on its edges. Internally the target has to synchronise that incoming clock to its own system clock, and synchronisation needs edges to align against. If the incoming clock is faster than a fraction of the system clock, the sampling point falls unpredictably relative to the bit cell.
The datasheet states the relationship as a ratio rather than a frequency, which is the part people miss. The maximum programming clock is a fraction of the target’s own clock — of the order of a quarter, with a wider margin strongly advisable — so the actual number of kilohertz you may use depends entirely on how fast the target is running.
| Target clock | Practical programming clock | Comment |
|---|---|---|
| 8 MHz internal, undivided | A few hundred kHz comfortably | The common case on a bench |
| 1 MHz (divided by eight) | Below a hundred kHz | Factory default on many parts |
| 128 kHz internal | A few kHz | Slow, and the read takes a while |
| External crystal at 16 MHz | Upper hundreds of kHz | Fast, but only if the crystal is present |
The low-voltage part makes it worse
This variant is specified to run from a supply well below the usual five volts, and at low supply the maximum operating frequency falls. A part running at 1.8 volts from an internal oscillator is not just slower in a nominal sense; it is limited by physics, and the programming clock limit falls with it.
So the same programmer setting that reads a five-volt unit cleanly will produce shifted data on a low-voltage unit, and the difference is not a fault in either device. It is the interface being asked to run faster than the target can follow.
The practical response is to start slow and only increase speed when there is a reason. Reading eight kilobytes at ten kilohertz takes a few seconds longer than at two hundred, which is not a meaningful cost on a job that will take an afternoon.
What shifted data looks like
Three signatures, in order of how often they appear.
Every byte off by a factor of two or a factor of sixteen. A bit shift produces values that are systematically related rather than random. A dump full of 0x02, 0x04, 0x08, 0x10 where instructions should be is a shift, not a corrupt array.
A file that disassembles into plausible but wrong instructions. Single-bit shifts of AVR opcodes frequently land on other valid opcodes, so the output reads as code and does something different. This is the failure that wastes the most time, because nothing looks broken.
A read that succeeds and a verify that fails. The programmer writes a page, reads it back through the same marginal link, and compares against data that went through the same distortion — occasionally it matches, occasionally it does not, and the intermittency is blamed on the chip.
Diagnosing it in one step
Read the same address range at two different clock rates and compare. If the two reads differ, the link is not trustworthy and the slower of the two is the candidate truth. That test takes a minute and eliminates the entire class of error.
If both reads agree, it does not prove correctness — both could be equally wrong. The confirmation is a second reference: read a known region, such as the signature row or a page you have already recovered from another unit, and check that it decodes as expected.
Other constraints on the same link
The clock rate is the one that produces silent corruption, but three others produce loud failures and are worth checking in the same session.
Supply voltage within the programming range. A part powered from a rail that sags during a page write will fail intermittently, and the failure will be attributed to the part.
Ground return. A long ground lead shared with a switching supply injects noise into the sampling. Short, direct, and to the same plane as the part.
Target clock present. If the target is configured for a crystal that is not fitted, the interface may respond to a signature read and then fail on anything that needs real timing.
What to record
The delivery should state the clock rate that worked and the supply voltage it was read at, because the same device or its sibling will be read again. A note that says “read at 50 kHz, 3.3 V, needed a 20 ms delay after power-on” is worth more than a page of narrative, and it takes one line.
Related reading
- ATmega88A and the clock fuse — why the target clock may not be what you assume.
- ATmega88PA and the bootloader surface — a route that does not depend on this timing at all.
- ATmega324V and the cost of the low-voltage grade — the same supply constraint in a larger part.
FAQ
Does a slower clock risk anything? No. Slower is always safe on this interface, up to the point where the programmer times out. Set the timeout generously rather than the clock high.
Can a fast link damage the device? Not electrically. It produces wrong data, not a broken part.
Why does the same setting work on some units and not others? Because the fuse settings differ, and with them the target clock. Nominal part numbers do not imply identical configuration.
Is a checksum between two reads enough? No. Two reads at the same wrong speed agree with each other. Compare across speeds or against a reference region.
Conclusion
The programming interface has a speed limit that is a ratio, not a number, so it moves with the target’s configuration and supply. Start slow, confirm across two rates, and write down the conditions — the data you get at the wrong speed is the kind that passes every check and is still wrong.
ATmega88PA: The Bootloader Doesn’t Care About the Lock Bits
Lock bits and bootloaders protect against different things, and confusing the two leads to a plan that spends a day on a protocol and discovers at the end that it cannot do what was wanted. The lock bits exist to stop an external programmer from reading the array. The bootloader exists to let the product update itself. Neither has anything to do with the other.
Which is why a device whose array is unreadable may still be perfectly willing to accept a new application — and why that convenience is not the same as a recovery.
Who writes and who reads
The lock bits on this family come in two groups. One group protects the boot section, the other protects the application section, and each group controls whether the self-programming instruction is allowed to modify that region from the other side. A third pair controls whether the array can be read at all through the programming interface.
A bootloader running in the boot section is subject to the first two groups and not to the third. It can write the application, because that is its function. It cannot read memory out of the device unless it was written to do so, because reading memory is not what a firmware updater needs.
| Operation | External programmer, unlocked | External programmer, locked | Bootloader, typical |
|---|---|---|---|
| Read flash | Yes | No | Only if implemented |
| Erase application | Yes | No | Yes, as part of update |
| Write application | Yes | No | Yes |
| Modify boot section | Yes | No | Only if boot section unprotected |
The third column is the one people get wrong. Most bootloaders implement four commands: identify, erase, write, and jump to application. None of them returns the existing program.
The entry conditions
A bootloader that is never entered is not a door. Entry depends on configuration and on the protocol.
Reset vectoring into the boot section. If the boot reset fuse is programmed, every reset starts in the bootloader, which then decides whether to stay or hand over. If the fuse is not programmed, the bootloader only runs if the application jumps to it, which is a deliberate design and usually triggered by a command or a button.
A time window. Bootloaders commonly wait a fraction of a second for a host to say something before starting the application. A device that is powered continuously never shows this window; a device that is power-cycled while a host is listening does.
A pin state. Some designs sample a pin during the window and stay resident if it is held. That is a hardware condition you can impose.
A magic sequence. Others require a specific byte sequence at a specific baud rate, which is undocumented but discoverable by listening to a working unit’s update.
Knowing which of these applies is a five-minute question with a scope and a serial adapter, and it determines whether the route exists at all.
What a bootloader is genuinely good for
Two legitimate uses, and both are worth having in the toolkit.
Restoring a device whose application is corrupt. If the flash holds a partial image from a failed update, a bootloader can take a known-good image and make the device work again. That is repair rather than recovery, and it is often what the customer actually needs.
Reading the bootloader’s own code. The boot section is usually not protected by the application-side lock bits, and its protocol is a written specification of how the device is updated. That tells you what the vendor’s production process looked like, which is useful context even when no read is possible.
What it cannot do, and the risk of trying
The dangerous move is using a bootloader erase to “see what happens”. It clears the application, which is exactly the evidence the recovery was meant to preserve, and it does not reveal anything the programmer could not have told you in one command.
If the bootloader does implement a read command, that changes the plan entirely and it is worth testing before any write. The test is cheap: ask for the first page and see whether the response is data or an error. Do it before the erase, never after.
The protection bits that close this door
Two configurations remove the route. If the boot section’s own lock bits are programmed, the self-programming path is restricted and updates cannot be applied from the application side — which is a common hardening step and makes the device effectively non-updatable. And if the general lock mode that disables self-programming is set, the bootloader cannot write anything at all, though it may still run.
The consequence is that a hardened device is quieter than an unhardened one: no update window, no response on the port, nothing to negotiate with. That absence is itself a finding, because it tells you the production process was deliberate.
Recording what was found
When a bootloader is present, the useful deliverable is a short description: where the boot section begins, how entry is triggered, what the protocol is, and what the update window looks like in time. That document lets the customer’s own production line program replacements without reverse engineering the process again, and it costs an hour to write.
Related reading
- ATmega48P and the family member without a boot section — the same argument from the other direction.
- ATmega88A and the clock fuse — why a device with a bootloader might not start at all.
- ATmega164 and the bits that guard the boot section — the protection mechanics in detail.
FAQ
Can a locked device be read through its bootloader? Only if the bootloader implements a read command, which is uncommon. Most return an error or nothing.
Does entering the bootloader require the application to cooperate? No, if the boot reset fuse is programmed. The part starts there on every reset.
Is the boot section readable when the application is locked? Often yes, because the protection groups are separate. Check before assuming.
Is it safe to let a bootloader erase the device? Only after the image is secured. The erase removes the thing you were trying to preserve.
Conclusion
A bootloader is a way to replace, not a way to read, and mixing those up wastes the one resource that cannot be recovered. Test for a read command first, treat erase as destructive, and document the entry conditions — the door is real, it just opens onto a different room than most people expect.
ATmega88A: The Fuse That Waits for a Crystal That Isn’t There
The failure looks like a dead microcontroller and it is not one. The part is powered, the supply is clean, the programming interface responds, the array reads perfectly — and the product does nothing. Pin states are static, no activity on any bus, no current beyond the quiescent figure.
Nine times out of ten the clock configuration is asking for something the board does not have.
How the clock is chosen
The low fuse byte contains a field that selects between the internal calibrated oscillator, an external crystal or resonator, and a low-frequency internal source. The same byte contains a field that sets how long the part waits after power-on before it starts executing, and a bit that divides the resulting clock by eight.
Those three settings interact. A part configured for an external crystal with a short startup delay will start reliably on a warm bench and intermittently in a cold cabinet, because the crystal needs more time to reach stable amplitude than the fuse allows. A part configured for the internal oscillator at eight megahertz divided by eight runs, and runs eight times slower than the firmware expects, which produces a device that works but communicates at the wrong baud rate.
| Selection group | Clock source | Typical failure when wrong |
|---|---|---|
| External crystal or resonator | Off-chip component | Part never starts; no clock at all |
| Low-power crystal mode | Off-chip, driven gently | Starts, then stalls or drifts |
| Internal low-frequency | On-chip, 128 kHz | Runs, hundreds of times too slow |
| Internal calibrated RC | On-chip, several frequencies | Runs at the wrong rate, timing constants off |
| Divided by eight bit | Prescaler on the above | Everything a factor of eight slow |
The three symptoms and what each means
Nothing at all happens. No pin activity, no current change beyond the quiescent draw. The clock source is external and absent, or the part is being held in reset by something else. Distinguish by reading the clock enable output if the fuse that routes the clock to a pin is available, or by watching for any activity on any pin with a scope over a full second.
The part starts, then stops. A crystal that begins oscillating and then fails, or a brown-out that trips when the application turns on a load. This is a power or startup-delay problem rather than a source problem.
The part works but everything is slow. Baud rates wrong, delays too long by a fixed factor, watchdog timeouts arriving early. That factor is the diagnostic: eight is the prescaler, and a different constant is the wrong oscillator frequency selected.
Reading it out of the code
When the fuses cannot be read, the firmware supplies the answer. Two patterns are decisive.
Baud rate registers. The USART divisor is a pair of registers computed from the clock frequency and the desired rate. If the firmware writes a divisor consistent with 8 MHz for a nominal 9600 baud, the clock is 8 MHz. If the divisor is eight times larger than that, the clock is 1 MHz and the prescaler is active.
Timer prescaler and reload values. A timer reloaded with a specific count to produce a millisecond tick encodes the clock frequency directly, because the arithmetic is forced by the requirement. The same applies to software delay loops, which are usually a nested counter sized against a known clock.
Both of these are cross-checks on the fuse decode, and they disagree often enough to be worth doing every time. When they disagree, trust the code: the firmware was written against the clock the designer had in mind, and the fuse is what somebody programmed later.
The diagnostic that settles it
If the fuse that routes the system clock to an output pin is available, and if that pin is not otherwise used, the measurement is direct: enable it, then measure the pin. The frequency you see is the frequency the core is running at, including the prescaler. There is no ambiguity and no inference.
On a part in a product, that requires changing a fuse, which requires deciding whether configuration changes are acceptable yet. Doing it on a replacement part is free and answers whether the design expects an external crystal at all.
When the board really has lost its crystal
Physical damage to a crystal or a resonator is common in equipment that has been dropped, and the failure is invisible: the component is still soldered, it just does not oscillate. A scope on the crystal pins shows whether the drive circuit is attempting to start it.
If the crystal is dead and the fuses require it, the part can be reconfigured to use the internal oscillator — at the cost of accuracy. The internal RC is calibrated to a few percent, which is enough for a keypad and not enough for a serial protocol at high baud or for anything that measures time. That trade-off should be stated in the delivery, because the product may work on the bench and fail with a customer’s equipment.
Restoring the original arrangement
The right end state is the one the product shipped with. If the original had a crystal and the crystal is good, configure for the crystal and set a startup delay that matches the component’s specification rather than the shortest available value. If the original used the internal oscillator, record which frequency and whether the prescaler was active, because both are part of the design and neither is visible in the array.
Related reading
- ATmega88PA and the bootloader as a way in — the same part with a different route available.
- ATmega88PV and the ISP clock limit — the other timing constraint on this family.
- ATmega324V and what the low-voltage grade costs — voltage and clock interacting.
FAQ
Can a part configured for a missing crystal be recovered? The array reads normally. Only the ability to run is affected, and it is fixed by changing the fuse or fitting the component.
Does the divided-by-eight bit affect the programming interface? It affects the core clock, which affects how the interface must be timed. A slow clock needs a slow programmer, not a faster one.
Is the internal oscillator accurate enough for serial communication? At moderate baud rates with a calibration value from the signature row, usually yes. At the top of the range, no.
Why does the same firmware work on one unit and not another? Different fuse values from the production programmer. It is the most common cause of unit-to-unit inconsistency in this family.
Conclusion
A silent part is more often waiting than broken. Read the clock field, cross-check it against the baud divisor and the timer reload in the code, and confirm with the clock output pin — three measurements that replace an afternoon of guessing.
ATmega48PV: Four Parts in One Socket
A product designed around this family has a footprint that accepts four devices: four kilobytes, eight, sixteen, thirty-two. They share pinout, package, and peripheral set, and the only thing that changes between them is how much flash is inside.
That compatibility is a gift to manufacturers and a hazard to anyone reading a board, because the part number is frequently not printed anywhere useful, the schematic says one thing, and the bill of materials says another. The device itself knows, and it will tell you in three bytes.
The three bytes
Every AVR responds to a signature read with three bytes. The first identifies the vendor, the second the family, and the third the specific device within it. On this family the third byte is the one that matters and it is the one that is never guessable from the board.
| Signature role | What it tells you | Why it matters here |
|---|---|---|
| Byte 0 | Vendor | Confirms the part is what the silkscreen suggests |
| Byte 1 | Family group | Places the device in the right datasheet |
| Byte 2 | Device | Distinguishes four parts that look identical |
Read it before anything else. It takes one command, it requires no special state, and it removes the most expensive class of mistake in this work: doing a full extraction and analysis against the wrong device.
Why the wrong identification is expensive
Three specific failures follow from assuming the wrong part.
The image is the wrong length. A read that stops at four kilobytes on a device with thirty-two produces a file that looks complete, disassembles cleanly, and is missing eighty-seven percent of the program. Nothing about the output flags the truncation.
The boot section assumption is wrong. The smallest member of the family has no boot section at all. Reading a device assumed to be larger and finding no bootloader looks like a firmware design choice rather than a hardware fact.
The vector table is misaligned. Different members implement different numbers of interrupt sources, and the table’s size differs accordingly. If the code analysis assumes the larger part, the later vectors are attributed to sources that do not exist.
Each of these produces a confident, wrong deliverable, which is worse than an obvious failure.
When the fitted part is not the specified part
A pattern worth knowing about: during a component shortage, a manufacturer substitutes a larger device for a smaller one because it is what was available. The firmware is identical, the board is identical, and the bill of materials is now wrong for one production batch.
The consequence for recovery is that the image from that unit has trailing erased space, or a different signature than expected, and the customer’s own records disagree. When the signature is unexpected, asking the question is more productive than assuming an error. A batch substitution explains a lot of anomalies that otherwise look like tampering.
The reverse also happens: a smaller device fitted where a larger was specified. That is a real problem for the product, because code that fits in sixteen kilobytes will not fit in eight, and the failure mode is a device that works until a firmware update.
What the identification does not tell you
The signature identifies the device, not its configuration and not its contents. Two units of the same part number can have entirely different firmware, different fuses, and different protection states.
So the signature is the first of four reads, not a substitute for the others:
- Signature — which device.
- Fuses — how it is configured.
- Lock bits — whether the array can be read.
- Array and EEPROM — what is in it.
That order is deliberate. Each read informs the interpretation of the next, and doing them in the wrong order means reinterpreting earlier conclusions.
The practical use of knowing the family
Once the family is established, several assumptions become safe and save time. The peripheral set is shared, so a routine that configures a timer in one member is recognisable in another. The register addresses are the same, so a disassembly annotated for one part is largely valid for its siblings. And a recovered image from a smaller member will run on a larger one, provided the fuses are sensible — larger to smaller is the direction that does not work.
That last point has a practical application beyond recovery: a product whose original part is obsolete can often be kept alive by fitting the next size up, with the same image and the same behaviour. Confirming that the image does not depend on the exact flash size is a quick check in the startup code and the vector table.
Related reading
- ATmega48P and the part with no boot section — what the smallest member cannot do.
- ATmega88A and the fuse that waits for a crystal — the next size up, and its clock configuration.
- ATmega168PV and the calibration byte — another value that must be read rather than assumed.
FAQ
Can the signature be read from a locked device? Yes. The signature is not protected by the lock bits on this family.
Is the signature readable without entering programming mode? It requires the programming interface, but not a successful flash read, so it works when the array does not.
Do the P, PA and PV variants share signatures? They are related but not always identical. Confirm against the specific orderable code, since revision differences appear in the third byte.
What if the signature does not match any known part? Then the read itself is suspect — check the clock, the wiring, and the supply before concluding the device is unusual.
Conclusion
Four parts share a socket, and only one of them is actually fitted. Three bytes answer the question in a second, and reading them first is the cheapest insurance in the whole procedure.
ATmega48P: The Part With No Boot Section
Four kilobytes of flash, half a kilobyte of SRAM, thirteen general-purpose I/O. The ATmega48P is the entry point of a family that spans from here to parts eight times its size, and the differences are not only quantitative. The smallest member lacks a structural feature that every larger sibling has, and that absence changes what can be done to the device from outside.
What is missing, exactly
Larger parts in the family divide the flash into an application section and a boot section, with the split point set by fuses. The boot section has two properties the application section does not: it can be protected independently, and it is the only place from which the self-programming instruction is allowed to execute.
Without a boot section there is nowhere for that instruction to legitimately run, so the device has no supported way to modify its own flash. No bootloader. No serial update protocol. No “hold this pin during reset and the vendor’s tool will talk to it” behaviour.
That single absence cascades:
| Capability | Larger family members | ATmega48P |
|---|---|---|
| Bootloader | Yes, size configurable | Not available |
| Field firmware update over UART | Yes | Not through the device |
| Read-while-write | Yes | Not available |
| Independent boot protection | Yes | Not applicable |
| Programming routes | ISP, plus serial bootloader | ISP only |
What that means for a locked device
On a part with a bootloader, a locked device is often still approachable, because the bootloader’s own protocol does not necessarily check the lock bits. Here there is no such channel. When the lock bits are set on this part, the practical routes reduce to the programming interface — and if that is also closed, to the silicon.
The reduction is honest and it is worth communicating early. A customer who has read about bootloader-based recovery on the internet will ask for it, and the correct answer is that this part does not have the hardware for it.
What the small size gives back
Four kilobytes is a strange advantage and it is a real one. An image of this size can be read, disassembled, and understood end to end. Not sampled, not triaged, not “the interesting handler is somewhere in the middle” — completely.
That changes the character of the work. There is no need to build a prioritised reading list, no need to decide which library function to skip. A thousand instructions is an afternoon, and at the end of it you know what every byte of the device does.
It also changes the quality of the delivery. On a large part, “here is the image and the main state machine” is a reasonable outcome. On this part, “here is the image, and here is what every function does” is achievable, and it is what the customer is really buying.
The constraints that show up in the code
Working inside four kilobytes leaves marks, and those marks are useful when reading.
No floating point unless it is unavoidable. A float library consumes a large fraction of the space, so arithmetic is integer or fixed point, and that shows up as shift-and-multiply sequences.
Functions are inlined or shared aggressively. A routine that appears in several places is usually a macro, and the same code appearing twice is evidence of a copy made by hand.
Strings are short and often packed. Lookup tables are byte-wide and indexed by a computed offset rather than stored as structures.
Recursion is absent. With a small stack, recursion is a luxury, and its absence makes the call graph a tree rather than a graph — which makes reading it considerably easier.
The commercial reality
These parts are inexpensive and they are usually socketed or on a small board. That produces a specific customer conversation: the replacement hardware is trivial to obtain, and the value is entirely in the firmware, which is the thing that cannot be bought.
Which is why the deliverable for this device should lean on analysis rather than on the binary alone. The binary is four kilobytes; anyone with the part can produce another one. The document that says what it does, what each of the thirteen pins is for, and how the timing works is the part that has no substitute.
Handling the replacement
Two practical points. First, the part is pin-compatible with larger members of the family in the same package, so a replacement may be a bigger device — and a bigger device will have a boot section that the original code does not use. That does not break anything, but the fuses must not be set to expect a bootloader that is not there.
Second, verify the replacement in the product rather than on the bench. At this size the firmware’s behaviour depends on the timing of the thing it controls, and a blink test on a breadboard proves very little.
Related reading
- ATmega48PV and four parts in one socket — identification when the package is shared.
- ATmega88PA and the bootloader as a door — what the larger sibling offers that this part cannot.
- ATmega261A and two kilobytes with no room to hide — the same argument at an even smaller size.
FAQ
Can a bootloader be added to this part? Not in the supported sense. Without a boot section there is nowhere for the self-programming instruction to run from.
Does the absence of a boot section affect reading? No. The array is read the same way. It affects the routes available when the array cannot be read.
Is the code really small enough to read completely? For a four-kilobyte image, yes. It is the size at which complete comprehension is a realistic goal.
Are the fuses the same as on larger parts? Similar but not identical, since the boot section settings do not exist. Use the datasheet for the exact orderable code rather than a sibling’s table.
Conclusion
A missing feature is information. On this part it removes the update channel, removes the bootloader route, and leaves a device small enough to understand entirely — which is, for once, an advantage that compensates for the constraint.