71 lines
1.6 KiB
C
71 lines
1.6 KiB
C
|
|
#ifndef EEPROM_H
|
||
|
|
#define EEPROM_H
|
||
|
|
|
||
|
|
#include <avr/io.h>
|
||
|
|
#include "lib/interupt.h"
|
||
|
|
#include "lib/mystd.h"
|
||
|
|
|
||
|
|
static inline void eeprom_wait(void) {
|
||
|
|
while (EECR & BV(EEPE))
|
||
|
|
;
|
||
|
|
}
|
||
|
|
static inline void eeprom_write_single_nocheck(uint16_t addr, uint8_t data) {
|
||
|
|
uint8_t sreg_save = SREG;
|
||
|
|
my_cli();
|
||
|
|
|
||
|
|
// wait until eeprom is good to go !
|
||
|
|
eeprom_wait();
|
||
|
|
while (SPMCSR & BV(SPMEN))
|
||
|
|
;
|
||
|
|
|
||
|
|
// setup the (addr, data) pair
|
||
|
|
EEAR = addr;
|
||
|
|
EEDR = data;
|
||
|
|
|
||
|
|
// we set the EEPROM master write bit
|
||
|
|
EECR = (EECR & ~BV(EEPE)) | BV(EEMPE);
|
||
|
|
// within four cpu cycle, we need to set the EEPROM write bit, otherwise the writes doesnt work
|
||
|
|
// why 4 ? -> the master bit is reset after 4 cycles, and you need both to actually write
|
||
|
|
EECR |= BV(EEPE);
|
||
|
|
|
||
|
|
// this is the exact setup written in p32
|
||
|
|
// here the write should be done
|
||
|
|
SREG = sreg_save;
|
||
|
|
}
|
||
|
|
|
||
|
|
static inline uint8_t eeprom_read_single(uint16_t addr) {
|
||
|
|
uint8_t sreg_save = SREG;
|
||
|
|
my_cli();
|
||
|
|
eeprom_wait();
|
||
|
|
|
||
|
|
EEAR = addr;
|
||
|
|
|
||
|
|
EECR |= BV(EERE);
|
||
|
|
|
||
|
|
SREG = sreg_save;
|
||
|
|
return EEDR;
|
||
|
|
}
|
||
|
|
|
||
|
|
// true on error
|
||
|
|
static inline bool eeprom_write_single(uint16_t addr, uint8_t data) {
|
||
|
|
if (eeprom_read_single(addr) != data)
|
||
|
|
eeprom_write_single_nocheck(addr, data);
|
||
|
|
|
||
|
|
return (eeprom_read_single(addr) != data);
|
||
|
|
}
|
||
|
|
// true on error
|
||
|
|
static inline bool eeprom_write(uint16_t addr, const uint8_t* data, uint16_t length) {
|
||
|
|
for (uint16_t i = 0; i < length; i++) {
|
||
|
|
if (eeprom_write_single(addr + i, data[i]))
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
static inline void eeprom_read(uint16_t addr, uint8_t* data, uint16_t length) {
|
||
|
|
for (uint16_t i = 0; i < length; i++)
|
||
|
|
data[i] = eeprom_read_single(addr + i);
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif /* EEPROM_H */
|