Chinaunix首页 | 论坛 | 博客
  • 博客访问: 24860
  • 博文数量: 10
  • 博客积分: 1415
  • 博客等级: 上尉
  • 技术积分: 75
  • 用 户 组: 普通用户
  • 注册时间: 2009-05-23 15:21
文章分类

全部博文(10)

文章存档

2011年(1)

2009年(9)

我的朋友
最近访客

分类: LINUX

2009-08-20 20:01:37

驱动程序设计:
  •     linux操作系统的驱动与bootloader的驱动区别: 要考虑与应用层的接口; 考虑多用户; 考虑其他协议; 设备驱动的作用:读数据,写数据; 初始化设备,读写设备; 将设备的数据分配给应用; 将应用的数据分配给设备; 操作系统中驱动和设备的关系是一一对应的; 应用和驱动的关系是一对多的; 内核的主要功能:进程管理, 内存管理, 文件系统, 设备控制, 网络; linux驱动的分类:字符设备, 块设备, 网络设备; 大部分情况:主编号标识相应的驱动程序(现代linux允许多个驱动程序共享主编号), 次设备号标识哪个设备; 设备文件的cp:$ sudo cp -a /dev/mouse /tmp/ (此时是fopen打开设备文件) $ sudo cp /dev/mouse /tmp/ (此时是open打开设备) linux设备驱动信息的查看: /proc/devices 查看系统支持的字符设备和块设备驱动; /proc/pci 查看系统的PCI设备; /proc/ioports 查看设备的IO端口; /proc/interrupts 查看正在使用的中断号,中断次数; /proc/net/dev 查看网络硬件设备,包括被down的网卡; /proc/kallsyms 查看模块符号; /proc/jitimer 查看定时器; dmesg 查看系统的启动信息,可以看到系统支持的一些驱动的打印信息; lspci lsusb -v uname -a ifconfig -a 查看所有网卡 模块不全是驱动,但大多数模块都是驱动; 那些函数可以在模块中使用,关于kernel的API,可以查看 模块的重新编译: 在/usr/src/linux下解压linux源码包; 拷贝配置文件:cp /boot/config-2.6.20-16.generic /usr/src/linux/.config; 重新编译内核:sudo make 在模块的工程目录下编译模块:make 模块的参数传递: module_param(name, type, perm); static int count; module_param(count,int,0); #insmod driver.ko count=10 #lsmod #rmmod driver 模块的交叉编译(arm开发板): 重新编译2.6.17.14内核,把zImage传给开发板; 将module工程目录拷贝到rootfs/usr/module下; 将module里的Makefile的源码路径变成2.6.17.14内核所在路径; 重新编译sudo make; 应用层--->TELNET,FTP,EMAIL 运输层--->TCP,UDP 网络层--->IP,ICMP,IGMP 链路层--->设备驱动程序及接口卡 USB设备驱动: 一些重要网站: linux驱动的相关知识:下载Linux Device Drivers,2nd Edition USB的相关资料: http://www.usbman.com/developer.htm usb1.1规范: /developer/docs/usbspec.zip ohci协议: ftp://ftp.compaq.com/pub/supportinformation/papers/hcir1_0a.pdf uhci协议: http://developer.inter.com/technology/usb/UHCI11D.pdf lsusb -v 查看USB设备信息; Vendor:Product =1241:1111 这是USB设备的ID号需要向USB.ORG申请获得; NumConfigurations = 1 表明配置描述符有1个; bEndpointAddress = 81(in) 意思是1000 0001,最高位1是读, 后面1是端点号; bmAttributes = 03(interrupt) 表明是中断类型的传送;因此有bInterval = 08(8ms) 表明间隔时间8ms; 工作过程: USB主机控制器通过DMA方式访问所有设备; 对设备的读写是通过设备的端点来实现的; USB主机通过协议链表来轮询这些端点,每个端点想要正常工作就要填充好端点格式,并放到协议链表中; 控制,实时,中断,大量传输需要不同的方式来填充协议链表; 当硬件读写完成通过中断方式来告诉CPU,并由CPU来处理剩下的工作; 字符设备C 块设备B 网络设备(无设备文件) 设备文件有文件节点, 但没有真正的内容; 主设备号标识与设备相连的驱动, 次设备号用来决定引用那个设备(一般如此, 非绝对); 设备号的内核类型dev_t MAJOR( dev_t dev); MINOR( dev_t dev); MKDEV( int major, int minor); sudo cp -a /dev/input/mice /tmp/ #fopen 拷贝文件 sudo cp /dev/input/mice /tmp/ #open 打开设备 cat /proc/devices pci ioports interrupts lspci //lsusb -v //cpuinfo partitions //dmesg 可查看模块输出信息 kallsyms 模块加载位置??? ln -s sda/c/ cc 建符号连接 sudo aptitude install linux-source-2.6.20 模块的写法 头文件 参数的使用 延时参数的使用 用户空间与kernel空间的数据互传; copy_to_user/copy_from_user put_user/get_user 第一个linuxkernel模块实验: uname -a //查看当前版本 查看/user/src/ 下是否有相应的linux source, 若无, 下载安装linux-source-2.6.20 sudo cp /boot/config-2.6.20-15.generic /usr/src/linux-2.6.20/.config sudo make 在module的编写目录下, make 再使用insmod rmmod lsmod dmesg查看模块进出信息; com2设置: ucon1<-0x5 轮询收发 ulcon1<-0x3 8N1 ubrdiv1<-26 115200bps 状态寄存器: UTRSTAT1, bit[1 : 0]判断收发ready; UTXH1->L(v) B(x)???发 URXH1->L(v) B(x)收; 对物理地址的读写, 有两种方法: 1. #define UCON1 (*((volatile unsigned *)ioremap(0x500c4004, 4))) 2. include #define iobase S3C24XX_VA_UART1 #define UCON1 (iobase + 0x04) __raw_writel( 5, UCON1); state = __raw_readb( UTRSTAT1); \n换行\r回车 ~/.trash回收站 function(void) void定义时不可少; 需包含一些 实验主要流程: 将linux2.6.17.14代码解压到~/.目录下, 重新make menuconfig设置arm, 增加module support; 重新编译后, 下载内核zimage到2410板子上, 在driver编辑目录, 将makefile的src路径变为~/.linux2.6.17.14; make, 获得driver. ko文件, 将他拷贝到rootfs/usr/driver/下 开发板用NFS方式启动, 在minicom中, 运行insmod driver.ko ,lsmod ,rmmod driver 观察结果; SCULL设备驱动: 在编写设备驱动时遇到了以下问题: 1. 收发相同->buf[]指向了一个固定的字符串, 需要收发分开数组; 2. 发可以, 收不到->在驱动中收发用不同数组, 写可以动态申请, 收用数组是成功的??? 3. 收发用数组指针如*buf++, 结果已经被移动, 用buf[tmp++]即可; 4. 在count经count--后, 却用在copy_to_user(buf, kbuf, cout)中, count已经为0了; 5. recieve信息在终端显示被char release打断, 两种处理方式可行: close之前sleep(1); release中不打印信息; 6. tmp++后, return tmp正好是所读个数, 而不是tmp+1; sudo -s /su username 字符设备驱动, GPIO驱动: 一些概念: dev_t为32位设备号(12+20); scull_dev结构, cdev结构 老注册方法: register_chrdev(major, &name, &fops) unregister_chrdev(major, &name) 新注册方法: regist_chrdev_region(dev_t, count, &name); alloc_chrdev_region(&dev, firstminor, count, &name); major = MAJOR(dev); cdev_init(&cdev, &fops); cdev. owner=THIS_MODULE; cdev.ops=&fops; cdev_add(&cdev, devno, 1); cdev_del(&cdev); unregister_chrdev_region( first, count); 关于中断: 处理器管理设备的方式, 轮询, 中断+DMA; S3C2410支持56个中断设备, 32个中断号; SRCPND, INTPND, INTMSK 写1清0; request_irq(irq, &handler, flags, &dev_name, &dev_id); free_irq(irq, &dev_id); GPIO实验: 注意这些目录: asm/arch-s3c2410/regs-irq.h asm/arc-s3c2410/regs-serial.h 寄存器名称: S3C2410_EINTPEND 寄存器读写函数: __raw_writel() __raw_writeb() __raw_readl() __raw_readb() 寄存器SRCPND, INTPND, EINTPENT均写1清0; irq_return_t 是中断服务函数的返回类型; static struct semaphore key_sem; up ( &key_sem); down_interruptible ( &key_sem); open时开中断, release时关中断, rmmod时free(irq); set_irq_type 设置中断类型; . bashrc: +PS1='$' 可改变shell提示符的显示内容; 推荐书籍: linux内核设计与实现==陈莉君, linux驱动 倪继利 网卡驱动: 网卡: 实模式, 286, 1M;/保护模式, 386, 4G BootRom: 启动novell网, IPX协议, 内存上虚拟一个盘; MAC协议层+PHY&传输层,物理层 MAC向IEEE申请6个16进制, 后6个16进制公司自配置; 00.xx.xx. yy.yy.yy DEVICE ID标识厂家, 型号; 保存在设备列表中, 靠PCI, USB等协议维护; 网线, 4线, 8线有一组备用; LCD, TVout, 若各自用单独振源, 将导致冲突; 网卡的调试方法: 硬件(电源, 晶振. . .); 软件(. . .); 将arm开发板的网卡去除后, 通过串口传程序的方法: 1. 启动pc端minicom, 启动开发板 2. 进入linux, cd /tmp 3. rx文件名; C + A, S, 选择xmodem; 4. 选文件(双空格->进目录; 空格+回车); PC端若不工作, 安装Lrzsz. 定义类型的几种情形: typedef, struct, #define等; 查找方法: grep str key$, key{, key空{ 等方法; S3C2410_IRQREG(x) ->C(x) + S3C24XX_VA_IRQ) Soket系统调用来操作网络设备, 而不是open一个设备文件; 看网卡硬件的方法, 确定有几个网卡; cat /proc/net/dev 或ifconfig -a 看本机ip的一个方法, ping 一个无法联通的ip; (在没有ifconfig); ifconfig up-->open ifconfig down-->close; register_netdev时会初始化net_device, 并调用init函数; net_device的主要成员: init, open(request_irq), stop(free_irq), hard_start_xmit, net_stats; 收发数据后, netif_rx把接收的数据交给协议层, netif-start/stop/wake-queue #define SMDK2410_ETH_IRQ IRQEINT8 SMDK2410存在于四个目录: include / asm ( arm-arm)/arch (arch-s3c2410); 双索引寄存器的操作, 可扩展存储空间; lxr & source insight 两种方便用于源代码查看的工具; 网卡实验: 两个抓包工具: tcpdump -i eth1 // wire shark 主要步骤: 1. 启动无网络的linux; 2. driver8900.ko, server, client下载到板子; 3. mknod /dev/mynet c 242 0 4. insmod driver8900.ko 5. . /server or . /client 硬件部分1015: AGND-----L----DGND 存储模式, 带缓存 IO模式, 不带缓存; Nandflash D[7: 0 ] 数据/命令/地址复用 RAM用了6个管, SDRAM用了一个管子和一个电容; candence兼并了orcad, 工具好用; 网卡实验: 1. write(pp_txtmd), write( pp_txlength) read(pp_busst); 若顺序反, 无法写成功; 2. 收到的ping包有64字节, 最后4字节有可能是CRC校验码; 3. 可以将buf={ 0x11, 0x12 . . .}放入头文件, 程序引用, 作为数据发送; 4. open若用RDONLY会无法写成功; 可查看cat /proc/ioports/ 观察IO空间; EINT8->0XF0000000+36 USB1.1, USB2.0/主, 从, OTG设备(5芯) USB缺点: 不稳定, 线<=5m; 北桥一般挂接高速设备, 如memory等; PCI设备启动时要获取: 中断号, IO空间, memory空间; 启动ip, . /app -qws (qt界面程序) 给2410上拷贝文件: scp来实现; sybian 赛班; arm-elf-gcc v2.95.3 一般错误返回-1, 成功返回0; Qimage可先生图形/setitimer在uclinux中定时; "hello" + 1==>"ello"; if(defined(x))可以为变量; ifdef x 只能是宏; 2.0/3.0输出结果不同于2/3, 前者是float数据; dpkg -L nfs-kernel-server 显示安装目录 通常服务器配置问题可以通过拷贝正确的配置文件解决; 编程中用些宏定义, 条件编译, 注释说明等; 驱动的一些例程: #driver makefile ifneq ($(KERNELRELEASE),) # kbuild part of makefile obj-m :=driver.o else KERNELSRC:=/home/username/linux-2.6.17.14 modules: make -C $(KERNELSRC) SUBDIRS=$(PWD) $@ clean: 具体源码请看原出处 http://blog.chinaunix.net/u1/53151/showart_423232.html
阅读(1109) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~