<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Debian 5.4 内核 H618&#x2F;H616 高速 SPI 小屏幕实战，ST7789V 跑上 60FPS 折腾总结]]></title><description><![CDATA[<p dir="auto">主要还是得靠AI，我是第一次玩这东西，坑很多，但是吧最后都填平了，只不过ai被我撸爆了<br />
Orangepi Zero 2W这个板子 H618芯片，板子上的pin接的一个spi屏幕<br />
最终效果<br />
&lt;iframe src="<a href="//player.bilibili.com/player.html?isOutside=true&amp;aid=116542847064811&amp;bvid=BV11sRSBDErM&amp;cid=38205524172&amp;p=1">//player.bilibili.com/player.html?isOutside=true&amp;aid=116542847064811&amp;bvid=BV11sRSBDErM&amp;cid=38205524172&amp;p=1</a>" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"&gt;&lt;/iframe&gt;</p>
<p dir="auto">这种Linux板子本身输出是走hdmi的所以对这种spi小屏幕支持得特别不好<br />
我刚开始走驱动的时候把lvgl接进去跑刷出来是0fps，从上往下一页一页刷，简直了</p>
<p dir="auto">这个不是CPU的锅，是驱动的问题，这驱动太老了，本声就是点个亮用的<br />
所以光靠我肯定搞不定，我是撸ai，成功搞定的</p>
<p dir="auto">现在留个总结在这里，以后谁遇上了也有个参考</p>
<p dir="auto">结果是可以跑到60fps，80mhz spi</p>
<p dir="auto">简单总结一下原理<br />
一次刷全屏数据，spi频率要拉满，然后需要单出一个线程专门处理dma刷过来的数据，简单点说就是开一次门以后就别关了，有数据就直接进来刷进去，驱动主要慢也就在这，每次刷数据都是找钥匙，开门，数据刷，再关门，神仙也快不起来</p>
<p dir="auto">下面是ai总结的，应该很全面了</p>
<p dir="auto">一、硬件环境<br />
Orange Pi Zero 2W<br />
H618/H616<br />
官方 Debian 5.4 内核<br />
屏幕：<br />
ST7789V<br />
240x280 SPI LCD</p>
<p dir="auto">二、别直接上 Mainline / tinyDRM</p>
<p dir="auto">反正我在armbain系统上没成功，即便成功了也没有我现在改的驱动快<br />
Failed to setup spi<br />
EINVAL<br />
三、真正能跑流畅的关键：不是 LVGL，而是 SPI</p>
<p dir="auto">原因：</p>
<ul>
<li>syscall 开销</li>
<li>SPI transfer 切碎</li>
<li>小块刷新太多</li>
<li>DC 切换频繁</li>
</ul>
<p dir="auto">最后 CPU 都耗在 ioctl 上。</p>
<p dir="auto">四、真正有效的路线：fb_st7789v + framebuffer</p>
<p dir="auto">最终稳定能跑的几个关键参数：<br />
spi-max-frequency = &lt;80000000&gt;;<br />
fps = &lt;60&gt;;<br />
txbuflen = &lt;131072&gt;;</p>
<h1>六、真正决定 FPS 的核心：改驱动，单独 DMA 刷新线程</h1>
<p dir="auto">这里其实才是整个项目最关键的部分。</p>
<p dir="auto">一开始：</p>
<p dir="auto">text fb_st7789v</p>
<p dir="auto">虽然能显示。</p>
<p dir="auto">但：</p>
<p dir="auto">text LVGL 一动就掉帧 SPI write 阻塞 CPU 占用高 动画一卡一卡</p>
<p dir="auto">后来发现：</p>
<p dir="auto">text 问题根本不是 SPI 频率 而是刷新机制。</p>
<p dir="auto">默认：</p>
<p dir="auto">text fb_st7789v</p>
<p dir="auto">很多刷新逻辑实际上是：</p>
<p dir="auto">text 谁调用刷新 谁阻塞等待 SPI DMA 完成</p>
<p dir="auto">这意味着：</p>
<p dir="auto">text LVGL render SPI flush DMA wait</p>
<p dir="auto">全部串行。</p>
<p dir="auto">结果：</p>
<p dir="auto">text CPU 大量时间卡在 SPI wait 上。</p>
<hr />
<p dir="auto">后来直接开始改驱动。</p>
<p dir="auto">核心思路：</p>
<h1>不让 LVGL 线程直接刷 SPI</h1>
<p dir="auto">而是：</p>
<p dir="auto">text 单独创建 DMA 刷新线程</p>
<p dir="auto">流程变成：</p>
<p dir="auto">text LVGL   ↓ 只提交 dirty buffer   ↓ 放入刷新队列   ↓ 独立 DMA thread   ↓ 后台 SPI DMA 刷新</p>
<p dir="auto">这样：</p>
<p dir="auto">text LVGL 渲染</p>
<p dir="auto">和：</p>
<p dir="auto">text SPI DMA 发送</p>
<p dir="auto">彻底解耦。</p>
<hr />
<h1>改完以后最大的变化</h1>
<p dir="auto">原来：</p>
<p dir="auto">text LVGL flush_cb</p>
<p dir="auto">会卡住。</p>
<p dir="auto">改完：</p>
<p dir="auto">text flush_cb</p>
<p dir="auto">基本只负责：</p>
<ul>
<li>标记 dirty</li>
<li>提交 buffer</li>
<li>立即返回</li>
</ul>
<p dir="auto">真正 SPI DMA：</p>
<p dir="auto">text 后台线程异步跑。</p>
<p dir="auto">这个提升非常大。</p>
<hr />
<h1>为什么这个方法效果这么明显</h1>
<p dir="auto">因为 SPI LCD 真正慢的是：</p>
<p dir="auto">text SPI transfer 时间</p>
<p dir="auto">而不是：</p>
<p dir="auto">text CPU 渲染</p>
<p dir="auto">尤其：</p>
<p dir="auto">text 240x280 RGB565</p>
<p dir="auto">全屏：</p>
<p dir="auto">text 240 × 280 × 2 ≈ 134KB</p>
<p dir="auto">60FPS：</p>
<p dir="auto">text 134KB × 60 ≈ 8MB/s</p>
<p dir="auto">已经非常接近 SPI 极限。</p>
<p dir="auto">所以：</p>
<p dir="auto">text 减少阻塞 减少等待 DMA后台化</p>
<p dir="auto">比：</p>
<p dir="auto">text 单纯提高 SPI 频率</p>
<p dir="auto">更重要。</p>
<hr />
<h1>后面进一步优化的方向</h1>
<p dir="auto">目前还准备继续：</p>
<h2>1. DMA 双缓冲</h2>
<p dir="auto">也就是：</p>
<p dir="auto">text ping-pong buffer</p>
<p dir="auto">SPI 刷当前 buffer 的时候：</p>
<p dir="auto">text LVGL 同时渲染下一帧</p>
<p dir="auto">进一步减少等待。</p>
<hr />
<h2>2. partial refresh</h2>
<p dir="auto">目前已经：</p>
<p dir="auto">text 只刷 dirty area</p>
<p dir="auto">但后面准备：</p>
<p dir="auto">text 合并区域 减少 transaction 次数</p>
<p dir="auto">因为：</p>
<p dir="auto">text SPI transaction 次数</p>
<p dir="auto">很多时候比：</p>
<p dir="auto">text SPI 频率</p>
<p dir="auto">更影响 FPS。</p>
<hr />
<h2>3. 更激进 DMA</h2>
<p dir="auto">目前：</p>
<p dir="auto">text fb_st7789v</p>
<p dir="auto">本质上还是：</p>
<p dir="auto">text Linux framebuffer</p>
<p dir="auto">后面甚至考虑：</p>
<p dir="auto">text 自己写 ultra-light SPI DMA framebuffer</p>
<p dir="auto">直接绕过大量 framebuffer/fbtft 历史包袱。</p>
<hr />
<h1>最终结论</h1>
<p dir="auto">最后发现：</p>
<p dir="auto">text 真正让 SPI 小屏跑流畅的 不是 LVGL 不是 tinyDRM 甚至不只是 SPI 频率</p>
<p dir="auto">而是：</p>
<p dir="auto">text 刷新架构。</p>
<p dir="auto">尤其：</p>
<p dir="auto">text DMA 异步线程化</p>
<p dir="auto">提升非常明显。</p>
<p dir="auto">需要驱动源码的给我私信吧，改了不少东西，可以直接把整个sd卡的img镜像给你</p>
]]></description><link>https://bbs.aw-ol.com/topic/6996/debian-5-4-内核-h618-h616-高速-spi-小屏幕实战-st7789v-跑上-60fps-折腾总结</link><generator>RSS for Node</generator><lastBuildDate>Mon, 11 May 2026 11:34:57 GMT</lastBuildDate><atom:link href="https://bbs.aw-ol.com/topic/6996.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 09 May 2026 13:57:42 GMT</pubDate><ttl>60</ttl></channel></rss>