`
saybody
  • 浏览: 907120 次
  • 性别: Icon_minigender_2
  • 来自: 西安
文章分类
社区版块
存档分类
最新评论

Linux2.6.33 自己动手写驱动

阅读更多

Linux2.6.33 自己动手写驱动

一、GPIO驱动编写和测试

1GPIO的这点事儿

GPIOGeneral-Purpose IO ports,通用的IO端口。一般的微处理器芯片都提供通用的可编程IO端口,用户可以通过配置寄存器将其配置成输入、输出或者其他特殊功能模式。

通用IO端口一般都可以实现按位操作,即用户可以针对IO端口的每一位(以下简称IO位)进行操作。

GPIO端口输出的高低电平可以通过控制一组LED发光二极管来加以验证,这里,我们截取TE2440-DEV-I教学板中的四个发光二极管做实验。

应用S3C2440GPF4-GPF7共四个IO位,各自控制一个发光二极管,分别对应D1-D4,硬件原理如图6.1所示。

<shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></path><lock v:ext="edit" aspectratio="t"></lock></shapetype><shape id="图片_x0020_1" o:spid="_x0000_i1026" type="#_x0000_t75" o:bordertopcolor="black" o:borderleftcolor="black" o:borderbottomcolor="black" o:borderrightcolor="black" style="visibility: visible; width: 371.25pt; height: 137.25pt; mso-wrap-style: square"><font size="3"><imagedata src="file:///C:/DOCUME~1/IBM/LOCALS~1/Temp/msohtmlclip1/01/clip_image001.emz" o:title="" gain="192753f" grayscale="t" bilevel="t"></imagedata><bordertop type="single" width="4"></bordertop><borderleft type="single" width="4"></borderleft><borderbottom type="single" width="4"></borderbottom><borderright type="single" width="4"></borderright></font></shape>

6.1 IO控制LED原理图

原理图分析:

(1) 四个发光二极管采用共阳极的连接方法,即四个发光二极管的阳极连接在一起,并连接到3.3V电源。

(2) 发光二极管的负极各自连接一个1K限流电阻,再分别连接到S3C2440GPF4-GPF7

思考:为什么要接一个1K的限流电阻呢?

顾名思义,串接限流电阻就是为了显示通过发光二极管的电流,从而达到减少功耗或者满足端口对最大电流的限制。

一般发光二极管的点亮电流为5mA~10mATE2440采用贴片发光二极管,1K限流电阻,驱动电压为3.3V,发光二极管压降为1.6V,那么发光二极管的电流大约为1.7mA。发光二极管已经能点亮了,如果希望更亮一些,可以将限流电阻减小,但是二极管的电流不能超多ARM芯片IO口的最大驱动电流。

(3) 根据电路原理可知,当GPF4-GPF7输出低电平时,由于发光二极管两端加上电压,则发光二极管点亮;当GPF4-GPF7输出高电平只,由于发光二极管两端压差为0,则发光二极管熄灭。

思考:发光二极管为什么会亮呢?

发光二极管在其两端的电压差超出其导通压降时开始工作,普通发光二极管的导通压降一般为1.6V~2.1V,同时,工作电流要满足该二极管的工作电流。满足电压和电流的要求,该二极管就可以发光了。

二极管的正负极可以用万用表的二极管档量出来,如果表上有了一点多的读数,红表笔接的发光二极管的正极,黑表笔接的就是发光二极管的负极。

(4) 我们可以通过程序控制GPF4-GPF7有规律的输出高低电平,则实现发光二极管有规律的亮灭。

2、驱动怎样编写

了解的硬件的概念以后,我们开始我们的驱动编写工作。

然后再在内核源码的“drivers/char/”目录下新建一个名为“TopElec_GPIO.c”的文件,作为我们的驱动文件。内容如下:

/*************************************

NAME:TopElec_GPIO.c

COPYRIGHT:www.top-elec.com

Ver1.00 2010/05/19

*************************************/

#include <linux/miscdevice.h>

#include <linux/delay.h>

#include <asm/irq.h>

#include <mach/regs-gpio.h>

#include <mach/hardware.h>

#include <linux/kernel.h>

#include <linux/module.h>

#include <linux/init.h>

#include <linux/mm.h>

#include <linux/fs.h>

#include <linux/types.h>

#include <linux/delay.h>

#include <linux/moduleparam.h>

#include <linux/slab.h>

#include <linux/errno.h>

#include <linux/ioctl.h>

#include <linux/cdev.h>

#include <linux/string.h>

#include <linux/list.h>

#include <linux/pci.h>

#include <asm/uaccess.h>

#include <asm/atomic.h>

#include <asm/unistd.h>

#include <linux/gpio.h>

#define DEVICE_NAME "GPIO-Control"

#define S3C2410_GPFCON S3C2410_GPIOREG(0x50)

#define S3C2410_GPFDAT S3C2410_GPIOREG(0x54)

#define S3C2410_GPFUP S3C2410_GPIOREG(0x58)

#define S3C2410_GPF4 S3C2410_GPIONO(S3C2410_GPIO_BANKF, 4)

#define S3C2410_GPF5 S3C2410_GPIONO(S3C2410_GPIO_BANKF, 5)

#define S3C2410_GPF6 S3C2410_GPIONO(S3C2410_GPIO_BANKF, 6)

#define S3C2410_GPF7 S3C2410_GPIONO(S3C2410_GPIO_BANKF, 7)

#define S3C2410_GPF4_OUTP (0x01 << 8)

#define S3C2410_GPF5_OUTP (0x01 << 10)

#define S3C2410_GPF6_OUTP (0x01 << 12)

#define S3C2410_GPF7_OUTP (0x01 << 14)

/* 应用程序执行ioctl(fd, cmd, arg)时的第2个参数 */

#define IOCTL_GPIO_ON 1

#define IOCTL_GPIO_OFF 0

/* 用来指定LED所用的GPIO引脚 */

static unsigned long gpio_table [] =

{

S3C2410_GPF(4),

S3C2410_GPF(5),

S3C2410_GPF(6),

S3C2410_GPF(7),

};

/* 用来指定GPIO引脚的功能:输出 */

static unsigned int gpio_cfg_table [] =

{

//由于2.6.33内核中没有定义GPIO的动作,所以我在上面自己定义了一下。

S3C2410_GPF4_OUTP,

S3C2410_GPF5_OUTP,

S3C2410_GPF6_OUTP,

S3C2410_GPF7_OUTP,

};

static int te2440_gpio_ioctl(

struct inode *inode,

struct file *file,

unsigned int cmd,

unsigned long arg)

{

if (arg > 4)

{

return -EINVAL;

}

switch(cmd)

{

case IOCTL_GPIO_ON:

// 设置指定引脚的输出电平为0

s3c2410_gpio_setpin(gpio_table[arg], 0);

return 0;

case IOCTL_GPIO_OFF:

// 设置指定引脚的输出电平为1

s3c2410_gpio_setpin(gpio_table[arg], 1);

return 0;

default:

return -EINVAL;

}

}

static struct file_operations dev_fops = {

.owner = THIS_MODULE,

.ioctl = te2440_gpio_ioctl,

};

static struct miscdevice misc = {

.minor = MISC_DYNAMIC_MINOR,

.name = DEVICE_NAME,

.fops = &dev_fops,

};

static int __init dev_init(void)

{

int ret;

int i;

for (i = 0; i < 4; i++)

{

s3c2410_gpio_cfgpin(gpio_table[i], gpio_cfg_table[i]);

s3c2410_gpio_setpin(gpio_table[i], 0);

}

ret = misc_register(&misc);

printk (DEVICE_NAME" initialized/n");

return ret;

}

static void __exit dev_exit(void)

{

misc_deregister(&misc);

}

module_init(dev_init);

module_exit(dev_exit);

MODULE_LICENSE("GPL");

MODULE_AUTHOR("www.top-elec.com");

MODULE_DESCRIPTION("GPIO control for Topelec TE2440DEV_I Board");

3、让驱动到内核里混一下

在内核源码中添加对LED 灯驱动的支持,修改同目录下的Kconfig文件,添加如下内容:

config TE2440_GPIO_TEST

tristate "TE2440DEV-I Board GPIO Test(LED TEST)"

depends on ARCH_S3C2440

default y if ARCH_S3C2440

help

GPIO control for TE2440DEV-I Board.

同样的道理,修改同目录下的Makefile文件,修改的内容如下:

obj-$(CONFIG_TE2440_GPIO_TEST) += TopElec_GPIO.o

4、配置和编译内核

进入内核目录,键入make menuconfig命令,进入内核配置菜单,如下图所示:

Diver->chacarter device-> TE2440DEV-I Board GPIO Test 的支持,当然,你也可以选择<M>将驱动编译成模块。

好了,OK,大胆的make吧!

当然可能有错误,因为内核的版本不一致,或是编译器的问题,总之,Linux虽然玩起来和带劲,但是问题也会很多,要有越挫越勇的精神才能成为真正的高手哦!

至于,怎么把内核搞到板子上不在这里就不说了。

5、编写测试程序

/*************************************

NAME:GPIO_TEST.c

COPYRIGHT:www.top-elec.com

*************************************/

#include <stdio.h> /*定义函数要用到的头文件*/

#include <stdlib.h>

#include <unistd.h>

#include <sys/ioctl.h>

int main(int argc, char **argv) /*运行时参数传递,开或关哪个LED*/

{

int on; /*定义led状态变量,1表示灯亮,2表示灯灭*/

int led_no; /*定义led变量--哪个led*/

int fd; /*定义led设备文件描述符的变量*/

if (argc != 3 || sscanf(argv[1], "%d", &led_no) != 1 || sscanf(argv[2],"%d", &on) != 1 ||

on < 0 || on > 1 || led_no < 1 || led_no > 4) /*判断命令输入参数个数*/

{

fprintf(stderr, "Usage: Please enter led number and led status,For example GPIO_TEST 1 0 /n");

exit(1);

}

fd = open("/dev/GPIO-Control", 0); /*为只读打开GPIO-Control设备文件,取出文件描述符*/

if (fd < 0) {

perror("open device /dev/GPIO-Control"); /*如果打开led文件出错,拿不到文件描述符,用perror宏输出错原因及信息*/

exit(1);

}

ioctl(fd, on, (led_no-1)); /*ioctl()函数控制LED,其中fd--是前面打开的LED文件描述符,on--是开关命令01led_no--是哪个LED*/

close(fd);

return 0;

}

顺便这个Makefile文件,看起来专业点:

CROSS=arm-softfloat-linux-gnu-

all:GPIO_TEST

GPIO_TEST:GPIO_TEST.c

$(CROSS)gcc GPIO_TEST.c -o GPIO_TEST

$(CROSS)strip GPIO_TEST

clean:

@rm -vf GPIO_TEST *.o *~

有了上面的两个 make就可以了

最后把测试程序搞的开发板上运行一下:

bash-3.2# ./GPIO_TEST 1 1 意思是D1被点亮

很多资料来源于网络,谢谢网络的上的无私奉献大侠们!

华清远见-嵌入式领域著名讲师 O(_)O 牛牛猛

点击链接加我好友!

http://student.csdn.net/invite.php?u=111047&c=758a60d66d3a92d1

欢迎大家去我CSDN博客上踩踩

我的个人主页

分享到:
评论

相关推荐

    基于linux2.6.33的spi flash 驱动移植总结

    在基于Linux 2.6.33的SPI Flash驱动移植过程中,主要涉及到了三个关键组件:SPI主机驱动(dm644x上的SPI功能模块驱动)、SPI Flash芯片驱动(w25x80的芯片驱动)以及SPI总线驱动。 **1. SPI主机驱动(dm644x上的SPI...

    基于linux-2.6.33网卡驱动之cs8900

    总的来说,基于Linux-2.6.33内核的cs8900网卡驱动开发涉及的知识点包括:C语言编程,Linux内核驱动开发框架,CS8900A硬件特性,中断处理,网络协议栈的接口,设备模型,以及驱动程序的移植技术。通过研究这些内容,...

    最新linux2.6.33内核移植到s3c2410平台详细步骤

    ### Linux 2.6.33 内核移植到 S3C2410 平台详解 #### 一、前言 随着嵌入式系统的不断发展,Linux内核的移植成为了一个重要的研究方向。本文主要介绍了如何将最新的Linux 2.6.33内核移植到S3C2410平台上,包括搭建...

    S3C2410的 Linux2.6.33内核移植以及搭建交叉编译

    ### S3C2410的 Linux2.6.33 内核移植与搭建交叉编译环境 #### 概述 本篇文章旨在详细介绍如何针对S3C2410平台进行Linux2.6.33内核移植,并在此基础上构建交叉编译环境的过程。整个流程分为几个关键步骤,包括环境...

    Linux2.6.33 下ZC301USB 摄像头使用教程

    ### Linux2.6.33下ZC301USB摄像头使用教程 #### 一、概述 本教程旨在详细介绍如何在Linux2.6.33环境下配置与使用ZC301USB摄像头,特别是针对中芯优电的TE-2440开发板。文章分为几个部分:编译器配置、内核配置、...

    linux-2.6.33

    linux 2.6.33源码,官方版本。

    linux虚拟网卡设备驱动

    2.6.33linux虚拟网卡设备驱动

    嵌入式Linux帧缓冲设备驱动程序.pdf

    本文将深入探讨嵌入式Linux帧缓冲驱动的体系结构、关键数据结构和编写方法,并结合具体的ARM9处理器S3C2440平台上的开发实例,介绍Linux 2.6.33内核基于Platform总线的帧缓冲驱动的实现原理和开发流程。 首先,帧...

    ubuntu下编译linux kernel 2.6.38

    在Ubuntu 10.10环境下编译Linux内核2.6.38涉及一系列步骤,需要对操作系统、内核版本、编译工具和配置选项有深入理解。以下是详细的编译流程和注意事项: 首先,确保你的环境是Pentium 4架构的Ubuntu 10.10(内核...

    虚拟网卡驱动VirtualMachineNetworkDriver

    虚拟网卡驱动VirtualMachineNetworkDriver是为虚拟化环境设计的一种特殊网络适配器,它使得在无需物理添加网卡的情况下,虚拟机也能实现网络通信。这个驱动程序的主要目标是提高虚拟化平台的效率,减少对硬件资源的...

    2.6.33-at91.patch.gz

    2.6.33-at91.patch.gz arm linux补丁

    linux-2.6.33.2

    linux 2.6.33.2源码,官方版本。

    linux-headers-2.6.32-25元代码

    5. **设备驱动**:Linux内核通过驱动程序与硬件交互,提供了广泛的设备支持。在这一版本中,可以学习到如何编写和调试设备驱动,例如USB、PCI等总线上的设备驱动。 6. **模块化设计**:Linux内核采用模块化设计,...

    cs8900.c和cs8900.h

    关于cs8900驱动移植基于linux2.6.33 s3c2410开发板

    Smarty v2.6.33.zip

    Smarty是一个流行的PHP模板引擎,它的版本2.6.33是该软件的一个特定迭代。...这个压缩包“Smarty v2.6.33....通过研究和使用这个压缩包中的文件,开发者和学习者可以提升自己的Web开发技能,同时了解软件工具的演变历程。

    Android和Linux内核版本对应关系

    - **备注**: 移除了Android代码的Linux Kernel 2.6.33版代码库。 ##### 8. Honeycomb (蜂巢) - **Android系统版本**: 3.0 - **发布时间**: 2011年2月2日 - **Linux Kernel内核版本**: 2.6.36 - **备注**: 专门针对...

Global site tag (gtag.js) - Google Analytics