2024年2月更新,Step to UEFI 文章索引:
RaptorLake_P I2C Shell 测试工具
Ch32V305 USART1 重映射
手册上有表明 USART引脚,这里选择PB15 为 TX, PA8 为 RX。
![](https://www.lab-z.com/wp-content/uploads/2024/05/image-6.png)
根据【参考1】给出的方法,编写代码:
void setup() {
GPIO_InitTypeDef GPIO_InitStructure={0};
Serial.begin(115200);
//打开重映射时钟和USART重映射后的I/O口引脚时钟,
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
//2. I/O口重映射开启.
GPIO_PinRemapConfig(GPIO_Remap_USART1_HighBit, ENABLE);
//3.配制重映射引脚, 这里只需配置重映射后的I/O,原来的不需要去配置.
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void loop() {
char sMsg1[] = "www.lab-z.com1";
Serial.println(sMsg1);
delay(1000);
}
USB 转串口的板子 RX 连接到 PB15上,在PC端即可收到字符串。
参考:
1. https://www.cnblogs.com/jeakon/archive/2012/10/04/2816798.html
Slim Boot编译环境的架设
本文根据【参考1】,实验和编写:
- 需要安装如下软件
- VS2019 需要保证安装VC
- Python 3.8.10 需要安装到 c:\Python38 目录下, 需要选择将路径加入系统变量
![](https://www.lab-z.com/wp-content/uploads/2024/05/image-11.png)
- Nasm 2.16.01 需要安装到 c:\nasm 目录下
- IASL 20190509 需要安装到 c:\asl 目录下
- OpenSSL 需要安装到c:\openssl 目录下
- Git 下面这个设置需要选择为“Checkout as-is, commit as-is” 其余默认即可
![](https://www.lab-z.com/wp-content/uploads/2024/05/image-12.png)
2. 解压 slimboot-master 到 c:\buildbs 目录下名为 sbl 的目录下
3.打开 x86 Native Tools Command Prompt for VS2019
4.生成一个 SBLKey
- 创建一个目录:Mkdir sblkey
- 在这个目录下生成Key:Python BootLoaderCorePkg\Tools\Generatekeys.py -k sblkey
![](https://www.lab-z.com/wp-content/uploads/2024/05/image-13.png)
这样会在sblkey目录下生成一堆 Key
5.接下来给 Qemu 生成一个BIOS 试试
- 需要指定key目录:set SBL_KEY_DIR=c:\buildbs\sbl\sblkey
- 使用Python BuildLoader.py build qemu
![](https://www.lab-z.com/wp-content/uploads/2024/05/image-14.png)
- 在这个过程中需要从Git下载一些代码,对于不方便联网的人可以直接将 Download.zip 解压到 c:\BuildBs 下面。第一次使用 git 会提示需要设置邮件地址,可以用 git config –global user.email “you@example.com” 设置一个假地址跳过
6.最终的结果如下,表示编译成功
![](https://www.lab-z.com/wp-content/uploads/2024/05/image-15.png)
参考:
1. https://slimbootloader.github.io/developer-guides/build-system.html
ch9350的测试小板
之前使用 WCH 家的 Ch9350 制作了一些板卡,但是这个芯片焊接对于我来说是有一些难度的。因此,这里专门设计了一个 ch9350的测试小板能够方便的进行原型验证。
电路图如下,相当于这个芯片的最小系统,外围软件只有2个电容:
![](https://www.lab-z.com/wp-content/uploads/2023/10/image-9.png)
PCB设计如下:
![](https://www.lab-z.com/wp-content/uploads/2023/10/image-10.png)
3D 预览如下:
![](https://www.lab-z.com/wp-content/uploads/2023/10/image-11.png)
焊接实物如下:
![](https://www.lab-z.com/wp-content/uploads/2023/10/image-12.png)
可以看到这个板子的优点如下:
- 外部线路简单,只预留了必要的引脚;
- 引出了2个USB端口,可以同时支持2个USB HID 设备
- 体型小巧便于在原型上使用
电路图和 PCB 下载:
LunarLake UART Shell 测试工具
ESP32-C3 Windows7 驱动
ESP32-C3 不支持 Windows 7, 意思是插上之后设备管理器中会出现Yellow Bang,无法识别串口。这样会给我们的开发和调试造成一定困难。经过研究可以通过修改Arduino Drivers 目录下面的 arduino-org.inf 来解决。
具体操作如下:
1.在[Strings]增加如下两行
LABZ.bootloader.name="Arduino ESP32-C3 bootloader"
LABZ.sketch.name="Arduiono ESP32-C3"
2.在 [DeviceList] 增加如下两行:
%LABZ.bootloader.name%=DriverInstall, USB\VID_2A03&PID_003A
%LABZ.sketch.name%=DriverInstall, USB\VID_2A03&PID_803A&MI_00
3.在[DeviceList.NTamd64]增加如下代码:
%LABZ.bootloader.name%=DriverInstall, USB\VID_303A&PID_1001
%LABZ.sketch.name%=DriverInstall, USB\VID_303A&PID_1001&MI_00
然后再像其他驱动一样安装即可:
![](https://www.lab-z.com/wp-content/uploads/2024/07/image-4.png)
修改后的 INF可以在这里下载:
MeteorLake-P UART Shell 测试工具
Sound Wire
SoundWire 是 MIPI 协会推出的关于音频的规范,有时候会被缩写为 SNDW。这个规范定义的总线有如下好处:
- 线路简单,一个 Clock 和 一个 Data线即可进行传输,这样能够极大降低产品成本(布线更简单,节省PCB);
- 速度快(最高12.288 MHz),使用类似 DDR(Double)的传输方式;
- 可以扩展进行 Clock Scaling 或者多个 Data Lane,能够轻松增加带宽;
- 单个 master 最多可以支持 11个 Slave;
- 支持slave to slave的数据传输方式。
基本拓扑结构是【参考1】:其中的 ADC 可以理解为麦克风,DAC 可以理解为喇叭,下图就是一个 SoundWire Master 连接了2个麦克风和三个喇叭:
![](https://www.lab-z.com/wp-content/uploads/2024/03/image-11.png)
复杂一点:Multi Lanes拓扑如下, Clock 提供给 Codec/BT/DSP,然后多个Lane(Data[0]/Data[1]/Data[2]), 这样能够提升一个周期数据的传输数量。
![](https://www.lab-z.com/wp-content/uploads/2024/03/image-12.png)
因此,对于 PC 来说,SoundWire 是重新定义了 SoC 或者说南桥对 Codec 的数据传输协议,取代了之前的 HDA 总线。对于软件或者 BIOS 来说应该是透明的。
参考:
UEFI TIPS: PciLib
如果你在编写代码时有使用到类似 PciRead8() 这样的函数,那么可以通过在 INF 中加入 PciLib:
[LibraryClasses]
UefiLib
ShellCEntryLib
IoLib
PciLib
然后在代码中使用 include 调用头文件即可:
#include <Library/PciLib.h>
具体的 PciLib.h 定义如下:
#define PCI_LIB_ADDRESS(Bus, Device, Function, Register) \
(((Register) & 0xfff) | (((Function) & 0x07) << 12) | (((Device) & 0x1f) << 15) | (((Bus) & 0xff) << 20))
RETURN_STATUS
EFIAPI
PciRegisterForRuntimeAccess (
IN UINTN Address
);
UINT8
EFIAPI
PciRead8 (
IN UINTN Address
);
UINT8
EFIAPI
PciWrite8 (
IN UINTN Address,
IN UINT8 Value
);
UINT8
EFIAPI
PciOr8 (
IN UINTN Address,
IN UINT8 OrData
);
UINT8
EFIAPI
PciAnd8 (
IN UINTN Address,
IN UINT8 AndData
);
UINT8
EFIAPI
PciAndThenOr8 (
IN UINTN Address,
IN UINT8 AndData,
IN UINT8 OrData
);
UINT8
EFIAPI
PciBitFieldRead8 (
IN UINTN Address,
IN UINTN StartBit,
IN UINTN EndBit
);
UINT8
EFIAPI
PciBitFieldWrite8 (
IN UINTN Address,
IN UINTN StartBit,
IN UINTN EndBit,
IN UINT8 Value
);
UINT8
EFIAPI
PciBitFieldOr8 (
IN UINTN Address,
IN UINTN StartBit,
IN UINTN EndBit,
IN UINT8 OrData
);
UINT8
EFIAPI
PciBitFieldAnd8 (
IN UINTN Address,
IN UINTN StartBit,
IN UINTN EndBit,
IN UINT8 AndData
);
UINT8
EFIAPI
PciBitFieldAndThenOr8 (
IN UINTN Address,
IN UINTN StartBit,
IN UINTN EndBit,
IN UINT8 AndData,
IN UINT8 OrData
);
UINT16
EFIAPI
PciRead16 (
IN UINTN Address
);
UINT16
EFIAPI
PciWrite16 (
IN UINTN Address,
IN UINT16 Value
);
UINT16
EFIAPI
PciOr16 (
IN UINTN Address,
IN UINT16 OrData
);
UINT16
EFIAPI
PciAnd16 (
IN UINTN Address,
IN UINT16 AndData
);
UINT16
EFIAPI
PciAndThenOr16 (
IN UINTN Address,
IN UINT16 AndData,
IN UINT16 OrData
);
UINT16
EFIAPI
PciBitFieldRead16 (
IN UINTN Address,
IN UINTN StartBit,
IN UINTN EndBit
);
UINT16
EFIAPI
PciBitFieldWrite16 (
IN UINTN Address,
IN UINTN StartBit,
IN UINTN EndBit,
IN UINT16 Value
);
UINT16
EFIAPI
PciBitFieldOr16 (
IN UINTN Address,
IN UINTN StartBit,
IN UINTN EndBit,
IN UINT16 OrData
);
UINT16
EFIAPI
PciBitFieldAnd16 (
IN UINTN Address,
IN UINTN StartBit,
IN UINTN EndBit,
IN UINT16 AndData
);
UINT16
EFIAPI
PciBitFieldAndThenOr16 (
IN UINTN Address,
IN UINTN StartBit,
IN UINTN EndBit,
IN UINT16 AndData,
IN UINT16 OrData
);
UINT32
EFIAPI
PciRead32 (
IN UINTN Address
);
UINT32
EFIAPI
PciWrite32 (
IN UINTN Address,
IN UINT32 Value
);
UINT32
EFIAPI
PciOr32 (
IN UINTN Address,
IN UINT32 OrData
);
UINT32
EFIAPI
PciAnd32 (
IN UINTN Address,
IN UINT32 AndData
);
UINT32
EFIAPI
PciAndThenOr32 (
IN UINTN Address,
IN UINT32 AndData,
IN UINT32 OrData
);
UINT32
EFIAPI
PciBitFieldRead32 (
IN UINTN Address,
IN UINTN StartBit,
IN UINTN EndBit
);
UINT32
EFIAPI
PciBitFieldWrite32 (
IN UINTN Address,
IN UINTN StartBit,
IN UINTN EndBit,
IN UINT32 Value
);
UINT32
EFIAPI
PciBitFieldOr32 (
IN UINTN Address,
IN UINTN StartBit,
IN UINTN EndBit,
IN UINT32 OrData
);
UINT32
EFIAPI
PciBitFieldAnd32 (
IN UINTN Address,
IN UINTN StartBit,
IN UINTN EndBit,
IN UINT32 AndData
);
UINT32
EFIAPI
PciBitFieldAndThenOr32 (
IN UINTN Address,
IN UINTN StartBit,
IN UINTN EndBit,
IN UINT32 AndData,
IN UINT32 OrData
);
UINTN
EFIAPI
PciReadBuffer (
IN UINTN StartAddress,
IN UINTN Size,
OUT VOID *Buffer
);
UINTN
EFIAPI
PciWriteBuffer (
IN UINTN StartAddress,
IN UINTN Size,
IN VOID *Buffer
);
MCP4922 SPI DAC 在 FireBeetle ESP32 上的测试
之前有介绍过,ESP32 没有 DAC 引脚,但是可以通过 PWM 来进行模拟,这次入手了 MCP4922 这款双通道 DAC 芯片。它使用 SPI 接口,提供12Bit 的输出精度。芯片引脚定义如下:
![](https://www.lab-z.com/wp-content/uploads/2024/01/image-16.png)
引脚编号 | 名称 | 介绍 |
1 | Vdd | 供电 2.7-5.5V |
2 | NC | 空 |
3 | CS# | SPI CS 引脚 |
4 | SCK | SPI Clock |
5 | SDI | SPI MOSI |
6 | NC | 空 |
7 | NC | 空 |
8 | LDAC# | 锁存,只有为低时,芯片才会从 Vouta和Voutb 输出电压 |
9 | SHDN# | 关闭,为低芯片停止工作 |
10 | Voutb | 输出B电压引脚 |
11 | Vrefb | 输出B 的参考电压,可以接入Vss到Vdd 以内的电压.这次测试接入了Vdd(3.3V) |
12 | Vss | 地 |
13 | Vrefa | 输出A 的参考电压,,可以接入Vss到Vdd 以内的电压.这次测试接入了Vdd(3.3V) |
14 | Vouta | 输出A的电压引脚 |
这次测试基于 https://github.com/michd/Arduino-MCP492X 提供的库文件,代码如下:
#include <MCP492X.h> // Include the library
#define PIN_SPI_CHIP_SELECT_DAC 25 // Or any pin you'd like to use
MCP492X myDac(PIN_SPI_CHIP_SELECT_DAC);
void setup() {
// put your setup code here, to run once:
myDac.begin();
}
void loop() {
for (int i=0;i<4096;i++) {
myDac.analogWrite(0, i);
myDac.analogWrite(1, 4095-i);
delay(1);
}
代码运行后使用示波器进行测试,结果如下:
![](https://www.lab-z.com/wp-content/uploads/2024/01/image-17.png)
修改代码,loop如下:
void loop() {
myDac.analogWrite(0, 0);
myDac.analogWrite(0, 4095);
}
可以看到波形如下:
![](https://www.lab-z.com/wp-content/uploads/2024/01/image-18.png)
参考:
- https://www.microchip.com/en-us/product/MCP4922#
- https://ua726.co.uk/2012/12/22/testing-the-mcp4922-with-an-arduino/
本文使用的库:
MCP492X Datasheet