admin 管理员组

文章数量: 887021


2023年12月25日发(作者:ensure failed 一直弹出来)

计算机系统应用 http://www.c~S a.org.crl 2011年第20卷第5期 u32 id; //平台设备的设备ID #ifdefined(XPAR_GPIQ XPAR_ASEADDR) struct device dev; //设备结构体 GPIO(0), u32 num resources;//平台设备使用的各类资源数 量 #endif #if defined(XPAR_GPIO 1_BASEADDR) struct resource resource;//资源 }; XPAR_GPIO(1), #endif 该结构一个重要的元素是resource,它存入了最为 重要的设备资源信息。在嵌入式开发工具EDK中生成 #if defined(XPAR_GPIO 2 BASEADDR) XPAR_GPIO(2), BSP(板级支持包)的时候有一个设备参数头文件 xparameter.h,里面定义了相关设备的设备数量、地址 资源、中断资源和时钟资源等。在添加平台设备信息 的时候需要用到该头文件中定义的地址信息和中断信 息,Xilinx公司的Vinex.4平台设备是在kernel/arch/ ppc/syslib/virtex_devices.C中定义的,在编写驱动之前, 需要在该文件中添加有关GPIO控制器的设备定义: ,. ML300/MIA03 Gpio Device:shortcut macro for single instance ●/ #define XPAR GPIO(num){\ .name=”xilinxgpio”,\ __.id=mum,\ .dev.platformdata=XPARGPIO##num## ___ISDUAL,\ 一—.numresources 2,\ —.resource (struct resource[]){\ {\ .start=XPARGPIO##num##一B —一ASEADDP.,| .end=XPARGPIO##num##HI —一一GHADD \ .lfags IORESOURCEMEM,\ _),\ {\ .start=XPARINTC0GPIO##n 一一一—um# ECID,1 _.lfags IORESOURCE_IRQ,\ },\ ),\ ) GPIO instances}/ 118实用案例ApplicationCase #endif 上述的代码定义了GPIO设备名称一一x“in】【 gpio,XPAR GPIO平台设备结构中name元素和设备 驱动的platform driver结构体中的drive,name必须是 相同的。这是因为在平台设备驱动注册时会对所有已 注册的platform device 中的 name .和当前注册的platform driver的driver.name进行比较,使得 platfrom device和platform driver建立关联,只有找到 相同的名称的platfomr device .才能注册成功。在平台设备的描述中GPIO设备定义了2个资源,一个是I,() 空间资源,描述了GPIO控制器设备所占用的总线地 址范围,IORESOⅥ E MEM表示第1组描述的是内 存类型的资源信息:另一个是中断资源,描述了设备 的中断号,IORESOURCE .mQ 表示第2组描述的是中断资源信息,设备驱动会根据类型来获取相应的资 源信息。本文共用到三个GPIO设备XPAR .GPIO(0) ,XPAR GPI1.注册 O(1),XPAR .GPIO(2)。 2 platform device virtex devices.c中的platform device是在系统启 动时,使用virtex _init(void) 函数进行注册。同时被注册还有很多virtex平台的设备,该函数 是在系统初始化阶段调用,驱动注册时需要匹配内核 中所有已注册的设备名,因此platform device设备的 注册过程必须在相应设备驱动加载之前被调用。 1.3定义platformdriver _与平台设备对应的平台设备驱动程序由struct platform rdiver .描述:struct platform_driver{ int( probe)(struct platform_device ); //探测 int( remove)(struct platform_device );//移除 void( shutdown)(struct platform_device );//关闭 int( suspend)(struct platform_device ,pm_ message t state);||拄起 

2011年第2O卷第5期 http://www.c-S—a.org.crl 计算机系统应用 int( resume)(struct platform_device );//恢复 struct devicedriver driver; _}; GPIO的驱动程序中结构体struct platformdriver _主要实现了xgpiodriver的探测和移除函数。代码如 _下: static struct platformdriver xgpio__driver { .probe xgpioprobe, _.remove xgpioremove, _.driver ={ .name =xilinxgpio, _.bus &platformbus_type, _.owner THISMODULE, _) 1.4注册platformdriver _最后需要调用platform_driverregister0i ̄数注册 平台设备驱动,在注册成功后会调用platformrdiver _结构元素probe函数指针,进入probe函数后,需要获 取设备的资源信息。注册平台设备驱动的实现函数如 下: static intinit xgpio,..——_init(void) { return platform_driverregister(&xgpio_ rdiver); } 2 GPIO控制器设备驱动 Linux是保护模式的操作系统,内核和应用程序分 别运行在完全分离的虚拟地址空间,用户空间的进程 一般不能直接访问硬件。设备驱动充当了硬件和应用 软件之间的纽带,它与底层硬件直接打交道,按照硬 件设备的具体工作方式读写设备寄存器,完成设备的 轮询、中断处理、DMA通信,进行物理内存向虚拟内 存的映射,最终使通信设备能收发数据,使显示设备 能否显示文字和画面,使存储设备能够记录文件和数 据n1。 2.1 GPIO控制器的平台设备驱动函数实现 使用platform_driverregister(&xgpio_driver)注册 GPIO设备驱动成功后,利用系统探测函数probe(), 获取设备需要的资源信息。在探测函数中,需要通过 platform _get.resource() 函数分别获得 GPIO 内存和1RQ 资源: struct resource platform—get_resource(struct platformdevice dev,unsigned int tYpe,unsigned int _num); 根据参数 type 所指定的类型, IORESOURCE MEM和IORESOURCE IRQ来获取 指定的资源。 驱动程序中相应代码为: regs_res platform get_resource(pdev, IORESOURCE_MEM,0); ’ irqres platform__get_resource(pdev, IORESOURCE_IRQ,0); 在获取资源成功后,驱动程序会申请内核空间和 I/O空间,将物理地址映射到虚拟地址以及申请中断 等。在Linux内核空间申请内存的主要函数是 kmalloc0、kzalloc0。由这两个函数申请的内存位于物 理内存映射区域,在物理上也是连续的。它们与真实 的物理地址只有一个固定的偏移,存在较简单的转换 关系。 驱动程序中与内存申请有关的程序代码: xgpio_inst=kmalloc(sizeof(struct xgpio_instance), GFP_KERNEL); miscdev = kmalloc(sizeof(struct miscdevice), GFP_KERNEL); 第一个参数是分配的空间大小,第二个标志表示 是在内核空间的进程中申请内存。GFP KERNEL标志 申请内存时,若暂时不能满足,则进程会睡眠引起阻 塞。使用kmalloc0、kzalloc0 ̄0请的内存要用kfi'ee() 释放。 2.1.1申请I/O内存空间和映射物理内存: GPIO设备控制器有一组寄存器用于读写设备和 获取设备状态,即控制寄存器、状态寄存器和数据寄 存器。这些寄存器位于I/O内存空间D1。首先需要调用 requestmern__region000请资源,接着将寄存器地址通 过ioremapO将物理地址映射到内核空间虚拟地址,之 后才可以调用编程接口访问这些设备的寄存器。访问 完成后用iounmap0对申请的内核虚拟地址进行释放, 并释放申请的I/O内存资源。GPIO控制器驱动程序的 相关代码如下: 申请I/O内存资源 / request_memregion(regs_res->start, remap_size, Application Case实用案例1 1 9 

计算机系统应用 http://www.c.S.a.org.cn 20 1 1年第2O卷第5期 DRIVER_NAME); static int xgpioopen(struct inode inode,struct ifle _ioremap(regs res->start,remap—size); / 映射物理地知道虚拟地址 / 2.1.2申请中断: "XGPIO requestirq(irq_res->start,xgpiointerrupt,0,__file) { Xlo_Out32((int)xgpioinst・>vaddr + XGPIO_GIER OFFSET,0x80000000); 全局中断 ”,xgpio—inst) 使能 / XIo_irq res.>start是要申请的硬件中断号; xgpio interrupt是向系统登记的中断处理函数,是一个 Out32((int1 xgpioinst一>vaddr + XGPIO IER OFFSET,0x00000003); 使能GPIO 回调函数,中断发生时,系统调用这个函数,dev id 参数f即xgpio_inst)将被传递。 2.1-3释放虚拟地址和内存资源 static int xgpioremove(struct platform_device pdev){iounmap(xgpio_inst->base_address); releasemem__region(xgpio_inst->phys_addr, xgpio_inst->remap size); kfree(xgpio_inst); return 0;/*success /} 2.2 GPIo控制器的字符型设备接口实现 在Linux的文件操作系统调用中,字符型设备一 般涉及到打开,读写和关闭文件等操作。在控制器驱 动程序中要给内核提供file operations结构,才能为设 备驱动提供用户调用的接口,定义如下: static struct ifleoperations xgpio__fops { .owner THISMODULE, _.read xgpioread, .open xgpio_open, .release xgpiorelease,}; 当系统启动后,GPIO控制器被初始化,申请资源 和内核I/O内存空间。用户调用open函数打开GPIO 设备时,系统调用了xgpio_open()i ̄数,主要完成使能 中断等功能。在打开设备后,返回一个文件指针,可 以用这个文件指针对设备进行一系列操作。当用户调 用read()函数对控制器进行读取的时候,系统调用了 xgpio_read0函数,读取GPIO设备数据寄存器的值。 当用户调用close()函数关闭GPIO设备时,系统调了 用xgpiorelease() ̄数,禁止中断。 2.2.1 GPIO控制器open()i ̄数的实现 在打开GPIO控制器后,依据GPIO数据文档,向 GPIO全局中断使能寄存器GIER写入0x80000000,向 中断使能寄存器IER写入0x00000003来使能中断: xgpio_open0ffl数实现代码如下 120实用案例ApplicationCase 中断 / . return O; } 2.2.2 GPIO控制器read() ̄数的实现 当用户空间调用read()i ̄数的时,调用putuser _函数实现内核空间数据到应用程序的传递,将内核空 间传递给用户空间的数据。xgpioread0 ̄数实现代码 如下: static ssize_t xgpioread(struct file file,char bur, size_t count,1ofi t ppos) { if(put_user(gpio_value,(int‘)buf)) return・EFAULT; else return sizeof(unsigned int); ) 2.2.3 GPIO控制器close()函数的实现 在关闭GPIO控制器后,向GPIO全局中断使能寄 存器GIER写入0x0,向中断使能寄存器IER写入0x0 来禁止中断。xgpio_release0函数实现代码如下: static int xgpiorelease(struct inode inode,stmct ifle。file) { XIo_Out32((int)xgpioinst->v__addr + XGPIOGIER__OFFSET,0x0); /.禁止全局中断 / XloOut32((int)xgpioinst->v_addr + XGPIOIER_OFFSET,0x0); 禁止GPIO中断 / _return0; } 3设备驱动添]Jtl ̄U嵌入式Linux内核中 嵌入式Linux设备驱动程序编写完成后,需要将 驱动程序加到内核中 ,这要求修改嵌入式Linux的源 

2011年第2O卷第5期 http://www.c-S・a.org,cn 计算机系统应用 代码,然后重新编译内核。步骤如下: release()函数,屏蔽GPIO中断。此时,驱动程序测试 3.1将设备驱动文件拷贝 ̄U/linux/driver/char目录下 结束。 3.2在/linux/driver/ehar目录下Makefile中增加如下 代码 5结语 obj一¥(CONFIG—XMU—GPIO)+ xgpio; Linux2.6内核引入的平台设备机制,使得内核对 在/linux/driver/char目录下Kconfig中增加如下代 设备的管理更加简便。本文介绍了基于PowerPC架构 码: 的嵌入式Linux平台设备驱动的一般设计方法。在基 Config XMUGPIO —.于FPGA的嵌入式系统中,外设通过GPIO的IP核与 tristate“XMU_ PIO” CPU的互连,因此,本文介绍的设备驱动程序的设计 depends on XILINXDRIVERS ——方法,具有的一定的通用性,对底层驱动程序开发人 select XILINXEDK ——员有较好的参考价值。此外,在Linux系统中,字符 help 设备和块设备都被映射到文件系统的文件和目录,很 This option enables support for Xilinx GPIO. 好地体现了“一切都是文件”的思想。所有的字符设 3_3重新编译内核,进入Linux目录,执行以下代码 备和块设备都被统一地呈现给用户,通过文件系统的 #make menuconfig 调用接口read()、write()等函数即可访问字符设备和块 在Character Devices一>中找到<>XMU GPIO选 设备【J1。 中为加载模块的形式:<}>XMU GPIO,然后保存退 出。 参考文献 #make l宋宝华.Linux设备驱动开发详解.北京:人民邮电出版社, 这样得到的内核包含了用户的设备驱动程序。 2008. 4 GPIo驱动程序的测试 2 Linux系列教材编写组.Linux操作系统分析与实践.北京:清 在应用程序中利用函数open()系统调用 华大学出版社,2008. xgpio open()i ̄数来使能GPIO中断,当中断发生时, 3周立功,陈明计,陈渝.ARM嵌入式Linux系统构建与驱动 执行中断处理程序;应用程序执行read() ̄数时,系统 程序开发范例.北京:北京航空航天大学出版社,2006. 调用了xgpio read()函数读取GPIO数据寄存器的值; 4董志国,李式巨.嵌入式Linux设备驱动开发.计算机工程与 当应用程序执行close()函数时,系统调用xgpio 设计,2006,2O(27):3737—3740. (上接第108页) 本系统的车流量统计部分还可以根据不同的要求 2贺春林.一种基于视频的车辆检测算法.计算机科 统计不同的时段和不同路况下的交通流量情况,例如 当给定道路的方向后,就可以统计出在某一给定时段 学,2005,32(5):243—245. 中向东、西、南、北不同方向行驶的车流量的变化规 3张玲,易卫明,何伟,郭磊民,陈丽敏.一种基于视频的车辆检 律,这样,能够给宏观的交通调控和调度~个合理的 测新方法,信息与电子工程,2006,4(4):264—267. 统计依据。这样,使得下一步让系统根据道路的车流 4王圣男,郁梅,蒋刚毅.智能交通系统中基于视频图像处理的 量状况自动进行交通灯的调度成为可能。 车辆检测与跟踪方法综述.计算机应用研究,2005,9:11—12. 参考文献 5 Be ̄ozzi M,Broggi A,Castelluccio S.A real time oriented l张超.视频监控中的图像匹配和运动目标检测【硕士学位论 system for vehicle detection.Journal of System Architec・ 文】.武汉:华中科技大学,2008.34—37. ture,1997,43(3):317—325. Application Case实用案例1 2 1 


本文标签: 设备 驱动 中断 函数 内核