aboutsummaryrefslogtreecommitdiffstats
path: root/fw/eeprom.c
diff options
context:
space:
mode:
Diffstat (limited to 'fw/eeprom.c')
-rw-r--r--fw/eeprom.c103
1 files changed, 74 insertions, 29 deletions
diff --git a/fw/eeprom.c b/fw/eeprom.c
index 567cdc1..e832fa0 100644
--- a/fw/eeprom.c
+++ b/fw/eeprom.c
@@ -12,6 +12,12 @@
// 16-byte page ('C' variant)
#define PAGE_SIZE 16u
+// Write cycle time = 5ms
+// 5ms / (4*Tosc) = 60000
+#define WRITE_DELAY 60000u
+
+#define BAILOUT 10u
+
// Commands
enum {
CMD_READ = 0x03,
@@ -30,42 +36,52 @@ enum {
STATUS_BP1 = 0x8, // block protection 1
};
-// Timing
-enum {
- TIME_WRITE_CYCLE_MS = 5,
-};
+static U8
+readStatus(void) {
+ U8 status;
-void
-eepromInit(void) {
- EEPROM_CS_TRIS = OUT;
+ EEPROM_CS = 0;
+ (void)spiTx(CMD_READ_STATUS);
+ status = spiTx(0x00);
EEPROM_CS = 1;
-
- eepromWriteDisable();
+ return status;
}
-void
-eepromWriteEnable(void) {
+static Status
+writeEnable(void) {
EEPROM_CS = 0;
(void)spiTx(CMD_WRITE_ENABLE);
EEPROM_CS = 1;
+
+ return (readStatus() & STATUS_WEL) ? OK : FAIL;
}
-void
-eepromWriteDisable(void) {
+static void
+writeDisable(void) {
EEPROM_CS = 0;
(void)spiTx(CMD_WRITE_DISABLE);
EEPROM_CS = 1;
}
-static bool
-isWriteInProgress(void) {
- U8 status;
-
- EEPROM_CS = 0;
- (void)spiTx(CMD_READ_STATUS);
- status = spiTx(0x00);
+void
+eepromInit(void) {
+ EEPROM_CS_TRIS = OUT;
EEPROM_CS = 1;
- return status & STATUS_WIP;
+
+ writeDisable();
+}
+
+// Wait for pending write to finish
+static Status
+waitForWrite(void) {
+ U8 status, k;
+
+ status = readStatus();
+ for (k = 0u; (status & STATUS_WIP) && (k < BAILOUT); k++) {
+ _delay(WRITE_DELAY);
+ status = readStatus();
+ }
+ return (k < BAILOUT) ? OK : FAIL;
}
static void
@@ -79,12 +95,24 @@ isPageStart(U16 addr) {
return (addr.lo % PAGE_SIZE) == 0;
}
-void
+Status
eepromWrite(U16 addr, U8 *data, U8 size) {
- while (isWriteInProgress()) {} // wait for previous write to finish
+ Status status;
- EEPROM_CS = 0; // pull chip-select low
+ // Wait for pending write to finish
+ status = waitForWrite();
+ if (status != OK) {
+ return FAIL; // timed out
+ }
+
+ // Set write-enable
+ status = writeEnable();
+ if (status != OK) {
+ return FAIL;
+ }
+ // Write
+ EEPROM_CS = 0;
(void)spiTx(CMD_WRITE);
spiTxAddr(addr);
while (size--) {
@@ -96,7 +124,14 @@ eepromWrite(U16 addr, U8 *data, U8 size) {
if (isPageStart(addr) && size) {
// Write current page to memory
EEPROM_CS = 1;
- while (isWriteInProgress()) {}
+ status = waitForWrite();
+ if (status != OK) {
+ return FAIL; // timed out
+ }
+ status = writeEnable();
+ if (status != OK) {
+ return FAIL;
+ }
EEPROM_CS = 0;
// Start next page
@@ -104,20 +139,30 @@ eepromWrite(U16 addr, U8 *data, U8 size) {
spiTxAddr(addr);
}
}
+ EEPROM_CS = 1;
- EEPROM_CS = 1; // release chip-select
+ return OK;
}
-void
+Status
eepromRead(U16 addr, U8 *data, U8 size) {
- EEPROM_CS = 0; // pull chip-select low
+ Status status;
+
+ // Wait for pending write to finish
+ status = waitForWrite();
+ if (status != OK) {
+ return FAIL; // timed out
+ }
+ // Read
+ EEPROM_CS = 0;
(void)spiTx(CMD_READ);
spiTxAddr(addr);
while (size--) {
*data = spiTx(0x00);
data++;
}
+ EEPROM_CS = 1;
- EEPROM_CS = 1; // release chip-select
+ return OK;
}