Linux 驱动学习之led驱动
首先是led.c文件:
#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>
#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);
tmp = (tmp & ~(0xffff)) | (0x1111);
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_t count, 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 |= (0xFU);
writel(tmp, S3C64XX_GPMDAT);
break;
case 1: //on
tmp = readl(S3C64XX_GPMDAT);
tmp &= ~(0xFU);
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 led dev\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("module exit\n");
return;
}
module_init(led_init);
module_exit(led_exit);
以上led.c就是led驱动的主要内容了,然后是Makefile文件:
obj-m:=led.o
KDIR:=/home/msc/Desktop/linux-3.0.1/
all:
make -C $(KDIR) M=$(shell pwd) modules
clean:
make -C $(KDIR) M=$(shell pwd) clean
这里的KDIR是和目标板相同的内核的交叉编译路径。
最后是测试代码test.c:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//#include <linux/io.h>
//#include <linux/gpio.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;
}
步骤:
1.将以上三个文件放在同一个文件夹下,使用make指令进行编译生成led.ko驱动。
2.使用arm-linux-gcc -o test test.c编译测试代码。
3.使用网络文件系统将上述文件夹挂载到目标板上
4.使用insmod led.ko 命令加载驱动。
5.使用mknod /dev/my_led c 240 0 创建设备文件。
6.运行测试代码./test就可以看到OK6410开发板上的四个led同时闪烁。
这里led.c 文件里芯片寄存器的配置是根据数据手册来的。所以还是要认真看数据手册。