第六篇:將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 <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 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 <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <asm-arm/arch-s3c2410/hardware.h>
#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個問題)的描述時,也全是和上述三點有關係。。。