diff options
| -rw-r--r-- | ports/alif/ospi_flash.c | 47 | ||||
| -rw-r--r-- | ports/alif/ospi_flash.h | 1 |
2 files changed, 47 insertions, 1 deletions
diff --git a/ports/alif/ospi_flash.c b/ports/alif/ospi_flash.c index 6f083de63..be575d9ed 100644 --- a/ports/alif/ospi_flash.c +++ b/ports/alif/ospi_flash.c @@ -50,10 +50,14 @@ typedef struct _ospi_flash_t { const ospi_pin_settings_t *pin; const ospi_flash_settings_t *set; ospi_flash_cfg_t cfg; + bool xip_active; } ospi_flash_t; static ospi_flash_t global_flash; +static int ospi_flash_xip_enter(ospi_flash_t *self); +static int ospi_flash_xip_exit(ospi_flash_t *self); + /******************************************************************************/ // Generic SPI-flash helper functions. @@ -299,6 +303,34 @@ int ospi_flash_init(void) { } } + // Enter XIP mode. It will be disabled during flash read/erase/write. + ospi_flash_xip_enter(self); + + return 0; +} + +uintptr_t ospi_flash_get_xip_base(void) { + ospi_flash_t *self = &global_flash; + return (uintptr_t)self->cfg.xip_base; +} + +static int ospi_flash_xip_enter(ospi_flash_t *self) { + if (!self->xip_active) { + uint32_t irq_state = disable_irq(); + self->xip_active = true; + ospi_xip_enter_16bit_cmd(&self->cfg, self->set->xip_data_len, self->set->read_command, self->set->read_command, self->set->read_dummy_cycles); + enable_irq(irq_state); + } + return 0; +} + +static int ospi_flash_xip_exit(ospi_flash_t *self) { + if (self->xip_active) { + uint32_t irq_state = disable_irq(); + ospi_xip_exit_16bit_cmd(&self->cfg, self->set->read_command, self->set->read_command); + self->xip_active = false; + enable_irq(irq_state); + } return 0; } @@ -308,21 +340,29 @@ int ospi_flash_init(void) { int ospi_flash_erase_sector(uint32_t addr) { ospi_flash_t *self = &global_flash; + ospi_flash_xip_exit(self); + ospi_flash_write_cmd(self, self->set->write_en); int ret = ospi_flash_wait_wel1(self); if (ret < 0) { + ospi_flash_xip_enter(self); return ret; } ospi_flash_write_cmd_addr(self, self->set->erase_command, OSPI_ADDR_L_32bit, addr); + ret = ospi_flash_wait_wip0(self); - return ospi_flash_wait_wip0(self); + ospi_flash_xip_enter(self); + return ret; } int ospi_flash_read(uint32_t addr, uint32_t len, uint8_t *dest) { // OSPI FIFO is limited to 256 bytes. Need DMA to get a longer read. + // Note that direct reading is much faster than using XIP memory-mapped read. ospi_flash_t *self = &global_flash; + ospi_flash_xip_exit(self); + while (len) { uint32_t l = len / 4; if (l > 256) { @@ -336,6 +376,7 @@ int ospi_flash_read(uint32_t addr, uint32_t len, uint8_t *dest) { dest += l * 4; } + ospi_flash_xip_enter(self); return 0; } @@ -365,6 +406,8 @@ static int ospi_flash_write_page(uint32_t addr, uint32_t len, const uint8_t *src } int ospi_flash_write(uint32_t addr, uint32_t len, const uint8_t *src) { + ospi_flash_xip_exit(&global_flash); + int ret = 0; uint32_t offset = addr & (PAGE_SIZE - 1); while (len) { @@ -381,6 +424,8 @@ int ospi_flash_write(uint32_t addr, uint32_t len, const uint8_t *src) { src += rest; offset = 0; } + + ospi_flash_xip_enter(&global_flash); return ret; } diff --git a/ports/alif/ospi_flash.h b/ports/alif/ospi_flash.h index 6f5d8327b..8fe69764a 100644 --- a/ports/alif/ospi_flash.h +++ b/ports/alif/ospi_flash.h @@ -88,6 +88,7 @@ int ospi_flash_mx_write_cr2(struct _ospi_flash_t *self, uint32_t addr, uint8_t v // SPI flash interface. int ospi_flash_init(void); +uintptr_t ospi_flash_get_xip_base(void); int ospi_flash_erase_sector(uint32_t addr); int ospi_flash_read(uint32_t addr, uint32_t len, uint8_t *dest); int ospi_flash_write(uint32_t addr, uint32_t len, const uint8_t *src); |
