RIoTboard连载五 RIoTboard GPIO相关函数和宏定义简介

原文地址:http://www.eeboard.com/bbs/thread-31222-1-1.html

最近几天忙于做LCD显示驱动板的原理图和PCB,终于板子投了,大概周一能够收到就可以焊接调试了。
这几天也算是有时间看下驱动相关的东西,先总最简单的GPIO开始说起吧。首先分析下linux下操作imx6s芯片的大概过程和主要函数与宏定义。
不管uboot中还是linux下imx6的GPIO配置都要区分IOMUX和GPIO的配置,首先通过配置IOMUX寄存器,设置芯片的pad管脚为GPIO功能,然后通过GPIO寄存器来设置GPIO功能。
那么我们看下linux下和IOMUX配置相关的几个函数和宏定义:

在看这个之前要先看一个对引脚配置非常关键的64位的数据定义:

typedef u64 iomux_v3_cfg_t 64bit 的数据定义
这个就是关于IOMUX/PAD的bit为的定义的组合,iomux_v3_cfg_t 的数据域分布如下:
MUX_CTRL_OFS:         0..11 (12)
Mux 控制寄存器地址偏移量,占用12 bit ,分布为iomux_v3_cfg_t 的第0-11bit
PAD_CTRL_OFS:          12..23 (12)
Pad 控制寄存器地址偏移占用12 bit ,分布为iomux_v3_cfg_t 的第12-23bit
SEL_INPUT_OFS:         24..35 (12)
Select input 地址偏移量,占用12 bit ,分布为iomux_v3_cfg_t 的第24-35bit
MUX_MODE + SION:           36..40  (5)
Mux 模式和Software Input On Field. 寄存器的设置,占据5 位,其中mux mode 占用3 bit SION 占用两个bit ,分布为iomux_v3_cfg_t 36-40bit
PAD_CTRL + NO_PAD_CTRL: 41..58 (18)
Pad_ctrl 寄存器配置占用18 bit ,分布为iomux_v3_cfg_t 41-58bit
SEL_INP:              59..62 (4)
SEL_INP 占用4 bit ,分布为iomux_v3_cfg_t 59-62bit
reserved:               63   (1)
这个iomux_v3_cfg_t 是后面几乎所有关于GPIO配置的地方都要用到的一个数据。好了,那下面我们先分析几个函数和宏定义
1.
IOMUX_PAD(PAD Control Offset, MUX ControlOffset, MUX Mode, Select Input Offset, Select Input, Pad Control)
IOMUX_PAD后面几个参数的定义做如下分析:
PAD Control Offset pad control register 的地址偏移,这个寄存器主要配置引脚物理和电气特性,类似接口形式,上下拉,驱动能力,速度等。
1.JPG
2014-5-10 16:50 上传
下载附件 (77.65 KB)

MUX Control Offset MUX control register 的地址偏移,这个寄存器主要是配置引脚的输入路径和引脚的模式选择 ALT0-ALT7.
2.JPG
2014-5-10 16:51 上传
下载附件 (76.78 KB)
MUX Mode MUX mode 数据,在MUX controlregisters 中定义。000-111 对应alt0-alt7
3.JPG
2014-5-10 16:52 上传
下载附件 (21.51 KB)
Select Input Offset MUX control register 地址偏移,主要配置功能见上述表格。
Select Input Select Input data ,在select inputregisters 定义。
Pad Control Pad Control data ,在Pad controlregisters 中定义。
后面我们看看IOMUX_PAD的定义如下:
#define IOMUX_PAD(_pad_ctrl_ofs, _mux_ctrl_ofs, _mux_mode, _sel_input_ofs, \
                _sel_input, _pad_ctrl)                                        \
        (((iomux_v3_cfg_t)(_mux_ctrl_ofs) << MUX_CTRL_OFS_SHIFT) |        \
                ((iomux_v3_cfg_t)(_mux_mode) << MUX_MODE_SHIFT) |        \
                ((iomux_v3_cfg_t)(_pad_ctrl_ofs) << MUX_PAD_CTRL_OFS_SHIFT) | \
                ((iomux_v3_cfg_t)(_pad_ctrl) << MUX_PAD_CTRL_SHIFT) |        \
                ((iomux_v3_cfg_t)(_sel_input_ofs) << MUX_SEL_INPUT_OFS_SHIFT) | \
                ((iomux_v3_cfg_t)(_sel_input) << MUX_SEL_INPUT_SHIFT))
通过IOMUX_PAD的定义可以看出,这个就是一个宏定义,是一个用来生成iomux_v3_cfg_t 这个数据的方法的定义。
括号里的参数都是按照iomux_v3_cfg_t 的数据域进行不同位数的移位然后相或,来产生iomux_v3_cfg_t 。
那我们看代码中的如下定义:
#define MX6DL_PAD_EIM_A25__GPIO_5_2 IOMUX_PAD(0x0504, 0x0134, 5, 0x0000, 0, NO_PAD_CTRL)

其实这个定义就是针对EIM_A25生成一个iomux_v3_cfg_t数据。
以上只是生成了IOMUX/PAD的相关数据,那么怎么配置IOMUX和GPIO呢,那就继续看下面一个函数
2.int mxc_iomux_v3_setup_pad(iomux_v3_cfg_tpad)
{
         u32mux_ctrl_ofs = (pad & MUX_CTRL_OFS_MASK) >> MUX_CTRL_OFS_SHIFT;
         u32mux_mode = (pad & MUX_MODE_MASK) >> MUX_MODE_SHIFT;
         u32sel_input_ofs = (pad & MUX_SEL_INPUT_OFS_MASK) >>MUX_SEL_INPUT_OFS_SHIFT;
         u32sel_input = (pad & MUX_SEL_INPUT_MASK) >> MUX_SEL_INPUT_SHIFT;
         u32pad_ctrl_ofs = (pad & MUX_PAD_CTRL_OFS_MASK) >>MUX_PAD_CTRL_OFS_SHIFT;
         u32pad_ctrl = (pad & MUX_PAD_CTRL_MASK) >> MUX_PAD_CTRL_SHIFT;
         if(mux_ctrl_ofs)
                   __raw_writel(mux_mode,base + mux_ctrl_ofs);
         if(sel_input_ofs)
                   __raw_writel(sel_input,base + sel_input_ofs);
         if(!(pad_ctrl & NO_PAD_CTRL) && pad_ctrl_ofs)
                   __raw_writel(pad_ctrl,base + pad_ctrl_ofs);
         return0;
}
这个函数呢也还是围绕着iomux_v3_cfg_t这个64位的数据做文章,大家也都可以看到,基本就是从iomux_v3_cfg_t  中取出和实际引脚对应的mux_mode等实际值,然后通过__raw_writel ()函数来完成引脚功能的实际初始化。
好了到现在我们可以配置IOMUX了,但是如何操作GPIO呢,其实在这个源代码里面没有看见类似直接操作寄存器来操作GPIO输出的函数,因为毕竟到了linux下面直接访问寄存器已经不向uboot或者裸机操作那么简单了,那么我们如何操作GPIO呢,下面就来看下linux的GPIO number的导出。
在imx6下面有GPIO1-7组GPIO,在uboot和GPIO初始化时候可以使用寄存器基地址或者 iomux_v3_cfg_t 这个数据来操作GPIO,但是到了linux就要将GPIO1-7组的GPIO统一编号到linux下,那么如何进行编号呢,可能大家都看到了,在board_mx6q_riot.c文件中有很多类似#define RIOT_USER_LED                IMX_GPIO_NR(5, 2)的定义,那么这个IMX_GPIO_NR又是什么呢,我们看看它的定义如下
#define IMX_GPIO_NR(bank, nr)                (((bank) - 1) * 32 + (nr))
由此可见这是个将不同组的GPIO统一到linux下的GPIO number的计算公式,即:<GPIO Instance – 1> × 32 + <GPIO Port number>
比如说RIOT板子的用户LED这个GPIO的转换,IMX_GPIO_NR(5,2),就是说在imx6芯片中控制LED的引脚是GPIO5_2,那么转换到linux就是GPIO ((5-1)*32+2)=130,即linux的GPIO数是GPIO-130。
关于linux的GPIO操作我们可以在linux命令行中路径/sys/class/gpio/export中导出GPIO number,然后对GPIO进行操作,来控制GPIO输入和输出,比如刚才分析我们的LED控制引脚在linux下是GPIO-130,那我们就可以进行如下操作:
echo 130 > /sys/class/gpio/export
设置输出命令:
echo out > /sys/class/gpio/gpio30/direction
设置输出1和输出0:
echo 1 > /sys/class/gpio/gpio130/value
echo 0 > /sys/class/gpio/gpio130/value
但是在我们系统中,GPIO-130已经由系统注册为platform设备,所以使用GPIO export会提示资源繁忙无法配置,那在后续的文章中我们就继续分析如何在linux源码中进行GPIO的控制。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值