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

漫画做视频在线观看网站新手搭建网站教程视频

漫画做视频在线观看网站,新手搭建网站教程视频,wordpress仿天涯主题,删除不了wordpress若该文为原创文章#xff0c;转载请注明原文出处。 字符设备驱动程序的基本框架#xff0c;主要是如何申请及释放设备号、添加以及注销设备#xff0c;初始化、添加与删除 cdev 结构体#xff0c;并通过 cdev_init 函数建立 cdev 和 file_operations 之间的关联#xff0c…若该文为原创文章转载请注明原文出处。 字符设备驱动程序的基本框架主要是如何申请及释放设备号、添加以及注销设备初始化、添加与删除 cdev 结构体并通过 cdev_init 函数建立 cdev 和 file_operations 之间的关联cdev 结构体和 file_operations 结构体。 记录编写第一个真正的 Linux 字符设备驱动点灯。 使用的开发板是正点原子的ATK-DLRK3568. 一、查看原理图 通过查看原理图得知LED控制引脚接到了 GPIO0_C0上通过三极管控制LEDGPIO0_C0输出高电平LED亮输出低电平LED灭。 二、GPIO介绍 GPIO(General Purpose Input/Output Port)通用输入输出端口。 除作为一般的输入/输出功能外还可以配置为中断和模拟UART、CAN、PWM、I2C、SDMMC、CLK等功能。 比如 GPIO0_C0 这个 IO 就可以用 作GPIOPWM1_M0GPU_AVS 和 UART0_RX 这四个功能所以我们首先要设置好当前引 脚用作什么功能。 rk356x 系列对应的文档为: • Rockchip_RK3568_TRM_Part1_xxx.pdf • Rockchip_RK3566_Datasheet_xxx.pdf • Rockchip_RK3568_Datasheet_xxx.pdf 1、GPIO分组 RK3568共160个GPIO引脚复用型引脚分为 5 组 (GPIO0~4)每组里面都有 32 个复 用型引脚而且又分为 4 个小组 (A、B、C、D)每个小组 8 个引脚 (0~7)。例如GPIO0_C7 是 GPIO0 大组第 3 个小组第 8 个引脚。 要查找GPIO对应的配置寄存器地址必须知道他属于哪个分组。 对于 LED 灯的控制进行控制也就是对上述 GPIO 的寄存器进行读写操作。 可大致分为以下几个 步骤 • 使能 GPIO 时钟 (默认开启不用设置) • 设置引脚复用为 GPIO(复位默认为 GPIO不用配置) • 设置引脚属性 (上下拉、速率、驱动能力, 默认) • 控制 GPIO 引脚为输出并输出高低电平 因为 GPIO 的时钟默认开启引脚默认复用为 GPIO我们只需要配置 GPIO 的引脚输入输出模式 及电平即可。 2、GPIO引脚号计算方法 pins 32*bank_num 8*group x bank_num : 0 ~ 4对应GPIO 0~4 group : 0 ~ 3对应GPIO A~DGPIO0_C0: GPIO0_C2 32*0(bank_num) 8*2(group) 0 16根据计算GPIO0_C0序号为16。在后面驱动代码时会用到。 2、寄存器配置 这里以GPIO0_C0为例查看Rockchip_RK3568_TRM_Part1手册可知GPIO0 组复用功能是在 PMU_GRF 寄存器实验中需要对 GPIO 进行配置一般情况下需要对 GPIO 的复用寄存器方向寄存器数据寄存器进行配置, 和复用相关的总共 8 个寄存器。 1. 查找复用寄存器 搜索 GPIO0_C0,GPIO0_C0_sel 在 PMU_GRF_GPIO0C_IOMUX_H 上偏移地址为 0x0010。GPIO0_C0可以通过控制[2:0]位来选择复用为哪个功能我们要控制led 灯所以功能要复用为 GPIO。 复用寄存器的基地址: GPIO0_C0 设置为 GPIO所以 PMU_GRF_GPIO0C_IOMUX_L 的 bit2:0 这三位 设置 000。另外 bit18:16 要设置为 111允许写 bit2:0。 2. 查找方向寄存器 通过设置 GPIO 寄存器设置输入输出、高低电平、中断、抖动等一些引脚的驱动能力电 气属性等主要通过设置 General Register Files (GRF)(以 GPIO0 组为例详细自行参考 Rockchip_RK35xx_TRM_Part1 手册) • GPIO_SWPORT_DDR_L低位引脚数据方向寄存器控制输入或者输出。 • GPIO_SWPORT_DDR_H高位引脚数据方向寄存器控制输入或者输出。 通过寄存器描述该寄存器有高 16bit 和低 16bit高 16bit 控制低 16bit 的 写使能低 16bit 控制 GPIO 的输出方向 0输入1输出。 GPIO0_C0属于 GPIO0 中 A-D 组总计 64 个引脚中的高 32 引脚范围所以需要将 GPIO_SWPORT_DDR_H 寄存器的第 0bit 位和 16bit 位置 1允许写 bit16。 GPIO0~GPIO4 的基地址 GPIO_SWPORT_DDR_H 寄存器地址计算  Operational Base offset  0xFDD60000 0x000C  0xFDD6000C 3. GPIO 引脚高低电平设置 • GPIO_SWPORT_DR_L低位引脚数据寄存器设置高低电平。 • GPIO_SWPORT_DR_H高位引脚数据寄存器设置高低电平。 GPIO_SWPORT_DR_L 和 GPIO_SWPORT_DR_H 寄存器有高 16bit 和低 16bit高 16bit 控制低 16bit 的写 使能低 16bit 控制 GPIO 的高低电平。 GPIO0_C0属于 GPIO0 中 A-D 组总计 64 个引脚 中高的 32 引脚范围所以需要将 GPIO_SWPORT_DR_H 寄存器的第0bit 位和 16bit 位置 1。 4. 总结 复用关系寄存器的基地址为 0xFDC20000 偏移地址为 0x0010 所以要操作的地址为基地址偏移地址0xFDC20010  GPIO 的基地址为 0xFDD60000偏移地址为 0x000C 所以方向寄存器要操作的地址为基地址偏移地址0xFDD6000C  GPIO 的基地址为 0xFDD60000偏移地址为 0x0004 所以数据寄存器要操作的地址为基地址偏移地址0xFDD60004 三、驱动程序编写 1、编写led_cdev.c驱动文件 #include linux/init.h #include linux/module.h #include linux/cdev.h #include linux/fs.h #include linux/uaccess.h #include linux/io.h#define DEV_NAME led_chrdev #define DEV_CNT (1)#define GPIO0_BASE (0xfdd60000)//每组GPIO,有2个寄存器,对应32个引脚每个寄存器负责16个引脚 //一个寄存器32位其中高16位都是使能位低16位对应16个引脚每个引脚占用1比特位 #define GPIO0_DR_L (GPIO0_BASE 0x0000) #define GPIO0_DR_H (GPIO0_BASE 0x0004)#define GPIO0_DDR_L (GPIO0_BASE 0x0008) #define GPIO0_DDR_H (GPIO0_BASE 0x000C)static dev_t devno; struct class *led_chrdev_class;struct led_chrdev {struct cdev dev;unsigned int __iomem *va_dr; // 数据寄存器设置输出的电压unsigned int __iomem *va_ddr; // 数据方向寄存器设置输入或者输出unsigned int led_pin; // 偏移 };/* 打开设备函数 */ static int led_chrdev_open(struct inode *inode, struct file *filp) { unsigned int val 0;struct led_chrdev *led_cdev (struct led_chrdev *)container_of(inode-i_cdev, struct led_chrdev,dev);filp-private_data container_of(inode-i_cdev, struct led_chrdev, dev);printk(open\n);//设置输出模式val ioread32(led_cdev-va_ddr);val | ((unsigned int)0x1 (led_cdev-led_pin16));val | ((unsigned int)0X1 (led_cdev-led_pin));iowrite32(val,led_cdev-va_ddr);//输出高电平val ioread32(led_cdev-va_dr);val | ((unsigned int)0x1 (led_cdev-led_pin16));val | ((unsigned int)0x1 (led_cdev-led_pin));iowrite32(val, led_cdev-va_dr);return 0; }static int led_chrdev_release(struct inode *inode, struct file *filp) {return 0; }/* 从设备读取数据 */ static ssize_t led_chrdev_read(struct file *file, char __user *buf, size_t size, loff_t *off) { printk(This is led_chrdev_read\r\n);return 0; }/* 向设备写入数据函数 */ static ssize_t led_chrdev_write(struct file *filp, const char __user * buf,size_t count, loff_t * ppos) {unsigned long val 0;char ret 0;struct led_chrdev *led_cdev (struct led_chrdev *)filp-private_data;printk(write \n);get_user(ret, buf);val ioread32(led_cdev-va_dr);printk(val %lx\n, val);if (ret 0 || ret 0){val | ((unsigned int)0x1 (led_cdev-led_pin16));val ~((unsigned int)0x01 (led_cdev-led_pin)); /*设置GPIO引脚输出低电平*/}else{val | ((unsigned int)0x1 (led_cdev-led_pin16));val | ((unsigned int)0x01 (led_cdev-led_pin)); /*设置GPIO引脚输出高电平*/}iowrite32(val, led_cdev-va_dr);printk(val %lx\n, val);return count; }/* 设备操作函数 */ static struct file_operations led_chrdev_fops {.owner THIS_MODULE, // 将 owner 字段指向本模块可以避免在模块的操作正在被使用时卸载该模块.open led_chrdev_open, // 将 open 字段指向 chrdev_open(...)函数.read led_chrdev_read, // 将 open 字段指向 chrdev_read(...)函数.write led_chrdev_write, // 将 open 字段指向 chrdev_write(...)函数.release led_chrdev_release, // 将 open 字段指向 chrdev_release(...)函数 };static struct led_chrdev led_cdev[DEV_CNT] {{.led_pin 0}, //偏移高16引脚,GPIO0_C0 };/* 驱动入口函数 */ static __init int led_chrdev_init(void) {int i 0;dev_t cur_dev;printk(led_chrdev init (lubancat2 GPIO0_C7)\n);/*0 将物理地址转化为虚拟地址 */led_cdev[0].va_dr ioremap(GPIO0_DR_H, 4); //led_cdev[0].va_ddr ioremap(GPIO0_DDR_H, 4); // /*1 创建设备号 */alloc_chrdev_region(devno, 0, DEV_CNT, DEV_NAME);/*2 创建类 */led_chrdev_class class_create(THIS_MODULE, led_chrdev);for (; i DEV_CNT; i) {/*3 初始化 cdev */cdev_init(led_cdev[i].dev, led_chrdev_fops);led_cdev[i].dev.owner THIS_MODULE;/*4 获取主设备号和次设备号 */cur_dev MKDEV(MAJOR(devno), MINOR(devno) i);/*5 添加一个 cdev,完成字符设备注册到内核 */cdev_add(led_cdev[i].dev, cur_dev, 1);/*6 创建设备*/device_create(led_chrdev_class, NULL, cur_dev, NULL, DEV_NAME %d, i);}return 0; }/* 驱动出口函数 */ static __exit void led_chrdev_exit(void) {int i;dev_t cur_dev;printk(led chrdev exit (lubancat2 GPIO0_C7)\n);/*注销字符设备*/for (i 0; i DEV_CNT; i) {iounmap(led_cdev[i].va_dr); // 释放模式寄存器虚拟地址iounmap(led_cdev[i].va_ddr); // 释放输出类型寄存器虚拟地址}for (i 0; i DEV_CNT; i) {cur_dev MKDEV(MAJOR(devno), MINOR(devno) i);//删除设备device_destroy(led_chrdev_class, cur_dev);// 删除 cdevcdev_del(led_cdev[i].dev);}// 注销设备号unregister_chrdev_region(devno, DEV_CNT);// 删除类class_destroy(led_chrdev_class);}module_init(led_chrdev_init); module_exit(led_chrdev_exit);MODULE_AUTHOR(yifeng); MODULE_LICENSE(GPL);总结 模块加载 1、初始化 LED 灯结构体成员将物理寄存器的地址映射到虚拟地址空间 2、向动态申请一个设备号 3、创建设备类 4、绑定 led_cdev 与 led_chrdev_fops 5、注册设备 6、创建设备 模块卸载 1、删除设备 2、注销设备 3、释放被占用的设备号 2、编写makefile KERNELDIR : /home/alientek/rk3568_linux_sdk/kernel ARCHarm64 CROSS_COMPILE/opt/atk-dlrk356x-toolchain/usr/bin/aarch64-buildroot-linux-gnu-export ARCH CROSS_COMPILECURRENT_PATH : $(shell pwd) obj-m : led_cdev.obuild: kernel_moduleskernel_modules:$(MAKE) -C $(KERNELDIR) M$(CURRENT_PATH) modules clean:$(MAKE) -C $(KERNELDIR) M$(CURRENT_PATH) clean编译 3、编写APP应用 ledApp.c #include stdio.h #include unistd.h #include sys/types.h #include sys/stat.h #include fcntl.h #include stdlib.h #include string.h#define LEDOFF 0 #define LEDON 1/** description : main主程序* param - argc : argv数组元素个数* param - argv : 具体参数* return : 0 成功;其他 失败*/ int main(int argc, char *argv[]) {int fd, retvalue;char *filename;unsigned char databuf[1];if(argc ! 3){printf(Error Usage!\r\n);return -1;}filename argv[1];/* 打开led驱动 */fd open(filename, O_RDWR);if(fd 0){printf(file %s open failed!\r\n, argv[1]);return -1;}databuf[0] atoi(argv[2]); /* 要执行的操作打开或关闭 *//* 向/dev/led文件写入数据 */retvalue write(fd, databuf, sizeof(databuf));if(retvalue 0){printf(LED Control Failed!\r\n);close(fd);return -1;}retvalue close(fd); /* 关闭文件 */if(retvalue 0){printf(file %s close failed!\r\n, argv[1]);return -1;}return 0; } 编译 /opt/atk-dlrk356x-toolchain/bin/aarch64-buildroot-linux-gnu-gcc ledApp.c -o ledApp 4、测试 测试有两个一是直接测试二是使用APP应用程序测试。 在测试前需要关闭心跳灯 echo none /sys/class/leds/work/trigger 加载LED驱动 insmod led_cdev.ko 测试方法一 直接给设备写入 1/0 来控制 LED 的亮灭 sh -c echo 0 /dev/led_chrdev0 sh -c echo 1 /dev/led_chrdev0 正点原子的LED是反的所以1是亮0是灭。 测试方法二 ./ledApp /dev/led 1 //打开 LED 灯 ./ledApp /dev/led 0 //关闭 LED 灯 经实验LED驱动工作正常。 卸载驱动 rmmod led_cdev 如有侵权或需要完整代码请及时联系博主。
http://www.hkea.cn/news/14585473/

相关文章:

  • 网站开发方案 ppt正在播网球比赛直播
  • 苏州做网站最好公司优化公司治理结构
  • 免费建立一个个人网站茂名建设局网站
  • 网站建设创业计划书模板范文简述网络营销的方法
  • ftp里找到的index文件查看网站建设中郑州做网站比较专业的机构
  • 沈阳网站建设专家峰峰信息港邯郸信息港
  • 天津网站建站公司工程建设项目招标
  • 做印刷的网站信息系统管理工程师
  • 自适应企业网站模板东莞互联网
  • 网站诸多北京医疗机构网站前置审批需要的材料有哪些
  • 只做动漫的网站织梦中英文网站模板
  • 东莞东城做网站公司网站降权表现
  • 网站搭建需要什么潍坊 优化型网站建设
  • 如何预览做好的网站网站集群建设实施方案
  • 做h5网站要多少钱企业网站开发一薇
  • 江苏省建设厅网站建造师强制注销js网站评论框
  • 银州手机网站建设百度网站建设要多少钱
  • 郑州市网站建设怎么样两个人做类似的梦 网站
  • 济南网站建设公司排名网站建设计划书 模板下载
  • wordpress安装后只显示英文站wordpress入站密码
  • 网站建设评审表贵阳网站建设兼职
  • 小说网站怎么建设wordpress搜索增强
  • 没有网站也可以做推广吗广州市建设工程信息管理平台
  • 学校多语种网站建设方案东莞网站优化哪里找
  • 网站设计速成广州网站备案要多久
  • 旅游网站建设要如何做wordpress 嵌入 插件
  • 滨州建网站公司网站改版多少钱
  • 制作html网站模板个人网站做微擎
  • 网站开发开题报告范文企业服务有哪些
  • 怎么样给自己做网站甜品店网站建设