Step to Memory 001 存储架构

继续之前的《PC 内存的秘密 第一部分》,来自 https://www.bit-tech.net/reviews/tech/memory/the_secrets_of_pc_memory_part_1/2/

第二章 存储架构

计算机上内存系统最显眼的部分是内存和板载插槽。每一代和每一类型的内存外形和插槽都略有不同,这样的设计用来避免因为误插不同型号的内存而造成损坏。

每个内存模块上都有称为 DRAM 的小型内存芯片,有时也被称为更通用的名称 – 集成电路 (IC)。DRAM 核心是一组称为单元的电容器,它们通过保持电荷来保留数据(0 或 1)。

在读取数据之前,指定的电容器会放电到一个放大器(电压电流太小,无法被直接读取,因此需要一个放大器)。也是因为这个原因信号读取过程是一个破坏性动作,会擦除电容器上的电荷。所以,在读取之后还需要额外的过程来为已读取的单元充电。这种易失性是 RAM 技术与 NAND 和 NOR 等固态存储器之间的主要区别。

根据金士顿内存公司的数据,对于第一代双倍数据速率内存(DDR1),普通计算机访问物理内存大约需要 200ns(纳秒),而硬盘驱动器则需要 12,000,000ns。如果换算成更容易理解的时间单位,两者的速度相差60,000 倍。这意味着做某件事需要 1 分钟或 42 天。

Cache(缓存)和 RAM 之间的区别

缓存也是一种内存,比 DDR 等标准系统内存快得多。这种内存用于充当频繁请求数据的专用存储区域,以实现超快速访问。根据情况,缓存也会被称作“缓冲区”。现代的缓存都是位于处理器芯片内,这些缓存根据优先级和访问速度进行分段:1 级 (L1)、2 级 (L2) 和 3 级 (L3)。L1 速度最快,延迟最低,但容量(通常以KB为单位)最小。在处理数据时,DDR 内存模块中最常访问的指令和数据会被复制到 L1 缓存中。缓存有许多不同的职责:有些仅用于数据,而有些则更专门用于命令代码或程序指令。所有现代台式机 CPU 都有一个专用的、独立的 L1 缓存,用于指令和数据。

L1 缓存的速度比标准 DDR2 甚至 DDR3 内存快很多倍。搭配最新 Intel X38 芯片组的 Intel E6750 的 L1 缓存性能约为 42,500MB/s。其次是速度稍慢但容量大得多(通常以MB为单位)的 L2 缓存,性能约为 20,500MB/s。相比之下,最新的双通道 DDR3 内存在 1,333MHz 和平均延迟设置下带宽约为 8,800MB/s。

一些 DDR 内存模块使用缓冲技术来实现更高的可靠性和性能。这些具有先进逻辑和电路的 “缓冲”内存是专门设计用于工作站和服务器级的。

Fully-Buffered DIMM (FB-DIMM) 使用高级内存缓冲器 (AMB) 来改善数据传输、信号完整性和错误检测。它旨在以串行方式移动数据,而不是 AMB 和内存控制器之间的并行架构。 FB-DIMM 的问题在于可扩展性较差,同时额外的芯片芯片会导致数据访问延迟以及发热严重的问题

常见的台式机内存模块被称为“无缓冲”DIMM;它们使用不同的内存总线技术,相比之下要便宜得多。读者应该注意,尽管标记为“DDR2”,但 FB-DIMM 与常见的台式计算机不兼容。

这里多介绍一下:这种内存长下面这样【参考1】

传统的内存拓扑结构都是这样:

FB-DIMM拓扑结构这样:

固态存储器 重要的是不要混淆这两种截然不同的存储器:易失性 RAM 技术和非易失性闪存存储器。闪存(或非易失性)存储器基于两种基本技术 – NAND 和 NOR。既然它们与 DDR 无关,为什么我们必须考虑这些类型的存储器?

计算机系统的未来在很大程度上依赖于现有的 DDR 存储器与非易失性闪存存储器协同工作,以提高整体系统性能。与随机存取存储器 (RAM) 技术不同,基于闪存的存储器无需一直供电即可保留数据。虽然它们的访问速度比当前的 DDR 技术慢,但由于没有机械部件,它们在随机读取期间通常比典型的机械硬盘驱动器快得多。


在 ReadyBoost 下,Microsoft Vista 和未来的操作系统将同时使用这两种类型的内存来提高整体系统性能。一个很好的例子是英特尔基于 NAND 闪存技术的“Turbo 内存”。在研发阶段,英特尔内部称为“Robson”技术,但现在 Turbo 内存已成为最新“Santa Rosa”迅驰平台不可或缺的一部分。它就像一个用于频繁使用的文件和应用程序的大型缓存,由于随机读取延迟很小并且能避免文件碎片(无需像硬盘寻道),因此比硬盘更快。

支持这种双存储技术的操作系统在启动时具有优势,因为关键操作系统文件可以在启动期间存储在基于闪存的内存中。

这种设计可以认为是在内存和硬盘之间再添加一层 Cache, 但是随着固态硬盘的普及,机械硬的落幕,这种多增加一层缓存的设计也退出了历史舞台。

固态硬盘

全固态硬盘驱动器是未来个人电脑的重要组成部分,它们的功耗相比机械硬盘要低得多。另外,在恶劣的移动环境中,其可靠性和生存能力远远高于标准机械磁盘驱动器。
通常,固态存储技术比当前的 DDR 技术慢,并且数据写入寿命可能相对较短,随着技术进步这个问题正在迅速改变。新技术在不断增加固态存储的寿命和存储密度。这种设备的寿命取决于制造商采用的错误校正、位冗余、操作逻辑和自诊断算法的组合。

使用固态硬盘的直接好处是,由于没有任何移动和旋转的机械系统,数据在任何突然的高 G 运动中都能生存下来。此外,固态硬盘的功耗和工作温度更低,是笔记本电脑和移动设备的理想选择。

因此,可以合理预期传统机械硬盘的许多故障将被消除。全球大型数据中心的运营成本有望大幅降低,空调需求减少,灾难性故障也更少。随着成本下降和密度增加,未来几年固态内存的市场将比 DRAM 技术更大。

原文距离今天已经有一段时间了,这段时间里,因为固态硬盘的迅速发展(主要是价格迅速降低),ReadyBoost 技术已经退出了历史舞台。如果有人诟病机械硬盘的缓慢,最好的方法就是更换为固态键盘。不过我个人还是更喜欢机械硬盘,因为这种硬盘只要妥善保存能够维持数据,并且在寿命将近时会有足够的提示而不是忽然完全坏掉。

参考:

1. https://www.simmtester.com/News/PublicationArticle/136

CH32X033 更改 UART1 到 PA10

CH32X035 EVT EXAM 中 USART1 默认使用 PB10 做 TX ,但是CH32X033 没有 PB10。这里介绍如何调整设置使用 PA10 为 TX。

对应着修改 DEBUG.C 的代码即可:

/*********************************************************************
 * @fn      USART_Printf_Init
 *
 * @brief   Initializes the USARTx peripheral.
 *
 * @param   baudrate - USART communication baud rate.
 *
 * @return  None
 */
void USART_Printf_Init(uint32_t baudrate)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;

#if(DEBUG == DEBUG_UART1)

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);
    GPIO_PinRemapConfig(GPIO_PartialRemap1_USART1, ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

#elif(DEBUG == DEBUG_UART2)
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

相当于Remap USART TX 为 PA10。

Step to Memory 000 内存常识

作为一名BIOS工程师,内存是无法回避的问题。最近在看一些内存的知识,忽然发现如果想理解现在的设计,那么必须去阅读过去的设计,这样才能知道为什么设计成今天的样子。而这一段让我想起来那一句名言:“He who controls the past controls the future.”

这一系列文章将从个人视角尝试介绍和理解x86 消费级内存相关知识。

首篇献给 《PC 内存的秘密》系列文章。需要注意的是这篇文章发表于2007年,其中一些知识已经发生了变化,在对应的位置我会标记出来。

《PC 内存的秘密 第一部分》原文来自 https://www.bit-tech.net/reviews/tech/memory/the_secrets_of_pc_memory_part_1/1/

第一章 基础知识

前言

作者:Richard Swinburne
Ryan Leng 是计算机系统领域的独立技术顾问和审计师,为公司提供硬件、软件、网络、安全、IT 政策制定和培训方面的服务。

他最初接受的是计算机科学和经济学方面的培训,之后从事了许多领域的工作,包括计算机硬件集成、软件设计和工程、监控系统、广告、多媒体制作、用户界面工程和图形设计。不久前,

Ryan 带着他尚未出版的关于 DDR 技术的书籍与bit-tech

进行了接触,我们读到这本书时,对其深度和对细节的关注以及能够以易于理解的方式传达复杂的想法印象深刻。 无论您是否精通内存技术知识,对于 PC 架构的基本部分来说,这仍然是一本有趣的读物。我们将他的工作分成几个部分,我们在此处发布的第一部分涵盖了基础知识。此处发布的信息仅仅是一份更大文档的摘录。

Ryan 解释道:本文旨在与大家分享我关于内存技术的知识和经验,尤其是我广泛使用过的双倍数据速率 (DDR) RAM。本文讨论了许多主题,包括代际差异、趋势、DDR 信号管理技术、系统优化策略、内存兼容性问题和购买注意事项。

我还希望帮助解释一些内存相关技术,这些技术可能在某些在线社区和“技术”网站中解释得模糊或不正确。为了使本文更易于理解,最重要的是,更容易让普通读者理解,我删除了许多细节和高度技术性的信息。

本文开始于研究华硕、升技、映泰、友通、海盗船、金士顿、威刚等产品的严重 DDR2 内存兼容性问题(800MHz 及以上)。DDR 内存技术的不确定性不断增加,内存系统设计人员一直都知道这一点,并且发现缓解和解决这些问题越来越具有挑战性。

为什么这对普通用户和爱好者很重要? RAM 稳定性问题和超频限制是相辅相成无法分割的。【最简单的理解是:如果你手上的6400Mhz内存,通过某种稳定的超频设置可以稳定的跑在8533Mhz, 那么对于供应商来说就会打上8533Mhz的标签进行出售了】。了解如何测试和解决兼容性问题可以帮助提高用户对 RAM 超频的了解。”

我们感谢 Ryan 为我们带来他的专业材料,并祝愿他未来一切顺利。

基础知识

管理内存技术标准的行业机构是联合电子设备工程委员会 (JEDEC)。近年来,该机构更名为“JEDEC 固态技术协会”。JEDEC 是更大的半导体工程标准化机构电子工业联盟 (EIA) 的一部分。EIA 是一个代表电子行业所有领域的行业协会。

您现在使用的计算机的所有制造商都是 EIA 和 JEDEC 的成员。自 1958 年以来,JEDEC 一直是固态行业标准的领先开发者。在过去 15 年中,DRAM 性能提高了 4,000%。然而,设计仍然相对简单,这是有意为之。RAM技术最基本的方面是需要持续供电才能保留数据,这个过程称为自刷新。因为现在的工业已经对现有基础设施进行了大量的投资,因此成本的考量一直推动着内存系统的设计。大部分复杂性被特意放在内存控制器中。这一切努力使得 DRAM 的产量相对较高,价格也相当便宜。消费产品的主要目标往往是向市场提供尽可能便宜的产品,以最大限度地提高普及率,而不是提供技术上更优越但是需要颠覆大量设计的产品。

根据MOSAID 公司的 Graham Allan 和 Jody Defazio 表示:目前的市场领导者 是DDR2方案,它提供供应安全、高存储容量、低成本和合理的通道带宽,但插槽并不方便且需要非常复杂的控制器才能让它工作起来。”为了便于分辨,SDRAM 将被表示为“SDR”,第一代 DDR SDRAM 将用“DDR1”表示,这里的“DDR”是 “Double-Data Rate standard”的缩写,表示双倍数据速率标准相关的内存技术系列。

测量

在讨论内存时,我们无法逃避诸如时钟周期、时序、每秒兆比特 (Mbps) 和兆赫 (MHz) 等术语。它们都是相关的,用于解释不同情况下内存系统的速度概念。

通常使用兆字节 (MB) 和千兆字节 (GB) 来描述存储容量。带宽和速度有着不同的测量单位,他们都是我们描述系统性能的方式,不仅限于内存,还应用于计算机的其他部分。需要注意的是,上述单位在作为存储单位时,我们通常以1024为单位。比如,1K表示 1024字节。

一个用于说明发送的数据量(Bits),通常以给定时间段内的单位(每秒位数)计算。另一个用于测量数据流动的速度(Hz)。“流”越快,一秒钟内可以承载更多的数据单位。在讨论内存系统的速度时,这两个通常互换使用。

高级用户会注意到一个称为时钟周期(CK 或 tCK)的测量单位用于描述内存延迟。它们是内存操作状态更改期间的必要延迟,其中延迟越短内存性能越好,速度越快。此外,时钟周期可以转换为纳秒 (ns)。比如,当前时钟频率是1000Hz,对应着一个时钟的周期就是 1/1000秒。10个时钟周期就是 10*(1/1000)秒。

使用“公路”的概念来理解

内存路径类似于道路。带宽(每秒比特数)类似于道路某一部分在给定时间内可以处理的最大汽车数量,这个值与可用车道的宽度或数量直接相关。

频率(Hz)相当于对这些汽车施加的最大速度限制。更高的速度限制将允许更多车辆以更快的速度行驶。但是,这个可能会导致更频繁的发生碰撞。内存延迟可以被认为是这些道路上有交通信号灯的路口。它们会造成延迟以避免车辆碰撞。缩短等待时间将增加车辆流量,但前提是它们已经准备好并有足够的时间移动。

Windows 驱动 SYS/INF/CAT的功能与用途

1.SYS 文件(驱动程序核心文件)

SYS 文件是驱动程序的核心二进制文件,包含硬件设备与操作系统交互的代码逻辑。例如,当用户插入新硬件时,系统会调用对应的 SYS 文件实现设备初始化、中断处理和数据传输等功能。

  • 功能:直接控制硬件设备,提供操作系统与硬件之间的接口。
  • 生成方式:通过编译驱动程序源代码(如 C/C++)生成,编译时会根据目标系统架构(如 32 位或 64 位)生成对应的文件。

2.INF 文件(安装信息文件)

INF 文件是文本格式的配置文件,指导 Windows 如何安装驱动程序。其内容包含设备标识、文件复制路径、注册表项修改等信息。

  • 功能:定义设备与驱动程序的匹配规则(如硬件 ID、兼容 ID)。
  • 指定需要复制的文件(如 SYS、DLL)及其目标路径。配置注册表、服务启动参数等系统设置。

示例结构:

Inf
[Version]
Signature="$WINDOWS NT$"
Class=SampleDriver
[Manufacturer]
%Manufacturer%=MyCompany
[MyCompany.NT]
%DeviceName%=DriverInstall, HardwareID\VEN_1234

3.CAT 文件(安全目录文件)

CAT 文件是经过数字签名的安全目录文件,用于验证驱动程序的完整性和合法性。

  • 功能:包含驱动程序文件的哈希值列表,确保文件未被篡改。
  • 支持 Windows 的驱动程序强制签名验证(尤其在 64 位系统中)。

三者的协作流程

  1. 系统检测到新硬件时,根据硬件 ID 匹配 INF 文件。
  2. 按照 INF 文件的指示复制 SYS 文件到系统目录并配置注册表。
  3. 通过 CAT 文件验证驱动签名,确保安全后完成安装。

上述回答来自 CSDN

ESP32 PSRAM 测试程序

一个测试 PSRAM 的程序

int n_elements = 1000;
unsigned char * acc_data_all;

void setup(){
        delay(3000);
        Serial.begin(115200);
        acc_data_all = (unsigned char *) ps_malloc (n_elements * sizeof (unsigned char)); 
        if(psramInit()){
        Serial.println("\nPSRAM is correctly initialized");
        }else{
        Serial.println("PSRAM not available");
        }
        memcpy(acc_data_all,"www.lab-z.com",14);
}

void loop() {
  Serial.println((char*)&acc_data_all[0]);
  delay(1000);
}

当使用 DFRobot FireBeetle 2 ESP32-S3 时,需要如下设置:

VirtualBox Windows 11 的 DSDT

最近在 VirtualBox 上进行ACPI 方面的试验,经过努力 Dump 出来 DSDT 的 ASL ,然后手工加入了一个自定义设备:

//LABZ_Debug_Start
       Device (LABZ)
            {
                Name (_HID, EisaId ("LAB33D6") /* Intel Virtual Buttons Device */)  // _HID: Hardware ID
                Method (_STA, 0, Serialized)  // _STA: Status
                {
                    Return (0x0F)
                }
	    }
//LABZ_Debug_End

有需要的朋友可以基于这个版本修改增加你需要的功能:

CH32V305 使用 UART3 的例子

根据 Ch32V307 的 “USART_Printf:串口打印调试例程” 修改而来。对于Ch32V305来说,UART3 在电路图如下位置:

Arduino 代码如下:

void zUSART_Printf_Init(uint32_t baudrate)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    USART_InitStructure.USART_BaudRate = baudrate;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Tx;

    USART_Init(USART3, &USART_InitStructure);
    USART_Cmd(USART3, ENABLE);

}

 void OutUart(char *buf, int size)
{
    for(int i = 0; i < size; i++)
    {
        while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET);
        USART_SendData(USART3, *buf++);
    }
}

void setup() {
  zUSART_Printf_Init(115200);
}

void loop() {
  char sMsg[]="www.lab-z.com";
  OutUart(sMsg,sizeof(sMsg));
  delay(1000);
}
// USART3 缓冲区最大长度
#define RXBUFFER3SIZE    100
// USART3 缓冲区
u8 RxBuffer3[RXBUFFER3SIZE];
// USART3 缓冲区内数据长度
volatile u8 RxCnt3 = 0;

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
void USART2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void USART3_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus

/*********************************************************************
   @fn      USARTx_CFG

   @brief   Initializes the USART2 & USART3 peripheral.

   @return  none
*/
void USARTx_CFG(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure = {0};
  USART_InitTypeDef USART_InitStructure = {0};
  NVIC_InitTypeDef  NVIC_InitStructure = {0};

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

  /* USART3 TX-->B.10  RX-->B.11 */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

  USART_InitStructure.USART_BaudRate = 115200;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_No;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;

  USART_Init(USART3, &USART_InitStructure);
  USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);

  NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  
  USART_Cmd(USART3, ENABLE);
}

void setup() {
  // 这次的测试是从 USART3 接收,然后将收到的数据从 USART1 送出
  Serial.begin(115200);
  Serial.println("Start");
  USARTx_CFG(); 
  Serial.println("Init Done");
}

void loop() {
  if (RxCnt3!=0) {
      for (int i=0;i<RxCnt3;i++) {
          Serial.write(RxBuffer3[i]);
        }
      RxCnt3=0;
    }
   
   delay(1000);
}

/*********************************************************************
 * @fn      USART3_IRQHandler
 *
 * @brief   This function handles USART3 global interrupt request.
 *
 * @return  none
 */
void USART3_IRQHandler(void)
{
    if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
    {
        RxBuffer3[RxCnt3++] = USART_ReceiveData(USART3);
    }
}

关闭Chrom禁止加载本地文件的方法

在调试 JavaScript 的时候,默认情况下是无法加载本地的图片或者其他文件的。这样对于调试造成了一定困扰,一种给解决方法是启动一个本地的Http Server 然后即可调试;此外还可以通过关闭浏览器的安全设置来实现。根据【参考1】,可以在命令行下运行如下命令:

"C:\Program Files\Google\Chrome\Application\chrome.exe" --allow-file-access-from-files --user-data-dir="C:\temp" --disable-web-security

在新开的窗口中打开你的 html 文件即可。

参考:

1.https://blog.csdn.net/meser88/article/details/130229417