alif/ospi_flash: Enter XIP mode when flash is idle.
Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
@@ -50,10 +50,14 @@ typedef struct _ospi_flash_t {
|
|||||||
const ospi_pin_settings_t *pin;
|
const ospi_pin_settings_t *pin;
|
||||||
const ospi_flash_settings_t *set;
|
const ospi_flash_settings_t *set;
|
||||||
ospi_flash_cfg_t cfg;
|
ospi_flash_cfg_t cfg;
|
||||||
|
bool xip_active;
|
||||||
} ospi_flash_t;
|
} ospi_flash_t;
|
||||||
|
|
||||||
static ospi_flash_t global_flash;
|
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.
|
// 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,21 +340,29 @@ int ospi_flash_init(void) {
|
|||||||
int ospi_flash_erase_sector(uint32_t addr) {
|
int ospi_flash_erase_sector(uint32_t addr) {
|
||||||
ospi_flash_t *self = &global_flash;
|
ospi_flash_t *self = &global_flash;
|
||||||
|
|
||||||
|
ospi_flash_xip_exit(self);
|
||||||
|
|
||||||
ospi_flash_write_cmd(self, self->set->write_en);
|
ospi_flash_write_cmd(self, self->set->write_en);
|
||||||
int ret = ospi_flash_wait_wel1(self);
|
int ret = ospi_flash_wait_wel1(self);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
ospi_flash_xip_enter(self);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ospi_flash_write_cmd_addr(self, self->set->erase_command, OSPI_ADDR_L_32bit, addr);
|
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) {
|
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.
|
// 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_t *self = &global_flash;
|
||||||
|
|
||||||
|
ospi_flash_xip_exit(self);
|
||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
uint32_t l = len / 4;
|
uint32_t l = len / 4;
|
||||||
if (l > 256) {
|
if (l > 256) {
|
||||||
@@ -336,6 +376,7 @@ int ospi_flash_read(uint32_t addr, uint32_t len, uint8_t *dest) {
|
|||||||
dest += l * 4;
|
dest += l * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ospi_flash_xip_enter(self);
|
||||||
return 0;
|
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) {
|
int ospi_flash_write(uint32_t addr, uint32_t len, const uint8_t *src) {
|
||||||
|
ospi_flash_xip_exit(&global_flash);
|
||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
uint32_t offset = addr & (PAGE_SIZE - 1);
|
uint32_t offset = addr & (PAGE_SIZE - 1);
|
||||||
while (len) {
|
while (len) {
|
||||||
@@ -381,6 +424,8 @@ int ospi_flash_write(uint32_t addr, uint32_t len, const uint8_t *src) {
|
|||||||
src += rest;
|
src += rest;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ospi_flash_xip_enter(&global_flash);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ int ospi_flash_mx_write_cr2(struct _ospi_flash_t *self, uint32_t addr, uint8_t v
|
|||||||
|
|
||||||
// SPI flash interface.
|
// SPI flash interface.
|
||||||
int ospi_flash_init(void);
|
int ospi_flash_init(void);
|
||||||
|
uintptr_t ospi_flash_get_xip_base(void);
|
||||||
int ospi_flash_erase_sector(uint32_t addr);
|
int ospi_flash_erase_sector(uint32_t addr);
|
||||||
int ospi_flash_read(uint32_t addr, uint32_t len, uint8_t *dest);
|
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);
|
int ospi_flash_write(uint32_t addr, uint32_t len, const uint8_t *src);
|
||||||
|
|||||||
Reference in New Issue
Block a user