完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
(1)新建并编辑gpio_led_control.c
在目录/home/sgw/prj/Firefly-RK3308/kernel/drivers/test下,新建gpio_led_control.c $ touch gpio_led_control.c $ gedit gpio_led_conrtol.c gpio_led_control.c内容 我的开发板是RCC-RK3308B-CC-PLUS,LED的端口号是10 #include #include #include #include #include #include #include #include #include MODULE_AUTHOR("Downey"); MODULE_LICENSE("GPL"); static int majorNumber = 0; /*Class 名称,对应/sys/class/下的目录名称*/ static const char *CLASS_NAME = "led_control_class"; /*Device 名称,对应/dev下的目录名称*/ static const char *DEVICE_NAME = "led_control_demo"; static int led_control_open(struct inode *node, struct file *file); static ssize_t led_control_read(struct file *file,char *buf, size_t len,loff_t *offset); static ssize_t led_control_write(struct file *file,const char *buf,size_t len,loff_t* offset); static int led_control_release(struct inode *node,struct file *file); #define LED_PIN 10 static int gpio_status; static char recv_msg[20]; static struct class *led_control_class = NULL; static struct device *led_control_device = NULL; /*File opertion 结构体,我们通过这个结构体建立应用程序到内核之间操作的映射*/ static struct file_operations file_oprts = { .open = led_control_open, .read = led_control_read, .write = led_control_write, .release = led_control_release, }; static void gpio_config(void) { if(!gpio_is_valid(LED_PIN)){ printk(KERN_ALERT "Error wrong gpio numbern"); return ; } gpio_request(LED_PIN,"led_ctr"); gpio_direction_output(LED_PIN,1); gpio_set_value(LED_PIN,1); gpio_status = 1; } static void gpio_deconfig(void) { gpio_free(LED_PIN); } static int __init led_control_init(void) { printk(KERN_ALERT "Driver initrn"); /*注册一个新的字符设备,返回主设备号*/ majorNumber = register_chrdev(0,DEVICE_NAME,&file_oprts); if(majorNumber < 0 ){ printk(KERN_ALERT "Register failed!!rn"); return majorNumber; } printk(KERN_ALERT "Registe success,major number is %drn",majorNumber); /*以CLASS_NAME创建一个class结构,这个动作将会在/sys/class目录创建一个名为CLASS_NAME的目录*/ led_control_class = class_create(THIS_MODULE,CLASS_NAME); if(IS_ERR(led_control_class)) { unregister_chrdev(majorNumber,DEVICE_NAME); return PTR_ERR(led_control_class); } /*以DEVICE_NAME为名,参考/sys/class/CLASS_NAME在/dev目录下创建一个设备:/dev/DEVICE_NAME*/ led_control_device = device_create(led_control_class,NULL,MKDEV(majorNumber,0),NULL,DEVICE_NAME); if(IS_ERR(led_control_device)) { class_destroy(led_control_class); unregister_chrdev(majorNumber,DEVICE_NAME); return PTR_ERR(led_control_device); } printk(KERN_ALERT "led_control device init success!!rn"); return 0; } /*当用户打开这个设备文件时,调用这个函数*/ static int led_control_open(struct inode *node, struct file *file) { printk(KERN_ALERT "GPIO init n"); gpio_config(); return 0; } /*当用户试图从设备空间读取数据时,调用这个函数*/ static ssize_t led_control_read(struct file *file,char *buf, size_t len,loff_t *offset) { int cnt = 0; /*将内核空间的数据copy到用户空间*/ cnt = copy_to_user(buf,&gpio_status,1); if(0 == cnt){ return 0; } else{ printk(KERN_ALERT "ERROR occur when reading!!n"); return -EFAULT; } return 1; } /*当用户往设备文件写数据时,调用这个函数*/ static ssize_t led_control_write(struct file *file,const char *buf,size_t len,loff_t *offset) { /*将用户空间的数据copy到内核空间*/ int cnt = copy_from_user(recv_msg,buf,len); if(0 == cnt){ if(0 == memcmp(recv_msg,"on",2)) { printk(KERN_INFO "LED ON!n"); gpio_set_value(LED_PIN,1); gpio_status = 1; } else { printk(KERN_INFO "LED OFF!n"); gpio_set_value(LED_PIN,0); gpio_status = 0; } } else{ printk(KERN_ALERT "ERROR occur when writing!!n"); return -EFAULT; } return len; } /*当用户打开设备文件时,调用这个函数*/ static int led_control_release(struct inode *node,struct file *file) { printk(KERN_INFO "Release!!n"); gpio_deconfig(); return 0; } /*销毁注册的所有资源,卸载模块,这是保持linux内核稳定的重要一步*/ static void __exit led_control_exit(void) { device_destroy(led_control_class,MKDEV(majorNumber,0)); class_unregister(led_control_class); class_destroy(led_control_class); unregister_chrdev(majorNumber,DEVICE_NAME); } module_init(led_control_init); module_exit(led_control_exit); (2)编辑Makefile文件 $ gedit Makefile Makefile内容 obj-m+=hello_world.o gpio_led_control.o all: make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) clean (3)编译生成.ko文件 回到/home/sgw/prj/Firefly-RK3308/kernel路径下 $ make (4)adb推到开发板 回到/home/sgw/prj/Firefly-RK3308/kernel/drivers/test目录 $ adb push gpio_led_control.ko mnt/ (5)新建并编辑gpio_led_contro_user.c文件 $ touch gpio_led_contro_user.c $ gedit gpio_led_control_user.c gpio_led_control_user.c内容 #include #include #include #include #include #include static char buf[256] = {1}; int main(int argc,char *argv[]) { int fd = open("/dev/led_control_demo",O_RDWR); if(fd < 0) { perror("Open file failed!!!rn"); return -1; } while(1){ printf("Please input scanf("%s",buf); if(strlen(buf) > 3){ printf("Ivalid input!n"); } else { int ret = write(fd,buf,strlen(buf)); if(ret < 0){ perror("Failed to write!!"); } } } close(fd); return 0; } (6)交叉编译gpio_led_contro_user.c 根据Firefly官网介绍,Builroot的编译工具链是buildroot/output/firefly_rk3308_release/host/bin/aarch64-rockchip-linux-gnu- $ /home/sgw/prj/Firefly-RK3308/buildroot/output/firefly_rk3308_release/host/bin/aarch64-rockchip-linux-gnu-gcc gpio_led_contro_user.c -o user (7)adb推进开发板 $ adb push user mnt/ (8)adb进入开发板加载并执行 $ adb shell /mnt # insmod gpio_led_control.ko /mnt # ./user Please input on Please input off Please input 可以看到开发板上的LED灯会亮灭。 |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
1040 浏览 3 评论
rk1126实现BT601输入,输入不带IIC接口的驱动程序
2671 浏览 0 评论
2216 浏览 1 评论
3418 浏览 3 评论
RK3568 Android11让系统ntp校准时间生效,需要设置些什么
3718 浏览 1 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-9-8 13:17 , Processed in 0.661580 second(s), Total 74, Slave 56 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191