ESP32 GC9A01 测试代码

最近买了一个圆形的液晶显示屏,这个造型很特别是表盘的原型。它的主控是 GC9A01,我在网上搜了一圈没有找到现成的库于是只能自己研究。查看了一下 SPEC发现Command 之类的和ST7789基本相同,但是直接使用 ST7789 无法驱动显示。为此只能从头研究。

GC9A01 TFT LCD

测试使用 FireBeetle(ESP32),特别需要注意的是从资料上看这个屏幕只支持 3.3V,因此使用 UNO 这样的板子有烧毁的可能,我也并没有试验过UNO 这样的5V 的板子,具体建议询问卖家。

硬件连接:

FireBeetle(ESP32)GC9A01 
3.3VVCC 
GNDGND 
D9DC 
D2RST 
D10(预留给CS 未使用)  
 CSGND
 BLK未连接
 SCL 
 SDA 
ESP32和 GC9A01连接

最终只得从卖家的代码上修改。卖家提供了很多代码,最终选择从C51 代码上修改:

#include <SPI.h>
//画笔颜色
#define WHITE            0xFFFF
#define BLACK            0x0000   
#define BLUE             0x001F  
#define BRED             0XF81F
#define GRED             0XFFE0
#define GBLUE            0X07FF
#define RED              0xF800
#define MAGENTA          0xF81F
#define GREEN            0x07E0
#define CYAN             0x7FFF
#define YELLOW           0xFFE0
#define BROWN            0XBC40 //棕色
#define BRRED            0XFC07 //棕红色
#define GRAY             0X8430 //灰色
#define DARKBLUE         0X01CF //深蓝色
#define LIGHTBLUE        0X7D7C //浅蓝色  
#define GRAYBLUE         0X5458 //灰蓝色
#define LIGHTGREEN       0X841F //浅绿色
#define LGRAY            0XC618 //浅灰色(PANNEL),窗体背景色
#define LGRAYBLUE        0XA651 //浅灰蓝色(中间层颜色)
#define LBBLUE           0X2B12 //浅棕蓝色(选择条目的反色)

#define TFT_DC D9
#define TFT_RST D2
#define TFT_CS D10

#define LCD_RES_Clr()  digitalWrite(TFT_RST,LOW)
#define LCD_RES_Set()  digitalWrite(TFT_RST,HIGH)

#define LCD_DC_Clr()  digitalWrite(TFT_DC,LOW)
#define LCD_DC_Set()  digitalWrite(TFT_DC,HIGH)

#define u16 word
#define delay_ms delay
#define LCD_W 240
#define LCD_H 240

#if defined (SPI_HAS_TRANSACTION)
  static SPISettings mySPISettings;
#endif

/******************************************************************************
      函数说明:LCD写入命令
      入口数据:dat 写入的命令
      返回值:  无
******************************************************************************/
void LCD_WR_REG(byte c)
{
  LCD_DC_Clr();//写命令
  #if defined (SPI_HAS_TRANSACTION)
      SPI.begin();
      SPI.beginTransaction(mySPISettings);
      SPI.transfer(c);
      SPI.endTransaction();
  #endif
  LCD_DC_Set();
}
/******************************************************************************
      函数说明:LCD写入数据
      入口数据:dat 写入的数据
      返回值:  无
******************************************************************************/
void LCD_WR_DATA(u16 dat)
{
    #if defined (SPI_HAS_TRANSACTION)
      SPI.begin();
      SPI.beginTransaction(mySPISettings);
      SPI.transfer(dat>>8);
      SPI.transfer(dat);
      SPI.endTransaction();
  #endif
}
/******************************************************************************
      函数说明:LCD写入数据
      入口数据:dat 写入的数据
      返回值:  无
******************************************************************************/
void LCD_WR_DATA8(byte c)
{
  #if defined (SPI_HAS_TRANSACTION)
      SPI.begin();
      SPI.beginTransaction(mySPISettings);
      SPI.transfer(c);
      SPI.endTransaction();
  #endif
}

void LCD_Init(void)
{
  
  LCD_RES_Clr();//复位
  delay_ms(100);
  LCD_RES_Set();
  delay_ms(100);
  
  LCD_WR_REG(0xEF);
  LCD_WR_REG(0xEB);
  LCD_WR_DATA8(0x14); 
  
  LCD_WR_REG(0xFE);      
  LCD_WR_REG(0xEF); 

  LCD_WR_REG(0xEB); 
  LCD_WR_DATA8(0x14); 

  LCD_WR_REG(0x84);     
  LCD_WR_DATA8(0x40); 

  LCD_WR_REG(0x85);     
  LCD_WR_DATA8(0xFF); 

  LCD_WR_REG(0x86);     
  LCD_WR_DATA8(0xFF); 

  LCD_WR_REG(0x87);     
  LCD_WR_DATA8(0xFF);

  LCD_WR_REG(0x88);     
  LCD_WR_DATA8(0x0A);

  LCD_WR_REG(0x89);     
  LCD_WR_DATA8(0x21); 

  LCD_WR_REG(0x8A);     
  LCD_WR_DATA8(0x00); 

  LCD_WR_REG(0x8B);     
  LCD_WR_DATA8(0x80); 

  LCD_WR_REG(0x8C);     
  LCD_WR_DATA8(0x01); 

  LCD_WR_REG(0x8D);     
  LCD_WR_DATA8(0x01); 

  LCD_WR_REG(0x8E);     
  LCD_WR_DATA8(0xFF); 

  LCD_WR_REG(0x8F);     
  LCD_WR_DATA8(0xFF); 


  LCD_WR_REG(0xB6);
  LCD_WR_DATA8(0x00);
  LCD_WR_DATA8(0x20);

  LCD_WR_REG(0x36);
  LCD_WR_DATA8(0x08);


  LCD_WR_REG(0x3A);     
  LCD_WR_DATA8(0x05); 


  LCD_WR_REG(0x90);     
  LCD_WR_DATA8(0x08);
  LCD_WR_DATA8(0x08);
  LCD_WR_DATA8(0x08);
  LCD_WR_DATA8(0x08); 

  LCD_WR_REG(0xBD);     
  LCD_WR_DATA8(0x06);
  
  LCD_WR_REG(0xBC);     
  LCD_WR_DATA8(0x00); 

  LCD_WR_REG(0xFF);     
  LCD_WR_DATA8(0x60);
  LCD_WR_DATA8(0x01);
  LCD_WR_DATA8(0x04);

  LCD_WR_REG(0xC3);     
  LCD_WR_DATA8(0x13);
  LCD_WR_REG(0xC4);     
  LCD_WR_DATA8(0x13);

  LCD_WR_REG(0xC9);     
  LCD_WR_DATA8(0x22);

  LCD_WR_REG(0xBE);     
  LCD_WR_DATA8(0x11); 

  LCD_WR_REG(0xE1);     
  LCD_WR_DATA8(0x10);
  LCD_WR_DATA8(0x0E);

  LCD_WR_REG(0xDF);     
  LCD_WR_DATA8(0x21);
  LCD_WR_DATA8(0x0c);
  LCD_WR_DATA8(0x02);

  LCD_WR_REG(0xF0);   
  LCD_WR_DATA8(0x45);
  LCD_WR_DATA8(0x09);
  LCD_WR_DATA8(0x08);
  LCD_WR_DATA8(0x08);
  LCD_WR_DATA8(0x26);
  LCD_WR_DATA8(0x2A);

  LCD_WR_REG(0xF1);    
  LCD_WR_DATA8(0x43);
  LCD_WR_DATA8(0x70);
  LCD_WR_DATA8(0x72);
  LCD_WR_DATA8(0x36);
  LCD_WR_DATA8(0x37);  
  LCD_WR_DATA8(0x6F);


  LCD_WR_REG(0xF2);   
  LCD_WR_DATA8(0x45);
  LCD_WR_DATA8(0x09);
  LCD_WR_DATA8(0x08);
  LCD_WR_DATA8(0x08);
  LCD_WR_DATA8(0x26);
  LCD_WR_DATA8(0x2A);

  LCD_WR_REG(0xF3);   
  LCD_WR_DATA8(0x43);
  LCD_WR_DATA8(0x70);
  LCD_WR_DATA8(0x72);
  LCD_WR_DATA8(0x36);
  LCD_WR_DATA8(0x37); 
  LCD_WR_DATA8(0x6F);

  LCD_WR_REG(0xED); 
  LCD_WR_DATA8(0x1B); 
  LCD_WR_DATA8(0x0B); 

  LCD_WR_REG(0xAE);     
  LCD_WR_DATA8(0x77);
  
  LCD_WR_REG(0xCD);     
  LCD_WR_DATA8(0x63);   


  LCD_WR_REG(0x70);     
  LCD_WR_DATA8(0x07);
  LCD_WR_DATA8(0x07);
  LCD_WR_DATA8(0x04);
  LCD_WR_DATA8(0x0E); 
  LCD_WR_DATA8(0x0F); 
  LCD_WR_DATA8(0x09);
  LCD_WR_DATA8(0x07);
  LCD_WR_DATA8(0x08);
  LCD_WR_DATA8(0x03);

  LCD_WR_REG(0xE8);     
  LCD_WR_DATA8(0x34);

  LCD_WR_REG(0x62);     
  LCD_WR_DATA8(0x18);
  LCD_WR_DATA8(0x0D);
  LCD_WR_DATA8(0x71);
  LCD_WR_DATA8(0xED);
  LCD_WR_DATA8(0x70); 
  LCD_WR_DATA8(0x70);
  LCD_WR_DATA8(0x18);
  LCD_WR_DATA8(0x0F);
  LCD_WR_DATA8(0x71);
  LCD_WR_DATA8(0xEF);
  LCD_WR_DATA8(0x70); 
  LCD_WR_DATA8(0x70);

  LCD_WR_REG(0x63);     
  LCD_WR_DATA8(0x18);
  LCD_WR_DATA8(0x11);
  LCD_WR_DATA8(0x71);
  LCD_WR_DATA8(0xF1);
  LCD_WR_DATA8(0x70); 
  LCD_WR_DATA8(0x70);
  LCD_WR_DATA8(0x18);
  LCD_WR_DATA8(0x13);
  LCD_WR_DATA8(0x71);
  LCD_WR_DATA8(0xF3);
  LCD_WR_DATA8(0x70); 
  LCD_WR_DATA8(0x70);

  LCD_WR_REG(0x64);     
  LCD_WR_DATA8(0x28);
  LCD_WR_DATA8(0x29);
  LCD_WR_DATA8(0xF1);
  LCD_WR_DATA8(0x01);
  LCD_WR_DATA8(0xF1);
  LCD_WR_DATA8(0x00);
  LCD_WR_DATA8(0x07);

  LCD_WR_REG(0x66);     
  LCD_WR_DATA8(0x3C);
  LCD_WR_DATA8(0x00);
  LCD_WR_DATA8(0xCD);
  LCD_WR_DATA8(0x67);
  LCD_WR_DATA8(0x45);
  LCD_WR_DATA8(0x45);
  LCD_WR_DATA8(0x10);
  LCD_WR_DATA8(0x00);
  LCD_WR_DATA8(0x00);
  LCD_WR_DATA8(0x00);

  LCD_WR_REG(0x67);     
  LCD_WR_DATA8(0x00);
  LCD_WR_DATA8(0x3C);
  LCD_WR_DATA8(0x00);
  LCD_WR_DATA8(0x00);
  LCD_WR_DATA8(0x00);
  LCD_WR_DATA8(0x01);
  LCD_WR_DATA8(0x54);
  LCD_WR_DATA8(0x10);
  LCD_WR_DATA8(0x32);
  LCD_WR_DATA8(0x98);

  LCD_WR_REG(0x74);     
  LCD_WR_DATA8(0x10); 
  LCD_WR_DATA8(0x85); 
  LCD_WR_DATA8(0x80);
  LCD_WR_DATA8(0x00); 
  LCD_WR_DATA8(0x00); 
  LCD_WR_DATA8(0x4E);
  LCD_WR_DATA8(0x00);         
  
  LCD_WR_REG(0x98);     
  LCD_WR_DATA8(0x3e);
  LCD_WR_DATA8(0x07);

  LCD_WR_REG(0x35); 
  LCD_WR_REG(0x21);

  LCD_WR_REG(0x11);
  delay_ms(120);
  LCD_WR_REG(0x29);
  delay_ms(20);
} 

/******************************************************************************
      函数说明:设置起始和结束地址
      入口数据:x1,x2 设置列的起始和结束地址
                y1,y2 设置行的起始和结束地址
      返回值:  无
******************************************************************************/
void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2)
{
    LCD_WR_REG(0x2a);//列地址设置
    LCD_WR_DATA(x1);
    LCD_WR_DATA(x2);
    LCD_WR_REG(0x2b);//行地址设置
    LCD_WR_DATA(y1);
    LCD_WR_DATA(y2);
    LCD_WR_REG(0x2c);//储存器写
}

/******************************************************************************
      函数说明:在指定区域填充颜色
      入口数据:xsta,ysta   起始坐标
                xend,yend   终止坐标
                color       要填充的颜色
      返回值:  无
******************************************************************************/
void LCD_Fill(u16 xsta,u16 ysta,u16 xend,u16 yend,u16 color)
{          
  u16 i,j; 
  LCD_Address_Set(xsta,ysta,xend-1,yend-1);//设置显示范围
  for(i=ysta;i<yend;i++)
  {                               
    for(j=xsta;j<xend;j++)
    {
      LCD_WR_DATA(color);
    }
  }                   
}
void setup() {
  pinMode(TFT_CS,OUTPUT);
  digitalWrite(TFT_CS,LOW);
  pinMode(TFT_DC,OUTPUT);
    pinMode(TFT_RST,OUTPUT);

  mySPISettings = SPISettings(1000000, MSBFIRST, SPI_MODE0);
  LCD_Init();

}

void loop() {
  LCD_Fill(0,0,LCD_W,LCD_H,BLUE);
  LCD_Fill(0,0,LCD_W,LCD_H,WHITE);
  LCD_Fill(0,0,LCD_W,LCD_H,BRED);
  LCD_Fill(0,0,LCD_W,LCD_H,GRED);
  LCD_Fill(0,0,LCD_W,LCD_H,RED);
  LCD_Fill(0,0,LCD_W,LCD_H,MAGENTA);
  LCD_Fill(0,0,LCD_W,LCD_H,GREEN);
  LCD_Fill(0,0,LCD_W,LCD_H,CYAN);     
}

测试的内容是不断让屏幕变换颜色:

FillScreen 测试

Windows 版本对照表

来自 https://docs.microsoft.com/zh-cn/windows/release-information/

目前常见的版本有 19H1(1903) 19H2(1909) 20H1(2004) 20H1(。

所有的日期都按照 ISO 8601 格式列出:YYYY-MM-DD)上次更新时间: 2021-01-04

半年频道

Version服务选项上市日期OS build最后修订日期终止服务:家庭版、教育版、专业教育版、专业工作站版和 IoT 核心版服务终止日期:企业版、教育版和 IoT 企业版
20H2半年频道2020-10-2019042.6852020-12-082022-05-102023-05-09Microsoft 建议使用
2004半年频道2020-05-2719041.6852020-12-082021-12-142021-12-14
1909半年频道2019-11-1218363.12562020-12-082021-05-112022-05-10
1809半年频道2019-03-2817763.16372020-12-08服务终止2021-05-11
1809半年频道(定向)2018-11-1317763.16372020-12-08服务终止2021-05-11
1803半年频道2018-07-1017134.19022020-12-08服务终止2021-05-11
1803半年频道(定向)2018-04-3017134.19022020-12-08服务终止2021-05-11

下面是2个已经终止的版本

Version服务选项上市日期OS build最后修订日期终止服务:家庭版、教育版、专业教育版、专业工作站版和 IoT 核心版服务终止日期:企业版、教育版和 IoT 企业版
1709半年频道2018-01-1816299.19372020-06-18服务终止2020-10-13
1709半年频道(定向)2017-10-1716299.19372020-06-18服务终止2020-10-13

企业版和 IoT 企业版 LTSB/LTSC 版本

Version服务选项上市日期OS build最后修订日期主要支持结束日期外延支持结束日期
1809长期服务频道 (LTSC)2018-11-1317763.12942020-06-162024-01-092029-01-09
1607长期服务分支 (LTSB)2016-08-0214393.37552020-06-182021-10-122026-10-13
1507 (RTM)长期服务分支 (LTSB)2015-07-2910240.186092020-06-182020-10-132025-10-14

Windows 10 发行历史记录

在 Windows 10 更新历史记录上了解有关 Windows 10 更新内容的更多信息。


 Version 20H2 (OS build 19042)

要将设备运行的 Windows 10 版本 2004 升级为 Windows 10 版本 20H2,可通过 更新支持包 来加速此流程。有关详细信息,请参阅KB4562830

OS build上市日期服务选项知识库文章
19042.6852020-12-08半年频道KB 4592438
19042.6622020-11-30半年频道KB 4586853
19042.6312020-11-19半年频道KB 4594440
19042.6302020-11-10半年频道KB 4586781
19042.6102020-10-29半年频道KB 4580364
19042.5722020-10-20半年频道

 Version 2004 (OS build 19041)

OS build上市日期服务选项知识库文章
19041.3312020-06-18半年频道KB 4567523
19041.3292020-06-09半年频道KB 4557957
19041.2642020-05-27半年频道

 Version 1909 (OS build 18363)

要将设备运行的 Windows 10 版本 1903 升级为 Windows 10 版本 1909,可通过更新支持包来加速此流程。有关详细信息,请参阅KB4517245

OS build上市日期服务选项知识库文章
18363.9042020-06-16半年频道KB 4567512
18363.9002020-06-09半年频道KB 4560960
18363.8362020-05-12半年频道KB 4556799
18363.8152020-04-21半年频道KB 4550945
18363.7782020-04-14半年频道KB 4549951
18363.7532020-03-30半年频道KB 4554364
18363.7522020-03-24半年频道KB 4541335
18363.7202020-03-12半年频道KB 4551762
18363.7192020-03-10半年频道KB 4540673
18363.6932020-02-27半年频道KB 4535996
18363.6572020-02-11半年频道KB 4532693
18363.6282020-01-28半年频道KB 4532695
18363.5922020-01-14半年频道KB 4528760
18363.5352019-12-10半年频道KB 4530684
18363.4762019-11-12半年频道KB 4524570

 Version 1903 (OS build 18362)

OS build上市日期服务选项知识库文章
18362.9042020-06-16半年频道KB 4567512
18362.9002020-06-09半年频道KB 4560960
18362.8362020-05-12半年频道KB 4556799
18362.8152020-04-21半年频道KB 4550945
18362.7782020-04-14半年频道KB 4549951
18362.7532020-03-30半年频道KB 4554364
18362.7522020-03-24半年频道KB 4541335
18362.7202020-03-12半年频道KB 4551762
18362.7192020-03-10半年频道KB 4540673
18362.6932020-02-27半年频道KB 4535996
18362.6572020-02-11半年频道KB 4532693
18362.6282020-01-28半年频道KB 4532695
18362.5922020-01-14半年频道KB 4528760
18362.5352019-12-10半年频道KB 4530684
18362.4762019-11-12半年频道KB 4524570
18362.4492019-10-24半年频道KB 4522355
18362.4182019-10-08半年频道KB 4517389
18362.3882019-10-03半年频道KB 4524147
18362.3872019-09-26半年频道KB 4517211
18362.3572019-09-23半年频道KB 4522016
18362.3562019-09-10半年频道KB 4515384
18362.3292019-08-30半年频道KB 4512941
18362.2952019-08-13半年频道KB 4512508
18362.2672019-07-26半年频道KB 4505903
18362.2392019-07-09半年频道KB 4507453
18362.2072019-06-27半年频道KB 4501375
18362.1752019-06-11半年频道KB 4503293
18362.1452019-05-29半年频道KB 4497935
18362.1162019-05-21半年频道KB 4505057

 Version 1809 (OS build 17763)

OS build上市日期服务选项知识库文章
17763.12942020-06-16半年频道 • 半年频道(定向) • LTSCKB 4567513
17763.12822020-06-09半年频道 • 半年频道(定向) • LTSCKB 4561608
17763.12172020-05-12半年频道 • 半年频道(定向) • LTSCKB 4551853
17763.11922020-04-21半年频道 • 半年频道(定向) • LTSCKB 4550969
17763.11582020-04-14半年频道 • 半年频道(定向) • LTSCKB 4549949
17763.11322020-03-30半年频道 • 半年频道(定向) • LTSCKB 4554354
17763.11312020-03-17半年频道 • 半年频道(定向) • LTSCKB 4541331
17763.10982020-03-10半年频道 • 半年频道(定向) • LTSCKB 4538461
17763.10752020-02-25半年频道 • 半年频道(定向) • LTSCKB 4537818
17763.10392020-02-11半年频道 • 半年频道(定向) • LTSCKB 4532691
17763.10122020-01-23半年频道 • 半年频道(定向) • LTSCKB 4534321
17763.9732020-01-14半年频道 • 半年频道(定向) • LTSCKB 4534273
17763.9142019-12-10半年频道 • 半年频道(定向) • LTSCKB 4530715
17763.8642019-11-12半年频道 • 半年频道(定向) • LTSCKB 4523205
17763.8322019-10-15半年频道 • 半年频道(定向) • LTSCKB 4520062
17763.8052019-10-08半年频道 • 半年频道(定向) • LTSCKB 4519338
17763.7752019-10-03半年频道 • 半年频道(定向) • LTSCKB 4524148
17763.7742019-09-24半年频道 • 半年频道(定向) • LTSCKB 4516077
17763.7402019-09-23半年频道 • 半年频道(定向) • LTSCKB 4522015
17763.7372019-09-10半年频道 • 半年频道(定向) • LTSCKB 4512578
17763.7202019-08-17半年频道 • 半年频道(定向) • LTSCKB 4512534
17763.6782019-08-13半年频道 • 半年频道(定向) • LTSCKB 4511553
17763.6522019-07-22半年频道 • 半年频道(定向) • LTSCKB 4505658
17763.6152019-07-09半年频道 • 半年频道(定向) • LTSCKB 4507469
17763.5932019-06-26半年频道 • 半年频道(定向) • LTSCKB 4509479
17763.5922019-06-18半年频道 • 半年频道(定向) • LTSCKB 4501371
17763.5572019-06-11半年频道 • 半年频道(定向) • LTSCKB 4503327
17763.5292019-05-21半年频道 • 半年频道(定向) • LTSCKB 4497934
17763.5042019-05-19半年频道 • 半年频道(定向) • LTSCKB 4505056
17763.5032019-05-14半年频道 • 半年频道(定向) • LTSCKB 4494441
17763.4752019-05-03半年频道 • 半年频道(定向) • LTSCKB 4495667
17763.4392019-05-01半年频道 • 半年频道(定向) • LTSCKB 4501835
17763.4372019-04-09半年频道 • 半年频道(定向) • LTSCKB 4493509
17763.4042019-04-02半年频道 • 半年频道(定向) • LTSCKB 4490481
17763.3792019-03-12半年频道 • 半年频道(定向) • LTSCKB 4489899
17763.3482019-03-01半年频道(定向) • LTSCKB 4482887
17763.3162019-02-12半年频道(定向) • LTSCKB 4487044
17763.2922019-01-22半年频道(定向) • LTSCKB 4476976
17763.2532019-01-08半年频道(定向) • LTSCKB 4480116
17763.1952018-12-19半年频道(定向) • LTSCKB 4483235
17763.1942018-12-11半年频道(定向) • LTSCKB 4471332
17763.1682018-12-05半年频道(定向) • LTSCKB 4469342
17763.1342018-11-13半年频道(定向) • LTSCKB 4467708
17763.1072018-11-13半年频道(定向) • LTSCKB 4464455
17763.552018-10-09半年频道(定向) • LTSCKB 4464330
17763.12018-10-02半年频道(定向) • LTSC

 Version 1803 (OS build 17134)

OS build上市日期服务选项知识库文章
17134.15532020-06-16半年频道 • 半年频道(定向)KB 4567514
17134.15502020-06-09半年频道 • 半年频道(定向)KB 4561621
17134.14882020-05-12半年频道 • 半年频道(定向)KB 4556807
17134.14562020-04-21半年频道 • 半年频道(定向)KB 4550944
17134.14252020-04-14半年频道 • 半年频道(定向)KB 4550922
17134.14012020-03-30半年频道 • 半年频道(定向)KB 4554349
17134.13992020-03-17半年频道 • 半年频道(定向)KB 4541333
17134.13652020-03-10半年频道 • 半年频道(定向)KB 4540689
17134.13452020-02-25半年频道 • 半年频道(定向)KB 4537795
17134.13042020-02-11半年频道 • 半年频道(定向)KB 4537762
17134.12762020-01-23半年频道 • 半年频道(定向)KB 4534308
17134.12462020-01-14半年频道 • 半年频道(定向)KB 4534293
17134.11842019-12-10半年频道 • 半年频道(定向)KB 4530717
17134.11302019-11-12半年频道 • 半年频道(定向)KB 4525237
17134.10992019-10-15半年频道 • 半年频道(定向)KB 4519978
17134.10692019-10-08半年频道 • 半年频道(定向)KB 4520008
17134.10402019-10-03半年频道 • 半年频道(定向)KB 4524149
17134.10392019-09-24半年频道 • 半年频道(定向)KB 4516045
17134.10092019-09-23半年频道 • 半年频道(定向)KB 4522014
17134.10062019-09-10半年频道 • 半年频道(定向)KB 4516058
17134.9842019-08-19半年频道 • 半年频道(定向)KB 4512509
17134.9502019-08-13半年频道 • 半年频道(定向)KB 4512501
17134.9152019-07-16半年频道 • 半年频道(定向)KB 4507466
17134.8852019-07-09半年频道 • 半年频道(定向)KB 4507435
17134.8602019-06-26半年频道 • 半年频道(定向)KB 4509478
17134.8582019-06-18半年频道 • 半年频道(定向)KB 4503288
17134.8292019-06-11半年频道 • 半年频道(定向)KB 4503286
17134.7992019-05-21半年频道 • 半年频道(定向)KB 4499183
17134.7662019-05-19半年频道 • 半年频道(定向)KB 4505064
17134.7652019-05-14半年频道 • 半年频道(定向)KB 4499167
17134.7532019-04-25半年频道 • 半年频道(定向)KB 4493437
17134.7062019-04-09半年频道 • 半年频道(定向)KB 4493464
17134.6772019-03-19半年频道 • 半年频道(定向)KB 4489894
17134.6482019-03-12半年频道 • 半年频道(定向)KB 4489868
17134.6192019-02-19半年频道 • 半年频道(定向)KB 4487029
17134.5902019-02-12半年频道 • 半年频道(定向)KB 4487017
17134.5562019-01-15半年频道 • 半年频道(定向)KB 4480976
17134.5232019-01-08半年频道 • 半年频道(定向)KB 4480966
17134.4722018-12-19半年频道 • 半年频道(定向)KB 4483234
17134.4712018-12-11半年频道 • 半年频道(定向)KB 4471324
17134.4412018-11-27半年频道 • 半年频道(定向)KB 4467682
17134.4072018-11-13半年频道 • 半年频道(定向)KB 4467702
17134.3762018-10-24半年频道 • 半年频道(定向)KB 4462933
17134.3452018-10-09半年频道 • 半年频道(定向)KB 4462919
17134.3202018-09-26半年频道 • 半年频道(定向)KB 4458469
17134.2862018-09-17半年频道 • 半年频道(定向)KB 4464218
17134.2852018-09-11半年频道 • 半年频道(定向)KB 4457128
17134.2542018-08-30半年频道 • 半年频道(定向)KB 4346783
17134.2282018-08-14半年频道 • 半年频道(定向)KB 4343909
17134.1912018-07-24半年频道 • 半年频道(定向)KB 4340917
17134.1672018-07-16半年频道 • 半年频道(定向)KB 4345421
17134.1652018-07-10半年频道 • 半年频道(定向)KB 4338819
17134.1372018-06-26半年频道(定向)KB 4284848
17134.1122018-06-12半年频道(定向)KB 4284835
17134.832018-06-05半年频道(定向)KB 4338548
17134.812018-05-23半年频道(定向)KB 4100403
17134.482018-05-08半年频道(定向)KB 4103721

 Version 1709 (OS build 16299)

OS build上市日期服务选项知识库文章
16299.19372020-06-18半年频道 • 半年频道(定向)KB 4567515
16299.19322020-06-09半年频道 • 半年频道(定向)KB 4561602
16299.18682020-05-12半年频道 • 半年频道(定向)KB 4556812
16299.18062020-04-14半年频道 • 半年频道(定向)KB 4550927
16299.17762020-03-30半年频道 • 半年频道(定向)KB 4554342
16299.17752020-03-17半年频道 • 半年频道(定向)KB 4541330
16299.17472020-03-10半年频道 • 半年频道(定向)KB 4540681
16299.17172020-02-25半年频道 • 半年频道(定向)KB 4537816
16299.16862020-02-11半年频道 • 半年频道(定向)KB 4537789
16299.16542020-01-23半年频道 • 半年频道(定向)KB 4534318
16299.16252020-01-14半年频道 • 半年频道(定向)KB 4534276
16299.15652019-12-10半年频道 • 半年频道(定向)KB 4530714
16299.15082019-11-12半年频道 • 半年频道(定向)KB 4525241
16299.14812019-10-15半年频道 • 半年频道(定向)KB 4520006
16299.14512019-10-08半年频道 • 半年频道(定向)KB 4520004
16299.14212019-10-03半年频道 • 半年频道(定向)KB 4524150
16299.14202019-09-24半年频道 • 半年频道(定向)KB 4516071
16299.13922019-09-23半年频道 • 半年频道(定向)KB 4522012
16299.13872019-09-10半年频道 • 半年频道(定向)KB 4516066
16299.13652019-08-16半年频道 • 半年频道(定向)KB 4512494
16299.13312019-08-13半年频道 • 半年频道(定向)KB 4512516
16299.12962019-07-16半年频道 • 半年频道(定向)KB 4507465
16299.12682019-07-09半年频道 • 半年频道(定向)KB 4507455
16299.12392019-06-26半年频道 • 半年频道(定向)KB 4509477
16299.12372019-06-18半年频道 • 半年频道(定向)KB 4503281
16299.12172019-06-11半年频道 • 半年频道(定向)KB 4503284
16299.11822019-05-28半年频道 • 半年频道(定向)KB 4499147
16299.11502019-05-19半年频道 • 半年频道(定向)KB 4505062
16299.11462019-05-14半年频道 • 半年频道(定向)KB 4499179
16299.11272019-04-25半年频道 • 半年频道(定向)KB 4493440
16299.10872019-04-09半年频道 • 半年频道(定向)KB 4493441
16299.10592019-03-19半年频道 • 半年频道(定向)KB 4489890
16299.10292019-03-12半年频道 • 半年频道(定向)KB 4489886
16299.10042019-02-19半年频道 • 半年频道(定向)KB 4487021
16299.9672019-02-12半年频道 • 半年频道(定向)KB 4486996
16299.9362019-01-15半年频道 • 半年频道(定向)KB 4480967
16299.9042019-01-08半年频道 • 半年频道(定向)KB 4480978
16299.8472018-12-19半年频道 • 半年频道(定向)KB 4483232
16299.8462018-12-11半年频道 • 半年频道(定向)KB 4471329
16299.8202018-11-27半年频道 • 半年频道(定向)KB 4467681
16299.7852018-11-13半年频道 • 半年频道(定向)KB 4467686
16299.7552018-10-18半年频道 • 半年频道(定向)KB 4462932
16299.7262018-10-09半年频道 • 半年频道(定向)KB 4462918
16299.6992018-09-26半年频道 • 半年频道(定向)KB 4457136
16299.6662018-09-17半年频道 • 半年频道(定向)KB 4464217
16299.6652018-09-11半年频道 • 半年频道(定向)KB 4457142
16299.6372018-08-30半年频道 • 半年频道(定向)KB 4343893
16299.6112018-08-14半年频道 • 半年频道(定向)KB 4343897
16299.5792018-07-24半年频道 • 半年频道(定向)KB 4338817
16299.5512018-07-16半年频道 • 半年频道(定向)KB 4345420
16299.5472018-07-10半年频道 • 半年频道(定向)KB 4338825
16299.5222018-06-21半年频道 • 半年频道(定向)KB 4284822
16299.4922018-06-12半年频道 • 半年频道(定向)KB 4284819
16299.4612018-05-21半年频道 • 半年频道(定向)KB 4103714
16299.4312018-05-08半年频道 • 半年频道(定向)KB 4103727
16299.4022018-04-23半年频道 • 半年频道(定向)KB 4093105
16299.3712018-04-10半年频道 • 半年频道(定向)KB 4093112
16299.3342018-03-22半年频道 • 半年频道(定向)KB 4089848
16299.3092018-03-13半年频道 • 半年频道(定向)KB 4088776
16299.2512018-03-05半年频道 • 半年频道(定向)KB 4090913
16299.2482018-02-13半年频道 • 半年频道(定向)KB 4074588
16299.2142018-01-31半年频道 • 半年频道(定向)KB 4058258
16299.2012018-01-18半年频道 • 半年频道(定向)KB 4073291
16299.1942018-01-17半年频道 • 半年频道(定向)KB 4073290
16299.1922018-01-03半年频道 • 半年频道(定向)KB 4056892
16299.1252017-12-12半年频道 • 半年频道(定向)KB 4054517
16299.982017-11-30半年频道(定向)KB 4051963
16299.642017-11-14半年频道(定向)KB 4048955
16299.192017-10-17半年频道(定向)KB 4043961

 Version 1703 (OS build 15063) – 服务终止

OS build上市日期服务选项知识库文章
15063.21082019-10-08半年频道 • CBKB 4520010
15063.20792019-10-03半年频道 • CBKB 4524151
15063.20782019-09-24半年频道 • CBKB 4516059
15063.20462019-09-23半年频道 • CBKB 4522011
15063.20452019-09-10半年频道 • CBKB 4516068
15063.20212019-08-17半年频道 • CBKB 4512474
15063.19882019-08-13半年频道 • CBKB 4512507
15063.19552019-07-16半年频道 • CBKB 4507467
15063.19282019-07-09半年频道 • CBKB 4507450
15063.18982019-06-26半年频道 • CBKB 4509476
15063.18972019-06-18半年频道 • CBKB 4503289
15063.18682019-06-11半年频道 • CBKB 4503279
15063.18392019-05-28半年频道 • CBKB 4499162
15063.18082019-05-19半年频道 • CBKB 4505055
15063.18052019-05-14半年频道 • CBKB 4499181
15063.17852019-05-02半年频道 • CBKB 4502112
15063.17842019-04-25半年频道 • CBKB 4493436
15063.17462019-04-09半年频道 • CBKB 4493474
15063.17162019-03-19半年频道 • CBKB 4489888
15063.16892019-03-12半年频道 • CBKB 4489871
15063.16592019-02-19半年频道 • CBKB 4487011
15063.16312019-02-12半年频道 • CBKB 4487020
15063.15962019-01-15半年频道 • CBKB 4480959
15063.15632019-01-08半年频道 • CBKB 4480973
15063.15082018-12-19半年频道 • CBKB 4483230
15063.15062018-12-11半年频道 • CBKB 4471327
15063.14782018-11-27半年频道 • CBKB 4467699
15063.14462018-11-13半年频道 • CBKB 4467696
15063.14182018-10-18半年频道 • CBKB 4462939
15063.13872018-10-09半年频道 • CBKB 4462937
15063.13562018-09-20半年频道 • CBKB 4457141
15063.13242018-09-11半年频道 • CBKB 4457138
15063.12922018-08-30半年频道 • CBKB 4343889
15063.12662018-08-14半年频道 • CBKB 4343885
15063.12352018-07-24半年频道 • CBKB 4338827
15063.12092018-07-16半年频道 • CBKB 4345419
15063.12062018-07-10半年频道 • CBKB 4338826
15063.11822018-06-21半年频道 • CBKB 4284830
15063.11552018-06-12半年频道 • CBKB 4284874
15063.11122018-05-17半年频道 • CBKB 4103722
15063.10882018-05-08半年频道 • CBKB 4103731
15063.10582018-04-17半年频道 • CBKB 4093117
15063.10292018-04-10半年频道 • CBKB 4093107
15063.9942018-03-22半年频道 • CBKB 4088891
15063.9662018-03-13半年频道 • CBKB 4088782
15063.9362018-03-08半年频道 • CBKB 4092077
15063.9362018-02-22半年频道 • CBKB 4077528
15063.9092018-02-13半年频道 • CBKB 4074592
15063.8772018-01-17半年频道 • CBKB 4057144
15063.8502018-01-03半年频道 • CBKB 4056891
15063.7862017-12-12半年频道 • CBKB 4053580
15063.7292017-11-22半年频道 • CBKB 4055254
15063.7262017-11-14半年频道 • CBKB 4048954
15063.6752017-11-02半年频道 • CBKB 4049370
15063.6742017-10-10半年频道 • CBKB 4041676
15063.6322017-09-25半年频道 • CBKB 4040724
15063.6082017-09-12半年频道 • CBKB 4038788
15063.5402017-08-08半年频道 • CBKB 4034674
15063.5022017-08-01半年频道 • CBKB 4032188
15063.4832017-07-11半年频道 • CBKB 4025342
15063.4472017-06-27CBKB 4022716
15063.4132017-06-13CBKB 4022725
15063.3322017-05-26CBKB 4020102
15063.2962017-05-09CBKB 4016871
15063.2502017-04-25CBKB 4016240
15063.1382017-04-11CBKB 4015583

 Version 1607 (OS build 14393)

OS build上市日期服务选项知识库文章
14393.37552020-06-18CBB • CB • LTSBKB 4567517
14393.37502020-06-09CBB • CB • LTSBKB 4561616
14393.36862020-05-12CBB • CB • LTSBKB 4556813
14393.36592020-04-21CBB • CB • LTSBKB 4550947
14393.36302020-04-14CBB • CB • LTSBKB 4550929
14393.35952020-03-17CBB • CB • LTSBKB 4541329
14393.35642020-03-10CBB • CB • LTSBKB 4540670
14393.35422020-02-25CBB • CB • LTSBKB 4537806
14393.35042020-02-11CBB • CB • LTSBKB 4537764
14393.34742020-01-23CBB • CB • LTSBKB 4534307
14393.34432020-01-14CBB • CB • LTSBKB 4534271
14393.33842019-12-10CBB • CB • LTSBKB 4530689
14393.33262019-11-12CBB • CB • LTSBKB 4525236
14393.33002019-10-15CBB • CB • LTSBKB 4519979
14393.32742019-10-08CBB • CB • LTSBKB 4519998
14393.32432019-10-03CBB • CB • LTSBKB 4524152
14393.32422019-09-24CBB • CB • LTSBKB 4516061
14393.32062019-09-23CBB • CB • LTSBKB 4522010
14393.32042019-09-10CBB • CB • LTSBKB 4516044
14393.31812019-08-17CBB • CB • LTSBKB 4512495
14393.31442019-08-13CBB • CB • LTSBKB 4512517
14393.31152019-07-16CBB • CB • LTSBKB 4507459
14393.30852019-07-09CBB • CB • LTSBKB 4507460
14393.30562019-06-27CBB • CB • LTSBKB 4509475
14393.30532019-06-18CBB • CB • LTSBKB 4503294
14393.30252019-06-11CBB • CB • LTSBKB 4503267
14393.29992019-05-23CBB • CB • LTSBKB 4499177
14393.29722019-05-19CBB • CB • LTSBKB 4505052
14393.29692019-05-14CBB • CB • LTSBKB 4494440
14393.29412019-04-25CBB • CB • LTSBKB 4493473
14393.29082019-04-25CBB • CB • LTSBKB 4499418
14393.29062019-04-09CBB • CB • LTSB

Step to UEFI (215)AudioPkg 测试

GitHub 上的John Davis开发出了能够在 UEFI Shell下播放声音的驱动AudioPkg。具体项目可以在 https://github.com/Goldfish64/AudioPkg 看到(从19年开始我就开始关注他的项目,但是一直没有实验成功。现在他这个项目完全 Move 到另外的项目中了)。偶然之间我发现需要将当前系统的 Audio 设置为 (非SST。区别上简单的说就是 Intel 做出来一个 HD-Audio 的标准,然后又改进出来另外一套称作 SST 的标准,在 SST中大量使用 DSP ,更节省 CPU 更节省电力。唯一的问题是相比前者外界不知道如何实现只能通过Intel 驱动来实现播放)。

AudioPkg在 EDK2 201903 下面使用 build -a X64 -p AudioPkg\AudioPkg.dsc 会遇到如下错误:

c:\buildbs\stable201903\AudioPkg\Platform\BootChimeDxe\BootChimeDxe.c(163): error C2220: warning treated as error - no 'object' file generated
c:\buildbs\stable201903\AudioPkg\Platform\BootChimeDxe\BootChimeDxe.c(163): warning C4244: 'function': conversion from 'UINTN' to 'UINT8', possible loss of data
c:\buildbs\stable201903\AudioPkg\Application\BootChimeCfg\BootChimeCfg.c(415): error C2220: warning treated as error - no 'object' file generated
c:\buildbs\stable201903\AudioPkg\Application\BootChimeCfg\BootChimeCfg.c(415): warning C4244: 'function': conversion from 'UINTN' to 'UINT8', possible loss of data
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio 14.0\Vc\bin\x86_amd64\cl.exe"' : return code '0x2'
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio 14.0\Vc\bin\x86_amd64\cl.exe"' : return code '0x2'

解决方法是通过在出现问题代码对应的INF 中添加编译开关忽略之:

[BuildOptions]
MSFT:*_*_X64_CC_FLAGS          = /wd4054 /wd4055 /wd4152

最终修改后的代码可以在这里下载:

编译后的 X64 EFI 可以在这里下载:

再次强调:如果你发现实体机Shell 下无法运行,很可能是因为 Setup 中选择了 Intel SST 导致的,请修改为非Intel SST 的项目。

测试的视频:

获得 ModernStandby ResumeTime 的方法

微软大力推广 MS的一个原因是这个功能能够让系统更快的从睡眠状态醒来,因此,需要有一种方法来测量这个时间。

在微软的网站上有介绍使用 Windows Performance Analyzer的方法【参考1】,这里用实例介绍一下。对于WPA 的安装,可以在【参考4】看到。

1.到 WPA 的安装目录下使用 wpr -start Power 开始记录

wpr 开始记录和停止记录的命令

2.使用 Power Button 让系统进入MS,推荐十五分钟以上,然后使用  wpr -stop MSA.etl 生成记录文件“msa.etl”

WPA 记录结果

3.双机打开这个文件后,展开 System Activitiy,在右侧寻找 “Microsoft-Windows-PDC”项目:

WPA 查看Microsoft-Windows-PDC

4.在下面可以找到 “ExitFromConnectedStandbyStart”和 “ExitFromConnectedStandbEnd ” 两项:

“ExitFromConnectedStandbyStart”和 “ExitFromConnectedStandbEnd ”

5.其中给出的时间差值就是 Resume 花费的时间,这里是 1967.822568100 – 1967.029685499=0.792882601秒。

差值就是我们需要的 Resume time
  1. https://docs.microsoft.com/en-us/windows-hardware/design/device-experiences/modern-standby-resume-performance
  2. https://docs.microsoft.com/en-us/windows-hardware/design/device-experiences/using-windows-performance-analyzer-to-analyze-modern-standby-issues#capture-a-wpa-trace
  3. https://docs.microsoft.com/en-us/windows-hardware/design/device-experiences/modern-standby-wi-fi-connected-scenarios
  4. http://www.lab-z.com/wpainst/

ESP32 SPI 速度测试

使用DFRobot 的 FireBeetle 测试 SPI速度,代码在\DFRobot_FireBeetle-ESP32\0.0.9\libraries\SPI\examples  下面:

/* The ESP32 has four SPi buses, however as of right now only two of
 * them are available to use, HSPI and VSPI. Simply using the SPI API 
 * as illustrated in Arduino examples will use HSPI, leaving VSPI unused.
 * 
 * However if we simply intialise two instance of the SPI class for both
 * of these buses both can be used. However when just using these the Arduino
 * way only will actually be outputting at a time.
 * 
 * Logic analyser capture is in the same folder as this example as
 * "multiple_bus_output.png"
 * 
 * created 30/04/2018 by Alistair Symonds
 */
#include <SPI.h>

static const int spiClk = 1000000; // 1 MHz

//uninitalised pointers to SPI objects
SPIClass * vspi = NULL;
SPIClass * hspi = NULL;

void setup() {
  //initialise two instances of the SPIClass attached to VSPI and HSPI respectively
  vspi = new SPIClass(VSPI);
  hspi = new SPIClass(HSPI);
  
  //clock miso mosi ss

  //initialise vspi with default pins
  //SCLK = 18, MISO = 19, MOSI = 23, SS = 5
  vspi->begin();
  //alternatively route through GPIO pins of your choice
  //hspi->begin(0, 2, 4, 33); //SCLK, MISO, MOSI, SS
  
  //initialise hspi with default pins
  //SCLK = 14, MISO = 12, MOSI = 13, SS = 15
  hspi->begin(); 
  //alternatively route through GPIO pins
  //hspi->begin(25, 26, 27, 32); //SCLK, MISO, MOSI, SS

  //set up slave select pins as outputs as the Arduino API
  //doesn't handle automatically pulling SS low
  pinMode(5, OUTPUT); //VSPI SS
  pinMode(15, OUTPUT); //HSPI SS

}

// the loop function runs over and over again until power down or reset
void loop() {
  //use the SPI buses
  vspiCommand();
  hspiCommand();
  delay(100);
}

void vspiCommand() {
  byte data = 0b01010101; // junk data to illustrate usage

  //use it as you would the regular arduino SPI API
  vspi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));
  digitalWrite(5, LOW); //pull SS slow to prep other end for transfer
  vspi->transfer(data);  
  digitalWrite(5, HIGH); //pull ss high to signify end of data transfer
  vspi->endTransaction();
}

void hspiCommand() {
  byte stuff = 0b11001100;
  
  hspi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));
  digitalWrite(15, LOW);
  hspi->transfer(stuff);
  digitalWrite(15, HIGH);
  hspi->endTransaction();
}

其中的 spiClk 指定的是SPI 通讯速度,最高可以设置为 80000000(80M),示波器测量如下:

40M 波形测试如下

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/spi_master.html

Secure Boot 导致的蓝屏问题

最近在 Debug 一个问题,在刷坏了一个主板之后我更换了同型号的另外的主板。开机之后出现了无法进入系统的问题。

BSOD Message

试验无法进入安全模式。接下使用之前的 WinPe 盘【参考1】启动,查看上图提到的 SrtTrail.txt 内容如下:

Startup Repair diagnosis and repair log
---------------------------
Last successful boot time: ‎5/‎19/‎2020 11:39:04 PM (GMT)
Number of repair attempts: 1

Session details
---------------------------
System Disk = \Device\Harddisk0
Windows directory = C:\Windows
AutoChk Run = 0
Number of root causes = 1

Test Performed: 
---------------------------
Name: Check for updates
Result: Completed successfully. Error code =  0x0
Time taken = 0 ms

Test Performed: 
---------------------------
Name: System disk test
Result: Completed successfully. Error code =  0x0
Time taken = 0 ms

Test Performed: 
---------------------------
Name: Disk failure diagnosis
Result: Completed successfully. Error code =  0x0
Time taken = 0 ms

Test Performed: 
---------------------------
Name: Disk metadata test
Result: Completed successfully. Error code =  0x0
Time taken = 141 ms

Test Performed: 
---------------------------
Name: Disk metadata test
Result: Completed successfully. Error code =  0x0
Time taken = 0 ms

Test Performed: 
---------------------------
Name: Target OS test
Result: Completed successfully. Error code =  0x0
Time taken = 16 ms

Test Performed: 
---------------------------
Name: Volume content check
Result: Completed successfully. Error code =  0x0
Time taken = 31 ms

Test Performed: 
---------------------------
Name: Boot manager diagnosis
Result: Completed successfully. Error code =  0x0
Time taken = 0 ms

Test Performed: 
---------------------------
Name: System boot log diagnosis
Result: Completed successfully. Error code =  0x0
Time taken = 0 ms

Test Performed: 
---------------------------
Name: Event log diagnosis
Result: Completed successfully. Error code =  0x0
Time taken = 0 ms

Test Performed: 
---------------------------
Name: Internal state check
Result: Completed successfully. Error code =  0x0
Time taken = 0 ms

Test Performed: 
---------------------------
Name: Check for installed LCU
Result: Completed successfully. Error code =  0x0
Time taken = 4515 ms

Test Performed: 
---------------------------
Name: Check for installed driver updates
Result: Completed successfully. Error code =  0x0
Time taken = 750 ms

Test Performed: 
---------------------------
Name: Check for pending package install
Result: Completed successfully. Error code =  0x0
Time taken = 1625 ms

Test Performed: 
---------------------------
Name: Boot status test
Result: Completed successfully. Error code =  0x0
Time taken = 0 ms

Test Performed: 
---------------------------
Name: Setup state check
Result: Completed successfully. Error code =  0x0
Time taken = 94 ms

Test Performed: 
---------------------------
Name: Registry hives test
Result: Completed successfully. Error code =  0x0
Time taken = 469 ms

Test Performed: 
---------------------------
Name: Windows boot log diagnosis
Result: Completed successfully. Error code =  0x0
Time taken = 0 ms

Root cause found: 
---------------------------
Boot critical file c:\windows\system32\drivers\msdmfilt.sys is corrupt.

Repair action: File repair
Result: Failed. Error code =  0x57
Time taken = 1063 ms

---------------------------
---------------------------

从上面可以看到是因为 msdmfilt.sys 导致的,搜索了一下这个文件是 WTDF 的文件。没有办法进入安全模式也就没有办法卸载。忽然想起来可能是因为BIOS版本不同导致的。尝试启动到 Shell 来刷BIOS。但是又遇到数字签名不对的问题。这时候我意识到安装 WDTF 的时候 Secure Boot 是Disabled的,更换主板后默认是 Enabled。于是,进入 Setup 设置为 Dsiabled,问题就解决了。

参考:

1. http://www.lab-z.com/newghost/ Ghost 替代者,新的全盘备份工具

2.https://softwaretested.com/windows/how-to-fix-srttrail-txt-bsod-error-on-windows-10/ How to Fix SrtTrail.txt BSOD Error on Windows 10

TinkerNode 恢复方法

因为 TinkerNode 内置U盘功能,所以在某些状况下U盘出现问题会导致系统被拖慢,开发板无法上传等等情况。遇到这样的问题可以通过下面的几个方法尝试修复:

1.Arduino IDE 上传 Blinker 或者一个空的文件;

2.使用 sptool.exe –chip esp32 –port 端口号 –baud 512000 erase_flash尝试烧写

例如:sptool.exe –chip esp32 –port COM43 –baud 512000 erase_flash

3.使用 Arduino IDE 下载 ESP32 支持包选择低波特率烧写。

Step to UEFI (214)Ps2键盘的LED 分析

之前研究过Shell下如何控制USB 键盘上的 LED【参考1】,这次研究如何实现 PS2 键盘的 LED 控制。

和 USB 键盘一样,PS2 键盘同样需要实现Shell 下键盘 LED 的同步。意思是如果系统中有一个 USB 键盘和一个PS2键盘,当USB键盘 Num 键按下后,键盘LED状态也要同步到PS2 键盘上。

PS2键盘

对应的代码可以在\MdeModulePkg\Bus\Isa\Ps2KeyboardDxe\Ps2KbdCtrller.c 的 UpdateStatusLights 函数中看到。根据代码基本想法如下在这个头文件中有如下定义\MdeModulePkg\Bus\Isa\Ps2KeyboardDxe\Ps2Keyboard.h:

typedef struct {
  UINTN                               Signature;

  EFI_HANDLE                          Handle;
  EFI_SIMPLE_TEXT_INPUT_PROTOCOL      ConIn;
  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL   ConInEx;

  EFI_EVENT                           TimerEvent;

  UINT32                              DataRegisterAddress;
  UINT32                              StatusRegisterAddress;
  UINT32                              CommandRegisterAddress;

  BOOLEAN                             LeftCtrl;
  BOOLEAN                             RightCtrl;
  BOOLEAN                             LeftAlt;
  BOOLEAN                             RightAlt;
  BOOLEAN                             LeftShift;
  BOOLEAN                             RightShift;
  BOOLEAN                             LeftLogo;
  BOOLEAN                             RightLogo;
  BOOLEAN                             Menu;
  BOOLEAN                             SysReq;

  BOOLEAN                             CapsLock;
  BOOLEAN                             NumLock;
  BOOLEAN                             ScrollLock;

  BOOLEAN                             IsSupportPartialKey;
  //
  // Queue storing key scancodes
  //
  SCAN_CODE_QUEUE                     ScancodeQueue;
  EFI_KEY_QUEUE                       EfiKeyQueue;
  EFI_KEY_QUEUE                       EfiKeyQueueForNotify;

  //
  // Error state
  //
  BOOLEAN                             KeyboardErr;

  EFI_UNICODE_STRING_TABLE            *ControllerNameTable;

  EFI_DEVICE_PATH_PROTOCOL            *DevicePath;
  //
  // Notification Function List
  //
  LIST_ENTRY                          NotifyList;
  EFI_EVENT                           KeyNotifyProcessEvent;
} KEYBOARD_CONSOLE_IN_DEV;

先找到系统中的全部  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL ,检查 Signature 确定后再使用下面的宏即可获得KEYBOARD_CONSOLE_IN_DEV结构体

#define KEYBOARD_CONSOLE_IN_DEV_FROM_THIS(a)  CR (a, KEYBOARD_CONSOLE_IN_DEV, ConIn, KEYBOARD_CONSOLE_IN_DEV_SIGNATURE)
#define TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS(a) \
  CR (a, \
      KEYBOARD_CONSOLE_IN_DEV, \
      ConInEx, \
      KEYBOARD_CONSOLE_IN_DEV_SIGNATURE \
      )

之后即可用UpdateStatusLights() 函数实现更改LED 状态。

最终完整代码如下:

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

#include  "Ps2Keyboard.h"

extern EFI_BOOT_SERVICES        *gBS;
extern EFI_SYSTEM_TABLE         *gST;
extern EFI_RUNTIME_SERVICES     *gRT;

EFI_GUID gEfiSimpleTextInputExProtocolGuid = 
  {0xdd9e7534, 0x7762, 0x4698, 
      { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } };
                       
UINTN
EFIAPI
MicroSecondDelay (
  IN      UINTN                     MicroSeconds
  )
{
  gBS->Stall(MicroSeconds);
  return MicroSeconds;
}

/**
  Write data register.

  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
  @param Data      value wanted to be written

**/
VOID
KeyWriteDataRegister (
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
  IN UINT8                   Data
  )
{
  IoWrite8 (ConsoleIn->DataRegisterAddress, Data);
}

/**
  Read data register .

  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV

  @return return the value

**/
UINT8
KeyReadDataRegister (
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
  )

{
  return IoRead8 (ConsoleIn->DataRegisterAddress);
}

/**
  Read status register.

  @param ConsoleIn  Pointer to instance of KEYBOARD_CONSOLE_IN_DEV

  @return value in status register

**/
UINT8
KeyReadStatusRegister (
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
  )
{
  return IoRead8 (ConsoleIn->StatusRegisterAddress);
}

/**
  wait for a specific value to be presented on
  8042 Data register by keyboard and then read it,
  used in keyboard commands ack

  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
  @param Value     the value wanted to be waited.

  @retval EFI_TIMEOUT Fail to get specific value in given time
  @retval EFI_SUCCESS Success to get specific value in given time.

**/
EFI_STATUS
KeyboardWaitForValue (
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
  IN UINT8                   Value
  )
{
  UINT8   Data;
  UINT32  TimeOut;
  UINT32  SumTimeOut;
  UINT32  GotIt;

  GotIt       = 0;
  TimeOut     = 0;
  SumTimeOut  = 0;

  //
  // Make sure the initial value of 'Data' is different from 'Value'
  //
  Data = 0;
  if (Data == Value) {
    Data = 1;
  }
  //
  // Read from 8042 (multiple times if needed)
  // until the expected value appears
  // use SumTimeOut to control the iteration
  //
  while (1) {
    //
    // Perform a read
    //
    for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
      if (KeyReadStatusRegister (ConsoleIn) & 0x01) {
        Data = KeyReadDataRegister (ConsoleIn);
        break;
      }

      MicroSecondDelay (30);
    }

    SumTimeOut += TimeOut;

    if (Data == Value) {
      GotIt = 1;
      break;
    }

    if (SumTimeOut >= KEYBOARD_WAITFORVALUE_TIMEOUT) {
      break;
    }
  }
  //
  // Check results
  //
  if (GotIt == 1) {
    return EFI_SUCCESS;
  } else {
    return EFI_TIMEOUT;
  }

}

//
//\MdeModulePkg\Bus\Isa\Ps2KeyboardDxe\Ps2KbdCtrller.c
//
/**
  write key to keyboard

  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
  @param Data      value wanted to be written

  @retval EFI_TIMEOUT   The input buffer register is full for putting new value util timeout
  @retval EFI_SUCCESS   The new value is sucess put into input buffer register.

**/
EFI_STATUS
KeyboardWrite (
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
  IN UINT8                   Data
  )
{
  UINT32  TimeOut;
  UINT32  RegEmptied;

  TimeOut     = 0;
  RegEmptied  = 0;

  //
  // wait for input buffer empty
  //
  for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
    if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) {
      RegEmptied = 1;
      break;
    }

    MicroSecondDelay (30);
  }

  if (RegEmptied == 0) {
    return EFI_TIMEOUT;
  }
  //
  // Write it
  //
  KeyWriteDataRegister (ConsoleIn, Data);

  return EFI_SUCCESS;
}

//
//\MdeModulePkg\Bus\Isa\Ps2KeyboardDxe\Ps2KbdCtrller.c
//
/**
  Show keyboard status lights according to
  indicators in ConsoleIn.

  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV

  @return status of updating keyboard register

**/
EFI_STATUS
UpdateStatusLights (
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
  )
{
  EFI_STATUS  Status;
  UINT8       Command;

  //
  // Send keyboard command
  //
  Status = KeyboardWrite (ConsoleIn, 0xed);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  KeyboardWaitForValue (ConsoleIn, 0xfa);

  //
  // Light configuration
  //
  Command = 0;
  if (ConsoleIn->CapsLock) {
    Command |= 4;
  }

  if (ConsoleIn->NumLock) {
    Command |= 2;
  }

  if (ConsoleIn->ScrollLock) {
    Command |= 1;
  }

  Status = KeyboardWrite (ConsoleIn, Command);

  if (EFI_ERROR (Status)) {
    return Status;
  }

  KeyboardWaitForValue (ConsoleIn, 0xfa);
  return Status;
}


int
EFIAPI
main (
  IN int Argc,
  IN CHAR16 **Argv
  )
{
  EFI_STATUS    Status;
  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL       *ConIn;
  KEYBOARD_CONSOLE_IN_DEV              *ConsoleIn;
  UINTN         HandleIndex, HandleCount;
  EFI_HANDLE    *DevicePathHandleBuffer = NULL;
  UINTN         i;
  //
  //Get all the Handles that have SimpleTextInputEx Protocol
  //
  Status = gBS->LocateHandleBuffer(
                  ByProtocol,
                  &gEfiSimpleTextInputExProtocolGuid,
                  NULL,
                  &HandleCount,
                  &DevicePathHandleBuffer);
  //
  //Open SimpleTextInputEx Protocol on each device
  //
  for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) 
  { 
    Status = gBS->HandleProtocol(
                      DevicePathHandleBuffer[HandleIndex],
                      &gEfiSimpleTextInputExProtocolGuid,
                      (VOID**)&ConIn);
    if (EFI_ERROR(Status))
      {
        Print(L"ERROR : Open ConIn fail.\n");
        gBS->FreePool(DevicePathHandleBuffer);  
        return 0;
      }
    
    //Get KEYBOARD_CONSOLE_IN_DEV by SimpleTextInputEx Protocol    
    ConsoleIn = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (ConIn);
    
    //Check the signature if it's what we want    
    if (ConsoleIn->Signature==KEYBOARD_CONSOLE_IN_DEV_SIGNATURE) {
            // Turn Off all LEDs
            ConsoleIn->CapsLock=0;
            ConsoleIn->NumLock=0;
            ConsoleIn->ScrollLock=0;
            UpdateStatusLights(ConsoleIn);
                    
            for (i=0;i<20;i++) {
                    ConsoleIn->NumLock=1;
                    UpdateStatusLights(ConsoleIn);
                    MicroSecondDelay(300000UL);
                    ConsoleIn->NumLock=0;
                    UpdateStatusLights(ConsoleIn);
                    MicroSecondDelay(300000UL);
                    
                    ConsoleIn->CapsLock=1;
                    UpdateStatusLights(ConsoleIn);
                    MicroSecondDelay(300000UL);
                    ConsoleIn->CapsLock=0;
                    UpdateStatusLights(ConsoleIn);
                    MicroSecondDelay(300000UL);
                    
                    ConsoleIn->ScrollLock=1;
                    UpdateStatusLights(ConsoleIn);
                    MicroSecondDelay(300000UL);
                    ConsoleIn->ScrollLock=0;
                    UpdateStatusLights(ConsoleIn);
                    MicroSecondDelay(300000UL);
                }
   } //if (ConsoleIn->Signature
  } //for (HandleIndex = 0;

  gBS->FreePool(DevicePathHandleBuffer);  
  return Status;
}

完整代码和X64 EFI 下载(因为含有 IO 代码,所以必须在实体机上运行)

工作的视频:

参考:

  1. https://www.lab-z.com/stu120uk/  UEFI 下控制USB键盘 LED
  2. http://www-ug.eecg.toronto.edu/msl/nios_devices/datasheets/PS2%20Keyboard%20Protocol.htm The PS/2 Keyboard Interface
  3. https://wiki.osdev.org/PS/2_Keyboard PS/2 Keyboard