|
|
|
|
|
|
|
|
#include <stdint.h> |
|
|
#include <stdint.h> |
|
|
//#include "HardwareSerial.h" |
|
|
//#include "HardwareSerial.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(KINETISK) |
|
|
|
|
|
|
|
|
// The EEPROM is really RAM with a hardware-based backup system to |
|
|
// The EEPROM is really RAM with a hardware-based backup system to |
|
|
// flash memory. Selecting a smaller size EEPROM allows more wear |
|
|
// flash memory. Selecting a smaller size EEPROM allows more wear |
|
|
// leveling, for higher write endurance. If you edit this file, |
|
|
// leveling, for higher write endurance. If you edit this file, |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
/* |
|
|
void do_flash_cmd(volatile uint8_t *fstat) |
|
|
void do_flash_cmd(volatile uint8_t *fstat) |
|
|
{ |
|
|
{ |
|
|
|
|
|
|
|
|
e: 4770 bx lr |
|
|
e: 4770 bx lr |
|
|
*/ |
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
#elif defined(KINETISL) |
|
|
|
|
|
|
|
|
|
|
|
#define EEPROM_SIZE 128 |
|
|
|
|
|
|
|
|
|
|
|
#define FLASH_BEGIN (uint16_t *)63488 |
|
|
|
|
|
#define FLASH_END (uint16_t *)65536 |
|
|
|
|
|
static uint16_t flashend = 0; |
|
|
|
|
|
|
|
|
|
|
|
void eeprom_initialize(void) |
|
|
|
|
|
{ |
|
|
|
|
|
const uint16_t *p = FLASH_BEGIN; |
|
|
|
|
|
|
|
|
|
|
|
do { |
|
|
|
|
|
if (*p++ == 0xFFFF) { |
|
|
|
|
|
flashend = (uint32_t)(p - 2); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
} while (p < FLASH_END); |
|
|
|
|
|
flashend = (uint32_t)(FLASH_END - 1); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
uint8_t eeprom_read_byte(const uint8_t *addr) |
|
|
|
|
|
{ |
|
|
|
|
|
uint32_t offset = (uint32_t)addr; |
|
|
|
|
|
const uint16_t *p = FLASH_BEGIN; |
|
|
|
|
|
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 *)&FTFL_FCCOB3 = 0x06000000 | (addr & 0x00FFFFFC); |
|
|
|
|
|
*(uint32_t *)&FTFL_FCCOB7 = data; |
|
|
|
|
|
__disable_irq(); |
|
|
|
|
|
(*((void (*)(volatile uint8_t *))((uint32_t)code | 1)))(&FTFL_FSTAT); |
|
|
|
|
|
__enable_irq(); |
|
|
|
|
|
stat = FTFL_FSTAT & 0x70; |
|
|
|
|
|
if (stat) { |
|
|
|
|
|
FTFL_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 < FLASH_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 = FLASH_BEGIN; p < FLASH_END; p++) { |
|
|
|
|
|
val = *p; |
|
|
|
|
|
if ((val & 255) < EEPROM_SIZE) { |
|
|
|
|
|
buf[val & 255] = val >> 8; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
buf[offset] = data; |
|
|
|
|
|
for (flashaddr=(uint32_t)FLASH_BEGIN; flashaddr < (uint32_t)FLASH_END; flashaddr += 1024) { |
|
|
|
|
|
*(uint32_t *)&FTFL_FCCOB3 = 0x09000000 | flashaddr; |
|
|
|
|
|
__disable_irq(); |
|
|
|
|
|
(*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&FTFL_FSTAT); |
|
|
|
|
|
__enable_irq(); |
|
|
|
|
|
val = FTFL_FSTAT & 0x70; |
|
|
|
|
|
if (val) FTFL_FSTAT = val; |
|
|
|
|
|
MCM_PLACR |= MCM_PLACR_CFCC; |
|
|
|
|
|
} |
|
|
|
|
|
flashaddr=(uint32_t)FLASH_BEGIN; |
|
|
|
|
|
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++); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif // KINETISL |