喜羊羊系列之【设备-驱动 动态加载进内核】

博客:http://blog.csdn.net/muyang_ren

这篇和设备驱动编入内核做对比

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

平台设备

dev_led.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include "led.h"

static void led_release(struct device *dev){

}

static struct platform_device s5pv210_led_device_lhy = {
	.name			= 	"s5pv210_led_lhy",
	.id				= 	1,

	.dev			=	{
			.release 	= led_release,  //开发模式下,这个真不能少!
	},
};

static int __init dev_led_init(void){
	platform_device_register(&s5pv210_led_device_lhy);
	return 0;
}

static void __exit dev_led_exit(void){
	platform_device_unregister(&s5pv210_led_device_lhy);
}

module_init(dev_led_init);
module_exit(dev_led_exit);
MODULE_LICENSE("GPL");

平台驱动

led_drv.c

#include<linux/init.h>
#include<linux/module.h>
#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"led.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/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 __init led_init(void)
{
	platform_driver_register(&s5pv210_led_driver);
	return 0;
}

static void __exit led_exit(void)
{
	platform_driver_unregister(&s5pv210_led_driver);

}

module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");

测试程序:

#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 "led.h"

/*
** ./led_test on	num	点亮LED1/2
** ./led_test off	num	熄灭LED1/2
*/
int main(int argc, char *argv[])
{
	if (argc != 3)
			printf("input:< %s on led_num >or< %s off led_num>\n",argv[0],argv[0]);

	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);
	}

	if(strcmp(argv[1],"on")==0){
		cmd=LED_ON;
	}else if(strcmp(argv[1],"off")==0){
		cmd=LED_OFF;
	}else{
		printf("err input!\n");
	}

	val = atoi(argv[2]);

	if(ioctl(fd,cmd,val)<0){
		perror("ioctl failed!\n");
		exit(1);
	}

	close(fd);
	return 0;
}

Makefile

ifeq ($(KERNELRELEASE),)
	KERNELDIR =/home/farsight/work/kernel/linux-3.0.8
	PWD =$(shell pwd)
modules:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
	arm-none-linux-gnueabi-gcc led_test.c -o led_test
	cp led_drv.ko dev_led.ko led_test /opt/filesystem/s5pv210
modules_install:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
clean:
	rm -rf *.so *.o *.ko *test  .tmp_versions *.mod.c *.order *.symvers
else
	obj-m :=led_drv.o dev_led.o
endif
时间: 2024-10-07 01:59:03

喜羊羊系列之【设备-驱动 动态加载进内核】的相关文章

[Android 性能优化系列]布局篇之动态加载布局

大家如果喜欢我的博客,请关注一下我的微博,请点击这里(http://weibo.com/kifile),谢谢 转载请标明出处(http://blog.csdn.net/kifile),再次感谢 原文地址:http://developer.android.com/training/improving-layouts/loading-ondemand.html 在接下来的一段时间里,我会每天翻译一部分关于性能提升的Android官方文档给大家 性能优化布局篇: [Android 性能优化系列]布局篇

Ajax动态加载数据

前言: 1.这个随笔实现了一个Ajax动态加载的例子. 2.使用.net 的MVC框架实现. 3.这个例子重点在前后台交互,其它略写. 开始: 1.控制器ActionResult代码(用于显示页面) /// <summary> /// 电话查询页面 /// </summary> /// <returns></returns> public ActionResult PhoneSearch(string sql) { phoneList=从数据库查询数据: V

mini2440驱动奇谭——LED驱动与测试(动态加载)

我的博客:http://blog.csdn.net/muyang_ren 实现功能:开发板动态加载led驱动模块并能通过测试程序 系统:Ubuntu 14.04 驱动交叉编译内核:linux-2.6.32.2               //建立交叉编译 开发板:mini2440 (128M nandflash)     //关于怎么烧写linux到开发板请点击,Linux RootFs 选择rootfs_rtm_2440.img  (光盘目录:image/linux/rtm ) 开发所需工具:

[Android学习系列15]下拉刷新列表实现动态加载

使用google官方的SwipeRefreshLayout 参考: http://blog.csdn.net/easyer2012/article/details/22857807 http://stormzhang.github.io/android/2014/03/29/android-swiperefreshlayout/ http://www.eoeandroid.com/thread-330439-1-1.html http://www.oschina.net/translate/sw

Unity3D的坑系列:动态加载dll

Unity3D的坑系列:动态加载dll 我现在参与的项目是做MMO手游,目标平台是Android和iOS,iOS平台不能动态加载dll(什么原因找乔布斯去),可以直接忽略,而在Android平台是可以动态加载dll的,有了这个就可以实现代码更新,不过实际上,在unity里要用上动态加载dll是有很多限制的(不了解的话就是坑). 限制1:在Android手机里动态加载dll不能使用Assembly.LoadFile(string path),只能使用Assembly.Load(byte[] raw

JDBC详解系列(二)之加载驱动

---[来自我的CSDN博客](http://blog.csdn.net/weixin_37139197/article/details/78838091)--- ??在JDBC详解系列(一)之流程中,我将数据库的连接分解成了六个步骤. JDBC流程: 第一步:加载Driver类,注册数据库驱动: 第二步:通过DriverManager,使用url,用户名和密码建立连接(Connection): 第三步:通过Connection,使用sql语句打开Statement对象: 第四步:执行语句,将结

APK动态加载框架(DL)解析

意义 这里说说这个开源项目的意义.首先要说的是动态加载技术(或者说插件化)在技术驱动型的公司中扮演这相当重要的角色,当项目越来越庞大的时候,需要通过插件化来减轻应用的内存和cpu占用,还可以实现热插拔,即在不发布新版本的情况下更新某些模块. 我 几个月前开始进行这项技术的研究,当时查询了很多资料,没有找到很好的开源.目前淘宝.微信等都有成熟的动态加载框架,包括apkplug,但是它们都是 不开源的.还有github上有一个开源项目AndroidDynamicLoader,其思想是通过Fragme

Android动态加载那些事儿

基础 1.Java 类加载器 类加载器(class loader)是 Java?中的一个很重要的概念.类加载器负责加载 Java 类的字节代码到 Java 虚拟机中.本文首先详细介绍了 Java 类加载器的基本概念,包括代理模式.加载类的具体过程和线程上下文类加载器等,接着介绍如何开发自己的类加载器,最后介绍了类加载器在 Web 容器和 OSGi?中的应用. 2.反射原理 Java 提供的反射機制允許您於執行時期動態載入類別.檢視類別資訊.生成物件或操作生成的物件,要舉反射機制的一個應用實例,就

cocos2dx3.2 异步动态加载--------保卫萝卜开发总结(一)

半个月没有更新博客,从这个项目开始学习了很多细节的东西,都不太成系统,但是却是开发上线中必须经历的东西.比如超级玛丽系列(一)中的正确的异步加载,正确的分层.正确的合成和加载plist.及时的移除未使用的cache.按照关卡动态加载当前关卡所需的资源等. 本章只分享一下异步加载的逻辑,如有不对的地方还望大家及时指出. 目前我代码中需要异步加载的资源一共有四类: 1.png    单个png的情况比较少 2.plist和png一起的打包资源 3.plist和pvr.ccz一起的打包资源 4.Coc