WriteEEPROM_BYTE,  WriteEEPROM_WORD,  and  WriteEEPROM_ULONG

Purpose: Write one (1), two (2), or four (4) successive BYTEs to EEPROM.
Assumes:  BYTEs in EEPROM are read from Least Significant to Most Significant.
Passed:     R25:R24 VOID *  vPtrEEPROM  address of the EEPROM first or only BYTE to write
R22 BYTEbValue the BYTE value to write to that EEPROM address (OR)
R23:R22 WORDwValue the WORD value to write to that EEPROM address (OR)  
R23:R22:R21:R20 ULONGulValue the ULONG value to write to that EEPROM address
Alters: The EEPROM Registers (EEARL, EEARH, EECR and EEDR), FLAGs; possibly R22, R23 and/or R24.
Example: 
   .ORG  0x1000

EEWriteDemo:
   RCALL   AEEWrite_Parse        ; Let the subroutine setup R25:R24 from 'X'
   SBRS    R21, BIT_PV_VALID     ; Exit unless a value (the address) was parsed
EEWrite_Ret:
   RET

   MOVW    R30, R22              ; For the address, only the Low WORD is needed
   PUSH    R24                   ; Save the 3rd byte (the value above 0xFFFF)
   RCALL   AEEWrite_Parse        ; Use the "next value" pointer, already in 'X'
   POP     R18                   ; Restore that saved 3rd byte, but into R18
   SBRS    R21, BIT_PV_VALID
   RJMP    AEEWrite_Ret          ; Exit if there was no 2nd value to parse

   MOVW    R20, R22              ; Move the ULONG returned in R25:R24:R23:R22
   MOVW    R22, R24              ;  to R23:R22:R21:R20 (the data value)
   MOVW    R24, R30              ; Retrieve and set the EEPROM address
   SBRC    R18, 7                ; If the address was 0x800000 to 0xFFFFFF, use
   JMP     AWriteEEPROM_ULONG    ;  the ULONG subroutine
   MOVW    R22, R20              ; The others use R23:R22 as the Low Order WORD
   CPSE    R18, R1               ; If the address was 0x010000 to 0x7FFFFF, use
   JMP     AWriteEEPROM_WORD     ;  the WORD routine, otherwise single BYTE
   JMP     AWriteEEPROM_BYTE     ; Each one returns directly to our caller

EEWrite_Parse:
   MOVW    R24, R26              ; Copy the pointer to the SRAM buffer address 
   JMP     AParseValue           ; Returns ULONG in R25:R24:R23:R22
Test it:EEPROM data change ebugging MUST be ON (use "#") to generate this output:
m>@ 0x1000 0x1E0 3
EEPROM BYTE at address 0x01E0 changed from 0xFF to 0x03
m>@ 0x1000 0x101e0 4
EEPROM BYTE at address 0x01E0 changed from 0x03 to 0x04
EEPROM BYTE at address 0x01E1 changed from 0xFF to 0x00
m>@ 0x1000 0xFF01E0 5   ; Note that the BYTE at 0x1E1 does not change:
EEPROM BYTE at address 0x01E0 changed from 0x04 to 0x05
EEPROM BYTE at address 0x01E2 changed from 0xFF to 0x00
EEPROM BYTE at address 0x01E3 changed from 0xFF to 0x00
m>@ 0x1000 0xFF01E0 -1
EEPROM BYTE at address 0x01E0 changed from 0x05 to 0xFF
EEPROM BYTE at address 0x01E1 changed from 0x00 to 0xFF
EEPROM BYTE at address 0x01E2 changed from 0x00 to 0xFF
EEPROM BYTE at address 0x01E3 changed from 0x00 to 0xFF
m>@ 0x1000 0xFF01E0 5
EEPROM BYTE at address 0x01E0 changed from 0xFF to 0x05
EEPROM BYTE at address 0x01E1 changed from 0xFF to 0x00
EEPROM BYTE at address 0x01E2 changed from 0xFF to 0x00
EEPROM BYTE at address 0x01E3 changed from 0xFF to 0x00
m>@ 0x1000 0xF801E0 -1
EEPROM BYTE at address 0x01E0 changed from 0x05 to 0xFF
EEPROM BYTE at address 0x01E1 changed from 0x00 to 0xFF
EEPROM BYTE at address 0x01E2 changed from 0x00 to 0xFF
EEPROM BYTE at address 0x01E3 changed from 0x00 to 0xFF
m>@ 0x1000 0xF001E0 2
EEPROM BYTE at address 0x01E0 changed from 0xFF to 0x02
EEPROM BYTE at address 0x01E1 changed from 0xFF to 0x00
EEPROM BYTE at address 0x01E2 changed from 0xFF to 0x00
EEPROM BYTE at address 0x01E3 changed from 0xFF to 0x00
m>@ 0x1000 0x1e0 4
EEPROM BYTE at address 0x01E0 changed from 0x02 to 0x04
m>@ 0x1000 0xF001E0 4  ; Note that no BYTEs are changed:
m>@ 0x1000 0x101E0 -2
EEPROM BYTE at address 0x01E0 changed from 0x04 to 0xFE
EEPROM BYTE at address 0x01E1 changed from 0x00 to 0xFF
m>@ 0x1000 0x8001E0 -1
EEPROM BYTE at address 0x01E0 changed from 0xFE to 0xFF
EEPROM BYTE at address 0x01E2 changed from 0x00 to 0xFF
EEPROM BYTE at address 0x01E3 changed from 0x00 to 0xFF
m>@ 0x1000 0x8001E0 -1
m>                                                                              
Notes: In order to minimize the number times any specific EEPROM BYTE is written, these routines first read the present value (of each BYTE.) If it is the same as the value to be written, that BYTE is skipped.
The write is not even attemped for any address past the end of physical EEPROM, which is 1,023 (= 0x3FF) for a 328P.
Dropin: 
(setup
code)
;   Setup for the WriteEEPROM_*() call:
; Passed:         R25:R24 VOID * vPtrEE address at which to begin writing
;                     R22 BYTE   bValue of the BYTE data to write  (OR)
;                 R23:R22 WORD   wValue of the WORD data to write  (OR)
;         R23:R22:R21:R20 ULONG  ulValue the ULONG data to write
; Alters: Possibly R22, R23, and/or R24, FLAGs and the EEPROM
;  (also: EEARL, EEARH, EECR and EEDR, of course)
Also see:  The WriteEEPROM_BYTE, WriteEEPROM_WORD, and WriteEEPROM_ULONG System Functions as well as the "#" EEPROM change toggle key.