网站设计网站源码,怎么介绍自己的学校,网站的搜索引擎,网站服务器做哪些安全措施以下内容源于朱有鹏嵌入式课程的学习与整理#xff0c;如有侵权请告知删除。
参考博客 platform总线驱动代码分析 平台设备与平台驱动的注册_天糊土的博客-CSDN博客 一、有driver无device 本节把之前的LED驱动源码改写成平台总线制式#xff0c;先实现platform_driver。 1、…以下内容源于朱有鹏嵌入式课程的学习与整理如有侵权请告知删除。
参考博客 platform总线驱动代码分析 平台设备与平台驱动的注册_天糊土的博客-CSDN博客 一、有driver无device 本节把之前的LED驱动源码改写成平台总线制式先实现platform_driver。 1、代码示例 #include linux/module.h // module_init module_exit
#include linux/init.h // __init __exit
#include linux/fs.h
#include linux/leds.h
#include mach/regs-gpio.h
#include mach/gpio-bank.h
#include linux/io.h
#include linux/ioport.h
#include mach/gpio.h
#include linux/platform_device.h
#include mach/leds-gpio.h
#include linux/slab.h#define X210_LED_OFF 1 // X210中LED是正极接电源负极节GPIO
#define X210_LED_ON 0 // 所以1是灭0是亮struct s5pv210_gpio_led {struct led_classdev cdev;struct s5pv210_led_platdata *pdata;
};static inline struct s5pv210_gpio_led *pdev_to_gpio(struct platform_device *dev)
{return platform_get_drvdata(dev);
}static inline struct s5pv210_gpio_led *to_gpio(struct led_classdev *led_cdev)
{return container_of(led_cdev, struct s5pv210_gpio_led, cdev);
}// 这个函数就是要去完成具体的硬件读写任务的
static void s5pv210_led_set(struct led_classdev *led_cdev,enum led_brightness value)
{struct s5pv210_gpio_led *p to_gpio(led_cdev);printk(KERN_INFO s5pv210_led_set\n);// 在这里根据用户设置的值来操作硬件// 用户设置的值就是valueif (value LED_OFF){// 用户给了个0希望LED灭gpio_set_value(p-pdata-gpio, X210_LED_OFF);}else{// 用户给的是非0希望LED亮gpio_set_value(p-pdata-gpio, X210_LED_ON);}
}static int s5pv210_led_probe(struct platform_device *dev)
{// 用户insmod安装驱动模块时会调用该函数// 该函数的主要任务就是去使用led驱动框架提供的设备注册函数来注册一个设备int ret -1;struct s5pv210_led_platdata *pdata dev-dev.platform_data;struct s5pv210_gpio_led *led;printk(KERN_INFO ----s5pv210_led_probe---\n);led kzalloc(sizeof(struct s5pv210_gpio_led), GFP_KERNEL);if (led NULL) {dev_err(dev-dev, No memory for device\n);return -ENOMEM;}platform_set_drvdata(dev, led);// 在这里去申请驱动用到的各种资源当前驱动中就是GPIO资源if (gpio_request(pdata-gpio, pdata-name)) {printk(KERN_ERR gpio_request failed\n);} else {// 设置为输出模式并且默认输出1让LED灯灭gpio_direction_output(pdata-gpio, 1);}// led1led-cdev.name pdata-name;led-cdev.brightness 0; led-cdev.brightness_set s5pv210_led_set;led-pdata pdata;ret led_classdev_register(dev-dev, led-cdev);if (ret 0) {printk(KERN_ERR led_classdev_register failed\n);return ret;}return 0;
}static int s5pv210_led_remove(struct platform_device *dev)
{struct s5pv210_gpio_led *p pdev_to_gpio(dev);led_classdev_unregister(p-cdev);gpio_free(p-pdata-gpio);kfree(p); // kfee放在最后一步return 0;
}static struct platform_driver s5pv210_led_driver {.probe s5pv210_led_probe,.remove s5pv210_led_remove,.driver {.name s5pv210_led,.owner THIS_MODULE,},
};static int __init s5pv210_led_init(void)
{return platform_driver_register(s5pv210_led_driver);
}static void __exit s5pv210_led_exit(void)
{platform_driver_unregister(s5pv210_led_driver);
}module_init(s5pv210_led_init);
module_exit(s5pv210_led_exit);// MODULE_xxx这种宏作用是用来添加模块描述信息
MODULE_LICENSE(GPL); // 描述模块的许可证
MODULE_AUTHOR(xjh 735503242qq.com); // 描述模块的作者
MODULE_DESCRIPTION(s5pv210 led driver); // 描述模块的介绍信息
MODULE_ALIAS(s5pv210_led); // 描述模块的别名信息 2、实测现象 在虚拟机上通过Makefile进行编译之后在开发板上测试结果如下。 [rootxjh ~]# cd /mnt
[rootxjh mnt]# ls
Makefile driver_test.c driver_test.mod.o
Module.symvers driver_test.ko driver_test.o
app.c driver_test.mod.c modules.order
[rootxjh mnt]# insmod driver_test.ko
[rootxjh mnt]# cd /sys/bus/platform/drivers/
[rootxjh drivers]# pwd
/sys/bus/platform/drivers
[rootxjh drivers]# ls
alarm ram_console s3c-pl330 s5pv210-nand
android_pmem reg-s5pv210-pd s3c-sdhci s5pv210-uart
arm-pmu s3c-adc s3c-ts s5pv210_led //这里出现
dm9000 s3c-button s3c24xx-pwm sec-fake-battery
i2c-gpio s3c-csis s3c64xx-iis smdkc110-rtc
max8698-pmic s3c-fimc s3cfb soc-audio
pm-wifi s3c-g2d s5p-cec switch-gpio
power s3c-i2c s5p-ehci timed-gpio
pvrsrvkm s3c-jpg s5p-hpd
pwm-backlight s3c-mfc s5p-tvout
[rootxjh drivers]# cd s5pv210_led/
[rootxjh s5pv210_led]# ls
bind module uevent unbind
[rootxjh s5pv210_led]# cd ..
[rootxjh drivers]# rmmod /mnt/driver_test.ko
[rootxjh drivers]# ls //卸载之后不再出现s5pv210_led
alarm ram_console s3c-pl330 s5pv210-nand
android_pmem reg-s5pv210-pd s3c-sdhci s5pv210-uart
arm-pmu s3c-adc s3c-ts sec-fake-battery
dm9000 s3c-button s3c24xx-pwm smdkc110-rtc
i2c-gpio s3c-csis s3c64xx-iis soc-audio
max8698-pmic s3c-fimc s3cfb switch-gpio
pm-wifi s3c-g2d s5p-cec timed-gpio
power s3c-i2c s5p-ehci
pvrsrvkm s3c-jpg s5p-hpd
pwm-backlight s3c-mfc s5p-tvout
[rootxjh drivers]# 由上可知在/sys/bus/platform/driver下有驱动s5pv210_led因为该程序中有如下片段。 static struct platform_driver s5pv210_led_driver {.probe s5pv210_led_probe,.remove s5pv210_led_remove,.driver {.name s5pv210_led, //驱动的名字.owner THIS_MODULE,},
};static int __init s5pv210_led_init(void)
{return platform_driver_register(s5pv210_led_driver);
} 但驱动程序中的probe函数不会被执行因为这里只是driver单方面的注册没有device。 二、有device无driver 本节分析系统移植时的mach文件添加与LED相关的platform_device并进行设备注册。 通过在x210_kernel/arch/arm/mach-s5pv210/mach-x210.c文件中搜索platform_device数组发现其没有LED平台设备。 static struct platform_device *smdkc110_devices[] __initdata {
#ifdef CONFIG_FIQ_DEBUGGERs5pv210_device_fiqdbg_uart2,
#endif
//省略部分代码这里没有LED相关的平台设备headset_switch_device,
}; 于是参考x210_kernel/arch/arm/mach-s3c2440/mach-mini2440.c文件在mach-x210.c中添加LED相关的platform_device定义。 步骤1在mach-x210.c文件中合适位置处定义LED平台设备 static struct platform_device x210_led1 {.name s5pv210_led,//注意这里的设备名字要与驱动的名字一致才能匹配.id 1, //这个id最终影响为s5pv210_led.1的后缀.dev {.platform_data x210_led1_pdata,}
};步骤2编写头文件x210_kernel/arch/arm/mach-s5pv210/include/mach/leds-gpio.h 在x210_kernel/arch/arm/mach-s5pv210/include/mach目录下原本没有leds-gpio.h文件。我们参考x210_kernel/arch/arm/mach-s3c2410/include/mach/leds-gpio.h来编写头文件从而对struct s5pv210_led_platdata这个结构体进行声明。代码如下。 /* arch/arm/mach-s5pv210/include/mach/leds-gpio.h** Copyright (c) 2006 Simtec Electronics* http://armlinux.simtec.co.uk/* Ben Dooks bensimtec.co.uk** s5pv210 - LEDs GPIO connector** This program is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License version 2 as* published by the Free Software Foundation.
*/#ifndef __ASM_ARCH_LEDSGPIO_H
#define __ASM_ARCH_LEDSGPIO_H leds-gpio.h#define S5PV210_LEDF_ACTLOW (10) /* LED is on when GPIO low */
#define S5PV210_LEDF_TRISTATE (11) /* tristate to turn off */struct s5pv210_led_platdata {unsigned int gpio;unsigned int flags;char *name;char *def_trigger;
};#endif /* __ASM_ARCH_LEDSGPIO_H */ 步骤3在mach-x210.c文件里实例化struct s5pv210_led_platdata这个结构体 首先在mach-x210.c文件开头位置添加 “ #include mach/leds-gpio.h ”。 然后参考mach-mini2440.c文件实例化结构体struct s5pv210_led_platdata代码如下。 /* LEDS */static struct s5pv210_led_platdata x210_led1_pdata {.name led1,.gpio S5PV210_GPJ0(3), //这个要根据数据手册得知.flags S5PV210_LEDF_ACTLOW | S5PV210_LEDF_TRISTATE,.def_trigger heartbeat, //上面以及这个都是私有的扩展数据
}; 步骤4将LED平台设备添加到platform_device数组中 static struct platform_device *smdkc110_devices[] __initdata {
#ifdef CONFIG_FIQ_DEBUGGERs5pv210_device_fiqdbg_uart2,
#endif
//省略部分代码这里没有LED相关的平台设备headset_switch_device,x210_led1,//added by xjh
}; 步骤5执行make以重新编译内核 由于只是修改几个文件不需要全部重新编译因此编译时间很短。 注意这里不需要make clean、make distclean、配置等操作直接make即可。 步骤6测试只有platform_device而没有platform_driver时的效果 将编译生成的内核镜像zImage在x210_kernel/arch/arm/boot目录下拷贝至tftp服务器共享目录下然后启动开发板对比前后的情形。注意LED平台设备不需要手动加载它集成到内核中了。由实验结果可知因为没有加载platform_driver因此只有platform_device。 [rootxjh devices]# pwd
/sys/bus/platform/devices
[rootxjh devices]# ls
alarm s3c-adc s3c-sdhci.2 s5p-cec
android_pmem.1 s3c-button s3c-sdhci.3 s5p-ehci
arm-pmu.0 s3c-csis s3c-ts s5p-hpd
dm9000.0 s3c-fimc.0 s3c2410-wdt s5p-tvout
pm-wifi s3c-fimc.1 s3c2440-i2c.0 s5pv210-nand
power.0 s3c-fimc.2 s3c2440-i2c.1 s5pv210-uart.0
pvrsrvkm s3c-g2d s3c2440-i2c.2 s5pv210-uart.1
pwm-backlight s3c-jpg s3c24xx-pwm.0 s5pv210-uart.2
reg-s5pv210-pd.0 s3c-keypad s3c24xx-pwm.1 s5pv210-uart.3
reg-s5pv210-pd.1 s3c-mfc s3c24xx-pwm.2 s5pv210_led.1 //这里
reg-s5pv210-pd.2 s3c-pl330.0 s3c24xx-pwm.3 sec-fake-battery
reg-s5pv210-pd.3 s3c-pl330.1 s3c64xx-iis.0 smdkc110-rtc
reg-s5pv210-pd.4 s3c-pl330.2 s3c64xx-iis.1 soc-audio.1
reg-s5pv210-pd.5 s3c-sdhci.0 s3c_lcd switch-gpio
regulatory.0 s3c-sdhci.1 s3cfb x210-led //这里为何出现
[rootxjh devices]# 题外话设备驱动框架2——基于驱动框架写LED驱动具体操作层 x210-led之所以出现是在x210_kernel/drivers/char/led/x210-led.c进行了平台设备注册。我忘记去除九鼎移植的LED驱动了。如果去除则不再出现x210-led。 static struct platform_driver x210_led_driver {.probe x210_led_probe,.remove x210_led_remove,.suspend x210_led_suspend,.resume x210_led_resume,.driver {.name x210-led,},
};static struct platform_device x210_led_device {.name x210-led,.id -1,
};static int __devinit x210_led_init(void)
{int ret;printk(x210 led driver\r\n);ret platform_device_register(x210_led_device);if(ret)printk(failed to register x210 led device\n);ret platform_driver_register(x210_led_driver);if(ret)printk(failed to register x210 led driver\n);return ret;
}static void x210_led_exit(void)
{platform_driver_unregister(x210_led_driver);
}module_init(x210_led_init);
module_exit(x210_led_exit);MODULE_LICENSE(GPL);
MODULE_AUTHOR(jianjun jiang jerryjianjungmail.com);
MODULE_DESCRIPTION(x210 led driver); [rootxjh devices]# cd x210-led/
[rootxjh x210-led]# ls
driver led2 led4 power uevent
led1 led3 modalias subsystem
[rootxjh x210-led]# echo 1 led1
[rootxjh x210-led]# cat led1
1
[rootxjh x210-led]# echo 0 led1
[rootxjh x210-led]# cat led1
0
[rootxjh x210-led]# 回归正题 屏蔽之前的所有修改则/sys/bus/platform/devices的内容如下不再有s5pv210_led.1。 [rootxjh devices]# pwd
/sys/bus/platform/devices
[rootxjh devices]# ls
alarm s3c-adc s3c-sdhci.2 s5p-cec
android_pmem.1 s3c-button s3c-sdhci.3 s5p-ehci
arm-pmu.0 s3c-csis s3c-ts s5p-hpd
dm9000.0 s3c-fimc.0 s3c2410-wdt s5p-tvout
pm-wifi s3c-fimc.1 s3c2440-i2c.0 s5pv210-nand
power.0 s3c-fimc.2 s3c2440-i2c.1 s5pv210-uart.0
pvrsrvkm s3c-g2d s3c2440-i2c.2 s5pv210-uart.1
pwm-backlight s3c-jpg s3c24xx-pwm.0 s5pv210-uart.2
reg-s5pv210-pd.0 s3c-keypad s3c24xx-pwm.1 s5pv210-uart.3
reg-s5pv210-pd.1 s3c-mfc s3c24xx-pwm.2 sec-fake-battery
reg-s5pv210-pd.2 s3c-pl330.0 s3c24xx-pwm.3 smdkc110-rtc
reg-s5pv210-pd.3 s3c-pl330.1 s3c64xx-iis.0 soc-audio.1
reg-s5pv210-pd.4 s3c-pl330.2 s3c64xx-iis.1 switch-gpio
reg-s5pv210-pd.5 s3c-sdhci.0 s3c_lcd x210-led
regulatory.0 s3c-sdhci.1 s3cfb
[rootxjh devices]# 可以同理操作完成其他LED平台设备的注册。 另外也可以将设备进行模块化地安装与卸载。见参考博客。 三、金风玉露一相逢 本节测试platform_device和platform_driver相遇时的情形。 由第二节可知设备已经集成到内核只要加载驱动就好。platform_driver如果加载成功将会执行platform_driver的probe函数。我们可以在probe函数中添加printk信息来验证见第一节的代码示例中的probe函数。 static int s5pv210_led_probe(struct platform_device *dev)
{
//省略部分代码printk(KERN_INFO ----s5pv210_led_probe---\n);//省略部分代码
} 实验现象如下 [rootxjh mnt]# insmod driver_test.ko
[ 70.047805] ----s5pv210_led_probe--- //由此可见的确执行了驱动的probe函数
[rootxjh mnt]# cd /sys/bus/platform/drivers/
[rootxjh drivers]# ls
alarm ram_console s3c-pl330 s5pv210-nand
android_pmem reg-s5pv210-pd s3c-sdhci s5pv210-uart
arm-pmu s3c-adc s3c-ts s5pv210_led //这里
dm9000 s3c-button s3c24xx-pwm sec-fake-battery
i2c-gpio s3c-csis s3c64xx-iis smdkc110-rtc
max8698-pmic s3c-fimc s3cfb soc-audio
pm-wifi s3c-g2d s5p-cec switch-gpio
power s3c-i2c s5p-ehci timed-gpio
pvrsrvkm s3c-jpg s5p-hpd
pwm-backlight s3c-mfc s5p-tvout
[rootxjh drivers]# cd s5pv210_led/
[rootxjh s5pv210_led]# ls
bind module s5pv210_led.1 uevent unbind
// s5pv210_led.1 这个是执行probe函数产生的有别于以前只有driver的那个
[rootxjh s5pv210_led]# cd s5pv210_led.1/
[rootxjh s5pv210_led.1]# ls
driver leds modalias power subsystem uevent
[rootxjh s5pv210_led.1]# cd leds/
[rootxjh leds]# ls
led1
[rootxjh leds]# cd led1/
[rootxjh led1]# pwd //不同目录内容一样啊
/sys/bus/platform/drivers/s5pv210_led/s5pv210_led.1/leds/led1
[rootxjh led1]# ls
brightness max_brightness subsystem
device power uevent
[rootxjh led1]# cat brightness
0
[rootxjh led1]# echo 1 brightness
[ 497.303247] s5pv210_led_set
[rootxjh led1]# cd /sys/class/leds
[rootxjh leds]# ls
led1 mmc0:: mmc1:: mmc2:: mmc3::
[rootxjh leds]# cd led1/
[rootxjh led1]# pwd
/sys/class/leds/led1 //不同目录内容一样啊
[rootxjh led1]# ls
brightness max_brightness subsystem
device power uevent
[rootxjh led1]#