|
|
|
|
|
|
|
|
/* Teensyduino Core Library |
|
|
/* Teensyduino Core Library |
|
|
* http://www.pjrc.com/teensy/ |
|
|
* http://www.pjrc.com/teensy/ |
|
|
* Copyright (c) 2013 PJRC.COM, LLC. |
|
|
|
|
|
|
|
|
* Copyright (c) 2016 PJRC.COM, LLC. |
|
|
* |
|
|
* |
|
|
* Permission is hereby granted, free of charge, to any person obtaining |
|
|
* Permission is hereby granted, free of charge, to any person obtaining |
|
|
* a copy of this software and associated documentation files (the |
|
|
* a copy of this software and associated documentation files (the |
|
|
|
|
|
|
|
|
#if defined(__MK20DX128__) || defined(__MK20DX256__) |
|
|
#if defined(__MK20DX128__) || defined(__MK20DX256__) |
|
|
#define EEPROM_MAX 2048 |
|
|
#define EEPROM_MAX 2048 |
|
|
#define EEPARTITION 0x03 // all 32K dataflash for EEPROM, none for Data |
|
|
#define EEPARTITION 0x03 // all 32K dataflash for EEPROM, none for Data |
|
|
|
|
|
#define EEESPLIT 0x30 // must be 0x30 on these chips |
|
|
#elif defined(__MK64FX512__) |
|
|
#elif defined(__MK64FX512__) |
|
|
#define EEPROM_MAX 4096 |
|
|
#define EEPROM_MAX 4096 |
|
|
#define EEPARTITION 0x04 // 64K dataflash for EEPROM, 64K for Data |
|
|
|
|
|
|
|
|
#define EEPARTITION 0x05 // all 128K dataflash for EEPROM |
|
|
|
|
|
#define EEESPLIT 0x10 // best endurance: 0x00 = first 12%, 0x10 = first 25%, 0x30 = all equal |
|
|
#elif defined(__MK66FX1M0__) |
|
|
#elif defined(__MK66FX1M0__) |
|
|
#define EEPROM_MAX 4096 |
|
|
#define EEPROM_MAX 4096 |
|
|
#define EEPARTITION 0x05 // 128K dataflash for EEPROM, 128K for Data |
|
|
#define EEPARTITION 0x05 // 128K dataflash for EEPROM, 128K for Data |
|
|
|
|
|
#define EEESPLIT 0x10 // best endurance: 0x00 = first 12%, 0x10 = first 25%, 0x30 = all equal |
|
|
#elif defined(__MKL26Z64__) |
|
|
#elif defined(__MKL26Z64__) |
|
|
#define EEPROM_MAX 255 |
|
|
#define EEPROM_MAX 255 |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if E2END < 32 |
|
|
#if E2END < 32 |
|
|
#define EEPROM_SIZE 32 |
|
|
#define EEPROM_SIZE 32 |
|
|
#define EEESIZE 0x39 |
|
|
|
|
|
|
|
|
#define EEESIZE 0x09 |
|
|
#elif E2END < 64 |
|
|
#elif E2END < 64 |
|
|
#define EEPROM_SIZE 64 |
|
|
#define EEPROM_SIZE 64 |
|
|
#define EEESIZE 0x38 |
|
|
|
|
|
|
|
|
#define EEESIZE 0x08 |
|
|
#elif E2END < 128 |
|
|
#elif E2END < 128 |
|
|
#define EEPROM_SIZE 128 |
|
|
#define EEPROM_SIZE 128 |
|
|
#define EEESIZE 0x37 |
|
|
|
|
|
|
|
|
#define EEESIZE 0x07 |
|
|
#elif E2END < 256 |
|
|
#elif E2END < 256 |
|
|
#define EEPROM_SIZE 256 |
|
|
#define EEPROM_SIZE 256 |
|
|
#define EEESIZE 0x36 |
|
|
|
|
|
|
|
|
#define EEESIZE 0x06 |
|
|
#elif E2END < 512 |
|
|
#elif E2END < 512 |
|
|
#define EEPROM_SIZE 512 |
|
|
#define EEPROM_SIZE 512 |
|
|
#define EEESIZE 0x35 |
|
|
|
|
|
|
|
|
#define EEESIZE 0x05 |
|
|
#elif E2END < 1024 |
|
|
#elif E2END < 1024 |
|
|
#define EEPROM_SIZE 1024 |
|
|
#define EEPROM_SIZE 1024 |
|
|
#define EEESIZE 0x34 |
|
|
|
|
|
|
|
|
#define EEESIZE 0x04 |
|
|
#elif E2END < 2048 |
|
|
#elif E2END < 2048 |
|
|
#define EEPROM_SIZE 2048 |
|
|
#define EEPROM_SIZE 2048 |
|
|
#define EEESIZE 0x33 |
|
|
|
|
|
|
|
|
#define EEESIZE 0x03 |
|
|
#elif E2END < 4096 |
|
|
#elif E2END < 4096 |
|
|
#define EEPROM_SIZE 4096 |
|
|
#define EEPROM_SIZE 4096 |
|
|
#define EEESIZE 0x32 |
|
|
|
|
|
|
|
|
#define EEESIZE 0x02 |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
// Writing unaligned 16 or 32 bit data is handled automatically when |
|
|
// Writing unaligned 16 or 32 bit data is handled automatically when |
|
|
|
|
|
|
|
|
uint8_t status; |
|
|
uint8_t status; |
|
|
|
|
|
|
|
|
if (FTFL_FCNFG & FTFL_FCNFG_RAMRDY) { |
|
|
if (FTFL_FCNFG & FTFL_FCNFG_RAMRDY) { |
|
|
|
|
|
uint8_t stat = FTFL_FSTAT & 0x70; |
|
|
|
|
|
if (stat) FTFL_FSTAT = stat; |
|
|
// FlexRAM is configured as traditional RAM |
|
|
// FlexRAM is configured as traditional RAM |
|
|
// We need to reconfigure for EEPROM usage |
|
|
// We need to reconfigure for EEPROM usage |
|
|
FTFL_FCCOB0 = 0x80; // PGMPART = Program Partition Command |
|
|
FTFL_FCCOB0 = 0x80; // PGMPART = Program Partition Command |
|
|
FTFL_FCCOB4 = EEESIZE; // EEPROM Size |
|
|
|
|
|
|
|
|
FTFL_FCCOB3 = 0; |
|
|
|
|
|
FTFL_FCCOB4 = EEESPLIT | EEESIZE; |
|
|
FTFL_FCCOB5 = EEPARTITION; |
|
|
FTFL_FCCOB5 = EEPARTITION; |
|
|
__disable_irq(); |
|
|
__disable_irq(); |
|
|
// do_flash_cmd() must execute from RAM. Luckily the C syntax is simple... |
|
|
// do_flash_cmd() must execute from RAM. Luckily the C syntax is simple... |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
// wait for eeprom to become ready (is this really necessary?) |
|
|
// wait for eeprom to become ready (is this really necessary?) |
|
|
while (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) { |
|
|
while (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) { |
|
|
if (++count > 20000) break; |
|
|
|
|
|
|
|
|
if (++count > 200000) break; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
#define FlexRAM ((uint8_t *)0x14000000) |
|
|
|
|
|
|
|
|
#define FlexRAM ((volatile uint8_t *)0x14000000) |
|
|
|
|
|
|
|
|
uint8_t eeprom_read_byte(const uint8_t *addr) |
|
|
uint8_t eeprom_read_byte(const uint8_t *addr) |
|
|
{ |
|
|
{ |
|
|
|
|
|
|
|
|
if (offset >= EEPROM_SIZE) return; |
|
|
if (offset >= EEPROM_SIZE) return; |
|
|
if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); |
|
|
if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); |
|
|
if (FlexRAM[offset] != value) { |
|
|
if (FlexRAM[offset] != value) { |
|
|
|
|
|
uint8_t stat = FTFL_FSTAT & 0x70; |
|
|
|
|
|
if (stat) FTFL_FSTAT = stat; |
|
|
FlexRAM[offset] = value; |
|
|
FlexRAM[offset] = value; |
|
|
flexram_wait(); |
|
|
flexram_wait(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if ((offset & 1) == 0) { |
|
|
if ((offset & 1) == 0) { |
|
|
#endif |
|
|
#endif |
|
|
if (*(uint16_t *)(&FlexRAM[offset]) != value) { |
|
|
if (*(uint16_t *)(&FlexRAM[offset]) != value) { |
|
|
|
|
|
uint8_t stat = FTFL_FSTAT & 0x70; |
|
|
|
|
|
if (stat) FTFL_FSTAT = stat; |
|
|
*(uint16_t *)(&FlexRAM[offset]) = value; |
|
|
*(uint16_t *)(&FlexRAM[offset]) = value; |
|
|
flexram_wait(); |
|
|
flexram_wait(); |
|
|
} |
|
|
} |
|
|
#ifdef HANDLE_UNALIGNED_WRITES |
|
|
#ifdef HANDLE_UNALIGNED_WRITES |
|
|
} else { |
|
|
} else { |
|
|
if (FlexRAM[offset] != value) { |
|
|
if (FlexRAM[offset] != value) { |
|
|
|
|
|
uint8_t stat = FTFL_FSTAT & 0x70; |
|
|
|
|
|
if (stat) FTFL_FSTAT = stat; |
|
|
FlexRAM[offset] = value; |
|
|
FlexRAM[offset] = value; |
|
|
flexram_wait(); |
|
|
flexram_wait(); |
|
|
} |
|
|
} |
|
|
if (FlexRAM[offset + 1] != (value >> 8)) { |
|
|
if (FlexRAM[offset + 1] != (value >> 8)) { |
|
|
|
|
|
uint8_t stat = FTFL_FSTAT & 0x70; |
|
|
|
|
|
if (stat) FTFL_FSTAT = stat; |
|
|
FlexRAM[offset + 1] = value >> 8; |
|
|
FlexRAM[offset + 1] = value >> 8; |
|
|
flexram_wait(); |
|
|
flexram_wait(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
case 0: |
|
|
case 0: |
|
|
#endif |
|
|
#endif |
|
|
if (*(uint32_t *)(&FlexRAM[offset]) != value) { |
|
|
if (*(uint32_t *)(&FlexRAM[offset]) != value) { |
|
|
|
|
|
uint8_t stat = FTFL_FSTAT & 0x70; |
|
|
|
|
|
if (stat) FTFL_FSTAT = stat; |
|
|
*(uint32_t *)(&FlexRAM[offset]) = value; |
|
|
*(uint32_t *)(&FlexRAM[offset]) = value; |
|
|
flexram_wait(); |
|
|
flexram_wait(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
#ifdef HANDLE_UNALIGNED_WRITES |
|
|
#ifdef HANDLE_UNALIGNED_WRITES |
|
|
case 2: |
|
|
case 2: |
|
|
if (*(uint16_t *)(&FlexRAM[offset]) != value) { |
|
|
if (*(uint16_t *)(&FlexRAM[offset]) != value) { |
|
|
|
|
|
uint8_t stat = FTFL_FSTAT & 0x70; |
|
|
|
|
|
if (stat) FTFL_FSTAT = stat; |
|
|
*(uint16_t *)(&FlexRAM[offset]) = value; |
|
|
*(uint16_t *)(&FlexRAM[offset]) = value; |
|
|
flexram_wait(); |
|
|
flexram_wait(); |
|
|
} |
|
|
} |
|
|
if (*(uint16_t *)(&FlexRAM[offset + 2]) != (value >> 16)) { |
|
|
if (*(uint16_t *)(&FlexRAM[offset + 2]) != (value >> 16)) { |
|
|
|
|
|
uint8_t stat = FTFL_FSTAT & 0x70; |
|
|
|
|
|
if (stat) FTFL_FSTAT = stat; |
|
|
*(uint16_t *)(&FlexRAM[offset + 2]) = value >> 16; |
|
|
*(uint16_t *)(&FlexRAM[offset + 2]) = value >> 16; |
|
|
flexram_wait(); |
|
|
flexram_wait(); |
|
|
} |
|
|
} |
|
|
return; |
|
|
return; |
|
|
default: |
|
|
default: |
|
|
if (FlexRAM[offset] != value) { |
|
|
if (FlexRAM[offset] != value) { |
|
|
|
|
|
uint8_t stat = FTFL_FSTAT & 0x70; |
|
|
|
|
|
if (stat) FTFL_FSTAT = stat; |
|
|
FlexRAM[offset] = value; |
|
|
FlexRAM[offset] = value; |
|
|
flexram_wait(); |
|
|
flexram_wait(); |
|
|
} |
|
|
} |
|
|
if (*(uint16_t *)(&FlexRAM[offset + 1]) != (value >> 8)) { |
|
|
if (*(uint16_t *)(&FlexRAM[offset + 1]) != (value >> 8)) { |
|
|
|
|
|
uint8_t stat = FTFL_FSTAT & 0x70; |
|
|
|
|
|
if (stat) FTFL_FSTAT = stat; |
|
|
*(uint16_t *)(&FlexRAM[offset + 1]) = value >> 8; |
|
|
*(uint16_t *)(&FlexRAM[offset + 1]) = value >> 8; |
|
|
flexram_wait(); |
|
|
flexram_wait(); |
|
|
} |
|
|
} |
|
|
if (FlexRAM[offset + 3] != (value >> 24)) { |
|
|
if (FlexRAM[offset + 3] != (value >> 24)) { |
|
|
|
|
|
uint8_t stat = FTFL_FSTAT & 0x70; |
|
|
|
|
|
if (stat) FTFL_FSTAT = stat; |
|
|
FlexRAM[offset + 3] = value >> 24; |
|
|
FlexRAM[offset + 3] = value >> 24; |
|
|
flexram_wait(); |
|
|
flexram_wait(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
val32 |= (*src++ << 16); |
|
|
val32 |= (*src++ << 16); |
|
|
val32 |= (*src++ << 24); |
|
|
val32 |= (*src++ << 24); |
|
|
if (*(uint32_t *)(&FlexRAM[offset]) != val32) { |
|
|
if (*(uint32_t *)(&FlexRAM[offset]) != val32) { |
|
|
|
|
|
uint8_t stat = FTFL_FSTAT & 0x70; |
|
|
|
|
|
if (stat) FTFL_FSTAT = stat; |
|
|
*(uint32_t *)(&FlexRAM[offset]) = val32; |
|
|
*(uint32_t *)(&FlexRAM[offset]) = val32; |
|
|
flexram_wait(); |
|
|
flexram_wait(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
val16 = *src++; |
|
|
val16 = *src++; |
|
|
val16 |= (*src++ << 8); |
|
|
val16 |= (*src++ << 8); |
|
|
if (*(uint16_t *)(&FlexRAM[offset]) != val16) { |
|
|
if (*(uint16_t *)(&FlexRAM[offset]) != val16) { |
|
|
|
|
|
uint8_t stat = FTFL_FSTAT & 0x70; |
|
|
|
|
|
if (stat) FTFL_FSTAT = stat; |
|
|
*(uint16_t *)(&FlexRAM[offset]) = val16; |
|
|
*(uint16_t *)(&FlexRAM[offset]) = val16; |
|
|
flexram_wait(); |
|
|
flexram_wait(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// write 8 bits |
|
|
// write 8 bits |
|
|
uint8_t val8 = *src++; |
|
|
uint8_t val8 = *src++; |
|
|
if (FlexRAM[offset] != val8) { |
|
|
if (FlexRAM[offset] != val8) { |
|
|
|
|
|
uint8_t stat = FTFL_FSTAT & 0x70; |
|
|
|
|
|
if (stat) FTFL_FSTAT = stat; |
|
|
FlexRAM[offset] = val8; |
|
|
FlexRAM[offset] = val8; |
|
|
flexram_wait(); |
|
|
flexram_wait(); |
|
|
} |
|
|
} |