// pcie_send_recv.c pcie收发数据.//使用用户空间io. uIO
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#define BAR_SIZE (1024 * 1024) // 1MB,根据设备调整,每次存1mb数据.
int main() {
int fd = open("/dev/uio0", O_RDWR); // 假设设备是 uio0
if (fd < 0) {
perror("open /dev/uio0");
exit(EXIT_FAILURE);
}
//设备映射到一个内存地址. fd是这个设备. 返回的bar是指向映射区域的指针,后续通过它访问硬件寄存器
void *bar = mmap(NULL, BAR_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (bar == MAP_FAILED ) {
perror("mmap");
close(fd);
exit(EXIT_FAILURE);
}
//用于声明变量可能被程序外部因素意外修改,强制编译器每次直接从内存地址读取最新值,而非使用寄存器中的缓存值。其核心机制是防止编译器优化误判,确保对硬件映射寄存器、多线程共享变量等易变数据的访问准确性。在嵌入式开发中,volatile还被用于处理中断服务程序或外部硬件触发的变量修改,确保程序响应实时状态变化。
volatile uint32_t *reg = (volatile uint32_t *)bar;
// 模拟:向设备寄存器写入数据("发送")
printf("Sending data to PCIe device...\n");
reg[0] = 0x12345678; // 写入控制寄存器或数据缓冲区
reg[1] = 0xABCDEF00; // 写入更多数据
// 模拟:从设备寄存器读取数据("接收")
printf("Receiving data from PCIe device...\n");
uint32_t recv0 = reg[2];
uint32_t recv1 = reg[3];
printf("Received: 0x%08x, 0x%08x\n", recv0, recv1);
munmap(bar, BAR_SIZE);
close(fd);
return 0;
}