RaptorLake_P I2C Shell 测试工具 

这个工具目前可以让你在 UEFI Shell 下扫描 PCH I2C 总线上的设备,给出扫描到的设备地址。可以用来判断 I2C 设备是否正常。

在运行之前请保证

  1. PCH 对应的 I2C 已经 Enable, 在 Shell 下能够看到对应的PCI Controller;
  2. I2C 对应的 GPIO 已经设置为 Native UART 功能。

使用方法:

rpli2ct <需要扫描的 I2C Num>

例如,下面就是一个例子,在 I2C5上发现了一些设备。

UEFI Application 下载(无源代码)

Ch32V305 USART1 重映射

手册上有表明 USART引脚,这里选择PB15 为 TX, PA8 为 RX。

根据【参考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】,实验和编写:

  1. 需要安装如下软件
    • VS2019 需要保证安装VC
    • Python 3.8.10 需要安装到 c:\Python38 目录下, 需要选择将路径加入系统变量
  • Nasm 2.16.01 需要安装到 c:\nasm 目录下
  • IASL 20190509 需要安装到 c:\asl 目录下
  • OpenSSL 需要安装到c:\openssl 目录下
  • Git 下面这个设置需要选择为“Checkout as-is, commit as-is” 其余默认即可

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

 这样会在sblkey目录下生成一堆 Key

5.接下来给 Qemu 生成一个BIOS 试试

  • 需要指定key目录:set SBL_KEY_DIR=c:\buildbs\sbl\sblkey

  • 使用Python BuildLoader.py build qemu
  • 在这个过程中需要从Git下载一些代码,对于不方便联网的人可以直接将 Download.zip 解压到 c:\BuildBs 下面。第一次使用 git 会提示需要设置邮件地址,可以用  git config –global user.email “you@example.com”  设置一个假地址跳过

6.最终的结果如下,表示编译成功

参考:

1. https://slimbootloader.github.io/developer-guides/build-system.html

ch9350的测试小板

之前使用 WCH 家的 Ch9350 制作了一些板卡,但是这个芯片焊接对于我来说是有一些难度的。因此,这里专门设计了一个 ch9350的测试小板能够方便的进行原型验证。

电路图如下,相当于这个芯片的最小系统,外围软件只有2个电容:

PCB设计如下:

3D 预览如下:

焊接实物如下:

可以看到这个板子的优点如下:

  1. 外部线路简单,只预留了必要的引脚;
  2. 引出了2个USB端口,可以同时支持2个USB HID 设备
  3. 体型小巧便于在原型上使用

电路图和 PCB 下载:

LunarLake UART Shell 测试工具

这个工具是用来给 LunarLake Shell 下进行 Uart 测试的工具,它通过 PCH UART输出字符。

在使用之前,请保证:

  1. PCH 对应的 UART 已经 Enable, 在 Shell 下能够看到对应的PCI Controller;
  2. UART 对应的 GPIO 已经设置为 Native UART 功能。

使用方法:

zu4l <UART 编号>

例如, zu4r 0 将会从第一个 PCH UART对应的引脚,以 115200 波特率输出 www.lab-z.com。

程序在这里下载(无源代码)

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

然后再像其他驱动一样安装即可:

修改后的 INF可以在这里下载:

MeteorLake-P UART Shell 测试工具

这个工具是用来给 MeteorLake-P Shell 下进行 Uart 测试的工具,它通过 PCH UART输出字符。

在使用之前,请保证:

  1. PCH 对应的 UART 已经 Enable, 在 Shell 下能够看到对应的PCI Controller;
  2. UART 对应的 GPIO 已经设置为 Native UART 功能。

使用方法:

mtlut <UART 编号>

例如, mtlut 0 将会从第一个 PCH UART对应的引脚,以 115200 波特率输出 www.lab-z.com。

程序在这里下载(无源代码)

Sound Wire

SoundWire 是 MIPI 协会推出的关于音频的规范,有时候会被缩写为 SNDW。这个规范定义的总线有如下好处:

  1. 线路简单,一个 Clock 和 一个 Data线即可进行传输,这样能够极大降低产品成本(布线更简单,节省PCB);
  2. 速度快(最高12.288 MHz),使用类似 DDR(Double)的传输方式;
  3. 可以扩展进行  Clock Scaling 或者多个 Data Lane,能够轻松增加带宽;
  4. 单个 master 最多可以支持 11个 Slave;
  5. 支持slave to slave的数据传输方式。

基本拓扑结构是【参考1】:其中的 ADC 可以理解为麦克风,DAC 可以理解为喇叭,下图就是一个 SoundWire Master 连接了2个麦克风和三个喇叭:

复杂一点:Multi Lanes拓扑如下, Clock 提供给 Codec/BT/DSP,然后多个Lane(Data[0]/Data[1]/Data[2]), 这样能够提升一个周期数据的传输数量。

因此,对于 PC 来说,SoundWire 是重新定义了 SoC 或者说南桥对 Codec 的数据传输协议,取代了之前的 HDA 总线。对于软件或者 BIOS 来说应该是透明的。

参考:

  1. https://elinux.org/images/8/80/Introduction-to-SoundWire-Vinod-Koul-Linaro.pdf
  1. https://zhuanlan.zhihu.com/p/535358005
  2. https://bbs.eetop.cn/thread-928626-1-1.html

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 的输出精度。芯片引脚定义如下:

引脚编号名称介绍
1Vdd供电 2.7-5.5V
2NC
3CS#SPI CS 引脚
4SCKSPI Clock
5SDISPI MOSI
6NC
7NC
8LDAC#锁存,只有为低时,芯片才会从 Vouta和Voutb 输出电压
9SHDN#关闭,为低芯片停止工作
10Voutb输出B电压引脚
11Vrefb输出B 的参考电压,可以接入Vss到Vdd 以内的电压.这次测试接入了Vdd(3.3V)
12Vss
13Vrefa输出A 的参考电压,,可以接入Vss到Vdd 以内的电压.这次测试接入了Vdd(3.3V)
14Vouta输出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);
}

代码运行后使用示波器进行测试,结果如下:

修改代码,loop如下:

void loop() {
   myDac.analogWrite(0, 0); 
   myDac.analogWrite(0, 4095);
}

可以看到波形如下:

参考:

  1. https://www.microchip.com/en-us/product/MCP4922#
  2. https://ua726.co.uk/2012/12/22/testing-the-mcp4922-with-an-arduino/

本文使用的库:

MCP492X Datasheet