找回密码
 加入我们
搜索
      
查看: 18406|回复: 7

[主板] 自制LPC接口的主板诊断卡

[复制链接]
发表于 2022-4-16 21:35 | 显示全部楼层 |阅读模式
本帖最后由 redstoner35 于 2022-4-17 13:01 编辑

作为一名itx塞服务器平台核手提箱(3175X 350W TDP)的玩家来说,咱是一直很馋ROG主板上面的那个叫做live dash的OLED小屏幕的说(如下图)
批注 2022-04-16 185828.png
这个小屏幕可以在开机之后显示主板当前的自检状态等等的信息,虽然咱的ITX已经有类似的集控中心,上面带一块2.42寸的OLED(见下图)能够显示和采集大量的有关硬件的状态信息,但是苦于之前没有找到相关的资料,通过这个小屏幕实时显示主板的port 80h自检代码(类似IPMI界面内的post snoop)的坑就一直鸽鸽了挺久的。
微信图片_20220310144900.jpg
后面百度了一下,找到了一篇来自CSDN的帖子里面描述了port 80h诊断卡的实现方式。里面提到了可以通过LPC总线以及PCIe到PCI Bridge的方式获取BIOS向IO 0x0080写入的debug数据。这个时候我大概的思路就定下来了,利用类似Intel MAX II这样的CPLD实现LPC总线的译码,然后将译码后的数据写入到芯片内搭建的FIFO中,这个FIFO作为一个I2C从机挂载在咱的集控中心的SMBUS上面,然后集控中心通过SMBUS进行Read FIFO的操作,根据FIFO内的数据翻译到具体的自检项目并显示在OLED屏幕上面。这个时候,首先就要确定如何连接到LPC总线了。那么这个问题就需要去看一下主板说明书的方块图。
批注 2022-04-16 185828.png
图中可以发现,这块主板的TPM接口是引出了LPC总线的,而且总线上同时有SuperIO/BMC等外设。结合永擎在IPMI内提供了port 80h redirection(post snoop)且BMC挂在LPC上面,这说明BIOS必然向LPC总线上的BMC发送了port 80h的自检代码。同时永擎很良心的给出了TPM接口的定义(见下图)这就意味着我们可以通过TPM接口上引出的LPC总线,在LPC总线上挂载一片CPLD进行LPC总线的译码来获取80h的自检代码。
批注 2022-04-16 185828.png
那么在敲定了具体的方案之后,就是测试平台的搭建了,这边我使用了一片板载Intel MAX II(EPM570T144C5N)CPLD的开发板以及那块即将变成EPC621D6X-2L2M(雾)的EPC621D4I-2M主板进行测试,平台的连接如下图。
QQ图片20220416192308.jpg
LPC总线一共有8根需要链接的线,分别是负责传输地址,数据和命令的LPCLAD[3:0](一共四条线)通知外设开始一个新的传输循环的LRFrame#(低电平有效),复位所有LPC外设的LRReset#(低电平有效)以及提供参考电平的GND和为LPC外设提供33MHz PCI时钟的LRCLK,这边因为还在测试期间,就直接用2.54-2.0的杜邦线从主板上面飞线到开发板上去了,虽然看着很丑但是因为LPC总线只有33MHz的CLK速度,时序余量还是相当大的,不会影响解码逻辑和主板端的正常工作。
把线接上去了之后就是开始在牙膏厂的EDA分配IO了,为了避免一些神奇的时序问题,LPCCLK这种时钟引脚需要使用CPLD的GCLK(全局时钟引脚),这边我使用了位于同一个IO Bank的18号引脚,剩下的引脚就随便来了,只要保证在同一个IO Bank就行。最终的引脚分配如下图。
批注 2022-04-16 185828.png
批注 2022-04-16 185828.png
分配完IO之后,就是具体的程序编写了。整个程序一共分为四个部份,分别是针对LPC总线进行port 80h write译码的译码模块,存储译码之后数据并按照需要送出数据的FIFO模块,为主机(我的集控中心)通过SMBUS(I2C)协议读取FIFO提供支持的I2C从机模块,以及驱动数码管显示代码(最终会被砍掉)和类似主板上那种四个LED的Easy debug灯的驱动模块。实际编译好的整个程序的模块结构如下。
批注 2022-04-16 185828.png
其中MAX II IntOSC和CLKMUX是负责为I2C从机模块和数码管扫描驱动提供时钟的部份,因为最终整个检测卡需要塞在TPM模块大小的PCB上面,不一定有空间放置有源晶振。所以在设计程序的时候为时钟源同时准备了MAX II的片内RC振荡器(本来是给片内EEPROM用的,但是也可以拿来输出,给一些低精度要求的东西提供时钟)和外接有源晶振这两种两种时钟源,CLKMUX这个模块会根据外接时钟源的有无自动选择用外部还是内部时钟作为整个模块的时钟源。



在讲完引脚分配之类的信息之后,接着就是整个project的重头戏,也是资料最匮乏的一个部分。就是对LPC总线上host(PCH)向IO port 0x0080(所谓的80h)端口进行写入时主机在LPC总线上发送的各个数据块进行解码,然后把解码后的数据输出的部份。幸好,intel非常大度地在他们的官网上公开了Low Pin Count(LPC)这一总线的接口协议规范,并且给出了LPC总线上面所有可能发生的传输类型的详细定义,这份数据表可以在不签订CNDA和注册开发者账户的情况下免费下载,这使得自己开发解码模块成为了可能。
批注 2022-04-16 185828.png
批注 2022-04-16 185828.png
上图是LPC支持的所有传输类型,其中Firmware Memory Read和Firmware Memory Write是在很久以前用于读写BIOS ROM的协议,因为支持的最大寻址范围有限制,已经不再被使用了,如今的BIOS ROM都是挂在eSPI总线上面的一片SPI Flash。根据一份不能放图的文档内提到的信息,BIOS会通过I/O Write to 0080h的方式向LPC总线上的外设(对于华擎这个板子来说就是BMC)报送BIOS各个自检阶段的输出代码,也就是所谓的POST Code,并且该过程是由主机发起向外设写入。那么意味着我们只需要实现协议中的
Host Initiated I/O Write Cycles这个协议的解码(如下图)即可。
批注 2022-04-16 185828.png

观察协议的数据可以发现,这个协议一共分为7个模块,最开始的首先是Start,这个阶段总线由主机驱动,告诉外设我接下来想发起哪种类型的传输。这个阶段允许值如下所示。因为我们的解码目标是I/O,因此我们这个阶段只需要判断在CLK上升沿的时候,总线上是不是0000就行,是的话就可以继续接受下一个阶段的数据,否则就停住。
批注 2022-04-16 185828.png
接下来就是第二个数据帧,这个帧的目的是告诉外设具体我想干什么,还有我是要读数据还是写数据。如果假设成是快递员去某一栋楼的某个房间取快递或者送快递,那么第一帧的作用是告诉快递员大概在那一层,这一帧的话就是更具体的信息,精确到是这一层的哪个区域,以及快递员是需要收快递还是发快递。那么这个数据帧的话,我们就需要判断主机的意图是不是IO Write,判断的方法很简单,只需要检测总线的第4-2条数据线是不是3'b001电平就行。其中第三第四条数据线都是0表示是目标的操作对象是IO(这层楼的区域),第二条线的1表示数据的方向是主机到IO口,也就是快递员要将快递送给这个房间的主人。
批注 2022-04-16 185828.png
剩下的部分其实就没什么好讲的了,就是快递员到达指定的区域之后,按照快递上的地址(ADDR这一个场,2Byte)的要求在区域内找到具体的房间,然后把快递(数据,1Byte)丢在房间门口之后打电话给主人(第一次TAR,主机将总线借给外设让外设可以发数据告诉主机是否收到)然后等待房间的主人出来拿快递,拿进房间之后主人在电话里告诉快递员我拿到了(SYNC这个场,外设驱动总线告诉主机我收到数据没)然后挂断电话(第二次TAR,外设将总线还给主机)知道了这些部分之后就可以编写出实现整个解码模块的状态机图表,状态机图表如下图所示。
未命名文件(1).png
有了状态机图表之后就可以在EDA内通过Verilog以门级和行为描述方式结合描述出相应的电路,然后综合之后运行仿真,检查逻辑和时序是否存在错误,是否符合协议文档的要求。这边仿真我使用了Quartus内的waveform editor,借助modelsim进行仿真,仿真并修正逻辑错误后就可以进行测试了。
批注 2022-04-16 185828.png
经过EDA综合之后生成的该模块的RTL图
批注 2022-04-16 185828.png
Modelsim仿真时生成的波形图,图中绿色部分为Start帧,0000表示是Memory/DMA/IO操作。红色区域为Cycle+DIR帧,0010表示IO写操作。橙色部分为ADDR帧,一共经过四个时钟周期,写入的数据是0080h,表示向port80h写数据。然后是一共使用两个时钟周期的DATA,图中写入的数据是AAh,最后黑色的部分则是TAR+SYNC帧,经过几次修正后波形已经符合文档中的规定。
QQ图片20220416210641.png
然后就是一些需要注意的部分了。首先是LAD[3:0]送数据的格式。地址帧的时候送数据的顺序是从MSB开始,每次半字节直到LSB。但是数据帧的时候,顺序是反过来的,首先送LSB所在的低半字节,然后送MSB所在的高半字节。因此在写程序的时候需要注意顺序。我这边编写程序采用位拼接的方式组成移位寄存器进行收取数据的操作。收取地址和数据的代码可以参考下面。

地址:IOAddress <= {IOAddress[11:0],LADIN[3:0]};//将地址放入移位寄存器内
数据:PortdataOut <= {LADIN[3:0],PortdataOut[7:4]};//接受数据帧

还有就是对于部分主板,LPC总线上面是没有能响应port 80h请求的外设的。对于这种情况,解码模块就需要产生TAR和SYNC进行外设的模拟。否则LPC Host会认为该端口无法写入从而不继续报送POST码。但是华擎的这张主板不需要,因为BMC会响应Host对port80h的IO写入请求,所以只需要完成接收数据的操作即可。




完成了解码部分之后,剩下的部分就简单的多了。只需要将解码出来的数据放入七段数码管的译码驱动逻辑进行显示和easy debug LED的驱动即可。这个部分就没什么难度了,网上也有大量的例程可以直接抄作业。这俩个模块的部分代码如下。注:Easy Debug LED译码器的代码范围我是根据AMI官方放出的Aptio V通用检查点的文件设置的,并非来自于主板说明书(说明书压根没提这事情,估计是永擎偷懒了hhhhhhh)可能有不准确的地方。
批注 2022-04-16 185828.png
Easy Debug LED译码器
5.PNG
数码管驱动模块(注:这边我使用了带消隐控制的驱动逻辑,在扫描切换到下一位数据的时候会短暂关闭译码器输出,避免数码管的伪影)

说了这么多当然就要附带上实际的演示视频了。不过因为BIOS毒性不支持步2 CPU的原因(0x79然后CATERR,我直呼卧槽)并没有跑到亮屏阶段,但是已经能证明模块正常工作了。下一步的任务就是编写我的集控系统那边的显示模块将代码在集控系统的板载OLED屏幕上面显示。





2022/4/17 更新

经过一上午的layout,直接集成CPLD和TPM2.0模块的解码子板就完成了。这个板子设计是当成TPM模块直接插在主板TPM接口上面,然后I2C通过板子上的两个焊盘飞线接出来。0402阻容件加上BGA封装版本的超小体积版本的MAX II CPLD(EPM570F100C5N)和高密度的四层布线方案把整个模块的体积压缩到了18x21mm,基本不用担心模块太大会卡到什么东西。虽然可用的空间很小,但是我依然保留了包含5个LED的Easy Debug指示灯。这五个指示灯分别显示CPU MEM VGA BOOT(用BDS替代,表示启动项选择)以及进入系统,系统接管主机后的OK指示灯,这样只需要看一眼主板上面的指示灯颜色,就能确定主板当前的自检以及启动状态。
6.PNG
7.PNG

评分

参与人数 1邪恶指数 +6 收起 理由
uuyyhhjj + 6 看不懂

查看全部评分

发表于 2022-4-16 21:56 | 显示全部楼层
太专业了牛
发表于 2022-4-16 21:56 | 显示全部楼层
这才是diy应该有的亚子
发表于 2022-4-16 21:57 | 显示全部楼层
太专业太niubility了,完全看不懂
发表于 2022-4-16 22:05 来自手机 | 显示全部楼层
太专业了,看不懂。点赞!
发表于 2022-4-17 00:07 | 显示全部楼层
楼主,有没有可能把信号改成手机显示?
 楼主| 发表于 2022-4-17 00:19 来自手机 | 显示全部楼层
本帖最后由 redstoner35 于 2022-4-17 12:50 编辑
LHP332 发表于 2022-4-17 00:07
楼主,有没有可能把信号改成手机显示?


这个难度其实很小的。挂个ESP32或者8266之类的东西(BLE透传模块也可以)把数据通过蓝牙/WLAN发走,手机端再开发个APP就能在手机上看了。不过目前我还没这个打算。
发表于 2024-4-10 20:42 | 显示全部楼层
能通过LPC 读取刷新bios嘛???有这种类型编程器嘛?
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

Archiver|手机版|小黑屋|Chiphell ( 沪ICP备12027953号-5 )沪公网备310112100042806 上海市互联网违法与不良信息举报中心

GMT+8, 2025-4-26 09:50 , Processed in 0.012424 second(s), 7 queries , Gzip On, Redis On.

Powered by Discuz! X3.5 Licensed

© 2007-2024 Chiphell.com All rights reserved.

快速回复 返回顶部 返回列表