linux裝置驅動(3)字元驅動 -led
阿新 • • 發佈:2018-12-19
本文基於mini2440
/*
* kernel : linux-2.6.22.6
* gcc : arm-linux-gcc -3.4.5
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
#include <linux/device.h> /* class_device ... */
/**
* mini2440 LED資源 低電平有效
*
* LED1 GPB5
* LED2 GPB6
* LED3 GPB7
* LED4 GPB8
*/
#define GPB_ADDR 0x56000010
static volatile unsigned int *gpbcon;
static volatile unsigned int *gpbdat;
static int major;
static struct class *third_drv_cls;
static struct class_device *third_drv_cls_dev;
static int third_drv_led_open (struct inode *inode, struct file *file)
{
// 設定對應引腳為輸出
*gpbcon |= (0x1 << (5*2)) | (0x1 << (6*2)) | (0x1 << (7*2)) | (0x1 << (8*2));
return 0;
}
static int third_drv_led_write (struct file *file, const char __user *usrbuf,
size_t len, loff_t *offset)
{
int val[8];
int cmd, ops;
if (copy_from_user(&val, usrbuf, 8))
return -EFAULT;
cmd = val[0];
ops = val[1];
if(cmd == 0) // close
{
switch(ops)
{
case 0:
*gpbdat |= (1 << 5);
break;
case 1:
*gpbdat |= (1 << 6);
break;
case 2:
*gpbdat |= (1 << 7);
break;
case 3:
*gpbdat |= (1 << 8);
break;
default:
break;
}
}
else if(cmd == 1) // open
{
switch(ops)
{
case 0:
*gpbdat &= ~(1 << 5);
break;
case 1:
*gpbdat &= ~(1 << 6);
break;
case 2:
*gpbdat &= ~(1 << 7);
break;
case 3:
*gpbdat &= ~(1 << 8);
break;
default:
break;
}
}
else
{
// do nothing .
}
return 0;
}
static struct file_operations third_drv_led_fops =
{
.owner = THIS_MODULE,
.open = third_drv_led_open,
.write = third_drv_led_write,
};
static int third_drv_init(void)
{
major = register_chrdev(0, "led_drv", &third_drv_led_fops);
third_drv_cls = class_create(THIS_MODULE, "led_drv");
third_drv_cls_dev = class_device_create(third_drv_cls, NULL,
MKDEV(major, 0), NULL, "myleds");
// 地址重新對映
gpbcon = (volatile unsigned int*)ioremap(GPB_ADDR, 4);
gpbdat = gpbcon + 1;
return 0;
}
static void third_drv_exit(void)
{
iounmap(gpbcon);
class_device_unregister(third_drv_cls_dev);
class_destroy(third_drv_cls);
unregister_chrdev(major, "led_drv");
}
module_init(third_drv_init);
module_exit(third_drv_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Flinn [email protected]");
MODULE_DESCRIPTION("led driver for mini2440");
測試程式參考我的另一個博文:
執行命令./driver_test_tool /dev/myleds -o 0 0 第一個0 表示熄滅, 第二個0表示第一個燈