最近遇到了 DRRS 的问题。总结如下:

作为 BIOS 工程师,如果想支持这个功能,第一件要做的事情是:和Panel 厂商确认屏幕是支持这个功能的。

DRRS 是 Display Refresh Rate Switching的缩写,通过降低笔记本上内置屏幕刷新频率达到省电的目的。

具体分为2种:

1.Static DRRS

2.Seamless DRRS(SDRRS)

Static DRRS : 当使用 Battery/DC Mode 的时候使用最低刷新频率; 当使用 Adapter/AC Mode 的时候使用最高刷新频率。其中的最低频率和最高频率是Panel 的 EDID 给定的。无论是否为支持 PSR 的Panel 都可以支持这个模式。当切换不同的频率时,会黑屏一下。

在 Setup 中有一个显示当前加载的CPU Micro Code 的版本的选项。比如,在 EDK2 的代码中有如下片段:

\Vlv2TbltDevicePkg\PlatformSetupDxe\Main.vfi  

text
    help   = STRING_TOKEN(STR_NULL_STRING),
    text   = STRING_TOKEN(STR_PROCESSOR_MICROCODE_STRING),
    text   = STRING_TOKEN(STR_PROCESSOR_MICROCODE_VALUE),
    flags  = 0,
key    = 0;

对应实现的代码:... > Read More

最近看到实验室有测试功耗的设备,于是进行了一下几款常见播放器的功耗比较。

先说说试验设备,用的是下面这款设备

YOKOGAWA WT310E Digital Power Meter
通过 WT310E 给设备(WHL HDK)提供 220V的电源,然后功耗信息通过 USB接口传输到另外的笔记本电脑上进行记录。测试机台通过 HDMI 显示器输出显示。显示器额外供电。

测试结果如下:

IDLE 是静止在桌面的情况下的功耗

可以看到,Windows 自带播放器表现最好。表现最差的是 QQPlayer... > Read More

通常情况下我们无需使用外部EEPROM 存储数据,因为 Arduino 本身有自带的。也许是因为这个原因我在网上搜索 Arduino 使用 AT24C02 的资料也很少。

最终在 https://github.com/tardate/Littl ... 4C02/BasicReadWrite 搜索到了一个例子。

先说连接方法:

元件引脚如下:

A0-A2 用于选择设备的地址,如果都为LOW,那么地址是 0x50

WP 是写保护,接HIGH 之后才能进行写入

/*
  EEPROM/AT24C02/BasicReadWrite
  Basic read/write operations to external EEPROM (AT24C02) with the...								 > Read More
			

理论上写中文注释是没问题的,因为 VS 是支持中文的。但是,很多用于 Build 的工具并没有考虑这种情况,因此会导致稀奇古怪的问题。最近我遇到了一个编译错误

C:\BuildBs\201903>build -a X64
Build environment: Windows-10-10.0.16299-SP0
Build start time: 09:15:25, Jun.02 2019

WORKSPACE        = c:\buildbs\201903
EDK_TOOLS_PATH   = c:\buildbs\201903\basetools
EDK_TOOLS_BIN    = c:\buildbs\201903\basetools\bin\win32
CONF_PATH        = c:\buildbs\201903\conf
PYTHON_COMMAND   = py -3


Architecture(s)  = X64
Build target  ...								 > Read More
			

BaseLib 提供了一些计算CheckSum 的函数,用这些可以让我们方便的计算一些协议要求的校验码。

下面编写一个简单的例子:

#include  <Uefi.h>
#include  <Library/BaseLib.h>
#include  <Library/UefiLib.h>
#include  <Library/ShellCEntryLib.h>

extern  EFI_SYSTEM_TABLE    *gST;
extern  EFI_BOOT_SERVICES   *gBS;

UINT8   Buffer={1,2,3,4,5};

/***
  Print a welcoming message.

  Establishes the main...								 > Read More
			

目前市面上能够测量心率的设备很多。有腕带腕表式的,也有夹在耳朵或者手指末端的。从准确性上来说,腕带式的容易松动因此没有胸带式的准确。同时,胸带式的对于运动统计来说也是最好的选择。

前一段入手了三根心率带和一个接收模块。其中的心率带是带有编码的,因此在接收端可以很容易的区分数据来源。当然,与之对应的还有不带编码的心率带,无法在多个的情况下使用。

先说说心率带模块:

  1. 内部使用 CR2032 纽扣电池,据说每天工作1小时可以撑9个月;
  2. 发送频率为 2.4Ghz;
  3. 平时处于睡眠模式,戴上之后才开始发送数据
  4. 发射数据每次 4 Bytes,3 Bytes ID+ 1 Byte 心率。

接收模块:

  1. 模块三个引脚,GND  VCC (特别强调是 3.3V供电) TX 。使用串口通讯。波特率 9600 bps。比如:DD 20 03 04 50(个人感觉有点低,设想如果很多根在同一个空间内使用不知道会有什么问题);
  2. 上面有一个LED,当收到有效数据后会闪动一次;
  3. 板子上的孔间距是 2.0mm 不是 2.54,使用杜邦线会很别扭,我直接焊接上导线来使用;

最近在编写一个需要随机生成数值的代码,使用之前的 rand 函数【参考1】发现每次生成的随机数是相同的,忽然意识到这是因为代码里面的随机种子是固定值导致的,如果使用当前时间作为随机种子那么每次生成的数值将会是不同的。

可以使用 Runtime Service 中的 GetTime 来取得时间作为种子,返回的时间格式如下:

//
// EFI Time Abstraction:
//  Year:       2000 - 20XX
//  Month:      1 - 12
//  Day:        1 - 31
//  Hour: ...								 > Read More
			

单纯的函数调用从动作上来说,Call 指令可以看作保存寄存器压栈外加 JMP 的过程(复杂的说调用 Call 会有有实模式,保护模式, Near/Far,gated等等差别,在 IA32 手册上描述足有8页之多)。因此,可以使用压栈保存寄存器外加一个跳转来实现。在 UEFI 中可以通过SetJump() 和 LongJump()函数组合来实现。

在 \MdePkg\Include\Library\BaseLib.h 可以看到下面的定义。

/**
  Saves the current CPU context that can be restored with a call to LongJump()
  and returns 0.

  Saves the current CPU context in the buffer specified by JumpBuffer and
 ...								 > Read More