现在的位置: 首页 > 综合 > 正文

Linux设备驱动之《点亮一盏LED》

2013年08月01日 ⁄ 综合 ⁄ 共 5843字 ⁄ 字号 评论关闭

    接着上一篇

字符设备驱动编写继续,GPIO就是General Purpose Input Output GPIO

(通用输入/输出)的意思,这里本人使用的开发板核心板为三星的s3c2440,非常普及的板,相信做ARM嵌入式的童鞋们一定都听说过的。

   如果玩过单片机那么对于ARM控制GPIO来说应该不会很陌生,上手比较容易,对于硬件的操作无非就是高低电平和寄存器的操作,所以对于ARM也是一样的。这里简单的介绍一个控制开发板上led的简单例子,对于硬件操作能有一定的基础概念和操作方法。

    全部程序的实现在三个文件中,头文件ioctl_c.h,C文件是驱动层test.c和应用层main.c

    首先是头文件,该文件主要定义了为GPIO操作的结构体和设备控制操作是的类型

_IOW()

_IOWR()

详解参见超链接中。

 

    然后是驱动层程序test.c

 

    函数说明:很多部分和上一篇讲解的字符驱动代码是一致的,这里就不作描述。

    在函数

 中多了一行 .ioctl=ioctl_test, 他就是应用层中ioctl函数的底层调用。

 

    那么就继续看ioctl_test函数

    这里有函数copy_from_user(),这是一个很常用很重要的函数,该函数主要作用就是将用户空间的数据复制到内核空间

。这里实际上是把应用层上的结构体复制到内核中。这里为什么这样在后面描述。

 

    然后根据函数参数cmd作判断,分别判断传入内核空间的是GPIO_IO_SET_GPG还是GPIO_IO_GET_GPG。

      switch(cmd)

    {

        case GPIO_IO_SET_GPG :led_ctl();break;

        case GPIO_IO_GET_GPG :led_ctl();break;

    //    case GPIO_IO_WRITE :printk("cmd3") ;break;

    //    case GPIO_IO_READ :printk("cmd3") ;break;

        default:break;

    }

 

    紧接着到led_ctl()函数中分析

    这里牵扯到了硬件操作,先看一下底板硬件电路图。是GPG5和GPG6两个脚。

    声明一个结构体 GPIO_Data_S led;

    所以结构中我们赋值 led.port=='G'&& led.bit==5 && led.value==0 和 led.port=='G' && led.bit==6 && led.value==0

 

    然后对硬件写数据,写硬件调用函数 __raw_writel()

    __raw_writel(0x400,S3C2410_GPGCON);

    __raw_writel(0xffdf,S3C2410_GPGDAT);

    这里为什么要些这个数据,我们要看一下s3c2440的数据手册

 

 

 

 

    如图0x400的二进制数是0000010000000000,这里的GPG5给01,说明是output,这个值赋给GPGCON寄存器中,这样才能点亮LED。

    而    0xffdf  的二进制则是1111111111011111
,GPGDAT的描述中说:当端口配置为输出,引脚状态和相应的位一样。这里0的意思就是第5位给低电平,由电路图知道引脚给0值LED亮。

    GPG6同理!!

 

    驱动层代码就分析到这里,后面是应用层编程。main.c

 

    函数说明:这里的#include "../ioctl_c.h"是头文件位置,可以根据情况自行修改。

        led_ctl.port='G';
        led_ctl.bit=5;
        led_ctl.value=0;

        ioctl(testdev,GPIO_IO_SET_GPG,&led_ctl);

    就实现GPG5的LED亮。

     最后执行编译,make
,交叉编译main.c。

     生成test.ko和main

     下载到开发板中
,演示如下

 

  试验证明:LED可以点亮! ^_^

 

【上篇】
【下篇】

抱歉!评论已关闭.