记一次 spinor flash 读速度优化
背景
某个项目使用的介质是 spinor
, 其 bootloader
需要从 flash
中加载 os
。
启动速度是一个关键指标,需要深入优化。其他部分的优化暂且略过,此篇主要记录对 nor
读速度的优化过程。
了解现状
接到启动速度优化的任务之后, 首先是了解情况。
当前的 bootloader
实测读速度只有约 4M/s
。
为了加快速度已经尝试过
spinor
驱动改为使用四线读命令读取数据。速度并没有明显改善。待确认改动是否生效。spinor
驱动改为使用dma
搬运数据。尚未修改成功。
计算上限
既然是要深入优化,那知道终点在哪还是很有必要的。
整个读取过程,数据主要是从 spinor
到达 soc
的 spi
控制器,再由 cpu
或 dma
搬运到 dram
中的目标位置。
spinor --> spi控制器 --> cpu/dma --> dram
先来考虑第一段的速度,这里比较好计算。针对当前的 soc
和 flash
的组合,从规格书可得到最高的 spi
时钟频率为 100M = 100 * 10^6
,且读数据可使用 4
线读取,即 soc
和 flash
之间有 4
根数据线在并行传输数据。那么简单算下 100 * 10^6 * 4bit = 400 * 10^6 bit/s = 47.68 MB/s
, 可知极限速度为 47.68 MB/s
。
当然较真一点,发送读命令给 flash
也需要时间,让我们来算下。
一般一个读命令需要 5 bytes
, 即 cmd + addr[3] + dummy
,所以实际的极限速度要考虑每发一次读命令后读取多少数据。读命令是单线传输的,数据是四线传输。假设发一次命令读 nbytes
数据,则命令和数据所占时间的比例为 5:(n/4)
, 那么实际用于传输数据的 clk
就只有 (n/4) / (5 + n/4) * 100M
。4
线传输的情况下每个 clk
可传输 4bit
,从 bit
换算成 byte
再除以 8
,于是速度公式为 (n/4) / (5 + n/4) * 100M * 4 / 8
, 这里要注意对于大小 1MB = 1024*1024 Byte
, 对于时钟 100M = 10^6
。
代入一些具体数据可得
每次读取bytes | 读速度 |
---|---|
64 | 36.33 MB/s |
256 | 44.23 MB/s |
1024 | 46.77 MB/s |
64k | 47.67 MB/s |
1M | 47.68 MB/s |
可以看出,如果每次读取数据量较小,那么发送读命令消耗的时间就不可忽视。每次读取的数据量越大,则读命令对速度造成的整体影响就越小。
后面的部分理论速度暂时没有很明确的计算方式,那暂时先知道完整的数据是这么流动的就可以了。
确认瓶颈
看了下驱动打印出来的确实是 80M
的 clk
和 4
线的读命令,虽然还没调到最高时钟 100M
,但当前 4M/s
也完全对不上,到底是谁出了问题呢?时钟不对?四线没配置成功?驱动存在 bug
? nor flash
物料的问题?
思考一下,要确认到底是谁的锅,最简单明了的方式还是量下波形,不管软件驱动上怎么写,控制器的寄存器怎么配,最终还是得反映在波形上才是最真实的传输效果。接上示波器或逻辑分析仪,看看 spi
线上的情况,是谁的问题就一目了然了。
首先量一下 spi clk
线,可以发现读数据的过程中,clk
的信号不是连续的,在有信号时其频率是正常的,但大部分时间 clk
线上却是没有信号的。再量量数据线,可以确认到确实使用了 4
线读。
问题很明显,spi
控制器是在间歇性读数据,所以虽然读 nor
的时候是 80M
的时钟频率进行读取,但把 spi
的空闲时间计算进去,均摊下来的总的速度就只有 4M/s
了。
那为什么 spi
控制器会间歇性读取而不是一直在读取呢? 这就涉及到刚刚所说的数据流了,spi
控制器本身的 fifo
是有限的,当从 spinor
读取的数据填满 fifo
之后,就必须等着 cpu/dma
把数据取走,腾出 fifo
空间来,才能继续发送指令从 nor
取数据。那么这段空闲时间,应该就是在等 cpu/dma
取数据了。
验证 CPU
有了怀疑方向,那就得看下代码了。目前驱动中使用的是 cpu
来搬运数据,正常读取过程中,cpu
在执行以下代码
while 待读取数据计数值大于0
if (查询spi寄存器,判断到fifo中存在数据)
读取spi fifo寄存器数据,写到dram的buffer中
待读取数据计数值减1
如果是这里成为了瓶颈,那就有两个地方比较有嫌疑,一是读取 spi
寄存器,而是写 dram
。
做点实验确认下
实验一,尝试下把写 dram
的操作去掉,使用如下操作,并由读取前后的 log
时间戳来判断耗时。
while 待读取数据计数值大于0
if (查询spi寄存器,判断到fifo中存在数据)
读取spi fifo寄存器数据
待读取数据计数值减1
重新测试下,发现速度没有明显变化。
实验二,尝试下减少读 spi
寄存器的操作
while 待读取数据计数值大于0
读取spi fifo寄存器数据
待读取数据计数值减1
重新测试下,发现读速度翻倍了,达到了 8M/s
,看来果然是这里成为了瓶颈。没想到 cpu
读个 spi
寄存器竟然这么耗时。
改用 DMA
cpu
太慢,那就指望 dma
了。
先来解决 dma
驱动异常问题,了解下情况,原来这个 dma
驱动的支持是从另一个分支上移植过来的,原本工作正常,到了这个分支就翻车了。
这就是一个找不同的问题了,先比较下两个分支的差异,再将可疑的地方 checkout/cherry-pick
到另一个分支来验证。很快找到了关键因素 dcache
。
这个分支上是默认打开了 dcache
的,可见旧文 记一个bootloader的cache问题,而这就导致了 dma
驱动工作异常。
简单点,关掉 dcache
试试,果然 dma
就正常了。测下速度,达到了 21M/s
。
再测试下不关 dcache
,在配置了 dma
描述符之后,刷一次 cache
再启动 dma
传输,也是正常的了。
优化配置
21M/s
的速度,看来瓶颈还是在 dma
这里。此时可以尝试将 spi clk
从 80M
提高到 100M
,可以发现整体读速度没有变化,这也可以佐证当前瓶颈仍然不在 nor
的读取速度上面。
测个波形看看,果然 clk
线上还是间歇性的,不过空闲时间比之前少了很多。
dma
的速度能不能改进呢? 这就涉及到具体的芯片了,需要深究下 dma
控制器和 spi
控制器的配置。
优化 dma
和 spi
控制器的配置后,dma
从 spi
控制器取数据的速度,终于超过了 80M
时钟下的 spinor
读取速度,将 spi clk
修改为 100M
,测得读速度约 36M/s
。
优化驱动
前面说到,发送读命令给 flash
也需要时间,在 os
中受限于 buffer
大小等,可能会限制每次读取和处理的数据量,但对于 bootloader
来说则完全可以一口气将所需的数据读入,无需分段。
另外可查看驱动中是否有无用的清空 buffer
之类的操作,一并优化掉。
提高时钟
驱动逻辑和寄存器上无法优化之后,还想提速,那么可以试试提高时钟。
提高 cpu
时钟和 dma
时钟,提高后测得速度约 47M/s
,基本就是理论极限了。
但具体能否提高时钟还是得谨慎评估,单个板子可以正常运行,不意味能够稳定量产。
压缩镜像
在读取速度无法进一步优化的情况下,要提高启动速度,那就得减少读入的数据量了。
可以评估下使用压缩的镜像来减少读入的数据量,只要多出的解压时间不长于节省掉的读取 flash
时间,那就是划算的。
是否压缩,选择哪种压缩算法,就跟 io
速度,cpu
解压速度直接相关了,最好经过实测确认,综合启动速度和 flash
占用来选择。
其他
如果是带压缩的镜像,那启动速度就是读取时间+解压时间。
读取时主要是 io
操作,解压则主要是 cpu
操作。那么是否有可能实现边读取边解压,使得总的启动时间进一步缩短呢?这个待研究
blog: https://www.cnblogs.com/zqb-all/p/12824908.html
公众号:https://sourl.cn/4X3jE7
记一次 spinor flash 读速度优化的更多相关文章
- 记一次cocos项目的加载速度优化
半个月前,我们用cosos creator做了一个简单的小游戏,也许算不上小游戏吧..一边学cocos,一边做,几经波折后终于上线了.然鹅,功能是实现了,但是加载速度十分感人(毕竟没经验嘛,无辜脸). ...
- Elasticsearch 调优之 搜索速度优化
本章讨论搜索速度优化:搜索速度与系统资源.数据索引方式.查询方式等多方面 1.为文件系统cache预留足够的内存 1)应用程序一般情况下,读写都会被操作系统“cache” 2)cache保存在物理内存 ...
- dWebpack编译速度优化实战
当你的应用的规模还很小时,你可能不会在乎Webpack的编译速度,无论使用3.X还是4.X版本,它都足够快,或者说至少没让你等得不耐烦.但随着业务的增多,嗖嗖嗖一下项目就有上百个组件了,也是件很简单的 ...
- 记一次针对excel导出的优化
最近发现我们系统导出excel文件时由于是导出百万级数据导出,速度过慢并且内存占用多,故进行了下面的一次优化. 我们使用apache的poi进行excel文件操作 主要耗时: 1.从数据库得到需要导出 ...
- [转]Asp.net mvc 网站之速度优化 -- 页面缓存
网站速度优化的一般方法 由于网站最重要的用户体验就是速度,特别是对于电子商务网站而言. 一般网站速度优化会涉及到几个方面: 1. 数据库优化 — 查询字段简历索引,使用数据库连接池和持久化,现在还有种 ...
- web访问速度优化分析
请求从发出到接收完成一共经历了DNS Lookup.Connecting.Blocking.Sending.Waiting和Receiving六个阶段,时间共计38ms.请求完成之后是DOM加载和页面 ...
- Tone Mapping算法系列二:一种自适应对数映射的高对比度图像显示技术及其速度优化。
办公室今天停电,幸好本本还有电,同事们好多都去打麻将去了,话说麻将这东西玩起来也还是有味的,不过我感觉我是输了不舒服,赢了替输的人不舒服,所以干脆拜别麻坛四五年了,在办公室一个人整理下好久前的一片论文 ...
- Mysql数据库写入数据速度优化
Mysql数据库写入数据速度优化 1)innodb_flush_log_at_trx_commit 默认值为1:设置为0,可以提高写入速度. 值为0:提升写入速度,但是安全方面较差,mysql服务器 ...
- (转)网站速度优化技巧:Nginx设置js、css过期时间
网站速度优化技巧:Nginx设置js.css过期时间 原文:http://www.webkaka.com/blog/archives/Nginx-set-the-expiration-time-for ...
随机推荐
- Git应用详解第九讲:Git cherry-pick与Git rebase
前言 前情提要:Git应用详解第八讲:Git标签.别名与Git gc 这一节主要介绍git cherry-pick与git rebase的原理及使用. 一.Git cherry-pick Git ch ...
- python教程:使用 async 和 await 协程进行并发编程
python 一直在进行并发编程的优化, 比较熟知的是使用 thread 模块多线程和 multiprocessing 多进程,后来慢慢引入基于 yield 关键字的协程. 而近几个版本,python ...
- CodeForces - 913C (贪心)
点完菜,他们发现好像觉得少了点什么? 想想马上就要回老家了某不愿透露姓名的林姓学长再次却陷入了沉思......... 他默默的去前台打算点几瓶二锅头. 他发现菜单上有n 种不同毫升的酒. 第 i 种有 ...
- win10下cuda安装以及利用anaconda安装pytorch-gpu过程
安装环境:win10+2070super 1.Cuda的下载安装及配置 (1)测试本机独立显卡是否支持CUDA的安装,点击此处查询显卡是否在列表中. (2)查看自己是否能右键找到NVIDA控制面板,如 ...
- 3. pkg
程序打包成可执行文件(.exe) 1.) npm install -g pkg 2.) 单个文件:pkg entrance.js ( windows: pkg -t win entrance.js ...
- AI-web-1靶机过关记录
靶机地址:172.16.1.195 Kali地址:172.16.1.107 1.信息收集 端口扫描: 目录扫描: 发现robots.txt敏感文件,查看 存在/m3diNf0/,/se3reTdir7 ...
- Git 创建远程仓库并克隆到本地,创建本地仓库并推送到远程仓库
配置用户信息 配置的是你个人的用户名称和电子邮件地址.这两条配置很重要,每次 Git 提交时都会引用这两条信息,说明是谁提交了更新,会随更新内容一起被永久纳入历史记录 git config --glo ...
- python学习18类4之静态类
'''''''''类的静态方法.普通方法.类方法 静态方法: 用 @staticmethod 装饰的不带 self 参数的方法叫做静态方法,类的静态方法可以没有参数,可以直接使用类名调用. 普通方法: ...
- QtConcurrent::run() 只能运行参数个数不超过5的函数
有时不得不看源码 qtconcurrentrun.h template <typename T, typename Param1, typename Arg1, typename Param2, ...
- CSS开发技巧(三):图片点击缩放
前言 利用CSS实现图片的点击缩放是一个很值得研究的效果.在某些业务需求场景中,我们可能并没有足够的空间展示过大的图片,这就需要限制图片容器的宽度和高度.然而图片限制了宽度,一些图片的细节便又无法看 ...