openwrt通过字符驱动的方式控制LED灯光

羽林君 2023-08-31 22:11



1、概述

通过在openwrt源码目录下(或者SDK包的openwrt的目录下)编写gpio的字符驱动生成ipk包,发送到开发板上insmod加载驱动,然后通过编写APP来进行测试。

2、在源码目录的 ./package/kernel下创建gpio_control_driver文件夹

  1. mkdir gpio_control_driver

3、在gpio_control_driver文件夹下创建Makefile和src文件夹

  1. mkdir src

  2. touch Makefile

4、编写Makefile

  1. include $(TOPDIR)/rules.mk

  2. include $(INCLUDE_DIR)/kernel.mk

  3. PKG_NAME:=gpio_control_driver

  4. PKG_RELEASE:=1

  5. include $(INCLUDE_DIR)/package.mk

  6. define KernelPackage/$(PKG_NAME)

  7. SUBMENU:=Other modules

  8. DEPENDS:=@GPIO_SUPPORT

  9. TITLE:=Driver for FA156 gpios control

  10. FILES:=$(PKG_BUILD_DIR)/gpio_control_driver.ko

  11. AUTOLOAD:=$(call AutoLoad,30,gpio_control_driver)

  12. endef

  13. define KernelPackage/$(PKG_NAME)/description

  14. Kernel module to control gpios for FA156

  15. endef

  16. define Build/Prepare

  17. mkdir -p $(PKG_BUILD_DIR)

  18. cp -rf ./src/* $(PKG_BUILD_DIR)/

  19. endef

  20. define Build/Compile

  21. $(MAKE) -C "$(LINUX_DIR)" \

  22. CROSS_COMPILE="$(TARGET_CROSS)" \

  23. ARCH="$(LINUX_KARCH)" \

  24. SUBDIRS="$(PKG_BUILD_DIR)" \

  25. EXTRA_CFLAGS="$(BUILDFLAGS)" \

  26. $(EXTRA_KCONFIG) \

  27. modules

  28. endef

  29. $(eval $(call KernelPackage,$(PKG_NAME)))

makefile注释在https://editor.csdn.net/md/?articleId=109803571这篇文章里,我详细注释了。

5、进入src目录下创建gpio_control_driver.c 、 Makefile

  1. touch gpio_control_driver.c

  2. touch Makefile

6、编写gpio_control_driver.c 、Makefile

Makefile:

  1. obj-m := gpio_control_driver.o

gpio_control_driver.c:

  1. #include

  2. #include

  3. #include

  4. #include

  5. #include

  6. #include

  7. #include

  8. #include

  9. #include

  10. #include

  11. #include

  12. #include

  13. #define NEWCHRLED_CNT 1

  14. #define NEWCHRLED_NAME "gpio_control"

  15. #define GPIO_CONTROL_SET_OUT 0x01

  16. #define GPIO_CONTROL_SET_IN 0x02

  17. //#define GPIO_CONTROL_GET_DIRECTION 0x03

  18. #define GPIO_CONTROL_SET_VALUE 0x04

  19. #define GPIO_CONTROL_GET_VALUE 0x05

  20. #define GPIO_CONTROL_REQUEST_GPIO 0x06

  21. #define GPIO_CONTROL_FREE_GPIO 0x07

  22. #define GET_GPIO_NUM(arg1) (unsigned char)((arg1 >> 24) & 0xff)

  23. #define GET_GPIO_VALUE(arg1) (unsigned char)((arg1 >> 16) & 0xff)

  24. struct gpio_control_dev{

  25. dev_t devid;

  26. struct cdev cdev;

  27. struct class *class;

  28. struct device *device;

  29. int major;

  30. int minor;

  31. };

  32. struct gpio_control_dev gpio_control;

  33. static int gpio_control_open(struct inode *pinode, struct file *pfile)

  34. {

  35. printk("***%s***\n",__func__);

  36. return 0;

  37. }

  38. static int gpio_control_release(struct inode *pinode, struct file *pfile)

  39. {

  40. printk("***%s***\n",__func__);

  41. return 0;

  42. }

  43. static long gpio_control_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg)

  44. {

  45. int ret;

  46. unsigned char gpio_number;

  47. unsigned char gpio_value;

  48. gpio_number = GET_GPIO_NUM(arg);

  49. gpio_value = GET_GPIO_VALUE(arg);

  50. switch (cmd){

  51. case GPIO_CONTROL_SET_OUT:

  52. ret = gpio_direction_output(gpio_number, gpio_value);

  53. if (ret < 0){

  54. return -1;

  55. }

  56. break;

  57. case GPIO_CONTROL_SET_IN:

  58. ret = gpio_direction_input(gpio_number);

  59. if (ret < 0){

  60. return -1;

  61. }

  62. break;

  63. case GPIO_CONTROL_SET_VALUE:

  64. gpio_set_value(gpio_number, gpio_value);

  65. break;

  66. case GPIO_CONTROL_GET_VALUE:

  67. ret = gpio_get_value(gpio_number);

  68. if (ret < 0){

  69. return -1;

  70. }

  71. break;

  72. case GPIO_CONTROL_REQUEST_GPIO:

  73. if (0 > gpio_request(gpio_number, "gpio_ctrl")){

  74. return -1;

  75. }

  76. break;

  77. case GPIO_CONTROL_FREE_GPIO:

  78. gpio_free(gpio_number);

  79. break;

  80. default:

  81. printk("***Unknown command:0x%02X\n***\n", cmd);

  82. break;

  83. }

  84. return 0;

  85. }

  86. static const struct file_operations gpio_control_ops = {

  87. .owner = THIS_MODULE,

  88. .open = gpio_control_open,

  89. .release = gpio_control_release,

  90. .unlocked_ioctl = gpio_control_ioctl,

  91. };

  92. static int __init led_init(void)

  93. {

  94. unsigned int ret = 0;

  95. /*1. register chrdev*/

  96. if (gpio_control.major) {

  97. gpio_control.devid = MKDEV(gpio_control.major, 0);

  98. ret =register_chrdev_region(gpio_control.devid, NEWCHRLED_CNT, NEWCHRLED_NAME);

  99. } else {

  100. ret = alloc_chrdev_region(&gpio_control.devid, 0, NEWCHRLED_CNT, NEWCHRLED_NAME);

  101. }

  102. if(ret < 0 )

  103. {

  104. goto faial_alloc_chrdeev;

  105. }

  106. /* 2. init chrdev*/

  107. gpio_control.cdev.owner = THIS_MODULE;

  108. cdev_init(&gpio_control.cdev, &gpio_control_ops);

  109. /* 3. add chrdev */

  110. ret = cdev_add(&gpio_control.cdev, gpio_control.devid, NEWCHRLED_CNT);

  111. if (ret < 0)

  112. {

  113. goto faial_add_chrdeev;

  114. }

  115. /* 4. create class */

  116. gpio_control.class = class_create(THIS_MODULE, NEWCHRLED_NAME);

  117. if (IS_ERR(gpio_control.class)) {

  118. goto faial_create_class;

  119. }

  120. /* 5. create device */

  121. gpio_control.device = device_create(gpio_control.class, NULL, gpio_control.devid, NULL, NEWCHRLED_NAME);

  122. if (IS_ERR(gpio_control.device)) {

  123. goto faial_create_device;

  124. }

  125. return 0;

  126. faial_create_device:

  127. device_destroy(gpio_control.class, gpio_control.devid);

  128. faial_create_class:

  129. class_destroy(gpio_control.class);

  130. faial_add_chrdeev:

  131. cdev_del(&gpio_control.cdev);

  132. faial_alloc_chrdeev:

  133. unregister_chrdev_region(gpio_control.devid, NEWCHRLED_CNT);

  134. }

  135. static void __exit led_exit(void)

  136. {

  137. cdev_del(&gpio_control.cdev);

  138. unregister_chrdev_region(gpio_control.devid, NEWCHRLED_CNT);

  139. device_destroy(gpio_control.class, gpio_control.devid);

  140. class_destroy(gpio_control.class);

  141. }

  142. module_init(led_init);

  143. module_exit(led_exit);

  144. MODULE_LICENSE("GPL");

  145. MODULE_AUTHOR("qingmu");

7、配置menuconfig

  1. make menuconfig


8、编译

回到openwrt的根目录下

  1. make ./package/kernel/gpio_control_driver/compile V=s

9、把生成的ipk包发送到板子上去

找到生成的ipk包
发送到板子上去

  1. scp ./bin/ipq/packages/base/kmod-gpio_control_driver_4.4.60-1_ipq.ipk root@192.168.1.1:/root

10、安装ipk包

  1. opkg install kmod-gpio_control_driver_4.4.60-1_ipq.ipk

11、加载驱动

在/lib/modules/4.19.57/下可以找到gpio_control_driver.ko,执行

  1. insmod gpio_control_driver.ko

这样驱动就加载完成了,如果想卸载,可以执行

  1. rmmod gpio_control_driver.ko

12、驱动测试

12.1、同样的方式把测试文件也打包成ipk包发送到板子上运行

  • 1、在openwrt的源码目录下(SDK包的openwrt的目录下)的./package目录下创建gpio_test目录,

    mkdir gpio_test

  • 2、在gpio_test的目录下创建Makefile和src目录

    touch Makefile
    mkdir src

  • 3、编写Makefile
    makefile:

    obj-m := gpio_control_driver.o

  • 4、在src的目录下创建gpiotest.c、gpio_test.h、Makefile

    touch gpiotest.c
    touch gpiotest.h
    touch Makefile

gpio_test.c :

  1. #include

  2. #include

  3. #include

  4. #include

  5. #include

  6. #include

  7. #include

  8. #include

  9. #include "gpio_test.h"

  10. static unsigned char gpio_pin;//define GPIOs to be use

  11. static int gpio_dev_fd;

  12. void demo1_release(int signal_no)

  13. {

  14. ioctl(gpio_dev_fd, GPIO_CONTROL_SET_IN, GPIO_IOCTL_PRAM(gpio_pin, 0));

  15. ioctl(gpio_dev_fd, GPIO_CONTROL_FREE_GPIO, GPIO_IOCTL_PRAM(gpio_pin, 0));

  16. exit(0);

  17. }

  18. //指定管脚拉高, 拉低

  19. int set_gpio(unsigned char pin, int state)

  20. {

  21. if(state == 1)

  22. {

  23. ioctl(gpio_dev_fd, GPIO_CONTROL_SET_VALUE, GPIO_IOCTL_PRAM(pin, 1));

  24. }

  25. else if(state == 0)

  26. {

  27. ioctl(gpio_dev_fd, GPIO_CONTROL_SET_VALUE, GPIO_IOCTL_PRAM(pin, 0));

  28. }

  29. else

  30. {

  31. printf("No such set\n");

  32. goto ERROR;

  33. }

  34. return 0;

  35. ERROR:

  36. return -1;

  37. }

  38. int gpio_init(int pin)

  39. {

  40. int ret;

  41. gpio_pin = pin;

  42. gpio_dev_fd = open(GPIO_CONTROL_DEVICE_PATH, O_RDWR);//open gpio device

  43. if (gpio_dev_fd < 0){

  44. printf("###open %s ERROR###\n", GPIO_CONTROL_DEVICE_PATH);

  45. goto ERROR;

  46. }else{

  47. printf("***open %s success***\n", GPIO_CONTROL_DEVICE_PATH);

  48. }

  49. ret = ioctl(gpio_dev_fd, GPIO_CONTROL_REQUEST_GPIO, GPIO_IOCTL_PRAM(pin, 0));

  50. if (ret < 0){

  51. printf("###request GPIO %d error###", pin);

  52. goto ERROR;

  53. }

  54. ret = ioctl(gpio_dev_fd, GPIO_CONTROL_SET_OUT, GPIO_IOCTL_PRAM(pin, 0));

  55. if (ret < 0){

  56. printf("###set GPIO %d output error###", pin);

  57. goto ERROR;

  58. }

  59. signal(SIGINT, demo1_release);//register terminal signal

  60. return 0;

  61. ERROR:

  62. return -1;

  63. }

  64. int main()

  65. {

  66. gpio_init(30);

  67. gpio_init(29);

  68. while(1)

  69. {

  70. set_gpio(30, 0);

  71. usleep(200000);

  72. set_gpio(30, 1);

  73. usleep(200000);

  74. set_gpio(29, 0);

  75. usleep(200000);

  76. set_gpio(29, 1);

  77. usleep(200000);

  78. }

  79. return 0;

  80. }

注意:我这里的LED的灯的gpio口是GPIO30和GPIO29,大家个根据自己的GPIO口进行更改

gpio_test.h :

  1. #ifndef GPIO_CONTROL_TEST_H_

  2. #define GPIO_CONTROL_TEST_H_

  3. #define GPIO_CONTROL_DEVICE_PATH "/dev/gpio_control"

  4. #define GPIO_IOCTL_PRAM(gpio_num, arg1) (((unsigned long)gpio_num << 24) + ((unsigned long)arg1 << 16))

  5. #define GET_GPIO_NUM(arg1) (unsigned char)((arg1 >> 24) & 0xff)

  6. #define GET_GPIO_VALUE(arg1) (unsigned char)((arg1 >> 16) & 0xff)

  7. //IOCTRL CMDs

  8. #define GPIO_CONTROL_SET_OUT 0x01

  9. #define GPIO_CONTROL_SET_IN 0x02

  10. //#define GPIO_CONTROL_GET_DIRECTION 0x03

  11. #define GPIO_CONTROL_SET_VALUE 0x04

  12. #define GPIO_CONTROL_GET_VALUE 0x05

  13. #define GPIO_CONTROL_REQUEST_GPIO 0x06

  14. #define GPIO_CONTROL_FREE_GPIO 0x07

  15. int set_gpio(unsigned char pin, int state);

  16. int gpio_init(int pin);

  17. void delay_ms(int ms);

  18. #endif

  • 5、回到openwrt根目录下编译

    make ./package/gpio_test/compile V=s

  • 6、找到对应的ipk包并发送到板子上

    find ./ -name gpio_te*.ipk

发送到对应的开发板,这里大家根据自己的实际情况来:

  1. scp ./bin/ipq/packages/base/gpio_test_1-1.0_ipq.ipk root@192.168.1.1:/root

  • 6、安装goio_test的ipk包

    opkg install gpio_test_1-1.0_ipq.ipk

  • 7、运行gpio_test应用程序

    gpio_test

此时LED灯开始闪烁,大功告成

来源:https://blog.csdn.net/weixin_45309916/article/details/109811535

                              ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧  END  ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧


推荐阅读

【1】jetson nano开发使用的基础详细分享

【2】Linux开发coredump文件分析实战分享

【3】CPU中的程序是怎么运行起来的 必读

【4】cartographer环境建立以及建图测试

【5】设计模式之简单工厂模式、工厂模式、抽象工厂模式的对比

本公众号全部原创干货已整理成一个目录,回复[ 资源 ]即可获得。

羽林君 某嵌入式程序猿分享技术、生活、人生云云文字。如有诗云:去年今日此门中,人面桃花相映红。人面不知何处去,桃花依旧笑春风。
评论
  • 高速先生成员--黄刚这不马上就要过年了嘛,高速先生就不打算给大家上难度了,整一篇简单但很实用的文章给大伙瞧瞧好了。相信这个标题一出来,尤其对于PCB设计工程师来说,心就立马凉了半截。他们辛辛苦苦进行PCB的过孔设计,高速先生居然说设计多大的过孔他们不关心!另外估计这时候就跳出很多“挑刺”的粉丝了哈,因为翻看很多以往的文章,高速先生都表达了过孔孔径对高速性能的影响是很大的哦!咋滴,今天居然说孔径不关心了?别,别急哈,听高速先生在这篇文章中娓娓道来。首先还是要对各位设计工程师的设计表示肯定,毕竟像我
    一博科技 2025-01-21 16:17 101浏览
  • 临近春节,各方社交及应酬也变得多起来了,甚至一月份就排满了各式约见。有的是关系好的专业朋友的周末“恳谈会”,基本是关于2025年经济预判的话题,以及如何稳定工作等话题;但更多的预约是来自几个客户老板及副总裁们的见面,他们为今年的经济预判与企业发展焦虑而来。在聊天过程中,我发现今年的聊天有个很有意思的“点”,挺多人尤其关心我到底是怎么成长成现在的多领域风格的,还能掌握一些经济趋势的分析能力,到底学过哪些专业、在企业管过哪些具体事情?单单就这个一个月内,我就重复了数次“为什么”,再辅以我上次写的:《
    牛言喵语 2025-01-22 17:10 41浏览
  •  万万没想到!科幻电影中的人形机器人,正在一步步走进我们人类的日常生活中来了。1月17日,乐聚将第100台全尺寸人形机器人交付北汽越野车,再次吹响了人形机器人疯狂进厂打工的号角。无独有尔,银河通用机器人作为一家成立不到两年时间的创业公司,在短短一年多时间内推出革命性的第一代产品Galbot G1,这是一款轮式、双臂、身体可折叠的人形机器人,得到了美团战投、经纬创投、IDG资本等众多投资方的认可。作为一家成立仅仅只有两年多时间的企业,智元机器人也把机器人从梦想带进了现实。2024年8月1
    刘旷 2025-01-21 11:15 399浏览
  • 现在为止,我们已经完成了Purple Pi OH主板的串口调试和部分配件的连接,接下来,让我们趁热打铁,完成剩余配件的连接!注:配件连接前请断开主板所有供电,避免敏感电路损坏!1.1 耳机接口主板有一路OTMP 标准四节耳机座J6,具备进行音频输出及录音功能,接入耳机后声音将优先从耳机输出,如下图所示:1.21.2 相机接口MIPI CSI 接口如上图所示,支持OV5648 和OV8858 摄像头模组。接入摄像头模组后,使用系统相机软件打开相机拍照和录像,如下图所示:1.3 以太网接口主板有一路
    Industio_触觉智能 2025-01-20 11:04 150浏览
  •  光伏及击穿,都可视之为 复合的逆过程,但是,复合、光伏与击穿,不单是进程的方向相反,偏置状态也不一样,复合的工况,是正偏,光伏是零偏,击穿与漂移则是反偏,光伏的能源是外来的,而击穿消耗的是结区自身和电源的能量,漂移的载流子是 客席载流子,须借外延层才能引入,客席载流子 不受反偏PN结的空乏区阻碍,能漂不能漂,只取决于反偏PN结是否处于外延层的「射程」范围,而穿通的成因,则是因耗尽层的过度扩张,致使跟 端子、外延层或其他空乏区 碰触,当耗尽层融通,耐压 (反向阻断能力) 即告彻底丧失,
    MrCU204 2025-01-17 11:30 182浏览
  • 数字隔离芯片是一种实现电气隔离功能的集成电路,在工业自动化、汽车电子、光伏储能与电力通信等领域的电气系统中发挥着至关重要的作用。其不仅可令高、低压系统之间相互独立,提高低压系统的抗干扰能力,同时还可确保高、低压系统之间的安全交互,使系统稳定工作,并避免操作者遭受来自高压系统的电击伤害。典型数字隔离芯片的简化原理图值得一提的是,数字隔离芯片历经多年发展,其应用范围已十分广泛,凡涉及到在高、低压系统之间进行信号传输的场景中基本都需要应用到此种芯片。那么,电气工程师在进行电路设计时到底该如何评估选择一
    华普微HOPERF 2025-01-20 16:50 73浏览
  • 2024年是很平淡的一年,能保住饭碗就是万幸了,公司业绩不好,跳槽又不敢跳,还有一个原因就是老板对我们这些员工还是很好的,碍于人情也不能在公司困难时去雪上加霜。在工作其间遇到的大问题没有,小问题还是有不少,这里就举一两个来说一下。第一个就是,先看下下面的这个封装,你能猜出它的引脚间距是多少吗?这种排线座比较常规的是0.6mm间距(即排线是0.3mm间距)的,而这个规格也是我们用得最多的,所以我们按惯性思维来看的话,就会认为这个座子就是0.6mm间距的,这样往往就不会去细看规格书了,所以这次的运气
    wuliangu 2025-01-21 00:15 186浏览
  •     IPC-2581是基于ODB++标准、结合PCB行业特点而指定的PCB加工文件规范。    IPC-2581旨在替代CAM350格式,成为PCB加工行业的新的工业规范。    有一些免费软件,可以查看(不可修改)IPC-2581数据文件。这些软件典型用途是工艺校核。    1. Vu2581        出品:Downstream     
    电子知识打边炉 2025-01-22 11:12 55浏览
  • 嘿,咱来聊聊RISC-V MCU技术哈。 这RISC-V MCU技术呢,简单来说就是基于一个叫RISC-V的指令集架构做出的微控制器技术。RISC-V这个啊,2010年的时候,是加州大学伯克利分校的研究团队弄出来的,目的就是想搞个新的、开放的指令集架构,能跟上现代计算的需要。到了2015年,专门成立了个RISC-V基金会,让这个架构更标准,也更好地推广开了。这几年啊,这个RISC-V的生态系统发展得可快了,好多公司和机构都加入了RISC-V International,还推出了不少RISC-V
    丙丁先生 2025-01-21 12:10 112浏览
  • Ubuntu20.04默认情况下为root账号自动登录,本文介绍如何取消root账号自动登录,改为通过输入账号密码登录,使用触觉智能EVB3568鸿蒙开发板演示,搭载瑞芯微RK3568,四核A55处理器,主频2.0Ghz,1T算力NPU;支持OpenHarmony5.0及Linux、Android等操作系统,接口丰富,开发评估快人一步!添加新账号1、使用adduser命令来添加新用户,用户名以industio为例,系统会提示设置密码以及其他信息,您可以根据需要填写或跳过,命令如下:root@id
    Industio_触觉智能 2025-01-17 14:14 122浏览
  • 本文介绍瑞芯微开发板/主板Android配置APK默认开启性能模式方法,开启性能模式后,APK的CPU使用优先级会有所提高。触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。源码修改修改源码根目录下文件device/rockchip/rk3562/package_performance.xml并添加以下内容,注意"+"号为添加内容,"com.tencent.mm"为AP
    Industio_触觉智能 2025-01-17 14:09 164浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦