×
单片机 > 单片机程序设计 > 详情

dm6441的gpio驱动

发布时间:2020-06-04 发布时间:
|
这是我进入嵌入式行业进公司做的第一个驱动,

平台:Ti   dm6441     linu2.6.18

GPIO是嵌入式系统最简单、最常用的资源了,比如点亮LED,控制蜂鸣器,输出高低电平,检测按键,等等。
由于硬件资源的原因,DM6441并不是GPIO管脚就是纯粹的GPIO脚,GPIO管脚和其他一些标准接口复用相同的引脚,
比如SPI和GPIO复用,I2C和GPIO复用等,到底是使用GPIO还是其他接口,在初始化的时候,都需要对PINMUX0和PINMUX1
两个寄存器进行设置(见DM6441的芯片p72),而软件设置则在Montavista linux-2.6.18_pro500/arch/arm/mach-davinci
目录下mux_cfg.c和对应的include/asm/arch-davinci/mux.h里。由数据手册知道gpio5,6,7默认是gpio功能。

对mux_cfg.c的分析

对MUX_CFG()的参数解释
   第一个是描述(和数据手册p72上要对应),第二个是pinmux0还是1,第三个是寄存器偏移。最后一个和调试有关的,
   倒数第二个就是你需要给pinmux寄存器相应位设置的值,倒数第三个就是pinmux相应位全为1的值(掩码值),
   倒数第四个就是pinmux相应位偏移值。如果你要改变引脚的模式,把对应引脚设置成0,再把其他功能设为1。
  (这是我的理解,参考下面的I2C和GPIO43_44设置)。
#include
#include

#include

#include
#include

#ifdef CONFIG_DAVINCI_MUX

struct pin_config __initdata_or_module davinci_dm644x_pins[] = {

MUX_CFG("HDIREN",   0,   16,    1,   1,  1)
MUX_CFG("ATAEN",   0,   17,    1,   1,  1)

MUX_CFG("MSTK",    1,   9,     1,   0,  0)

MUX_CFG("I2C",    1,   7,     1,   1,  0)

MUX_CFG("MCBSP",   1,   10,    1,   1,  0)

MUX_CFG("PWM0",    1,   4,     1,   1,  0)

MUX_CFG("PWM1",    1,   5,     1,   1,  0)

MUX_CFG("PWM2",    1,   6,     1,   1,  0)

MUX_CFG("VLINQEN",   0,   15,    1,   1,  0)
MUX_CFG("VLINQWD",   0,   12,    3,   3,  0)  //pinmux上面是2位在表示    所以0x11=3  3位就是111=7

MUX_CFG("EMACEN",   0,   31,    1,   1,  1)

MUX_CFG("GPIO3V",   0,   31,    1,   0,  1)

MUX_CFG("GPIO0",   0,   24,    1,   0,  1)
MUX_CFG("GPIO3",   0,   25,    1,   0,  0)
MUX_CFG("GPIO43_44",   1,   7,     1,   0,  0)
MUX_CFG("GPIO46_47",   0,   22,    1,   0,  1)

MUX_CFG("RGB666",   0,   22,    1,   1,  1)

MUX_CFG("LOEEN",   0,   24,    1,   1,  1)
MUX_CFG("LFLDEN",   0,   25,    1,   1,  0)
};

内核里提供的接口在linux-2.6.18_pro500/arch/arm/mach-davinci目录下的gpio.c,这个是寄存器级的驱动。对这个文件的相关操作
见http://blog.csdn.net/langxing0508/archive/2008/12/25/3604043.aspx  达芬奇DM644X平台(ARM9, Linux-2.6.10)BSP之gpio.c浅析
说得不错,这里表示感谢。

下面是我的gpio驱动程序
 

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#include

#include
#include
#include
#include
//#include
#define DEVICE_NAME "dm644x_gpios"  
#define GPIO_MAJOR 199
 

#define ZX_GPIO5         5   
#define ZX_GPIO6         6   
#define ZX_GPIO7         7   
 
static int davinci_dm644x_gpio_open(struct inode *inode, struct file *file)
{
 printk("open gpio,here is driver/n"); 
 const char *tag = NULL;
 int gpio5_value;
 int gpio6_value;
 int gpio7_value;

// gpio_request(ZX_GPIO6, tag);
// gpio_set_value(ZX_GPIO6, 0);
// __gpio_set(ZX_GPIO6, 0);
// printk("%s/n", tag);
 gpio_direction_output(ZX_GPIO5, 0);
 gpio_direction_output(ZX_GPIO6, 0);
 gpio_direction_output(ZX_GPIO7, 0);
 gpio5_value = gpio_get_value(ZX_GPIO5);
 gpio6_value = gpio_get_value(ZX_GPIO6);
 gpio7_value = gpio_get_value(ZX_GPIO7);

 printk("gpio5_value = %d, gpio6_value =%d , gpio7_value = %d/n", gpio5_value, gpio6_value, gpio7_value);
 return 0;
}
 
static int gpio_release(struct inode *inode,struct file *filp)
{
 return 0;
}

[page]
static int davinci_dm644x_gpio_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
  //  const char *tag;
    int   gpio5_value1;
     int   gpio5_value2;
    int   gpio6_value1;
       int   gpio6_value2;
    int   gpio7_value1;
       int   gpio7_value2;
       switch(cmd)
       {
       case 0:     //gpio = 0
    
      
      
           gpio_direction_output(ZX_GPIO5, 0); 
      gpio_direction_output(ZX_GPIO6, 0);
      gpio_direction_output(ZX_GPIO7, 0);
      gpio5_value1 = gpio_get_value(ZX_GPIO5);
      gpio6_value1 = gpio_get_value(ZX_GPIO6);
      gpio7_value1 = gpio_get_value(ZX_GPIO7);
       printk("gpio5_value1 = %d, gpio6_value1 = %d, gpio7_value1 = %d/n", gpio5_value1, gpio6_value1,gpio7_value1);
         //    }
 
              break;
       case 1:            //gpio = 1
              //if(0==arg)
              //{
          // gpio_request(ZX_GPIO5, tag);
          // printk("cmd = 1, ZX_GPIO5= %d/n", ZX_GPIO5);
            gpio_direction_output(ZX_GPIO5, 1); 
       gpio_direction_output(ZX_GPIO6, 1);
       gpio_direction_output(ZX_GPIO7, 1);
       gpio5_value2 = gpio_get_value(ZX_GPIO5);
       gpio6_value2 = gpio_get_value(ZX_GPIO6);
       gpio7_value2 = gpio_get_value(ZX_GPIO7);
      printk("gpio5_value2 = %d, gpio6_value2 =%d, gpio7_value2=%d/n", gpio5_value2, gpio6_value2, gpio7_value2);
              //}
             
              break;
       default:
              return -EINVAL;
       }
}
 

static const struct file_operations davinci_dm644x_gpio_fileops = {
       .owner   = THIS_MODULE,
       .open    = davinci_dm644x_gpio_open,
       .ioctl   = davinci_dm644x_gpio_ioctl,
    .release = gpio_release
};
 
static int __init davinci_dm644x_gpio_init(void)
{
       int ret;
 
       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");

下面是应用程序

#include
#include
#include
#include
 
#define     on     (1)
#define     off    (0)
 
int main(void)
{
      
       int gpio_number = 0;
       int fd;
 


       fd = open("/dev/dm644x_gpios", 0);
       if (fd < 0)
       {
             perror("open device /dev/dm644x_gpios");
             exit(1);
       }
   
   printf("open gpio, here is app/n"); 
   sleep(1);
   printf("gpio_number = %d/n", gpio_number);
   sleep(1);  
    while (1) {  
       ioctl(fd, 1, 0);
    sleep(5);    
    ioctl(fd, 0, gpio_number);
    sleep(5);
        
       close(fd);
       return 0;
}


下面是Makefile
#
# Makefile for the skeleton device drivers.
#

KDIR=/root/work/linux-2.6.18_pro500          # 内核目录
PWD := $(shell pwd)              #是指要编译的内核模块的源程序在哪个目录下,$(PWD)指与Makefile在同一目录下,也就是当前目录。


ifeq ($(KERNELRELEASE), )

modules:
 $(MAKE) -C $(KDIR) M=$(PWD) modules             #编译模块的规则,
 arm_v5t_le-gcc -o gpio_test app.c               #编译应用程序
 cp -f *.ko gpio_test /nfsroot/dm644x/filesys    #把编译好的驱动和应用程序复制到扳子的文件系统中去
 #scp char-reg.ko zlh@192.168.1.160:/home/zlh/opt/filesystem
modules_install:
 $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
clean:                                                              #删除生成的所有文件
 rm -rf gpio_test *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

.PHONY: modules modules_install clean

else
 #obj-m += skeleton_dev_class.o
 obj-m += gpio_driver.o      #你要编译的模块名称,这里必须和$(PWD)目录下C程序文件的名称相对应,如果C程序文件为world.c,那么必须修改成obj-m = world.o,也可
               #Obj-m = hello.o
               #Hello-objs = hello1.o, hello2.o   编译多个文件生成hello.o
endif


直接make 就行了    如果不行的话make ARCH=arm CROSS_COMPILE=arm_v5t_le-   加上编译工具

超级终端操作:
insmod  gpio_drive.ko
mknod  /dev/dm644x_gpios  c  199  0
./gpio_test 



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
ARM 汇编的必知必会