Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable the RWW function of Macronix Flash MX25LW51245G in OSPI block device driver #14221

Merged
merged 5 commits into from
Jun 2, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,17 @@ uint8_t _sfdp_basic_param_table[64] = {0x30, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF,
uint8_t _sfdp_4_byte_inst_table[8] = {0x7F, 0xEF, 0xFF, 0xFF, 0x21, 0x5C, 0xDC, 0x14};
#endif

//#define MX_FLASH_SUPPORT_RWW 1

#define MX25LM51245G_FLASH_SIZE 0x4000000 /* 512 MBits => 64 MBytes */
#define MX25LM51245G_BLOCK_SIZE 0x10000 /* 1024 blocks of 64 KBytes */
#define MX25LM51245G_SECTOR_SIZE 0x1000 /* 16384 sectors of 4 kBytes */
#define MX25LM51245G_PAGE_SIZE 0x100 /* 262144 pages of 256 bytes */
#define MX25LM51245G_CHUNK_SIZE 0x10 /* fred: 16 bytes */

#ifdef MX_FLASH_SUPPORT_RWW
#define MX25LM51245G_BANK_SIZE 0x01000000 /* fred: 16 MBytes */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why you don't create a new file MX25LW51245G_config.h ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have created a new file MX25LW51245G_config.h .

#define MX25LM51245G_BANK_SIZE_MASK ~(MX25LM51245G_BANK_SIZE - 1) /* fred: 0xFF000000 */
#endif

#endif // MBED_OSPI_FLASH_MX25LM51245G_H
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@
#define MBED_CONF_OSPIF_OSPI_FREQ 40000000
#endif

#define MX_FLASH_SUPPORT_RWW
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not related to the memory ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is.
I have moved it to MX25LW51245G_config.h.


/** Enum ospif standard error codes
*
* @enum ospif_bd_error
Expand Down Expand Up @@ -381,6 +383,10 @@ class OSPIFBlockDevice : public mbed::BlockDevice {
// Detect 4-byte addressing mode and enable it if supported
int _sfdp_detect_and_enable_4byte_addressing(uint8_t *basic_param_table_ptr, int basic_param_table_size);

#ifdef MX_FLASH_SUPPORT_RWW
bool _is_mem_ready_rww(bd_addr_t addr, uint8_t rw);
#endif

private:
enum ospif_clear_protection_method_t {
OSPIF_BP_ULBPR, // Issue global protection unlock instruction
Expand Down Expand Up @@ -449,6 +455,16 @@ class OSPIFBlockDevice : public mbed::BlockDevice {

uint32_t _init_ref_count;
bool _is_initialized;
#ifdef MX_FLASH_SUPPORT_RWW
enum wait_flag {
NOT_STARTED, // no wait is started
WRITE_WAIT_STARTED, // write wait is started
ERASE_WAIT_STARTED, // erase wait is started
};
uint32_t _busy_bank; // Current busy bank
wait_flag _wait_flag; // wait flag
PlatformMutex _busy_mutex;
#endif
};

#endif
164 changes: 149 additions & 15 deletions storage/blockdevice/COMPONENT_OSPIF/source/OSPIFBlockDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,16 @@ using namespace mbed;
#define OSPIF_NO_QUAD_ENABLE (-1)

// Configuration Register2 address
#define OSPIF_CR2_OPI_EN_ADDR 0x00000000
#define OSPIF_CR2_OPI_EN_ADDR 0x00000000
#define OSPIF_CR2_BANK_STATUS_ADDR 0xc0000000
#define OSPIF_CR2_RWWDI ((uint8_t)0x00) /*!< No active program or erase operation */
#define OSPIF_CR2_RWWDS ((uint8_t)0x01) /*!< Program/erase in other bank */
#define OSPIF_CR2_RWWBS ((uint8_t)0x03) /*!< program/erase operation in addressed bank */

#ifdef MX_FLASH_SUPPORT_RWW
#define MX25LM51245G_BANK_SIZE 0x01000000 /* 16 MBytes */
#define MX25LM51245G_BANK_SIZE_MASK ~(MX25LM51245G_BANK_SIZE - 1) /* 0xFF000000 */
#endif

/* SFDP Header Parsing */
/***********************/
Expand Down Expand Up @@ -232,6 +241,11 @@ OSPIFBlockDevice::OSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinNam
_attempt_4_byte_addressing = true;
_4byte_msb_reg_write_inst = OSPIF_INST_4BYTE_REG_WRITE_DEFAULT;
_support_4_byte_inst = false;

#ifdef MX_FLASH_SUPPORT_RWW
_wait_flag = NOT_STARTED;
_busy_bank = 0xffffffff;
#endif
}

int OSPIFBlockDevice::init()
Expand Down Expand Up @@ -358,6 +372,14 @@ int OSPIFBlockDevice::deinit()
return result;
}

if (false == _is_mem_ready()) {
tr_error("Device not ready after write, failed");
}

#ifdef MX_FLASH_SUPPORT_RWW
_wait_flag = NOT_STARTED;
#endif

change_mode(SPI);

// Disable Device for Writing
Expand All @@ -383,6 +405,29 @@ int OSPIFBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
int status = OSPIF_BD_ERROR_OK;
tr_debug("Read Inst: 0x%xh", _read_instruction);

#ifdef MX_FLASH_SUPPORT_RWW
bool need_wait;
need_wait = (_wait_flag != NOT_STARTED) && ((addr & MX25LM51245G_BANK_SIZE_MASK) == _busy_bank);

// Wait for ready
if (need_wait) {

_busy_mutex.lock();

if (_is_mem_ready_rww(addr, false) == false) {
return OSPIF_BD_ERROR_OK;
}

} else {
if (_wait_flag == WRITE_WAIT_STARTED) {
tr_debug("\r\n RWW1 CNT");
} else if (_wait_flag == ERASE_WAIT_STARTED) {
tr_debug("\r\n RWE2 CNT");
}
}

#endif

_mutex.lock();

// In DOPI mode, the number of read data should be even
Expand All @@ -397,8 +442,13 @@ int OSPIFBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)

_mutex.unlock();

return status;
#ifdef MX_FLASH_SUPPORT_RWW
if (need_wait) {
_busy_mutex.unlock();
}
#endif

return status;
}

int OSPIFBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size)
Expand All @@ -418,6 +468,16 @@ int OSPIFBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size
chunk = (offset + size < _page_size_bytes) ? size : (_page_size_bytes - offset);
written_bytes = chunk;

#ifdef MX_FLASH_SUPPORT_RWW
_busy_mutex.lock();

// Wait for ready
if (_is_mem_ready_rww(addr, true) == false) {
return OSPIF_BD_ERROR_OK;
}

#endif

_mutex.lock();

//Send WREN
Expand All @@ -437,17 +497,25 @@ int OSPIFBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size
goto exit_point;
}

buffer = static_cast<const uint8_t *>(buffer) + chunk;
addr += chunk;
size -= chunk;
#ifdef MX_FLASH_SUPPORT_RWW
_wait_flag = WRITE_WAIT_STARTED;
_busy_bank = addr & MX25LM51245G_BANK_SIZE_MASK;

_mutex.unlock();

_busy_mutex.unlock();
#else
if (false == _is_mem_ready()) {
tr_error("Device not ready after write, failed");
program_failed = true;
status = OSPIF_BD_ERROR_READY_FAILED;
goto exit_point;
}
_mutex.unlock();
#endif
buffer = static_cast<const uint8_t *>(buffer) + chunk;
addr += chunk;
size -= chunk;
}

exit_point:
Expand Down Expand Up @@ -511,6 +579,15 @@ int OSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t size)
tr_debug("Erase - Region: %d, Type:%d ",
region, type);

#ifdef MX_FLASH_SUPPORT_RWW
_busy_mutex.lock();

// Wait for ready
if (_is_mem_ready_rww(addr, true) == false) {
return OSPIF_BD_ERROR_OK;
}
#endif

_mutex.lock();

if (_set_write_enable() != 0) {
Expand All @@ -527,15 +604,14 @@ int OSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t size)
goto exit_point;
}

addr += eu_size;
size -= eu_size;
#ifdef MX_FLASH_SUPPORT_RWW
_wait_flag = ERASE_WAIT_STARTED;
_busy_bank = addr & MX25LM51245G_BANK_SIZE_MASK;

if ((size > 0) && (addr > _sfdp_info.smptbl.region_high_boundary[region])) {
// erase crossed to next region
region++;
bitfield = _sfdp_info.smptbl.region_erase_types_bitfld[region];
}
_mutex.unlock();

_busy_mutex.unlock();
#else
if (false == _is_mem_ready()) {
tr_error("OSPI After Erase Device not ready - failed");
erase_failed = true;
Expand All @@ -544,6 +620,16 @@ int OSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t size)
}

_mutex.unlock();
#endif

addr += eu_size;
size -= eu_size;

if ((size > 0) && (addr > _sfdp_info.smptbl.region_high_boundary[region])) {
// erase crossed to next region
region++;
bitfield = _sfdp_info.smptbl.region_erase_types_bitfld[region];
}
}

exit_point:
Expand Down Expand Up @@ -1537,6 +1623,51 @@ bool OSPIFBlockDevice::_is_mem_ready()
return mem_ready;
}

#ifdef MX_FLASH_SUPPORT_RWW
bool OSPIFBlockDevice::_is_mem_ready_rww(bd_addr_t addr, uint8_t rw)
{
uint16_t cr2_value = 0;
bool mem_ready = true;
static uint32_t rww_cnt = 0; // For testing
static uint32_t rwe_cnt = 0; // For testing

bd_addr_t bank_addr = addr & MX25LM51245G_BANK_SIZE_MASK;

if ((_wait_flag == NOT_STARTED) || (!rw && bank_addr != _busy_bank)) {
return mem_ready;
}
//Read CR2 Register 1 from device, the number of read byte need to be even in octa flash DOPI mode
if (OSPI_STATUS_OK != _ospi_send_general_command(OSPIF_INST_RDCR2, bank_addr + OSPIF_CR2_BANK_STATUS_ADDR,
NULL, 0,
(char *) &cr2_value, OSPI_DEFAULT_STATUS_REGISTERS)) { // store received value in cr2_value
tr_error("Reading CR2 Register failed");
}

cr2_value &= OSPIF_CR2_RWWBS;

if ((cr2_value == OSPIF_CR2_RWWBS) || (rw && (cr2_value == OSPIF_CR2_RWWDS))) {

// Wait until device ready
if (false == _is_mem_ready()) {
tr_error(" _is_mem_ready Failed");
mem_ready = false;
}
_wait_flag = NOT_STARTED;
} else if (!rw && (cr2_value == OSPIF_CR2_RWWDS)) {
// For testing
if (_wait_flag == WRITE_WAIT_STARTED) {
rww_cnt++;
tr_debug("rww_cnt = 0x%x ", rww_cnt);
} else {
rwe_cnt++;
tr_debug("rwe_cnt = 0x%x ", rwe_cnt);
}
}

return mem_ready;
}
#endif

/***************************************************/
/*********** OSPI Driver API Functions *************/
/***************************************************/
Expand Down Expand Up @@ -1665,9 +1796,12 @@ ospi_status_t OSPIFBlockDevice::_ospi_send_general_command(ospi_inst_t instructi
if ((_inst_width == OSPI_CFG_BUS_OCTA) || (_inst_width == OSPI_CFG_BUS_OCTA_DTR)) {
if ((instruction == OSPIF_INST_RSR1) || (instruction == OSPIF_INST_RDID) ||
(instruction == OSPIF_INST_RDCR2) || (instruction == OSPIF_INST_RDCR)) {
_ospi.configure_format(_inst_width, _inst_size, _address_width, _address_size, OSPI_CFG_BUS_SINGLE, 0, _data_width, _dummy_cycles);
addr = 0;
} else if (instruction == OSPIF_INST_WSR1) {
_ospi.configure_format(_inst_width, _inst_size, _address_width, _address_size, OSPI_CFG_BUS_SINGLE,
0, _data_width, _dummy_cycles);
if (instruction != OSPIF_INST_RDCR2) {
addr = 0;
}
} else if ((instruction == OSPIF_INST_WSR1)) {
addr = 0;
}
}
Expand Down
Loading