@@ -52,7 +52,16 @@ using namespace mbed;
5252#define OSPIF_NO_QUAD_ENABLE (-1 )
5353
5454// Configuration Register2 address
55- #define OSPIF_CR2_OPI_EN_ADDR 0x00000000
55+ #define OSPIF_CR2_OPI_EN_ADDR 0x00000000
56+ #define OSPIF_CR2_BANK_STATUS_ADDR 0xc0000000
57+ #define OSPIF_CR2_RWWDI ((uint8_t )0x00 ) /* !< No active program or erase operation */
58+ #define OSPIF_CR2_RWWDS ((uint8_t )0x01 ) /* !< Program/erase in other bank */
59+ #define OSPIF_CR2_RWWBS ((uint8_t )0x03 ) /* !< program/erase operation in addressed bank */
60+
61+ #ifdef MX_FLASH_SUPPORT_RWW
62+ #define MX25LM51245G_BANK_SIZE 0x01000000 /* 16 MBytes */
63+ #define MX25LM51245G_BANK_SIZE_MASK ~(MX25LM51245G_BANK_SIZE - 1 ) /* 0xFF000000 */
64+ #endif
5665
5766/* SFDP Header Parsing */
5867/* **********************/
@@ -232,6 +241,11 @@ OSPIFBlockDevice::OSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinNam
232241 _attempt_4_byte_addressing = true ;
233242 _4byte_msb_reg_write_inst = OSPIF_INST_4BYTE_REG_WRITE_DEFAULT;
234243 _support_4_byte_inst = false ;
244+
245+ #ifdef MX_FLASH_SUPPORT_RWW
246+ _wait_flag = NOT_STARTED;
247+ _busy_bank = 0xffffffff ;
248+ #endif
235249}
236250
237251int OSPIFBlockDevice::init ()
@@ -358,6 +372,17 @@ int OSPIFBlockDevice::deinit()
358372 return result;
359373 }
360374
375+ if (false == _is_mem_ready ()) {
376+ tr_error (" Device not ready after write, failed" );
377+ /* program_failed = true;
378+ status = OSPIF_BD_ERROR_READY_FAILED;
379+ goto exit_point;*/
380+ }
381+
382+ #ifdef MX_FLASH_SUPPORT_RWW
383+ _wait_flag = NOT_STARTED;
384+ #endif
385+
361386 change_mode (SPI);
362387
363388 // Disable Device for Writing
@@ -383,6 +408,29 @@ int OSPIFBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
383408 int status = OSPIF_BD_ERROR_OK;
384409 tr_debug (" Read Inst: 0x%xh" , _read_instruction);
385410
411+ #ifdef MX_FLASH_SUPPORT_RWW
412+ bool need_wait;
413+ need_wait = (_wait_flag != NOT_STARTED) && ((addr & MX25LM51245G_BANK_SIZE_MASK) == _busy_bank);
414+
415+ // Wait for ready
416+ if (need_wait) {
417+
418+ _busy_mutex.lock ();
419+
420+ if (_is_mem_ready_rww (addr, false ) == false ) {
421+ return OSPIF_BD_ERROR_OK;
422+ }
423+
424+ } else {
425+ if (_wait_flag == WRITE_WAIT_STARTED) {
426+ tr_debug (" \r\n RWW1 CNT" );
427+ } else if (_wait_flag == ERASE_WAIT_STARTED) {
428+ tr_debug (" \r\n RWE2 CNT" );
429+ }
430+ }
431+
432+ #endif
433+
386434 _mutex.lock ();
387435
388436 // In DOPI mode, the number of read data should be even
@@ -397,8 +445,13 @@ int OSPIFBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
397445
398446 _mutex.unlock ();
399447
400- return status;
448+ #ifdef MX_FLASH_SUPPORT_RWW
449+ if (need_wait) {
450+ _busy_mutex.unlock ();
451+ }
452+ #endif
401453
454+ return status;
402455}
403456
404457int OSPIFBlockDevice::program (const void *buffer, bd_addr_t addr, bd_size_t size)
@@ -418,6 +471,16 @@ int OSPIFBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size
418471 chunk = (offset + size < _page_size_bytes) ? size : (_page_size_bytes - offset);
419472 written_bytes = chunk;
420473
474+ #ifdef MX_FLASH_SUPPORT_RWW
475+ _busy_mutex.lock ();
476+
477+ // Wait for ready
478+ if (_is_mem_ready_rww (addr, true ) == false ) {
479+ return OSPIF_BD_ERROR_OK;
480+ }
481+
482+ #endif
483+
421484 _mutex.lock ();
422485
423486 // Send WREN
@@ -437,17 +500,26 @@ int OSPIFBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size
437500 goto exit_point;
438501 }
439502
440- buffer = static_cast <const uint8_t *>(buffer) + chunk;
441- addr += chunk;
442- size -= chunk;
503+ #ifdef MX_FLASH_SUPPORT_RWW
504+ _wait_flag = WRITE_WAIT_STARTED;
505+ _busy_bank = addr & MX25LM51245G_BANK_SIZE_MASK;
506+
507+ _mutex.unlock ();
443508
509+ _busy_mutex.unlock ();
510+ #else
444511 if (false == _is_mem_ready ()) {
445512 tr_error (" Device not ready after write, failed" );
446513 program_failed = true ;
447514 status = OSPIF_BD_ERROR_READY_FAILED;
448515 goto exit_point;
449516 }
450517 _mutex.unlock ();
518+ #endif
519+
520+ buffer = static_cast <const uint8_t *>(buffer) + chunk;
521+ addr += chunk;
522+ size -= chunk;
451523 }
452524
453525exit_point:
@@ -511,6 +583,15 @@ int OSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t size)
511583 tr_debug (" Erase - Region: %d, Type:%d " ,
512584 region, type);
513585
586+ #ifdef MX_FLASH_SUPPORT_RWW
587+ _busy_mutex.lock ();
588+
589+ // Wait for ready
590+ if (_is_mem_ready_rww (addr, true ) == false ) {
591+ return OSPIF_BD_ERROR_OK;
592+ }
593+ #endif
594+
514595 _mutex.lock ();
515596
516597 if (_set_write_enable () != 0 ) {
@@ -527,15 +608,14 @@ int OSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t size)
527608 goto exit_point;
528609 }
529610
530- addr += eu_size;
531- size -= eu_size;
611+ #ifdef MX_FLASH_SUPPORT_RWW
612+ _wait_flag = ERASE_WAIT_STARTED;
613+ _busy_bank = addr & MX25LM51245G_BANK_SIZE_MASK;
532614
533- if ((size > 0 ) && (addr > _sfdp_info.smptbl .region_high_boundary [region])) {
534- // erase crossed to next region
535- region++;
536- bitfield = _sfdp_info.smptbl .region_erase_types_bitfld [region];
537- }
615+ _mutex.unlock ();
538616
617+ _busy_mutex.unlock ();
618+ #else
539619 if (false == _is_mem_ready ()) {
540620 tr_error (" OSPI After Erase Device not ready - failed" );
541621 erase_failed = true ;
@@ -544,6 +624,16 @@ int OSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t size)
544624 }
545625
546626 _mutex.unlock ();
627+ #endif
628+
629+ addr += eu_size;
630+ size -= eu_size;
631+
632+ if ((size > 0 ) && (addr > _sfdp_info.smptbl .region_high_boundary [region])) {
633+ // erase crossed to next region
634+ region++;
635+ bitfield = _sfdp_info.smptbl .region_erase_types_bitfld [region];
636+ }
547637 }
548638
549639exit_point:
@@ -1537,6 +1627,51 @@ bool OSPIFBlockDevice::_is_mem_ready()
15371627 return mem_ready;
15381628}
15391629
1630+ #ifdef MX_FLASH_SUPPORT_RWW
1631+ bool OSPIFBlockDevice::_is_mem_ready_rww (bd_addr_t addr, uint8_t rw)
1632+ {
1633+ uint16_t cr2_value = 0 ;
1634+ bool mem_ready = true ;
1635+ static uint32_t rww_cnt = 0 ; // For testing
1636+ static uint32_t rwe_cnt = 0 ; // For testing
1637+
1638+ bd_addr_t bank_addr = addr & MX25LM51245G_BANK_SIZE_MASK;
1639+
1640+ if ((_wait_flag == NOT_STARTED) || (!rw && bank_addr != _busy_bank)) {
1641+ return mem_ready;
1642+ }
1643+ // Read CR2 Register 1 from device, the number of read byte need to be even in octa flash DOPI mode
1644+ if (OSPI_STATUS_OK != _ospi_send_general_command (OSPIF_INST_RDCR2, bank_addr + OSPIF_CR2_BANK_STATUS_ADDR,
1645+ NULL , 0 ,
1646+ (char *) &cr2_value, OSPI_DEFAULT_STATUS_REGISTERS)) { // store received value in cr2_value
1647+ tr_error (" Reading CR2 Register failed" );
1648+ }
1649+
1650+ cr2_value &= OSPIF_CR2_RWWBS;
1651+
1652+ if ((cr2_value == OSPIF_CR2_RWWBS) || (rw && (cr2_value == OSPIF_CR2_RWWDS))) {
1653+
1654+ // Wait until device ready
1655+ if (false == _is_mem_ready ()) {
1656+ tr_error (" _is_mem_ready Failed" );
1657+ mem_ready = false ;
1658+ }
1659+ _wait_flag = NOT_STARTED;
1660+ } else if (!rw && (cr2_value == OSPIF_CR2_RWWDS)) {
1661+ // For testing
1662+ if (_wait_flag == WRITE_WAIT_STARTED) {
1663+ rww_cnt++;
1664+ tr_debug (" rww_cnt = 0x%x " , rww_cnt);
1665+ } else {
1666+ rwe_cnt++;
1667+ tr_debug (" rwe_cnt = 0x%x " , rwe_cnt);
1668+ }
1669+ }
1670+
1671+ return mem_ready;
1672+ }
1673+ #endif
1674+
15401675/* **************************************************/
15411676/* ********** OSPI Driver API Functions *************/
15421677/* **************************************************/
@@ -1665,9 +1800,12 @@ ospi_status_t OSPIFBlockDevice::_ospi_send_general_command(ospi_inst_t instructi
16651800 if ((_inst_width == OSPI_CFG_BUS_OCTA) || (_inst_width == OSPI_CFG_BUS_OCTA_DTR)) {
16661801 if ((instruction == OSPIF_INST_RSR1) || (instruction == OSPIF_INST_RDID) ||
16671802 (instruction == OSPIF_INST_RDCR2) || (instruction == OSPIF_INST_RDCR)) {
1668- _ospi.configure_format (_inst_width, _inst_size, _address_width, _address_size, OSPI_CFG_BUS_SINGLE, 0 , _data_width, _dummy_cycles);
1669- addr = 0 ;
1670- } else if (instruction == OSPIF_INST_WSR1) {
1803+ _ospi.configure_format (_inst_width, _inst_size, _address_width, _address_size, OSPI_CFG_BUS_SINGLE,
1804+ 0 , _data_width, 4 );
1805+ if (instruction != OSPIF_INST_RDCR2) {
1806+ addr = 0 ;
1807+ }
1808+ } else if ((instruction == OSPIF_INST_WSR1)) {
16711809 addr = 0 ;
16721810 }
16731811 }
0 commit comments