|
|
@@ -0,0 +1,551 @@ |
|
|
|
#include "ch.h" |
|
|
|
#include "hal.h" |
|
|
|
|
|
|
|
#include "eeconfig.h" |
|
|
|
|
|
|
|
/*************************************/ |
|
|
|
/* Hardware backend */ |
|
|
|
/* */ |
|
|
|
/* Code from PJRC/Teensyduino */ |
|
|
|
/*************************************/ |
|
|
|
|
|
|
|
/* Teensyduino Core Library |
|
|
|
* http://www.pjrc.com/teensy/ |
|
|
|
* Copyright (c) 2013 PJRC.COM, LLC. |
|
|
|
* |
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining |
|
|
|
* a copy of this software and associated documentation files (the |
|
|
|
* "Software"), to deal in the Software without restriction, including |
|
|
|
* without limitation the rights to use, copy, modify, merge, publish, |
|
|
|
* distribute, sublicense, and/or sell copies of the Software, and to |
|
|
|
* permit persons to whom the Software is furnished to do so, subject to |
|
|
|
* the following conditions: |
|
|
|
* |
|
|
|
* 1. The above copyright notice and this permission notice shall be |
|
|
|
* included in all copies or substantial portions of the Software. |
|
|
|
* |
|
|
|
* 2. If the Software is incorporated into a build system that allows |
|
|
|
* selection among a list of target devices, then similar target |
|
|
|
* devices manufactured by PJRC.COM must be included in the list of |
|
|
|
* target devices and selectable in the same manner. |
|
|
|
* |
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
|
|
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
|
|
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
|
|
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
|
|
* SOFTWARE. |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
#if defined(K20x) /* chip selection */ |
|
|
|
/* Teensy 3.0, 3.1, 3.2; mchck; infinity keyboard */ |
|
|
|
|
|
|
|
// The EEPROM is really RAM with a hardware-based backup system to |
|
|
|
// flash memory. Selecting a smaller size EEPROM allows more wear |
|
|
|
// leveling, for higher write endurance. If you edit this file, |
|
|
|
// set this to the smallest size your application can use. Also, |
|
|
|
// due to Freescale's implementation, writing 16 or 32 bit words |
|
|
|
// (aligned to 2 or 4 byte boundaries) has twice the endurance |
|
|
|
// compared to writing 8 bit bytes. |
|
|
|
// |
|
|
|
#define EEPROM_SIZE 32 |
|
|
|
|
|
|
|
// Writing unaligned 16 or 32 bit data is handled automatically when |
|
|
|
// this is defined, but at a cost of extra code size. Without this, |
|
|
|
// any unaligned write will cause a hard fault exception! If you're |
|
|
|
// absolutely sure all 16 and 32 bit writes will be aligned, you can |
|
|
|
// remove the extra unnecessary code. |
|
|
|
// |
|
|
|
#define HANDLE_UNALIGNED_WRITES |
|
|
|
|
|
|
|
// Minimum EEPROM Endurance |
|
|
|
// ------------------------ |
|
|
|
#if (EEPROM_SIZE == 2048) // 35000 writes/byte or 70000 writes/word |
|
|
|
#define EEESIZE 0x33 |
|
|
|
#elif (EEPROM_SIZE == 1024) // 75000 writes/byte or 150000 writes/word |
|
|
|
#define EEESIZE 0x34 |
|
|
|
#elif (EEPROM_SIZE == 512) // 155000 writes/byte or 310000 writes/word |
|
|
|
#define EEESIZE 0x35 |
|
|
|
#elif (EEPROM_SIZE == 256) // 315000 writes/byte or 630000 writes/word |
|
|
|
#define EEESIZE 0x36 |
|
|
|
#elif (EEPROM_SIZE == 128) // 635000 writes/byte or 1270000 writes/word |
|
|
|
#define EEESIZE 0x37 |
|
|
|
#elif (EEPROM_SIZE == 64) // 1275000 writes/byte or 2550000 writes/word |
|
|
|
#define EEESIZE 0x38 |
|
|
|
#elif (EEPROM_SIZE == 32) // 2555000 writes/byte or 5110000 writes/word |
|
|
|
#define EEESIZE 0x39 |
|
|
|
#endif |
|
|
|
|
|
|
|
void eeprom_initialize(void) |
|
|
|
{ |
|
|
|
uint32_t count=0; |
|
|
|
uint16_t do_flash_cmd[] = { |
|
|
|
0xf06f, 0x037f, 0x7003, 0x7803, |
|
|
|
0xf013, 0x0f80, 0xd0fb, 0x4770}; |
|
|
|
uint8_t status; |
|
|
|
|
|
|
|
if (FTFL->FCNFG & FTFL_FCNFG_RAMRDY) { |
|
|
|
// FlexRAM is configured as traditional RAM |
|
|
|
// We need to reconfigure for EEPROM usage |
|
|
|
FTFL->FCCOB0 = 0x80; // PGMPART = Program Partition Command |
|
|
|
FTFL->FCCOB4 = EEESIZE; // EEPROM Size |
|
|
|
FTFL->FCCOB5 = 0x03; // 0K for Dataflash, 32K for EEPROM backup |
|
|
|
__disable_irq(); |
|
|
|
// do_flash_cmd() must execute from RAM. Luckily the C syntax is simple... |
|
|
|
(*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&(FTFL->FSTAT)); |
|
|
|
__enable_irq(); |
|
|
|
status = FTFL->FSTAT; |
|
|
|
if (status & (FTFL_FSTAT_RDCOLERR|FTFL_FSTAT_ACCERR|FTFL_FSTAT_FPVIOL)) { |
|
|
|
FTFL->FSTAT = (status & (FTFL_FSTAT_RDCOLERR|FTFL_FSTAT_ACCERR|FTFL_FSTAT_FPVIOL)); |
|
|
|
return; // error |
|
|
|
} |
|
|
|
} |
|
|
|
// wait for eeprom to become ready (is this really necessary?) |
|
|
|
while (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) { |
|
|
|
if (++count > 20000) break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
#define FlexRAM ((uint8_t *)0x14000000) |
|
|
|
|
|
|
|
uint8_t eeprom_read_byte(const uint8_t *addr) |
|
|
|
{ |
|
|
|
uint32_t offset = (uint32_t)addr; |
|
|
|
if (offset >= EEPROM_SIZE) return 0; |
|
|
|
if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); |
|
|
|
return FlexRAM[offset]; |
|
|
|
} |
|
|
|
|
|
|
|
uint16_t eeprom_read_word(const uint16_t *addr) |
|
|
|
{ |
|
|
|
uint32_t offset = (uint32_t)addr; |
|
|
|
if (offset >= EEPROM_SIZE-1) return 0; |
|
|
|
if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); |
|
|
|
return *(uint16_t *)(&FlexRAM[offset]); |
|
|
|
} |
|
|
|
|
|
|
|
uint32_t eeprom_read_dword(const uint32_t *addr) |
|
|
|
{ |
|
|
|
uint32_t offset = (uint32_t)addr; |
|
|
|
if (offset >= EEPROM_SIZE-3) return 0; |
|
|
|
if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); |
|
|
|
return *(uint32_t *)(&FlexRAM[offset]); |
|
|
|
} |
|
|
|
|
|
|
|
void eeprom_read_block(void *buf, const void *addr, uint32_t len) |
|
|
|
{ |
|
|
|
uint32_t offset = (uint32_t)addr; |
|
|
|
uint8_t *dest = (uint8_t *)buf; |
|
|
|
uint32_t end = offset + len; |
|
|
|
|
|
|
|
if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); |
|
|
|
if (end > EEPROM_SIZE) end = EEPROM_SIZE; |
|
|
|
while (offset < end) { |
|
|
|
*dest++ = FlexRAM[offset++]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
int eeprom_is_ready(void) |
|
|
|
{ |
|
|
|
return (FTFL->FCNFG & FTFL_FCNFG_EEERDY) ? 1 : 0; |
|
|
|
} |
|
|
|
|
|
|
|
static void flexram_wait(void) |
|
|
|
{ |
|
|
|
while (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) { |
|
|
|
// TODO: timeout |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void eeprom_write_byte(uint8_t *addr, uint8_t value) |
|
|
|
{ |
|
|
|
uint32_t offset = (uint32_t)addr; |
|
|
|
|
|
|
|
if (offset >= EEPROM_SIZE) return; |
|
|
|
if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); |
|
|
|
if (FlexRAM[offset] != value) { |
|
|
|
FlexRAM[offset] = value; |
|
|
|
flexram_wait(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void eeprom_write_word(uint16_t *addr, uint16_t value) |
|
|
|
{ |
|
|
|
uint32_t offset = (uint32_t)addr; |
|
|
|
|
|
|
|
if (offset >= EEPROM_SIZE-1) return; |
|
|
|
if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); |
|
|
|
#ifdef HANDLE_UNALIGNED_WRITES |
|
|
|
if ((offset & 1) == 0) { |
|
|
|
#endif |
|
|
|
if (*(uint16_t *)(&FlexRAM[offset]) != value) { |
|
|
|
*(uint16_t *)(&FlexRAM[offset]) = value; |
|
|
|
flexram_wait(); |
|
|
|
} |
|
|
|
#ifdef HANDLE_UNALIGNED_WRITES |
|
|
|
} else { |
|
|
|
if (FlexRAM[offset] != value) { |
|
|
|
FlexRAM[offset] = value; |
|
|
|
flexram_wait(); |
|
|
|
} |
|
|
|
if (FlexRAM[offset + 1] != (value >> 8)) { |
|
|
|
FlexRAM[offset + 1] = value >> 8; |
|
|
|
flexram_wait(); |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
void eeprom_write_dword(uint32_t *addr, uint32_t value) |
|
|
|
{ |
|
|
|
uint32_t offset = (uint32_t)addr; |
|
|
|
|
|
|
|
if (offset >= EEPROM_SIZE-3) return; |
|
|
|
if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); |
|
|
|
#ifdef HANDLE_UNALIGNED_WRITES |
|
|
|
switch (offset & 3) { |
|
|
|
case 0: |
|
|
|
#endif |
|
|
|
if (*(uint32_t *)(&FlexRAM[offset]) != value) { |
|
|
|
*(uint32_t *)(&FlexRAM[offset]) = value; |
|
|
|
flexram_wait(); |
|
|
|
} |
|
|
|
return; |
|
|
|
#ifdef HANDLE_UNALIGNED_WRITES |
|
|
|
case 2: |
|
|
|
if (*(uint16_t *)(&FlexRAM[offset]) != value) { |
|
|
|
*(uint16_t *)(&FlexRAM[offset]) = value; |
|
|
|
flexram_wait(); |
|
|
|
} |
|
|
|
if (*(uint16_t *)(&FlexRAM[offset + 2]) != (value >> 16)) { |
|
|
|
*(uint16_t *)(&FlexRAM[offset + 2]) = value >> 16; |
|
|
|
flexram_wait(); |
|
|
|
} |
|
|
|
return; |
|
|
|
default: |
|
|
|
if (FlexRAM[offset] != value) { |
|
|
|
FlexRAM[offset] = value; |
|
|
|
flexram_wait(); |
|
|
|
} |
|
|
|
if (*(uint16_t *)(&FlexRAM[offset + 1]) != (value >> 8)) { |
|
|
|
*(uint16_t *)(&FlexRAM[offset + 1]) = value >> 8; |
|
|
|
flexram_wait(); |
|
|
|
} |
|
|
|
if (FlexRAM[offset + 3] != (value >> 24)) { |
|
|
|
FlexRAM[offset + 3] = value >> 24; |
|
|
|
flexram_wait(); |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
void eeprom_write_block(const void *buf, void *addr, uint32_t len) |
|
|
|
{ |
|
|
|
uint32_t offset = (uint32_t)addr; |
|
|
|
const uint8_t *src = (const uint8_t *)buf; |
|
|
|
|
|
|
|
if (offset >= EEPROM_SIZE) return; |
|
|
|
if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); |
|
|
|
if (len >= EEPROM_SIZE) len = EEPROM_SIZE; |
|
|
|
if (offset + len >= EEPROM_SIZE) len = EEPROM_SIZE - offset; |
|
|
|
while (len > 0) { |
|
|
|
uint32_t lsb = offset & 3; |
|
|
|
if (lsb == 0 && len >= 4) { |
|
|
|
// write aligned 32 bits |
|
|
|
uint32_t val32; |
|
|
|
val32 = *src++; |
|
|
|
val32 |= (*src++ << 8); |
|
|
|
val32 |= (*src++ << 16); |
|
|
|
val32 |= (*src++ << 24); |
|
|
|
if (*(uint32_t *)(&FlexRAM[offset]) != val32) { |
|
|
|
*(uint32_t *)(&FlexRAM[offset]) = val32; |
|
|
|
flexram_wait(); |
|
|
|
} |
|
|
|
offset += 4; |
|
|
|
len -= 4; |
|
|
|
} else if ((lsb == 0 || lsb == 2) && len >= 2) { |
|
|
|
// write aligned 16 bits |
|
|
|
uint16_t val16; |
|
|
|
val16 = *src++; |
|
|
|
val16 |= (*src++ << 8); |
|
|
|
if (*(uint16_t *)(&FlexRAM[offset]) != val16) { |
|
|
|
*(uint16_t *)(&FlexRAM[offset]) = val16; |
|
|
|
flexram_wait(); |
|
|
|
} |
|
|
|
offset += 2; |
|
|
|
len -= 2; |
|
|
|
} else { |
|
|
|
// write 8 bits |
|
|
|
uint8_t val8 = *src++; |
|
|
|
if (FlexRAM[offset] != val8) { |
|
|
|
FlexRAM[offset] = val8; |
|
|
|
flexram_wait(); |
|
|
|
} |
|
|
|
offset++; |
|
|
|
len--; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
void do_flash_cmd(volatile uint8_t *fstat) |
|
|
|
{ |
|
|
|
*fstat = 0x80; |
|
|
|
while ((*fstat & 0x80) == 0) ; // wait |
|
|
|
} |
|
|
|
00000000 <do_flash_cmd>: |
|
|
|
0: f06f 037f mvn.w r3, #127 ; 0x7f |
|
|
|
4: 7003 strb r3, [r0, #0] |
|
|
|
6: 7803 ldrb r3, [r0, #0] |
|
|
|
8: f013 0f80 tst.w r3, #128 ; 0x80 |
|
|
|
c: d0fb beq.n 6 <do_flash_cmd+0x6> |
|
|
|
e: 4770 bx lr |
|
|
|
*/ |
|
|
|
|
|
|
|
#elif defined(KL2x) /* chip selection */ |
|
|
|
/* Teensy LC (emulated) */ |
|
|
|
|
|
|
|
#define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0)) |
|
|
|
|
|
|
|
extern uint32_t __eeprom_workarea_start__; |
|
|
|
extern uint32_t __eeprom_workarea_end__; |
|
|
|
|
|
|
|
#define EEPROM_SIZE 128 |
|
|
|
|
|
|
|
static uint32_t flashend = 0; |
|
|
|
|
|
|
|
void eeprom_initialize(void) |
|
|
|
{ |
|
|
|
const uint16_t *p = (uint16_t *)SYMVAL(__eeprom_workarea_start__); |
|
|
|
|
|
|
|
do { |
|
|
|
if (*p++ == 0xFFFF) { |
|
|
|
flashend = (uint32_t)(p - 2); |
|
|
|
return; |
|
|
|
} |
|
|
|
} while (p < (uint16_t *)SYMVAL(__eeprom_workarea_end__)); |
|
|
|
flashend = (uint32_t)((uint16_t *)SYMVAL(__eeprom_workarea_end__) - 1); |
|
|
|
} |
|
|
|
|
|
|
|
uint8_t eeprom_read_byte(const uint8_t *addr) |
|
|
|
{ |
|
|
|
uint32_t offset = (uint32_t)addr; |
|
|
|
const uint16_t *p = (uint16_t *)SYMVAL(__eeprom_workarea_start__); |
|
|
|
const uint16_t *end = (const uint16_t *)((uint32_t)flashend); |
|
|
|
uint16_t val; |
|
|
|
uint8_t data=0xFF; |
|
|
|
|
|
|
|
if (!end) { |
|
|
|
eeprom_initialize(); |
|
|
|
end = (const uint16_t *)((uint32_t)flashend); |
|
|
|
} |
|
|
|
if (offset < EEPROM_SIZE) { |
|
|
|
while (p <= end) { |
|
|
|
val = *p++; |
|
|
|
if ((val & 255) == offset) data = val >> 8; |
|
|
|
} |
|
|
|
} |
|
|
|
return data; |
|
|
|
} |
|
|
|
|
|
|
|
static void flash_write(const uint16_t *code, uint32_t addr, uint32_t data) |
|
|
|
{ |
|
|
|
// with great power comes great responsibility.... |
|
|
|
uint32_t stat; |
|
|
|
*(uint32_t *)&(FTFA->FCCOB3) = 0x06000000 | (addr & 0x00FFFFFC); |
|
|
|
*(uint32_t *)&(FTFA->FCCOB7) = data; |
|
|
|
__disable_irq(); |
|
|
|
(*((void (*)(volatile uint8_t *))((uint32_t)code | 1)))(&(FTFA->FSTAT)); |
|
|
|
__enable_irq(); |
|
|
|
stat = FTFA->FSTAT & (FTFA_FSTAT_RDCOLERR|FTFA_FSTAT_ACCERR|FTFA_FSTAT_FPVIOL); |
|
|
|
if (stat) { |
|
|
|
FTFA->FSTAT = stat; |
|
|
|
} |
|
|
|
MCM->PLACR |= MCM_PLACR_CFCC; |
|
|
|
} |
|
|
|
|
|
|
|
void eeprom_write_byte(uint8_t *addr, uint8_t data) |
|
|
|
{ |
|
|
|
uint32_t offset = (uint32_t)addr; |
|
|
|
const uint16_t *p, *end = (const uint16_t *)((uint32_t)flashend); |
|
|
|
uint32_t i, val, flashaddr; |
|
|
|
uint16_t do_flash_cmd[] = { |
|
|
|
0x2380, 0x7003, 0x7803, 0xb25b, 0x2b00, 0xdafb, 0x4770}; |
|
|
|
uint8_t buf[EEPROM_SIZE]; |
|
|
|
|
|
|
|
if (offset >= EEPROM_SIZE) return; |
|
|
|
if (!end) { |
|
|
|
eeprom_initialize(); |
|
|
|
end = (const uint16_t *)((uint32_t)flashend); |
|
|
|
} |
|
|
|
if (++end < (uint16_t *)SYMVAL(__eeprom_workarea_end__)) { |
|
|
|
val = (data << 8) | offset; |
|
|
|
flashaddr = (uint32_t)end; |
|
|
|
flashend = flashaddr; |
|
|
|
if ((flashaddr & 2) == 0) { |
|
|
|
val |= 0xFFFF0000; |
|
|
|
} else { |
|
|
|
val <<= 16; |
|
|
|
val |= 0x0000FFFF; |
|
|
|
} |
|
|
|
flash_write(do_flash_cmd, flashaddr, val); |
|
|
|
} else { |
|
|
|
for (i=0; i < EEPROM_SIZE; i++) { |
|
|
|
buf[i] = 0xFF; |
|
|
|
} |
|
|
|
for (p = (uint16_t *)SYMVAL(__eeprom_workarea_start__); p < (uint16_t *)SYMVAL(__eeprom_workarea_end__); p++) { |
|
|
|
val = *p; |
|
|
|
if ((val & 255) < EEPROM_SIZE) { |
|
|
|
buf[val & 255] = val >> 8; |
|
|
|
} |
|
|
|
} |
|
|
|
buf[offset] = data; |
|
|
|
for (flashaddr=(uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_start__); flashaddr < (uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_end__); flashaddr += 1024) { |
|
|
|
*(uint32_t *)&(FTFA->FCCOB3) = 0x09000000 | flashaddr; |
|
|
|
__disable_irq(); |
|
|
|
(*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&(FTFA->FSTAT)); |
|
|
|
__enable_irq(); |
|
|
|
val = FTFA->FSTAT & (FTFA_FSTAT_RDCOLERR|FTFA_FSTAT_ACCERR|FTFA_FSTAT_FPVIOL);; |
|
|
|
if (val) FTFA->FSTAT = val; |
|
|
|
MCM->PLACR |= MCM_PLACR_CFCC; |
|
|
|
} |
|
|
|
flashaddr=(uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_start__); |
|
|
|
for (i=0; i < EEPROM_SIZE; i++) { |
|
|
|
if (buf[i] == 0xFF) continue; |
|
|
|
if ((flashaddr & 2) == 0) { |
|
|
|
val = (buf[i] << 8) | i; |
|
|
|
} else { |
|
|
|
val = val | (buf[i] << 24) | (i << 16); |
|
|
|
flash_write(do_flash_cmd, flashaddr, val); |
|
|
|
} |
|
|
|
flashaddr += 2; |
|
|
|
} |
|
|
|
flashend = flashaddr; |
|
|
|
if ((flashaddr & 2)) { |
|
|
|
val |= 0xFFFF0000; |
|
|
|
flash_write(do_flash_cmd, flashaddr, val); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
void do_flash_cmd(volatile uint8_t *fstat) |
|
|
|
{ |
|
|
|
*fstat = 0x80; |
|
|
|
while ((*fstat & 0x80) == 0) ; // wait |
|
|
|
} |
|
|
|
00000000 <do_flash_cmd>: |
|
|
|
0: 2380 movs r3, #128 ; 0x80 |
|
|
|
2: 7003 strb r3, [r0, #0] |
|
|
|
4: 7803 ldrb r3, [r0, #0] |
|
|
|
6: b25b sxtb r3, r3 |
|
|
|
8: 2b00 cmp r3, #0 |
|
|
|
a: dafb bge.n 4 <do_flash_cmd+0x4> |
|
|
|
c: 4770 bx lr |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
uint16_t eeprom_read_word(const uint16_t *addr) |
|
|
|
{ |
|
|
|
const uint8_t *p = (const uint8_t *)addr; |
|
|
|
return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8); |
|
|
|
} |
|
|
|
|
|
|
|
uint32_t eeprom_read_dword(const uint32_t *addr) |
|
|
|
{ |
|
|
|
const uint8_t *p = (const uint8_t *)addr; |
|
|
|
return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8) |
|
|
|
| (eeprom_read_byte(p+2) << 16) | (eeprom_read_byte(p+3) << 24); |
|
|
|
} |
|
|
|
|
|
|
|
void eeprom_read_block(void *buf, const void *addr, uint32_t len) |
|
|
|
{ |
|
|
|
const uint8_t *p = (const uint8_t *)addr; |
|
|
|
uint8_t *dest = (uint8_t *)buf; |
|
|
|
while (len--) { |
|
|
|
*dest++ = eeprom_read_byte(p++); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
int eeprom_is_ready(void) |
|
|
|
{ |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
void eeprom_write_word(uint16_t *addr, uint16_t value) |
|
|
|
{ |
|
|
|
uint8_t *p = (uint8_t *)addr; |
|
|
|
eeprom_write_byte(p++, value); |
|
|
|
eeprom_write_byte(p, value >> 8); |
|
|
|
} |
|
|
|
|
|
|
|
void eeprom_write_dword(uint32_t *addr, uint32_t value) |
|
|
|
{ |
|
|
|
uint8_t *p = (uint8_t *)addr; |
|
|
|
eeprom_write_byte(p++, value); |
|
|
|
eeprom_write_byte(p++, value >> 8); |
|
|
|
eeprom_write_byte(p++, value >> 16); |
|
|
|
eeprom_write_byte(p, value >> 24); |
|
|
|
} |
|
|
|
|
|
|
|
void eeprom_write_block(const void *buf, void *addr, uint32_t len) |
|
|
|
{ |
|
|
|
uint8_t *p = (uint8_t *)addr; |
|
|
|
const uint8_t *src = (const uint8_t *)buf; |
|
|
|
while (len--) { |
|
|
|
eeprom_write_byte(p++, *src++); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
#else |
|
|
|
#error EEPROM support not implemented for your chip |
|
|
|
#endif /* chip selection */ |
|
|
|
|
|
|
|
|
|
|
|
/*****************/ |
|
|
|
/* TMK functions */ |
|
|
|
/*****************/ |
|
|
|
|
|
|
|
void eeconfig_init(void) |
|
|
|
{ |
|
|
|
eeprom_write_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER); |
|
|
|
eeprom_write_byte(EECONFIG_DEBUG, 0); |
|
|
|
eeprom_write_byte(EECONFIG_DEFAULT_LAYER, 0); |
|
|
|
eeprom_write_byte(EECONFIG_KEYMAP, 0); |
|
|
|
eeprom_write_byte(EECONFIG_MOUSEKEY_ACCEL, 0); |
|
|
|
#ifdef BACKLIGHT_ENABLE |
|
|
|
eeprom_write_byte(EECONFIG_BACKLIGHT, 0); |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
void eeconfig_enable(void) |
|
|
|
{ |
|
|
|
eeprom_write_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER); |
|
|
|
} |
|
|
|
|
|
|
|
void eeconfig_disable(void) |
|
|
|
{ |
|
|
|
eeprom_write_word(EECONFIG_MAGIC, 0xFFFF); |
|
|
|
} |
|
|
|
|
|
|
|
bool eeconfig_is_enabled(void) |
|
|
|
{ |
|
|
|
return (eeprom_read_word(EECONFIG_MAGIC) == EECONFIG_MAGIC_NUMBER); |
|
|
|
} |
|
|
|
|
|
|
|
uint8_t eeconfig_read_debug(void) { return eeprom_read_byte(EECONFIG_DEBUG); } |
|
|
|
void eeconfig_write_debug(uint8_t val) { eeprom_write_byte(EECONFIG_DEBUG, val); } |
|
|
|
|
|
|
|
uint8_t eeconfig_read_default_layer(void) { return eeprom_read_byte(EECONFIG_DEFAULT_LAYER); } |
|
|
|
void eeconfig_write_default_layer(uint8_t val) { eeprom_write_byte(EECONFIG_DEFAULT_LAYER, val); } |
|
|
|
|
|
|
|
uint8_t eeconfig_read_keymap(void) { return eeprom_read_byte(EECONFIG_KEYMAP); } |
|
|
|
void eeconfig_write_keymap(uint8_t val) { eeprom_write_byte(EECONFIG_KEYMAP, val); } |
|
|
|
|
|
|
|
#ifdef BACKLIGHT_ENABLE |
|
|
|
uint8_t eeconfig_read_backlight(void) { return eeprom_read_byte(EECONFIG_BACKLIGHT); } |
|
|
|
void eeconfig_write_backlight(uint8_t val) { eeprom_write_byte(EECONFIG_BACKLIGHT, val); } |
|
|
|
#endif |