免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2312 | 回复: 0
打印 上一主题 下一主题

Linux Arm驱动开发总结 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-08-20 20:01 |只看该作者 |倒序浏览
驱动程序设计:
  •     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,可以查看http://kernelbook.sf.net
    模块的重新编译:
    在/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驱动的相关知识:http://www.xml.com/ldd/chapter/book下载Linux Device Drivers,2nd Edition
    USB的相关资料:http://www.bode.cs.tum.edu/Par/arch/usb/usbdoc
                  http://www.usbman.com/developer.htm
                  http://www.usb.org
    usb1.1规范:   http://www.usb.org/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设置:  
    ucon1L(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缺点:   不稳定, 线"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

               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/97214/showart_2033168.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP