|
|
|
|
|
|
|
|
// Conversation about how this code works & what the upper limits are |
|
|
// Conversation about how this code works & what the upper limits are |
|
|
// https://forum.pjrc.com/threads/57377?p=214566&viewfull=1#post214566 |
|
|
// https://forum.pjrc.com/threads/57377?p=214566&viewfull=1#post214566 |
|
|
|
|
|
|
|
|
static void flash_write(void *addr, const void *data, uint32_t len); |
|
|
|
|
|
static void flash_erase_sector(void *addr); |
|
|
|
|
|
|
|
|
// To be called from LittleFS_Program, any other use at your own risk! |
|
|
|
|
|
void eepromemu_flash_write(void *addr, const void *data, uint32_t len); |
|
|
|
|
|
void eepromemu_flash_erase_sector(void *addr); |
|
|
|
|
|
|
|
|
static uint8_t initialized=0; |
|
|
static uint8_t initialized=0; |
|
|
static uint16_t sector_index[FLASH_SECTORS]; |
|
|
static uint16_t sector_index[FLASH_SECTORS]; |
|
|
|
|
|
|
|
|
if (sector_index[sector] < 2048) { |
|
|
if (sector_index[sector] < 2048) { |
|
|
//printf("ee_wr, writing\n"); |
|
|
//printf("ee_wr, writing\n"); |
|
|
uint16_t newdata = offset | (data << 8); |
|
|
uint16_t newdata = offset | (data << 8); |
|
|
flash_write(end, &newdata, 2); |
|
|
|
|
|
|
|
|
eepromemu_flash_write(end, &newdata, 2); |
|
|
sector_index[sector] = sector_index[sector] + 1; |
|
|
sector_index[sector] = sector_index[sector] + 1; |
|
|
} else { |
|
|
} else { |
|
|
//printf("ee_wr, erase then write\n"); |
|
|
//printf("ee_wr, erase then write\n"); |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
buf[offset] = data; |
|
|
buf[offset] = data; |
|
|
p = (uint16_t *)(FLASH_BASEADDR + sector * 4096); |
|
|
p = (uint16_t *)(FLASH_BASEADDR + sector * 4096); |
|
|
flash_erase_sector(p); |
|
|
|
|
|
|
|
|
eepromemu_flash_erase_sector(p); |
|
|
index = 0; |
|
|
index = 0; |
|
|
for (i=0; i < 256; i++) { |
|
|
for (i=0; i < 256; i++) { |
|
|
if (buf[i] != 0xFF) { |
|
|
if (buf[i] != 0xFF) { |
|
|
// TODO: combining these to larger write |
|
|
// TODO: combining these to larger write |
|
|
// would (probably) be more efficient |
|
|
// would (probably) be more efficient |
|
|
uint16_t newval = i | (buf[i] << 8); |
|
|
uint16_t newval = i | (buf[i] << 8); |
|
|
flash_write(p + index, &newval, 2); |
|
|
|
|
|
|
|
|
eepromemu_flash_write(p + index, &newval, 2); |
|
|
index = index + 1; |
|
|
index = index + 1; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// write bytes into flash memory (which is already erased to 0xFF) |
|
|
// write bytes into flash memory (which is already erased to 0xFF) |
|
|
static void flash_write(void *addr, const void *data, uint32_t len) |
|
|
|
|
|
|
|
|
void eepromemu_flash_write(void *addr, const void *data, uint32_t len) |
|
|
{ |
|
|
{ |
|
|
__disable_irq(); |
|
|
__disable_irq(); |
|
|
FLEXSPI_LUTKEY = FLEXSPI_LUTKEY_VALUE; |
|
|
FLEXSPI_LUTKEY = FLEXSPI_LUTKEY_VALUE; |
|
|
|
|
|
|
|
|
FLEXSPI_LUT60 = LUT0(CMD_SDR, PINS1, 0x32) | LUT1(ADDR_SDR, PINS1, 24); // 32 = quad write |
|
|
FLEXSPI_LUT60 = LUT0(CMD_SDR, PINS1, 0x32) | LUT1(ADDR_SDR, PINS1, 24); // 32 = quad write |
|
|
FLEXSPI_LUT61 = LUT0(WRITE_SDR, PINS4, 1); |
|
|
FLEXSPI_LUT61 = LUT0(WRITE_SDR, PINS4, 1); |
|
|
FLEXSPI_IPTXFCR = FLEXSPI_IPTXFCR_CLRIPTXF; // clear tx fifo |
|
|
FLEXSPI_IPTXFCR = FLEXSPI_IPTXFCR_CLRIPTXF; // clear tx fifo |
|
|
FLEXSPI_IPCR0 = (uint32_t)addr & 0x007FFFFF; |
|
|
|
|
|
|
|
|
FLEXSPI_IPCR0 = (uint32_t)addr & 0x00FFFFFF; |
|
|
FLEXSPI_IPCR1 = FLEXSPI_IPCR1_ISEQID(15) | FLEXSPI_IPCR1_IDATSZ(len); |
|
|
FLEXSPI_IPCR1 = FLEXSPI_IPCR1_ISEQID(15) | FLEXSPI_IPCR1_IDATSZ(len); |
|
|
FLEXSPI_IPCMD = FLEXSPI_IPCMD_TRG; |
|
|
FLEXSPI_IPCMD = FLEXSPI_IPCMD_TRG; |
|
|
const uint8_t *src = (const uint8_t *)data; |
|
|
const uint8_t *src = (const uint8_t *)data; |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// erase a 4K sector |
|
|
// erase a 4K sector |
|
|
static void flash_erase_sector(void *addr) |
|
|
|
|
|
|
|
|
void eepromemu_flash_erase_sector(void *addr) |
|
|
{ |
|
|
{ |
|
|
__disable_irq(); |
|
|
__disable_irq(); |
|
|
FLEXSPI_LUTKEY = FLEXSPI_LUTKEY_VALUE; |
|
|
FLEXSPI_LUTKEY = FLEXSPI_LUTKEY_VALUE; |
|
|
|
|
|
|
|
|
while (!(FLEXSPI_INTR & FLEXSPI_INTR_IPCMDDONE)) ; // wait |
|
|
while (!(FLEXSPI_INTR & FLEXSPI_INTR_IPCMDDONE)) ; // wait |
|
|
FLEXSPI_INTR = FLEXSPI_INTR_IPCMDDONE; |
|
|
FLEXSPI_INTR = FLEXSPI_INTR_IPCMDDONE; |
|
|
FLEXSPI_LUT60 = LUT0(CMD_SDR, PINS1, 0x20) | LUT1(ADDR_SDR, PINS1, 24); // 20 = sector erase |
|
|
FLEXSPI_LUT60 = LUT0(CMD_SDR, PINS1, 0x20) | LUT1(ADDR_SDR, PINS1, 24); // 20 = sector erase |
|
|
FLEXSPI_IPCR0 = (uint32_t)addr & 0x007FF000; |
|
|
|
|
|
|
|
|
FLEXSPI_IPCR0 = (uint32_t)addr & 0x00FFF000; |
|
|
FLEXSPI_IPCR1 = FLEXSPI_IPCR1_ISEQID(15); |
|
|
FLEXSPI_IPCR1 = FLEXSPI_IPCR1_ISEQID(15); |
|
|
FLEXSPI_IPCMD = FLEXSPI_IPCMD_TRG; |
|
|
FLEXSPI_IPCMD = FLEXSPI_IPCMD_TRG; |
|
|
while (!(FLEXSPI_INTR & FLEXSPI_INTR_IPCMDDONE)) ; // wait |
|
|
while (!(FLEXSPI_INTR & FLEXSPI_INTR_IPCMDDONE)) ; // wait |