platform设备驱动之LED(misc设备)

来源:互联网 发布:盛势网络剧百度云资源 编辑:程序博客网 时间:2024/05/13 18:39

一、开发环境

1、硬件平台:FS2410

2、主机:Ubuntu 10.10

3、内核版本:linux 2.6.35

4、交叉编译工具链:arm-none-linux-gnueabi-


二、详细代码

led_device.c:

#include <linux/module.h>#include <linux/init.h>#include <linux/device.h>#include <linux/platform_device.h>#include <linux/kernel.h>struct resource led_resource[] = {[0] = {.start = 0x56000050,.end = 0x56000054,.flags = IORESOURCE_MEM,}};struct platform_device led_device = {.name = "led",.id = -1,.num_resources = ARRAY_SIZE(led_resource),.resource = led_resource,};static int __init led_device_init(void){int ret;ret = platform_device_register(&led_device);if(ret < 0)printk("failed to register led_device");return ret;}static void __exit led_device_exit(void){platform_device_unregister(&led_device);return;}module_init(led_device_init);module_exit(led_device_exit);MODULE_AUTHOR("yhr");MODULE_LICENSE("GPL");

led_driver.c

#include <linux/module.h>#include <linux/init.h>#include <linux/cdev.h>#include <linux/fs.h>#include <linux/slab.h>#include <linux/kernel.h>#include <linux/device.h>#include <linux/platform_device.h>#include <linux/miscdevice.h>#include <linux/io.h>#include <mach/map.h>static volatile unsigned int *gpfcon;static volatile unsigned int *gpfdat;void init_led(void){writel(readl(gpfcon) & ~(0xff << 8), gpfcon);writel(readl(gpfcon) | (0x55 << 8), gpfcon);writel(readl(gpfdat) & ~(0xf << 4), gpfdat);return ;}static int led_open(struct inode *inode, struct file *filp){init_led();return 0;}static int led_release(struct inode *inode, struct file *filp){writel(readl(gpfdat) | (0xf << 4), gpfdat);return 0;}static ssize_t led_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos){return 0;}static ssize_t led_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos){return 0;}static struct file_operations led_fops = {.owner = THIS_MODULE,.open = led_open,.release = led_release,.read = led_read,.write = led_write,};struct miscdevice led_dev = {.minor = MISC_DYNAMIC_MINOR,.fops = &led_fops,.name = "led",};static int led_probe(struct platform_device *pdev){struct resource *res;struct resource *led_mem;int size;int ret;ret = misc_register(&led_dev);res = platform_get_resource(pdev, IORESOURCE_MEM, 0);if(res == NULL){printk("failed to get resource\n");}size = resource_size(res);led_mem = request_mem_region(res->start, size, pdev->name);if(led_mem == NULL){printk("failed to request_mem_region\n");}gpfcon = ioremap(res->start, size);gpfdat = ioremap(res->end, size);return ret;}static int led_remove(struct platform_device *pdev){struct resource *res;int size;res = platform_get_resource(pdev, IORESOURCE_MEM, 0);if(res == NULL){printk("failed to get resource\n");}size = resource_size(res);iounmap(gpfcon);iounmap(gpfdat);release_mem_region(res->start, size);misc_deregister(&led_dev);return 0;}struct platform_driver led_driver = {.probe = led_probe,.remove = led_remove,.driver = {.name = "led",.owner = THIS_MODULE,},};static int __init led_driver_init(void){int ret;ret = platform_driver_register(&led_driver);if(ret < 0)printk("failed to register led_driver\n");return ret;}static void __exit led_driver_exit(void){platform_driver_unregister(&led_driver);return ;}module_init(led_driver_init);module_exit(led_driver_exit);MODULE_AUTHOR("yhr");MODULE_LICENSE("GPL");

Makefile:

ifeq ($(KERNELRELEASE),)# set your object kernel dirKERNELDIR = /home/linux/linux-2.6.35 PWD := $(shell pwd)modules:$(MAKE) -C $(KERNELDIR) M=$(PWD) modulesmodules_install:$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_installclean:rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions Module* modules*.PHONY: modules modules_install cleanelse    obj-m := led_device.o led_driver.oendif

应用测试程序(led_test.c):

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>int main(void){int dev_fd;if((dev_fd = open("/dev/led", O_RDONLY)) < 0){perror("failed to open led");exit(-1);}while(1);return 0;}