在天嵌的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 灯关闭了。
相关产品:
http://www.embedsky.com/index.php?s=/Product/show/id/47.html
http://www.embedsky.com/index.php?s=/Product/show/id/80.html
http://www.embedsky.com/index.php?s=/Product/show/id/43.html
文章评论(0条评论)
登录后参与讨论