QSPI flash support -custom S5D9

Greetings,

We are running into an error when trying to call  api ->pageprogram NOR flash device MT25Q512 with Custom S5D9,it always errors as SSP_ERR_UNSUPPORTED,I am not getting which mode is not supported .How do I add supported mode.

I run this hal application project of (s7Gk )  https://www.renesas.com/eu/en/software/D6001438.html on S5D9-PK kit,which is using windbond W25Q64FV,So its different from MT25Q512 since windboand nor flash is obsolete.We are using MT25Q.I am able to run this project on s5d9-PK successfully,it writes and read back too, 

Can suggest what can be the cause to SSP_ERR_UNSUPPORTED error .

I have observerd below,

1.SFMSDC register initialize value that is (0x000020c4)remains same after page write and read api executed in Example project,while in my project case,qspi.zip

this register initial value is  (0x000020c4) and when call to pageprogram api, SFMSDC register values changes to (0x0000ff04) 

 

2.Supply to IC is Ok.

 Please Assist me to correct the pageprogram error . 

  • In reply to Alex:

    It is in the HW manual, The QSPI ROM window :-

    and the effect that the number of address bytes has :-

  • In reply to Jeremy:

    I am not sure how much I understood this map. I have couple of queries.

    Does it mean that to be able to write to the external flash device,  address should be in the range of 0x0000 0000 to 0xFC00 0000?

    In the application example why base address of qspi (0x6000 0000 ) is used.so is the data written from this base address? Till which address is it written.

    Where can I actually see this addresses and it updated written contents.

  • In reply to Alex:

    The QSPI pageprogram API expects the write address to have an offset of 0x60000000 :-

    E.g. to program address 0 in the QSPI device, the QSPI pageprogram API would be called with the device address set to 0x60000000.

    To read back from address 0 in the QSPI device, with the QSPI peripheral in ROM access communication mode, the CPU could directly read from address 0x60000000 assuming QSPI_EXT[5:0] = 0 (since you have a 64MB QSPI memory device, there is no need to change QSPI_EXT[5:0] from 0)

  • In reply to Jeremy:

    Sorry ,in my yesterdays reply ,i sent one zero less in device_physical address.
    from the begining ,I have set


    #define BUFFER_LENGTH (32)
    #define CLEAR (0x00)
    #define QSPI_DEVICE_ADDRESS (0x60000000)


    for (uint8_t i = 0; i < BUFFER_LENGTH; i++)
    {
     writeBuffer[i] = i;
     readBuffer[i] = CLEAR;
     directreadBuffer[i] = CLEAR;
    }


    err = g_qspi0.p_api->open(g_qspi0.p_ctrl, g_qspi0.p_cfg);

    err = g_qspi0.p_api->sectorErase(g_qspi0.p_ctrl, (uint8_t *) QSPI_DEVICE_ADDRESS);

    err = g_qspi0.p_api->pageProgram(g_qspi0.p_ctrl, (uint8_t *) QSPI_DEVICE_ADDRESS, writeBuffer, BUFFER_LENGTH);

    if (SSP_SUCCESS != err)
    {

    printf("Could not initiate erase sector, error:%d\n",err);

    }

    err = g_qspi0.p_api->read(g_qspi0.p_ctrl, (uint8_t *) QSPI_DEVICE_ADDRESS, readBuffer, BUFFER_LENGTH);

    if (SSP_SUCCESS != err)
    {

    printf("Could not initiate erase sector, error:%d\n",err);

    }

    err = g_qspi0.p_api->close(g_qspi0.p_ctrl);


    means I am trying to actually write 0x0000 0000 ;

    It still returns SSP_UNSUPPORTED

    Is it possible to see "p_memory_address" in qspi pageProgram() api,

    What I am doing incorrectly/missing?

  • In reply to Alex:

    After calling each API, you need to check the error code returned, and act upon the error code. E.g. you are calling :-

     

    err = g_qspi0.p_api->open(g_qspi0.p_ctrl, g_qspi0.p_cfg);

    err = g_qspi0.p_api->sectorErase(g_qspi0.p_ctrl, (uint8_t *) QSPI_DEVICE_ADDRESS);

    err = g_qspi0.p_api->pageProgram(g_qspi0.p_ctrl, (uint8_t *) QSPI_DEVICE_ADDRESS, writeBuffer, BUFFER_LENGTH);

     

    with no check on the error code returned by any of the API.

    Also, after erasing a sector, or programming a page, you need to check the status of the QSPI device to wait for the operation to finished before :-

     ssp_err_t err;
        uint32_t count;
        bool write_in_progress;

        err = g_qspi0.p_api->open(g_qspi0.p_ctrl, g_qspi0.p_cfg);
        if (SSP_SUCCESS != err)
        {
            while(1); /* TODO - better error handling */
        }

        err = g_qspi0.p_api->sectorErase(g_qspi0.p_ctrl,  (uint8_t *)BSP_PRV_QSPI_DEVICE_PHYSICAL_ADDRESS);
        if (SSP_SUCCESS != err)
        {
            while(1); /* TODO - better error handling */
        }

        count = 0;

        do{
            err = g_qspi0.p_api->statusGet(g_qspi0.p_ctrl, &write_in_progress);
            if (SSP_SUCCESS != err)
            {
                while(1); /* TODO - better error handling */
            }
            R_BSP_SoftwareDelay(500, BSP_DELAY_UNITS_MICROSECONDS); /* Sector erase takes a while, so only check every 0.5 millisecond */
            count++;
        }
        while ((true == write_in_progress) && (STATUS_CHECK_COUNT > count));

        if (STATUS_CHECK_COUNT < count)
        {
            /* Error timeout occurred */
            while(1); /* TODO - better error handling */
        }

    err = g_qspi0.p_api->pageProgram(g_qspi0.p_ctrl,  (uint8_t *)BSP_PRV_QSPI_DEVICE_PHYSICAL_ADDRESS, (uint8_t *)g_write_data,  4 );
        if (SSP_SUCCESS != err)
        {
            while(1); /* TODO - better error handling */
        }

        count = 0;

        do{
            err = g_qspi0.p_api->statusGet(g_qspi0.p_ctrl, &write_in_progress);
            if (SSP_SUCCESS != err)
            {
                while(1); /* TODO - better error handling */
            }
            R_BSP_SoftwareDelay(50, BSP_DELAY_UNITS_MICROSECONDS);
            count++;
        }
        while ((true == write_in_progress) && (STATUS_CHECK_COUNT > count));

        if (STATUS_CHECK_COUNT < count)
        {
            /* Error timeout occurred */
            while(1); /* TODO - better error handling */
        }

        err = g_qspi0.p_api->close(g_qspi0.p_ctrl);
        if (SSP_SUCCESS != err)
        {
            while(1); /* TODO - better error handling */
        }

  • In reply to Jeremy:

    I added some "wait" after each api call ,still same output ,Pageprogram API returns SSP_UNSUPPORTED

    This new hal code  in src/directory

    extern void initialise_monitor_handles(void);

    #define BUFFER_LENGTH       (4)

    #define CLEAR               (0x00)

    #define QSPI_DEVICE_ADDRESS (0x60000000)

    /* This application project showcases How to erase,write and read the QSPI flash device.*/

    void qspi_hal_module_guide_project(void)

    {

       /* variable to save return values for error */

       ssp_err_t         err;

       /* buffer to store read and write values */

       uint8_t           writeBuffer[BUFFER_LENGTH];

       uint8_t           readBuffer[BUFFER_LENGTH];

       uint8_t           directreadBuffer[BUFFER_LENGTH];

       uint32_t count;

       bool              in_progress;

       /* pointer to read directly from ROM */

       const uint8_t *qspi_read_ptr;

       initialise_monitor_handles();

       /* Turn on leds. Leds are connected in sync mode with Micro pins */

       g_ioport.p_api->pinWrite(IOPORT_PORT_01_PIN_12, IOPORT_LEVEL_LOW);

       g_ioport.p_api->pinWrite(IOPORT_PORT_01_PIN_13, IOPORT_LEVEL_LOW);

    /*    g_ioport.p_api->pinWrite(LED_YELLOW_PIN, IOPORT_LEVEL_HIGH);*/

       /* Fill write buffer with test data. Clear read buffers */

       for (uint8_t i = 0; i < BUFFER_LENGTH; i++)

       {

           writeBuffer[i] =  i;

           readBuffer[i] = CLEAR;

           directreadBuffer[i] = CLEAR;

       }

       /* Open QSPI interface */

       err = g_qspi0.p_api->open(g_qspi0.p_ctrl, g_qspi0.p_cfg);

       if (SSP_SUCCESS != err)

       {

         printf("Could not open QSPI interface, error:%d\n",err);

         while (1)

          {

          }

       }

       /* Erase first sector on QSPI flash memory */

       err = g_qspi0.p_api->sectorErase(g_qspi0.p_ctrl, (uint8_t *) QSPI_DEVICE_ADDRESS);

       if (SSP_SUCCESS != err)

       {

        printf("Could not initiate erase sector, error:%d\n",err);

        while (1)

           {

           }

        }

       /* Wait until previous operation ends */

        count = 0;

       do{

           err = g_qspi0.p_api->statusGet(g_qspi0.p_ctrl, &in_progress);

           if (SSP_SUCCESS != err)

           {

               while(1); /* TODO - better error handling */

           }

           R_BSP_SoftwareDelay(500, BSP_DELAY_UNITS_MICROSECONDS); /* Sector erase takes a while, so only check every 0.5 millisecond */

           count++;

       }

       while (in_progress);

       /* Load write buffer data to QSPI flash memory */

       err = g_qspi0.p_api->pageProgram(g_qspi0.p_ctrl, (uint8_t *) QSPI_DEVICE_ADDRESS, writeBuffer, BUFFER_LENGTH);

       if (SSP_SUCCESS != err)

       {

        printf("Could not initiate write a page, error:%d\n",err);

        while (1)

           {

           }

       }

       else

       printf((const char *)"Writing data to QSPI\n");

       /* Wait until previous operation ends*/

       do

       {

          err = g_qspi0.p_api->statusGet(g_qspi0.p_ctrl, &in_progress);

       } while (in_progress);

       if (SSP_SUCCESS != err)

        {

          printf("Could not complete write sector, error:%d\n",err);

          while (1)

               {

               }

        }

       else

       printf((const char *)"Data written\n");

       /* Load QSPI flash memory data to read buffer */

       err = g_qspi0.p_api->read(g_qspi0.p_ctrl, (uint8_t *) QSPI_DEVICE_ADDRESS, readBuffer, BUFFER_LENGTH);

       if (SSP_SUCCESS != err)

       {

          printf("Could not complete read operation, error:%d\n",err);

           while (1)

           {

           }

       }

       printf((const char *)"Reading data from QSPI\n");

       /* Close QSPI interface */

       err = g_qspi0.p_api->close(g_qspi0.p_ctrl);

       if (SSP_SUCCESS != err)

       {

           printf("Could not close the QSPI instance, error:%d\n",err);

           while (1)

           {

           }

       }

       /* Compare write and read buffers */

       for (uint8_t i = 0; i < BUFFER_LENGTH; i++)

       {

           if( writeBuffer[i] == readBuffer[i] )

           {

               printf("readBuffer[%d]:%d\n",i,readBuffer[i]);

           }

       }

    }

    When BSP code  runs one time(clicked on RUN button in debug mode )

    SFMSDC register is 

    SFMXT =1 

    SFMXD=1 

    i.e configured to xip mode 

    But when I click on run button again  and resume operation after i get SSP_UNSUPPORTED error ,XIP mode is disabled 

    Is this expected for qspi?

  • In reply to Alex:

    You need to work out why the call to Pageprogram API returns SSP_UNSUPPORTED. Disable the complier optimisation :-

     

    rebuild the project, debug it, and step into the pageprogram API to work out why it fails.

  • In reply to Jeremy:

    Hi Jeremy,

    Thanks to advice on stepinto pageprogram() api

    I checked qspi_validate_address_range() returned with SSP_ERR_UNSUPPORTED when  calculated memory size is less than qspi flash memory available :

    so for this particlular condition,hovered mouse over all the variable of condition "p_ctrl->total_size_bytes" it shows value: 0 (not sure if its corect)

    BSP_PRV_QSPI_DEVICE_PHYSICAL_ADDRESS  =: (not sure)

    byte_count : 4(which is  what's been passed thro' PageProgram i.e correct)

    device_address :0x6000 0000 (which is  what's been passed thro' PageProgram i.e correct)

    I am not sure about below

    Though Its

      /** Physical address the QSPI device is mapped to */
    #define BSP_PRV_QSPI_DEVICE_PHYSICAL_ADDRESS (0x60000000)

  • In reply to Alex:

    p_ctrl->memory_size is set here in the QSPI api open() :-

     

     

    and then a bit later pctrl->total_size_bytes is set (again in the open() function) :-

    So I would suggest that you need to debug the bsp_qspi_init() and check that it does set everything up correctly.

  • In reply to Jeremy:

    I will have a check on bsp_qspi_init() again

    memory capacity's been read correctly in p_ctrl->memory capacity (I can see its correct value) But it  is not getting copied into p_ctrl->total_size_bytes correctly.Ity shows : 0

    p_ctrl->total_size_bytes = (uint32_t)((uint32_t)1 << p_ctrl->memory_capacity);

    #else
    /* This is for compatibility with a prior implementation of the BSP QSPI code that set spi_mode based on the
    * number of data lines available instead of the current SPI mode. QSPI_PAGE_PROGRAM_DATA_LINES should always be
    * defined for new implementations that use multiple data lines for page program. */
    p_ctrl->data_lines = (uint8_t) p_ctrl->spi_mode;
    #endif

    what is significance of data lines?Is neccessary to change datalines and spi mode if 4-byte addressing is used ?

  • In reply to Alex:

    By default in SPI extended mode page program will only use a single data line. There is no need to change it if 4 byte addressing is enabled. Using more data lines can speed up the programming of the QSPI device.
  • In reply to Jeremy:

    I  checked bsp_qspi_init()..qspi device is set into XiP mode (xip bit of  volatile status register set ),DTR is disabled,status register is read correctly when power on.

    Memory capacity is read correctly ,I dont understand why is it  not just getting copied correctly into p_ctrl->total_size_bytes.

    I am spending time on realising why are there 4 conection (DQ0,DQ1,DQ2,DQ3) in schematic of S5D9-PK for qspi :is it related to data lines configuartion in software.

  • In reply to Alex:

    Quad SPI has upto 4 data lines. How is the QSPI on your board connected? Which QSPI pins are configured in the pin setup for your board?
  • In reply to Jeremy:

    QSPI device is connected via 4 DQ lines(3:0)

    I have configured below pins in "_C only" pingroup for quad operation mode  

    Pins:- P211,P210,P209,P208 - DQ (3:0) lines

              P214 : QSPCLK

             P207 : QSSL 

     

     

  • In reply to Alex:

    Hi Alex-
    Do this last 2 posts of this thread help any? Seems like there may be a similar issue.
    renesasrulz.com/.../qspi-hal-driver-returns-ssp_err_unsupported