Skip to content

Commit 0db8da1

Browse files
committed
modify for the RWW function of Macronix Flash
1 parent 0c6753b commit 0db8da1

File tree

5 files changed

+270
-17
lines changed

5 files changed

+270
-17
lines changed

storage/blockdevice/COMPONENT_OSPIF/include/OSPIF/MX25LM51245G_config.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,17 @@ uint8_t _sfdp_basic_param_table[64] = {0x30, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF,
4242
uint8_t _sfdp_4_byte_inst_table[8] = {0x7F, 0xEF, 0xFF, 0xFF, 0x21, 0x5C, 0xDC, 0x14};
4343
#endif
4444

45+
//#define MX_FLASH_SUPPORT_RWW 1
46+
47+
#define MX25LM51245G_FLASH_SIZE 0x4000000 /* 512 MBits => 64 MBytes */
48+
#define MX25LM51245G_BLOCK_SIZE 0x10000 /* 1024 blocks of 64 KBytes */
49+
#define MX25LM51245G_SECTOR_SIZE 0x1000 /* 16384 sectors of 4 kBytes */
50+
#define MX25LM51245G_PAGE_SIZE 0x100 /* 262144 pages of 256 bytes */
51+
#define MX25LM51245G_CHUNK_SIZE 0x10 /* fred: 16 bytes */
52+
53+
#ifdef MX_FLASH_SUPPORT_RWW
54+
#define MX25LM51245G_BANK_SIZE 0x01000000 /* fred: 16 MBytes */
55+
#define MX25LM51245G_BANK_SIZE_MASK ~(MX25LM51245G_BANK_SIZE - 1) /* fred: 0xFF000000 */
56+
#endif
57+
4558
#endif // MBED_OSPI_FLASH_MX25LM51245G_H

storage/blockdevice/COMPONENT_OSPIF/include/OSPIF/OSPIFBlockDevice.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@
6262
#define MBED_CONF_OSPIF_OSPI_FREQ 40000000
6363
#endif
6464

65+
#define MX_FLASH_SUPPORT_RWW
66+
6567
/** Enum ospif standard error codes
6668
*
6769
* @enum ospif_bd_error
@@ -381,6 +383,10 @@ class OSPIFBlockDevice : public mbed::BlockDevice {
381383
// Detect 4-byte addressing mode and enable it if supported
382384
int _sfdp_detect_and_enable_4byte_addressing(uint8_t *basic_param_table_ptr, int basic_param_table_size);
383385

386+
#ifdef MX_FLASH_SUPPORT_RWW
387+
bool _is_mem_ready_rww(bd_addr_t addr, uint8_t rw);
388+
#endif
389+
384390
private:
385391
enum ospif_clear_protection_method_t {
386392
OSPIF_BP_ULBPR, // Issue global protection unlock instruction
@@ -449,6 +455,16 @@ class OSPIFBlockDevice : public mbed::BlockDevice {
449455

450456
uint32_t _init_ref_count;
451457
bool _is_initialized;
458+
#ifdef MX_FLASH_SUPPORT_RWW
459+
enum wait_flag {
460+
NOT_STARTED, // no wait is started
461+
WRITE_WAIT_STARTED, // write wait is started
462+
ERASE_WAIT_STARTED, // erase wait is started
463+
};
464+
uint32_t _busy_bank; // Current busy bank
465+
wait_flag _wait_flag; // wait flag
466+
PlatformMutex _busy_mutex;
467+
#endif
452468
};
453469

454470
#endif

storage/blockdevice/COMPONENT_OSPIF/source/OSPIFBlockDevice.cpp

Lines changed: 153 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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

237251
int 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

404457
int 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

453525
exit_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

549639
exit_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

Comments
 (0)