蚂蚁S9矿板PS并发和竞争驱动 ---原子操作 参考蚂蚁S9矿板引脚定义.csdn蚂蚁S9矿板PS并发和竞争驱动 —目录.csdn蚂蚁S9矿板PS并发和竞争驱动 —原子操作.csdn蚂蚁S9矿板PS并发和竞争驱动 —自旋锁.csdn蚂蚁S9矿板PS并发和竞争驱动 —信号量.csdn蚂蚁S9矿板PS并发和竞争驱动 —互斥体.csdn驱动 atomic.koatomic.c#includelinux/types.h#includelinux/kernel.h#includelinux/delay.h#includelinux/ide.h#includelinux/init.h#includelinux/module.h#includelinux/errno.h#includelinux/gpio.h#includeasm/mach/map.h#includeasm/uaccess.h#includeasm/io.h#includelinux/cdev.h#includelinux/of.h#includelinux/of_address.h#includelinux/of_gpio.h#defineGPIOLED_CNT1/* 设备号个数 */#defineGPIOLED_NAMEgpioled/* 名字 *//* dtsled设备结构体 */structgpioled_dev{dev_tdevid;/* 设备号 */structcdevcdev;/* cdev */structclass*class;/* 类 */structdevice*device;/* 设备 */intmajor;/* 主设备号 */intminor;/* 次设备号 */structdevice_node*nd;/* 设备节点 */intled_gpio;/* LED所使用的GPIO编号 */atomic_tlock;/* 原子变量 */};staticstructgpioled_devgpioled;/* led设备 *//* * description : 打开设备 * param – inode : 传递给驱动的inode * param - filp : 设备文件file结构体有个叫做private_data的成员变量 * 一般在open的时候将private_data指向设备结构体。 * return : 0 成功;其他 失败 */staticintled_open(structinode*inode,structfile*filp){/* 通过判断原子变量的值来检查LED有没有被别的应用使用 */if(!atomic_dec_and_test(gpioled.lock)){printk(KERN_ERRgpioled: Device is busy!\n);atomic_inc(gpioled.lock);/* 小于0的话就加1,使其原子变量等于0 */return-EBUSY;/* LED被其他应用使用返回忙 */}return0;}/* * description : 从设备读取数据 * param - filp : 要打开的设备文件(文件描述符) * param - buf : 返回给用户空间的数据缓冲区 * param - cnt : 要读取的数据长度 * param - offt : 相对于文件首地址的偏移 * return : 读取的字节数如果为负值表示读取失败 */staticssize_tled_read(structfile*filp,char__user*buf,size_tcnt,loff_t*offt){return0;}/* * description : 向设备写数据 * param - filp : 设备文件表示打开的文件描述符 * param - buf : 要写给设备写入的数据 * param - cnt : 要写入的数据长度 * param - offt : 相对于文件首地址的偏移 * return : 写入的字节数如果为负值表示写入失败 */staticssize_tled_write(structfile*filp,constchar__user*buf,size_tcnt,loff_t*offt){intret;charkern_buf[1];retcopy_from_user(kern_buf,buf,cnt);// 得到应用层传递过来的数据if(0ret){printk(KERN_ERRkernel write failed!\r\n);return-EFAULT;}if(0kern_buf[0])gpio_set_value(gpioled.led_gpio,0);// 如果传递过来的数据是0则关闭ledelseif(1kern_buf[0])gpio_set_value(gpioled.led_gpio,1);// 如果传递过来的数据是1则点亮ledreturn0;}/* * description : 关闭/释放设备 * param – filp : 要关闭的设备文件(文件描述符) * return : 0 成功;其他 失败 */staticintled_release(structinode*inode,structfile*filp){/* 关闭驱动文件的时候释放原子变量 */atomic_inc(gpioled.lock);return0;}/* 设备操作函数 */staticstructfile_operationsgpioled_fops{.ownerTHIS_MODULE,.openled_open,.readled_read,.writeled_write,.releaseled_release,};staticint__initled_init(void){constchar*str;intret;/* 1.获取led设备节点 */gpioled.ndof_find_node_by_path(/led);if(NULLgpioled.nd){printk(KERN_ERRgpioled: Failed to get /led node\n);return-EINVAL;}/* 2.读取status属性 */retof_property_read_string(gpioled.nd,status,str);if(!ret){if(strcmp(str,okay))return-EINVAL;}/* 2、获取compatible属性值并进行匹配 */retof_property_read_string(gpioled.nd,compatible,str);if(0ret){printk(KERN_ERRgpioled: Failed to get compatible property\n);returnret;}if(strcmp(str,ming,led)){printk(KERN_ERRgpioled: Compatible match failed\n);return-EINVAL;}printk(KERN_INFOgpioled: device matching successful!\r\n);/* 4.获取设备树中的led-gpio属性得到LED所使用的GPIO编号 */gpioled.led_gpioof_get_named_gpio(gpioled.nd,led-gpio,0);if(!gpio_is_valid(gpioled.led_gpio)){printk(KERN_ERRgpioled: Failed to get led-gpio\n);return-EINVAL;}printk(KERN_INFOgpioled: led-gpio num %d\r\n,gpioled.led_gpio);/* 5.向gpio子系统申请使用GPIO */retgpio_request(gpioled.led_gpio,LED-GPIO);if(ret){printk(KERN_ERRgpioled: Failed to request led-gpio\n);returnret;}/* 6.将led gpio管脚设置为输出模式 */gpio_direction_output(gpioled.led_gpio,0);/* 7.初始化LED的默认状态 */retof_property_read_string(gpioled.nd,default-state,str);if(!ret){if(!strcmp(str,on))gpio_set_value(gpioled.led_gpio,1);elsegpio_set_value(gpioled.led_gpio,0);}elsegpio_set_value(gpioled.led_gpio,0);/* 8.注册字符设备驱动 *//* 创建设备号 */if(gpioled.major){gpioled.devidMKDEV(gpioled.major,0);retregister_chrdev_region(gpioled.devid,GPIOLED_CNT,GPIOLED_NAME);if(ret)gotoout1;}else{retalloc_chrdev_region(gpioled.devid,0,GPIOLED_CNT,GPIOLED_NAME);if(ret)gotoout1;gpioled.majorMAJOR(gpioled.devid);gpioled.minorMINOR(gpioled.devid);}printk(gpioled: major%d,minor%d\r\n,gpioled.major,gpioled.minor);/* 初始化cdev */gpioled.cdev.ownerTHIS_MODULE;cdev_init(gpioled.cdev,gpioled_fops);/* 添加一个cdev */retcdev_add(gpioled.cdev,gpioled.devid,GPIOLED_CNT);if(ret)gotoout2;/* 创建类 */gpioled.classclass_create(THIS_MODULE,GPIOLED_NAME);if(IS_ERR(gpioled.class)){retPTR_ERR(gpioled.class);gotoout3;}/* 创建设备 */gpioled.devicedevice_create(gpioled.class,NULL,gpioled.devid,NULL,GPIOLED_NAME);if(IS_ERR(gpioled.device)){retPTR_ERR(gpioled.device);gotoout4;}/* 9.初始化原子变量 */atomic_set(gpioled.lock,1);/* 原子变量初始值为1 */return0;out4:class_destroy(gpioled.class);out3:cdev_del(gpioled.cdev);out2:unregister_chrdev_region(gpioled.devid,GPIOLED_CNT);out1:gpio_free(gpioled.led_gpio);returnret;}staticvoid__exitled_exit(void){/* 注销设备 */device_destroy(gpioled.class,gpioled.devid);/* 注销类 */class_destroy(gpioled.class);/* 删除cdev */cdev_del(gpioled.cdev);/* 注销设备号 */unregister_chrdev_region(gpioled.devid,GPIOLED_CNT);/* 释放GPIO */gpio_free(gpioled.led_gpio);}/* 驱动模块入口和出口函数注册 */module_init(led_init);module_exit(led_exit);MODULE_AUTHOR(DengTao 773904075qq.com);MODULE_DESCRIPTION(ming ZYNQ GPIO LED Driver);MODULE_LICENSE(GPL);atomicApp.c#includestdio.h#includeunistd.h#includesys/types.h#includesys/stat.h#includefcntl.h#includestdlib.h#includestring.h/* * description : main主程序 * param - argc : argv数组元素个数 * param - argv : 具体参数 * return : 0 成功;其他 失败 */intmain(intargc,char*argv[]){intfd,ret;intcnt0;unsignedcharbuf[1];if(3!argc){printf(Usage:\n\t./atomicApp /dev/gpioled 1 close led\n\t./atomicApp /dev/gpioled 0 open led\n);return-1;}/* 打开设备 */fdopen(argv[1],O_RDWR);if(0fd){printf(ERROR: file %s open failed!\r\n,argv[1]);return-1;}/* 将字符串转换为int型数据 */buf[0]atoi(argv[2]);/* 向驱动写入数据 */retwrite(fd,buf,sizeof(buf));if(0ret){printf(ERROR: LED Control Failed!\r\n);close(fd);return-1;}/* 模拟占用25秒LED设备 */for(;;){sleep(5);cnt;printf(App running times:%d\r\n,cnt);if(cnt5)break;}printf(App running finished!\n);/* 关闭设备 */close(fd);return0;}编译驱动和app$CC-o atomicApp atomicApp.c测试rootant:~# insmod atomic.koatomic: loading out-of-tree module taints kernel. gpioled: device matching successful!gpioled: led-gpio num943gpioled:major244,minor0rootant:~# ls /dev/gpiogpiochip0 gpioled rootant:~# ls /dev/gpioled/dev/gpioled rootant:~# ./atomicApp /dev/gpioled 1App running times:1 App running times:2 App running times:3 App running times:4 App running times:5 App running finished!rootant:~# ./atomicApp /dev/gpioled 0 App running times:1 App running finished!rootant:~# ./atomicApp /dev/gpioled 0gpioled: Device is busy!ERROR:file/dev/gpioledopenfailed!

相关新闻

最新新闻

从三极管到专用芯片:LED驱动电路方案全解析与实战设计

从三极管到专用芯片:LED驱动电路方案全解析与实战设计

1. 项目概述:从“点亮”到“驱动”的跨越刚接触电子制作的朋友,第一个项目十有八九是“点亮一颗LED”。用开发板上的GPIO口,或者一个电池加个电阻,看着小灯亮起,成就感满满。但很快你就会发现,当你想让一排…

2026/7/29 4:17:55
单片机数码管驱动原理:从静态显示到动态扫描与TM1650芯片应用

单片机数码管驱动原理:从静态显示到动态扫描与TM1650芯片应用

1. 从点亮一个“8”开始:数码管显示的本质如果你刚接触单片机,点亮第一个LED灯时的兴奋感可能还记忆犹新。那么,点亮数码管,让单片机控制它显示出清晰的数字或字母,无疑是硬件编程路上的又一个里程碑。数码管&#xff…

2026/7/29 4:17:55
DBC文件制作全攻略:从CAN总线信号解析到实战工具应用

DBC文件制作全攻略:从CAN总线信号解析到实战工具应用

1. 从零开始:DBC文件到底是什么,为什么需要它?如果你正在和汽车电子、工业控制或者机器人打交道,尤其是涉及到CAN总线通信,那么“DBC文件”这个词你肯定绕不过去。我第一次接触DBC文件时,也犯过嘀咕&#x…

2026/7/29 4:17:55
滤波电容选型实战:从理论到应用,打造稳定电源系统

滤波电容选型实战:从理论到应用,打造稳定电源系统

1. 项目概述:从“能用”到“好用”的滤波电容选型实战在电子电路设计的江湖里,滤波电容绝对算得上是一位“扫地僧”级别的存在。它看似平平无奇,规格书上无非是容量、耐压、尺寸、材质,但真正用起来,选对了是“润物细无…

2026/7/29 4:17:55
等保2.0下交换机安全配置:5大高频漏洞加固与实战指南

等保2.0下交换机安全配置:5大高频漏洞加固与实战指南

1. 项目概述:为什么交换机安全配置是等保2.0的“咽喉要道”干了这么多年网络运维和安全合规,我越来越觉得,交换机这玩意儿,就像家里的总电闸。平时没人注意它,一旦出问题,整个网络都得“停电”。尤其是在等…

2026/7/29 4:17:55
从LED驱动到MCU控制:一个硬件工程师的汽车尾灯模组实战设计全解析

从LED驱动到MCU控制:一个硬件工程师的汽车尾灯模组实战设计全解析

1. 项目概述:从“尾灯模组”说起,一个硬件工程师的实战拆解“尾灯模组”这四个字,在汽车电子、消费电子乃至创客圈里,都是一个既经典又充满挑战的课题。乍一看,它不就是让几个LED亮起来、灭下去,再搞点流水…

2026/7/29 4:12:54

月新闻