The logic of flash is that it can't accept data using MOV (like eeprom), it accepts data as AND. I.e. you can write 0 to each bit of flash, but you can't write 1. To write 1, you need to erase the entire sector at the same time - erased flash contains 1 in all bits.
When I often needed to write just one byte, it seemed unnecessary to supplement the eeprom, often erase flash-a hole will be wiped. I organized a chain of data cells. The first byte was a signature with the values: FFh-cell is free, 0Fh-cell contains current data, 00h-cell is canceled. So by finding a cell with the signature 0Fh, I could find the actual data. To write new actual data, I wrote the signature 00h to the current cell, and the signature 0Fh to the next one. When the sector ended, I erased it and used a new circle.
const
cEmptyFlashCell = 0xFF;
cActualFlashCell = 0x0F;
cCanceledFlashCell = 0x00;
cEmptyFlashValue = 0;
type
tFlashCell = record
Singnatute : byte;
Value : byte;
end;
const
cLowFlashData = 1;
cHighFlashData = cSectorSize div SizeOf(tFlashCell);
type
tFlashData = array[cLowFlashData..cHighFlashData] of tFlashCell;
var
FlashData : tFlashData absolute cFlashEnd-cFlashSectorSize;
funtion GetFlashCurrPos:dword;
var i: dword;
begin
i:=cLowFlashData;
while (i<=cHighFlashData) and (FlashData[i].Signature<>cActualFlashCell ) do Inc(i);
if i>cHighFlashData then i:=cLowFlashData;
Result:=i;
end;
function GetFromFlashValue:byte;
var t: dword;
begin
t:=GetFlashCurPos;
if FlashData[t].Signature=cEmptyFlashCell then begin
Result:=cEmptyFlashValue;
and else begin
Result:=FlashData[t].Value;
end;
end;
procedure SetToFlashValue(aValue:byte);
var t: dword;
begin
t:=GetFlashCurPos;
if t=cHighFlashData then begin
EraseFlashSector;
t:=cLowFlashData;
end else begin
if FlashData[t].Signature<>cEmptyFlashCell then begin
SaveToFlash(t,cCanceledFlashCell,0);
Inc(t);
end;
end;
SaveToFlash(t,cActualFlashCell,aValue);
end;