39 解决全志h3 linux内核源码里的关于script.fex的bug
来源:互联网 发布:不动产静态投资 软件 编辑:程序博客网 时间:2024/04/26 09:34
在script.fex里有关于io口的配置:
Port:端口+组内序号<功能分配><内部电阻状态><驱动能力><输出电平状态> [gpio_para] gpio_used = 1 ;gpio_num = 30 ;gpio_pin_1 = port:PL10<1><default><default><1> ;gpio_pin_2 = port:PA15<1><default><default><0> ...
发现在内核源码里并没有对io口的上下拉功能,驱动电流等级等相关的配置寄存器进行设置,从而让io口的上下拉功能,驱动电流等功能根本无法应用.
自己写代码来根据script.bin里的io口相关设置来配置相应的寄存器解决这个问题:
1) 使用内核里的导出函数”script_get_pio_list”, 获取script.bin里关于主键”gpio_para”所有关于gpio的子键的配置值.
script_item_u *list; n = script_get_pio_list("gpio_para", &list); //返回值为gpio口的个数
2) 映射关于io口的配置寄存器基地址, 并准备好每组的gpio口的配置寄存器.
根据上图,封装一个结构体。
#define PIO_BASE 0x01c20800typedef volatile unsigned int uint32;typedef struct { // gpio口的功能配置寄存器, 每个io口在配置寄存器里占用4位(实际用3位) uint32 CFGs[4]; //4个功能配置寄存器,每个寄存配置8个io口 // gpio口的数据寄存器, 每个io口占用一位. uint32 DAT; // gpio口驱动电流配置寄存器, 每个io口占用2位 uint32 DRVs[2]; // 两个寄存器,每个寄存器配置16个io口 // gpio口上下拉配置寄存器, 每个io口占用2位 uint32 PULLs[2]; // 两个寄存器,每个寄存器配置16个io口}PIO_t; //表示每组io口都有的配置寄存器static PIO_t *pios[7]; // 每个元素分别存放PA, PB, PC, PD, PE, PF, PG组io口的寄存器地址static u8 *vaddr;
并在映射寄存器地址后,分配好每组io口的寄存器地址
vaddr = ioremap(PIO_BASE, SZ_4K); //映射gpio配置寄存器的基地址 if (NULL == vaddr) return -ENOMEM; for (i = 0; i < ARRAY_SIZE(pios); i++) //准备好每组io口的配置寄存器的地址 pios[i] = (PIO_t *)(vaddr+i*0x24);
3) 再根据从script.bin获取出来的io口相关配置值来设置寄存器
for (i = 0; i < n; i++) { //在内核里每组io口都算是32个一组,即使硬件上每组都没有32个io口那么多. //所以list[i].gpio.gpio / 32 即可算出是第几组, j = list[i].gpio.gpio >> 5; // pios[j]就是表示相应组的配置寄存结构体 k = list[i].gpio.gpio & 31; //算出在组内是第几个io口 sel = list[i].gpio.mul_sel; //script.bin里io功能选择 pull = list[i].gpio.pull; //上下拉功能 drv = list[i].gpio.drv_level; //驱动电流等级 level = list[i].gpio.data; //io口作输出时,输出什么电平 if (-1 != sel) //功能选择不是<default> { pios[j]->CFGs[k>>3] &= ~(0xf << ((k&7)<<2)); pios[j]->CFGs[k>>3] |= sel << ((k&7)<<2); if (1 == sel) //如果是输出,还需指定输出的电平 { pios[j]->DAT &= ~(1<<k); pios[j]->DAT |= level << k; } } if (-1 != pull) //上下拉功能不是<default> { pios[j]->PULLs[k>>4] &= ~(3 << ((k&15)<<1)); pios[j]->PULLs[k>>4] |= pull << ((k&15)<<1); } if (-1 != drv) //驱动电流等级不是<default> { pios[j]->DRVs[k>>4] &= ~(3 << ((k&15)<<1)); pios[j]->DRVs[k>>4] |= drv << ((k&15)<<1); } }
完整代码:
h3gpio.c
#include <linux/init.h>#include <linux/module.h>#include <mach/sys_config.h>#include <mach/pinctrl.h>#include <asm/io.h>#include <mach/gpio.h>#define PIO_BASE 0x01c20800typedef volatile unsigned int uint32;typedef struct { // gpio口的功能配置寄存器, 每个io口在配置寄存器里占用4位(实际用3位) uint32 CFGs[4]; //4个功能配置寄存器,每个寄存配置8个io口 // gpio口的数据寄存器, 每个io口占用一位. uint32 DAT; // gpio口驱动电流配置寄存器, 每个io口占用2位 uint32 DRVs[2]; // 两个寄存器,每个寄存器配置16个io口 // gpio口上下拉配置寄存器, 每个io口占用2位 uint32 PULLs[2]; // 两个寄存器,每个寄存器配置16个io口}PIO_t; //表示每组io口都有的配置寄存器static PIO_t *pios[7]; // 每个元素分别存放PA, PB, PC, PD, PE, PF, PG组io口的寄存器地址static u8 *vaddr;static int __init h3gpio_init(void){ script_item_u *list; int n, i, j, k; int sel, pull, drv, level; vaddr = ioremap(PIO_BASE, SZ_4K); //映射gpio配置寄存器的基地址 if (NULL == vaddr) return -ENOMEM; for (i = 0; i < ARRAY_SIZE(pios); i++) //准备好每组io口的配置寄存器的地址 pios[i] = (PIO_t *)(vaddr+i*0x24); // pa的配置寄存器0的地址 == &pios[0]->CFG0 n = script_get_pio_list("gpio_para", &list); //返回值为gpio口的个数 if (n <= 0) return -ENODEV; for (i = 0; i < n; i++) { //在内核里每组io口都算是32个一组,即使硬件上每组都没有32个io口那么多. //所以list[i].gpio.gpio / 32 即可算出是第几组, j = list[i].gpio.gpio >> 5; // pios[j]就是表示相应组的配置寄存结构体 k = list[i].gpio.gpio & 31; //算出在组内是第几个io口 sel = list[i].gpio.mul_sel; //script.bin里io功能选择 pull = list[i].gpio.pull; //上下拉功能 drv = list[i].gpio.drv_level; //驱动电流等级 level = list[i].gpio.data; //io口作输出时,输出什么电平 if (-1 != sel) //功能选择不是<default> { pios[j]->CFGs[k>>3] &= ~(0xf << ((k&7)<<2)); pios[j]->CFGs[k>>3] |= sel << ((k&7)<<2); if (1 == sel) //如果是输出,还需指定输出的电平 { pios[j]->DAT &= ~(1<<k); pios[j]->DAT |= level << k; } } if (-1 != pull) //上下拉功能不是<default> { pios[j]->PULLs[k>>4] &= ~(3 << ((k&15)<<1)); pios[j]->PULLs[k>>4] |= pull << ((k&15)<<1); } if (-1 != drv) //驱动电流等级不是<default> { pios[j]->DRVs[k>>4] &= ~(3 << ((k&15)<<1)); pios[j]->DRVs[k>>4] |= drv << ((k&15)<<1); } } return 0;}static void __exit h3gpio_exit(void){ iounmap(vaddr);}module_init(h3gpio_init);module_exit(h3gpio_exit);MODULE_LICENSE("GPL");
阅读全文
0 0
- 39 解决全志h3 linux内核源码里的关于script.fex的bug
- 38 全志平台的script.bin在linux内核里的应用分析
- linux内核源码里的链表
- 全志FEX文件介绍
- 关于checkbox的全选择的script
- 关于香橙派H3的一些问题
- 全志H3 linux系统recovery制作过程
- 全志的 Linux 内核后门分析
- 关于NanoPi NEO(全志H3)平台下的LEDE(openWRT)系统的编译(分色排版)(不知道怎么烧录)
- 34 dht12单总线方式的Linux驱动及解决H3丢失中断的问题
- 关于一个bug的解决
- 关于linux内核驱动源码里 __devexit 这个宏
- 全志H3芯片支持4k点对点输出,高清广告机的福音
- 全志H3-android 4.4下进行USB Camera的配置和使用总结
- Linux内核里的DebugFS
- Linux内核里的DebugFS
- Linux内核里的DebugFS
- Linux内核里的DebugFS
- Activity与fragment之间的交互总结
- grep 、find、xargs使用方法
- Eclipse M2E 插件配置
- 欢迎使用CSDN-markdown编辑器
- RocketMQ使用心得1-消息发送
- 39 解决全志h3 linux内核源码里的关于script.fex的bug
- 懒人改善生活之
- Struts2实现上传文件
- MyEclipse Import 工程 UnknownFaceted Project Problem (Java Version Mismatch) 问题解决!
- Fastlane安装,实现自动化打包和发布
- JS表单验证-12个常用的JS表单验证
- 解决路径传参的乱码问题
- 注解
- 如果注册一个net_device呢?