UEFI开发探索20 – 串口通信

(请保留->发布地址: http://yiiyee.cn/blog/author/luobing/ )

串口可能是生命力最强的接口标准了,从1980年到现在,仍旧在发挥巨大的作用。特别是工业环境下,可说是王者标准了。

前几年开发过网络转串口,我惊奇的发现很多金融场合也在用串口。

扯远了,回到UEFI下的串口通信。

1 Shell命令查看串口

我的开发环境仍旧是虚拟机winxp+UDK2010,一直没有时间去搭建UDK2018。UEFI Shell中有个命令Sermode,可以查看以及设置串口参数。

图1 TianoCore模拟环境中枚举串口

设备管理器中有两个串口,TianoCore的模拟环境中也列出了两个串口。下面的问题是,如何与虚拟机中的串口通信?

2 与虚拟机中的串口通信

有段时间我学习使用windbg,用来调试驱动代码。它可以配合虚拟机调试OS的执行情况,或者进行内核态的源代码调试。

Windbg使用的是命名管道来与虚拟机通信,这给了我一定的启示。我开发了一个小工具,用来读写命名管道。虚拟机常用的管道名称是,\\.\pipe\com_1,如下图所示。

图2 宿主机与虚拟机的串口通信

这样就把虚拟机和宿主机的串口通信通道打通了。当然,也可以直接用两台计算机用串口进行通信,不过现在有串口的机器都比较少,比较难找。

3 UEFI下的串口函数

串口的协议比较简单,网上也有大把的资料说明。没有必要一一解释其原理,我主要还是关注UEFI下操作串口的函数。

UEFI Spec的12.8 Serial I/O protocol中很详细的描述了相关的串口函数。

图3 Serial IO Protocol (UEFI Spec 2.8 page 466)

按照Spec的说明,编写了读写的函数,以及测试用的函数:

EFI_STATUS DisplayAllSerialMode(void);
EFI_STATUS DisplaySerialMode(void);
EFI_STATUS SendDataToSerial(UINTN length,VOID *buffer);
EFI_STATUS GetDataFromSerial(UINTN *length,VOID *buffer);
EFI_STATUS SetSerialPortAttrib(UINT64 BaudRate, EFI_PARITY_TYPE Parity,UINT8 DataBits, EFI_STOP_BITS_TYPE StopBits);

第一个函数把系统上的所有串口信息打印出来,类似于Sermode的枚举功能。剩余的几个函数只使用第一个找到的串口,对其进行读写。

这种操作方式让我有点不习惯。以前编写串口程序,不管是windows app还是单片机,习惯都是先打开串口设备。而在UEFI下,在枚举Handle的过程中,每个Handle对应的就是串口设备。

把数据发向串口很容易,直接用Write函数就行了。读串口我没有想到什么办法,UEFI不提供中断,我也没有找到串口数据来之后,会触发什么事件。

在测试过程中,从Host OS发过来的数据,偶尔会打印出来。代码还是有问题。

4 编译运行

运行的结果如图所示。

图4 程序运行结果

程序测试了三个功能:

  1. 打印当前所有串口设备参数,很明显,与Sermode的信息是一致的;
  2. 向串口发送测试字符串。字符串被写的调试工具抓到了;
  3. 读取从串口发过来的信息。失败!

我写串口的目的是希望有一个打印的调试手段,方便在图形模式下调试程序。从这个角度来说,目前的程序代码已经满足要求了。

不过,找不到好的机制来读取串口数据,总归不爽。

希望了解这方面的大牛可以指点一二^_^

5 One more thing

在写这个程序的过程中,发现一个现象。所有TianoCore模拟环境下,显示在屏幕上的数据都会传送到我写的命名管道调试工具中。

而通过命名管道发送的数据,也会输入到Shell下。我所写的调试工具,其发送编辑框重载了Enter键,所以可以连Enter键也一起发过去。以Sermode为例:

图5 用命名管道调试工具发送shell命令

通过调试工具写入sermode(回车),点击“发送”按钮,Shell直接就执行了此命令。

另外一个让我感兴趣的是,通过命名管道调试工具发送的数据能很好的被TianoCore模拟环境收到。它应该是通过串口接收的,这通过上述的实验已经证明了。

也就是说,UEFI下有很好的机制来接收串口数据,只是我不知道而已。

我觉得可以把这个调试工具好好改造一下,成为一个方便的UEFI开发辅助工具。所以我把源代码也一起放上去了,和本篇博客的代码放在同一文件夹下。此工具使用VS2015,在Win10下开发。

百度云链接:https://pan.baidu.com/s/1gccSosw8_UAGTI5gZPnLCA
提取码:dx23
代码在 13 SerialPort-PipeTool下。
/luo2:UEFI的串口调试代码;
/PipeTool.exe: 命名管道调试工具的执行文件,32位程序,兼容winxp—win10系列系统;
/pipetool:PipeTool的源代码,VS2015编译。

2,456 total views, 2 views today

发表评论

电子邮件地址不会被公开。