> 技术文档 > xdma的linux驱动编译给arm使用(中断检测-测试程序)_xdma linux

xdma的linux驱动编译给arm使用(中断检测-测试程序)_xdma linux


1、驱动链接

XDMA驱动源码官网下载地址为:https://github.com/Xilinx/dma_ip_drivers
下载最新版本的XDMA驱动源码,即master版本,否则其驱动用不了(xdma ip核版本为4.1)。
xdma的linux驱动编译给arm使用(中断检测-测试程序)_xdma linux

2、驱动

此部分来源于博客:xdma驱动编译(给arm使用)

2.1、修改驱动的Makefile

修改dma_ip_drivers-master/XDMA/linux-kernel/xdma/Makefile

# ifneq ($(KERNELRELEASE),)# $(TARGET_MODULE)-objs := libxdma.o xdma_cdev.o cdev_ctrl.o cdev_events.o cdev_sgdma.o cdev_xvc.o cdev_bypass.o xdma_mod.o xdma_thread.o# obj-m := $(TARGET_MODULE).o# else# BUILDSYSTEM_DIR:=/lib/modules/$(shell uname -r)/build# PWD:=$(shell pwd) 找到上面的并注释掉(最后一行还有一个 endif 也注释掉),紧挨着就添加下面的: $(TARGET_MODULE)-objs := libxdma.o xdma_cdev.o cdev_ctrl.o cdev_events.o cdev_sgdma.o cdev_xvc.o cdev_bypass.o xdma_mod.o xdma_thread.oobj-m := $(TARGET_MODULE).oBUILDSYSTEM_DIR:=/home/debian/Desktop/xiaguangbo/project/rk3588/project/kernel # linux 源码目录PWD:=$(shell pwd)

2.2、编译

export ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-make

3、测试工具

3.1、修改测试工具Makefile

修改 dma_ip_drivers-master/XDMA/linux-kernel/tools/Makefile

# CC ?= gccCC = aarch64-linux-gnu-gcc

3.2、编译

make

编译之后用file xxx查看文件是否是属于aarch64架构的,如果不是查看Makefile对不对

4、xdma中断检测上位机

4.1、代码

#include #include #include #include #include #include #include #include #include #include  #include #include #include #include #include #include #include #include #include #include #include /* ltoh: little to host *//* htol: big to host */#if __BYTE_ORDER == __LITTLE_ENDIAN# define ltohl(x) (x)# define ltohs(x) (x)# define htoll(x) (x)# define htols(x) (x)#elif __BYTE_ORDER == __BIG_ENDIAN# define ltohl(x) __bswap_32(x)# define ltohs(x) __bswap_16(x)# define htoll(x) __bswap_32(x)# define htols(x) __bswap_16(x)#endif#define MAP_SIZE (1024*1024UL)#define MAP_MASK (MAP_SIZE - 1)static void * user_base;static int start_en;unsigned int user_irq_ack;static void *mmap_control(int fd,long mapsize){void *vir_addr;vir_addr = mmap(0, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);return vir_addr;}static void user_write(unsigned int address,unsigned int val){ unsigned int writeval = htoll(val); *((unsigned int *)(user_base+address)) = writeval;}static unsigned int user_read(unsigned int address){ unsigned int read_result = *((unsigned int *)(user_base+address)); read_result = ltohl(read_result); return read_result;}void *event0_process(){int val;int h_event0; h_event0 = open(\"/dev/xdma0_events_0\", O_RDWR | O_SYNC); if(h_event0 < 0) { printf(\"open event0 error\\n\");}else{printf(\"open event0\\n\");while (1){if (start_en) {read(h_event0,&val,4);if (val == 1)printf(\"event_0 done!\\n\");elseprintf(\"event_0 timeout!\\n\");}usleep(1);}close(h_event0);}}void *event1_process(){int val;int h_event1; h_event1 = open(\"/dev/xdma0_events_1\", O_RDWR | O_SYNC); if(h_event1 < 0) { printf(\"open event1 error\\n\");}else{printf(\"open event1\\n\");while (1){if (start_en) {read(h_event1,&val,4);if (val == 1)printf(\"event_1 done!\\n\");elseprintf(\"event_1 timeout!\\n\");}usleep(1);}close(h_event1);}}void *event2_process(){int val;int h_event2; h_event2 = open(\"/dev/xdma0_events_2\", O_RDWR | O_SYNC); if(h_event2 < 0) { printf(\"open event2 error\\n\");}else{printf(\"open event2\\n\");while (1){if (start_en) {read(h_event2,&val,4);if (val == 1)printf(\"event_2 done!\\n\");elseprintf(\"event_2 timeout!\\n\");}usleep(1);}close(h_event2);}}void *event3_process(){int val;int h_event3; h_event3 = open(\"/dev/xdma0_events_3\", O_RDWR | O_SYNC); if(h_event3 < 0) { printf(\"open event3 error\\n\");}else{printf(\"open event3\\n\");while (1){if (start_en) {read(h_event3,&val,4);if (val == 1)printf(\"event_3 done!\\n\");elseprintf(\"event_3 timeout!\\n\");}usleep(1);}close(h_event3);}}int main(int argc, char* argv[]){ static int h_c2h0; static int h_h2c0; static int h_user; pthread_t t_event0; pthread_t t_event1; pthread_t t_event2; pthread_t t_event3; char* user_name = \"/dev/xdma0_user\"; char* c2h0_name = \"/dev/xdma0_c2h_0\"; char* h2c0_name = \"/dev/xdma0_h2c_0\";start_en = 0; h_c2h0 = open(c2h0_name,O_RDWR | O_NONBLOCK); if(h_c2h0 < 0) { printf(\"open c2h0 error\\n\"); }; h_h2c0 = open(h2c0_name,O_RDWR); if(h_h2c0 < 0) { printf(\"open h2c0 error\\n\"); }; h_user = open(user_name, O_RDWR | O_SYNC); if(h_user < 0) { printf(\"open user error\\n\"); }; user_base = mmap_control(h_user,MAP_SIZE);user_write(0x00000, 0xf); pthread_create(&t_event0, NULL, event0_process, NULL);pthread_create(&t_event1, NULL, event1_process, NULL);pthread_create(&t_event2, NULL, event2_process, NULL);pthread_create(&t_event3, NULL, event3_process, NULL);usleep(100);user_irq_ack = 0xffff0000;user_write(0x00004, user_irq_ack);//start irqstart_en = 1;printf(\"start\\n\");pthread_join(t_event0,NULL);pthread_join(t_event1,NULL);pthread_join(t_event2,NULL);pthread_join(t_event3,NULL);user_irq_ack = 0x00000000;user_write(0x00004, user_irq_ack);//stop irqclose(h_c2h0);close(h_h2c0);close(h_user);close(t_event0);close(t_event1);close(t_event2);close(t_event3);}

4.2编译中断测试程序

aarch64-linux-gnu-gcc pcie_irq.c -o pcie_irq -static -lpthread