西宁专业网站建设域名备案掉了网站还可以用

当前位置: 首页 > news >正文

西宁专业网站建设,域名备案掉了网站还可以用,网站ui设计欣赏,沈阳关键词优化报价目录 一、硬件原理 二、添加设备树 1、创建pinctrl 2、创建节点 3、检查 编译复制 三、修改工程模板​编辑 四、驱动编写 1、添加keyio函数 2、添加调用 3、驱动出口函数添加释放 4、添加原子操作 5、添加两个宏定义 6、初始化原始变量 7、打开操作 8、读操作 总体代…目录 一、硬件原理 二、添加设备树 1、创建pinctrl 2、创建节点 3、检查 编译复制 三、修改工程模板​编辑 四、驱动编写 1、添加keyio函数  2、添加调用 3、驱动出口函数添加释放 4、添加原子操作 5、添加两个宏定义 6、初始化原始变量 7、打开操作 8、读操作 总体代码如下 五、应用编写 总体代码如下 验证 一、硬件原理 打开原理图找到KEY 可以看到KEY0是接到UART1 CTS上 打开参考手册找到IOMUXC_SW_MUX_CTL_PAD_UART1_CTS_B 看到是可以复用为GPIO1_IO18的 根据IOMUXC_SW_PAD_CTL_PAD_UART1_CTS_B配置的电气属性为0xF080具体属性如下 配置UART1_CTS_B的IO属性          *bit 16:0 HYS关闭      *bit [15:14]: 11 默认22K上拉      *bit [13]: 1 pull功能      *bit [12]: 1 pull/keeper使能      *bit [11]: 0 关闭开路输出      *bit [7:6]: 10 速度100Mhz      *bit [5:3]: 000 关闭输出      bit [0]: 0 低转换率 二、添加设备树 1、创建pinctrl 先查找UART1_CTS对应的宏这个在arch/arm/boot/dts/imx6ul-pinfunc.h 在iomuxc里添加keygrp 2、创建节点 创建key节点 3、检查 添加完之后在文件里分别搜索MX6UL_PAD_UART1_CTS_B__GPIO1_IO018和gpio1 18检查一下是否有存在使用避免占用 打开开发板检查创建是否存在 编译复制 三、修改工程模板 修改makefile 复制基本的字符驱动模板到key.c 四、驱动编写 自行编写好基本的字符设备 1、添加keyio函数  在驱动入口前添加  96行of_find_node_by_path 函数通过路径来查找指定的节点“key”返回找到的节点 102行of_get_named_gpio函数获取设备树中“key-gpios”属性信息0为其第一个信息获取到的 GPIO 编号 108行gpio_request 函数在使用 GPIO 之前申请GPIO 管脚设名字“key0”返回值0申请成功 114行gpio_direction_input函数设置 GPIO 为输入返回值0设置成功 2、添加调用 在驱动入口函数里面后部添加 在驱动入口里面调用 keyio函数  3、驱动出口函数添加释放 4、添加原子操作 5、添加两个宏定义 方便原子操作值不是固定的  6、初始化原始变量 初始化keyvalue,把宏INVAKEY赋值给keyvalue在驱动入口函数定义 7、打开操作 设置私有数据 8、读操作 61行获取私有数据 63-67行 gpio_get_value函数返回值为 GPIO 的输入电平状态1 为高电平0 为低电平。如果按下不放就是1进入while等待释放释放为0取反进入while中执行 atomic_set函数把KEY0VALUE赋值给keyvalue。否则直接执行 atomic_set函数把宏INVAKEY赋值给keyvalue 69行atomic_read函数读取keyvalue值赋给value 71行copy_to_user函数把value的值拷贝给用户空间成功执行拷贝操作则返回0 总体代码如下 #include linux/module.h #include linux/kernel.h #include linux/init.h #include linux/fs.h #include linux/uaccess.h #include linux/io.h #include linux/cdev.h #include linux/device.h #include linux/of.h #include linux/of_address.h #include linux/of_irq.h #include linux/slab.h #include linux/of_address.h #include linux/of_gpio.h #include linux/atomic.h#define KEY_CNT 1 / 设备号个数 / #define KEY_NAME key / 名字 /#define INVAKEY 0x00 #define KEY0VALUE 0XF0/ key设备结构体 / struct key_dev {dev_t devid; / 设备号 /struct cdev cdev; / cdev */struct class class; / 类 */struct device device; / 设备 /int major; / 主设备号 /int minor; / 次设备号 */struct device_node nd; / 设备节点 /int key_gpio; / key所使用的GPIO编号 /atomic_t keyvalue; / 按键值 / } key; / key设备 //** description : 打开设备 param - inode : 传递给驱动的inode* param - filp : 设备文件file结构体有个叫做private_data的成员变量* 一般在open的时候将private_data指向设备结构体。* return : 0 成功;其他 失败*/ static int key_open(struct inode *inode, struct file filp) {filp-private_data key;return 0; }/** description : 从设备读取数据 param - filp : 要打开的设备文件(文件描述符)* param - buf : 返回给用户空间的数据缓冲区* param - cnt : 要读取的数据长度* param - offt : 相对于文件首地址的偏移* return : 读取的字节数如果为负值表示读取失败*/ static ssize_t key_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt) {int value;struct key_dev *dev filp-private_data;int ret 0;if(gpio_get_value(dev-key_gpio) 0){/按下/while(!gpio_get_value(dev-key_gpio));atomic_set(dev-keyvalue,KEY0VALUE);}else{atomic_set(dev-keyvalue,INVAKEY);}value atomic_read(dev-keyvalue);ret copy_to_user(buf,value,sizeof(value));return ret; }/** description : 向设备写数据* param - filp : 设备文件表示打开的文件描述符* param - buf : 要写给设备写入的数据* param - cnt : 要写入的数据长度* param - offt : 相对于文件首地址的偏移* return : 写入的字节数如果为负值表示写入失败*/ static ssize_t key_write(struct file *filp, const char __user *buf, size_t cnt, loff_t offt) {return 0; }/** description : 关闭/释放设备 param - filp : 要关闭的设备文件(文件描述符)* return : 0 成功;其他 失败*/ static int key_release(struct inode *inode, struct file filp) {return 0; }/ 设备操作函数 */ static struct file_operations key_fops {.owner THIS_MODULE,.open key_open,.read key_read,.write key_write,.release key_release, };/key io初始化/ static int keyio_init(struct key_dev *dev) { int ret 0; /初始化atomic/atomic_set(key.keyvalue,INVAKEY);dev-nd of_find_node_by_path(/key);if (dev-nd NULL){ret -EINVAL;goto fail_nd;}dev-key_gpio of_get_named_gpio(dev-nd, key-gpios, 0);if (dev-key_gpio 0){ret -EINVAL;goto fail_gpio;}ret gpio_request(dev-key_gpio, key0);if (ret){ret -EBUSY;printk( IO %d cant request\r\n, dev-key_gpio);}ret gpio_direction_input(dev-key_gpio);if (ret){ret -EINVAL;goto fail_input;}return 0; fail_input:gpio_free(dev-key_gpio); fail_gpio: fail_nd:device_destroy(key.class, key.devid);return ret; }/** description : 驱动入口函数* param : 无* return : 无/ static int __init key_init(void) {int ret 0;/ 初始化原子变量 /atomic_set(key.keyvalue,INVAKEY);/ 注册字符设备驱动 /key.major 0;/ 1、创建设备号 /if (key.major){ / 定义了设备号 /key.devid MKDEV(key.major, 0);register_chrdev_region(key.devid, KEY_CNT, KEY_NAME);}else{ / 没有定义设备号 /alloc_chrdev_region(key.devid, 0, KEY_CNT, KEY_NAME); / 申请设备号 /key.major MAJOR(key.devid); / 获取分配号的主设备号 /key.minor MINOR(key.devid); / 获取分配号的次设备号 /}if(ret 0){goto fail_devid;}printk(major %d , minor %d \r\n, key.major, key.minor);/ 2、初始化cdev */key.cdev.owner THIS_MODULE;cdev_init(key.cdev, key_fops);/初始化的 cdev 结构体变量//* 3、添加一个cdev */cdev_add(key.cdev, key.devid, KEY_CNT);/添加字符设备/if(ret){goto fail_cdevadd;}/* 4、创建类 /key.class class_create(THIS_MODULE, KEY_NAME);if (IS_ERR(key.class)){ret PTR_ERR(key.class);goto fail_class;}/ 5、创建设备 /key.device device_create(key.class, NULL, key.devid, NULL, KEY_NAME);if (IS_ERR(key.device)){ret PTR_ERR(key.device);goto fail_device;}ret keyio_init(key);if (ret 0){goto fail_device;}printk(key_init\r\n);return 0; fail_device:class_destroy(key.class); fail_class:cdev_del(key.cdev); fail_cdevadd:unregister_chrdev_region(key.devid,KEY_CNT); fail_devid:return ret; }/** description : 驱动出口函数 param : 无* return : 无/ static void __exit key_exit(void) {/ 注销字符设备驱动 /cdev_del(key.cdev);/ 删除cdev /unregister_chrdev_region(key.devid, KEY_CNT); / 释放设备号 */device_destroy(key.class, key.devid);/摧毁设备/class_destroy(key.class);/删除类/gpio_free(key.key_gpio);/释放io/ }module_init(key_init); module_exit(key_exit); MODULE_LICENSE(GPL); MODULE_AUTHOR(zuozhongkai);五、应用编写 总体代码如下 #include sys/types.h #include sys/stat.h #include fcntl.h #include stdio.h #include unistd.h #include stdlib.h #include string.h#define INVAKEY 0x00 #define KEY0VALUE 0XF0/*argc:应用程序参数个数argv数组元素个数argv:具体参数,也可以写作char **argv./keyAPP filename ./keyAPP /dev/key */ int main(int argc, char *argv[]) {int fd,retvalue;char *filename;unsigned char databuf[1];int value0;/判断命令行输入参数是否正确/if(argc ! 2){printf(error usage!\r\n);return -1;}/用指针指向文件/filename argv[1];/打开文件/fd open(filename , O_RDWR);if(fd 0){printf(file open failed\r\n,filename);return -1;}/循环读取/while(1){read(fd,value,sizeof(value));if(value KEY0VALUE){printf(KEY0 press , value %d\r\n,value);}}/关闭文件/close(fd);return 0; } 循环读取处用read读取内核拷贝的数据 验证 可以看到按下按键就会打印value的值 这里埋下一个伏笔运行测试APP会占用99%的CPU资源 后续章节进行介绍