一,主要参数

二,代码示例
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寄存器



浙公网安备 33010602011771号