Recovery MCU PIC12CE673 Flash: Sixteen Bytes That Were Never Secret
There is a part of this device that protection does not cover, because it was not designed to be covered. The sixteen bytes of data EEPROM are reachable through two pins by an external master, independent of whether the processor is running and independent of the code protection state. That is a deliberate feature of the CE family, and it divides the device’s content into two classes that need to be treated differently.
The PIC12CE673 is an eight-pin OTP part with a thousand words of program memory, sixteen bytes of data EEPROM, and a small analogue front end. It was designed for products that need a few bytes of non-volatile data without an external memory device: calibration constants, a serial number, a set of limits, a simple pairing value.
The two regions
| Region | Access | Protection applies | Who can read it |
|---|---|---|---|
| program array | programming interface | yes | an authorised programmer |
| data EEPROM | two-wire interface from outside | no, by design | anyone with a bus master and power |
The second row is not an oversight. The EEPROM exists so that a production fixture or a service tool can read and write the unit-specific values without entering programming mode, and that convenience requires an external interface.
The consequence is a security model that most designs of this era did not articulate: the sixteen bytes are public. Anything stored there should be assumed known to anyone who can reach the pins.
What gets stored there, and what should not
| Content | Appropriate | Why |
|---|---|---|
| calibration offsets | yes | useless without the product |
| serial number | yes | identity, not a secret |
| operating limits | yes | configuration, not a secret |
| a pairing key | risky | readable by anyone with a bus master |
| a customer password | no | it will be extracted in minutes |
| a rolling counter | yes, with care | readable, but still useful as state |
The fifth row is where products get into trouble. A design that stores a user password in this array has a password that can be read out with two wires, and the only thing protecting it is that nobody has bothered. This is worth saying plainly to a customer who is recovering a design in order to continue manufacturing it: the security property they believe they have may not exist.
The recovery advantage
From the other side, the same feature is a gift. On a device whose processor no longer runs, the EEPROM may still be readable, because the interface logic does not depend on the core executing code.
Three conditions make the attempt worthwhile. The device must be powered within its operating range from an external supply. The rest of the board must be isolated so that the product’s own circuits do not drive the two pins. And the access must be slow enough for the device to respond — a two-wire interface at a conservative clock rate is more reliable than a fast one on a part of this age.
If it works, the result is sixteen bytes and proof that at least part of the die is alive, which changes the assessment of the program array: a die that answers on the EEPROM interface is a die worth reading, not a dead part.
What the program array contributes
The program array on this part is a thousand words, which is small enough that the reading is quick and the analysis is thorough. Two features of the code are worth extracting specifically because they explain the EEPROM.
The first is the routine that reads a value from the EEPROM into RAM. Its address constants identify which of the sixteen bytes hold what. The second is the routine that writes, which on a production unit is often gated by a flag so that it runs once.
| Code feature | What it establishes |
|---|---|
| EEPROM read routine | which slots are used, and their order |
| write gating | whether the values are written at production or in service |
| bounds checks | the valid range of each parameter |
| checksum over the array | whether corruption is detected at start-up |
The fourth row explains a common failure after a reconstruction: a device with a blank EEPROM that runs its check, finds a mismatch, and refuses to operate. The program is right and the data is missing.
A refusal that is not a failure
If the external interface does not respond, that is not evidence that the EEPROM is empty. The interface may be disabled by the product’s own wiring, the die’s interface logic may be damaged while the array is intact, or the supply may be outside the range the part requires.
The way to distinguish is to attempt the read with the device removed from the board, in a socket, with a known supply. That single step converts an ambiguous result into a definite one.
Delivering both regions with their status
The program image with the word convention, the configuration decoded, and the sixteen bytes presented as raw data with their addresses and, where the code establishes it, their roles.
Specific to this part, the delivery should state how the EEPROM was obtained — external interface, through the processor, or from the die — because a customer assessing the reliability of a reconstruction needs to know whether the values came from the device or from a pattern.
Where the sibling part with half the program memory has the same array and a different failure profile, PIC12CE518 binary recovery covers reconstruction. Where the same sixteen bytes are discussed from the design side, PIC12CE674 software follows the verification. And where an eight-pin OTP part has no such array at all, PIC12C509A binary covers that case.
The short version
Sixteen bytes on a two-wire bus, outside the protection model by design. Try the external read first on a failed unit, do not assume a non-response means empty, and tell the customer that anything stored there was never a secret.
Recover Microcontroller ATmega461PA Archive
Recover Microcontroller ATmega461PA Archive from locked flash memory and readout the atmega461pa mcu program, rewrite it to new MCU atmega461pa for cloning;

When the SPI is enabled, the data direction of the MOSI, MISO, SCK, and SS pins is overridden according to Table 93. For more details on automatic port overrides.
The following code examples show how to initialize the SPI as a Master and how to perform a simple transmission. DDR_SPI in the examples must be replaced by the actual Data Direction Register controlling the SPI pins.
DD_MOSI, DD_MISO and DD_SCK must be replaced by the actual data direction bits for these pins. E.g. if MOSI is placed on pin PB5, replace DD_MOSI with DDB5 and DDR_SPI with DDRB. When the SPI is configured as a Slave, the Slave Select (SS) pin is always input. When SS is held low, the SPI is activated, and MISO becomes an output if configured so by the user after Reverse engineering attiny4313 Microcontroller code.
All other pins are inputs. When SS is driven high, all pins are inputs, and the SPI is passive, which means that it will not receive incoming data. Note that the SPI logic will be reset once the SS pin is driven high. The SS pin is useful for packet/byte synchronization to keep the slave bit counter synchronous with the master clock generator. When the SS pin is driven high, the SPI slave will immediately reset the send and receive logic, and drop any partially received data in the Shift Register.
When the SPI is configured as a Master (MSTR in SPCR is set), the user can determine the direction of the SS pin. If SS is configured as an output, the pin is a general output pin which does not affect the SPI system. Typically, the pin will be driving the SS pin of the SPI Slave.
If SS is configured as an input, it must be held high to ensure Master SPI operation. If the SS pin is driven low by peripheral circuitry when the SPI is configured as a Master with the SS pin defined as an input, the SPI system interprets this as another master selecting the SPI as a slave and starting to send data to it. To avoid bus contention, the SPI system takes the following actions if Recover attiny2313a Microcontroller heximal:
The MSTR bit in SPCR is cleared and the SPI system becomes a Slave. As a result of the SPI becoming a Slave, the MOSI and SCK pins become inputs. The SPIF Flag in SPSR is set, and if the SPI interrupt is enabled, and the I-bit in SREG is set, the interrupt routine will be executed.
Thus, when interrupt-driven SPI transmission is used in Master mode, and there exists a possibility that SS is driven low, the interrupt should always check that the MSTR bit is still set. If the MSTR bit has been cleared by a slave select, it must be set by the user to re-enable SPI Master mode.
Reverse MCU ATmega461PV Binary
Reverse MCU ATmega461PV and readout microcontroller atmega461pv secured Binary, crack mcu protective system and using focus ion beam to cut off the security fuse bit;

The interconnection between Master and Slave CPUs with SPI is shown in Figure 80. The system consists of two shift Registers, and a Master clock generator. Th e SPI Master initiates the communication cycle when pulling low the Slave Select SS pin of the desired Slave.
Master and Slave prepare the data to be sent in their respective shift Registers, and the Master generates the required clock pulses on the SCK line to interchange data if break atmega64pa MCU binary.
Data is always shifted from Master to Slave on the Master Out – Slave In, MOSI, line, and from Slave to Master on the Master In – Slave Out, MISO, line. After each data packet, the Master will synchronize the Slave by pulling high the Slave Select, SS, line.
When configured as a Master, the SPI interface has no automatic control of the SS line. This must be handled by user software before communication can start. When this is done, writing a byte to the SPI Data Register starts the SPI clock generator, and the hardware shifts the eight bits into the Slave. After shifting one byte, the SPI clock generator stops, setting the end of Transmission Flag (SPIF) after break atmega128a MCU firmware.
If the SPI Interrupt Enable bit (SPIE) in the SPCR Register is set, an interrupt is requested. The Master may continue to shift the next byte by writing it into SPDR, or signal the end of packet by pulling high the Slave Select, SS line. The last incoming byte will be kept in the Buffer Register for later use. When configured as a Slave, the SPI interface will remain sleeping with MISO tri-stated as long as the SS pin is driven high. In this state, software may update the contents of the SPI Data Register, SPDR, bu t the data will not be shifted out by incoming clock pulses on the SCK pin until the SS pin is driven low.
As one byte has been completely shifted, the end of Transmission Flag, SPIF is set. If the SPI Interrupt Enable bit, SPIE, in the SPCR Register is set, an interrupt is requested.
The Slave may continue to place new data to be sent into SPDR before reverseing the incoming data. The last incoming byte will be kept in the Buffer Register for later use. The system is single buffered in the transmit direction and double buffered in the receive direction. This means that bytes to be transmitted cannot be written to the SPI Data Register before the entire shift cycle is completed.
When receiving data, however, a received character must be reverse from the SPI Data Register before the next character has been completely shifted in. Otherwise, the first byte is lost.
In SPI Slave mode, the control logic will sample the incoming signal of the SCK pin. To ensure correct sampling of the clock signal, the frequency of the SPI clock should never exceed fosc/4.
Recovery Microcontroller PIC16F877 Program: From One Unit to a Production Run
The first unit is a technical problem: get the content out, prove it is complete, document it. The hundredth unit is a production problem, and it fails in ways the first one never reveals. A program that runs correctly on a bench from a file loaded by hand may behave differently when a contract manufacturer programs it at volume with a fixture that was configured from a verbal description.
The PIC16F877 is the forty-pin flagship of its family: 8192 by 14 bits of program memory, 368 bytes of RAM, 256 bytes of data EEPROM, five ports. It is the part that appears in the largest number of legacy designs, which means a recovery on it is more likely than most to be followed by a production request.
What changes at volume
| Concern | Single unit | Production run |
|---|---|---|
| content source | one read | a controlled master file |
| per-unit variation | not examined | must be identified and generated |
| configuration | set by hand | part of the programming data |
| calibration | copied from the original | measured, or copied from the original |
| verification | it runs | a defined test, applied to every unit |
| traceability | a report | a file version and a programming record |
The second row is the one that causes the most trouble. On a product with per-unit calibration stored in EEPROM, the recovered unit’s bytes are that unit’s calibration, not a universal value. Programming a hundred devices with those bytes produces a hundred devices that all believe they are the original — which passes a functional test and fails a specification test.
Consistency across units: what to compare
If the customer can supply two or three units of the same product, comparing their images before committing to a master file answers the question that a single unit cannot.
| Difference observed | Interpretation | Consequence for the master |
|---|---|---|
| nothing | identical units | one master file, no per-unit data |
| a few words in EEPROM | per-unit calibration | master needs a calibration step |
| a serial number region | identity data | must be generated per unit |
| a block of code | different firmware revisions | decide which version to reproduce |
| the whole image | different products | the units are not comparable |
The second row is the common case and it has a clean solution: the master file is programmed with default values, and a calibration step writes the real ones. Whether the customer has the fixture to perform that step is a question worth asking before the run, because on some products the calibration is done by the original equipment with a test rig that no longer exists.
The programming data package
A contract manufacturer needs more than a hex file. The package that avoids returns:
The image, with the word convention stated, over the full address range including the blank tail.
The configuration word, as a separate item or as a statement of the values the programmer must set, because many programming fixtures do not take the config word from the file.
The EEPROM content or its defaults, explicitly labelled with which addresses are per-unit.
The device identification and revision the file was validated against, so that a substitution of a different family member is caught rather than absorbed.
A first-article procedure: program one device, fit it, run the product’s functions, and record the result. That procedure is what turns a file into a qualified build.
Verification that means something
Three levels of verification exist, and only the third is evidence that the job is finished.
| Level | What it proves | What it misses |
|---|---|---|
| file comparison | the file matches the file | everything about behaviour |
| read-back comparison | the device matches the file | configuration, calibration, timing |
| behavioural test | the product works | nothing, if the test is complete |
Read-back comparison is the level most contract manufacturers offer by default, and it is the one that produces the widest gap between “passed” and “works”. A device whose configuration word was not programmed passes a read-back comparison of the program array and fails to start.
The behavioural test needs a definition, and the definition comes from the original unit: what the product does at power-up, what it does when each input changes, and what its outputs do in each state. Writing that down during the analysis phase costs an hour and prevents a production dispute.
What the recovery report should carry forward
Four items that are irrelevant to a single unit and essential to a run: the per-unit data map, the configuration values, the behavioural definition, and the revision of the silicon the file was validated on.
The last one matters more than it appears. A production run that programs a file validated on one mask revision into parts from another revision may hit an erratum the original design never encountered, and the failure will appear at the customer’s test station rather than at the programmer.
When the volume is small
Below a few hundred units the economics change: hand programming from a socket is cheaper than setting up a fixture, and a behavioural test on each unit is affordable. The package above still applies, with the fixture replaced by a documented manual procedure — which is worth writing down even for ten units, because the tenth is often assembled two years after the first.
Where the protection state decides whether a run is possible at all, PIC16F876 flash sets out the combinations. Where the per-unit data has to be located before it can be generated, PIC16F874 eeprom follows the parameter block. And where a mask-programmed part makes a run impossible without new silicon, PIC16CR83 heximal explains why.
The short version
One unit is a read; a hundred is a process. Compare units to find what varies, deliver a package rather than a file, and define a behavioural test before the first article is built. The recovered content is the input to a production run, not the run itself.
Reverse Chip ATmega461V Program
Reverse Chip ATmega461V and read mcu atmega461v flash Program, the fuse bit of atmega461v microcontroller will be broken to reset the status of MCU from locked to unlocked one;

The clock source for Timer/Counter2 is named clkT2S. clkT2S is by default connected to the main system I/O clock clkIO. By setting the AS2 bit in ASSR, Timer/Counter2 is asynchronously clocked from the TOSC1 pin.
This enables use of Timer/Counter2 as a Real Time Counter (RTC). When AS2 is set, pins TOSC1 and TOSC2 are disconnected from Port C if Reverse chip atmega861v code.
A crystal can then be connected between the TOSC1 and TOSC2 pins to serve as an independent clock source for Timer/Counter2. The Oscillator is optimized for use with a 32.768 kHz crystal. Applying an external clock source to TOSC1 is not recommended.
For Timer/Counter2, the possible prescaled selections are: clkT2S/8, clkT2S/32, clkT2S/64, clkT2S/128, clkT2S/256, and clkT2S/1024. Additionally, clkT2S as well as 0 (stop) may be selected after Reverse mcu atmega261 hex.
Setting the PSRASY bit in GTCCR resets the prescaler. This allows the user to operate with a predictable prescaler. When this bit is one, the Timer/Counter2 prescaler will be reset.
This bit is normally cleared immediately by hardware. If the bit is written when Timer/Counter2 is operating in asynchronous mode, the bit will remain one until the prescaler has been reset.
The bit will not be cleared by hardware if the TSM bit is set. Refer to the description of the “Bit 7– TSM: Timer/Counter Synchronization Mode” on page 170 for a description of the Timer/Counter Synchronization mode when Reverse CHIP PROGRAM.
The Serial Peripheral Interface (SPI) allows high-speed synchronous data transfer between the ATmega461v and peripheral devices or between several AVR devices. The ATmega640/1280/1281/2560/2561 SPI includes the following features:
Full-duplex, Three-wire Synchronous Data Transfer
Master or Slave Operation
LSB First or MSB First Data Transfer
Seven Programmable Bit Rates
End of Transmission Interrupt Flag
Write Collision Flag Protection
Wake-up from Idle Mode
Double Speed (CK/2) Master SPI Mode when Reverse CHIP PROGRAM
USART can also be used in Master SPI mode, see “USART in SPI Mode” on page 231. The Power Reduction SPI bit, PRSPI, in “Power Reduction Register 0 – PRR0” on page 54 on page 50 must be written to zero to enable SPI module.
Break IC ATmega461 Eeprom
Break IC ATmega461 and read Eeprom data and flash program out from microcontroller atmega461, reprogramme heximal file into new atmega461 mcu for cloning,

If Timer/Counter2 is used to wake the device up from Power-save or ADC Noise Reduction mode, precautions must be taken if the user wants to re-enter one of these modes: The interrupt logic needs one TOSC1 cycle to be reset when recover microcontroller pic18f252 program.
If the time between wake-up and re-entering sleep mode is less than one TOSC1 cycle, the interrupt will not occur, and the device will fail to wake up. If the user is in doubt whether the time before re-entering Power-save or ADC Noise Reduction mode is sufficient, the following algorithm can be used to ensure that one TOSC1 cycle has elapsed:
Write a value to TCCR2x, TCNT2, or OCR2x.
Wait until the corresponding Update Busy Flag in ASSR returns to zero.
Enter Power-save or ADC Noise Reduction mode before Break IC.When the asynchronous operation is selected, the 32.768 kHz Oscillator for Timer/Counter2 is always running, except in Power-down and Standby modes. After a Power-up Reset or wake-up from Power-down or Standby mode, the user should be aware of the fact that this Oscillator might take as long as one second to stabilize after recover microcontroller attiny13a hex.
The user is advised to wait for at least one second before using Timer/Counter2 after power-up or wake-up from Power-down or Standby mode and The contents of all Timer/Counter2 Registers must be considered lost after a wake-up from Power-down or Standby mode due to unstable clock signal upon start-up, no matter whether the Oscillator is in use or a clock signal is applied to the TOSC1 pin.
Description of wake up from Power-save or ADC Noise Reduction mode when the timer is clocked asynchronously: When the interrupt condition is met, the wake up process is started on the following cycle of the timer clock, that is, the timer is always advanced by at least one before the processor can break the counter value.
After wake-up, the MCU is halted for four cycles, it executes the interrupt routine, and resumes execution from the instruction following SLEEP.
Breaking of the TCNT2 Register shortly after wake-up from Power-save may give an incorrect result. Since TCNT2 is clocked on the asynchronous TOSC clock, breaking TCNT2 must be done through a register synchronized to the internal I/O clock domain.
Synchronization takes place for every rising TOSC1 edge. When waking up from Power-save mode, and the I/O clock (clkI/O) again becomes active, TCNT2 will break as the previous value (before entering sleep) until the next rising TOSC1 edge.
The phase of the TOSC clock after waking up from Power-save mode is essentially unpredictable, as it depends on the wake-up time. The recommended procedure for breaking TCNT2 is thus as follows:
Write any value to either of the registers OCR2x or TCCR2x.
Wait for the corresponding Update Busy Flag to be cleared.
During asynchronous operation, the synchronization of the Interrupt Flags for the asynchronous timer takes 3 processor cycles plus one timer cycle. The timer is therefore advanced by at least one before the processor can break the timer value causing the setting of the Interrupt Flag if Break IC eeprom.
The Output Compare pin is changed on the timer clock and is not synchronized to the processor clock.
Recover Microcontroller PIC16F874 Eeprom: Finding the Parameter Block
A hundred and twenty-eight bytes is not much storage, but it is enough for a complete set of operating parameters, and that is what it holds on almost every design built around this part. The bytes are not scattered: they are a block with an order, an order that the program imposed when it wrote them, and the routine that reads them is the map.
The PIC16F874 is the forty-pin member of the family: 4096 by 14 bits of program memory, 128 bytes of data EEPROM, five ports. It appears in equipment that has settings — controllers, timers, dosing equipment, environmental chambers — which means the EEPROM content is the difference between one installation and the next.
How a parameter block gets its structure
The program does not write the EEPROM byte by byte at random addresses. It writes a sequence, usually from a buffer in RAM, and it reads the sequence back the same way. Both operations use a pointer that starts at an address and advances, and that pointer’s start address and limit define the block.
So the block is discoverable from the code, in three steps.
The first is to find the EEPROM read routine. It is the only code that touches the EEPROM address and data registers, and it will be called from a small number of places.
The second is to find the loop that calls it repeatedly. That loop has a counter with a limit, and the limit is the block size.
The third is to find the RAM buffer the values land in. The addresses used after the load are the parameter slots, and their use identifies their meaning.
Reading the parameter slots
Once the buffer is known, each slot can be read by following its uses.
| Usage pattern | Parameter type | Typical encoding |
|---|---|---|
| compared against a conversion result | a threshold | raw counts |
| multiplied or shifted before use | a calibration factor | fixed point |
| copied to a timer reload | a period | timer counts |
| used as a loop limit | a count of items or repeats | integer |
| copied to an output port at start-up | a configuration word for external hardware | bit flags |
| compared against zero only | an enable flag | boolean |
The fifth row is worth looking for specifically. On a forty-pin part with five ports, a byte in EEPROM that is written to a port at start-up is a hardware configuration: which relays are enabled, which outputs are active-low, which display mode is selected. Those bytes explain unit-to-unit differences that otherwise look like faults.
Why the order tells you about the product
Parameters are stored in the order the design uses them, and that order is a description of the product’s feature set.
A block that begins with four thresholds and then a calibration factor belongs to a device with four setpoints and one sensor. A block that begins with a mode byte, then a table of times, belongs to a device with selectable programs. A block with a large run of similar values is a curve — a temperature profile, a dosing schedule, a set of segment times.
Reading the block layout before reading the code often gives a faster understanding of the product than the control flow does, because the layout is a summary of what the product can be told to do.
The map, the checksum and the blank case
Three details recur on this part and each has a diagnostic value.
A map byte or a length byte. Many designs store the block’s own size or a version at the start, so that a firmware update can migrate old contents. If the first byte is a small number that matches the block size, that is what it is.
A checksum over the block. Designs that care about data integrity store a checksum, and a device restored with a blank EEPROM fails its own check at start-up. This is the most common reason a correctly programmed device appears not to work.
An all-blank array. A 128-byte array of 0xFF means the EEPROM was never written, which on a production unit usually means the settings were defaults held in the program. In that case the parameter block exists only as default values in the code, and those are worth tabulating too.
| Observation | Meaning | Action |
|---|---|---|
| all 0xFF | never written, defaults in code | read the defaults from the initialisation |
| first byte equals block length | versioned block | record the version |
| a byte makes the sum zero | checksum present | include it in any reconstruction |
| non-uniform from a known offset | per-unit calibration | preserve exactly, do not normalise |
Reconstructing a block from behaviour
When the EEPROM is unreadable — protected, or the device is damaged — the block can sometimes be rebuilt from observed behaviour: set a parameter through the product’s interface, watch what changes. On equipment with a keypad and a display this is feasible, though slow.
The result is a block that is correct in the parameters the interface exposes and default in the rest. That distinction belongs in the report, because a block that is 80 percent right behaves in ways that are 100 percent wrong for the parameters that were not exercised.
Delivering the block as a documented object
The bytes, raw, at their addresses. A table of slots with their roles and, where the arithmetic allows, their values in engineering units. The version or checksum byte identified. And a note on which slots were inferred from the interface rather than read from the device.
Where the same family’s structure work is the subject rather than the data, PIC16F873 software covers the conversion to maintainable source. Where the protection matrix decides whether the block is readable at all, PIC16F876 flash sets out the combinations. And where an eight-pin part has sixteen bytes instead of a hundred and twenty-eight and the same problem at smaller scale, PIC12CE518 binary recovery covers it.
The short version
Follow the load routine to the block, follow the block to its uses, and the product’s configurability becomes explicit. Preserve the bytes exactly, document the slots, and record which values came from behaviour rather than from the device.
Recover Microcontroller ATmega261 Heximal
Recover Microcontroller ATmega261 Heximal from embedded flash memory, the mcu atmega261 will be unlocked by focus ion beam and locked code can be extracted from atmega261 memory;

If a write is performed to any of the five Timer/Counter2 Registers while its update busy flag is set, the updated value might get corrupted and cause an unintentional interrupt to occur.
The mechanisms for reading TCNT2, OCR2A, OCR2B, TCCR2A and TCCR2B are different. When reading TCNT2, the actual timer value is read. When reading OCR2A, OCR2B, TCCR2A and TCCR2B the value in the temporary storage register is read when breaking pic12f617 microcontroller.
When Timer/Counter2 operates asynchronously, some considerations must be taken. Warning: When switching between asynchronous and synchronous clocking of Timer/Counter2, the Timer Registers TCNT2, OCR2x, and TCCR2x might be corrupted.
A safe procedure for switching clock source is:
Disable the Timer/Counter2 interrupts by clearing OCIE2x and TOIE2.
Select clock source by setting AS2 as appropriate.
Write new values to TCNT2, OCR2x, and TCCR2x.
To switch to asynchronous operation: Wait for TCN2UB, OCR2xUB, and TCR2xUB.
Clear the Timer/Counter2 Interrupt Flags.
Enable interrupts, if needed.
The CPU main clock frequency must be more than four times the Oscillator frequency.
When writing to one of the registers TCNT2, OCR2x, or TCCR2x, the value is transferred to a temporary register, and latched after two positive edges on TOSC1.
The user should not write a new value before the contents of the temporary register have been transferred to its destination. Each of the five mentioned registers have their individual temporary register, which means that e.g. writing to TCNT2 does not disturb an OCR2x write in progress when Reverse engineering pic16hv610 microcontroller program.
To detect that a transfer to the destination register has taken place, the Asynchronous Status Register – ASSR has been implemented. When entering Power-save or ADC Noise Reduction mode after having written to TCNT2, OCR2x, or TCCR2x, the user must wait until the written register has been updated if Timer/Counter2 is used to wake up the device. Otherwise, the MICROCONTROLLER will enter sleep mode before the changes are effective.
This is particularly important if any of the Output Compare2 interrupt is used to wake up the device, since the Output Compare function is disabled during writing to OCR2x or TCNT2. If the write cycle is not finished, and the MICROCONTROLLER enters sleep mode before the corresponding OCR2xUB bit returns to zero, the device will never receive a compare match interrupt, and the MICROCONTROLLER will not wake up.
Recovery MCU PIC16F871 Software: Two Units of the Same Design Are Not the Same Silicon
A forty-pin part with two kilobytes of program memory, three timers, two serial ports and a converter — a general-purpose controller that was designed into equipment with a long production life. Fifteen years of production means at least three or four mask revisions, and each revision fixes things that were wrong, sometimes in ways that change how the device behaves at the edges.
Most of the time this is invisible. Then a customer sends two units of the same product, both working, both from the same drawing, and their images differ in forty words. The question that follows is whether one of them is corrupt. Usually the answer is that neither is: they were built in different years, on different revisions of the same design, and the difference is in the code because the erratum demanded it.
What revisions change
| Area | Typical revision change | Effect on a recovery |
|---|---|---|
| protection behaviour | how much of the array the inhibit covers | a read that works on one unit and not another |
| reset and power-up timing | the delay before code execution | a design that works on one batch and not the next |
| EEPROM write sequencing | required delay between operations | data loss on units from one period |
| analogue accuracy | trimming or reference behaviour | measured values offset by a small amount |
| programming interface | entry timing tolerances | a fixture that works on some units only |
The first row explains a specific and frustrating pattern: a customer with ten units sends one, it reads, and the other nine do not. If the ten were bought over several years, they may not all be the same revision, and the protection mechanism on the earlier ones may differ from the later.
The revision is on the die, and usually not on the package
Package markings carry a date code and a lot, and the date code is a good proxy for the revision, but it is a proxy. The authoritative statement is the die marking, which carries a revision letter or a mask code that maps to a documented revision history.
For a job where the unit is being opened anyway, reading that marking costs nothing and belongs in the report. For a job where the unit is not being opened, the date code plus the behaviour observed on the bench is enough to make a working assumption, and the assumption should be stated.
The reason to record it is not archival neatness. It is that a customer comparing a newly recovered image against an image recovered two years ago will find differences, and the first question will be whether the earlier work was wrong. A revision letter in both reports answers that in one line.
Comparing two units without false alarms
When two units of the same product are available, comparing their images is a powerful check — it locates the unit-specific region, confirms that the rest is identical, and gives a second sample of the constant tables.
The comparison has to be done with three filters.
| Difference type | Looks like | Interpretation |
|---|---|---|
| a single word in the configuration area | different protection or oscillator setting | units from different production periods |
| a contiguous block of words | a routine that was rewritten | revision difference, not corruption |
| scattered single words | table values | unit-specific calibration |
| the entire image shifted | different builds | different software versions, not revisions |
| nothing at all | identical units | the comparison gives no information |
The third row is the useful one commercially: on a product with per-unit calibration written at end of line, the differing words are the calibration, and comparing two units tells you which addresses hold it without reading a single line of code.
Errata as a description of what to look for
A device’s errata sheet lists the things that do not work as the datasheet says. For a reader of recovered code, that list is a guide to the workarounds: a delay added where the datasheet says none is needed, a double read of a register, a re-initialisation after a conversion.
Those patterns look like defensive or clumsy code until they are matched against the errata, at which point they are obviously correct. Annotating them as workarounds, with the erratum they address, is one of the more valuable things a report can contain, because it prevents a customer’s engineer from “cleaning up” code that is doing exactly what it must.
Reading a forty-pin part efficiently
Two kilobytes of words over five ports is a lot of surface. The order that works: configuration word, port direction and peripheral initialisation, the timer setup and its reload values, then the main loop.
Timers deserve early attention on this part, because three of them usually means three jobs: a system tick, a baud rate generator, and a pulse measurement. The reload values converted through the oscillator give the tick period directly, and that number is the clock of the whole product’s behaviour.
What the delivery records
The image with the convention stated, the configuration decoded, the EEPROM raw, the annotated listing, and — specific to this kind of job — a revision statement: which silicon revision the unit carries, how that was established, and what in the image is attributable to it.
Where the same family’s smaller member has a converter the reading depends on, PIC16F872 program covers that path. Where a sibling’s protection combinations are the subject, PIC16F876 flash sets out the matrix. And where the same unit-to-unit comparison is used to locate calibration rather than revisions, PIC16F874 eeprom follows the parameter block.
The short version
Same drawing does not mean same silicon. Record the revision, filter unit comparisons by difference type, and read the errata as a map of the code’s odd corners. A difference between two units is usually history, not damage.
ATmega261PA: Output Drivers, Slew, and Code That Depends on Them
Code is digital; pins are analogue. Between them sits an output driver with a finite rise time, a finite drive current, and a behaviour that changes when the die is redesigned. A picoPower revision redesigns those drivers, and firmware that assumed the old ones can fail without a single instruction differing.
This is the class of problem that is hardest to attribute, because the program is identical, the board is identical, and only the part changed.
What a picoPower revision alters at the pin
Three characteristics shift, all in the direction of lower power:
Drive current. The driver can source and sink less. A pin driving an LED directly sees a dimmer LED; a pin driving a capacitive load sees a slower edge.
Slew rate. Deliberately reduced on many pins, because fast edges waste current. A slower edge is fine for a static signal and not fine for a signal that has to meet a setup time.
Pull-up and pull-down strength. Weaker, for the same reason. A pin relying on an internal pull-up to charge a node now takes longer to do so.
None of these appears in the code. All of them can break it.
Where firmware depends on the driver
Four patterns, in order of frequency:
Bit-banged protocols with no delay. A two-wire or one-wire implementation that toggles a pin and immediately samples it depends on the pin settling within the instruction time. A weaker driver breaks it.
Multiplexed displays. Segments driven directly from port pins rely on sufficient current. Lower drive means dimmer output rather than a fault, which is easy to miss.
RC timing loops. A pin charging a capacitor until a threshold is reached takes longer with a weaker driver, which shifts every timing constant derived from it.
Shared buses without an external driver. A bus with more than a couple of devices and no buffer relies on the pin’s drive to meet timing.
| Dependency | Symptom after a revision change | Diagnostic |
|---|---|---|
| Bit-banged bus | Intermittent acknowledge failures | Scope the edge |
| Direct LED drive | Dimmer, not broken | Measure current |
| RC timing | Consistent offset in measurements | Recompute the constant |
| Unbuffered bus | Marginal at temperature extremes | Look at rise time |
Why this reads as a software bug
If a device works on the old die and fails on the new one, the natural hypothesis is a firmware change. Verification says the firmware is identical, which points at the hardware, and the hardware is the same board.
The remaining variable is the die, and the mechanism above is what changes on it. That reasoning is easy to follow once stated and hard to reach from symptoms, because the symptom is a protocol failure and the cause is a drive current.
What the code reveals
The dependency is visible in the code, if you know to look:
- A toggle followed immediately by a sample, with no delay between, is a timing dependency on the driver.
- A port write driving a load with no transistor in the schematic is a current dependency.
- A loop counting until an input changes is an RC dependency.
Each of those is a design decision that was validated on one die. Recording it makes the risk explicit, which is the useful outcome: not “this is broken” but “this depends on a pin characteristic that revisions can change”.
Reading order
- Signature and fuses, including the package date code, because the die is the variable.
- Lock byte.
- Array read, verified.
- Port initialisation: which pins are outputs, which have pull-ups.
- Cross-reference every output pin against the external circuit.
Step 5 is the one that turns the image into a risk assessment. A pin that drives a transistor is robust; a pin that drives a node directly is not.
Related notes
- ATmega261P and the watchdog fuse — another configuration fact that explains odd behaviour.
- ATmega261PV and sleep — the same die family in its low-power role.
- ATmega16PA and picoPower — the revision family described from the interface side.
FAQ
Does a picoPower part drive less current? Generally yes, and the datasheet gives the figures per pin and per supply.
Can the drive be increased in software? Not on this family. The characteristic is set by the die.
Why does a bit-banged bus fail intermittently? Because the edge is slower and the sampling point is now marginal rather than comfortable.
Is a dimmer LED a fault? It is a consequence. Whether it matters depends on the specification the product has to meet.
Conclusion
Pin behaviour is part of the contract between firmware and hardware, and revisions can change it without changing a single instruction. Reading the port configuration and asking what each output actually drives converts an unexplained field failure into a stated dependency — which is the only form in which it can be managed.