通过在openwrt源码目录下(或者SDK包的openwrt的目录下)编写gpio的字符驱动生成ipk包,发送到开发板上insmod加载驱动,然后通过编写APP来进行测试。
mkdir gpio_control_driver
mkdir src
touch 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/$(PKG_NAME)
SUBMENU:=Other modules
DEPENDS:=@GPIO_SUPPORT
TITLE:=Driver for FA156 gpios control
FILES:=$(PKG_BUILD_DIR)/gpio_control_driver.ko
AUTOLOAD:=$(call AutoLoad,30,gpio_control_driver)
endef
define KernelPackage/$(PKG_NAME)/description
Kernel module to control gpios for FA156
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
cp -rf ./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) \
modules
endef
$(eval $(call KernelPackage,$(PKG_NAME)))
makefile注释在https://editor.csdn.net/md/?articleId=109803571这篇文章里,我详细注释了。
touch gpio_control_driver.c
touch Makefile
Makefile:
obj-m := gpio_control_driver.o
gpio_control_driver.c:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define NEWCHRLED_CNT 1
#define NEWCHRLED_NAME "gpio_control"
#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
#define GET_GPIO_NUM(arg1) (unsigned char)((arg1 >> 24) & 0xff)
#define GET_GPIO_VALUE(arg1) (unsigned char)((arg1 >> 16) & 0xff)
struct gpio_control_dev{
dev_t devid;
struct cdev cdev;
struct class *class;
struct device *device;
int major;
int minor;
};
struct gpio_control_dev gpio_control;
static int gpio_control_open(struct inode *pinode, struct file *pfile)
{
printk("***%s***\n",__func__);
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;
gpio_number = GET_GPIO_NUM(arg);
gpio_value = GET_GPIO_VALUE(arg);
switch (cmd){
case GPIO_CONTROL_SET_OUT:
ret = gpio_direction_output(gpio_number, gpio_value);
if (ret < 0){
return -1;
}
break;
case GPIO_CONTROL_SET_IN:
ret = gpio_direction_input(gpio_number);
if (ret < 0){
return -1;
}
break;
case GPIO_CONTROL_SET_VALUE:
gpio_set_value(gpio_number, gpio_value);
break;
case GPIO_CONTROL_GET_VALUE:
ret = gpio_get_value(gpio_number);
if (ret < 0){
return -1;
}
break;
case GPIO_CONTROL_REQUEST_GPIO:
if (0 > gpio_request(gpio_number, "gpio_ctrl")){
return -1;
}
break;
case GPIO_CONTROL_FREE_GPIO:
gpio_free(gpio_number);
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 int __init led_init(void)
{
unsigned int ret = 0;
/*1. register chrdev*/
if (gpio_control.major) {
gpio_control.devid = MKDEV(gpio_control.major, 0);
ret =register_chrdev_region(gpio_control.devid, NEWCHRLED_CNT, NEWCHRLED_NAME);
} else {
ret = alloc_chrdev_region(&gpio_control.devid, 0, NEWCHRLED_CNT, NEWCHRLED_NAME);
}
if(ret < 0 )
{
goto faial_alloc_chrdeev;
}
/* 2. init chrdev*/
gpio_control.cdev.owner = THIS_MODULE;
cdev_init(&gpio_control.cdev, &gpio_control_ops);
/* 3. add chrdev */
ret = cdev_add(&gpio_control.cdev, gpio_control.devid, NEWCHRLED_CNT);
if (ret < 0)
{
goto faial_add_chrdeev;
}
/* 4. create class */
gpio_control.class = class_create(THIS_MODULE, NEWCHRLED_NAME);
if (IS_ERR(gpio_control.class)) {
goto faial_create_class;
}
/* 5. create device */
gpio_control.device = device_create(gpio_control.class, NULL, gpio_control.devid, NULL, NEWCHRLED_NAME);
if (IS_ERR(gpio_control.device)) {
goto faial_create_device;
}
return 0;
faial_create_device:
device_destroy(gpio_control.class, gpio_control.devid);
faial_create_class:
class_destroy(gpio_control.class);
faial_add_chrdeev:
cdev_del(&gpio_control.cdev);
faial_alloc_chrdeev:
unregister_chrdev_region(gpio_control.devid, NEWCHRLED_CNT);
}
static void __exit led_exit(void)
{
cdev_del(&gpio_control.cdev);
unregister_chrdev_region(gpio_control.devid, NEWCHRLED_CNT);
device_destroy(gpio_control.class, gpio_control.devid);
class_destroy(gpio_control.class);
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("qingmu");
make menuconfig
回到openwrt的根目录下
make ./package/kernel/gpio_control_driver/compile V=s
找到生成的ipk包
发送到板子上去
scp ./bin/ipq/packages/base/kmod-gpio_control_driver_4.4.60-1_ipq.ipk root@192.168.1.1:/root
opkg install kmod-gpio_control_driver_4.4.60-1_ipq.ipk
在/lib/modules/4.19.57/下可以找到gpio_control_driver.ko,执行
insmod gpio_control_driver.ko
这样驱动就加载完成了,如果想卸载,可以执行
rmmod gpio_control_driver.ko
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 :
#include
#include
#include
#include
#include
#include
#include
#include
#include "gpio_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(30);
gpio_init(29);
while(1)
{
set_gpio(30, 0);
usleep(200000);
set_gpio(30, 1);
usleep(200000);
set_gpio(29, 0);
usleep(200000);
set_gpio(29, 1);
usleep(200000);
}
return 0;
}
注意:我这里的LED的灯的gpio口是GPIO30和GPIO29,大家个根据自己的GPIO口进行更改
gpio_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
5、回到openwrt根目录下编译
make ./package/gpio_test/compile V=s
6、找到对应的ipk包并发送到板子上
find ./ -name gpio_te*.ipk
发送到对应的开发板,这里大家根据自己的实际情况来:
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 ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧