Windows操作系统: PCIE Axidma篇 1 BAR扫盲

2024-01-15 23:40

本文主要是介绍Windows操作系统: PCIE Axidma篇 1 BAR扫盲,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

BAR:

  也就是基地址寄存器(Base address register):
  设备在系统的PCI地址空间里申请一段来用,所申请的空间基址和大小保存在BAR寄存器里。BAR里的只是PCI域的地址空间,需要映射到IO地址空间里或者内存地址空间里之后软件才能使用。映射到IO空间的话,用IO读写指令和函数去访问设备;映射到内存空间的话,首先得到的是物理地址,映射到虚拟地址后就可以像用指针那样访问。IO BAR和MEM BAR分别是映射到IO空间和内存空间的BAR;BAR寄存器的0位指示要映射到哪,有的设备这位可以由用户设置,有的只读。
  Xilinx的官方论坛上有人是这样解释的感觉很恰当:
  BAR 仅用于地址解码。它没有实现内存,只有访问内存的地址窗口。对于每个 BAR,系统将读取所需内存窗口的大小并分配一个物理地址范围以访问该窗口。在用户端的 FPGA 内,您通常会收到指示哪个 BAR 处于活动状态的信号(哪个地址窗口用于此事务)。然后,您需要解码此信息以决定如何处理传输。
在这里插入图片描述
  系统的讲解参考自:
  http://blog.chinaaet.com/justlxy/p/5100053320
  基地址寄存器(BAR)在配置空间(Configuration Space)中的位置如下图所示:
在这里插入图片描述
  其中Type0 Header最多有6个BAR,而Type1 Header最多有两个BAR。这就意味着,对于Endpoint来说,最多可以拥有6个不同的地址空间。但是实际应用中基本上不会用到6个,通常1~3个BAR比较常见。
  主要注意的是,如果某个设备的BAR没有被全部使用,则对应的BAR应被硬件全被设置为0,并且告知软件这些BAR是不可以操作的。对于被使用的BAR来说,其部分低比特位是不可以被软件操作的,只有其高比特位才可以被软件操作。而这些不可操作的低比特决定了当前BAR支持的操作类型和可申请的地址空间的大小。
  一旦BAR的值确定了(Have been programmed),其指定范围内的当前设备中的内部寄存器(或内部存储空间)就可以被访问了。当该设备确认某一个请求(Request)中的地址在自己的BAR的范围内,便会接受这请求。
  下面用几个简单的例子来熟悉BAR的机制:
  例1. 32-bit Memory Address Space Request
  如下图所示,请求一个4KB的NP-MMIO一般需要以下三个步骤:
在这里插入图片描述
  Step1:如图中(1)所示,未初始化的BAR的低比特(114)都是0,高比特(3112)都是不确定的值。所谓初始化,就是系统(软件)向整个BAR都写1,来确定BAR的可操作的最低位是哪一位。当前可操作的最低位为12,因此当前BAR可申请的(最小)地址空间大小为4KB(212)。如果可操作的最低位为20,则该BAR可申请的(最小)地址空间大小为1MB(220)。
  Step2:完成初始化(写1操作)之后,软件便开始读取BAR的值,来确定每一个BAR对应的地址空间大小和类型。其中操作的类型一般由最低四位所决定,具体如上图右侧部分所示。
  Step3:最后一步是,软件向BAR的高比特写入地址空间的起始地址(Start Address)。如图中所示,为0xF9000000。
  例2. 64-bit Memory Address Space Request
  下面是一个申请64MB P-MMIO地址空间的例子,由于采用的是64-bit的地址,因此需要两个BAR。具体如下图所示:
在这里插入图片描述
  例3. IO Address Space Request
  下面是一个申请IO地址空间的例子,如下图所示:
在这里插入图片描述
  注:需要特别注意的是,软件对BAR的检测与操作(Evaluating)必须是顺序执行的,即先BAR0,然后BAR1,……,直到BAR5。当软件检测到那些被硬件设置为全0的BAR,则认为这个BAR没有被使用。
  注:无论是PCI还是PCIe,都没有明确规定,第一个使用的BAR必须是BAR0。事实上,只要设计者原意,完全可以将BAR4作为第一个BAR,并将BAR0~BAR3都设置为不使用。

  代码里对bar的读写示例如下:

#include <iostream>
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <strsafe.h>
#include <Windows.h>
#include <SetupAPI.h>
#include <INITGUID.H>
#include <WinIoCtl.h>
#include <cstring>#include <string>
#include <thread>
#include <vector>
#include <Windows.h>
#include <SetupAPI.h>
#include <signal.h>
#include <INITGUID.H>
#include<process.h>HANDLE get_ctr_bar_handle(const char *path)
{HANDLE tmp_handle = NULL,result = NULL;tmp_handle = CreateFile(path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);if (tmp_handle == INVALID_HANDLE_VALUE){LOG(LOG_TAG"opening device %s failed,errno = %ld\r\n",path,GetLastError());return NULL;}return tmp_handle;
}int write_bar(HANDLE dev_handel, off_t target, DWORD value)
{DWORD t_value = value;DWORD write_size = sizeof(DWORD);LARGE_INTEGER offset;offset.QuadPart = target;if (INVALID_SET_FILE_POINTER == SetFilePointerEx(dev_handel, offset, NULL, FILE_BEGIN)){LOGE(LOG_TAG"SetFilePointerEx failed,line %d,errno =  %ld\r\n", __LINE__, GetLastError());return -(int)GetLastError();}if (!WriteFile(dev_handel, &t_value, write_size, &write_size, NULL)){LOGE(LOG_TAG"WriteFile failed,line %d,errno =  %ld\n",__LINE__, GetLastError());return -(int)GetLastError();}//LOGD("write bar:---- address:0x%x,value 0x%x\r\n",target,value);return 0;
}DWORD read_bar(HANDLE dev_handel, off_t target, DWORD *value_ptr)
{DWORD read_size = sizeof(DWORD);LARGE_INTEGER offset;offset.QuadPart = target;if (INVALID_SET_FILE_POINTER == SetFilePointerEx(dev_handel, offset, NULL, FILE_BEGIN)){LOGE(LOG_TAG"SetFilePointerEx failed,line %d,errno = %ld\r\n", __LINE__, GetLastError());return -(int)GetLastError();}if (!ReadFile(dev_handel, value_ptr, read_size, &read_size, NULL)){LOGE(LOG_TAG"ReadFile failed,line %d,errno = %ld\n", __LINE__, GetLastError());return -(int)GetLastError();}//LOGD("read bar:---- address:0x%x,value 0x%x\r\n", target, *value_ptr);return 0;
}

这篇关于Windows操作系统: PCIE Axidma篇 1 BAR扫盲的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/610587

相关文章

Windows设置nginx启动端口的方法

《Windows设置nginx启动端口的方法》在服务器配置与开发过程中,nginx作为一款高效的HTTP和反向代理服务器,被广泛应用,而在Windows系统中,合理设置nginx的启动端口,是确保其正... 目录一、为什么要设置 nginx 启动端口二、设置步骤三、常见问题及解决一、为什么要设置 nginx

在 Windows 上安装 DeepSeek 的完整指南(最新推荐)

《在Windows上安装DeepSeek的完整指南(最新推荐)》在Windows上安装DeepSeek的完整指南,包括下载和安装Ollama、下载DeepSeekRXNUMX模型、运行Deep... 目录在www.chinasem.cn Windows 上安装 DeepSeek 的完整指南步骤 1:下载并安装

高效管理你的Linux系统: Debian操作系统常用命令指南

《高效管理你的Linux系统:Debian操作系统常用命令指南》在Debian操作系统中,了解和掌握常用命令对于提高工作效率和系统管理至关重要,本文将详细介绍Debian的常用命令,帮助读者更好地使... Debian是一个流行的linux发行版,它以其稳定性、强大的软件包管理和丰富的社区资源而闻名。在使用

龙蜥操作系统Anolis OS-23.x安装配置图解教程(保姆级)

《龙蜥操作系统AnolisOS-23.x安装配置图解教程(保姆级)》:本文主要介绍了安装和配置AnolisOS23.2系统,包括分区、软件选择、设置root密码、网络配置、主机名设置和禁用SELinux的步骤,详细内容请阅读本文,希望能对你有所帮助... ‌AnolisOS‌是由阿里云推出的开源操作系统,旨

windows系统下shutdown重启关机命令超详细教程

《windows系统下shutdown重启关机命令超详细教程》shutdown命令是一个强大的工具,允许你通过命令行快速完成关机、重启或注销操作,本文将为你详细解析shutdown命令的使用方法,并提... 目录一、shutdown 命令简介二、shutdown 命令的基本用法三、远程关机与重启四、实际应用

五大特性引领创新! 深度操作系统 deepin 25 Preview预览版发布

《五大特性引领创新!深度操作系统deepin25Preview预览版发布》今日,深度操作系统正式推出deepin25Preview版本,该版本集成了五大核心特性:磐石系统、全新DDE、Tr... 深度操作系统今日发布了 deepin 25 Preview,新版本囊括五大特性:磐石系统、全新 DDE、Tree

Windows自动化Python pyautogui RPA操作实现

《Windows自动化PythonpyautoguiRPA操作实现》本文详细介绍了使用Python的pyautogui库进行Windows自动化操作的实现方法,文中通过示例代码介绍的非常详细,对大... 目录依赖包睡眠:鼠标事件:杀死进程:获取所有窗口的名称:显示窗口:根据图片找元素:输入文字:打开应用:依

javafx 如何将项目打包为 Windows 的可执行文件exe

《javafx如何将项目打包为Windows的可执行文件exe》文章介绍了三种将JavaFX项目打包为.exe文件的方法:方法1使用jpackage(适用于JDK14及以上版本),方法2使用La... 目录方法 1:使用 jpackage(适用于 JDK 14 及更高版本)方法 2:使用 Launch4j(

windows端python版本管理工具pyenv-win安装使用

《windows端python版本管理工具pyenv-win安装使用》:本文主要介绍如何通过git方式下载和配置pyenv-win,包括下载、克隆仓库、配置环境变量等步骤,同时还详细介绍了如何使用... 目录pyenv-win 下载配置环境变量使用 pyenv-win 管理 python 版本一、安装 和

Python使用pysmb库访问Windows共享文件夹的详细教程

《Python使用pysmb库访问Windows共享文件夹的详细教程》本教程旨在帮助您使用pysmb库,通过SMB(ServerMessageBlock)协议,轻松连接到Windows共享文件夹,并列... 目录前置条件步骤一:导入必要的模块步骤二:配置连接参数步骤三:实例化SMB连接对象并尝试连接步骤四: