快捷搜索:   nginx

Linux设备驱动程序--与硬件通信(2)

  但这并不表示I/O端口的指令在s3c24x0中不可用。但是只要你注意其源码,你就会发现:其实I/O端口的指令只是一个外壳,内部还是使用和I/O内存一样的代码。以下列出一些:

  I/O端口

  #define outb(v,p)        __raw_writeb(v,__io(p))

  #define outw(v,p)        __raw_writew((__force __u16) \

  cpu_to_le16(v),__io(p))

  #define outl(v,p)        __raw_writel((__force __u32) \

  cpu_to_le32(v),__io(p))

  #define inb(p)    ({ __u8 __v = __raw_readb(__io(p)); __v; })

  #define inw(p)    ({ __u16 __v = le16_to_cpu((__force __le16) \

  __raw_r

eadw(__io(p))); __v; })

  #define inl(p)    ({ __u32 __v = le32_to_cpu((__force __le32) \

  __raw_readl(__io(p))); __v; })

  I/O内存

  #define ioread8(p)    ({ unsigned int __v = __raw_readb(p); __v; })

  #define ioread16(p)    ({ unsigned int __v = le16_to_cpu(__raw_readw(p)); __v; })

  #define ioread32(p)    ({ unsigned int __v = le32_to_cpu(__raw_readl(p)); __v; })

  #define iowrite8(v,p)    __raw_writeb(v, p)

  #define iowrite16(v,p)    __raw_writew(cpu_to_le16(v), p)

  #define iowrite32(v,p)    __raw_writel(cpu_to_le32(v), p)

  我对I/O端口的指令和I/O内存的指令都写了相应的驱动程序,都通过了测试。在这里值得注意的有4点:

  (1)所有的读写指令所赋的地址必须都是虚拟地址,你有两种选择:使用内核已经定

  义好的地址,如

  S3C2440_GPJCON等等,这些都是内核定义好的虚拟地址,有兴趣的可以看源码。还有一种方法就是使用自己用ioremap映射的虚拟地址。绝对

  不能使用实际的物理地址,否则会因为内核无法处理地址而出现oops。

  (2)在使用I/O指令时,可以不使用request_region和request_mem_region,而直接使用outb、ioread等指令。因为request的功能只是告诉内核端口被谁占用了,如再次request,内核会制止。

  (3)在使用I/O指令时,所赋的地址数据有时必须通过强制类型转换为 unsigned long ,不然会有警告(具体原因请看

  Linux设备驱动程序学习(7)-内核的数据类型

  ) 。虽然你的程序可能也可以使用,但是最好还是不要有警告为妙。

  (4)在include\asm-arm\arch-s3c2410\hardware.h中定义了很多io口的操作函数,有需要可以在驱动中直接使用,很方便。

  实验源码:

  IO_port.tar.gz

  IO_port_test.tar.gz

  IO_mem.tar.gz

  IO_mem_test.tar.gz

  两个模块都实现了阻塞型独享设备的访问控制,并通知内核不支持llseek。具体的测试在IO_port中。

  测试现象如下:

  [Tekkaman2440@SBC2440V4]#cd /lib/modules/

  [Tekkaman2440@SBC2440V4]#insmod IO_port.ko

  [Tekkaman2440@SBC2440V4]#insmod IO_mem.ko

  [Tekkaman2440@SBC2440V4]#cat /proc/devices

  Character devices:

  1 mem

  2 pty

  3 ttyp

  4 /dev/vc/0

  4 tty

  4 ttyS

  5 /dev/tty

  5 /dev/console

  5 /dev/ptmx

  7 vcs

  10 misc

  13 input

  14 sound

  81 video4linux

  89 i2c

  90 mtd

  116 alsa

  128 ptm

  136 pts

  153 spi

  180 usb

  189 usb_device

  204 s3c2410_serial

  251 IO_mem

  252 IO_port

  253 usb_endpoint

  254 rtc

  Block devices:

  1 ramdisk

  256 rfd

  7 loop

  31 mtdblock

  93 nftl

  96 inftl

  179 mmc

  [Tekkaman2440@SBC2440V4]#mknod -m 666 /dev/IO_port c 252 0

  [Tekkaman2440@SBC2440V4]#mknod -m 666 /dev/IO_mem c 251 0

  [Tekkaman2440@SBC2440V4]#cd /tmp/

  [Tekkaman2440@SBC2440V4]#./IO_mem_test

  io_addr : c485e0d0

  IO_mem: the module can not lseek!

  please input the command :1

  IO_mem: ioctl 1 ok!

  please input the command :8

  IO_mem: ioctl STATUS ok!current_status=0X1

  please input the command :3

  IO_mem: ioctl 3 ok!

please input the command :q

  [Tekkaman2440@SBC2440V4]#./IO_porttest_sleep &

  [Tekkaman2440@SBC2440V4]#./IO_porttest_sleep &

  [Tekkaman2440@SBC2440V4]#./IO_porttest_sleep &

  [Tekkaman2440@SBC2440V4]#./IO_port_test

  IO_port: the module can not lseek!

  please input the command :1

  IO_port: ioctl 1 ok!

  please input the command :8

  IO_port: ioctl STATUS ok!current_status=0X1

  please input the command :3

  IO_port: ioctl 3 ok!

  please input the command :8

  IO_port: ioctl STATUS ok! current_status=0X3

  please input the command :q

  [1] Done ./IO_porttest_sleep

  [Tekkaman2440@SBC2440V4]#ps

  PID Uid VSZ Stat Command

  1 root 1744 S init

  2 root SW [kthreadd]

  3 root SWN [ksoftirqd/0]

  4 root SW [watchdog/0]

  5 root SW [events/0]

  6 root SW [khelper]

  61 root SW [kblockd/0]

  62 root SW [ksuspend_usbd]

  65 root SW [khubd]

  67 root SW [kseriod]

  79 root SW [pdflush]

  80 root SW [pdflush]

  81 root SW [kswapd0]

  82 root SW [aio/0]

  709 root SW [mtdblockd]

  710 root SW [nftld]

  711 root SW [inftld]

  712 root SW [rfdd]

  746 root SW [kpsmoused]

  755 root SW [kmmcd]

  773 root SW [rpciod/0]

  782 root 1752 S -sh

  783 root 1744 S init

  785 root 1744 S init

  787 root 1744 S init

  790 root 1744 S init

  843 root 1336 S ./IO_porttest_sleep

  844 root 1336 S ./IO_porttest_sleep

  846 root 1744 R ps

  [Tekkaman2440@SBC2440V4]#ps

  PID Uid VSZ Stat Command

  1 root 1744 S init

  2 root SW [kthreadd]

  3 root SWN [ksoftirqd/0]

  4 root SW [watchdog/0]

  5 root SW [events/0]

  6 root SW [khelper]

  61 root SW [kblockd/0]

  62 root SW [ksuspend_usbd]

  65 root SW [khubd]

  67 root SW [kseriod]

  79 root SW [pdflush]

  80 root SW [pdflush]

  81 root SW [kswapd0]

  82 root SW [aio/0]

  709 root SW [mtdblockd]

  710 root SW [nftld]

  711 root SW [inftld]

  712 root SW [rfdd]

  746 root SW [kpsmoused]

  755 root SW [kmmcd]

  773 root SW [rpciod/0]

  782 root 1752 S -sh

  783 root 1744 S init

  785 root 1744 S init

  787 root 1744 S init

  790 root 1744 S init

  847 root 1744 R ps

  [3] + Done ./IO_porttest_sleep

  [2] + Done ./IO_porttest_sleep

  程序是针对2440的,若是用2410只需要改改测试的io口就好了

本文作者:未知

顶(0)
踩(0)

您可能还会对下面的文章感兴趣:

最新评论