通過一天的學習總結一下掛接在/proc上的對LED燈控制的驅動開發,代碼和過程
1.驅動代碼
[cpp]
#include <linux/module.h>
#include <linux/init.h>
#include <linux/version.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include <linux/gpio.h>
#include <mach/regs-gpio.h>
MODULE_LICENSE("Dual BSD/GPL");
#define USER_ROOT_DIR "led"
#define USER_ENTRY1 "led_entry1"
static struct proc_dir_entry *led_root;
static struct proc_dir_entry *led_entry1;
static char msg[255];
static unsigned long led_table [] =
{
S3C2410_GPB(5),
S3C2410_GPB(6),
S3C2410_GPB(7),
S3C2410_GPB(8),
};
static unsigned int led_cfg_table[] =
{
S3C2410_GPIO_OUTPUT,
S3C2410_GPIO_OUTPUT,
S3C2410_GPIO_OUTPUT,
S3C2410_GPIO_OUTPUT,
};
//int proc_read_information(char *page, char **start, off_t off, int count, int *eof, void *data);
int proc_write_information(struct file *file, const char *buffer, unsigned long count, void *data);
static int proc_test_init(void)
{
int i;
for( i=0;i<4;i++)
{
s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);
}
// Create user root dir under /proc
led_root = proc_mkdir(USER_ROOT_DIR, NULL);
if (NULL==led_root)
{
printk(KERN_ALERT "Create dir /proc/%s error!\n",USER_ROOT_DIR);
return -1;
}
printk(KERN_INFO "Create dir /proc/%s\n", USER_ROOT_DIR);
// Create a test entry under USER_ROOT_DIR
led_entry1 = create_proc_entry(USER_ENTRY1,0666, led_root);
if (NULL == led_entry1)
{
printk(KERN_ALERT "Create entry %s under /proc/%s error!\n",USER_ENTRY1, USER_ROOT_DIR);
goto err_out;
}
printk(KERN_INFO "Create /proc/%s/%s\n",USER_ROOT_DIR, USER_ENTRY1);
//led_entry1->read_proc = proc_read_information;
led_entry1->write_proc = proc_write_information;
return 0;
err_out: remove_proc_entry(USER_ROOT_DIR, led_root);
return -1;
}
static void proc_test_exit(void)
{
// Remove all entries
remove_proc_entry(USER_ENTRY1, led_root);
remove_proc_entry(USER_ROOT_DIR, NULL);
printk(KERN_INFO "All Proc Entry Removed!\n");
}
//int proc_read_information(char *page, char **start, off_t off, int count, int *eof, void *data)
//{
//}
int proc_write_information(struct file *file, const char *buffer, unsigned long count, void *data)
{
int count2=0,i ;
if (copy_from_user((void *)msg, (const void __user *)buffer, count))
return -EFAULT;
count2 = simple_strtoul(msg, NULL, 0);
//printk("information %d\n",count2);
switch(count2)
{
case 0:
case 1:
for(i=0; i<4; i++)
{
s3c2410_gpio_setpin(led_table[i],!count2);
}
break;
default:
return -EINVAL;
}
return 0;
}
module_init(proc_test_init);
module_exit(proc_test_exit);
2.驅動Makefile
[cpp]
obj-m:=led2.o
CURRENT_PATH:=$(shell pwd)
ARM_LINUX_KERNEL:=/opt/FriendlyARM/mini2440/linux-2.6.32.2
all:
$(MAKE) -C $(ARM_LINUX_KERNEL) SUBDIRS=$(CURRENT_PATH) modules
clean:
rm -rf *.cmd *.o *.ko *.mod.c *.symvers *.order
3.開發過程
編寫好驅動代碼和Makefile,在PC機上編譯成功後通過FTP把led2.ko文件上傳到開發板,加載驅動(insmod led2.ko),
執行echo 1 >/proc/led/led_entry1,燈全亮
執行echo 0 >/proc/led/led_entry1,燈全滅
注意:開發板缺省的文件系統已經有了led 測試程序,所以在開發板的命令行終端執行:
#/etc/rc.d/init.d/leds stop