在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  0x01c20800
typedef 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  0x01c20800
typedef 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]->CFG0n = 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");

39 解决全志h3 linux内核源码里的关于script.fex的bug相关推荐

  1. Linux移植:正点原子阿尔法IMX6ULL开发板Linux内核源码移植详细步骤(4.1.15版本内核)

    Linux移植:正点原子阿尔法IMX6ULL开发板Linux内核源码移植详细步骤(4.1.15版本内核) 文章目录 Linux移植:正点原子阿尔法IMX6ULL开发板Linux内核源码移植详细步骤(4 ...

  2. Linux内核源码中使用宏定义的若干技巧

    在C中,宏定义的概念虽然简单,但是真要用好却并不那么容易,下面从Linux源码中抽取一些宏定义的使用方法,希望能从中得到点启发: 1. 类型检查 比如module_init的宏定义: 点击(此处)折叠 ...

  3. ubuntu下wget下载Linux内核源码、make生成.config文件

    根据资料,如果要调试Linux内核源码,需要自己编译内核源码:原因是,一般下载的内核并不是为调试而编译的,要在编译时开启 "Compile the kernel with debug inf ...

  4. Linux内核源码分析方法

    说明:这是一个刚接触内核三个月的同学,通过对一个内核特性的分析,总结出一套分析内核的方法. 一.内核源码之我见 Linux内核代码的庞大令不少人"望而生畏",也正因为如此,使得人们 ...

  5. 【linux内核-源码编译之centos7】

    linux内核-源码编译之centos7 一. 为什么要编译内核 二.疑难杂症 三.演示环境 四.下载源码 4.1.两者源码区别 4.2.将获取到的源码放在/usr/src/kernels/ 下 五. ...

  6. linux内核代码研读与实战,Linux内核源码研读与实战演练

    Linux内核源码研读与实战演练 网盘下载链接: http://pan.baidu.com/s/1fIYf0 密码: 341f 要是网盘失效了,请加我QQ: 3113533060 课程内容: 第1部分 ...

  7. 详细讲解Linux内核源码内存管理(值得收藏)

    Linux的内存管理是一个非常复杂的过程,主要分成两个大的部分:内核的内存管理和进程虚拟内存.内核的内存管理是Linux内存管理的核心,所以我们先对内核的内存管理进行简介. 一.物理内存模型 物理内存 ...

  8. 编译linux源码报错,记录一次Linux内核源码编译实验

    记录一次Linux内核源码编译实验 文章目录 记录一次Linux内核源码编译实验 0. 实验环境 1. 选择.下载内核源码 2. 安装必要的依赖软件以及性能要求 3. 解压.配置和编译内核源码 3.1 ...

  9. 腾讯首发Linux内核源码《嵌入式开发进阶笔记》差距差的不止一点点哦

    一,前言 Linux内核是一个操作系统(OS)内核,本质上定义为类Unix.它用于不同的操作系统,主要是以不同的Linux发行版的形式.Linux内核是第一个真正完整且突出的免费和开源软件示例.Lin ...

最新文章

  1. getLocationInWindow getLocationOnScreen getLeft , getTop, getBottom,getRight
  2. 非模态的titlewindow,点击外部时的事件
  3. 【问题解决】微软OneNote使用笔记,Ditto解决OneNote复制粘贴文本输出图片问题
  4. 访问数据库_访问数据库
  5. GAN做图像翻译的一点总结
  6. 消除电脑的四大噪音源
  7. oracle几何体数据类型,Oracle数据库之spatial操作geometry方法
  8. 如何建立数据平台?看上市公司的选择!
  9. 关于IE6,7下面的一些兼容性问题
  10. python中的unicode码是什么_Python中Unicode字符串
  11. matlab隐函数参数拟合,matlab拟合隐函数参数(1stOpt拟合7参数请求代跑)
  12. CRichEditDoc下保存文档出现\rtf1\ansi\ansicpg936\deff0的解决方法
  13. 萌新小白的HTML第一天学习
  14. SD卡CF卡U盘硬盘等磁盘属性显示为0字节怎么恢复数据
  15. error C2059: syntax error : 'constant'
  16. android开屏页单张图片设置的收评秒开引起的图片变形问题
  17. EAS单据F7设置默认值
  18. linux动画制作软件,你也可以成为设计师!宫崎骏御用2D动画制作软件
  19. 图说三极管,太容易懂了!(史上最详细版本)
  20. Oracle查看连接池

热门文章

  1. UVM基础-Seq-Sqr-Driver交互详解
  2. UNIX/LINUX 平台可执行文件格式分析
  3. C++小程序:拯救公主(文字游戏)
  4. 【python-深度学习】matplotlib库的使用
  5. 通过psping测试结果,初步判断远端服务器的状态
  6. Qtum智能合约使用方法及说明
  7. 3. GDI+ Bitmap和GDI HBITMAP互转
  8. 据说有了IPv6,全世界的每一粒沙子都能编上一个网址!
  9. 移动安全-Burpy自动化加解密APP报文
  10. C语言多行字符串输入问题