128d256

导航

 

一,主要参数

 二,代码示例

1,在英飞凌官网搜索S25FL512SAGMFMG10,除了手册外还可以下载一份驱动代码,fls文件夹里的三个文件就可以作为这款FLASH的驱动层了,见下图。

 

2,fls文件夹里的驱动代码对于不同主设备是通用的,但是它们调用的最底层要重写一下,就是FLASH_READ函数和FLASH_WRITE函数,可以使用Hals\Generic\slld_hal_example.c内给的模板重写一下,如果有软件片选操作的话,片选也可以写入函数里。我这里重写后直接放到slld.c文件了,并且直接命名为FLASH_RD和FLASH_WR,注意这款芯片是64M字节的,需要4字节寻址,因为3字节寻址只能寻到16M字节的空间。在英飞凌的这个库里面,四字节寻址可以使用特定的函数,应该是函数名带4B的那种;也可以在slld_targetspecific.h中定义“

#define USE_4B_ADDR_CMDS”,然后用普通的函数接口就行,我用的是第二种方法,具体情况可以看手册。
// HAL read functions API
static SLLD_STATUS FLASH_RD
(
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 where to store the read data */
int     Number_Of_Read_Bytes                        /* number of bytes to be read */
)
{
    (void)device_num;

    SLLD_STATUS status = SLLD_OK;
    int16_t write_length  = 0;
    int16_t read_length   = 0;
    uint8_t cmd_buffer[5] ={0};

    // Write the command
    write_length  = 1;
    cmd_buffer[0] = command;

    // Write the address
    if (sys_addr != ADDRESS_NOT_USED)
    {
        switch (command)
        {
        case SPI_DUALIO_HPRD_CMD:
        {
            write_length  = 4;
            cmd_buffer[1] = (BYTE)((sys_addr >> 16) & 0x000000FF);
            cmd_buffer[2] = (BYTE)((sys_addr >>  8) & 0x000000FF);
            cmd_buffer[3] = (BYTE)(sys_addr         & 0x000000FF);
            break;
        }
        case SPI_DUALIO_HPRD_4B_CMD:
        {
            write_length  = 5;
            cmd_buffer[1] = (BYTE)((sys_addr >> 24) & 0x000000FF);
            cmd_buffer[2] = (BYTE)((sys_addr >> 16) & 0x000000FF);
            cmd_buffer[3] = (BYTE)((sys_addr >>  8) & 0x000000FF);
            cmd_buffer[4] = (BYTE)(sys_addr         & 0x000000FF);
            break;
        }
        case SPI_QUADIO_HPRD_CMD:
        {
            write_length  = 4;
            cmd_buffer[1] = (BYTE)((sys_addr >> 16) & 0x000000FF);
            cmd_buffer[2] = (BYTE)((sys_addr >>  8) & 0x000000FF);
            cmd_buffer[3] = (BYTE) (sys_addr        & 0x000000FF);
            break;
        }
        case SPI_QUADIO_HPRD_4B_CMD:
        {
            write_length  = 5;
            cmd_buffer[1] = (BYTE)((sys_addr >> 24) & 0x000000FF);
            cmd_buffer[2] = (BYTE)((sys_addr >> 16) & 0x000000FF);
            cmd_buffer[3] = (BYTE)((sys_addr >> 8)  & 0x000000FF);
            cmd_buffer[4] = (BYTE) (sys_addr        & 0x000000FF);
            break;
        }
        default:
        {
            write_length  = 5;
            cmd_buffer[1] = (BYTE)((sys_addr >> 24) & 0x000000FF);
            cmd_buffer[2] = (BYTE)((sys_addr >> 16) & 0x000000FF);
            cmd_buffer[3] = (BYTE)((sys_addr >>  8) & 0x000000FF);
            cmd_buffer[4] = (BYTE) (sys_addr        & 0x000000FF);
            break;
        }
        }
    }

    SPI_set_slave_select(SPI_INSTANCE, SPI_SLAVE);
    // Read the data
    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 the relevant mode
            SPI_transfer_block(SPI_INSTANCE, cmd_buffer, write_length, data_buffer, (uint16_t)Number_Of_Read_Bytes);
            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 the relevant mode
            SPI_transfer_block(SPI_INSTANCE, cmd_buffer, write_length, data_buffer, (uint16_t)Number_Of_Read_Bytes);
            break;
        }
        default:
        {
            // Read the data using the relevant mode
            SPI_transfer_block(SPI_INSTANCE, cmd_buffer, write_length, data_buffer, (uint16_t)Number_Of_Read_Bytes);
            break;
        }
        }
    }
    SPI_clear_slave_select(SPI_INSTANCE, SPI_SLAVE);

    return(status);
}

// HAL write functions API
static SLLD_STATUS FLASH_WR
(
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_Written_Bytes                     /* number of bytes to be written */
)
{
    (void)device_num;

    SLLD_STATUS status = SLLD_OK;
    int16_t write_length  = 0;
    static uint8_t cmd_buffer[1000] ={0};

    // Write the command
    write_length  = 1;
    cmd_buffer[0] = command;

    // Write the address
    if (sys_addr != ADDRESS_NOT_USED)
    {
        write_length  = 5;
        cmd_buffer[1] = (BYTE)((sys_addr >> 24) & 0x000000FF);
        cmd_buffer[2] = (BYTE)((sys_addr >> 16) & 0x000000FF);
        cmd_buffer[3] = (BYTE)((sys_addr >> 8)  & 0x000000FF);
        cmd_buffer[4] = (BYTE) (sys_addr        & 0x000000FF);
    }

    // Write the data
    if (Number_Of_Written_Bytes != 0)
    {
        write_length += Number_Of_Written_Bytes;
        
        if (sys_addr != ADDRESS_NOT_USED)
        {
            for(uint32_t i=0; i<Number_Of_Written_Bytes; i++)
            {
                cmd_buffer[4+1+i] = data_buffer[i];
            }
        }
        else
        {
            for(uint32_t i=0; i<Number_Of_Written_Bytes; i++)
            {
                cmd_buffer[0+1+i] = data_buffer[i];
            }          
        }
    }

    SPI_set_slave_select(SPI_INSTANCE, SPI_SLAVE);
    SPI_transfer_block(SPI_INSTANCE, cmd_buffer, write_length, 0, 0);
    SPI_clear_slave_select(SPI_INSTANCE, SPI_SLAVE);

    return(status);
}

 

3,使用slld_Read_IdentificationCmd函数读取FLASH的ID,这个函数使用0x90命令读取id,调用这个函数主设备发送四个字节,第一个字节是命令0x90,第二到四个字节是地址(全零),之后接收两个字节,即制造商id(0x01)和设备id(0x19)。

 调用这个函数后通过示波器抓取波形如下图(黄色为CLK,绿色为MOSI),解码后可知发送的是0x90,0x00,0x00,0x00。CLK一共有8*6个方波,前8*4个是4字节发送,后8*2个是2字节的接收,这里只给出局部放大图。

观察返回id正确后就能初步判断发送和接收正常了,就可以用其他的接口愉快的玩耍了。

4,贴一下验证的函数吧

    uint8_t wrBuffer[20]={1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10};
    uint8_t rdBuffer[20]={0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0};
    uint8_t ID[5]={0};
    uint8_t crval[1]={255};
    uint8_t sr1val[1]={255};
    uint8_t sr2val[1]={255};
    DEVSTATUS devstatus1;
    DEVSTATUS devstatus2;

{
        slld_RDIDCmd(0, &ID[0], 6);    //读取另一种ID,和上面的id
        slld_RCRCmd(0, &crval[0]);     //读取控制寄存器
        slld_RDSRCmd(0, &sr1val[0]);   //读取状态寄存器
        slld_RDSR2Cmd(0, &sr2val[0]);  //读取状态寄存器2
        slld_SEOp(0, 0x1400000, &devstatus1);  //擦除地址为0x1400000之后的这块扇区,一个扇区为256K字节(地址长度为:0x40000)
        slld_WriteOp(0, 0x1400000, &wrBuffer[0], 20, &devstatus2);  //写入20个字节
        slld_ReadOp(0, 0x1400000, &rdBuffer[0], 20);                //读取写入的字节
}

三,附录

1,lld接口函数

 

 

 

2,CR,SR,SR1寄存器

 

 

 

posted on 2025-06-27 11:23  方悠然  阅读(42)  评论(0)    收藏  举报