您的位置:首页 > 运维架构 > Linux

AM3715/DM3730 GPIO驱动的实现(linux)

2013-10-11 10:56 375 查看
初学AM3715,折腾了几天,才搞定GPIO,网上找了很多资料,没有特别全的,我把我实现的驱动贴出来,供像我一样的初学者参考。

内核版本:linux2.6.32 (开发板自带)

开发板型号:英码SBC-3715 

交叉工具连:arm-none-linux-gnueabi-gcc version 4.3.3 (Sourcery G++ Lite 2009q1-203) (开发板自带)

先介绍一下文件结构:

驱动部分:

gpio_3715.c

Makefile (在内核外部编译,所以需要Makefile,指定内核路径信息)

make.sh (自己写的make执行命令,主要是执行命令的时候输入平台信息和工具链信息)

APP部分:

app_3715_gpio.c
测试程序,每3秒gpio10电平变换一次,死循环

Makefile
(指定编译器,生成可执行程序)

驱动实现功能:

实现gpio10引脚的输出功能,可控制。应用测试程序中做具体控制。

以下是文件内容:

—————————————————————————————————————————————————————————————————————————————

//gpio_3715.c(驱动文件)

#include <linux/i2c.h>

#include <linux/delay.h>

#include <linux/gpio.h>

#include <media/v4l2-common.h>

#define GPIO_MAJOR
251

#define DEVICE_NAME
"gpio_3715"

//---------------------------------------------------------------------------------------------------------------

static int gpio_open(struct inode *inode,struct file *file)

{

        printk("gpio 3715 open successfully !\n");

        return 0;

}

//-----------------------------------------------------------------------------------------------------------------

static int gpio_close(struct inode *inode,struct file *file)

{
gpio_free(10);

        printk("gpio 3715 release successfully !\n");
return 0;

}

//---------------------------------------------------------------------------------------------------------------

static ssize_t  gpio_read(struct file *file,char __user *buf, size_t count,loff_t *offset)

{

                int i;

                i = gpio_get_value(10);

                if(1 == i)

                        copy_to_user("HIGH",buf,sizeof(buf));

                else

                        copy_to_user("LOW",buf,sizeof(buf));

                return 0;

}

//------------------------------------------------------------------------------------------------------------------

static int gpio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)

{
int ret = -1;

ret = gpio_request(10,"enable gpio10");  
//request gpio 10

printk("request back code is %d\n",ret);

ret = -1 ;

        ret = gpio_direction_output(10,1);
printk("output set back code is %d\n",ret);

        
switch(cmd)

        {

                case 0:

                        printk("success0\n");

                        gpio_set_value(10,0);

                        return 0;

                case 1:

                        printk("success1\n");

                        gpio_set_value(10,1);

                        return 0;

                default:

                        printk("No operations!\n");

                        return -1;

        }

}

//-----------------------------------------------------------------------------------------------------------------

static const struct file_operations gpio_ops = {

        .owner = THIS_MODULE,

        .open = gpio_open,

        .read = gpio_read,
.ioctl = gpio_ioctl, 
.release = gpio_close,

};

//--------------------------------------------------------------------------------------------------------------

static struct cdev omap3715_gpio_cdev;

static int __init omap3gpio_init(void)

{
dev_t dev;

        int ret = 0;
unsigned int reg_data;
unsigned int *core_addr ;

printk("Registering GPIO_3715 Device...\n------>\n");

core_addr = ioremap(0x48002A18,4);

__raw_writel(0x00040000,core_addr); 

gpio_request(10, "enable gpio10");
gpio_direction_output(10, 0);
gpio_set_value(10, 1);

dev = 0 ;
dev = MKDEV(GPIO_MAJOR,0);

        ret = register_chrdev_region(dev,1,DEVICE_NAME);                

        if(ret < 0)

        {

                printk(KERN_WARNING"gpio register_chrdev faild\n");

                return ret;

        }

        printk(KERN_WARNING"gpio register_chrdev success, major = %d\n", ret);

cdev_init(&omap3715_gpio_cdev,&gpio_ops);
omap3715_gpio_cdev.ops = &gpio_ops ;
omap3715_gpio_cdev.owner = THIS_MODULE ;

ret = cdev_add(&omap3715_gpio_cdev,dev,1);

printk("gpio_3715 is installed ! \n");

        return 0;

}

//---------------------------------------------------------------------------------------------------------------------

static void __exit omap3gpio_exit(void) 

{
unregister_chrdev_region(MKDEV(GPIO_MAJOR,0),1);
cdev_del(&omap3715_gpio_cdev);
printk("you have uninstalled the gpio_3715 .\n");

}        

module_init(omap3gpio_init);

module_exit(omap3gpio_exit);

MODULE_AUTHOR("Seed txyugood");

MODULE_DESCRIPTION("omap3gpio  driver");

MODULE_LICENSE("GPL");

____________________________________________________________________________________________________________________________________

// Makefile(驱动部分)

KERNELDIR = /3715/linux/source/linux-03.00.01.06/

PWD := $(shell pwd) 

all:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules      

obj-m := gpio_3715.o

clean:
rm -rf *.o *.order *.mod.* *.symvers 

distclean:
rm -rf *.o *.ko *.order *.mod.* *.symvers

—————————————————————————————————————————————————————————————————————————————

// make.sh(驱动部分编译命令脚本)

#!/bin/bash

make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-

make clean

—————————————————————————————————————————————————————————————————————————————

//app_3715_gpio.c (测试程序)

#include <stdio.h>

#include <stdlib.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <linux/input.h>

#include <unistd.h>

#include <sys/ioctl.h>

#define IOCLEAR  0

#define IOWRITE 1

#define NOKEY 0

int main(int argc, char *argv[])

{
int i, fd; 
printf("\nstart  gpio_3715 test\n\n");

fd = open("/dev/gpio_3715", O_RDWR);
printf("fd = %d\n",fd);

if(fd==-1)
{

        printf("can not open gpio_3715 device\n");
}  
else
{

        while(1)

        { 

            ioctl(fd,0);
    sleep(3);

            ioctl(fd,1);      
  sleep(3);

        }

      }

close(fd);

return 0;

}

—————————————————————————————————————————————————————————————————————————————

// Makefile (应用程序)

#CC = /usr/local/arm/4.2.2-eabi/usr/bin/arm-linux-gcc

CC = arm-none-linux-gnueabi-gcc

#CFLAGS= -I/home/urbetter-linux2.6.28-v1.0/kernel/include -Wall

#CFLAGS= -I/home/fang/linux/linux_kernel/linux2.6.28/kernel/urbetter-linux2.6.28-v1.0/include -Wall

CFLAGS= -I/3715/linux/source/linux-03.00.01.06/include -Wall

app_3715_gpio:app_3715_gpio.c
$(CC) -o app_3715_gpio app_3715_gpio.c

clean:
rm -f *.o app_3715_gpio

—————————————————————————————————————————————————————————————————————————————

编译好驱动和应用程序后,分别得到gpio_3715.ko和app_3713_gpio ,

(1) 将gpio_3715.ko利用insmod命令加载进内核:

insmod gpio_3715.ko

如果加载成功,会提示成功信息。

(2) 创建设备

mknod gpio_3715 c 251 0

(3) 改变应用程序权限并执行

chmod 777 app-3715_gpio  

./app-3715_gpio

最后,通过万用表或者示波器测量gpio10,会出现每3s的电平变换。至此,驱动完成。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息