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

OK6410的linux的LED驱动,GPIO驱动

2013-04-06 16:30 435 查看
Ok6410开发板LED连接:

4个LED分别连接到核心板上的GPM端:

目前4个LED对应的端口:

GPM0->LED1  GPM1->LED2 GPM2->LED3  GPM3->LED4

查看s3c6410芯片手册,端口M对应的三个寄存器地址:



对应控制寄存器GPMCON设置相应的位,将端口设置为输出:

再对寄存器GPMDAT对应的位写入0/1即可控制LED的点亮与熄灭:

以上是原理部分,下面开工写代码,。

驱动代码可以在linux的源代码树里添加编写也可以另外在单独的目录里编写,第一种方法比较直观,并可以用内核的图形配置界面进行配置,但是需要修改相应的Mkaefile和Kconfig文件,这里为了尽量不破坏源代码的结构,也为了更好的移植采用第二种办法,另起炉灶,但是仍需要借助内核的源代码。

 #include <linux/module.h>

#include <linux/kernel.h>
#include <linux/fs.h>
#include <asm/uaccess.h> /* copy_to_user,copy_from_user */
#include <linux/miscdevice.h>
#include <linux/pci.h>
#include <mach/map.h>
#include <mach/regs-gpio.h>
#include<mach/gpio-bank-m.h> //此文件是GPM对应的寄存器地址等的定义
#include <plat/gpio-cfg.h>

#define LED_MAJOR 240

int led_open (struct inode *inode,struct file *filp)

{
unsigned tmp;
tmp =readl(S3C64XX_GPMCON);
tmp = (tmp &~(0x7U<<1))|(0x1U);
writel(tmp,S3C64XX_GPMCON);
printk("#########open######\n");
return 0;
}

ssize_t led_read (struct file *filp, char __user *buf, size_t count,loff_t*f_pos)
{
printk("#########read######\n");
return count;
}

ssize_t led_write (struct file *filp, const char __user *buf, size_tcount,loff_t *f_pos)
{
char wbuf[10];
unsigned tmp;
printk("#########write######\n");
copy_from_user(wbuf,buf,count);
switch(wbuf[0])
{
case 0: //off
tmp =readl(S3C64XX_GPMDAT);
tmp |= (0x1U);
writel(tmp, S3C64XX_GPMDAT);
break;
case 1: //on
tmp =readl(S3C64XX_GPMDAT);
tmp &= ~(0x1U);
writel(tmp, S3C64XX_GPMDAT);
break;
default :
break;
}
return count;
}

int led_release (struct inode *inode, struct file *filp)
{
printk("#########release######\n");
return 0;
}

struct file_operations led_fops ={
.owner = THIS_MODULE,
.open = led_open,
.read = led_read,
.write = led_write,
.release = led_release,
};

int __init led_init (void)
{ int rc;
printk ("Test leddev\n");
rc =register_chrdev(LED_MAJOR,"led",&led_fops);
if (rc <0)
{
printk ("register%s char dev error\n","led");
return -1;
}
printk("ok!\n");
return 0;
}

void __exit led_exit (void)
{
unregister_chrdev(LED_MAJOR,"led");
printk ("moduleexit\n");
return ;
}

module_init(led_init);
module_exit(led_exit);
 

gpio-bank-m.h文件代码树中没有该文件,众里寻他千百度啊,终于在WRT的一个补丁文件中找到了该文件:

在\home\linux-2.6\arch\arm\mach-s3c64xx\include\mach可以自己新建一个gpio-bank-m.h

编写Makefile文件 KDIR为linux内核所在目录

obj-m := driver_led.o
KDIR :=/home/linux-2.6/
all:
make -C $(KDIR) M=$(shellpwd) modules
install:
cp driver_led.ko/nfsroot/
clean:
make -C $(KDIR) M=$(shellpwd) clean

编写测试程序:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main (void)
{
int fd;
char buf[10]={0,1};
fd = open("/dev/my_led",O_RDWR);
if (fd < 0)
{
printf("Open /dev/my_led file error\n");
return -1;
}
while(1)
{
write(fd,&buf[0],1);
sleep(1);
write(fd,&buf[1],1);
sleep(1);
}
close (fd);
return 0;

}


Make生成.ko文件:

arm-linux-gcc  test.c -o  test

    

将以上生成的两个文件拷贝到NFS目录,连接开发板,进行实验

模块儿文件拷贝到/lib/modules/3.2.0-rc7-00022-gd0c9386/目录下,3.2.0-是对应的版本号:

程序可以拷贝到任意目录:

创建设备文件:

mknod  /dev/my_led  c  240  0

加载模块

运行测试程序:

可以看到开发板上第一个LED状态不断变化。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: