@@ -50,10 +50,14 @@ typedef struct _ospi_flash_t {
5050 const ospi_pin_settings_t * pin ;
5151 const ospi_flash_settings_t * set ;
5252 ospi_flash_cfg_t cfg ;
53+ bool xip_active ;
5354} ospi_flash_t ;
5455
5556static ospi_flash_t global_flash ;
5657
58+ static int ospi_flash_xip_enter (ospi_flash_t * self );
59+ static int ospi_flash_xip_exit (ospi_flash_t * self );
60+
5761/******************************************************************************/
5862// Generic SPI-flash helper functions.
5963
@@ -299,6 +303,34 @@ int ospi_flash_init(void) {
299303 }
300304 }
301305
306+ // Enter XIP mode. It will be disabled during flash read/erase/write.
307+ ospi_flash_xip_enter (self );
308+
309+ return 0 ;
310+ }
311+
312+ uintptr_t ospi_flash_get_xip_base (void ) {
313+ ospi_flash_t * self = & global_flash ;
314+ return (uintptr_t )self -> cfg .xip_base ;
315+ }
316+
317+ static int ospi_flash_xip_enter (ospi_flash_t * self ) {
318+ if (!self -> xip_active ) {
319+ uint32_t irq_state = disable_irq ();
320+ self -> xip_active = true;
321+ 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 );
322+ enable_irq (irq_state );
323+ }
324+ return 0 ;
325+ }
326+
327+ static int ospi_flash_xip_exit (ospi_flash_t * self ) {
328+ if (self -> xip_active ) {
329+ uint32_t irq_state = disable_irq ();
330+ ospi_xip_exit_16bit_cmd (& self -> cfg , self -> set -> read_command , self -> set -> read_command );
331+ self -> xip_active = false;
332+ enable_irq (irq_state );
333+ }
302334 return 0 ;
303335}
304336
@@ -308,21 +340,29 @@ int ospi_flash_init(void) {
308340int ospi_flash_erase_sector (uint32_t addr ) {
309341 ospi_flash_t * self = & global_flash ;
310342
343+ ospi_flash_xip_exit (self );
344+
311345 ospi_flash_write_cmd (self , self -> set -> write_en );
312346 int ret = ospi_flash_wait_wel1 (self );
313347 if (ret < 0 ) {
348+ ospi_flash_xip_enter (self );
314349 return ret ;
315350 }
316351
317352 ospi_flash_write_cmd_addr (self , self -> set -> erase_command , OSPI_ADDR_L_32bit , addr );
353+ ret = ospi_flash_wait_wip0 (self );
318354
319- return ospi_flash_wait_wip0 (self );
355+ ospi_flash_xip_enter (self );
356+ return ret ;
320357}
321358
322359int ospi_flash_read (uint32_t addr , uint32_t len , uint8_t * dest ) {
323360 // OSPI FIFO is limited to 256 bytes. Need DMA to get a longer read.
361+ // Note that direct reading is much faster than using XIP memory-mapped read.
324362 ospi_flash_t * self = & global_flash ;
325363
364+ ospi_flash_xip_exit (self );
365+
326366 while (len ) {
327367 uint32_t l = len / 4 ;
328368 if (l > 256 ) {
@@ -336,6 +376,7 @@ int ospi_flash_read(uint32_t addr, uint32_t len, uint8_t *dest) {
336376 dest += l * 4 ;
337377 }
338378
379+ ospi_flash_xip_enter (self );
339380 return 0 ;
340381}
341382
@@ -365,6 +406,8 @@ static int ospi_flash_write_page(uint32_t addr, uint32_t len, const uint8_t *src
365406}
366407
367408int ospi_flash_write (uint32_t addr , uint32_t len , const uint8_t * src ) {
409+ ospi_flash_xip_exit (& global_flash );
410+
368411 int ret = 0 ;
369412 uint32_t offset = addr & (PAGE_SIZE - 1 );
370413 while (len ) {
@@ -381,6 +424,8 @@ int ospi_flash_write(uint32_t addr, uint32_t len, const uint8_t *src) {
381424 src += rest ;
382425 offset = 0 ;
383426 }
427+
428+ ospi_flash_xip_enter (& global_flash );
384429 return ret ;
385430}
386431
0 commit comments