PSoC 6 ModusToolbox SMIF Access Not Working on Custom Board

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

cross mob
lock attach
Attachments are accessible only for community members.
JoGr_3160431
Level 1
Level 1
5 replies posted 5 questions asked First question asked

Hello,

I am having issues related to the SMIF block and using it to access a QSPI flash. I am using a PSoC 6 (part number CY9C6247BZI-D54) on a custom board. We are using a Micron flash (part MT25QU512ABB8E12). The project is in ModusToolbox 1.1.

The behavior that I'm seeing is that memory reads do not seem to work reliably. I know _something_ is happening with the buffer, because the values within it change to all 0x00. However, that isn't the expected data. Sometimes, adding an additional delay after the call to ReadMemory() allows the data to reach that buffer, but this doesn't always work.

My project has a custom .cymem file I wrote, based on the S25FL512 .cymem file that the dev board uses. In doing so, I specified read and write commands that are specific for quad data width use, eliminating the need to call quad-enable.

I used the smif_mem.c/h files from the SMIF sample project for ModusToolbox (CE220823_PSoC6_SMIFMemWriteAndRead) as a base and modified them from there. As I mentioned, I no longer need to set a quad enable register. I also removed a few status register reads in ReadMemory, because they can't really show much on a read. In WriteMemory, I added a timeout to the reading the busy flag in the register, reads to both relevant status registers and checks of those values after a write. I also added the ability for it to retry a write, but I've never seen this actually occur.

In use, WriteMemory() seems to work, but ReadMemory() consistently returns with 0x00 in allocated buffer. However, the WriteMemory() is hard to check without an accompanying ReadMemory() to check data against. Behavior I have noticed sometimes is that a call to ReadMemory() will return and have 0x00 in the rxBuffer, and then a later read of that buffer shows something different. My assumption from this is that the busy check allows a read transaction to be "done" before the data arrives. However, this may not be the case.

What I want to know is this: Has anybody gotten a flash device that isn't on the SMIF Configuration tool dropdown to work consistently? What did you do to get that set up and working properly? Do you have to add any delay after a ReadMemory? I went ahead and attached to this my .cymem file and my modified smif_mem.c file in case that helps anybody get some insight into what I'm experiencing here.

0 Likes
1 Solution

Please modify your code in smif_mem.c  to this:

static cy_en_smif_status_t PollTransferStatus(cy_en_smif_txfr_status_t transferStatus)

{

     cy_en_smif_status_t status = CY_SMIF_SUCCESS;

     uint32_t timeout = SMIF_TRANSFER_TIMEOUT;

     while (((uint32_t)transferStatus != Cy_SMIF_GetTxfrStatus(KIT_QSPI_HW, &KIT_QSPI_context)) && ( timeout > 0u))

     {

          Cy_SysLib_DelayUs(CY_SMIF_WAIT_1_UNIT);

          timeout--;

     }

     if((uint32_t)transferStatus != Cy_SMIF_GetTxfrStatus(KIT_QSPI_HW, &KIT_QSPI_context))

     {

          status = CY_SMIF_EXCEED_TIMEOUT;

     }

     return status;

}

void ReadMemory(SMIF_Type *baseaddr,

                            cy_stc_smif_context_t *smifContext,

                            uint8_t rxBuffer[],

                            uint32_t rxSize,

                            uint8_t *address)

{

    cy_en_smif_status_t status;

    while(Cy_SMIF_BusyCheck(baseaddr))

    {

        /* Wait until the SMIF IP operation is completed. */

    }

   

    while(Cy_SMIF_Memslot_IsBusy(SMIF_HW, (cy_stc_smif_mem_config_t*)smifMemConfigs[0], &SMIF_context)) //added per forum recommendation

    {

     /* Wait until the Erase operation is completed */

     }

    /* The 4 Page program command */

    status = Cy_SMIF_Memslot_CmdRead(baseaddr, smifMemConfigs[0], address, rxBuffer, rxSize, NULL, &SMIF_context);

    CheckStatus("\r\n\r\nSMIF Cy_SMIF_Memslot_CmdRead failed\r\n",status);

   

    if(CY_SMIF_SUCCESS == status)

    {

        /* Wait until the SMIF block completes receiving data */

        status = PollTransferStatus(CY_SMIF_REC_CMPLT);

    }

}

The Cy_SMIF_Memslot_CmdRead() uses Cy_SMIF_TransmitCommand() and then Cy_SMIF_ReceiveData() to perform the read operation and hence you need to use the Cy_SMIF_GetTxfrStatus() to poll for the status of receiving data.

Regards,

Dheeraj

View solution in original post

0 Likes
4 Replies
DheerajK_81
Moderator
Moderator
Moderator
First comment on KBA First comment on blog 5 questions asked

For the Write operation, check that the SMIF driver has completed transferring by calling Cy_SMIF_BusyCheck(). Also, check that the memory is available with Cy_SMIF_Memslot_IsBusy() before proceeding to read operations.

Please share your project and the datasheet of the memory chip to get more insight into the issue.

Regards,

Dheeraj

0 Likes
lock attach
Attachments are accessible only for community members.

I tried adding the busy checks as instructed and saw no change. I also attempted to add more checks before and after each write and read to no avail.

I have attached to this reply pared down iteration of my project with only memory access related files left in place. I also attached the datasheet for my flash. The third attachment shows the terminal output of this test.

Specifically I attempt to write data, then read it back three times, then check the three reads against each other and against the written data at a given address. If all four buffers match, the address is increased by the page size and the test is repeated. It stops once there is a mismatch.

0 Likes

Issue I found after posting this: An erase is needed before calling WriteMemoryReliable(). The issue I'm seeing still appears above, since consecutive reads to the same address should always return the same data, but writing of course will likely fail.

This line should be added:

EraseMemory(SMIF_HW, (cy_stc_smif_mem_config_t*)smifMemConfigs[0], address, &SMIF_context );

Best,

Josh

0 Likes

Please modify your code in smif_mem.c  to this:

static cy_en_smif_status_t PollTransferStatus(cy_en_smif_txfr_status_t transferStatus)

{

     cy_en_smif_status_t status = CY_SMIF_SUCCESS;

     uint32_t timeout = SMIF_TRANSFER_TIMEOUT;

     while (((uint32_t)transferStatus != Cy_SMIF_GetTxfrStatus(KIT_QSPI_HW, &KIT_QSPI_context)) && ( timeout > 0u))

     {

          Cy_SysLib_DelayUs(CY_SMIF_WAIT_1_UNIT);

          timeout--;

     }

     if((uint32_t)transferStatus != Cy_SMIF_GetTxfrStatus(KIT_QSPI_HW, &KIT_QSPI_context))

     {

          status = CY_SMIF_EXCEED_TIMEOUT;

     }

     return status;

}

void ReadMemory(SMIF_Type *baseaddr,

                            cy_stc_smif_context_t *smifContext,

                            uint8_t rxBuffer[],

                            uint32_t rxSize,

                            uint8_t *address)

{

    cy_en_smif_status_t status;

    while(Cy_SMIF_BusyCheck(baseaddr))

    {

        /* Wait until the SMIF IP operation is completed. */

    }

   

    while(Cy_SMIF_Memslot_IsBusy(SMIF_HW, (cy_stc_smif_mem_config_t*)smifMemConfigs[0], &SMIF_context)) //added per forum recommendation

    {

     /* Wait until the Erase operation is completed */

     }

    /* The 4 Page program command */

    status = Cy_SMIF_Memslot_CmdRead(baseaddr, smifMemConfigs[0], address, rxBuffer, rxSize, NULL, &SMIF_context);

    CheckStatus("\r\n\r\nSMIF Cy_SMIF_Memslot_CmdRead failed\r\n",status);

   

    if(CY_SMIF_SUCCESS == status)

    {

        /* Wait until the SMIF block completes receiving data */

        status = PollTransferStatus(CY_SMIF_REC_CMPLT);

    }

}

The Cy_SMIF_Memslot_CmdRead() uses Cy_SMIF_TransmitCommand() and then Cy_SMIF_ReceiveData() to perform the read operation and hence you need to use the Cy_SMIF_GetTxfrStatus() to poll for the status of receiving data.

Regards,

Dheeraj

0 Likes