喜羊羊系列之【设备 - 驱动 编入内核】
来源:互联网 发布:淘宝店铺更改所在地 编辑:程序博客网 时间:2024/06/06 03:26
博客:http://blog.csdn.net/muyang_ren
这篇和设备-驱动动态加载进内核做对比
*针对不同的平台,可能放进的不是下面的文件内,只做参考
1、头文件
放进:linux-3.0.8\arch\arm\plat-samsung\include\plat
led.h
#ifndef _HEAD_H#define _HEAD_H#define MAGIC 'h'#define LED_ON _IOW(MAGIC,1,int)#define LED_OFF _IOW(MAGIC,0,int)struct led_device{ dev_t devno;unsigned int led_major;struct cdev *led_cdev;struct class *led_class;struct device *led_device;};#endif
====================================================================================================================================
2、设备文件
方法一:将设备资源直接加进/linux-3.0.8/arch/arm/mach-s5pv210下的mach-smdkv210.c
① struct platform_device s5pv210_led_device_lhy = {.name= "s5pv210_led_lhy",.id= 1,};static struct platform_device *smdkv210_devices[] __initdata = {。。。。。。。。。。。。。。。。。。。。。。。。。。。}
②将设备信息加入总线<span style="white-space:pre"></span>修改arch/arm/mach-s5pv210/mach-smdkv210.c文件static struct platform_device *smdkv210_devices[] __initdata = {....../*添加如下代码*/&s5pv210_led_device_lhy, //新添加的}方法二:
①将设备文件dev-led.c 放进 linux-3.0.8/arch/arm/plat-samsung
led_dev.c
#include <linux/platform_device.h>#include <plat/led.h>#include <plat/devs.h>#include <plat/cpu.h>struct platform_device s5pv210_led_device_lhy = {.name= "s5pv210_led_lhy",.id= 1,};②向arch/arm/mach-s5pv210/mach-smdkv210.c(跟平台架构相关文件)添加
static struct platform_device *smdkv210_devices[] __initdata = {....&s5pv210_led_device_lhy, //新添加};③向linux-3.0.8/arch/arm/plat-samsung/Makefile添加
obj-$(CONFIG_S3C_DEV_LED) += led_dev.o④向linux-3.0.8/arch/arm/plat-samsung/Kconfig添加
config S3C_DEV_LED bool "S5PV210 LED driver support" help s5pv210 led device support
⑤添加外部声明arch/arm/plat-samsung/include/plat/devs.h
extern struct platform_device s5pv210_led_device_lhy;
====================================================================================================================================
3、平台驱动
①将led_drv.c 放进linux-3.0.8/drivers/my_led
led_drv.c
#include<linux/fs.h>//register_chrled#include<linux/device.h>//class_create/ledice_create#include<linux/slab.h>//kmalloc#include<asm/uaccess.h>//copy_to_user/copy_from_user#include<asm/io.h>//ioremap#include<linux/gpio.h>//gpio_request#include <plat/gpio-cfg.h>//s3c_gpio_cfgpin#include <linux/cdev.h> //cdev_alloc#include <linux/platform_device.h>//以下是移植时需要增加的#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <plat/cpu.h>#include <plat/led.h>#include <plat/devs.h>static struct led_device *led_drv;static int led_open(struct inode *inode, struct file *file){printk(KERN_INFO"%s()-%d\n", __func__, __LINE__);s3c_gpio_cfgpin(S5PV210_GPC0(3),S3C_GPIO_OUTPUT);s3c_gpio_cfgpin(S5PV210_GPC0(4),S3C_GPIO_OUTPUT);return 0;}static ssize_t led_read(struct file *file, char __user *buf, size_t count, loff_t *offset){printk(KERN_INFO"%s()-%d\n", __func__, __LINE__);return count;}ssize_t led_write(struct file *file, const char __user *buf, size_t count, loff_t *offset){printk(KERN_INFO"%s()-%d\n", __func__, __LINE__);return 0;}static long led_ioctl(struct file *file, unsigned int cmd, unsigned long val){printk(KERN_INFO"%s()-%d\n", __func__, __LINE__);printk(KERN_INFO"cmd=%d arg=%ld\n", cmd, val);switch(cmd){case LED_ON:gpio_set_value(S5PV210_GPC0(val),1);break;case LED_OFF:gpio_set_value(S5PV210_GPC0(val),0);break;default:break;}return 0;}//硬件操作方法static struct file_operations led_fops={.owner= THIS_MODULE,.open = led_open,.write = led_write,.read = led_read,.unlocked_ioctl = led_ioctl,};static int s5pv210_led_probe(struct platform_device *pdrv){int ret;led_drv = kmalloc(sizeof(struct led_device),GFP_KERNEL);if(led_drv==NULL){printk(KERN_ERR"no memory malloc for fs210_led\n");return -ENOMEM;}/*1. 动态注册/申请主设备*/ret=alloc_chrdev_region(&led_drv->devno,0,1,"dev_module");if (ret < 0) {printk(KERN_ERR "unable to get major\n");return -EFAULT;goto out_err_1;}//从设备号中分离出主设备号led_drv->led_major = MAJOR(led_drv->devno);/*为cdev分配空间*/led_drv->led_cdev = cdev_alloc();/*注册硬件操作方法/初始化cdev*/cdev_init(led_drv->led_cdev,&led_fops);/*注册字符设备*/cdev_add(led_drv->led_cdev,led_drv->devno,1);/*2. 创建设备类*/led_drv->led_class=class_create(THIS_MODULE,"led_class");if (IS_ERR(led_drv->led_class)) {printk(KERN_ERR "class_create() failed for led_class\n");ret = -ENODATA;goto out_err_2;}/*3. 创建设备文件*/led_drv->led_device=device_create(led_drv->led_class,NULL,MKDEV(led_drv->led_major,0),NULL,"led"); // /led/xxxif (IS_ERR(led_drv->led_device)) {printk(KERN_ERR "device_create failed for led_device\n");ret = -ENODEV;goto out_err_3;}/*申请GPC0_3,4引脚资源*/gpio_request(S5PV210_GPC0(3),"LED1");gpio_request(S5PV210_GPC0(4),"LED2");return 0;out_err_3:class_destroy(led_drv->led_class);out_err_2:unregister_chrdev(led_drv->led_major,"led_module");out_err_1:kfree(led_drv);return ret;}static int s5pv210_led_remove(struct platform_device *pdrv){unregister_chrdev(led_drv->led_major,"led_module");device_destroy(led_drv->led_class,MKDEV(led_drv->led_major,0));class_destroy(led_drv->led_class);gpio_free(S5PV210_GPC0(3));gpio_free(S5PV210_GPC0(4));kfree(led_drv);return 0;}struct platform_device_id led_ids[]={[0]={.name = "s5pv210_led_lhy",.driver_data = 0,},};static struct platform_driver s5pv210_led_driver = {.probe= s5pv210_led_probe,.remove = s5pv210_led_remove,.driver = {.name = "s5pv210_led_lhy",.owner = THIS_MODULE,},.id_table = led_ids,}; static int __devinit s5pv210_led_init(void){return platform_driver_register(&s5pv210_led_driver);}static void __devexit s5pv210_led_exit(void){platform_driver_unregister(&s5pv210_led_driver);}module_init(s5pv210_led_init);module_exit(s5pv210_led_exit);MODULE_DESCRIPTION("LED driver for Marvell PM860x");MODULE_AUTHOR("kiron");MODULE_LICENSE("GPL");MODULE_ALIAS("platform:s5pv210-led");②在当前目录的Kconfig后添加,没有就新建
config S5PV210_LED_DRV tristate "led_dev for fs210 device" help led driver is for s5pv210, choose y/m/n③在当前目录的Makefile后添加,没有就新建
<span style="white-space:pre"></span>obj-$(CONFIG_S5PV210_LED_DRV) = led_drv.o
④修改上级目录的Makefile和Kconfig
将linux-3.0.8/drivers/Kconfig 添加
source "drivers/my_led/Kconfig"将linux-3.0.8/drivers/Makefile 添加
<span style="white-space:pre"></span>obj-y += mydriver/
最后就是自己make menuconfig里配置选项了。
====================================================================================================================================
4、测试程序
编译测试要使用交叉工具连<span style="white-space:pre"></span>arm-none-linux-gnueabi-gcc led_test.c -o led_test
附:
将可执行文件加入到开机启动,修改根文件系统filesystem
vi filesystem/etc/init.d/rcS./star_app/led_test
测试程序
#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <sys/ioctl.h>#include <unistd.h>#define MAGIC 'h'#define LED_ON _IOW(MAGIC,1,int)#define LED_OFF _IOW(MAGIC,0,int)static void my_sleep(int n){int j;for(j=0; j<10000000*n; j++);}int main(void){printf("-------------------------------\n"<span style="white-space:pre"></span>"|| start:一闪一闪亮晶晶 ||\n""-------------------------------\n");my_sleep(1);int fd;unsigned int cmd=0;unsigned long val=0;fd=open("/dev/led", O_RDWR);if(fd<0){perror("open failed!\n");exit(1);}int i;for(i=0; i<10; i++){if(i%2==0)cmd=LED_OFF;elsecmd=LED_ON;val=3; //亮 led3if(ioctl(fd,cmd,val)<0){perror("ioctl failed!\n");exit(1);}val=4; //亮 led4if(ioctl(fd,cmd,val)<0){perror("ioctl failed!\n");exit(1);}my_sleep(1);}close(fd);return 0;}
- 喜羊羊系列之【设备 - 驱动 编入内核】
- 喜羊羊系列之【设备-驱动 动态加载进内核】
- 驱动编入内核(移植)---Kconfig的使用
- Linux内核之设备驱动
- Linux内核驱动之设备
- Linux内核设备驱动之GIC驱动
- linux 内核编程之字符设备驱动
- linux内核驱动之主次设备号
- Linux内核之字符设备驱动
- Linux内核之设备驱动模型
- Linux设备驱动----之linux内核
- Linux 内核设备驱动之GPIO驱动之GPIO API
- 嵌入式linux平台设备驱动(设备驱动模型)开发之linux内核中的设备驱动
- Linux字符设备驱动之cdev_init()系列
- Linux字符设备驱动之register_chrdev_region()系列
- Linux字符设备驱动之cdev_init()系列
- Linux字符设备驱动之register_chrdev_region()系列
- 字符设备驱动之cdev_init()系列函数
- Access Remote Database Table in ABAP Program Via DBLink of ORACLE
- 激光雷达学习笔记(一)数据采集
- Unity3d_UGUI加载场景进度条
- [BZOJ3931]CQOI2015网络吞吐量|最短路|最大流
- tomcat-5.0.28在https模式下IE8无法下载文件问题解决
- 喜羊羊系列之【设备 - 驱动 编入内核】
- 任意模型的折纸效果 Folding effect
- 解决同一IP不同端口访问的站点iframe应用session丢失的问题
- OpenCL异构计算资料收集
- lufylegend引擎俄罗斯方块的实现
- javascript轮播技术
- Making a Kali Bootable USB Drive
- poj 3083
- mysql 时间日期查询