一、PCIPCIe的概念

PCI和PCIe都是计算机中的总线技术。PCI(Peripheral Component Interconnect)总线是一种计算机内部总线,用于在主机和外部设备之间传输数据。它首次出现在1993年,被称为“老式PCI”,后来在2004年被新一代的PCIe(Peripheral Component Interconnect Express)所替代。PCIe是一种高速串行总线,不仅速度更快,而且具有更大的带宽。PCIE首次出现在2004年,随着新一代CPU厂商的加入,越来越多的芯片组和外围设备开始采用PCIe。

二、PCI和PCIe的架构和工作原理

PCI总线通过一组平行电线和总线上的逻辑电平来传输数据。总线架构包括多个设备(如网卡、显卡、声卡等)和总线控制器(PCI主机桥和PCI桥)。PCI设备通过基址寄存器(BAR)向主机发送数据请求,并通过数据寄存器(DSR)接收主机返回的数据。

PCIE总线则使用基于分组的高速串行总线,它将数据分成小的数据包,然后通过多种通信通道进行传输,带宽高得多。一个PCIe总线可以同时支持轮询方式和中断方式的多种工作模式,并且还支持多个设备之间的直接通信。

三、PCI和PCIe的主要特点

1、传输速度

PCI的传输速度较慢,最大传输速度理论值为133MB/s,净速率为100MB/s。而PCIe采用基于分组的高速串行通信技术,数据传输速度更快。PCIe 1.0时代的传输速率最高为2.5Gb/s,而PCIe 3.0时代的传输速率最高可以达到8Gb/s。

2、带宽

PCI的带宽有限,它的带宽瓶颈在于总线的频率。PCIe的基本带宽从1倍到16倍都是一个标准,每个链接都有它所能支持的带宽,每个端口和总线可以在这些不同的基本带宽选择中进行交互,并达到最佳的合理性能。

3、电源管理

PCIe拥有强大的电源管理功能。PCIe支持热插拔、电源管理等高级特性,这意味着设备在需要时可随时插入和拔出。PCIE可以控制设备的供电并管理其睡眠模式,以最大程度地节省电力,并在需要时将其唤醒。

四、PCI和PCIe在代码中的应用实例

1、使用PCIe读取和写入文件

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(void)
{
    int fd;
    char *filename = "/dev/pcie_driver";
    char bufwrite[] = "Hello, PCIe!";
    char bufread[20];
    
    //打开设备文件
    fd = open(filename, O_RDWR);
    if(fd < 0){
        printf("can't open file %s\n", filename);
        exit(0);
    }
    
    //写入数据
    write(fd, bufwrite, sizeof(bufwrite));
    
    //读取数据
    read(fd, bufread, sizeof(bufread));
    printf("%s\n", bufread);
    
    //关闭设备文件
    close(fd);
    
    return 0;
}

2、使用PCIe控制LED灯

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <sys/mman.h>
#include <fcntl.h>

//定义地址映射表
#define LED_BASE     0x40000000
#define LED_SPAN     0x00010000

#define LED_0        0x00
#define LED_1        0x01
#define LED_2        0x02
#define LED_3        0x03

int main(void)
{
    int fd;
    int *mapped_base;
    volatile int *led_reg;
    
    //打开设备文件
    fd = open("/dev/mem", O_RDWR|O_SYNC);
    if (fd == -1) {
        printf("open '/dev/mem' error\n");
        exit(EXIT_FAILURE);
    }
    
    //映射地址
    mapped_base = mmap(0, LED_SPAN, PROT_READ|PROT_WRITE, MAP_SHARED, fd, LED_BASE);
    if (mapped_base == NULL) {
        printf("mmap error\n");
        close(fd);
        exit(EXIT_FAILURE);
    }
    
    //获取LED寄存器指针
    led_reg = (int *)(mapped_base + LED_0);
    
    //设置LED灯状态
    *led_reg = 0x01;
    
    //关闭映射
    munmap((void *)mapped_base, LED_SPAN);
    
    //关闭设备文件
    close(fd);
    
    return 0;
}

五、总结

PCI和PCIe是计算机中非常重要的总线技术,两者在传输速度、带宽和电源管理等方面存在许多差异。在代码中,可以通过文件读写、映射地址等方式实现PCIe设备的控制和读写。