S5PV210(TQ210)学习笔记——LED驱动
2015-09-06 00:00
274 查看
摘要: 在天嵌的TQ210开发板上按照天嵌提供的说明书把uboot,内核,文件系统都做好后,今天尝试写一个led的驱动。
1、看电路图,找到led连接哪个引脚。由图可见,开发板上的两个led分别连接在GPC0_3和GPC0_4的两个引脚上。
2、打开s5pv210的芯片手册,搜索一下GPC0CON[4]在2-48页找到GPC0CON的地址为 :Address = 0xE020_0060,下面还有GPC0DAT的地址为: Address = 0xE020_0064
有图可以看出s5pv210不同于2440,s5pv210每个引脚由4位来配置,我们要把GPC0CON[4]、GPC0CON[3]这两个引脚配置成输出(Output)。
3、接下来就可以写驱动程序了:
*******************led_drv.c***********************
include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//device_create(),class_create()的头文件
#include
//定义出这两寄存器
volatile unsigned long *gpc0con = NULL;
volatile unsigned long *gpc0dat = NULL;
//volatile struct unsigned long *gpc1con = NULL;
static struct class *leddrv_class;
int major;
static int led_drv_open(struct inode *inode, struct file *file)
{
printk("liu guo feng open led_drvn");
/*配置GPC1 3 4为输出引脚*/
//寄存器清0
*gpc0con &= ~((0xf<<(3*4)) | (0xf<<(4*4)));
//*gpc1con = 0x00000000;
//设置为输出引脚
*gpc0con |= ((0x1<<(3*4)) | (0x1<<(4*4)));
return 0;
}
static ssize_t led_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
int val;
//用户空间向内核空间传递数据
copy_from_user(&val, buf, count);//内核空间向用户空间传递数据copy_to_user
printk("val=%dn",val);
if(val == 1)
{
//点灯
*gpc0dat |= ((1<<3) | (1<<4));
// *gpc1dat = 0xff;
printk("led onn");
}
else
{
//灭灯
*gpc0dat &= ~((1<<3) | (1<<4));
// *gpc1dat |= ((1<<3) | (1<<4));
//*gpc1dat = 0xff;
printk("led offn");
}
//printk("liu guo feng write led_drvn");
return 0;
}
//定义了这样的一个结构
static struct file_operations led_drv_fops = {
.owner = THIS_MODULE, //这是一个宏
.open = led_drv_open,
.write = led_drv_write,
};
//入口函数
int led_drv_init(void)
{
major = register_chrdev(0, "led_drv", &led_drv_fops);
//在sys的目录下会创建一个leddrv目录
leddrv_class = class_create(THIS_MODULE, "leddrv");
//在leddrv目录下创建xyz,里面有主、次设备号,而mdev会动态地在创建/dev/xyz
device_create(leddrv_class, NULL, MKDEV(major, 0), NULL, "led"); /* /dev/led*/
//把物理地址映射成虚拟地址
gpc0con = (volatile unsigned long *)ioremap(0xE0200060,16);
//gpc0dat = (volatile unsigned long *)ioremap(0xE0200064,16);
gpc0dat = gpc0con + 1;
return 0;
}
void led_drv_exit(void)
{
unregister_chrdev(major, "led_drv");
//对应的卸载
device_destroy(leddrv_class,MKDEV(major, 0));
class_destroy(leddrv_class);
//取消映射
iounmap(gpc0con);
}
module_init(led_drv_init);
module_exit(led_drv_exit);
MODULE_LICENSE("GPL");
******************Makefile*********************************
KERN_DIR = /opt/EmbedSky/TQ210/Kernel_2.6.35.7_TQ210_for_Linux_v1.1
all:
make -C $(KERN_DIR) M=`pwd` modules
clean:
make -C $(KERN_DIR) M=`pwd` modules clean
rm -rf modules.order
obj-m += led_drv.o
*********************************************************
上面的KERN_DIR = /opt/EmbedSky/TQ210/Kernel_2.6.35.7_TQ210_for_Linux_v1.1是内核的路径
把上面两个文件复制到linux下,执行make命令就可以生成led_drv.ko的驱动文件
下面还要写一个测试文件:
***********************leddrvtest.c*********************************
#include
#include
#include
#include
/*
leddrvtest on
leddrvtest off
*/
int main(int argc,char **argv)
{
int fd;
int val = 1;
fd = open("/dev/led",O_RDWR);
if(fd < 0)
printf("can't open!n");
//传进来的参数个数argc
if(argc !=2)
{
printf("Usage:n");
printf("%s
return 0;
}
if( strcmp(argv[1],"on") == 0)
{
val=1;
}
else
{
val = 0;
}
write(fd, &val, 4);
return 0;
}
************************************************
把leddrvtest.c复制到linux下。
执行arm-linux-gcc -o leddrvtest leddrvtest.c 就可以生成leddrvtest的测试文件
把led_drv.ko和leddrvtest复制到开发板的根文件系统下,
我的开发板已经使用NFS挂载根文件系统。连接好后给开发板上电。
在开发板上执行insmod led_drv.ko添加驱动。
执行./leddrvtest on 灯打开了。
执行./leddrvtest off 灯关闭了。
1、看电路图,找到led连接哪个引脚。由图可见,开发板上的两个led分别连接在GPC0_3和GPC0_4的两个引脚上。
2、打开s5pv210的芯片手册,搜索一下GPC0CON[4]在2-48页找到GPC0CON的地址为 :Address = 0xE020_0060,下面还有GPC0DAT的地址为: Address = 0xE020_0064
有图可以看出s5pv210不同于2440,s5pv210每个引脚由4位来配置,我们要把GPC0CON[4]、GPC0CON[3]这两个引脚配置成输出(Output)。
3、接下来就可以写驱动程序了:
*******************led_drv.c***********************
include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//device_create(),class_create()的头文件
#include
//定义出这两寄存器
volatile unsigned long *gpc0con = NULL;
volatile unsigned long *gpc0dat = NULL;
//volatile struct unsigned long *gpc1con = NULL;
static struct class *leddrv_class;
int major;
static int led_drv_open(struct inode *inode, struct file *file)
{
printk("liu guo feng open led_drvn");
/*配置GPC1 3 4为输出引脚*/
//寄存器清0
*gpc0con &= ~((0xf<<(3*4)) | (0xf<<(4*4)));
//*gpc1con = 0x00000000;
//设置为输出引脚
*gpc0con |= ((0x1<<(3*4)) | (0x1<<(4*4)));
return 0;
}
static ssize_t led_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
int val;
//用户空间向内核空间传递数据
copy_from_user(&val, buf, count);//内核空间向用户空间传递数据copy_to_user
printk("val=%dn",val);
if(val == 1)
{
//点灯
*gpc0dat |= ((1<<3) | (1<<4));
// *gpc1dat = 0xff;
printk("led onn");
}
else
{
//灭灯
*gpc0dat &= ~((1<<3) | (1<<4));
// *gpc1dat |= ((1<<3) | (1<<4));
//*gpc1dat = 0xff;
printk("led offn");
}
//printk("liu guo feng write led_drvn");
return 0;
}
//定义了这样的一个结构
static struct file_operations led_drv_fops = {
.owner = THIS_MODULE, //这是一个宏
.open = led_drv_open,
.write = led_drv_write,
};
//入口函数
int led_drv_init(void)
{
major = register_chrdev(0, "led_drv", &led_drv_fops);
//在sys的目录下会创建一个leddrv目录
leddrv_class = class_create(THIS_MODULE, "leddrv");
//在leddrv目录下创建xyz,里面有主、次设备号,而mdev会动态地在创建/dev/xyz
device_create(leddrv_class, NULL, MKDEV(major, 0), NULL, "led"); /* /dev/led*/
//把物理地址映射成虚拟地址
gpc0con = (volatile unsigned long *)ioremap(0xE0200060,16);
//gpc0dat = (volatile unsigned long *)ioremap(0xE0200064,16);
gpc0dat = gpc0con + 1;
return 0;
}
void led_drv_exit(void)
{
unregister_chrdev(major, "led_drv");
//对应的卸载
device_destroy(leddrv_class,MKDEV(major, 0));
class_destroy(leddrv_class);
//取消映射
iounmap(gpc0con);
}
module_init(led_drv_init);
module_exit(led_drv_exit);
MODULE_LICENSE("GPL");
******************Makefile*********************************
KERN_DIR = /opt/EmbedSky/TQ210/Kernel_2.6.35.7_TQ210_for_Linux_v1.1
all:
make -C $(KERN_DIR) M=`pwd` modules
clean:
make -C $(KERN_DIR) M=`pwd` modules clean
rm -rf modules.order
obj-m += led_drv.o
*********************************************************
上面的KERN_DIR = /opt/EmbedSky/TQ210/Kernel_2.6.35.7_TQ210_for_Linux_v1.1是内核的路径
把上面两个文件复制到linux下,执行make命令就可以生成led_drv.ko的驱动文件
下面还要写一个测试文件:
***********************leddrvtest.c*********************************
#include
#include
#include
#include
/*
leddrvtest on
leddrvtest off
*/
int main(int argc,char **argv)
{
int fd;
int val = 1;
fd = open("/dev/led",O_RDWR);
if(fd < 0)
printf("can't open!n");
//传进来的参数个数argc
if(argc !=2)
{
printf("Usage:n");
printf("%s
return 0;
}
if( strcmp(argv[1],"on") == 0)
{
val=1;
}
else
{
val = 0;
}
write(fd, &val, 4);
return 0;
}
************************************************
把leddrvtest.c复制到linux下。
执行arm-linux-gcc -o leddrvtest leddrvtest.c 就可以生成leddrvtest的测试文件
把led_drv.ko和leddrvtest复制到开发板的根文件系统下,
我的开发板已经使用NFS挂载根文件系统。连接好后给开发板上电。
在开发板上执行insmod led_drv.ko添加驱动。
执行./leddrvtest on 灯打开了。
执行./leddrvtest off 灯关闭了。
相关文章推荐
- Day01 准备工作
- linux 中断处理(基于linux-3.7.2 arm linux)
- TQ210裸机编程(2)——按键(查询法
- BL1校验和
- S5PV210启动过程详解
- (二)S5pv210的GPIO使用_part1<LED汇编版>
- (一)s5pv210启动方式
- 驱动实战-----OK6410驱动编程之led驱动1
- 驱动实战-----OK6410驱动编程之led驱动2
- linux驱动之LED驱动_1
- linux驱动之分离分层的概念
- 【原创】Tiny6410简单驱动 --- LED控制
- Linux下:Live555+S5pV210的mfc模块硬解方案实现
- 安卓内核开发-tiny210v2上的程序烧写
- 修改kernel version的方法及后果
- S5PV210 LED驱动程序
- GPIO驱动分析 & GPIO使用方法--S5PC110和S5PC210
- TQ2440 第一个驱动程序:LED驱动程序
- 从程序的执行过程的角度去编写IRQ中断框架代码
- 基于s5pv210的lcd色度键功能的个人探索总结