Openwrt编写GPIO驱动控制LED

2023-11-01

一、驱动的编写

1.创建gpio_control_driver文件夹

2.在gpio_control_driver文件夹下再创建src文件夹以及Makefile文件

Makefile文件如下:

include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk

PKG_NAME:=gpio_control_driver
PKG_RELEASE:=1

include $(INCLUDE_DIR)/package.mk

define KernelPackage/gpio_control_driver
  SUBMENU:=Other modules
  DEPENDS:=@GPIO_SUPPORT
  TITLE:=Driver for JS9331/JS7628 gpios control
  FILES:=$(PKG_BUILD_DIR)/gpio_control_driver.ko
  KCONFIG:=
  AUTOLOAD:=$(call AutoLoad,30,gpio_control_driver)
endef

define KernelPackage/gpio_control_driver/description
 Kernel module to control gpios for JS9331 and JS7628
endef

EXTRA_KCONFIG:= \
        CONFIG_GPIO_CONTROL_DRIVER=m

define Build/Prepare
	mkdir -p $(PKG_BUILD_DIR)
	$(CP) ./src/* $(PKG_BUILD_DIR)/
endef

define Build/Compile
	$(MAKE) -C "$(LINUX_DIR)" \
		CROSS_COMPILE="$(TARGET_CROSS)" \
		ARCH="$(LINUX_KARCH)" \
		SUBDIRS="$(PKG_BUILD_DIR)" \
		EXTRA_CFLAGS="$(BUILDFLAGS)" \
		$(EXTRA_KCONFIG)
endef

$(eval $(call KernelPackage,gpio_control_driver))

3.在src文件夹下再创建Makefile,Kconfig文件以及gpio对应的.c,.h驱动文件

Makefile文件:

obj-${CONFIG_GPIO_CONTROL_DRIVER}     += gpio_control_driver.o

Kconfig文件:

config GPIO_CONTROL_DRIVER
        tristate "Gpio control driver for AR9344"
        depends on GENERIC_GPIO

驱动文件gpio_control_driver.c:

#include <linux/types.h>
#include <linux/gpio.h>
#include <linux/timer.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/hrtimer.h>
#include <linux/stat.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/time.h>
#include <asm-generic/errno-base.h>
#include <linux/miscdevice.h>


#include "gpio_control_driver.h"

static int gpio_control_open(struct inode *pinode, struct file *pfile)
{
	printk("***%s***\n",__func__);
	//initialize

	return 0;
}

static int gpio_control_release(struct inode *pinode, struct file *pfile)
{
	printk("***%s***\n",__func__);

	return 0;
}


static long gpio_control_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg)
{
	int ret;
	unsigned char gpio_number;
	unsigned char gpio_value;

	//printk("***%s***\n",__func__);
	//printk("cmd:0x%02X\n", cmd);

	gpio_number = GET_GPIO_NUM(arg);
	gpio_value  = GET_GPIO_VALUE(arg);
	//printk("gpio number:%d\n", gpio_number);
	//printk("gpio value:0x%02X\n", gpio_value);

	switch (cmd){
	case GPIO_CONTROL_SET_OUT:
		//printk("command: GPIO_CONTROL_SET_OUT\n");
		ret = gpio_direction_output(gpio_number, gpio_value);
		if (ret < 0){
			//printk("###gpio_direction_output ERROR: can't set gpio %d output###\n", gpio_number);
			return -1;
		}
		//printk("command: GPIO_CONTROL_SET_OUT done\n");
		break;

	case GPIO_CONTROL_SET_IN:
		ret = gpio_direction_input(gpio_number);
		if (ret < 0){
			//printk("###gpio_direction_input ERROR: can't set gpio %d input###\n", gpio_number);
			return -1;
		}
		//printk("command: GPIO_CONTROL_SET_IN\n");
		break;
#if 0
	case GPIO_CONTROL_GET_DIRECTION:

		printk("command: GPIO_CONTROL_GET_DIRECTION\n");
		break;
#endif
	case GPIO_CONTROL_SET_VALUE:
		gpio_set_value(gpio_number, gpio_value);
		//printk("command: GPIO_CONTROL_SET_VALUE\n");
		break;

	case GPIO_CONTROL_GET_VALUE:
		ret = gpio_get_value(gpio_number);
		if (ret < 0){
			//printk("###gpio_get_value ERROR: can't get gpio %d value###\n", gpio_number);
			return -1;
		}
		//printk("command: GPIO_CONTROL_GET_VALUE\n");
		break;

	case GPIO_CONTROL_REQUEST_GPIO:
		//printk("command: GPIO_CONTROL_REQUEST_ONE\n");
		if (0 > gpio_request(gpio_number, "gpio_ctrl")){
			//printk("###gpio_request ERROR: can't request %d pin for output###\n", gpio_number);
			return -1;
		}
		//printk("command: GPIO_CONTROL_REQUEST_GPIO done\n");
		break;

	case GPIO_CONTROL_FREE_GPIO:
		gpio_free(gpio_number);
		//printk("command: GPIO_CONTROL_FREE_GPIO done\n");
		break;

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

	}

	return 0;
}

static const struct file_operations gpio_control_ops = {
		.owner 			= THIS_MODULE,
		.open			= gpio_control_open,
		.release		= gpio_control_release,
		.unlocked_ioctl	= gpio_control_ioctl,
};

static struct miscdevice s_gpio_control_dev = {
		.minor = MISC_DYNAMIC_MINOR,
		.fops = &gpio_control_ops,
		.name = GPIO_CONTROL_DEV_NAME
};

//module initialize function
static int gpio_control_init(void)
{
	int result;
	//initialize and register device
	result = misc_register(&s_gpio_control_dev);
	if (result != 0) {
		//printk("###misc_register error###\n");
		return -1;
	}

	printk("**gpio_control module initiation OK**\n");
	return result;
}

//module exit fuc
void gpio_control_exit(void)
{
	//unregister what we registered
	misc_deregister(&s_gpio_control_dev);

	printk("**gpio_control module exit**\n");
}

module_init(gpio_control_init);
module_exit(gpio_control_exit);

MODULE_VERSION("V1.0");
MODULE_AUTHOR("wq <wq@wq.com>");
MODULE_LICENSE("Dual BSD/GPL");

驱动文件gpio_control_driver.h:

#ifndef GPIO_CONTROL_DRIVER_H_
#define GPIO_CONTROL_DRIVER_H_

#include <linux/cdev.h>
#include <linux/ioctl.h>
#include <linux/kfifo.h>

#define GET_GPIO_NUM(arg1) (unsigned char)((arg1 >> 24) & 0xff)
#define GET_GPIO_VALUE(arg1) (unsigned char)((arg1 >> 16) & 0xff)

#define GPIO_CONTROL_MAJOR 					99//device major number


#define GPIO_CONTROL_DEV_NAME		"gpio_control"

//IOCTRL CMDs
#define GPIO_CONTROL_SET_OUT			0x01
#define GPIO_CONTROL_SET_IN			0x02
//#define GPIO_CONTROL_GET_DIRECTION		0x03
#define GPIO_CONTROL_SET_VALUE			0x04
#define GPIO_CONTROL_GET_VALUE			0x05
#define GPIO_CONTROL_REQUEST_GPIO		0x06
#define GPIO_CONTROL_FREE_GPIO			0x07



#endif /* GPIO_CONTROL_DRIVER_H_ */

 

二、驱动的编译安装

1.将gpio_control_driver文件夹拷贝到openwrt源码目录下的/package/kernel/下

2.进入openwrt的/目录,输入

make menuconfig

3.配置如下

4.编译

make V=s

5.在源码/bin/targets/ath79/generic/packages下找到kmod-gpio_control_driver_4.19.57-1_mips_24kc.ipk,通过scp上传到板子上。

6.安装驱动

在板子上执行

opkg install kmod-gpio_control_driver_4.19.57-1_mips_24kc.ipk

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

insmod gpio_control_driver.ko

这样驱动已经成功安装,如果想卸载,可以执行

rmmod gpio_control_driver.ko

此时,可以看见在板子的/dev/下存在gpio_control驱动

7.将驱动加载到内核

我们也可以直接将驱动加载到内核,这样就不需要手动安装了,只要将内核配置改为

然后还是去openwrt的/目录下执行

make V=s

将/bin/targets/ath79/generic/下生成的新固件(.bin文件)更新下系统,等系统重启完可以看见在板子的/dev/下存在gpio_control驱动

 

三、驱动的测试

1.编写测试程序

驱动测试文件gpio_control_test.c:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include "gpio_control_test.h"

static unsigned char gpio_pin;//define GPIOs to be use
static int gpio_dev_fd;

void demo1_release(int signal_no)
{
	ioctl(gpio_dev_fd, GPIO_CONTROL_SET_IN, GPIO_IOCTL_PRAM(gpio_pin, 0));
	ioctl(gpio_dev_fd, GPIO_CONTROL_FREE_GPIO, GPIO_IOCTL_PRAM(gpio_pin, 0));
	exit(0);
}


//指定管脚拉高, 拉低
int set_gpio(unsigned char pin, int state)
{   

    if(state == 1)
    {
        ioctl(gpio_dev_fd, GPIO_CONTROL_SET_VALUE, GPIO_IOCTL_PRAM(pin, 1));
    }
    else if(state == 0)
    {
        ioctl(gpio_dev_fd, GPIO_CONTROL_SET_VALUE, GPIO_IOCTL_PRAM(pin, 0));
    }
    else
    {
        printf("No such set\n");
        goto ERROR;
    }

    return 0;

    ERROR:
        return -1; 
}

int gpio_init(int pin)
{
    int ret;

    gpio_pin = pin;

    gpio_dev_fd = open(GPIO_CONTROL_DEVICE_PATH, O_RDWR);//open gpio device
    if (gpio_dev_fd < 0){
        printf("###open %s ERROR###\n", GPIO_CONTROL_DEVICE_PATH);
        goto ERROR;
    }else{
        printf("***open %s success***\n", GPIO_CONTROL_DEVICE_PATH);
    }
    
    ret = ioctl(gpio_dev_fd, GPIO_CONTROL_REQUEST_GPIO, GPIO_IOCTL_PRAM(pin, 0));
	if (ret < 0){
		printf("###request GPIO %d error###", pin);
		goto ERROR;
	}
	ret = ioctl(gpio_dev_fd, GPIO_CONTROL_SET_OUT, GPIO_IOCTL_PRAM(pin, 0));
	if (ret < 0){
		printf("###set GPIO %d output error###", pin);
		goto ERROR;
	}

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

    return 0;

    ERROR:
        return -1; 
}


int main()
{
    gpio_init(42);
    gpio_init(40);
    gpio_init(39);
   
    while(1)
    {
        set_gpio(42, 1);
        usleep(200000);
        set_gpio(42, 0);
        usleep(200000);
        set_gpio(40, 1);
        usleep(200000);
        set_gpio(40, 0);
        usleep(200000);
        set_gpio(39, 1);
        usleep(200000);
        set_gpio(39, 0);
        usleep(200000);
    }
}


驱动测试文件gpio_control_test.h:

#ifndef GPIO_CONTROL_TEST_H_
#define GPIO_CONTROL_TEST_H_

#define GPIO_CONTROL_DEVICE_PATH		"/dev/gpio_control"

#define GPIO_IOCTL_PRAM(gpio_num, arg1) (((unsigned long)gpio_num << 24) + ((unsigned long)arg1 << 16))
#define GET_GPIO_NUM(arg1) (unsigned char)((arg1 >> 24) & 0xff)
#define GET_GPIO_VALUE(arg1) (unsigned char)((arg1 >> 16) & 0xff)

//IOCTRL CMDs
#define GPIO_CONTROL_SET_OUT			0x01
#define GPIO_CONTROL_SET_IN			0x02
//#define GPIO_CONTROL_GET_DIRECTION		0x03
#define GPIO_CONTROL_SET_VALUE			0x04
#define GPIO_CONTROL_GET_VALUE			0x05
#define GPIO_CONTROL_REQUEST_GPIO		0x06
#define GPIO_CONTROL_FREE_GPIO			0x07

int set_gpio(unsigned char pin, int state);
int gpio_init(int pin);
void delay_ms(int ms);



#endif

2.编译

mips-openwrt-linux-gcc -o gpio_control_test gpio_control_test.c

3.将gpio_control_test通过scp上传到板子上并执行,可以看到3个灯的闪烁

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Openwrt编写GPIO驱动控制LED 的相关文章

随机推荐

  • hive连接报错-java.lang.NoClassDefFoundError: Could not initialize class org.apache.hadoop.security.UserG

    hive连接报错 java lang NoClassDefFoundError Could not initialize class org apache hadoop security UserGroupInformation 报错信息
  • 享学笔记:并发编程之多线程基础(一)

    一 创建多线程的三种方式 1 继承Thread类 重写run方法 class Demo extends Thread Override public void run System out println 这是一个子线程 Thread 启动
  • Linux搭建部署环境

    Linux搭建部署环境手册 说明 说明 该笔记是在linux上安装jdk mysql tomcat redis 以便于建立一个linux系统下的部署环境 建议 保留该安装笔记 以便于企业复用 ps 安装软件前必须得先有防火墙做端口的开放 软
  • 报错提示:未找到插件 ‘org.springframework.bootspring-boot-maven-plugin

    解决方法 到自己本地的Maven仓库中寻找如下路径 选一个版本号添加进去即可
  • 算法:dfs(深度优先搜索算法)

    dfs 暴搜 一条路走到黑 然后回溯 开启另一条路 再一条路走到黑 那么如何对暴搜进行优化 剪枝 当发现某一条树枝时不可能找到答案时 就没必要还在这条路走到黑一直搜索了 将这条树枝减去 趁早换一条路 如图 可以用递归来一条路走到黑 递归最恰
  • JeecgBoot获取当前登录用户信息

    前言 如果使用JeecgBoot项目进行开发的时候 有的场景需要获取当前登录人信息做一些逻辑操作 下面分享下通过前后端分别获取用户的方式 前端获取 本质是使用vuex进行获取 引入store import store from store
  • Java数字反转

    这道题非常像之前做过的一道题 求水仙花数 输出对应位的数字 这题不一样的在于带有小数点 但是除余没法留小数点上的数字 需要变整后除余 求末位数 求末位数 随后倒数第二位直接初余便可以得到 不要忘记和第一个数中间放一个小数点 由于题母给的是f
  • 分割问题中“类间竞争”是怎么回事

    softmax会返回多种不同类别 而sigmoid会得到二值结果 softmax的值域是 0 1 sigmoid的值域是 0 1 sigmoid可以看成是softmax的两类分类的特例
  • 2023华为OD机试真题-分苹果(JAVA、Python、C++)

    题目描述 A B两团体把苹果分为两堆 A盼望依照它的盘算规矩平分苹果 他的盘算规矩是依照二进制加法盘算 而且不盘算走位 12 5 9 1100 0101 9 B的盘算规矩是十进制加法 包含畸形进位 B盼望在满意A的情形下获取苹果分量最多 输
  • xss挑战之旅11关到13关,操作步骤配截图。

    level11 分析代码 相比上一关 多了一个str11 SERVER HTTP REFERER 验证的是http头部的xss注入 使用burp抓包 修改相应的字段 构造http头部referer的payload 头部本身没有Referer
  • 数据的中心化,标准化及意义

    在机器学习回归问题 以及训练神经网络过程中 通常需要对原始数据进行中心化 零均值化 与标准化 归一化 预处理 目的 通过中心化和标准化处理 最终得到均值为0 标准差为1的服从标准正态分布的数据 在多指标评价体系中 由于各评价指标的性质不同
  • OPENSSL ENGINE机制

    OPENSSL ENGINE机制 1 概念 OpenSSL项目是一个开放源代码安全项目 它的目标是开发一个健壮的 商业级的 完整的开放源代码的工具包 用强大的加密算法来实现安全的Socket层 Secure Sockets Layer SS
  • 弱口令招新赛靶机赛道WriteUp

    nmap sS p 22 oG 172 27 13 0 24 grep open 使用该命令扫描网段下开放22端口的主机 发现主机后 信息收集 得到两个开放的端口 22端口 服务为ssh服务 版本为7 6p1 服务器为ubuntu 此版本存
  • Vue3项目搭建教程(create-vue)

    什么是create vue create vue是一个脚手架工具 用来快速创建v3的项目 Vuecli用来创建v2的项目 介绍 Vue CLI create vue是Vue官方新的脚手架工具 底层切换到了 vite 下一代前端工具链 为开发
  • 2021全国省市区街道(乡镇)数据及编码(不包含港澳台)

    已按拼音首字母排序 共31省直辖市 342个城市 3352个区县 41206个街道 乡镇 安徽省 340000 安庆市 340800 安徽安庆经济开发区 340871 菱北街道 340871001 老峰镇 340871100 大观区 340
  • 嵌入式Linux应用开发完全手册(一)嵌入式Linux基础知识

    嵌入式Linux应用开发完全手册 3 嵌入式Linux基础知识 3 1 交叉编译工具 编译工具链 编译工作由几个步骤完成 分别用到了不同的工具 PC端应用 gcc ld objcopy objdump 交叉编译 编译和运行在不同的环境下 a
  • mysql 5.6 创建索引导致表锁阻塞查询

    今天遇到一个表锁 对表进行select操作阻塞 最后发现在表操作时的时候执行了创建索引 导致整个表锁了 测试如下 1 先执行一个慢查询 mysql gt select sleep 500 from order log 2 对表进行创建索引操
  • 链式栈和队列以及重载,const,void(*)补充

    一 C 版链式栈和队列 1 1栈 include
  • 聊一聊TypeScript中的泛型与断言~

    思考 后端接口给前端返回数据时 一般会遵循一定的规律 例如 都有code msg data三个属性 而不同的接口返回的具体数据保存在data中 它的格式是不同的 随便定义一个数据 请求得到用户信息 const res1 code 200 m
  • Openwrt编写GPIO驱动控制LED

    一 驱动的编写 1 创建gpio control driver文件夹 2 在gpio control driver文件夹下再创建src文件夹以及Makefile文件 Makefile文件如下 include TOPDIR rules mk