4

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

 3 years ago
source link: http://yiiyee.cn/blog/2021/02/07/uefi%e5%bc%80%e5%8f%91%e6%8e%a2%e7%b4%a275-yie001pcie%e5%bc%80%e5%8f%91%e6%9d%bf%ef%bc%8808-%e8%b7%91%e9%a9%ac%e7%81%af%e5%ae%9e%e9%aa%8c%ef%bc%89/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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 0LED2SW1控制寄存器CTLRIO基址+0x1bit 1LED3GPO辅助寄存器AUXRIO基址+0xf8bit 0LED4RST0辅助寄存器AUXRIO基址+0xf8bit 7KEY1GPI1输入寄存器GPIRIO基址+0x2bit 1KEY2GPI2输入寄存器GPIRIO基址+0x2bit 2I2CSDA输出寄存器GPORIO基址+0x0bit 0I2CSCL输出寄存器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-exolorer
项目所用ROM文件位于:/ 75 YIE1LED下

28 total views, 1 views today


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK