通过在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 <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#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 [email protected]:/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
mkdir gpio_test
touch Makefile
mkdir src
obj-m := gpio_control_driver.o
touch gpiotest.c
touch gpiotest.h
touch Makefile
gpio_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_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
make ./package/gpio_test/compile V=s
find ./ -name gpio_te*.ipk
发送到对应的开发板,这里大家根据自己的实际情况来:
scp ./bin/ipq/packages/base/gpio_test_1-1.0_ipq.ipk [email protected]:/root
opkg install gpio_test_1-1.0_ipq.ipk
gpio_test
此时LED灯开始闪烁,大功告成
最近看一段代码有所迷惑,先简单总结一下。有关结构体数组初始化的问题struct _m_usmart_nametab usmart_nametab[]=本文引用地址:http://www.eepw.com.cn/article/201611/322298.htm{#if USMART_USE_WRFUNS==1 //如果使能了读写操作(void*)read_addr,"u32 read_addr(u...
关于celery 的实现消息队列,以及异步函数的使用有很多用途,比较常见的一个用途就是前端向后端发起一个请求,后端完成这个请求需要较长的时间,可以先向前端返回结果,然后将这个实现的过程存储,在后端慢慢实现。那么这个过程,就可以使用 celery 来实现。技术框架:在这里用到的 Python 的后端框架是 Django。celery 可以使用的中间件有 Redis,rabbitmq 等,这里...
**抓取?callback=jQuery…形式的url最近爬取 遇到好些 这种 为 jsonp 动态加载方式 的 网站, 做个笔记记录下两种采集方式1 模拟浏览器 selenium + webdriver 采集 模拟人为滚动优点: 无需分析请求参数 节省配置时间缺点: 获取数据较慢, 浏览器一直往下滚 占用较大内存 易崩2 java || python get请求优点: 获取速度...
目的:https://layui.itze.cn/demo/index.html 实现官网的数据table,对应的layui的资源已经下载好过程就不写了,后面直接放项目代码:数据来源:https://blog.csdn.net/yangjiabei_0301/article/details/78222174用flask作为后端:运行完整代码已经上传:传送门:https://github.com/jevy146/layui_flask_use...
报错 MMC: no card present 的, 一般是在移植 uboot 的时候配置有误, 排查的时候, 按照教程的操作步骤来进行检查。例如在 uboot 源码的./configs/mx6ull_alientek_emmc_defconfig 下。CONFIG_SYS_EXTRA_OPTIONS=“IMX_CONFIG=board/freescale/mx6ull_alientek_emmc/imximage.cfg,MX6ULL_EVK_EMMC_REWORK”我就是因为这个配置中的 MX
1. Repo的基本结构Repo包括几部分:Repo脚本, Repo库,Manifest库,Project库2. 从0开始创建repo仓库repo脚本:这是一个python脚本,用来下载repo和manifest这两个git库获取repo脚本,下载并修改权限curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo -o repochmod +x reporepo 库: repo工具本身也是一个git库,包含若干python脚本,每
在android studio更新到3.0以上打包签名是会出现Signature Versions V1、V2的选项v1 v2的意思:android 7.0中引入了APK Signature Scheme v2,v1呢是jar Signature来自JDKV1:应该是通过ZIP条目进行验证,这样APK 签署后可进行许多修改 - 可以移动甚至重新压缩文件。V2:验证压缩文件的所有字节,而...
http://www.ttlsa.com/php/curl-replace-ile_get_contents/初学php的朋友们,很容易翻一个错误,在写采集程序或者调用api接口总会有线考虑到使用file_get_contents函数来或许内容,程序的访问量不大倒是没什么影响,但是访问量提升了那非常的悲剧了,你会发现服务器负载飙升,最后服务器宕机.初入公司便遇到这个问题,遂使用cu
医院信息集成平台概述以往医院的信息系统建设分期建设,造成系统操作上的割裂和数据之间通讯的割裂,严重的损坏了业务流程的连贯性,互联互通的核心是数据层面和应用层面的整合。具体来说,重点要解决医院信息系统的系统异构集成、数据共享和数据交换传输标准等关键性技术问题。全院各个应用系统均与医院信息平台互联,并通过医院信息平台实现相互之间的数据交换和应用服务的调用。医院信息集成平台就是实现医院信息系统应用整合。应用整合的首要需求是实现各医院应用系统之间的互联互通:从集成的层面上,需要考虑三个层面:数据层面...
深度学习模型计算复杂度高,参数存在冗余。(1)线性或非线性量化。(2)结构或非结构剪枝。(3)网络结构搜索。(4)权重矩阵的低秩分解。(蒸馏)优化精度、性能、存储等,使得可以在一些场景和设备上进行相应模型的部署。(1)剪枝位置的判定一般根据权重。权重越小,证明该神经元的作用越小。(2)剪枝的方式:删去网络层上的权重的向量/整个神经元/单个像素(数据)。由于矩阵操作的并行化,减去单个像素或者向量并不能减少计算量。即有的硬件并不支持稀疏矩阵的运输,所以一般剪枝操作是直接减去整个神经元。(3)判别剪神经元的
PHP用socket连接SMTP服务器发送邮件PHP用socket连接SMTP服务器发送邮件学习实验记录:分析与SMTP会话的一般流程1. HELO XXX \r\n //XXX就是自己起个名字,和服务器打个招呼返回 250 表示成功2. AUTH LOGIN \r\n //请求与服务器开始验证用户(登陆)返回 334 表示成功3. 用户名 \r...
密码大小写敏感是Oracle 11g数据库默认的一个新特性,数据库配置助手(DBCA)在创建数据库期间允许你将这个设置返回到11g以前的功能。 SEC_CASE_SENSITIVE_LOGON初始化参数控制密码大小写是否敏感,如果现有应用程序与11g的认证过程冲突,你可以使用ALTER SYSTEM命令将这一功能关闭。 ALTER SYSTEM SET SEC_CASE_SENSITI