RL-FLASHFS +W25Q64,F103与F407使用表现差别巨大,找不到原因求助
本帖最后由 littlestone08 于 2024-4-11 19:41 编辑使用W25Q64,
KEIL4 +MDK4,使用标准库,照参考的代码写了驱动后,基本上没有遇到什么问题,运行自带的File_ex1例子,状态非常好。
于是,同样的代码换成STM32F407, 单片机,连引脚名都没有换,结果就悲剧了,表现如下:
[*]运行"dir"命令时非常慢,文件越大越慢,发现是最终是调用了"ffind"最后到驱动的ReadData函数,似乎是把文件的所有内容都枚举了一遍,最要命的是ReadData读一次只读4字节或8字节,但同样在STM32F103上,也是4字节或8字节的调用,就非常快。经过打印驱动调用过程信息对比,M4的单片机上,似乎枚举了文件的所有内容,而F103上只枚举了需要的部分。
[*] 运行"type"命令(程序中逐个字符读取),同样的情况,F103,瞬间读完1000行文本,而F407则是肉眼可见的慢的速度在打印(使用的是SEGGER RTT,非阻塞SKIP)
[*] F103建立好1000行的文本,拆下芯片放到F407的板子上,仅读取和列出,速度依然很慢。而F407建立好的文件的芯片,放到F103的板子上,速度也很快,说明不是芯片上存储内容差异引起的,进一步推论F407的驱动的代码应该也是没有问题的,要不然,把W25Q64换到F103的板子上,多少会出现问题。
[*] 怀疑M3和M4链接的代码不同,但是因为不是开源,也没有办法验证,于是换了KEIL5+RTE+CUBEMX方式,重新实现了一遍,以为能解决问题,折腾好几天,跑通了,在F407上速度与KEIL4上一样的慢。
抓狂了。Q网络上搜索,似乎RL-FLASH +NOR的贴子并不多,更不用说F407指定型号。Q
以上对比是在相同级别的SPI时钟速度上对比(示波器对比),按说,相同的开发环境,库版本,相同的开发环境和驱动,不应该出现这么大的差别。不知道有没有大佬遇到过可以指点一下或讨论下。
如果有需要,我可以贴出代码或以附件的形式给出完整的工程,在此多谢:handshake
看来是发错版块了,看到有一个专门的“文件系统”的版本块,管理如果能挪一下位置最好了。
“文件系统”的那一块也浏览了一个遍,也说EFS有慢的问题,但应该都是可以接受的那种,而我的这个F407上是出奇的不正常。
今天早上又试了一下F103的速度非常的正常,多创建几个“大文件”也是很不错
F4系列确实没有做SPI Flash的FlashFS例子,方便的话,分享你的工程看下。标准库版的就行。 本帖最后由 littlestone08 于 2024-4-12 11:38 编辑
感谢老大回复, 附件如下:
[*]Src_FromSS.zip:项目包,为了减少影响,删减了很多无关的功能,只留下RTT输出,用了RTOS。
[*]comm.zip: 为了方便项目公用RTT,打包在COMM中,项目中打开后可能需要重新修改下里面引用文件的路径。
里面的东西基本上都是F103移过来的,尤其是驱动文件,就担心有些许的不同可能会造成影响。
前两天不知道怎么回事,在SPI长时间访问的时候(比如,执行DIR命令,SPI总线上不停的发出命令),RTT输出就乱了,感觉好像是把缓冲中的数据无规律的发送出来, 不知道如何解决,可能会影响您调试。
-----------
刚抓的效果,与上一个F103的效果对比。可以看到:
[*]建立了三个小文件,就已经无法使用了;
[*]DIR命令输出的时候,越到后面越慢得无法忍受,而且RTT不停的乱输出,我猜测可能是代码中有什么问题,因为这个问题是突然出现的,原来也是同样的慢,也拿不准是不是有关联?
[*]TYPE打印输出时,输出时间越长,每个字符输出速度越慢,1000行的数据时间太久,没法做动图上传上来。
[*]在KEIL5+RTE中,也是同样的慢,但直接使用驱动函数访问存储时明显没有什么问题,速度是可以的。
---------------
老大的回复让我又看见曙光,希望可以有时间指点一番,如果确实不行,我也就死心了:'(
本帖最后由 littlestone08 于 2024-4-12 11:52 编辑
这个图是KEIL5+RTE+DRIVER的形式,使用DIR命令的效果要稍快一点,(KEIL4中 DIR执行后,如果有1000行的数据文件, 会等至少20分钟才能输出),但与F103那个表现正常的比起来,还是差太多了,。
做了一个直接使用DRIVER中的ReadData读数据的功能,看显示的速度来说,函数本身应该是没问题的,DIR命令表现也比KEIL4中的要稍好一点点,但也是不正常。
打印的时候,似乎是越到后面输出越慢,难道是每输出一个字符的时候,都是把前面的都读出来?
(图中有RTT抽风式的间歇输出,会影响分析,请海涵)
-------------
附图
littlestone08 发表于 2024-4-12 10:50
感谢老大回复, 附件如下:
[*]Src_FromSS.zip:项目包,为了减少影响,删减了很多无关的功能,只留下RTT ...
有一种情况不知道你排查了没,标准库使用MDK4里面的FlashFS可以方便的裸机测试,测试过裸机方式没。 没有试,意思是有可能是任务的优先级太低?所以会慢?我抽空就去试一下。测试完了及时反馈,感谢提供思路。
-----------------------------------------
另外,M4和M3的CAN控制器的寄存器应该是差不多的用法吧?我粗粗看了一下手册,应该没有什么特别注意的地方吧?
eric2013 发表于 2024-4-13 09:09
有一种情况不知道你排查了没,标准库使用MDK4里面的FlashFS可以方便的裸机测试,测试过裸机方式没。
已经测试过下面的过程
[*]Keil4裸机执行问题表象无改善
[*]降低过SPI频率,现象无改善
[*]Keil5+MDK5+RTOS2去掉过OS无改善(因为FS-FLASHFS与OS绑定,也是预料之内)
[*]直接使用驱动函数读取数据,无错误数据,速度也很快
[*]以前Keil4中也使用标准库函数实现的替换掉现在使用的寄存器方式的写法,现象相同,所以后来测试都是以寄存器驱动文件为主
-----------
现在经过测试,又设置下面的场景进行测试:
都使用KEIL4环境,F103与F407都格式化,并增加一个10行的小文本文件,保证芯片内容相同,并使用TYPE命令输出,记录ReadData驱动函数的调用次数
现象总结:
日志输出格式为[时间]RdDat:[目标地址]-[长度]...[结束时间OK
[*]初始化文件系统时,调用的ReadData次数相同(正常)
[*]使用的输出函数相同,都是使用putchar单个字符输出,但103的输出是整个文件内容输出了,而F407是与驱动调用部分混合的(不知道为什么)
[*]二者格式化调用EraseSection过程相同(正常)
[*]读取目标文件并打印输出,F407调用ReadData的次数不正常的多。(不正常)
[*]DIR命令时,F407调用ReadData的次数不正常的过多(不正常)
[*]数据量过大后,RTT输出紊乱(不正常)
[*]二块电路板,把W25Q64拆下来互换,重复测试,现象相同(以前也测试过,但是没有记录日志,这次是为了保存RTT日志)
个人分析:
[*]每个字符输出(每个字符在FLASH中占4个字节),似乎都是重新从最原始的SECTOR读取,逐个枚举直到找到目标字符,即想读取第3个字符,似乎有点像链表,不访问前面就访问不了后面,文件中越是到后面的内容,越是读取的次数多。
[*]数一下读取第一个字符,调用了5次ReadData,第二个字符6次,第三个字符7次,佐证分析的第1点,而F103的文件中则没有这样的规划
[*]第7次读取时,F103读取了320个字符,而F407仅读取了1个字符,似乎是F103的程序启用了某种缓存机制,而F407则只是字节直接读FLASH(没有能力分析文件的数据结构)
附件中在完整的TYPE 10.TXT命令后的RTT记录输出。关键点应该是这里望老大分析下。
本帖最后由 littlestone08 于 2024-4-14 19:47 编辑
eric2013 发表于 2024-4-13 09:09
有一种情况不知道你排查了没,标准库使用MDK4里面的FlashFS可以方便的裸机测试,测试过裸机方式没。
因为去掉RTX和不去掉没有什么区别,所以继续使用OS进行测试,由于看现象是因为F407未使用缓存,尝试各任务STACK多增加了1K,Startup.s文件中的定义也增加了一倍,但运行后是问题现象依旧,没有任何改善。
RL-FLASH中NOR的选项很少,尝试找有没有BUFFER开关类似设置的地方,但尝试无果 littlestone08 发表于 2024-4-13 11:16
没有试,意思是有可能是任务的优先级太低?所以会慢?我抽空就去试一下。测试完了及时反馈,感谢提供思路。 ...
F1和F4的CAN一样。 littlestone08 发表于 2024-4-14 11:04
因为去掉RTX和不去掉没有什么区别,所以继续使用OS进行测试,由于看现象是因为F407未使用缓存,尝试各任 ...
驱动上还有一个地方可以看下,就是你看下F4的SPI Flash驱动底层设计,他的SPI上拉电阻使能没。可以使能了试试。 eric2013 发表于 2024-4-16 08:50
驱动上还有一个地方可以看下,就是你看下F4的SPI Flash驱动底层设计,他的SPI上拉电阻使能没。可以使能了 ...
还真没有注意W25Q芯片有上拉电阻使能的地方,我现在就去看手册。 本帖最后由 littlestone08 于 2024-4-20 16:52 编辑
eric2013 发表于 2024-4-16 08:50
驱动上还有一个地方可以看下,就是你看下F4的SPI Flash驱动底层设计,他的SPI上拉电阻使能没。可以使能了 ...
因为修改帖子需要等审核出来,我直接再回复一下。
刚才应该是理解错了,应该说的是F4芯片的SPI接口上拉使能吧。初始化部分是用标准库写的,用的是带上拉的,按说应该没问题。
-----------------
另外,硬汉哥对8楼的那个调用ReadData函数的调用有什么看法吗?因为看起来F407上只会4字节4 字节的读,而且读下一个字符必须要先读出上一个字符,像是磁带的顺序存储一样,这个表现我感觉很关键,因为ReadData是被动调用的,而在F103上就不会这样,就是不知道为什么F407会这样。能抽空看一下?
littlestone08 发表于 2024-4-20 16:27
因为修改帖子需要等审核出来,我直接再回复一下。
刚才应该是理解错了,应该说的是F4芯片的SPI接口上拉 ...
你的F4系列底层也是用的类似这种代码吧
这个是FlashFS提供好的一个驱动
/*
*********************************************************************************************************
*
* 模块名称 : SPI驱动模块
* 文件名称 : SPI_STM32F103.c
* 版 本 : V1.0
* 说 明 : 本驱动是基于bsp_spi_bus.c文件实现。
* (1)使用FlashFS的SPI FLASH文件系统前务必先调用初始化函数bsp_InitSPIBus(在函数bsp.c中初始化)。
* (2)本文件使用的是官方模板,用户只需添加函数功能即可,故不对变量定义和函数名做重新规范。
*
* 修改记录 :
* 版本号日期 作者 说明
* V1.0 2015-09-09 Eric2013正式发布
*
* Copyright (C), 2015-2020, 安富莱电子 www.armfly.com
*
*********************************************************************************************************
*/
#include <File_Config.h>
#include "bsp.h"
/*
**********************************************************************************************************
宏定义
**********************************************************************************************************
*/
/*
SPI 驱动定义
spi0_drv: 第一个SPI设备驱动
spi1_drv: 第二个SPI设备驱动
*/
#define __DRV_IDspi0_drv
#define __FPCLK 72000000
/* SPI_SR位定义 */
#define RXNE 0x01
#define TXE 0x02
#define BSY 0x80
#define FPCLK (__FPCLK/1000)
/* 串行Flsh的片选GPIO端口*/
#define SPI_SelectHard SPI1
#define SF_RCC_CS RCC_APB2Periph_GPIOF
#define SF_PORT_CS GPIOF
#define SF_PIN_CS GPIO_Pin_11
#define SF_CS_0() SF_PORT_CS->BRR = SF_PIN_CS
#define SF_CS_1() SF_PORT_CS->BSRR = SF_PIN_CS
/*
**********************************************************************************************************
宏定义
**********************************************************************************************************
*/
/* SPI驱动接口函数 */
static BOOL Init (void);
static BOOL UnInit (void);
static U8 Send (U8 outb);
static BOOL SendBuf (U8 *buf, U32 sz);
static BOOL RecBuf (U8 *buf, U32 sz);
static BOOL BusSpeed (U32 kbaud);
static BOOL SetSS (U32 ss);
/* SPI 设备驱动控制块 */
SPI_DRV __DRV_ID = {
Init,
UnInit,
Send,
SendBuf,
RecBuf,
BusSpeed,
SetSS,
NULL
};
/*
*********************************************************************************************************
* 函 数 名: Init
* 功能说明: 初始化SPI设备,这里仅初始化了SPI Flash的片选,SPI初始化调用函数bsp_InitSPIBus()实现
* 形 参: 无
* 返 回 值: __TRUE
*********************************************************************************************************
*/
static BOOL Init (void)
{
/*
安富莱STM32-V4 开发板口线分配:串行Flash型号为 W25Q128 (104MHz)
片选 PF8/SF_CS
*/
GPIO_InitTypeDef GPIO_InitStructure;
/* 使能GPIO 时钟 */
RCC_APB2PeriphClockCmd(SF_RCC_CS, ENABLE);
/* 配置片选口线为推挽输出模式 */
SF_CS_1(); /* 片选置高,不选中 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = SF_PIN_CS;
GPIO_Init(SF_PORT_CS, &GPIO_InitStructure);
return (__TRUE);
}
/*
*********************************************************************************************************
* 函 数 名: UnInit
* 功能说明: 卸载SPI设备,正常情况下此函数实现卸载需要将SPI接口设置为初始化状态,即未开启状态。
* 由于多个设备使用SPI接口,这里仅是将片选至高。
* 形 参: 无
* 返 回 值: __TRUE
*********************************************************************************************************
*/
static BOOL UnInit (void)
{
SF_CS_1();
return (__TRUE);
}
/*
*********************************************************************************************************
* 函 数 名: Send
* 功能说明: 发送一个字节数据
* 形 参: 无
* 返 回 值: SPI接口返回值
*********************************************************************************************************
*/
static U8 Send (U8 outb)
{
/* 通过SPI接口读写一个字节 */
SPI_SelectHard->DR = outb;
/* 等待数据接收完毕 */
while (!(SPI_SelectHard->SR & RXNE));
return (SPI_SelectHard->DR);
}
/*
*********************************************************************************************************
* 函 数 名: SendBuf
* 功能说明: 通过SPI接口发送多个字节
* 形 参: buf 数据地址
* sz发送数据大小
* 返 回 值: __TRUE
*********************************************************************************************************
*/
static BOOL SendBuf (U8 *buf, U32 sz)
{
U32 i;
for (i = 0; i < sz; i++)
{
SPI_SelectHard->DR = buf;
/* 等待发送完成 */
while (!(SPI_SelectHard->SR & TXE));
SPI_SelectHard->DR;
}
/* 等待接收完成 */
while (SPI_SelectHard->SR & (BSY | RXNE))
{
SPI_SelectHard->DR;
}
return (__TRUE);
}
/*
*********************************************************************************************************
* 函 数 名: RecBuf
* 功能说明: 通过SPI接口接收多个字节
* 形 参: buf 数据地址
* sz接收数据大小
* 返 回 值: __TRUE
*********************************************************************************************************
*/
static BOOL RecBuf (U8 *buf, U32 sz)
{
U32 i;
for (i = 0; i < sz; i++)
{
SPI_SelectHard->DR = 0xFF;
/* 等待接收完成 */
while (!(SPI_SelectHard->SR & RXNE));
buf = SPI_SelectHard->DR;
}
return (__TRUE);
}
/*
*********************************************************************************************************
* 函 数 名: BusSpeed
* 功能说明: 设置SPI速度,驱动SPI Flash使用的是18MHz
* 形 参: buf 数据地址
* sz接收数据大小
* 返 回 值: __TRUE
*********************************************************************************************************
*/
static BOOL BusSpeed (U32 kbaud)
{
U8 br;
if (kbaud >= FPCLK / 2) br = 0; /* FPCLK/2 */
else if (kbaud >= FPCLK / 4) br = 1; /* FPCLK/4 */
else if (kbaud >= FPCLK / 8) br = 2; /* FPCLK/8 */
else if (kbaud >= FPCLK / 16)br = 3; /* FPCLK/16 */
else if (kbaud >= FPCLK / 32)br = 4; /* FPCLK/32 */
else if (kbaud >= FPCLK / 64)br = 5; /* FPCLK/64 */
else if (kbaud >= FPCLK / 128) br = 6; /* FPCLK/128*/
else br = 7; /* FPCLK/256*/
SPI_SelectHard->CR1 = (SPI_SelectHard->CR1 & ~(7 << 3)) | (br << 3);
return (__TRUE);
}
/*
*********************************************************************************************************
* 函 数 名: BusSpeed
* 功能说明: 设置SPI速度,驱动SPI Flash使用的是18MHz
* 形 参: ss
* 0 表示选中设备
* 1 表示取消选中
* 返 回 值: __TRUE
*********************************************************************************************************
*/
static BOOL SetSS (U32 ss) {
if(ss == 0)
{
bsp_SpiBusEnter(); /* 占用SPI总线, 用于总线共享 */
bsp_SPI_Init(SPI_Direction_2Lines_FullDuplex | SPI_Mode_Master | SPI_DataSize_8b
| SPI_CPOL_High | SPI_CPHA_2Edge | SPI_NSS_Soft | SPI_BaudRatePrescaler_4 | SPI_FirstBit_MSB);
SF_CS_0();
}
else
{
SF_CS_1();
bsp_SpiBusExit(); /* 释放SPI总线, 用于总线共享 */
}
return (__TRUE);
}
/***************************** 安富莱电子 www.armfly.com (END OF FILE) ******************************** eric2013 发表于 2024-4-21 00:47
你的F4系列底层也是用的类似这种代码吧
这个是FlashFS提供好的一个驱动
感谢硬汉大佬。
我以前用过这个类似的代码试过,不过和我原来的效果不多,所以就还用我当前的代码试。
我现在用这个代码再试下,反馈结果上来。如果还不行,暂时放弃,想办法用下littleFS了。
页:
[1]