Step to UEFI (283)QEMU下面的 LVGL 测试

LVGL(Light and Versatile Graphics Library,轻巧而多功能的图形库)是一个免费的开放源代码图形库,它提供创建具有易于使用的图形元素,精美的视觉效果和低内存占用的嵌入式GUI所需的一切。LVGL的项目作者是来自匈牙利首都布达佩斯的 Gábor Kiss-Vámosi 。Kiss 在2016年将其并发布在 GitHub 上。

当时叫 LittlevGL而不是LVGL,后来作者统一修改为 LVGL 甚至连仓库地址都改了。 像一般的开源项目的那样,它是作为一个人的项目开始的。 从那时起,陆续有近 100 名贡献者参与了项目开发,使得 LVGL 逐渐成为最受欢迎的嵌入式图形库之一。【参考1】

https://ay123.net/mystudy/845/ 由Bin Porting 到了UEFI上。他在 https://github.com/mxmks/LVGLUEFIRWNothing/tree/main 提供了完整的代码。这次就以这套代码为例进行测试。

需要注意的是:如果你在 EDK2 的 Emulator上测试,需要调整分辨率大于等于1024×768【参考2】. 如果你在 QEMU 上测试,那么需要使用如下命令打开USB 鼠标支持(默认情况下是支持 PS2 鼠标的,但是我测试没有成功):

qemu-system-x86_64 -bios ovmf.fd  -net none -hda fat:rw:c:\temp\ov -usb -device usb-mouse

之后,在 QEMU 中加载 USB 驱动(MdeModulePkg\Bus\Usb\UsbBusDxe\UsbBusDxe)和USB Mouse 驱动(MdeModulePkg\Bus\Usb\UsbMouseDxe\UsbMouseDxe)。

有兴趣的朋友不妨自行实验。

本问题提到的 USB 驱动和 USB Mouse 驱动可以通过 EDK2 编译获得,也可以在这里下载:

参考:

1. https://www.xpstem.com/article/10465

2.

ch569 上手测试

为了玩转 Ch569 ,需要准备如下硬件和软件:

硬件要求:

1.官方的 Ch569 开发板,官方买到的是两块插接在一起的,大多数情况下我们的实验都只使用到一块。

CH559 开发板

CH559 开发板

2.USB 3.0 A-A 线一根

软件要求(都可以在官网下载到):

1.项目管理和编译工具:MounRiver

2.官方 Demo: CH569EVT

3.烧写软件:WCHISPTool

安装完成CH569 后,以\CH569EVT\EVT\EXAM\USBSS\USBD\CH372Device为例。这个代码能够将Ch569模拟为Ch372设备。

编译之后的得到编译后的文件位于: obj\CH372Device.hex。

Ch569开发板的烧写方式是将HD0 Pin 接地然后再上电。设备管理器中会出现 “USB Module”这个设备:

之后我们打开WCHISP 工具,如果没有出现下图左侧的界面,那么需要点击右侧“Dedicated MCUs”按钮。

之后在上面的 Object File1 中选择上面提到的 CH372Device.hex 文件,最后点击 Download 即可。

烧录完成后,可以通过 EVT\EXAM\USBSS\USBD\CH372-HSPIDataTransDemo.zip 中的程序进行测试。这个程序会对设备进行一个速度读写测试,在我电脑上测试结果如下:

这个程序测试的是对一个端点写入,然后从另外的端口读取出来。

Step to UEFI (282)如何修改 Emulator 的分辨率

在测试一些简单的 UEFI Application 时,EDK2 自带的Emulator 还是非常方便的。这次介绍的就是如何修改 Emulator的默认分辨率。

首先,使用 build -a X64 -p EmulatorPkg\EmulatorPkg.dsc -t VS2019 编译 Emulator

接下来运行 Build\EmulatorX64\DEBUG_VS2019\X64 中的 WinHost.exe,在 Shell 中运行【参考1】提供的 Application 检查当前的分辨率,可以看到默认为 800×600。

接下来修改分辨率,在 \EmulatorPkg\EmulatorPkg.dsc 中指定分辨率为 1024×768:

[PcdsDynamicDefault.common.DEFAULT]
  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64|0
  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64|0
  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|0
  #LABZ_Start
  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution|1024
  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution|768
  #LABZ_End
[PcdsDynamicHii.common.DEFAULT]
  gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn|L"Setup"|gEmuSystemConfigGuid|0x0|80
  gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|L"Setup"|gEmuSystemConfigGuid|0x4|25
  gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|L"Timeout"|gEfiGlobalVariableGuid|0x0|10

重新编译 Emulator后再次运行,可以看到分辨率已经修改为我们指定的。

参考:

1.https://www.lab-z.com/stu233sp/ 屏幕分辨率研究

2.http://lab-z.com/stu282/ 如何修改 Emulator 的分辨率

Step to UEFI (281)Emulator Debug Message 的输出

几年之前,研究过 EDK2 的调试信息输出的问题【参考1】【参考2】。最近偶然之间发现目前的 EDK2 的 EmulatorPkg 生成的 WinHost.exe 无法使用“>>”进行输出重定向。这次针对这个问题进行研究。

首先说说具体的现象。使用 winhost >> out.txt 命令,尝试抓取Debug 信息,仍然能在屏幕上看到 Debug 信息:

打开 out.txt 可以看到抓到了部分的信息:

根据之前的知识,我们在 EmulatorPkg 中搜索 STD_OUTPUT_HANDLE,可以找到三个位置:

1. \EmulatorPkg\Win\Host\WinHost.c 中的SecPrint() 函数,我们在其中加入   strcat(Buffer,”DBG0″)

2. \EmulatorPkg\Win\Host\WinThunk.c 中的SecWriteStdErr() 函数,我们加入

  NumberOfBytes=NumberOfBytes+4;

  strcat(Buffer,”DBG1″);

3. \EmulatorPkg\Win\Host\WinThunk.c中的SecWriteStdOut() 函数,我们加入

  NumberOfBytes=NumberOfBytes+4;

  strcat(Buffer,”DBG2″);

再次进行测试,在 OUT.TXT 中可以看到:

对应的屏幕可以看到如下输出:

所以,问题在于:

  1. WriteFile ( GetStdHandle (STD_OUTPUT_HANDLE),…….) 能够重定向到文件中
  2. WriteFile ( GetStdHandle (STD_ERROR_HANDLE),…….) 无法定向到文件中

如果将上面的2中的STD_ERROR_HANDLE,修改为STD_OUTPUT_HANDLE,即可重定向到文件中。

当然,遇到 Windows 相关问题,还是需要请教天杀,对此他给出了Microsoft的资料【参考3】,如果我们不想修改代码,那么可以直接使用下面的方式重定向到文件中:

WinHost 2 >>OUT.txt

有兴趣的朋友不妨自己动手试试。

参考:

  1. http://www.lab-z.com/stu82/  NT32Pkg的Debug Message 
  2. http://www.lab-z.com/stu130nt32/ NT32 模拟器中的 Debug Message 输出
  3. https://learn.microsoft.com/zh-cn/troubleshoot/developer/visualstudio/cpp/language-compilers/redirecting-error-command-prompt

ESP32 IDF 快速上手指南

  1. idf.py menuconfig 可以修改一些编译参数,比较重要的有:
    a. ESP PSRAM 配置是否使用 PSRAM
    b. Log output 配置调试信息输出等级
  2. Idf.py build 编译代码
  3. Idf.py -p 串口 flash 烧写编译后的结果
  4. Idf.py -p 串口 monitor 打开串口监视器【参考1】
    a. Ctrl+] 退出串口监视器
    b. Ctrl+R 重启ESP32
    c. Ctrl+L 开始记录 Log/停止记录 Log
    上述可以写在一行 idp.py -p COM4 build flash monitor
  5. idf.py clean/fullclean 重新构建项目
  6. idf.py size-components 查看内存、Flash 占用情况
  7. idf.py size-files 更详细的占用情况
  8. idf.py set-target esp32s3 这个命令设置当前编译处理器目标

参考:IDF 监视器
1.https://docs.espressif.com/projects/esp-idf/zh_CN/stable/esp32/api-guides/tools/idf-monitor.html

Step to UEFI (280)计算精确时间

一些情况下,我们需要得知操作消耗的时间,比如:通过硬盘读写操作耗费的时间能够计算出硬盘的速度。针对这个问题,之前有过研究,例如:GetTime 研究【参考1】、EADK clock()【参考2】。这里再次进行研究。

首先,在MdePkg\Include\Library\TimerLib.h给出了下面两个函数:

/**
  Retrieves the current value of a 64-bit free running performance counter.
  The counter can either count up by 1 or count down by 1. If the physical
  performance counter counts by a larger increment, then the counter values
  must be translated. The properties of the counter can be retrieved from
  GetPerformanceCounterProperties().
  @return The current value of the free running performance counter.
**/
UINT64
EFIAPI
GetPerformanceCounter (
  VOID
  );
/**
  Converts elapsed ticks of performance counter to time in nanoseconds.
  This function converts the elapsed ticks of running performance counter to
  time value in unit of nanoseconds.
  @param  Ticks     The number of elapsed ticks of running performance counter.
  @return The elapsed time in nanoseconds.
**/
UINT64
EFIAPI
GetTimeInNanoSecond (
  IN      UINT64  Ticks
  );
/**
  Retrieves the current value of a 64-bit free running performance counter.
  The counter can either count up by 1 or count down by 1. If the physical
  performance counter counts by a larger increment, then the counter values
  must be translated. The properties of the counter can be retrieved from
  GetPerformanceCounterProperties().
  @return The current value of the free running performance counter.
**/
UINT64
EFIAPI
GetPerformanceCounter (
  VOID
  );
/**
  Converts elapsed ticks of performance counter to time in nanoseconds.
  This function converts the elapsed ticks of running performance counter to
  time value in unit of nanoseconds.
  @param  Ticks     The number of elapsed ticks of running performance counter.
  @return The elapsed time in nanoseconds.
**/
UINT64
EFIAPI
GetTimeInNanoSecond (
  IN      UINT64  Ticks
  );

其中的GetPerformanceCounter() 返回CPU 当前经过的计数值或者说多少个 Ticks,GetTimeInNanoSecond() 函数能将经过的计数值转化为纳秒为单位的时间。

编写一个 UEFI Shell代码进行测试:

1. 在AppPkg.dsc 中加入 TimerLib

CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
  TimerLib|UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
###################################################################################################
#
# Components Section - list of the modules and components that will be processed by compilation
#

2.编写代码如下:

#include  <Uefi.h>
#include  <Library/UefiLib.h>
#include  <Library/ShellCEntryLib.h>
#include  <Library/TimerLib.h>
#include  <Library/UefiBootServicesTableLib.h>
INTN
EFIAPI
ShellAppMain (
  IN UINTN Argc,
  IN CHAR16 **Argv
  )
{
	UINT64	Start=GetPerformanceCounter();
	gBS->Stall(1000000UL);
	Print(L"You have dealyed [%llu]ns\n",
			GetTimeInNanoSecond(GetPerformanceCounter()-Start));
  return(0);
}

具体动作就是首先保存当前的 CPU 计数值,然后延时 1s, 最后输出以纳秒为单位的经过时间。可以看到每次运行耗时会有一点波动。

因为没有使用 CLIB , 所以 Build出来代码体积也比较小,只有9KB.

参考:

  1. https://www.lab-z.com/stugt-2/
  2. https://www.lab-z.com/stu14/

可以指定压缩后文件大小的JPEG工具

大部分JPEG 工具都可以指定图片的压缩质量,从0-100 。但是有时候我们需要一个绝对的数值,比如:500KB 的照片我们期望压缩到40KB。经过努力找到了一个这样的开源工具,在

https://github.com/tjko/jpegoptim

命令行方式工作,比如,我找了一副3.39MB的图片:

使用如下命令:

jpegoptim.exe -dnew -S200 Demo.jpeg

其中 -dnew 指定新生成的图片放在new目录下,-S200指定压缩到200KB(特别注意S需要大写)

压缩之后大小为 193KB

只要不是特别夸张的参数,例如:要把上述图片压缩为40KB,个人感觉都还是可以接收的。

UEIF Tips: EDK2 的 AppPkg

最近打算用 EDK2 202308 编写 UEFI Application,忽然发现无法找到 AppPkg,于是花点时间研究这个问题。这个问题在“VS2019 EDK202008 下的 Libc 编译”【参考1】有提及。具体来说 EDK2 在edk2-stable201903 tag升级到edk2-stable201905 tag这个过程中移除的。接下来的问题就是:如何在最新的 EDK2 环境中使用 AppPkg。具体的方法是,在一下网址下载 AppPkg:

https://github.com/tianocore/edk2-libc/tree/master

解压之后放在EDK2 的根目录下,接下来就可以像之前一样使用 AppPkg 编写 Application了。

参考:

1. https://www.lab-z.com/2019libc/

Turbo Vision

和现在的GUI不同,在 Dos 的时代,使用 ASCII 字符同样能够绘制精美的窗口,这种被称作“CUI”。 Turbo Pascal 7.0 就是典型的代表,它基于Turbo Vision来实现的。

最近看到了一个开源的 Turbo Vision项目,让这套界面在 Windows下再次焕发青春。项目地址是

https://github.com/magiblot/tvision

下面介绍一下编译方法:

  1. 需要准备 VS2019 这种 MS 的编译器
  2. 运行 cmake . -B ./build && -A x64

3. 运行 cmake –build ./build –config Release

编译后生成的 exe 在 build 目录下

有兴趣的朋友可以试试。

=============================================================

2024年2月19日

还可以使用下面的命令来生成 nmake 语法的 makefile

cmake . -B ./build2 -G "NMake Makefiles" ..

之后,进入 build2 目录,运行 nmake 也可以生成 exe

CMAKE 打开具体动作显示的方法

有些项目是通过 CMAKE 来实现的,我们可以通过在根目录下CMakeLists.txt文件添加

set(CMAKE_VERBOSE_MAKEFILE ON) 的方法打开显示,这样就可以看到具体使用的编译命令。例如:

cmake_minimum_required (VERSION 3.5)
if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.13.0")
    cmake_policy(SET CMP0077 NEW) # 'option()' honors normal variables.
endif()

set(CMAKE_VERBOSE_MAKEFILE ON)

set(MASTER_PROJECT FALSE)
if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
    set(MASTER_https://zhuanlan.zhihu.com/p/587290104PROJECT )
endif()

上述方法来自 https://zhuanlan.zhihu.com/p/587290104