一、             DM6446 GPIO的介绍

     说到LINUX 驱动移植,没有移植过的朋友,或刚刚进入LINUX领域的朋友,最好去看看《LINUX 设备驱动程序》第三版,有个理论或感性的认识。该版本是基于2.6.10的基础上描述的,经典读物,网上有电子版,但是建议花几十元买本书是值得的。
       GPIO是嵌入式系统最简单、最常用的资源了,比如点亮LED,控制蜂鸣器,输出高低电平,检测按键,等等。GPIO分输入和输出,在Montavista linux-2.6.18中,有关GPIO的最底层的寄存器驱动,是在linux-2.6.18_pro500\arch\arm\mach-davinci目录下的gpio.c,这个是寄存器级的驱动,搞过单片机MCU的朋友应该比较熟悉寄存器级的驱动。根据DM6446的芯片DATASHEET,DM6446的GPIO分为3组BANK,BANK01组包括GPIO0~GPIO31,BANK23组包括GPIO32~GPIO63,BANK45组包括GPIO64~GPIO70,由于硬件资源的原因,DM6446并不是GPIO管脚就是纯粹的GPIO脚,GPIO管脚和其他一些标准接口复用相同的引脚,比如SPI和GPIO复用,I2C和GPIO复用等,到底是使用GPIO还是其他接口,在初始化的时候,都需要对PINMUX0和PINMUX1两个寄存器进行设置(见DM6446的芯片DATASHEET第3章),而软件设置则在Montavista linux-2.6.18_pro500\arch\arm\mach-davinci目录下mux_cfg.c和对应的mux.h里。本人这里使用GPIO10、GPIO12、GPIO28,分别对应控制BUZZER、LED1、LED0,所以不需要对mux_cfg.c和mux.h进行修改。我们把这些GPIO应用归入linux字符设备来移植。
 
二、GPIO源码移植分析
 
/* drivers/char/davinci_dm644x_gpios.c*/
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/types.h>
#include <linux/cdev.h>
 
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/arch/hardware.h>
#include <asm/arch/gpio.h>
 
#define DEVICE_NAME "dm644x_gpios"   /*定义设备驱动的名字,或设备节点名称*/
#define GPIO_MAJOR 199 /*使用 cat /proc/devices查看不要和存在的char节点重复*/
 
/*my app gpio define*/
#define DM644X_GPIO_BUZZER             10    /*GPIO10*/
#define DM644X_GPIO_LED1           12    /*GPIO10*/
#define DM644X_GPIO_LED0           28    /*GPIO10*/
 
static int davinci_dm644x_gpio_open(struct inode *inode, struct file *file)
{
    return 0;/*该函数可以什么都不做,也可以加入类似初始化的设置*/
}
 
static int davinci_dm644x_gpio_ioctl(
       struct inode *inode,
       struct file *file,
       unsigned int cmd,
       unsigned long arg)
{
       switch(cmd) /*cmd 表示应用程序传入的led动作,是on 还是off*/
       {
       case 0:     //gpio = 0
              if(0==arg) /*arg由自己硬件电路决定使用那些GPIO*/
              {
                     gpio_direction_output(DM644X_GPIO_LED0, 0);/*调用TI linux-2.6.18寄存器驱动*/
              }
              else if(1==arg)
              {
                     gpio_direction_output(DM644X_GPIO_LED1, 0);
              }
              else if(2==arg)
              {
                     gpio_direction_output(DM644X_GPIO_BUZZER, 0);
              }
              else
              {
                     return -EINVAL;
              }
              break;
       case 1:            //gpio = 1
              if(0==arg)
              {
                     gpio_direction_output(DM644X_GPIO_LED0, 1);
              }
              else if(1==arg)
              {
                     gpio_direction_output(DM644X_GPIO_LED1, 1);
              }
              else if(2==arg)
              {
                     gpio_direction_output(DM644X_GPIO_BUZZER, 1);
              }
              else
              {
                     return -EINVAL;
              }
              break;
       default:
              return -EINVAL;
       }
}
 
/*定义驱动设备文件API,在linux系统当中,任何设备都可以当做文件的方式操作,这一点和单片机和MCU有很大差别*/
static const struct file_operations davinci_dm644x_gpio_fileops = {
       .owner   = THIS_MODULE,
       .open    = davinci_dm644x_gpio_open,
       .ioctl       = davinci_dm644x_gpio_ioctl,
};
 
static int __init davinci_dm644x_gpio_init(void) /*内核初始化会调用该函数*/
{
       int ret;
 
       gpio_direction_output(DM644X_GPIO_LED0, 1);     //led0 is on
udelay(1);
       gpio_direction_output(DM644X_GPIO_LED1, 1);     //led1 is on
udelay(1);
       gpio_direction_output(DM644X_GPIO_BUZZER, 1);       //BUZZER is on
mdelay(500); /*初始化时,buzzer 发出声音500ms*/
       gpio_direction_output(DM644X_GPIO_BUZZER, 1);       //BUZZER is off
 
       ret = register_chrdev(GPIO_MAJOR, DEVICE_NAME, &davinci_dm644x_gpio_fileops);
       if(ret < 0)
       {
              printk(DEVICE_NAME " register falid!\n");
              return ret;
       }
 
       printk (DEVICE_NAME" initialized\n");
 
       return ret;
}
 
static void __exit davinci_dm644x_gpio_exit(void)
{
       unregister_chrdev(GPIO_MAJOR, DEVICE_NAME);
}
 
module_init(davinci_dm644x_gpio_init);
module_exit(davinci_dm644x_gpio_exit);
 
MODULE_AUTHOR("xxx <>");
MODULE_DESCRIPTION("Davinci DM644x gpio driver");
MODULE_LICENSE("GPL");
 
这个驱动源码是一种比较老的驱动移植,即register_chrdev(GPIO_MAJOR, DEVICE_NAME, &davinci_dm644x_gpio_fileops),静态分配设备节点,适合linux-2.4.x和linux-2.6.10前的版本,当然也可以在2.6.18及以后的版本使用,现在新的版本char字符设备的移植可以参考davinci_resizer.c、davinci_previewer.c等文件。
上面的初始化函数调用udelay和msdelay,udelay一般适用于一个比较小的delay,如果你填的数大于2000,系统会认为你这个是一个错误的delay函数,因此如果需要2ms以上的delay需要使用mdelay函数。
由于这些delay函数本质上都是忙等待,对于长时间的忙等待意味这无谓的耗费着cpu的资源,因此对于毫秒级的延时,内核提供了msleep,ssleep等函数,这些函数将使得调用它的进程睡眠参数指定的时间。
寄存器级的驱动gpio_direction_output()函数是定义在linux-2.6.18_pro500/arch/arm/mach-davinci/下的gpio.c里,里边还有gpio_direction_input()和GPIO中断函数。
 
三、修改内核配置文件
 
在linux-2.6.18_pro500/drivers/char目录下,
修改Kconfig文件,在menu "Character devices"下面,加入
 
config DAVINCI_DM644X_GPIOS
       tristate "Davinci DM644x GPIO GPIOs"
       depends on ARCH_DAVINCI
       help
        This option enables support for LEDs and Buzzer connected to GPIO lines
        on Ti Davinci DM644x CPUs, such as the DM6446。
修改Makefile文件,在128行
obj-$(CONFIG_DAVINCI_DM646X_TSIF)       += tsif_control.o tsif_data.o下面,加入:
obj-$( DAVINCI_DM644X_GPIOS) += davinci_dm644x_gpios.o
 
修改linux-2.6.18 内核menu配置
选上“Character devices”里的“Davinci DM644x GPIOs”,保存修改后的配置,然后make uImage,对内核的编译;
 
四、GPIO应用程序源码
 
    源码添加:
/* dm644x_gpio_test.c*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
 
/* ./dm644x_gpio_test 0 1 */ //led0 on
/* ./dm644x_gpio_test 0 0 */ //led0 off
/* ./dm644x_gpio_test 1 1 */ //led1 on
/* ./dm644x_gpio_test 1 0 */ //led1 off
/* ./dm644x_gpio_test 2 1 */ // buzzer on
/* ./dm644x_gpio_test 2 0 */ // buzzer off
 
int main(int argc, char **argv)
{
       int on;
       int gpio_number;
       int fd;
       // argv[0]== dm644x_gpio_test
    // argv[1]== gpio_number
    // argv[1]== on
       if (argc != 3 || sscanf(argv[1], "%d", &gpio_number) != 1 || sscanf(argv[2],"%d", &on) != 1 ||on < 0 || on > 1 || gpio _number < 0 || gpio _number > 3)
       {
              fprintf(stderr, "Usage:\n");
              fprintf(stderr, "\t dm644x_gpio_test  gpio_number on|off\n");
              fprintf(stderr, "Options:\n");
              fprintf(stderr, "\t gpio_number from 0 to 2\n");
              fprintf(stderr, "\t on 1   off 0\n");
              exit(1);
       }
       fd = open("/dev/dm644x_gpios", 0);
       if (fd < 0)
       {
      
             perror("open device /dev/dm644x_gpios");
             exit(1);
      
       }
       ioctl(fd, on, gpio_number);
       close(fd);
       return 0;
}
 
Makefile添加:
#application makefile for dm644x gpio test
CROSSCOMPILE = arm_v5t_le-
CC=$(CROSSCOMPILE)gcc
LD=$(CROSSCOMPILE)ld
OBJCOPY=$(CROSSCOMPILE)objcopy
OBJDUMP=$(CROSSCOMPILE)objdump
INCLUDE = /home/user/linux-2.6.18_pro500/include/*指向你的内核include*/
 
all: dm644x_gpio_test
 
dm644x_gpio_test: dm644x_gpio_test.c
       $(CROSSCOMPILE)gcc -Wall -O2 dm644x_gpio_test.c -I $(INCLUDE) -o dm644x_gpio_test
       $(CROSSCOMPILE)strip dm644x_gpio_test
       cp -f dm644x_gpio_test /home/user/nfs/target/opt/app/
clean:
       @rm -vf dm644x_gpio_test *.o *~
 
五、文件系统节点添加
        文件系统里,/etc/init.d/rcS文件
         # Run /etc/rc.d/rc.local if it exists
         [ -x /etc/rc.d/rc.local ] && /etc/rc.d/rc.local
        前面加mknod /dev/dm644x_gpios c 199 0或在shell命令行下执行mknod /dev/dm644x_gpios c 199 0;这就是静态分配设备节点的做法。
       运行系统,进入shell命令下,
     #cd / opt/app/
     #./ dm644x_gpio_test 0 1可以控制点亮LED0
     等等,有平台的朋友可以试试。
 
六、总结

本人拿一个比较简单的设备驱动移植的例子来讲解,目的让大家理解davinci dm6446系统架构。由于时间仓促,以上可能会有不完善的地方,还请各位网友指点。Davinci dm6446 开发攻略到本章节,基本上一个完整的DM6446系统的框架基本介绍完了,感谢各位网友的支持,dm6446 开发攻略的文章也接近尾声。由于很长一段时间忙着给购买我们产品的客户搭建开发环境、codec环境,开发驱动,调试3G产品等等,所以更新博客的速度放慢下来,毕竟客户的要求才是最重要的。同时也赶在51CTO 5周年纪念日到来之前,结束DM6446开发攻略的主体文章,算是告一个段落,以便为51CTO 5周年纪念写篇感想文章做好铺垫,毕竟来这个圈子也快一年了,有些东西总是需要总结的。

Davinci DM6446开发攻略——LINUX GPIO驱动源码移植的更多相关文章

  1. TI Davinci DM6446开发攻略——根文件系统的裁剪和移植

    一.补充文件系统知识 Linux根文件系统是存放tool软件.lib文件.script(脚本).配置文件.其他特殊文件.自己开发的应用程序的地方.嵌入式linux的根文件系统rootfs就像windo ...

  2. DAVINCI DM6446 开发攻略——V4L2视频驱动和应用分析

     针对DAVINCI DM6446平台,网络上也有很多网友写了V4L2的驱动,但只是解析Montavista linux-2.6.10 V4L2的原理.结构和函数,深度不够.本文决定把Montavis ...

  3. Davinci DM6446开发攻略——u-boot-1.3.4移植(1)

    UBOOT的版本更新速度比较快,截止今天,稳定正式的版本是u-boot-2009.11-rc2,而TI最新的EVM开发包里的UBOOT是1.2.0版本,国内很多公司还一直使用u-boot-1.1.4和 ...

  4. Davinci DM6446开发攻略-UBOOT-2009.03移植2 nand flash的烧写

      很长一段时间没有更新博客了,是因为要推出新开发方案和做好客户服务工作,忙得不易乐乎.有关DAVINCI U-BOOT的移植,以前写过一篇u-boot-1.3.4(2008年的),其实和这个u-bo ...

  5. Davinci DM6446开发攻略——linux-2.6.18移植

     TI DAVINCI 使用最新的内核是montavista linux-2.6.18,之前说过,国内很多公司,包括开发板的软件包,一直在使用montavista linux-2.6.10,这个版本准 ...

  6. TI Davinci DM6446开发攻略——开发环境搭建

    TI DAVINCI DM6446的开发环境搭建不像三星S3C2410,S3C2440,ATMEL的AT91SAM9260之类的单核ARM那么简单,因为DM6446还有DSP端的开发环境,以及双核之间 ...

  7. Davinci DM6446开发攻略——DSP开发工程建立

    前段时间一直忙一个项目,同时在生活上时时提防和抵抗中国地沟油.国外核心转基因调和油.大豆油.色拉油.大米玉米.可怕的喂药鱼.药水泡农药喷无虫咬的青菜,所以没时间打理自己的博客,让开发攻略停顿了一段时间 ...

  8. TI Davinci DM6446开发攻略——UBL移植

     UBL的程序设计,相对UBOOT.KERNEL.ROOTFS.设备驱动.DSP开发来说,还是比较简单.我们先从DAVINCI的启动说起,了解UBL在DAVIN系统中的位置和作用.对于固件程序烧写在N ...

  9. DM6446开发攻略——u-boot-1.3.4移植(1)

    http://zjbintsystem.blog.51cto.com/964211/282387转载   UBOOT的版本更新速度比较快,截止今天,稳定正式的版本是u-boot-2009.11-rc2 ...

随机推荐

  1. Bom部分

    Bom部分  browser object model(浏览器对象模型)将浏览器中的各个组件封装成对象,我们可以使用这些对象来操作浏览器的一些动作.封装的规则基于ECMAScriptBom的组成--— ...

  2. java的优势解读

    1. java确定每种基本类型所占存储空间的大小.它们的大小不会像大多数语言那样随机器硬件架构的变化而变化.这种所占存储空间大小的不变性是java程序比用其他大多数语言编写的程序更具有可移植性的原因之 ...

  3. windows程序设计获取文本框(窗口、对话框)文本

    就是这样一个简单的界面,窗口上重绘的对话框(这种写法参考我之前博文): 需要做到的就是点击确定,获取文本框中内容. // 处理对话框消息 INT_PTR CALLBACK NewDlgProc(HWN ...

  4. 配置apache使之支持浏览器端的缓存

    当直接在浏览器中输入一个URL,或者点击一个链接的时候,那么浏览器缓存就会起作用,如果缓存没有过期,那么浏览器会从本地读取资源,不会发起HTTP请求,如果缓存过期,那么浏览器会发起新的浏览器请求. 一 ...

  5. iis发布网站问题-由于权限不足而无法读取配置文件,无法访问请求的页面

    错误一: HTTP Error 500.19 - Internal Server Error 配置错误: 不能在此路径中使用此配置节.如果在父级别上锁定了该节,便会出现这种情况.锁定是默认设置的 (o ...

  6. c++类的基础

    1.抽象: 抽象出公有特性,包括公有动作,公有数据. 2.类:类是具有相同属性和行为的一组对象的集合(变量和函数) 声明格式: class 类名(Dog) { 类体:(数据和函数成员)默认为私有成员, ...

  7. 模板方法模式和JDBCTemplate(一)

    本篇博客的目录: 一:模板方法模式介绍 二:模板方法模式的简单实现 三:总结 一:模板方法模式的介绍 1.1:模板方法模式的定义 定义:一个操作中的算法的骨架,而将一些步骤延迟到子类中.Templat ...

  8. filezilla server客户端FTP连接不上解决

    windows服务器上安装Filezilla server后,本地客户端连接不上.解决办法: 1.在防火墙把filezilla的 Filazilla server interface.exe 和Fil ...

  9. unity爬坑记录

    这里记一下平时遇到的unity bug: unity2017最好不要在prefab上面修改它上面的组件参数 最好是拖放到场景之后修改场景内的物体组件参数 完事了apply一下删掉 不这样做的话 可能u ...

  10. Android Native App自动化测试实战讲解(上)(基于python)

    1.Native App自动化测试及Appuim框架介绍 android平台提供了一个基于java语言的测试框架uiautomator,它一个测试的Java库,包含了创建UI测试的各种API和执行自动 ...