记一次 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 ...
随机推荐
- 【Java】手动编写第一个Java程序,HelloWorld!
第一个Java程序HelloWorld! 环境前提:确保你已经配置好了JDK8的环境变量,和本体安装 打开文本编辑器,这里我使用的是EditPlus 编写代码: public class Hello{ ...
- Mac 窗口管理软件 Spectacle
我个人使用的窗口管理软件是 Magnet(本人在 Mac 下付费的首款软件,记得是 6 元~),今天为大家介绍一款类似的开源软件. 简介 Spectacle 是一款可以快速调整窗口大小与位置的开源软件 ...
- Julia基础语法字符和字符串
1.Julia字符串 2.字符
- 学习Salesforce | 带你解锁Superbadge的真正作用
Superbadges是对专业知识和技能的一种认可,通过解决企业在实际业务场景中遇到的复杂问题,展示你的Salesforce专业技能. 要想获得Superbadge,首先需要完成Trailhead徽章 ...
- K - Two Contests
题目连接:https://atcoder.jp/contests/agc040/tasks/agc040_b 大佬题解:https://blog.csdn.net/duanghaha/article/ ...
- 在数组添加元素时报错:IndexError: list index out of range
今天第一次发随笔还有许多不足之处,欢迎评论!!! 最近在写一个成语接龙的小游戏,结果在数组添加元素时报错:IndexError: list index out of range 源码: import ...
- 【学习笔记】splay入门(更新中)
声明:本博客所有随笔都参照了网络资料或其他博客,仅为博主想加深理解而写,如有疑问欢迎与博主讨论✧。٩(ˊᗜˋ)و✧*。 前言 终于学习了 spaly \(splay\) !听说了很久,因为dalao总 ...
- 挑战全网最幽默的Vuex系列教程:第三讲 Vuex旗下的Mutation
写在前面 上一讲「Vuex 旗下的 State 和 Getter」,告诉了我们怎么去使用仓库 store 中的状态数据.当然,光会用肯定还不够,大部分的应用场景还得对这些状态进行操控,那么具体如何操控 ...
- IOC 概念
转摘:https://www.cnblogs.com/DebugLZQ/archive/2013/06/05/3107957.html 博文目录 1.IOC的理论背景 2.什么是IOC 3.IOC也叫 ...
- Java 中正则表达式使用
正则表达式基本用法: 测试代码: @Test public void test01() { String str = "adsfd##4324"; // 创建正则表达式对象 Pat ...