/* write up a 256 byte page or partial page */ static void spiflash_page_program(spiflash_driver_t* const drv, const uint32_t addr, const uint16_t len, uint8_t* data) { /* do nothing if asked to write beyond a page boundary */ if (((addr & 0xFF) + len) > drv->page_len) return; /* do nothing if we would overflow the flash */ if (addr > (drv->num_bytes - len)) return; spiflash_write_enable(drv); spiflash_wait_while_busy(drv); uint8_t header[] = { SPIFLASH_PAGE_PROGRAM, (addr & 0xFF0000) >> 16, (addr & 0xFF00) >> 8, addr & 0xFF }; const spi_transfer_t transfers[] = { { header, ARRAY_SIZE(header) }, { data, len } }; spi_bus_transfer_gather(drv->target, transfers, ARRAY_SIZE(transfers)); }
void spiflash_chip_erase(spiflash_driver_t* const drv) { uint8_t device_id; device_id = 0; while(device_id != drv->device_id) { device_id = spiflash_get_device_id(drv); } spiflash_write_enable(drv); spiflash_wait_while_busy(drv); uint8_t data[] = { SPIFLASH_CHIP_ERASE }; spi_bus_transfer(drv->target, data, ARRAY_SIZE(data)); }
_ramfunc void spiflash_mem_mode() { // WRR CF1 to enable quad and set latency cycles spiflash_wait(); spiflash_write_enable(); uint8_t buf[2] = {0, (SPIFI_CR1_QUAD)}; spifi_cmd(0x01, SPIFI_FRAMEFORM_0, 0, true, 2, buf); // timeout CS high time fbclk LPC_SPIFI->CTRL = (0xffff << 0) | (0x1 << 16) | (1 << 30); LPC_SPIFI->DATINTM = 0; LPC_SPIFI->MEMCMD = (0xEC << 24) | SPIFI_FRAMEFORM_4 | SPIFI_FIELDFORM_SERIAL_OPCODE | ((2 + 1) << 16); while (!(LPC_SPIFI->STAT & SPIFI_STATUS_MCINIT)); // Execute some instructions, or it crashes when jumping to flash... volatile unsigned j=100000; while (j--); CGU_SetDIV(CGU_CLKSRC_IDIVA, 2); // Fast SPIFI clock }
_ramfunc void spiflash_erase_sector(unsigned addr) { spiflash_wait(); spiflash_write_enable(); spifi_cmd(0xDC, SPIFI_FRAMEFORM_4, addr, false, 0, NULL); }
_ramfunc void spiflash_write_page(unsigned addr, uint8_t* data, unsigned length) { spiflash_wait(); spiflash_write_enable(); spifi_cmd(0x12, SPIFI_FRAMEFORM_4, addr, true, length, data); }