UEFI开发探索75- YIE001PCIe开发板(08 跑马灯实验)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

在等待开发板YIE002焊接的日子里,回到YIE001上继续编程。

本篇准备完成跑马灯的实验,让YIE001上的4个LED灯跑起来。在开篇中,已经大致了解了YIE001上的硬件资源,为方便后续的编程,把这些资源先记录一下。

表1 开发板YIE001上硬件资源

开发板上名称引脚名称所属寄存器地址位址
LED1SW0控制寄存器CTLRIO基址+0x1bit 0
LED2SW1控制寄存器CTLRIO基址+0x1bit 1
LED3GPO辅助寄存器AUXRIO基址+0xf8bit 0
LED4RST0辅助寄存器AUXRIO基址+0xf8bit 7
KEY1GPI1输入寄存器GPIRIO基址+0x2bit 1
KEY2GPI2输入寄存器GPIRIO基址+0x2bit 2
I2CSDA输出寄存器GPORIO基址+0x0bit 0
I2CSCL输出寄存器GPORIO基址+0x0bit 1

需要注意的是,在CH366提供的芯片手册上,对于GPO和RST0所属的寄存器AUXR,给出的地址为IO基址+0x18。在实际使用中,此寄存器无法写入,经过测试发现应该是0xf8才对。

需要注意的是,在CH366提供的芯片手册上,对于GPO和RST0所属的寄存器AUXR,给出的地址为IO基址+0x18。在实际使用中,此寄存器无法写入,经过测试发现应该是0xf8才对。

下面介绍下跑马灯的编写以及测试过程。

1 控制LED灯的函数

我是在开发探索71的框架示例上进行改造的,框架代码不用修改,主要将原来的HelloUEFI()函数替换为新的函数就可以了。首先编写控制LED灯的函数,其相关的宏定义如下:

#define CH366CTLR 0x01
#define CH366AUXR 0xf8
#define LED1 1   //SW0 see CH366's manual
#define LED2 2   //SW1
#define LED3 3   //GPO
#define LED4 4   //RST0

#define KEY1 1   //GPI1 -- GPIR(IO基地址+02h) bit 1
#define KEY2 2   //GPI2 -- GPIR(IO基地址+02h) bit 2
#define LEDON 0   //低电平点亮灯
#define LEDOFF 1  //高电平关闭灯

对照芯片手册,很容易将点亮和关闭LED等的函数编写出来,代码如下所示。

/**
  点亮或者关闭开发板YIE001上的灯.
  @param  IoBaseAddress     YIE001上PCIE芯片的基地址
  @param  LedNum            灯的标识,共有四个,从LED1至LED4
  @param  value             LEDON或者LEDOFF,亮灯或者关灯
  @retval VOID              
**/
VOID SetLed(UINT16 IoBaseAddress,UINT8 LedNum,UINT8 value)
{
  UINT8 regValue=0;
  if(LedNum==LED1)
  {
    regValue = IoRead8(MyIoBaseAddr+CH366CTLR);   //CTRL 
    if(value)
      regValue |= 0x01;
    else
      regValue &= 0xFE;
    IoWrite8(MyIoBaseAddr+CH366CTLR,regValue);      
  }
  if(LedNum==LED2)
  {
    regValue = IoRead8(MyIoBaseAddr+CH366CTLR);   //CTRL
    if(value)
      regValue |= 0x02;
    else
      regValue &= 0xFD;
    IoWrite8(MyIoBaseAddr+CH366CTLR,regValue);      
  }
  if(LedNum==LED3)
  {
    regValue = IoRead8(MyIoBaseAddr + CH366AUXR);  //AUXR 0x18? 0xF8!
    if(value)
      regValue |= 0x01;
    else
      regValue &= 0xFE;
    IoWrite8(MyIoBaseAddr+CH366AUXR,regValue); 
  }
  if(LedNum==LED4)
  {
    regValue = IoRead8(MyIoBaseAddr + CH366AUXR);  //AUXR 0x18? 0xF8!
    if(value)
      regValue |= 0xF0;
    else
      regValue &= 0x7F;
    IoWrite8(MyIoBaseAddr+CH366AUXR,regValue); 
  }
}

代码非常简单,就不解释了。

2 实现跑马灯

在嵌入式开发中,一般会使用定时器来实现跑马灯。为了简单起见,我使用了while循环来实现依次点亮-依次熄灭的功能。代码如下:

VOID HelloMyROM(VOID)
{
  EFI_INPUT_KEY key={0,0};
  gST->ConOut->OutputString(gST->ConOut,L"Hello, I am YIE001!\n\r");
  gST->ConOut->OutputString(gST->ConOut,L"Start Horse Race Lamp, ESC key to exit...\n\r");
 
  while(key.ScanCode!=0x17)	//ESC键退出循环
  {
    GetKey(&key);
    if(key.UnicodeChar == 0x31)   //按’1’退出当前循环
      break;
    SetLed(MyIoBaseAddr,LED1,LEDON);
    Delayms(200);
    SetLed(MyIoBaseAddr,LED2,LEDON);
    Delayms(200);
    SetLed(MyIoBaseAddr,LED3,LEDON);
    Delayms(200);
    SetLed(MyIoBaseAddr,LED4,LEDON);
    Delayms(200);
    SetLed(MyIoBaseAddr,LED4,LEDOFF);
    Delayms(200);
    SetLed(MyIoBaseAddr,LED3,LEDOFF);
    Delayms(200);
    SetLed(MyIoBaseAddr,LED2,LEDOFF);
    Delayms(200);
    SetLed(MyIoBaseAddr,LED1,LEDOFF);
    Delayms(200);
  }
}

以上的代码,能够实现目标功能。不过,在检查键盘按键的过程中,有些滞后感。主要是因为在控制灯的过程中,无法检查键盘输入。可以使用UEFI的Event,重新构建代码,解决上述问题。具体的实现就不写了,有兴趣可以自己试试。

3 编译及测试

所写的示例工程,假设为YIE1LED。可以在编译成ROM生成文件后,写入开发板YIE001,在实际的机器上进行测试。

3.1 编译

编译命令如下:

C:\UEFIWorkspace>build -t VS2015x86 -p RobinPkg\RobinPkg.dsc \
-m RobinPkg\Drivers\YIE1LED\YIE1LED.inf -a X64

生成的文件,位于C:\vUDK2018\edk2\Build\RobinPkg\DEBUG_VS2015x86\X64下,名称为YIE1LED.rom。

3.2 刷写YIE001的固件

YIE001上使用的PCIe芯片,是沁恒电子的CH366。在其官网上,提供了Windows和DOS下的刷写工具:http://www.wch.cn/search?t=all&q=366。

所提供的刷写工具为CH364PGM.COM(DOS工具)和CH364PGM.EXE(Windows工具),个人比较习惯于使用DOS工具进行刷写。从官方提供的一些资料来看,编写一个UEFI下的刷写工具,也是可以的。不过涉及到商业版权等一些非技术性原因的限制,暂时还是不这么做了。

按照如下步骤刷写固件:

(1) 修改ROM文件

CH366对ROM文件有一定的要求,个人感觉这算是芯片特性吧,其他的PCIE芯片好像没看到这种要求。

也即将ROM文件的第三字节(即偏移0x02)修改为0x40,对照PCI ROM的头结构,可以知道这是指定ROM文件长度为32K。

我一般是使用UltraEdit进行二进制修改,也可以使用VS Code配合hexdump插件进行修改。如图1所示。

图1 修改扩展ROM头结构中的ROM长度

(2刷写Flash ROM

用U盘制作DOS启动盘,将ROM文件和DOS刷写工具CH364PGM.COM拷贝在U盘中同一文件夹下。

将YIE001开发板插在带PCIE接口的测试机器上,当然,必须是X86架构的机器。笔者使用的是MSI的机器,使用的处理器为AMD A8-7650K。选择进入U盘的DOS系统,运行如下命令:

C:\FLASH\CH364PGM.COM YIE1LED.ROM
* Program CH364/CH366/CH367/CH368 Flash-ROM, V2.0
……   //其他提示信息
* OK! Written & verified

刷写成功后,重新启动计算机,准备查看ROM代码运行情况。

目前大部分计算机还是支持DOS启动盘的,如果上述方法无法成功,请进入Windows系统,使用Windows刷写工具对YIE001进行刷写。

(3)测试

不需要做特别的动作,启动系统后,BIOS将自动加载YIE001上的Option ROM代码。其运行情况如图2所示。

图2 YIE001的跑马灯

Gitee地址:https://gitee.com/luobing4365/uefi-explorer
项目所用ROM文件位于:/ 75 YIE1LED下

1,173 total views, 2 views today

发表评论

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