*針對不同的平臺。可能放進的不是以下的文件內,僅僅做參考
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 #include #include #include #include #include #include #include #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下簡易蜂鳴器驅動代碼及測試實例
- 熱門資源推薦
- 熱門放大器推薦
設計資源 培訓 開發板 精華推薦
- 直播:TI SimpleLink MCU無線平臺及軟件介紹!豐富的提問禮在這里等你~
- 參加RT-Thread軟件包賽,贏取RoboMaster等豐厚獎品!
- 一天一個Webench設計,看誰能撐30天?
- 有獎直播:TI毫米波雷達在汽車車內的應用
- TI C2000精品課暑期伴你行 學習好禮送不停
- 有獎活動 | 英飛凌新品情報站:最新 5V XENSIVTM PAS CO2 傳感器 知識挑戰賽
- 直播:TI及安富利帶你快速通過新能源汽車安全系統認證 預報名、看直播贏好禮!
- NXP微控制器電路板,針對USB Type C接口設計,評測創意有獎征集,曬心得更有多重好禮!
- 年末芯幣競價最后一期——RIGOL 數字示波器