0

0

firefly-rk3288开发板Linux驱动——LED驱动

絕刀狂花

絕刀狂花

发布时间:2025-04-17 15:54:16

|

919人浏览过

|

来源于php中文网

原创

本文主要介绍三个部分的内容:一、准备sdk源码 二、如何操作gpio 三、led设备驱动的实现。由于firefly官方一直在对源码进行更新,所以本文只以我正在用的版本介绍。此外,官方提供的下载工具版本不同需要准备的镜像文件(.img文件)也不同,因此,这里也只介绍我正在使用的版本。 sdk版本:firefly-sdk-20200629.7z 下载工具版本:androidtool v2.58 u-boot:2017.09 linux内核:4.4.194 文件系统:buildroot

firefly-rk3288开发板Linux驱动——LED驱动

镜像文件如下,如上图所示,只会下载勾选的镜像。

代码语言:javascript代码运行次数:0运行复制
boot.img ==================>  kernel/zboot.imgMiniLoaderALL.bin =========>  /u-boot/rk3288_loader_v1.08.258.binparameter.txt =============>  device/rockchip/rk3288/parameter-buildroot.txtrecovery.img ==============>  buildroot/output/rockchip_rk3288_recovery/images/recovery.imgrootfs.img ================>  buildroot/output/rockchip_rk3288/images/rootfs.ext2trust.img =================>  u-boot/trust.imguboot.img =================>  u-boot/uboot.img
一、准备SDK源码

实际上,firefly官网已经有具体的步骤,但官网会经常更新,所以这里再简单的介绍一遍流程。

1.下载Linux-SDK源码包

这里是官网链接

firefly-rk3288开发板Linux驱动——LED驱动
2.解压Linux-SDK源码包

将下载好的Linux-SDK源码包拷贝至虚拟机,虚拟机安装好7z解压缩工具和git工具。

代码语言:javascript代码运行次数:0运行复制
7z x firefly-sdk-20200629.7z -r  #递归解压主和子目录的内容git reset --hard cd ~/proj/Firefly-RK3288#2. 下载远程 bundle 仓库git clone https://github.com/FireflyTeam/bundle.git -b rk3288-linux-bundle#3. 若 clone 失败,可以前往 github 下载 bundle.zip:#4. 更新 SDK,并且后续更新不需要再次拉取远程仓库,直接执行以下命令即可./bundle/update rk3288-linux-bundle#5. 按照提示已经更新内容到 FETCH_HEAD,同步 FETCH_HEAD 到 firefly 分支git rebase FETCH_HEAD#6. 更新共用仓库./bundle/update common-linux-bundlegit rebase FETCH_HEAD

最后需要注意本地分支是否是firefly,如果不是,切换之。

firefly-rk3288开发板Linux驱动——LED驱动

解压后文件夹如下:

firefly-rk3288开发板Linux驱动——LED驱动
3.编译Linux内核源码

这里是直接进入Linux内核源码目录下进行编译,也可以使用官方的build.sh脚本编译,这个官网有教程,这里不再介绍。

代码语言:javascript代码运行次数:0运行复制
#交叉编译器目录firefly-sdk/prebuilts/gcc/linux-x86/arm/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bincd /RK3288/firefly-sdk/kernel #进入内核源码目录export ARCH=armexport CROSS_COMPILE=arm-linux-gnueabihf-  make firefly_linux_defconfig  #使用内核默认配置make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig  # 使用图形化配置make -j8 rk3288-firefly.img #编译  此过程包含设备树、uImage、zImage的编译以及image打包过程。最终生成需要的zboot.img文件

这里仅仅介绍了内核镜像文件的生成,对于开头提到的其他文件,由于不是本文的重点,这里也不再介绍,大家可以去查看官网教程。需要注意的是内核一定要编译通过,因为后面的驱动需要能够编译通过的内核源码。

二、应用层操作GPIO

RK3288的GPIO号对应的引脚可以通过如下文件查看:

代码语言:javascript代码运行次数:0运行复制
cat /sys/kernel/debug/pinctrl/pinctrl/pins 
代码语言:javascript代码运行次数:0运行复制
[root@rk3288:/sys/kernel/debug/pinctrl/pinctrl]# cat /sys/kernel/debug/pinctrl/pinctrl/pinsregistered pins: 264pin 0 (gpio0-0)pin 1 (gpio0-1)pin 2 (gpio0-2)pin 3 (gpio0-3)pin 4 (gpio0-4)pin 5 (gpio0-5)............

开发板上两个LED对应的引脚是:

代码语言:javascript代码运行次数:0运行复制
pin 249 (gpio8-1)=====> bluepin 250 (gpio8-2)=====> yellow

可以通过export GPIO的方式操作这两个GPIO:

代码语言:javascript代码运行次数:0运行复制
[root@rk3288:/sys/class/gpio]# echo 250 > export[root@rk3288:/sys/class/gpio]# cd gpio250[root@rk3288:/sys/devices/platform/pinctrl/gpio/gpio250]# lsactive_low  device  direction  edge  power  subsystem  uevent  value[root@rk3288:/sys/devices/platform/pinctrl/gpio/gpio250]#

direction:GPIO的方向,可以设置为in或者out value:0低电平 其他值高电平

开发板上两个LED已经应用为LED子系统(gpio8-1,gpio8-2),需要取消这个应用才可以使用sys文件操作GPIO,方法如下:

ShoopD 网上商店系统
ShoopD 网上商店系统

用 php + mysql 驱动的在线商城系统,我们的目标为中国的中小企业及个人提供最简洁,最安全,最高效的在线商城解决方案,使用了自建的会员积分折扣功能,不同的会员组有不同的折扣,让您的商店吸引更多的后续客户。 系统自动加分处理功能,自动处理会员等级,免去人工处理的工作量,让您的商店运作起来更方便省事 采用了自建的直接模板技术,免去了模板解析时间,提高了代码利用效率 独立开发的购物车系统,使用最

下载
代码语言:javascript代码运行次数:0运行复制
Device Drivers > LED Support  < >   LED Support for GPIO connected LEDs 
三、LED设备驱动

前面我们已经准备好了能够编译通过的linux内核源码,现在我们可以编写Linux设备驱动了,由于我们使用的是带设备树的Linux内核,所以驱动的编写和不带设备树的内核是有一点区别的,但总体流程不变。

1.firefly-rk3288 设备树文件

firefly-rk3288 设备树文件位于/firefly-sdk/kernel/arch/arm/boot/dts目录下,对于led设备,我们需要打开rk3288-firefly.dtsi文件,找到led设备节点:

代码语言:javascript代码运行次数:0运行复制
leds {compatible = "gpio-leds";work {gpios = <&gpio8 1 GPIO_ACTIVE_LOW>;label = "firefly:blue:user";linux,default-trigger = "rc-feedback";pinctrl-names = "default";pinctrl-0 = <&work_led>;};power {gpios = <&gpio8 2 GPIO_ACTIVE_LOW>;label = "firefly:green:power";linux,default-trigger = "default-on";pinctrl-names = "default";pinctrl-0 = <&power_led>;};};

rk3288开发板共有两个led,分别对应GPIO8_A1和GPIO8_A2,但是我们在驱动程序中需要通过设备树获取到这两个GPIO的值。所以下面介绍几个常用设备树操作函数(#include ):

a.通过绝对路径,获取设备节点

代码语言:javascript代码运行次数:0运行复制
static inline struct device_node *of_find_node_by_path(const char *path)

b.通过父节点和名称,获取设备树子节点

代码语言:javascript代码运行次数:0运行复制
static inline struct device_node *of_get_child_by_name(const struct device_node *node,const char *name)

b.通过节点和名称,获取GPIO引脚号

代码语言:javascript代码运行次数:0运行复制
static inline int of_get_named_gpio(struct device_node *np,                                   const char *propname, int index)
2.firefly-rk3288 LED设备驱动编写

带设备树的LED驱动与不带设备树的驱动区别在于,带设备树的LED驱动需要在程序中从设备树中获取需要的GPIO编号,然后就是字符设备驱动的那一套流程了。

驱动源码文件如下:

代码语言:javascript代码运行次数:0运行复制
#include //模块加载卸载函数#include //内核头文件#include //数据类型定义#include //file_operations结构体#include //class_create等函数#include #include /*包含printk等操作函数*/#include /*设备树操作相关的函数*/#include /*gpio接口函数*/#include #include /*cdev_init cdev_add等函数*/#include /*gpio接口函数*/#include /*__copy_from_user 接口函数*/#define  DEVICE_NAME     "rk3288_led"typedef struct{ struct device_node *led_node;//设备树节点 int led_pin;//GPIO 引脚  struct cdev cdev;//定义一个cdev结构体 struct class *class;//创建一个LED类 struct device *device;//创建一个LED设备 该设备是需要挂在LED类下面的 int major;//主设备号 dev_t  dev_id;}led_typdef;static led_typdef ledx;//定义一个LED设备static int led_open(struct inode *inode, struct file *filp){    int ret = -1;retry:ret = gpio_request(ledx.led_pin, "led_yellow");    if(ret != 0)    {  printk("gpio %d req failed:%d\r\n",ledx.led_pin,ret);  gpio_free(ledx.led_pin);//引脚被占用(错误码-16)释放掉  goto retry;}gpio_direction_output(ledx.led_pin,0);return 0;}static int led_release(struct inode* inode ,struct file *filp){gpio_free(ledx.led_pin);return 0;}static int led_write(struct file *filp, const char __user *buf, size_t count,                loff_t *f_pos){    int ret;    unsigned char pbuf[1];ret = __copy_from_user(pbuf,buf, 1);if(ret < 0){       printk("__copy_from_user failed\r\n");   return ret;}gpio_set_value(ledx.led_pin, pbuf[0]);return 0;}static ssize_t led_read(struct file *filp, char __user *buf,size_t cnt, loff_t *offt){   return 0;}static struct file_operations led_fops={.owner= THIS_MODULE,.open = led_open,.write= led_write,.read       = led_read,.release= led_release,};static int __init led_init(void){   //struct device_node *node;   /*获取设备节点*/   ledx.led_node = of_find_node_by_path("/leds/work");   printk("/leds:%p\r\n",ledx.led_node);    if(ledx.led_node == NULL)   {  printk("find node by path fialed!\r\n");       return -1;   }   /*ledx.led_node = of_get_child_by_name(node, "user");   printk("/leds/work:%p\r\n",ledx.led_node);   if(ledx.led_node == NULL)   {  printk("get child node by name fialed!\r\n");   return -1;   }*/      /*获取GPIO信息*/   ledx.led_pin = of_get_named_gpio(ledx.led_node,"gpios",0);   printk("led_pin:%d\r\n",ledx.led_pin);   if(!gpio_is_valid(ledx.led_pin))   {      printk("get_gpio failed:%d \r\n",ledx.led_pin);  return -1;   }   /*申请设备号*/   alloc_chrdev_region(&ledx.dev_id,0,1,DEVICE_NAME);   /*初始化一个cdev*/   cdev_init(&ledx.cdev,&led_fops);      /*向cdev中添加一个设备*/   cdev_add(&ledx.cdev,ledx.dev_id,1);   /*创建一个LED类*/   ledx.class = class_create(THIS_MODULE, "led_class");   if(ledx.class == NULL)   {      printk("class_create failed\r\n");  return -1;   }   /*在LED类下创建一个LED设备*/   ledx.device = device_create(ledx.class, NULL, ledx.dev_id, NULL, DEVICE_NAME);      printk("module init ok\n");      return 0;  }static void led_exit(void){/*删除LED类*/cdev_del(&ledx.cdev);/*释放LED设备号*/unregister_chrdev_region(ledx.dev_id, 1);/*注销LED设备*/device_destroy(ledx.class, ledx.dev_id);/*注销LED类*/class_destroy(ledx.class);    printk("module exit ok\n");}module_init(led_init);module_exit(led_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("xzx2020");

MakeFile文件如下:

代码语言:javascript代码运行次数:0运行复制
obj-m:=led_driver.oPWD:=$(shell pwd)KDIR:=/RK3288/firefly-sdk/kernelall:$(MAKE) -C $(KDIR) M=$(PWD) clean:rm -rf *.ko *.order *.symvers *.cmd *.o *.mod.c *.tmp_versions .*.cmd .tmp_versions

驱动编译成功后会生成一个.ko文件,将.ko文件拷贝到开发板上并加载,出现如下提示表明驱动加载成功。

firefly-rk3288开发板Linux驱动——LED驱动

接下来,我们还需要编写一个测试APP,用于测试驱动是否正常工作,测试APP的源码如下:

代码语言:javascript代码运行次数:0运行复制
#include #include #include #include #include #include #include #include #include #include #include #include int main(void){   int fd = -1,i;   char buf[1]={0};   fd = open("/dev/rk3288_led",O_RDWR);   if(fd < 0)   {      printf("open /dev/rk3288_led fail fd=%d\n",fd);    }   for(i=0;i<50;i++)    {      buf[0] = 0;      write(fd,buf,1);      usleep(200000);      buf[0] = 1;      write(fd,buf,1);      usleep(200000);   }   fd = close(fd);   if(fd < 0)   {      printf("led test error\n");   }   return 0;   }

将上述源码用交叉编译器编译,即可生成可执行文件,将该可执行文件加上执行权限拷贝到开发上并执行,开发板的蓝色LED灯应该就开始闪烁起来了。

相关文章

驱动精灵
驱动精灵

驱动精灵基于驱动之家十余年的专业数据积累,驱动支持度高,已经为数亿用户解决了各种电脑驱动问题、系统故障,是目前有效的驱动软件,有需要的小伙伴快来保存下载体验吧!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
js获取数组长度的方法
js获取数组长度的方法

在js中,可以利用array对象的length属性来获取数组长度,该属性可设置或返回数组中元素的数目,只需要使用“array.length”语句即可返回表示数组对象的元素个数的数值,也就是长度值。php中文网还提供JavaScript数组的相关下载、相关课程等内容,供大家免费下载使用。

557

2023.06.20

js刷新当前页面
js刷新当前页面

js刷新当前页面的方法:1、reload方法,该方法强迫浏览器刷新当前页面,语法为“location.reload([bForceGet]) ”;2、replace方法,该方法通过指定URL替换当前缓存在历史里(客户端)的项目,因此当使用replace方法之后,不能通过“前进”和“后退”来访问已经被替换的URL,语法为“location.replace(URL) ”。php中文网为大家带来了js刷新当前页面的相关知识、以及相关文章等内容

374

2023.07.04

js四舍五入
js四舍五入

js四舍五入的方法:1、tofixed方法,可把 Number 四舍五入为指定小数位数的数字;2、round() 方法,可把一个数字舍入为最接近的整数。php中文网为大家带来了js四舍五入的相关知识、以及相关文章等内容

754

2023.07.04

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

478

2023.09.01

JavaScript转义字符
JavaScript转义字符

JavaScript中的转义字符是反斜杠和引号,可以在字符串中表示特殊字符或改变字符的含义。本专题为大家提供转义字符相关的文章、下载、课程内容,供大家免费下载体验。

434

2023.09.04

js生成随机数的方法
js生成随机数的方法

js生成随机数的方法有:1、使用random函数生成0-1之间的随机数;2、使用random函数和特定范围来生成随机整数;3、使用random函数和round函数生成0-99之间的随机整数;4、使用random函数和其他函数生成更复杂的随机数;5、使用random函数和其他函数生成范围内的随机小数;6、使用random函数和其他函数生成范围内的随机整数或小数。

1031

2023.09.04

如何启用JavaScript
如何启用JavaScript

JavaScript启用方法有内联脚本、内部脚本、外部脚本和异步加载。详细介绍:1、内联脚本是将JavaScript代码直接嵌入到HTML标签中;2、内部脚本是将JavaScript代码放置在HTML文件的`<script>`标签中;3、外部脚本是将JavaScript代码放置在一个独立的文件;4、外部脚本是将JavaScript代码放置在一个独立的文件。

658

2023.09.12

Js中Symbol类详解
Js中Symbol类详解

javascript中的Symbol数据类型是一种基本数据类型,用于表示独一无二的值。Symbol的特点:1、独一无二,每个Symbol值都是唯一的,不会与其他任何值相等;2、不可变性,Symbol值一旦创建,就不能修改或者重新赋值;3、隐藏性,Symbol值不会被隐式转换为其他类型;4、无法枚举,Symbol值作为对象的属性名时,默认是不可枚举的。

553

2023.09.20

excel表格操作技巧大全 表格制作excel教程
excel表格操作技巧大全 表格制作excel教程

Excel表格操作的核心技巧在于 熟练使用快捷键、数据处理函数及视图工具,如Ctrl+C/V(复制粘贴)、Alt+=(自动求和)、条件格式、数据验证及数据透视表。掌握这些可大幅提升数据分析与办公效率,实现快速录入、查找、筛选和汇总。

0

2026.01.21

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 7.5万人学习

Django 教程
Django 教程

共28课时 | 3.3万人学习

Excel 教程
Excel 教程

共162课时 | 12.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号