/*the driver is for led writted by william in 2013.2.27 and the kernel 2.6.25*/
#include <linux/module.h> //动态加载模块到内核,假如没有这个头文件,编译一切正常,但是安装驱动模块后,不会产生节点,即不成功。
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/hardware.h>
#include <asm/arch/gpio.h>
#include <asm-arm/arch-pxa/mfp.h>
#include "led.h"
/*led.h 中的内容如下
#ifndef __LED_H__
#define __LED_H__
#define LED_ON 0
#define LED_OFF 1
#define Led_Count 5
struct Led_dev{
int Led_Num;
unsigned char state;
unsigned int timems;
//unsigned int offtimems;
};
#endif
*/
#define LED_DEVICE_NAME "william_led"
struct Led_dev LED_DEV;
static unsigned long led_table[] = {
2,3,4,5,83,
}; //这是根据硬件电路图得出的gpio引脚
/*
int led_open(struct inode *inode,struct file *filp)
{
return 0;
}
int led_release(struct inode *inode,struct file *filp)
{
return 0;
}
static ssize_t led_read(struct file *filp,char *buf,size_t size,loff_t *ppos)
{
if(copy_to_user(buf,&LED_DEV,sizeof(LED_DEV)))
{
printk("copy to user failed !\n");
return -EFAULT;
}
return sizeof(LED_DEV);
}
*/
static ssize_t led_write(struct file *filp,const char *buf,size_t size,loff_t *ppos)
{
unsigned int gpioID;
int i,num;
struct Led_dev NEW_LED_DEV = LED_DEV;
if(copy_from_user(&NEW_LED_DEV,buf,sizeof(NEW_LED_DEV)))
{
printk("copy from user failed !\n");
return -EFAULT;
}
if(NEW_LED_DEV.Led_Num < Led_Count)
{
num = NEW_LED_DEV.Led_Num;
gpioID = mfp_to_gpio(led_table[num]); //#define mfp_to_gpio(m) ((m) % 128)
gpio_direction_output(gpioID,NEW_LED_DEV.state);
}
else
{
for(i=0;i<Led_Count;i++)
{
gpioID = mfp_to_gpio(led_table[i]);
gpio_direction_output(gpioID,NEW_LED_DEV.state);
}
}
return 0;
}
/*
static int led_ioctl(struct inode *inodep,struct file *filp,unsigned int cmd,unsigned long arg)
{
return 0;
}
*/
static struct file_operations led_fops = {
.owner = THIS_MODULE,
//.read = led_read,
.write = led_write,
//.ioctl = led_ioctl,
//.open = led_open, //有些函数我们用不到可以省去,看上去更简洁
//.release = led_release,
};
static struct miscdevice led_dev = {
.minor = 53, //cat /proc/misc 查看这个次设备号是否已被使用
.name = LED_DEVICE_NAME,
.fops = &led_fops,
}; //混杂设备必须的三个元素minor ,name,fops 。
static int led_probe(struct platform_device *pdev)
{
int ret;
int i;
unsigned int gpioID;
ret = misc_register(&led_dev);
for(i=0;i<ARRAY_SIZE(led_table);i++){
gpioID = mfp_to_gpio(led_table[i]);
ret = gpio_request(gpioID,"leds-request");
if(ret){
printk("Failed in gpio-%d",gpioID);
}
gpio_direction_output(gpioID,LED_OFF);
}
return 0;
}
static int led_remove(struct platform_device *pdev)
{
int i;
unsigned int gpioID;
for(i=0;i<ARRAY_SIZE(led_table);i++){
gpioID = mfp_to_gpio(led_table[i]);
gpio_direction_output(gpioID,LED_OFF);
gpio_free(gpioID);
}
misc_deregister(&led_dev);
return 0;
}
#ifdef CONFIG_PM //这里考虑能耗,添加了休眠模式
static int led_suspend(struct platform_device *pdev, pm_message_t state)
{
return 0;
}
static int led_resume(struct platform_device *pdev)
{
return 0;
}
#else
#define s3c24xx_led_suspend NULL
#define s3c24xx_led_resume NULL
#endif
static struct platform_driver led_driver = {
.driver = {
.name = "william_test_led",
},
.probe = led_probe,
.remove = led_remove,
.suspend = led_suspend,
.resume = led_resume,
};
# 这个需要在内核你所用板子的函数中添加
# static struct platform_device led_device = {
# .name = "william_test_led",
# .id = -1,
# };
# 并在初始化函数中添加
# platform_device_register(&led_device);
static int __init led_init(void)
{
printk("hello led !\n");
return platform_driver_register(&led_driver);
}
static void __exit led_exit(void)
{
platform_driver_unregister(&led_driver);
printk("bye led !\n");
}
module_init(led_init);
module_exit(led_exit);
MODULE_AUTHOR("William Wang");
MODULE_LICENSE("GPL");
//注意:驱动要保持其简洁性,不要加led闪烁之类的附加功能,凡API易做的,尽量在API中做。
附加测试程序
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include "led.h"
void delay(int n)
{
int i;
for(i=0;i<n;i++)
for(i=0;i<10000;i++);
}
int do_led(struct Led_dev testled)
{
int fd;
if((fd=open("/dev/william_led",O_RDWR)) == -1)
{
printf("open err !\n");
}
fd = write(fd,&testled,sizeof(testled));
if(fd == -1)
{
printf("write err !\n");
}
close(fd);
return 0;
}
int main(void)
{
int i;
struct Led_dev test_led ={
2,
LED_ON,
10,
};
for(i=0;i<5;i++){
test_led.Led_Num = i;
do_led(test_led);
delay(test_led.timems); //delay 作用不明显
test_led.state = ~test_led.state;
do_led(test_led);
}
return 0;
}
实例操作led驱动
最新推荐文章于 2021-10-28 16:00:44 发布