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

Nor Flash Forum Discussions

vivekion
Level 1
Level 1
First reply posted First question asked Welcome!

Hi team,

I'm getting myself on-boarded with SLLD_v16.2.1 drivers shared for S25FL128LAGMFM000 flash so that I can start porting with host MCU device drivers. While going through the component datasheet and driver code, I came across a few discrepancies.

This is the prototype for FLASH_READ API in slld_hal files:

 

SLLD_STATUS FLASH_READ
(
        BYTE    device_num,                     /* device number to which operation will be done */
        BYTE     command,                        /* write a single command byte to flash */
        ADDRESS  sys_addr,                       /* system address to be used */
        BYTE    *data_buffer,                    /* Pointer to the data buffer containing data to be written */
        int      Number_Of_Read_Bytes            /* number of bytes to be read */
)

 

 Here, one of the arguments is a command that is actually an instruction code as per the datasheet. Now if we see implementation inside it, there are some decision-making based on this same command only for dual/quad/fast mode. Check the code snippet below and different switch case statements based on command in it.

 

{
    SLLD_STATUS status = SLLD_OK;
    int Number_Of_Dummy_Bytes = 0;

    // Select the device - Insert code to drive CS# low
    printf("Drive CS# low\n");
    
    // Write the command - Insert code to write command to the device
    printf("writing command: 0x%X\n", command);

    // Write the address - Insert HAL specific code to write the address to the device
    // in the selected mode based on command type
    if (sys_addr != ADDRESS_NOT_USED)
    {
        switch (command)
        {
            case SPI_DUALIO_HPRD_CMD:
            {
                // Shift out the address two bits at a time in 3-bytes addressing scheme
                printf("Dual address write in 3-bytes addressing scheme, address: 0x%X, command: 0x%X\n", sys_addr, command);
                break;
            }
            case SPI_DUALIO_HPRD_4B_CMD:
            {
                // Shift out the address two bits at a time in 4-bytes addressing scheme
                printf("Dual address write in 4-bytes addressing scheme, address: 0x%X, command: 0x%X\n", sys_addr, command);
                break;
            }
            case SPI_QUADIO_HPRD_CMD:
            {
                // Shift out the address four bits at a time in 3-bytes addressing scheme
                printf("Quad address write in 3-bytes addressing scheme, address: 0x%X, command: 0x%X\n", sys_addr, command);
                break;
            }
            case SPI_QUADIO_HPRD_4B_CMD:
            {
                // Shift out the address four bits at a time in 4-bytes addressing scheme
                printf("Quad address write in 4-bytes addressing scheme, address: 0x%X, command: 0x%X\n", sys_addr, command);
                break;
            }
            case SPI_READ_4B_CMD:
            case SPI_FAST_READ_4B_CMD:
            case SPI_DUALIO_RD_4B_CMD:
            case SPI_QUADIO_RD_4B_CMD:
            {
                // Shift out the address one bit at a time in 4-bytes addressing scheme
                printf("Single address write in 4-bytes addressing scheme, address: 0x%X, command: 0x%X\n", sys_addr, command);
                break;
            }
            default:
            {
                // Shift out the address one bit at a time in 3-bytes addressing scheme
                printf("Single address write in 3-bytes addressing scheme, address: 0x%X, command: 0x%X\n", sys_addr, command);
                break;
            }
        }
    }

    // Write the dummy bytes - Insert HAL specific code to write the dummy bytes to the device
    switch (command)
    {
        case SPI_FAST_READ_CMD:
        case SPI_FAST_READ_4B_CMD:
        case SPI_DUALIO_RD_CMD:
        case SPI_DUALIO_RD_4B_CMD:
        case SPI_QUADIO_RD_CMD:
        case SPI_QUADIO_RD_4B_CMD:
        case SPI_OTPR_CMD:
        {
            Number_Of_Dummy_Bytes = 1;
            // Write a dummy byte to the data bus
            printf("Writing a dummy byte in single mode, command: 0x%X\n", command);
            break;
        }
        case SPI_DUALIO_HPRD_CMD:
        case SPI_DUALIO_HPRD_4B_CMD:
        {
            Number_Of_Dummy_Bytes = 1;
            // Write a dummy byte to the data bus - This is actually the mode bit
            printf("Writing a dummy byte in dual mode, command: 0x%X\n", command);
            break;
        }
        case SPI_QUADIO_HPRD_CMD:
        case SPI_QUADIO_HPRD_4B_CMD:
        {
            Number_Of_Dummy_Bytes = 3;
            // Write 3 dummy bytes to the data bus - The first byte is actually the mode bit
            printf("Writing 3 dummy bytes in quad mode, command: 0x%X\n", command);
            break;
        }
        case SPI_RES_CMD:
        {
            Number_Of_Dummy_Bytes = 3;
            // Write 3 dummy bytes to the data bus
            printf("Writing 3 dummy bytes in single mode, command: 0x%X\n", command);
            break;
        }
        default:
        {
            // Default to no dummy bytes written
            Number_Of_Dummy_Bytes = 0;
            break;
        }
    }

    // Read the data - Insert HAL specific code to read data from the device
    if (Number_Of_Read_Bytes != 0)
    {
        switch (command)
        {
            case SPI_DUALIO_RD_CMD:
            case SPI_DUALIO_RD_4B_CMD:
            case SPI_DUALIO_HPRD_CMD:
            case SPI_DUALIO_HPRD_4B_CMD:
            {
                // Read the data using dual mode
                printf("Read the data using dual mode, command: 0x%X\n", command);
                break;
            }
            case SPI_QUADIO_RD_CMD:
            case SPI_QUADIO_RD_4B_CMD:
            case SPI_QUADIO_HPRD_CMD:
            case SPI_QUADIO_HPRD_4B_CMD:
            {
                // Read the data using quad mode
                printf("Read the data using quad mode, command: 0x%X\n", command);
                break;
            }
            default:
            {
                // Read the data using the single mode
                printf("Read the data using single mode, command: 0x%X\n", command);
                break;
            }
        }
    }

    // Deselect the device - Insert HAL specific code to drive CS# high
    printf("Drive CS# high\n");

    return(status);
}

 

Here I don't understand the coupling between commands and communication modes like dual/quad/QPI SPI. Also, this requires the SPI_HAL function to understand all commands(instructions) and that does not seem like a good HAL function design.

Here, in this snippet, case statements do not take into account all commands(instructions), and therefore at-leat some command functions seem broken. Take the example of slld_RDIDCmd from slld.c file located in device-specific FLL folder.

 

/******************************************************************************
 *
 * slld_RDIDCmd - Read Edentification from SPI Flash
 *
 * This function issues the RDID command to SPI Flash and reads out the ID.
 * On some devices this command is documented in the data sheet as
 * Release from deep power down and read electronic signature
 *
 * RETURNS: SLLD_OK or SLLD_E_HAL_ERROR
 *
 */
SLLD_STATUS slld_RDIDCmd
(
        BYTE      device_num,                     //device number
        BYTE      *target,              /* variable in which to store read data */
        BYTECOUNT  len_in_bytes         /* number of bytes to read */
)
{
    SLLD_STATUS status = SLLD_OK;

#ifdef INCLUDE_SOFTWARE_PROTECT_STATUS_CHECK
    /* check if target device is software protected */
    if(sys_software_protect_status != FLASH_SOFTWARE_UNPROTECTED)
    {
        status = SLLD_E_DEVICE_SOFTWARE_PROTECTED;
        return(status);
    }
#endif

    status = FLASH_RD(device_num,SPI_RDID_CMD, (ADDRESS)ADDRESS_NOT_USED, target, len_in_bytes);

    return(status);
}

 

For instance, slld_RDIDCmd is called with 'len_in_bytes'argument equal to 3. slld_RDIDCmd function calls FLASH_RD function inside it. (FLASH_RD is a macro and actually, FLASH_READ will be called as per a macro setting. I'm not sure about all type of macro settings and when to use them)

Here, the command argument for the FLASH_READ function is SPI_RDID_CMD. The function will execute in this way:

 

Drive CS# low
writing command: 0x9F (RDID 9F command instruction)
(As sys_addr is ADDRESS_NOT_USED, the switch case for address write will be skipped.)
(In the switch case for dummy byte write, as no matching case if there, it will go into default and make Number_Of_Dummy_Bytes = 0)
(As Number_Of_Dummy_Bytes == 0, the control will not go into the switch case for read from device)
Drive CS# high

 

slld_RDIDCmd will not read anything at all.

Questions:

  1. Is the driver SLLD_v16.2.1 the correct and the latest version to be used for S25FL128L?
  2. Is the file referred(slld_hal files) for FLASH_READ and FLASH_WRITE the correct one? Is there any tutorial for porting drivers that I can refer to?
  3. The target of this porting activity is to port the minimum required drivers for our application having minimum possible footprint. Please also let me know if you have any guide or reference for such an optimization also.
0 Likes
1 Solution
AS_36
Moderator
Moderator
Moderator
500 replies posted 250 solutions authored 250 replies posted

Hi @vivekion 

The condition being checked in the last section of the FLASH_READ function is (Number_Of_Read_Bytes != 0), and not (Number_Of_Dummy_Bytes != 0). In the case of slld_RDIDCmd function, when FLASH_READ function is called, the Number_Of_Read_Bytes is coming from len_in_bytes parameter which can be defined by the user. Therefore, the slld_RDIDCmd function will execute properly and provide the required number of bytes of data from the device ID (as specified by len_in_bytes parameter).

The SLLD_v16.2.1 (including all its components such as the HAL files) is the correct and latest version to be used for all Infineon Serial NOR flash devices. There is an slld_hal_example.c file inside the driver which can be referred while modifying the HAL file for your application. There is also an LLD user guide present inside the doc folder of the driver which can referred for porting related topics.

Regards.

View solution in original post

0 Likes
4 Replies
AS_36
Moderator
Moderator
Moderator
500 replies posted 250 solutions authored 250 replies posted

Hi @vivekion 

The condition being checked in the last section of the FLASH_READ function is (Number_Of_Read_Bytes != 0), and not (Number_Of_Dummy_Bytes != 0). In the case of slld_RDIDCmd function, when FLASH_READ function is called, the Number_Of_Read_Bytes is coming from len_in_bytes parameter which can be defined by the user. Therefore, the slld_RDIDCmd function will execute properly and provide the required number of bytes of data from the device ID (as specified by len_in_bytes parameter).

The SLLD_v16.2.1 (including all its components such as the HAL files) is the correct and latest version to be used for all Infineon Serial NOR flash devices. There is an slld_hal_example.c file inside the driver which can be referred while modifying the HAL file for your application. There is also an LLD user guide present inside the doc folder of the driver which can referred for porting related topics.

Regards.

0 Likes
vivekion
Level 1
Level 1
First reply posted First question asked Welcome!

Thanks for replying.

I still have some confuasion regarding how the read will happen because as per the datasheet to read data from the device, dummy bytes are required. 

vivekion_0-1625134989485.png

Here, even if the last section is executing, the last section is not sending any dummy bytes to read over SPI.

0 Likes
AS_36
Moderator
Moderator
Moderator
500 replies posted 250 solutions authored 250 replies posted

Hi @vivekion 

I didn't understand your question. What do you mean by "as per the datasheet to read data from the device, dummy bytes are required"? Do you mean that we need to provide clock cycles to the flash so that the output data (device ID) can be shifted out on SO line?

If my understanding of the question is correct, then the answer would be yes, you do need to provide the required number of clock cycles to the flash so that data can be shifted out on SO line. The HAL file needs to be modified with your microcontroller specific APIs. 

Regards.

0 Likes
vivekion
Level 1
Level 1
First reply posted First question asked Welcome!

Yes, I meant that we need to provide clock cycles to the flash so that the output data (device ID) can be shifted out on SO line? 
So does this mean sending dummy bytes and clocks are different things? 

(Also, can we have a quick call on this? These queries are blockers for us at the moment and the development falls under critical timelines for our customer.)

0 Likes