博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
喜羊羊系列【设备 - 驱动器 编译进内核】
阅读量:6701 次
发布时间:2019-06-25

本文共 7320 字,大约阅读时间需要 24 分钟。

博客:

这篇和做对照

*针对不同的平台。可能放进的不是以下的文件内,仅仅做參考

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 = {。。

。。。

。。。

。。。

。。

。。

。。。

。。。

。。。。 }

②将设备信息加入总线	改动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 
#include
#include
#include
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
//register_chrled#include
//class_create/ledice_create#include
//kmalloc#include
//copy_to_user/copy_from_user#include
//ioremap#include
//gpio_request#include
//s3c_gpio_cfgpin#include
//cdev_alloc#include
//下面是移植时须要添加的#include
#include
#include
#include
#include
#include
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/xxx if (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后加入,没有就新建
	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 加入
	obj-y        += mydriver/

最后就是自己make menuconfig里配置选项了。

====================================================================================================================================

4、測试程序

编译測试要使用交叉工具连
	arm-none-linux-gnueabi-gcc led_test.c -o led_test

附:

将可运行文件增加到开机启动,改动根文件系统filesystem

vi  filesystem/etc/init.d/rcS./star_app/led_test

測试程序

#include 
#include
#include
#include
#include
#include
#include
#include
#include
#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"
"|| 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; else cmd=LED_ON; val=3; //亮 led3 if(ioctl(fd,cmd,val)<0){ perror("ioctl failed!\n"); exit(1); } val=4; //亮 led4 if(ioctl(fd,cmd,val)<0){ perror("ioctl failed!\n"); exit(1); } my_sleep(1); } close(fd); return 0;}

版权声明:本文博客原创文章,博客,未经同意,不得转载。

你可能感兴趣的文章
VirtualBox 扩展虚拟硬盘容量
查看>>
CS224n笔记13 卷积神经网络
查看>>
springBoot(20):使用Spring Session实现集群-redis
查看>>
磁盘及文件系统的管理
查看>>
linux常用命令技巧--更新中
查看>>
我的友情链接
查看>>
Docker学习笔记——Java及Tomcat Dockerfile
查看>>
PHP中面向对象的图片处理类
查看>>
笔记--相册
查看>>
LINUX添加一块网卡地址配置及问题
查看>>
lastb
查看>>
[置顶] cocos2d-x 手游源码站
查看>>
2016年学习Linux决心书(老男孩教育在线课程班第二期)
查看>>
Linux文件系统
查看>>
37signals为何砍掉中层?个人点评,高素质人才队伍工作,靠的是全体发挥综合能力,而不是靠......
查看>>
jQuery中阻止冒泡
查看>>
touchesEnded不响应
查看>>
从表到里学习JVM实现
查看>>
关于数据库查询优化的思考
查看>>
如何在android studio中设置sdk path?
查看>>