BSP

关于QSPI的BUG,以及BSP驱动W25Q256FV的问题

发布于 2020-06-19 08:48:37
    本帖最后由 yushigengyu 于 2020-6-19 09:25 编辑


最近项目用来了QSPI驱动W25Q256FV这款芯片。
由于SFUD有这款芯片的驱动,就找了bsp stm32l475-atk-pandora下的port
烧录后的现象是可以识别芯片,但是读写不正常。


然后就仔细检查了port文件:

有bug的是下面一段代码

void w25qxx_enter_qspi_mode(struct rt_qspi_device *device)
{
char status = 0;
/* 0x38 enter qspi mode */
char instruction = 0x38;
char write_status2_buf[2] = {0};

/* 0x31 write status register2 */
write_status2_buf[0] = 0x31;

status = w25qxx_read_status_register2(device);
if (!(status & 0x02))
{
status |= 1 << 1;
w25qxx_write_enable(device);
write_status2_buf[1] = status;
rt_qspi_send(device, &write_status2_buf, 2);
rt_qspi_send(device, &instruction, 1);
rt_kprintf("flash already enter qspi mode\n");
rt_thread_mdelay(10);
}
}
rt_qspi_send(device, &write_status2_buf, 2) 是明显有问题的,修改成rt_qspi_send(device, write_status2_buf, 2);
本以为问题就解决了,但是没想到还一直有问题。没办法,接上逻辑分析仪,看了下时许,发现rt_qspi_send(device, write_status2_buf, 2)这句spi没有发送对应指令,这个指令是开启QSPI,问题应该在这里。
一开始没想是内核代码的问题,一追踪才发现,QSPI内核代码有这样的判断
 if (length > 1)
{
if (device->config.medium_size > 0x1000000 && length >= 5)
{
/* medium size greater than 16Mb, address size is 4 Byte */
message.address.content = (ptr[1] << 24) | (ptr[2] << 16) | (ptr[3] << 8) | (ptr[4]);
message.address.size = 32;
message.address.qspi_lines = 1;
count += 4;
}
else if (length >= 4)
{
/* address size is 3 Byte */
message.address.content = (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
message.address.size = 24;
message.address.qspi_lines = 1;
count += 3;
}
else
{
return -RT_ERROR;
}
}

所以当length>1后,内核认为一定存在address,所以对于2-3长度的数据都不予处理,直接报错,所以这rt_qspi_send(device, write_status2_buf, 2);这句直接报错返回了。
这显然是不合理的,先不说在send函数中做了逻辑判断。关键是qspi发送就不应该有这个逻辑,个人理解这里应该qspi内核的一个bug。

这里rt_qspi_send(device, write_status2_buf, 2)对应的是如下时序,

20200619092423.jpg

也是开启芯片QSPI的方法。
至于为什么有的人可以驱动成功,我也查了一些资料,有人说W25Q256有JV和FV两种,JV不需要开启QSPI就可以用QSPI读取,而FV需要开启,不知道是不是这原因导致.

这边为了让驱动能正确运行,我临时修改了一点代码,只是临时解决下问题:
    if (length > 1)
{
if (device->config.medium_size > 0x1000000 && length >= 5)
{
/* medium size greater than 16Mb, address size is 4 Byte */
message.address.content = (ptr[1] << 24) | (ptr[2] << 16) | (ptr[3] << 8) | (ptr[4]);
message.address.size = 32;
message.address.qspi_lines = 1;
count += 4;
}
else if (length >= 4)
{
/* address size is 3 Byte */
message.address.content = (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
message.address.size = 24;
message.address.qspi_lines = 1;
count += 3;
}else if(length == 2){
message.address.content = 0 ;
message.address.qspi_lines = 0;
message.address.size = 0;
}else
return -RT_ERROR;
}


查看更多

关注者
0
被浏览
248
1 个回答
cychen
cychen 2020-07-20

这个问题我很早就发过

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友