Way back when (~10 years ago) I wrote some code into my Monitor that will write into the AT28C256 EEPROM. The code is quite simple... using a toggle bit, which also requires that the code writing to the EEPROM is NOT within the EEPROM. This is basically what Ed is referring to. The earlier version of my Monitor could accidentally write to the EEPROM address space... and yes, the internal operations resulted in the monitor code kinda crashing, resulting in a BRK trap being executed. Later versions (of my Monitor) check for the address range and will not attempt to simply write into the EEPROM space.
The AT28BV256 is basically the same, however... if you don't send the unlock sequence first, the write routine (using toggle bit) will appear to work correctly without any errors, but the contents of the EEPROM will not be updated.
As Mike has been using the SST39 series, it appears to have the same unlock sequence as the AT28BV256. I do have some of the SST39 series flash ROMs but haven't put one in circuit yet. Based on the address range for the unlock sequence, you can get the ROM addressable window down to 24KB. According to the datasheet for the SST39 series, you can do a byte-by-byte write sequence, but you first need to perform a sector erase, which is based on a 4KB block. Again, I've not put one of these into circuit yet, but perhaps Mike can confirm this is the case.
In the end, I think armed with some knowledge on the devices you're using, you can get around all of these issues with a combination of hardware design and software to support the hardware as needed. Also, here's the routine I use to program the AT28BV256 EEPROM insitu. The code is kept in EEPROM and copied to page zero for execution:
Code:
;Byte write code for EEPROM.
; Note: AT28BV256 requires an unlock sequence for all write operations.
; This is different from earlier Atmel EEPROMs (i.e., AT28C256). The
; sequence must be sent first to unlock the device, then data can be
; sent for programming. Note that byte writes can be 1 to 64 bytes.
; The EEPROM is defined in constants for the Offset of the EEPROM in
; the hardware memory map.
;
BYTE_WRS SEI ;Disable interrupts
;
LDA #$AA ;Get code $AA
STA EEPROM+$5555 ;Send to EEPROM
LDA #$55 ;Get code $55
STA EEPROM+$2AAA ;Send to EEPROM
LDA #$A0 ;Get code $A0
STA EEPROM+$5555 ;Send to EEPROM
;
LDA (SRCL) ;Get source byte
STA (TGTL) ;Write to target byte
LDA (TGTL) ;Read target byte (EEPROM)
AND #%01000000 ;Mask off bit 6 - toggle bit
BYTE_WLP STA TEMP3 ;Store in Temp location
LDA (TGTL) ;Read target byte again (EEPROM)
AND #%01000000 ;Mask off bit 6 - toggle bit
CMP TEMP3 ;Compare to last read (toggles if write mode)
BNE BYTE_WLP ;Branch back if not done
CLI ;Re-enable interrupts
BYTE_WRE RTS ;Return to caller
;
Note that the same code excluding the unlock sequence works with the AT28C256.