diff --git a/src/common.h b/src/common.h index ae5ad53..d075862 100644 --- a/src/common.h +++ b/src/common.h @@ -4,7 +4,7 @@ #include "common/math.h" #include "common/types.h" #include "common/watchdog.h" -#include "common/eeprom.h" +#include "common/memory.h" #include #include diff --git a/src/common/eeprom.c b/src/common/eeprom.c deleted file mode 100644 index a250306..0000000 --- a/src/common/eeprom.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "common.h" - -// TODO: Implement EEPROM storage with wear leveling - -int MEM_Read(mem_data_t *out) -{ - UNUSED(out); - - return 0; -} - -int MEM_Write(mem_data_t *in) -{ - UNUSED(in); - - return 0; -} diff --git a/src/common/memory.c b/src/common/memory.c new file mode 100644 index 0000000..1c3113f --- /dev/null +++ b/src/common/memory.c @@ -0,0 +1,89 @@ +#include "common.h" + +#include + +static int WriteRaw(word addr, byte data); +static byte ReadRaw(word addr); + +int MEM_Read(mem_data_t *out) +{ + // TODO + UNUSED(out); + UNUSED(ReadRaw); + return 0; +} + +int MEM_Write(mem_data_t *in) +{ + // TODO + UNUSED(in); + UNUSED(WriteRaw); + return 0; +} + +static int WriteRaw(word addr, byte data) +{ + // The EEMWE bit determines whether setting EEWE to + // one causes the EEPROM to be written. When EEMWE + // is set, setting EEWE within four clock cycles + // will write data to the EEPROM at the selected + // address. + + // If EEMWE is zero, setting EEWE will have no + // effect. When EEMWE has been written to one by + // software, hardware clears the bit to zero after + // four clock cycles. + + // Caution: An interrupt between the last two steps + // will make the write cycle fail, since the EEPROM + // Master Write Enable will time-out. + + // If an interrupt routine accessing the EEPROM is + // interrupting another EEPROM Access, the EEAR or + // EEDR reGister will be modified, causing the + // interrupted EEPROM Access to fail. + + // It is recommended to have the Global Interrupt + // Flag cleared during all the steps to avoid these + // problems. + + // Wait until ready + while (EECR & BIT(EEWE)); + + // No interrupts during EEPROM write + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { + EEAR = addr; + EEDR = data; + + // Write to address + EECR |= BIT(EEMWE); + EECR |= BIT(EEWE); + } + + return 0; +} + +static byte ReadRaw(word addr) +{ + // Wait until ready + while (EECR & BIT(EEWE)); + + EEAR = addr; + + // The EEPROM Read Enable Signal EERE is the read + // strobe to the EEPROM. When the correct address + // is set up in the EEAR Register, the EERE bit + // must be written to a logic one to trigger the + // EEPROM read. + + // Read from address + EECR |= BIT(EERE); + + // The EEPROM read access takes one instruction, + // and the requested data is available immediately. + // When the EEPROM is read, the CPU is halted for + // four cycles before the next instruction is + // executed. + + return EEDR; +} diff --git a/src/common/eeprom.h b/src/common/memory.h similarity index 67% rename from src/common/eeprom.h rename to src/common/memory.h index 4b6eeb8..a06151b 100644 --- a/src/common/eeprom.h +++ b/src/common/memory.h @@ -1,5 +1,5 @@ -#ifndef MAD_CORE_COMMON_EEPROM_H -#define MAD_CORE_COMMON_EEPROM_H +#ifndef MAD_CORE_COMMON_MEMORY_H +#define MAD_CORE_COMMON_MEMORY_H typedef struct mem_data_s mem_data_t; @@ -11,4 +11,4 @@ struct mem_data_s { int MEM_Read(mem_data_t *out); int MEM_Write(mem_data_t *in); -#endif // MAD_CORE_COMMON_EEPROM_H +#endif // MAD_CORE_COMMON_MEMORY_H