4 Replies Latest reply on Mar 5, 2019 10:46 PM by DheerajK_81

    PSoC 6 SMIF API Appears To Require Additional Delay

    JoGr_3160431

      Hello,

       

      I am attempting to use a PSoC 6 with an external QSPI Flash Memory via the SMIF hardware module, and I have stumbled onto a strange issue that appears both on my company's custom board and on the PSoC 6 BLE Pioneer Kit board.

       

      The API provides two main vectors by which one can check if the data transfer is complete: Cy_SMIF_BusyCheck(), or via passing in a callback function. The SMIF example project (CE220823_PSoC6MCU_SMIFMemoryWriteandReadOperation) uses the BusyCheck function. However, it appears that these are not correctly identifying the end of data transmission; if the read data is used too quickly after calling for a read, the data will not be as expected. In the sample project, immediately after each write and read, a function prints the entire buffer to terminal (PrintWriteData and PrintReadData). If I remove these print functions, as well as a couple of status register reads and the associated prints of those, the comparison in the sample project fails. If I then replace every commented out section with a static delay via Cy_Syslib_Delay(1000), the comparison succeeds. This implies that the time taken to print the buffer is masking the fact that BusyCheck does not actually indicate if the device is indeed busy.

       

      This all uses the BusyCheck function call, but in my main project I also attempted to use the callback function to similar ends. I have yet to recreate that in this sample, but I could if someone wanted to see it play out.

       

      What I can surmise from all this is that, irrespective of the flash hardware used, the SMIF API fails to accurately generate a signal to inform the processor that data transfer is complete.

       

      My question is this: has anyone else yet used the SMIF interface to interact with a flash device successfully without immediately printing the buffers? Is there a better method to check if data transfer has completed than the two the API seems to offer for you? My current solution is to add long static delays after both the read and the write functions, which hamper performance too much to be used in production.

       

      To this post, I have attached the captured terminal outputs for the three arrangements of the sample project (unmodified being the freshly created sample project, modified being output where various unnecessary checks and prints are removed, and modified_delay_added being where those commented out sections have a seconds worth of delay added to them.) I also attached an archive of the modified sample project.

        • 1. Re: PSoC 6 SMIF API Appears To Require Additional Delay
          DheerajK_81

          This is an issue with the ReadMemory and WriteMemory function in the code example. It is not correctly checking if the command is completed. By adding the printf() in the code, it adds a delay, which gives time for the SMIF to complete the code.

           

          Here is the correct function sequence you need to follow:

           

            /* Set QE */

            smif_status = Cy_SMIF_Memslot_QuadEnable(SMIF_1_HW, (cy_stc_smif_mem_config_t*)smifMemConfigs[0], &SMIF_1_context);

            if(smif_status!=CY_SMIF_SUCCESS)

            {

            handle_error();

            }

            while(Cy_SMIF_Memslot_IsBusy(SMIF_1_HW, (cy_stc_smif_mem_config_t*)smifMemConfigs[0], &SMIF_1_context))

            {

            }

           

          /* The 4 Page program command */

            smif_status = Cy_SMIF_Memslot_CmdRead(SMIF_1_HW, smifMemConfigs[0], arrayAddress, rxBuffer, rxSize, &RxCmpltMemoryCallback, &SMIF_1_context);

            if(smif_status!=CY_SMIF_SUCCESS)

            {

            handle_error();

            }

            while(Cy_SMIF_BusyCheck(SMIF_1_HW))

            {

            }

           

          This will ensure the least time is taken.I have attached the updated smif_mem.c file. Please make the changes mentioned in that and let me know how it goes. We will try to fix this in the next version of the code example.

           

          You said that, "However, it (BusyCheck function) appears that these are not correctly identifying the end of data transmission". Can you elaborate more on what's going wrong?

           

           

          Regards,

          Dheeraj

          • 2. Re: PSoC 6 SMIF API Appears To Require Additional Delay
            JoGr_3160431

            Dheeraj,

             

            Thank you for your prompt reply. However, I'm nearly certain that your solution will not change the issue at hand on the read function, as the only difference is before the actual CmdRead call occurs. In the ReadMemory() function, that precise sequence shown in your message is followed in my edited smif_mem.c, as per the my attached project archive.

             

            This function call should, according to the PDL documentation for the SMIF block, keep the processor waiting until the SMIF hardware block says that data transmission is complete:

             

              while(Cy_SMIF_BusyCheck(SMIF_1_HW))

              {

              }

             

            I argue that it returns the "not busy" value before the SMIF block is actually finished retrieving data and that the call to PrintReadData masks the remaining time necessary. The data in rxBuffer should be ready as soon as that while() loop is exited, but it does not appear to be so.

            • 3. Re: PSoC 6 SMIF API Appears To Require Additional Delay
              DheerajK_81

              Please note the key difference between the two APIs. Cy_SMIF_IsBusy only looks for the SMIF blocks hardware status. The Cy_SMIF_Memslot_IsBusy() sends a status check to the memory slave and checks its WIP status. When not checked you may end up sending a command to the slave when work is still in progress there.

               

              Regards,

              Dheeraj

              • 4. Re: PSoC 6 SMIF API Appears To Require Additional Delay
                DheerajK_81

                To summarize,

                 

                This is an issue with the ReadMemory and WriteMemory function in the code example. It is not correctly checking if the command is completed. By adding the printf() in the code, it adds a delay, which gives time for the SMIF to complete the code.

                 

                Here is the correct function sequence you need to follow:

                 

                  /* Set QE */

                  smif_status = Cy_SMIF_Memslot_QuadEnable(SMIF_1_HW, (cy_stc_smif_mem_config_t*)smifMemConfigs[0], &SMIF_1_context);

                  if(smif_status!=CY_SMIF_SUCCESS)

                  {

                  handle_error();

                  }

                  while(Cy_SMIF_Memslot_IsBusy(SMIF_1_HW, (cy_stc_smif_mem_config_t*)smifMemConfigs[0], &SMIF_1_context))

                  {

                  }

                 

                /* The 4 Page program command */

                  smif_status = Cy_SMIF_Memslot_CmdRead(SMIF_1_HW, smifMemConfigs[0], arrayAddress, rxBuffer, rxSize, &RxCmpltMemoryCallback, &SMIF_1_context);

                  if(smif_status!=CY_SMIF_SUCCESS)

                  {

                  handle_error();

                  }

                  while(Cy_SMIF_BusyCheck(SMIF_1_HW))

                  {

                  }

                 

                This will ensure the least time is taken.I have attached the updated smif_mem.c file. Please make the changes mentioned and it will work. We will try to fix this in the next version of the code example.

                 

                Also please note the key difference between the two APIs. Cy_SMIF_IsBusy only looks for the SMIF blocks hardware status. The Cy_SMIF_Memslot_IsBusy() sends a status check to the memory slave and checks its WIP status. When not checked you may end up sending a command to the slave when work is still in progress there.

                 

                Regards,

                Dheeraj