S25FL256S - DDR Quad I/O Read

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
DeWa_4681626
Level 1
Level 1

Hi

I am using a PSOC 62 to access S25FL256S memory. PP, READ, 4QPP, 4QOR, 4QIOR all work fine (read/write within a page). However, I can't get DDR Quad I/O Read to work.
I understand that for this particular command, I need to have mode and dummy cycles by configuring LC (My SCK is set to 1MHz) as specified in Table 23 (EDh, EEh column) of the datasheet.  

However, I have tried all the combinations but still can't read expected data out.

From these results so far, I think I can conclude memory content is ok, but just fail to perform a DDR Quad I/O Read (data read out is always 0xFF).

I suspect it may be related to DLP, so I had issued a PNVDLR command to set NVDLR to 0x34, and a DLPRD command also confirmed the pattern was set correctly.

However, I am not sure if DLP is indeed enable. I don't see a register that enable DLP in the datasheet. May I know how to enable it?

Or as long as NVDLR is non zero, is DLP enable automatically?

In addition, do I need to adjust mode or dummy cycles to accommodate for DLP cycles?
Or perhaps I am missing something else?

Thanks,
Dennis

0 Likes
1 Solution

Hi Dennis,

I would like to inform you that PSoC 62 does not support DDR feature. However, you can go through the following KBA about DLP Minimum Dummy Cycles for Enabling Data Learning Pattern (DLP) in Serial NOR Flash Devices – KBA22829... if you still want to learn about it.

Please let me know if you have any further questions about DLP or DDR.

Best Regards,

Apurva

View solution in original post

0 Likes
6 Replies
Apurva_S
Moderator
Moderator
Moderator
100 likes received 500 replies posted 250 solutions authored

Hi Dennis,

Is it possible for you to share your PSoC project with us?

Regards,

Apurva

0 Likes

Hi Apurva,
Thanks for the quick reply. I am using Mbed to develop the application. It does support PSOC 62 and the QSPI API is built on top of cy_qspi_api. I extracted relevant code section below. I understand the Mbed API may look different from Cypress API, so I have added comments. If anything is not clear, please let me know. Also, let me know if you need anything from me. Thanks!

// predefine section

#define CMD_WRR   0x01

#define CMD_PNVDLR 0x43

#define CMD_DDR4QIOR 0xEE // 4 byte addr

#define CMD_4QOR  0x6C // 4 byte addr

#define CMD_4QPP  0x34 // 4 byte addr

#define CMD_WREN  0x06

#define ADDRESS   0x20

// code section

  char tx_buf[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 };

  char cfg_buf[2];

  char rx_buf[6];

  size_t buf_len = sizeof(tx_buf);
   size_t rx_len, tx_len;

  qspi_status_t result;

  // instantiate a QSPI device

  QSPI qspi_device(CYBSP_QSPI_D0, CYBSP_QSPI_D1, CYBSP_QSPI_D2, CYBSP_QSPI_D3, CYBSP_QSPI_SCK, CYBSP_QSPI_SS);

  // set SCK = 1MHz

  qspi_device.set_frequency(1000000);

  // Configure bus for register related commands

  // 1st argument: (instruction bus width) single bus

  // 2nd argument: (address bus width) single bus

  // 3rd argument: address size (using 4-bye addressing)

  // 4th argument: (mode bus width) single bus (although mode is not applicable for register commands here)

  // 5th argument: mode size of 8 bits (also not applicable)

  // 6th argument: (data bus width) single bus

  // 7th argument: dummy cycle

  result = qspi_device.configure_format(QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_32, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 0);

  // WREN before update DLP

  result = qspi_device.command_transfer(CMD_WREN, -1, nullptr, 0, nullptr, 0);

  if (result != QSPI_STATUS_OK) {

    printf("WREN failed");

  }

  cfg_buf[0] = 0x34;

  cfg_len = 1;

  result = qspi_device.command_transfer(CMD_PNVDLR, -1, cfg_buf, cfg_len, nullptr, 0);

  if (result != QSPI_STATUS_OK) {

    printf("PNVDLR failed");

  }

  // WREN before updating LC

  result = qspi_device.command_transfer(CMD_WREN, -1, nullptr, 0, nullptr, 0);

  if (result != QSPI_STATUS_OK) {

    printf("WREN failed");

  }

  // WRR to update LC

  // since QUAD bit has been set, use 2 bytes for WRR command

  cfg_buf[0] = 0x2;  // status register (although according to datasheet, only WREN and WRDI can change this bit)

  cfg_buf[1] = 0x2; // config reg sets LC = 0x1 & QUAD = 1

  cfg_len = 2;

  result = qspi_device.command_transfer(CMD_WRR, -1, cfg_buf, cfg_len, nullptr, 0);

  if (result != QSPI_STATUS_OK) {

    printf("WRR failed");

  }

  // WREN before program

  result = qspi_device.command_transfer(CMD_WREN, -1, nullptr, 0, nullptr, 0);

  if (result != QSPI_STATUS_OK) {

    printf("WREN failed");

  }

  // Configure bus before quad page program

  // instruction: single bus

  // address: single bus

  // 4-byte addressing

  // mode: single bus (not applicable for 4QPP)

  // mode size: 8 bits (not applicable for 4QPP)

  // data: quad bus

  // dummy cycles: 0

  result = qspi_device.configure_format(QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_32, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_QUAD, 0);

  if (result != QSPI_STATUS_OK) {

      printf("Switching to Quad Page Program failed");

  }

  result = qspi_device.write(CMD_4QPP, -1, ADDRESS, tx_buf, &buf_len); // -1 indicates no value used for mode phase

  if (result != QSPI_STATUS_OK) {

     printf("Write failed");

  }

  ThisThread::sleep_for(5000); // wait 5s for write operation to complete

  // Configure bus before DDR Quad I/O Read

  // instruction: single bus

  // address: quad bus

  // 4-byte addressing

  // mode: quad bus

  // mode size: 8 bits

  // data: quad bus

  // dummy cycles: 6 (since LC = 00b)

  result = qspi_device.configure_format(QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_QUAD, QSPI_CFG_ADDR_SIZE_32, QSPI_CFG_BUS_QUAD, QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_QUAD, 6);

  if (result != QSPI_STATUS_OK) {

      printf("Switching to Quad Out Read failed");

  }

  // DDR Quad I/O Read

  result = qspi_device.read(CMD_DDR4QIOR, 0xA5, ADDRESS, rx_buf, &buf_len);

  if (result != QSPI_STATUS_OK) {

     printf("Read failed");

  }

  else {

     printf("Read After Write Addr 0x%X len %d", ADDRESS, buf_len);

     for (int i = 0; i < (int)buf_len; i++){

       printf("%d data 0x%X", i, rx_buf);

     }

  }

  // Perform a Quad Read for comparison

  // instruction: single bus

  // address: single bus

  // 4-byte addressing

  // mode: single bus (not applicable)

  // mode size: 8 bits (not applicable)

  // data: quad bus

  // dummy cycles: 8 (since LC = 00b)

  result = qspi_device.configure_format(QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_32, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_QUAD, 8);

  if (result != QSPI_STATUS_OK) {

      printf("Switching to Quad Out Read failed");

  }

  result = qspi_device.read(CMD_4QOR, -1, ADDRESS, rx_buf, &buf_len);  // -1 indicates no value used for mode phase

  if (result != QSPI_STATUS_OK) {

     printf("Read failed");

  }

  else {

     printf("Good 4QOR Read After Write Addr 0x%X len %d", ADDRESS, buf_len);

     for (int i = 0; i < (int)buf_len; i++){

       printf("%d data 0x%X", i, rx_buf);

     }

  }

0 Likes

Hi Dennis,

I would like to inform you that PSoC 62 does not support DDR feature. However, you can go through the following KBA about DLP Minimum Dummy Cycles for Enabling Data Learning Pattern (DLP) in Serial NOR Flash Devices – KBA22829... if you still want to learn about it.

Please let me know if you have any further questions about DLP or DDR.

Best Regards,

Apurva

0 Likes

Hi Apurva,

That is a bit unfortunate to hear PSoC 62 doesn't support DDR feature. Thanks for sharing the link about DLP; I did have the correct configuration. It would be nice if DDR support can be added so I can see my work in action

By the way, although datasheet pointed out that LC (CR1[7:6]) bits are volatile, the value persists even after a power cycle (instead of resetting back to default)

Thanks,

Dennis

0 Likes

Hi Dennis,

The below image is from the S25FL256S datasheet -

pastedImage_0.png

Could you please point out exactly where does the datasheet say that the LC bits are volatile?

Regards,

Apurva

0 Likes

Hi Apurva,

My bad. I was looking at Table 17 but forgot the fact that individual bits within a register can be non volatile.

Thanks for all the help,Dennis

0 Likes