第六篇:将LED驱动编译到内核
日期:2009-3-12
内核的drivers目录里提供了LED的驱动文件,查看后,发现管脚定义也和我板子上的定义一致(呵呵)
于是就把内核提供的LED例子弄的我存放文件的目录,想编译下,主要是测试下看是否有错误。
编译内核提供的 LED 例子,操作如下;
arm-linux-gcc -DKERNEL -DMODULE -I/armsys2410/kernel/include -c example-leds.c
example-leds.c文件内容如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define DEVICE_NAME "leds"
#define example_led_MAJOR 231
static unsigned long example_led_table [] = {
GPIO_F7,//GPIO_B7,
GPIO_F6,//GPIO_B8,
GPIO_F5,//GPIO_B9,
GPIO_F4,//GPIO_B10,
};
static int example_leds_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(example_led_table[arg], !cmd);
default:
return -EINVAL;
}
}
static struct file_operations example_leds_fops = {
owner: THIS_MODULE,
ioctl: example_leds_ioctl,
};
static devfs_handle_t devfs_handle;
static int __init example_leds_init(void)
{
int ret;
int i;
ret = register_chrdev(example_led_MAJOR, DEVICE_NAME, &example_leds_fops);
if (ret < 0) {
printk(DEVICE_NAME " can't register major number/n");
return ret;
}
devfs_handle = devfs_register(NULL, DEVICE_NAME, DEVFS_FL_DEFAULT,
example_led_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR, &example_leds_fops, NULL);
for (i = 0; i < 8; i++) {
set_gpio_ctrl (example_led_table[i] | GPIO_PULLUP_EN | GPIO_MODE_OUT);
write_gpio_bit(example_led_table[i], 1);
}
printk(DEVICE_NAME " initialized/n");
return 0;
}
static void __exit example_leds_exit(void)
{
devfs_unregister(devfs_handle);
unregister_chrdev(example_led_MAJOR, DEVICE_NAME);
}
module_init(example_leds_init);
module_exit(example_leds_exit);
哀。
错误太多了,,,,列出来的话,真的很吓人的。。。
于是又把自己之前编译没有错误的led.c文件,拿出来测试下,看是否编译环境有问题??
操作如下:
arm-linux-gcc -DKERNEL -DMODULE -I/armsys2410/kernel/include -c led.c
编译没问题
led.c文件内容:
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include
#include
#include
#include
#include
#include
#define DEVICE_NAME "leds"
#define LED_MAJOR 232
static unsigned long led_table[]={GPIO_F4,GPIO_F5,GPIO_F6,GPIO_F7};
static int leds_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);
printk("pin ");
break;
default:
return -EINVAL;
}
}
static struct file_operations leds_fops={
owner:THIS_MODULE,
ioctl:leds_ioctl,
};
static int __init leds_init(void){
int ret;
int i;
ret = register_chrdev(LED_MAJOR,DEVICE_NAME,&leds_fops);
if(ret<0)
{
printk(DEVICE_NAME"can't register major number");
return ret;
}
for(i=0;i<4;i++)
{
set_gpio_ctrl(led_table[i]|GPIO_PULLUP_EN|GPIO_MODE_OUT);
write_gpio_bit(led_table[i],1);
}
printk(DEVICE_NAME "initialized/n");
return 0;
}
static void __exit leds_exit(void){
unregister_chrdev(LED_MAJOR,DEVICE_NAME);
}
module_init(leds_init);
module_exit(leds_exit);
很纳闷,为什么编译内核提供的LED测试程序时,错误非常多??
而编译 阿南教程上的没有错??
编译时参数选项一样,就文件名不同而已,,,
想来想去,也就觉得在两个文件中的最大区别是:
led.c文件的开始有如下声明:
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
后来在 example-leds.c(系统提供的文件)中也加了如下声明:
再次编译没有问题了,(上述声明,加入文件的开头处)
操作如下:
arm-linux-gcc -DKERNEL -DMODULE -I/armsys2410/kernel/include -c example-leds.c
为啥会出现上述的问题呢???
目前我的猜测就是:
内核提供的例子是将驱动程序直接编译到内核去的,所以不需要加上述的声明
而驱动程序用加载到内核的方法时(即insmod动态加载时),就需要加上述的声明
也不知道说的对不对?呵呵
就目前的情况看
led.c文件与 example-leds.c文件的区别:
1 前者是insmod方式加载的,后者是直接编译到内核。
2 前者有关于内核、模块的宏定义,后者没有
3 前者在驱动初始化和退出时,没有使用设备文件系统,后者在驱动源文件中使用了
如:static devfs_handle_t devfs_handle;(其他没列出 呵呵)
看教程中关于出现问题(教程有3个问题)的描述时,也全是和上述三点有关系。。。