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的电平变换。至此,驱动完成。
内核版本: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的电平变换。至此,驱动完成。
相关文章推荐
- zynq平台实现linux gpio驱动
- linux下 PCI驱动实现
- 驱动移植pcDuino的linux移植五gpio驱动开发
- Davinci DM6446开发攻略——LINUX GPIO驱动源码移植
- Linux kernel驱动相关抽象概念及其实现 之“linux设备模型kobject,kset,ktype”
- WinCE流设备驱动简介及GPIO驱动的实现
- Linux 内核设备驱动之GPIO驱动之GPIO 框架初始化
- Linux I2C驱动分析与实现(二)
- 如何实现Linux下的U盘(USB Mass Storage)驱动
- linux设备驱动总线模型实现
- linux 标准GPIO 驱动模型—version1
- linux驱动开发之输入子系统编程(一)使用工作队列实现中断下半部
- 手把手教你从零实现Linux misc设备驱动一(基于友善之臂4412开发板)
- linux驱动学习笔记1(简单实现open,read,write,ioctl)
- 45 超声波测距模块的linux platform驱动模型实现
- OpenRisc-18-or1200下linux简单gpio字符设备驱动
- Linux 驱动学习笔记05--字符驱动实例,实现一个共享内存设备的驱动
- WinCE流设备驱动简介及GPIO驱动的实现
- Linux驱动总结3- unlocked_ioctl和堵塞(waitqueue)读写函数的实现
- linux中触摸屏驱动的实现(1)——基于s3c6410处理器