日期:2014-05-16 浏览次数:20870 次
看了这么多内核代码,终于要自己开始做驱动了.按照由易到难,由浅入深的顺序,就从LED开始.
LED驱动可以说是hello world之后最简单的驱动模块了.如果自己写一个LED驱动那是很简单的,其实用linux内核中的leds子系统来做也是比较简单的,内核中的leds子系统是将led抽象成platform_device,并有leds_class.这样,在/sys/class/leds/目录下面就可以利用sysfs文件系统来实现LED的操作.其实,也可以在此基础上添加/dev访问的接口,甚至用不着包含mknod的脚本和udev等工具,在模块注册后就可以生成/dev下的设备文件.
一步一步的来,首先利用platform虚拟总线来实现sysfs文件系统下的LED操作.
在mach-smdk2440.c中新增platform_device如下:
static struct platform_device smdk_led5 = { .name = "s3c24xx_led", .id = 0, .dev = { .platform_data = &smdk_pdata_led5, .release = &platform_led_release, }, };对于具体的板子,是GPB5-8对应四个LED,所以这里smdk_pdata_led5的定义如下:
static struct s3c24xx_led_platdata smdk_pdata_led5 = { .gpio = S3C2410_GPB(5), .flags = S3C24XX_LEDF_ACTLOW ,//| S3C24XX_LEDF_TRISTATE, .name = "led5", //.def_trigger = "nand-disk", };接着在static struct platform_device *smdk2440_devices[] __initdata中新增&smdk_led5,这样系统在启动时就会由smdk2440_machine_init调用platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices));来添加刚才加上的platform_device.
看完了platform_device再看下platform_driver是如何注册的:
在drivers/leds目录下的Makefile中有obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o
所以在make menuconfig的时候记得将其选为M.
这样,注册leds-s3c24xx.ko就会在/sys/class/leds中有
led5 led6 led7 led8四个目录,进入led5目录,有
brightness device power trigger
dev max_brightness subsystem uevent
执行echo 0 > brightness就可以关闭led,而echo 1 > brightness就可以打开led.
因为有leds_class,而在led-class.c中leds-init函数中有leds_class->dev_attrs = led_class_attrs;
其中,led_class_attrs定义如下
static struct device_attribute led_class_attrs[] = { __ATTR(brightness, 0644, led_brightness_show, led_brightness_store), __ATTR(max_brightness, 0444, led_max_brightness_show, NULL), #ifdef CONFIG_LEDS_TRIGGERS __ATTR(trigger, 0644, led_trigger_show, led_trigger_store), #endif __ATTR_NULL, };根据sysfs的属性文件,读写属性文件最终调用的就是show和store函数,在这里就是led_brightness_show和led_brightness_store函数.
到此,就可以通过sysfs文件系统来访问led设备了.
那么,开头说的在此基础如何做/dev访问的接口呢?
在leds目录下新建一个文件led-dev.c
在Makefile中添加obj-$(CONFIG_LEDS_INTF_DEV)
+= led-dev.o