写了一个简单的2410字符设备驱动程序
时间:2007-04-08 来源:einsn
一直看书,看资料,不自己写写程序,感觉极不踏实;作为一个以前搞过单片机的人,我看OS代码时,都喜欢看看底层的驱动,回到硬件那里,去看看怎么一回事,这样感觉踏实多了。
用的是2410板子,想写个LED的驱动,LED驱动只需写个只有两个命令的ioctl就行了。ARM板没有做LED接口,看来得打其它IO口的主意了,发现里面有四个中断按键,和引出的SPI接口,查看了一下datasheet,均可以做普通IO口用。以前自己用感光板做的51单片机开发板可以派上用场了,上面有8个LED。用杜邦线接上后,按按键按下去看,LED可以点亮,说明硬件基本问题了,(这么简单的电路还测一下,呵呵别拍砖)。
接下来可以写设备驱动:参考了一下前辈们的一些实例,也就不多说了。程序如下:
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/sched.h>
#include<linux/delay.h>
#include <linux/poll.h>
#include <linux/spinlock.h>
#include <linux/irq.h>
#include <linux/delay.h>
#include <asm/hardware.h> #define DEVICE_NAME "leds" #define LED_MAJOR 231
static unsigned long led_table[] ={
GPIO_G2,
GPIO_F0,
GPIO_F3,
GPIO_E11}; static int einleds_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){
switch(cmd)
{
case 0:
case 1:
if (arg > 4) {
return -EINVAL;
}
write_gpio_bit(led_table[arg], !cmd);
default:
return -EINVAL;
} }
static struct file_operations einleds_fops={
owner:THIS_MODULE,
ioctl:einleds_ioctl,
};
static devfs_handle_t leds_handle; static int __init einleds_init(void){
int rv;
int i;
rv=register_chrdev(LED_MAJOR, DEVICE_NAME, &einleds_fops);
if(rv<0){
printk(DEVICE_NAME"<Ein>Can't use this major number.\n");
return rv;
}
// I don't known why need to use the function "devfs_register"
leds_handle = devfs_register(NULL, DEVICE_NAME, DEVFS_FL_DEFAULT,
LED_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR, &einleds_fops, NULL); //initial io port for(i=0;i<4;i++){
set_gpio_ctrl(led_table[i]|GPIO_MODE_OUT);//set as output
write_gpio_bit(led_table[i], 1);//off the led
} printk("<Ein>Leds Initial OK!\n");
return 0; }
static void __exit einleds_exit(void){
devfs_unregister(leds_handle);
unregister_chrdev(LED_MAJOR, DEVICE_NAME);
printk("<Ein>Leds Remove OK!\n");
}
module_init(einleds_init);
module_exit(einleds_exit); MODULE_LICENSE("GPL"); ------------------------------ devfs_register这个函数还没有去弄懂,知道的就说说吧。 重新编译了一次内核,把原来的按键驱动拿掉,以免冲突,以后也可以多几个IO操作。 再编译一下上面的程序,加载上去,一切顺利。 再写个小小的应用程序,真的可以控制。呵呵!
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/sched.h>
#include<linux/delay.h>
#include <linux/poll.h>
#include <linux/spinlock.h>
#include <linux/irq.h>
#include <linux/delay.h>
#include <asm/hardware.h> #define DEVICE_NAME "leds" #define LED_MAJOR 231
static unsigned long led_table[] ={
GPIO_G2,
GPIO_F0,
GPIO_F3,
GPIO_E11}; static int einleds_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){
switch(cmd)
{
case 0:
case 1:
if (arg > 4) {
return -EINVAL;
}
write_gpio_bit(led_table[arg], !cmd);
default:
return -EINVAL;
} }
static struct file_operations einleds_fops={
owner:THIS_MODULE,
ioctl:einleds_ioctl,
};
static devfs_handle_t leds_handle; static int __init einleds_init(void){
int rv;
int i;
rv=register_chrdev(LED_MAJOR, DEVICE_NAME, &einleds_fops);
if(rv<0){
printk(DEVICE_NAME"<Ein>Can't use this major number.\n");
return rv;
}
// I don't known why need to use the function "devfs_register"
leds_handle = devfs_register(NULL, DEVICE_NAME, DEVFS_FL_DEFAULT,
LED_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR, &einleds_fops, NULL); //initial io port for(i=0;i<4;i++){
set_gpio_ctrl(led_table[i]|GPIO_MODE_OUT);//set as output
write_gpio_bit(led_table[i], 1);//off the led
} printk("<Ein>Leds Initial OK!\n");
return 0; }
static void __exit einleds_exit(void){
devfs_unregister(leds_handle);
unregister_chrdev(LED_MAJOR, DEVICE_NAME);
printk("<Ein>Leds Remove OK!\n");
}
module_init(einleds_init);
module_exit(einleds_exit); MODULE_LICENSE("GPL"); ------------------------------ devfs_register这个函数还没有去弄懂,知道的就说说吧。 重新编译了一次内核,把原来的按键驱动拿掉,以免冲突,以后也可以多几个IO操作。 再编译一下上面的程序,加载上去,一切顺利。 再写个小小的应用程序,真的可以控制。呵呵!
相关阅读 更多 +