Bios工程师手边事—PCI资源分配

PCIe 总线基础 驱动接口 和 BAR空间详解 在一个系统中的每一个设备(device)在地址空间的大小和类型是不同的,对应不同的访问需求。例如,某一个设备在内部寄存器或者存储空间有256Byte,可以通过IO地址空间访问,另个一设备有16K大小的空间则需要通过MMIO的方式进行访问;哪些地址应该使用哪种方式(IO或Memory)来访问设备的内部位置,这是系统软件(即BIOS和OS内核)的工作,PCI设备无法自己决定,但是需要提供一个方法让系统软件去决定以何种方式去访问设备内部地址空间。 阅读详情
AI摘要

本文介绍了EFI BIOS中PCI BUS驱动如何进行资源分配,包括PCI设备所需的IO、Memory、IRQ以及OpROM。通过PCI扫描和PCIBAR分析,详细讲解了PCI设备资源的需求与分配过程,涉及PCI BAR是否存在、计算长度以及OpRom的支持判断。

一说到资源,大家马上想到“利用”两个字。是的,没有利用价值的资源不是真正的资源。大到整个社会,小到个人,都在利用资源实现自己的想法。PCI设备也不例外,想让PCI设备工作,PCI设备驱动一定要有资源可以利用,但是这个资源从何而来?下面就来介绍一下EFI下最为重要的一个驱动:PCIBUS驱动。

    在此注明一下,IRQ也是PCI资源重要的一种。但是其并不是PCIBUS驱动所设,之前我也有写过一篇INTERRUPT的文章讲述这一点,所以此篇文章将此忽略。

    PCIBUS驱动要为PCI设备分配的资源有哪些呢?换言之,一个PCI设备插到系统中,它需要什么东西才可以正常工作?IO,Memory,IRQ,OpROM。IRQ是CPU查找设备请求访问的触发机制,IO和MEMORY是CPU访问设备所用到的映射机制,OpROM是PCI设备厂商方便用户使用其设备所提供的一个便利机制。想要搞懂如何分配这些资源,首先PCIBUS要找到相应的设备,我们来看一下PCIBUS找设备的过程。

 

1 PCI扫描

    在PLTRST#过后,所有PCI设备均处于初始状态。包括PCI BUS,也只有Host Bridge掌控的BUS0处于正常状态,其余的PCI桥都处于“杂乱无章”的状态。如果想让PCI BUS能够正常工作,能够让CPU发出的PCI访问信息正确路由至PCI设备处,我们必须扫描PCI BUS,为各个PCI 桥分配上正确的Primary Bus,Secondary Bus和SubOrdinate Bus。

    EFI BIOS采用深度优先的算法来扫描PCI Bus,具体可查看UDK2014 PCIBUS驱动的PciScanBus函数,这是一个递规的函数。从BUS0开始,见到有扫描的PCI设备为PCI桥的时候,便为该PCI桥分配Secondary Bus,然后立即转入该Secondary Bus的扫描。除了设置PCI Bus Number,PCI BUS驱动还会根据PCI桥下挂的设备资源来设置PCI桥的2个BASE ADRESSRegister以及MEMORY BASE,Limit和IO Base,Limit。

    在扫描的过程中,PCI BUS驱动会检查PCI Agent(我也不知道Agent怎么翻译)。如果其支持内存,IO和OpROM,则PCI BUS会计算其大小,然后为其分配基址。下面来看一下,PCI BUS如何获取PCI设备是否支持MEMORY,IO,OpROM的,以及如何获取其大小的。

 

2PCIBar

    一个PCI Agent,有6个PCIBar,在其配置空间的0ffset 0x10至0x24处,每个Bar占4个字节。PCI Agent需不需要Memory和IO,需要多少,是由PCI Agent本身决定的,所以我们要通过访问这些BAR来确定这些资源。

 

2.1 是否需要MEMORY和IO

    在PCIBUS Gather PCI Agent信息的时候,会调用BarExisted()函数来确定某个BAR是否支持MEMORY和IO。我们来看一个函数体:

EFI_STATUS

BarExisted(

  IN PCI_IO_DEVICE *PciIoDevice,      //指向该PCI Agent结构体

  IN UINTN         Offset,             //这个是BAR的offset,0x10到0x24

  OUT UINT32        *BarLengthValue,    //用来接收BAR需要的资源长度,这个最重要

  OUT UINT32        *OriginalBarValue   //PCI AGENT原始值

  )

{

  EFI_PCI_IO_PROTOCOL *PciIo;

  UINT32              OriginalValue;

  UINT32              Value;

  EFI_TPL             OldTpl;

 

  PciIo = &PciIoDevice->PciIo;

  // 保存原始的BAR值

  PciIo->Pci.Read (PciIo,EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);

  // 提升本任务优先级别,TPL_HIGH_LEVEL为最高级别

  OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);

  //写全1,再读回值,对于有关长度的BIT,写1无效。

  PciIo->Pci.Write (PciIo,EfiPciIoWidthUint32, (UINT8) Offset, 1, &gAllOne);

  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32,(UINT8) Offset, 1, &Value);

  PciIo->Pci.Write (PciIo,EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);

  // 恢复任务优先级

  gBS->RestoreTPL (OldTpl);

  if (BarLengthValue != NULL) {

    *BarLengthValue = Value;

  }

  if (OriginalBarValue != NULL) {

    *OriginalBarValue = OriginalValue;

  }

//返回值为0,说明此BAR不支持MEMORY或IO,否则是支持的

  if (Value == 0) {

    return EFI_NOT_FOUND;

  } else {

    return EFI_SUCCESS;

  }

}

如果此BAR根本不支持MEMORY或IO,再去取补计算这个BAR的LENGTH是没意义的。

 

2.2 计算BAR长度

    计算BAR长度,就是对2.1中读到的BarLengthValue参数求补操作。

    看一下下面的程序段,Value就是BarLengthValue。

    该BAR请求IO的情况:

    Mask = 0xfffffffc;

    if ((Value & 0xFFFF0000) != 0) {    //操,难道还有为0的情况?

     PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeIo32;

     PciIoDevice->PciBar[BarIndex].Length    = ((~(Value & Mask)) + 1);//该BAR真正的长度

     PciIoDevice->PciBar[BarIndex].Alignment =PciIoDevice->PciBar[BarIndex].Length - 1;

 

    } else {

      //It is a IO16 bar

     PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeIo16;

     PciIoDevice->PciBar[BarIndex].Length    = 0x0000FFFF & ((~(Value & Mask)) +1);

     PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length- 1;

 

如果BIT0=0,那么该BAR是请求MEMORY的BAR,如下图所示,可以看出其需求:


 Mask  =0xfffffff0;

    PciIoDevice->PciBar[BarIndex].BaseAddress= OriginalValue & Mask;

    switch (Value & 0x07) {

    case 0x00:      //BIT2,1=00B,需求32位

      if ((Value & 0x08) != 0) {

        PciIoDevice->PciBar[BarIndex].BarType= PciBarTypePMem32;

      } else {

       PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;

      }

     PciIoDevice->PciBar[BarIndex].Length    = (~(Value & Mask)) + 1;  //和IO没啥区别

      if (PciIoDevice->PciBar[BarIndex].Length< (SIZE_4KB)) {

       PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);

      } else {

       PciIoDevice->PciBar[BarIndex].Alignment =PciIoDevice->PciBar[BarIndex].Length - 1;

      }

      break;

    case 0x04:      //BIT2,1=10B,需求64位,需要两个BAR

      if ((Value & 0x08) != 0) {

       PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;

      } else {

       PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;

      }

     PciIoDevice->PciBar[BarIndex].Length    = Value & Mask;

     PciIoDevice->PciBar[BarIndex].Alignment =PciIoDevice->PciBar[BarIndex].Length - 1;

      Offset += 4;

 

      Status = BarExisted (

                 PciIoDevice,

                 Offset,

                 &Value,

                 &OriginalValue

                 );

 

      if (EFI_ERROR (Status)) {

        if(PciIoDevice->PciBar[BarIndex].Length == 0) {

         PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;

        }

        return Offset + 4;

      }

      Value |= ((UINT32)(-1) <<HighBitSet32 (Value));

     PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64)OriginalValue, 32);

 

     PciIoDevice->PciBar[BarIndex].Length    = PciIoDevice->PciBar[BarIndex].Length |LShiftU64 ((UINT64) Value, 32);

     PciIoDevice->PciBar[BarIndex].Length    =(~(PciIoDevice->PciBar[BarIndex].Length)) + 1;//64位MEMORY,长度和32位算法一样

      if(PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {

       PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);

      } else {

       PciIoDevice->PciBar[BarIndex].Alignment =PciIoDevice->PciBar[BarIndex].Length - 1;

      }

 

      break;

 

  //其它情况,PCI还未定义

    default:

     PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeUnknown;

      PciIoDevice->PciBar[BarIndex].Length    = (~(Value & Mask)) + 1;

      if(PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {

        //

        // Force minimum 4KByte alignment forVirtualization technology for Directed I/O

        //

        PciIoDevice->PciBar[BarIndex].Alignment= (SIZE_4KB - 1);

      } else {

       PciIoDevice->PciBar[BarIndex].Alignment =PciIoDevice->PciBar[BarIndex].Length - 1;

      }

      break;

}

 

    这些BAR和长度算出后,紧接着PCIBUS就会提交给HOST Bridge该设备的资源请求,HOST Bridge进行分配。

 

3 OpRom

3.1 判断是否支持OpRom

    如果设备上有一颗I2C的ROM,那么该PCI Agent是支持OpROM的。那如何确定是否支持呢?我们来看一下UDK2014的一段代码:

EFI_STATUS

GetOpRomInfo(

  IN OUT PCI_IO_DEVICE    *PciIoDevice

  )

{

  UINT8                           RomBarIndex;

  UINT32                          AllOnes;

  UINT64                          Address;

  EFI_STATUS                      Status;

  UINT8                           Bus;

  UINT8                           Device;

  UINT8                           Function;

  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL*PciRootBridgeIo;

  Bus             = PciIoDevice->BusNumber;

  Device          = PciIoDevice->DeviceNumber;

  Function       = PciIoDevice->FunctionNumber;

  PciRootBridgeIo =PciIoDevice->PciRootBridgeIo;

  //PCI Agent的ROMBar在配置空间的0x30处,而PciBridge的RomBar在0x38处,我们先假设其为PCI Agent

  RomBarIndex = PCI_EXPANSION_ROM_BASE;

  if (IS_PCI_BRIDGE (&PciIoDevice->Pci)){  //若PCI设备为桥设备,则将Index改为0x38

    RomBarIndex= PCI_BRIDGE_ROMBAR;

  }

 //和PCIBar没什么区别,也要往寄存器里写全1

  AllOnes = 0xfffffffe;

  Address = EFI_PCI_ADDRESS (Bus, Device,Function, RomBarIndex);

  Status = PciRootBridgeIo->Pci.Write (

                                 PciRootBridgeIo,

                                 EfiPciWidthUint32,

                                  Address,

                                  1,

                                  &AllOnes

                                  );

  if (EFI_ERROR (Status)) {

    return EFI_NOT_FOUND;

  }

  Status = PciRootBridgeIo->Pci.Read(

                                 PciRootBridgeIo,

                                 EfiPciWidthUint32,

                                  Address,

                                  1,

                                  &AllOnes

                                  );

  if (EFI_ERROR (Status)) {

    return EFI_NOT_FOUND;

  }

//BIT0指示是否允许OpROM的读取,BIT1到BIT10指示其大小

  AllOnes &= 0xFFFFF800;

  if ((AllOnes == 0) || (AllOnes ==0xFFFFF800)) {

    return EFI_NOT_FOUND;

  }

 

  PciIoDevice->RomSize = (UINT64)((~AllOnes) + 1); //也相当于取补,和PCIBAR一样

  return EFI_SUCCESS;

}

 

当该RomSize确定后,会在LoadOpRomImage()中找寻OpROM,并将OpRom下载至相应内存处。该种方法在读之前,需要进行RomDecode,就是将Expantion ROM base address的BIT0置1,那么PCI Agent就会映射EEPROM的东西至该BASE Address处,我们就可以通过读内存的方式读取ROMSize个字节。

 

3.2 另一种找寻ROM的方法

    OpROM并不总是放在EEPROM中,现在BIOS的作法是将其直接配在BIOS中,这样可以节省一颗ROM芯片,并且省去了RomDecode的步骤。我使用的是INSYDE代码,不敢贴代码。现在就把实现流程说一下吧。

Step1,将OpROM编译成一个RAW型SECTION,并生成一个FILE,放入任一FV中。

Step2,将OpROM的VID,DID,以及FILE GUID放入一个固定的数组中。

Step3,安装一个事件,并使用RegisterProtocolNotify(),在gEfiBdsArchProtocolGuid安装时,偷梁换柱,重定向BDS入口函数至自己的一个函数XXX上。

Step4,BDS进入时,先执行XXX,重定向gEfiPciPlatformProtocolGuid的实例。

Step5,PCI BUS扫描时,在RegisterPciDevice()函数中,优先CHECK STEP2的OpROM,如果VID和DID相同,则将STEP1中的OPROM解析至内存中。

(唉,每次写点东西,查阅INSYDE代码的时候,老是觉得自己是偷窃。希望早日把国产平台的BIOS做出来。这才是我自己真正的东西。)


SYS/BIOS内存分配相关问题 问题描述: 需要更改SYS/BIOS的内存分配,不能单纯地更改cmd文件中的地址和数据长度,SYS/BIOS中的地址需要通过更改/新建RTSC Platform文件来进行更改/分配。 解决方案: 情况:进行Platform文件的更改 ①确定XDCtools version与需要修改的RTSC Platform文件保持一致,如果不一致则无法打开该已经生成好的文件,无法进行修改。同时,在下方的Products and Repositories应该添加包含该XDCtools版本的库... 阅读详情

相关推荐

Linux内核之PCI设备

PCI设备 外围设备互连(PCI)是一种将系统中外部设备以结构化与可控制方式连接到起来的总线标准,包括系统部件连接的电气特性及行为。本章将详细讨论Linux核心对系统中的PCI总线与设备的初始化过程。 图6.1 一个基于PCI的系统示意图 图6.1是一个基于PCI的系统示意图。PCI总线和PCI-PCI桥接器在连接系统中设备到上起关键作

tebeg521的专栏 1140

5 --> pcie初始化枚举和资源分配流程代码分析

本文主要是对PCIe的初始化枚举、资源分配流程进行分析。 PCIe architecture 1.1 pcie的拓扑结构 在分析PCIe初始化枚举流程之前,先描述下pcie的拓扑结构。 如下图所示: 整个PCIe是一个树形的拓扑: • Root Complex是树的根,它一般实现了一个主桥设备(host bridge), 一条内部PCIe总线(BUS 0),以及通过若干个PCI bridge扩展出一些root port。host bridge可以完成CPU地址到PCI域地址的转换,pci bridge用

weixin_38387929的博客 2033

TSB83AA23寄存器编程实战:从电源管理到DMA配置的1394b控制器深度解析

寄存器编程是嵌入式系统与底层硬件交互的核心技术,它通过直接读写特定内存地址来控制硬件行为,实现对设备功能的精确管理。其原理在于将硬件功能映射为可寻址的寄存器位域,软件通过置位或清零这些位来发送指令。这项技术的价值在于提供了对硬件最直接、最高效的控制能力,是驱动开发、性能优化和功耗管理的基础。在嵌入式系统、外设驱动开发以及需要精细硬件控制的领域,如音视频采集、工业控制等场景中,寄存器编程是工程师必须掌握的技能。本文以德州仪器TSB83AA23这款经典的IEEE 1394b控制器为例,深入探讨其**电源管理寄存

weixin_30175731的博客 146

PCIe BAR、Type0、Type1介绍

BAR(Base Address Register)空间是指PCI设备中的基地址寄存器(Base Address Register)所映射的地址空间。每个PCI设备都有多个BAR,用于指示设备在系统地址空间中的位置。BAR空间通常用于映射设备的内存区域或I/O端口,以便系统软件可以与设备进行通信。在PCI设备的配置空间中,BAR寄存器存储了设备在系统地址空间中的基地址信息。系统软件在引导过程中会读取这些BAR寄存器的值,以确定设备在系统中的地址范围,并将设备映射到适当的地址空间中。

weixin_38452632的博客 5764

QEMU跨架构模拟实战:从x86到ARM与RISC-V的虚拟机搭建

虚拟化技术是现代基础设施的核心,它让开发者可以在单一物理机上运行多种操作系统和硬件架构。QEMU作为一款强大的开源模拟器,通过动态二进制翻译与KVM硬件加速,支持x86、ARM、RISC-V等异构平台。它采用qcow2镜像格式,支持快照与按需分配,兼顾灵活性与性能。在实际应用中,QEMU常用于嵌入式开发、内核调试、云原生环境模拟以及国产操作系统(如麒麟、UOS)的兼容性测试。无需额外硬件,即可在普通x86电脑上搭建ARM或RISC-V虚拟环境,快速验证软件行为。从基础概念入手,系统讲解QEMU的安装、磁盘创

weixin_30824479的博客 498

UEFI——PCI/PCIe

PCI设备驱动不会使用PCI Root Bridge I/O协议访问PCI设备,而是会使用PCI总线驱动为PCI设备产生的PCI IO Protocol来访问PCI设备的IO/MEMORY空间和配置空间。为1表示使用PCI桥的配置空间;EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL为PCI根桥提供了抽象的IO功能,由PCI Host Bus Controller(PCI主总线驱动器)产生,一般由PCI/PCIe总线驱动枚举设备、获得Option ROM、分配PCI设备资源等。

weixin_45258382的博客 5168

PCIe配置空间与BAR空间详解:从枚举原理到掉卡排错实战

在计算机系统中,CPU如何识别板卡上的设备并为其分配资源,是一项底层而关键的技术。PCIe作为现代高速总线,沿袭并扩展了PCI的配置空间机制,通过标准化的数据结构实现设备发现、资源分配与错误管理。配置空间中的Vendor ID、Class Code等字段描述设备身份,而BAR空间则映射设备内部的地址窗口。系统枚举时,固件或操作系统读取BAR掩码计算所需地址大小,并协调桥与设备间的关系。当链路出现降速或掉卡时,AER错误寄存器、Link Status等配置字段提供关键线索。理解配置空间与BAR的交互,是进行P

weixin_33933118的博客 381

协方差矩阵

对两个类内协方差矩阵进行对角化,可以将它们变换为对角矩阵。这个过程可以通过对每个协方差矩阵进行特征值分解来实现,从而得到它们的特征向量和特征值,进而得到它们的对角矩阵形式。这个过程的意义在于,它可以帮助我们找到一个新的坐标系,使得在这个坐标系下,每个特征之间都是独立的,从而简化了计算。具体来说,当我们使用对角协方差矩阵作为特征向量的坐标系时,它意味着每个特征之间都是相互独立的,从而方便了进一步的分析和处理。在实际应用中,对角化协方差矩阵可以用于降维、特征选择和分类等任务。

m0_55196097的博客 1万+

PCIE接口协议深度解析:从枚举、掉卡排查到带宽优化实战

高速串行总线是CPU与外部设备互连的核心技术,通过点对点差分传输和分层协议架构实现高带宽、低延迟的数据通信。其核心原理在于事务层、数据链路层与物理层的协同工作,利用Lane扩展和Generation代际演进持续提升传输速率。在工程实践中,链路训练、配置空间枚举、BAR地址分配、AER错误报告与热插拔机制共同决定了系统的稳定性与兼容性。该技术广泛应用于NVMe固态存储、GPU加速卡、万兆网卡及FPGA采集卡等场景,而掉卡、降速、降Lane等故障的排查与带宽优化则是底层开发与运维人员必须掌握的关键技能。

weixin_34279579的博客 339

中兴SDH设备开局及业务配置

中兴SDH设备开局及业务配置 1.设备开局(S200-----S325) A.开电之后,按住截铃(bell off)开关,直至NCP告警灯变成橙色; B.此时,设备进入Download状态,设备IP为:192.192.192.11/24; 2.用交叉线(568A)将设备的QX口连接至电脑,电脑配置和设备相同网段的IP信息; 3.在电脑上测试连通性:pin...

weixin_33897722的博客 3998

SMETANA 安装使用教程

关于SMETANA的安装和简单使用信息

qq_44940977的博客 1170

毕业到踏足BIOS一年以来的旅程

2020年六月离开学校开始第一份工作,作为一个涉世未深的少年,遇到了第一个主动询问的上司&hr,不亏待每一份热情,在一番闲聊之后,没投过几次简历的自己就成为了一名赛事数据工程师,正式成为了程序员。之后才了解到,我的简历中有参加过电子设计大赛这一经历,即便是志愿者,却也带来了机遇,不是么 风乍起,合当奋意向人生 第一次租房,第一次上下班,一切都发生的那么自然,但似乎身边的一切并不是那么糟,没有996,没有强制加班,甚至在初入公司时候还能暂住在上司家中,策策和藏藏是他两只宠物狗的名字,那时候想着在校时光

这里是为我所统率的战场 2800

告别臃肿VS!仅用Visual Studio 2022 Build Tools为Qt 5.12.12配置MSVC2017开发环境

本文详细介绍了如何仅使用Visual Studio 2022 Build Tools为Qt 5.12.12配置MSVC2017开发环境,避免安装臃肿的完整VS。通过精准选择组件、配置Qt Creator编译器和优化Kit设置,实现高效、精简的Windows平台Qt开发环境搭建,特别适合追求性能和资源优化的开发者。

weixin_30340617的博客 351

PCIe设备漫游记----BIOS篇

初步了解完PCI总线标准之后,我们接下来正式开始PCIe设备的漫游之旅。从我们按下PC的电源按钮开始,BIOS就接管系统控制权开始工作,它会先进行一些内存和设备的初始化工作(当然,也包括我们的PCI设备),由于商业上的原因,Phoenix等厂商的BIOS代码需要授权协议,在此,我们以另外一个款开源BIOS(openbios)为例,来剖析BIOS中,我们的PCIe设备是如何被找到以及初始化的。

门没锁的专栏 1万+

使用光流进行 Warp 的流程

光流描述了图像帧中每个像素的运动。前向光流:描述了帧中每个像素在帧中的移动位置。后向光流:描述了帧中每个像素在帧​ 中的移动位置。水平方向的位移(x 方向),即每个像素水平移动了多少像素。垂直方向的位移(y 方向),即每个像素垂直移动了多少像素。使用光流进行 Warp 的流程Warp 是通过光流对图像进行变换的操作,旨在将前一帧的像素根据光流场映射到下一帧的对应位置。Step 1: 计算光流我们首先需要通过光流网络(如 RAFT)来估算两帧之间的光流。我们可以获得前向光流(从帧​ 到帧。

qq_44199605的博客 2108

人体检测技术之TOF

智能人脸/视频锁领域的人体检测需求是要求远距离达到1m左右即可,一旦在此距离内检测人,则锁唤醒进行人脸识别,视频录制等操作。所以,人体检测技术非常关键。选型主要是几个维度:1.支持检测的距离范围,能否准确输出距离信息2.支持检测FOV3.场景适应性如何,如人体衣服颜色4.环境适应性如何,夏天高温环境下的测距是否准确5.批量一致性情况。

AIoT深度探索者 | 嵌入式系统架构师 深耕物联网(IoT)与人工智能(AI)融合技术,聚焦​​边缘计算、图像开发、低功耗通信协议​​,致力于智能硬件,关注我获取最新技术文章信息与海量资源~ 2348

PCI、PCIe、PCI BIOS概念介绍

现在看到,有的网卡的名字叫Realtek PCIe GBE xxxx Controller 类似;想想以前折腾机箱的时候肯定听过PCI的名字;下面来看一下PCI和PCIe的概念;以及相关的BIOS操作,作为一名程序员可以了解; 一 PCI总线 PCI是Peripheral Component Interconnect(外设部件互连标准)的缩写,它是目前个人电脑中使用最为广泛的接口,几乎所有的主板产品上都带有这种插槽。PCI插槽也是主板带有最多数量的插槽类型,在目前流行的台式机主板上,ATX结构的主板一.

bcbobo21cn的专栏 4774

《Python等级认证CCF-GESP真题解析》专栏总目录

❤️ 专栏名称:《🌸 专栏介绍:中国计算机学会GESP《CCF编程能力等级谁》Python编程(1~8级)历届真题解析。🚀 订阅专栏:订阅后可阅读专栏内所有真题解析,真题持续更新中,限时9.9元,欢迎订阅!

人生就是一个不断学习的过程 1880

PCI总线

PCI 总线介绍 外围部件互连总线PCI (Peripheral Component Interconnect) 总线,是一种先进的高性能32/64 位地址数据复 用局部总线,可同时支持多组外围设备,为中央处理器与高速外围设备提供了一座沟通的桥梁,是现在PC 领域中流行的总线。本文重点介绍UEFI 规范如何支持PCI 总线,以及UEFI 固件中PCI 总线驱动的实现 。 BIO...

Helping BIOSer become Awesome! 3310

Ultralytics YOLOv8 英伟达™ Jetson®处理器部署

英伟达™(NVIDIA®)Jetson 是一系列嵌入式计算板卡,旨在为边缘设备带来加速的 AI(人工智能)计算。这些小巧而功能强大的设备围绕英伟达™(NVIDIA®)的GPU架构打造,能够直接在设备上运行复杂的人工智能算法和深度学习模型,而无需依赖云计算资源。Jetson 板卡通常用于机器人、自动驾驶汽车、工业自动化和其他需要在本地以低延迟和高效率执行人工智能推理的应用中。此外,这些板卡基于 ARM64 架构,与传统 GPU 计算设备相比运行功耗更低。英伟达™(NVIDIA®)JetPack SDK。

机器人控制与仿真应用 3876

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

PCIe初始化枚举和资源分配流程分析

本文主要是对PCIe的初始化枚举、资源分配流程进行分析,代码对应的是alikernel-4.19,平台是arm64 1. PCIe architecture 1.1 pcie的拓扑结构 在分析PCIe初始化枚举流程之前,先描述下pcie的拓扑结构。如下图所示: 整个PCIe是一个树形的拓扑:• Root Complex是树的根,它一般实现了一个主桥设备(host bridge), 一条内部PCIe总线(BUS 0),以及通过若干个PCI bridge扩展出一些root port。host bridge可以.

kunkliu的博客 1万+

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

BIOS设置与系统分区:从基础到实战指南

掌握BIOS设置与系统分区的核心知识,能够帮助用户更好地管理硬件资源、优化系统性能,并在系统安装与维护中游刃有余。无论是新手还是资深开发者,理解这些底层原理都将为技术实践提供坚实基础。如果您在操作中遇到问题,欢迎在评论区留言讨论!

2301_80555615的博客 2576

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

解锁Insyde的BIOS隐藏设置

我使用的笔记本是神舟K580PI3D1, 其他的没有试过。 步骤: 1.使用BIOS_Backup_TooKit_V2.0 软件提取BIOS image文件 2.使用 UEFITool 软件解析BIOS image, 并提取出相应的 .sct 文件 3.使用Universal IFR Extractor 软件将 .sct文件解析为可读的 .txt文件 4.从 .txt文件里找出你想改...

qq_34352738的博客 3万+

PCI BAR寄存器详解(二 实例讲解)

前言 下面以一个实际项目,讲解 PCI 驱动程序和 BAR 空间的相关操作函数。 一、驱动程序加载与卸载 static const struct pci_device_id pci_ids[] = { { PCI_DEVICE(0x1DED, 0x1020), }, {0,} }; MODULE_DEVICE_TABLE(pci, pci_ids); static struct pci_driver pci_driver = { .name = DRV_NAME, .id_table = p

weixin_42109053的博客 4796

TPL问题的一种解决方式

UEFI中TPL问题

qq_39578202的博客 706

PCI BAR寄存器详解(一)

一、PCI 设备的配置空间 其中Device ID和Vendor ID是区分不同设备的关键,OS 在很多时候就是通过匹配他们来找到不同的设备驱动(Class Code有时也起一定作用)。 我们重点来了解一下这些Base Address Registers(BAR)。BAR是PCI配置空间中从0x10 到 0x24的6个register,用来定义PCI需要的配置空间大小以及配置PCI设备占用的地址空间。 该组寄存器简称为 BAR 寄存器, BAR 寄存器保存 PCI 设备使用的地址空间的基地址,该基地址保存

weixin_42109053的博客 6129
上一篇: 吕小敏Legend
下一篇: EC修炼之道—代码架构
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值