喜羊羊系列【设备 - 驱动器 编译进内核】

发布者:Mingyue1314最新更新时间:2025-01-07 来源: cnblogs关键字:设备  驱动器  编译  内核 手机看文章 扫描二维码
随时随地手机看文章

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


1、头文件

放进:linux-3.0.8archarmplat-samsungincludeplat

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

#includegpio.h> //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()-%dn', __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()-%dn', __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()-%dn', __func__, __LINE__);

return 0;

}


static long led_ioctl(struct file *file, unsigned int cmd, unsigned long val)

{

printk(KERN_INFO'%s()-%dn', __func__, __LINE__);

printk(KERN_INFO'cmd=%d arg=%ldn', 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_ledn');

return -ENOMEM;

}


/*1. 动态注冊/申请主设备*/

ret=alloc_chrdev_region(&led_drv->devno,0,1,'dev_module');

if (ret < 0) {

printk(KERN_ERR 'unable to get majorn');

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_classn');

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_devicen');

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;

}

关键字:设备  驱动器  编译  内核 引用地址:喜羊羊系列【设备 - 驱动器 编译进内核】

上一篇:gpiolib库详解
下一篇:Linux下简易蜂鸣器驱动代码及测试实例

推荐阅读最新更新时间:2026-03-25 12:13

编译可加载触摸屏驱动的uImage内核
pc:Centos5.4 内核:linux 3.0.1 开发板:ok6410 交叉编译器:arm-linux-gcc 4.4.1 1. make menuconfig 去掉原来的触摸屏驱动程序 - Device Drivers - Input device support - Generic input layer - Touchscreens s3c touchscreens make uImage 错误:undefined refer to s3c_device_ts 修改 arch/arm/mach-s3c64xx/目录下的makefile,将跟ts有关的.o注释掉(无用); 进入arch/a
[单片机]
wince中将自己的应用程序编译内核并开机启动的一种方法
1.准备好需要自动运行的程序,比如123.exe 2.将“123.exe”拷贝到该路径下:WINCE600OSDesignsS3C6410_DEMOS3C6410_DEMORelDirSamsung_SMDK6410_Release. 3.在pc上新建一个“123.txt”的文档,里面填入以下内容:10#Windows123.exe.之后将该文件重命名为 123.lnk 4.修改project.bib文件 FILES ; Name Path Memory 123.exe $(_FLATRELEASEDIR)123.exe NK H 123.lnk $(_FLATRELEASE
[单片机]
ATMEL AT91SAM9X25官方推荐内核编译方法
英文资料参考地址:http://www.at91.com/linux4sam/bin/view/Linux4SAM/LinuxKernel 预先安装arm-none-linux-gnueabi交叉编译工具链。可参考配置方法:http://blog.csdn.net/kumquat_cui/article/details/7651718 arm-none-linux-gnueabi交叉编译工具可以在以下网站获取:http://sourcery.mentor.com/public/gnu_toolchain/arm-none-linux-gnueabi/ (1)从https://github.com/linux4sam/l
[单片机]
TQ210 嵌入式A8环境搭建及编译内核、镜像、文件系统
ubuntu开机错误/root/.profile gedit/root/.profile mesg改为tty-s&&mesg n 编译内核错误 1.make :*** 错误 1 make:*** 错误 2 解决:解决办法:sudo apt-get install libncurses5-dev 或者:sudoapt-get install ncurses-dev zImage /home/catia/android-sdks/platform-tools/aapt: error while loading shared libraries: libz.so.1: cannot open shared object fil
[单片机]
Linux 内核驱动自动创建设备节点并挂载设备
一、首先需要在最开始定义两个数据结构: static struct class *firstdrv_class; static struct device *firstdrv_device; 二、在init函数里通过class_create和device_create函数创建相应的设备节点,示例代码如下: static int first_drv_init(void) { /* 主设备号设置为0表示由系统自动分配主设备号 */ major = register_chrdev(0, first_drv , &first_drv_fops); /* 创建firstdrv类 */ firstdr
[单片机]
迅为iMX6D/Q/PLUS设备树 Android7.1.2 系统编译
1 安装 JDK 1) Android 8.1 系统编译依赖于 JAVA 8。编译之前需安装 OpenJDK。安装命令如下: add-apt-repository ppa penjdk-r/ppa apt-get update sudo apt-get install openjdk-8-jdk 执行结果,如下图: 2)如果您之前安装过其他版本的 JDK,需要进行版本切换。如果没有安装过,可以跳过此步骤,查看目前已经安装在系统里的 Java 版本,使用以下命令: update-java-alternatives -l 查看相应的 jdk(java javac 等)是否在 ubuntu 的 jdk 菜单里,查看切换 jdk 的命
[单片机]
迅为iMX6D/Q/PLUS<font color='red'>设备</font>树 Android7.1.2 系统<font color='red'>编译</font>
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved