今天学习了LINUX的字符驱动的原理,在参考网络上提供的方法后,编写了一些简单的驱动并实现。过程中实现了对SAM9261 I/O管脚的控制。 首先,在/path/to/linux/driver/char 下添加新的C 文件,作为驱动的源码文件。然后添加如下代码,可以作为模板使用:
#include <linux/autoconf.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <asm/arch/gpio.h>
#include <linux/delay.h>
unsigned char cmd[3];
static int testdriver_major = 200; //新设的主设备号
/**
* open the driver -在用户模式下调用
*/
static int char_test_open(struct inode *inode, struct file *file){
printk(KERN_ALERT "[open the driver!!]/n");
return 0;
}
/**
* read function, be carefull the return object is ssize_t!
*/
static ssize_t char_test_read(struct file *file, char *buf, int count, loff_t *ppos){
printk(KERN_ALERT "[read char test]/n");
return count;
}
/***
* as the read function
*/
static ssize_t char_test_write(struct file *file, char *buf, int count, loff_t *ppos){
printk(KERN_ALERT "write char test/n");
return count;
}
/**
* close the driver
*/
static int char_test_release(struct inode *inode, struct file *file){
printk(KERN_ALERT "release char test/n");
return 0;
}
/**
* file operations interface define
*/
struct file_operations char_test_fops = {
.read = char_test_read,
.write = char_test_write,
.open = char_test_open,
.release = char_test_release,
};
/**
* init the char
* use commad as module driver: # insmod ***.ko (in linux 2.6 the module driver's type is .ko)
*/
static int __init char_test_init(void)
{
printk(KERN_ALERT "INIT char test/n");
int ret;
//int pin0,pin1,pin2,pin7,pin8,pin9;
/*注册驱动,在/dev下显示的名字是chartest, 通过命令: mknod -m 666 chartest c 200 0 来注册*/
ret = register_chrdev(testdriver_major, "chartest", &char_test_fops);//register device
if (ret < 0) {
printk(KERN_ALERT "[INIT char test failed]/n");
return ret;
}
/** 这里定义了些9261的管脚的控制。实现对某个管脚的电平控制,0~3.2v的范围,返回是0 和1
at91_set_GPIO_periph(AT91_PIN_PA0,1);
gpio_direction_input(AT91_PIN_PA0);
//at91_set_gpio_input(AT91_PIN_PA0, 1);
at91_set_GPIO_periph(AT91_PIN_PA1,1);
gpio_direction_output(AT91_PIN_PA1, 1);
at91_set_gpio_value(AT91_PIN_PA1, 1);//mosi
at91_set_GPIO_periph(AT91_PIN_PA2,1);
gpio_direction_output(AT91_PIN_PA2, 1);
at91_set_gpio_value(AT91_PIN_PA2, 1);//spck
at91_set_GPIO_periph(AT91_PIN_PA27,1);
gpio_direction_output(AT91_PIN_PA27, 1);
at91_set_gpio_value(AT91_PIN_PA27, 1);// /sss = 1 disable
at91_set_GPIO_periph(AT91_PIN_PA28,1);
gpio_direction_output(AT91_PIN_PA28, 1);
at91_set_gpio_value(AT91_PIN_PA28, 1); // /fss = 1 disable
at91_set_GPIO_periph(AT91_PIN_PA29,1);
gpio_direction_output(AT91_PIN_PA29, 1);
at91_set_gpio_value(AT91_PIN_PA29, 0);
*/
return ret;
}
//释放驱动
static void __exit char_test_exit(void)
{
unregister_chrdev(testdriver_major, "chartest");
printk(KERN_ALERT "char test end/n");
}
module_init(char_test_init);
module_exit(char_test_exit);
MODULE_DESCRIPTION("char device test");
MODULE_LICENSE("GPL");
当然最后要修改下Makefile 和 Kconfig Kconfig 在endmenu 前添加: config AT91_HELLO tristate "hello" default n help hello to who in times. Makefile 添加句:obj-$(CONFIG_AT91_HELLO) += hello.o 位置很容易找到的,看到类似的语句就是了,添加在后面。 配置该驱动,选择M,为添加模块,要从新编译内核,并把相应的内核放到开发板,使其能接受新开发的驱动。 然后在写个简单的用户程序,测试下就OK了~~