Hi,

starting with svn 7610, sdcc/pic16 allows read/write access EEPROM via
generic pointers in the range of 0x40_0000 to 0x7F_FFFF (though only
the one or two least significant byte(s) are actually used to index
into the EEPROM). Devices that do not have any EEPROM will silently
ignore EEPROM accesses, reads will return random values. Also note
that interrupts are disabled during EEPROM accesses and that writes
wait for the end of the EEPROM write by polling EECON1.WR after each
byte while interrupts are still disabled. This seems to be the safest
and simplest approach; safe improvements are welcome.

!!! THE CODE IS COMPLETELY UNTESTED. IT COMPILES FOR ME, BUT THERE ARE
NO GUARANTEES WHATSOEVER BEYOND THAT !!!

In order to accomodate the different device types (no EEPROM, 8-bit
EEPROM range, 16-bit EEPROM range (via EEADRH)), generic pointer
access to EEPROM is a bit involved:
device/lib/pic16/libsdcc/gptr/gptr{get,put}[1234].c branches off to
device-specific EEPROM dispatcher routine defined in either
(a) device/non-free/lib/pic16/libdev/gptr/dispatch.S (returns immediately)
(b) device/non-free/lib/pic16/libdev/gptr/eeprom8_*_dispatch.S (jumps
on to __eeprom8_* to access 8-bit EEPROMs using EEADR only)
(c) device/non-free/lib/pic16/libdev/gptr/eeprom16_*_dispatch.S (jumps
on to __eeprom16_* to access 16-bit EEPROMs using EEADRH:EEADR)
The __eeprom{8,16}_gptr{get,put}[1234] routines are again defined in
device/lib/pic16/libsdcc/gptr/eeprom{8,16}_gptr{get,put}[1234].c and
included in libsdcc, but are linked into the final executable only
when referenced, and each device library references only one set of
these (either eeprom8 or eeprom16).

Writing to EEPROM is rather longish, so I factored the relevant code
out into device/lib/pic16/libsdcc/gptr/eeprom{8,16}_write.c and call
it from eeprom{8,16}_gptrput[1234].c

The indirection via dispatchers requires two GOTOs (4 cycles) where
one BRA (1 cycle) could suffice iff I provided 3 complete sets of
gptr{get,put}[1234] and linked the proper one into each device lib,
but that would require compiling them for each device separately and
would add more free code to the non-free tree, both of which I wanted
to avoid.



To use, you MUST use an updated sdcc + an updated library (libsdcc,
libdev) and you SHOULD try something like

uint8_t *eeprom = (void *)0x400000;

uint8_t read_eeprom(uint16_t offset)
{
  return eeprom[offset];
}

void write_eeprom(uint16_t offset, uint8_t val)
{
  eeprom[offset] = val;
}

Pitfalls:
* TYPE __at(0x400000) ID = INIT; does not work yet and probably never will
* TYPE __at(0x400000) ID; does not work (yet)
* accessing bitfields in EEPROM does probably not work
* accessing structs in EEPROM via
  (*((struct TAG *)0x400000)).FIELD
  should work (except for bitfields, see above), but is untested
* *((TYPE*)&eeprom[offset]) should work for any primitive TYPE with
sizeof(TYPE) <= 4, including generic pointers (3 byte)

I would like to hear any code review and/or test results.

Raphael

------------------------------------------------------------------------------
For Developers, A Lot Can Happen In A Second.
Boundary is the first to Know...and Tell You.
Monitor Your Applications in Ultra-Fine Resolution. Try it FREE!
http://p.sf.net/sfu/Boundary-d2dvs2
_______________________________________________
Sdcc-user mailing list
Sdcc-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sdcc-user

Reply via email to