飞思卡尔的芯片与三星的芯片有很大的不同, 从GPIO 的配置上就能看到飞思卡尔有多操蛋.
在本节中我们使用GPIO3-23 来点亮板子上的 ERR-LED.
1. 配置 IOMUX 来选择GPIO模式(IOMUXC), GPIO3-23为普通io口
2. 设置GPIO为输出(GDR)
3. 写DR寄存器
Software Mux Control Registers (SW_MUX_CTL)
选择IO口的工作模式,每一个管脚都对应一个SW_MUX_CTL寄存器
Software Pad Control Registers (SW_PAD_CTL)
设置IO口的驱动电压,回转率,驱动强度,开漏输出,上拉阻值,DDR类型等
关于io口还有8个寄存器如下:
typedef struct
{
unsinged long DR; // lqm:Data register
unsinged long GDIR; // lqm:GPIO Direction register. 0:input 1:output
unsinged long PSR; // lqm:Pad sample register. read only
unsinged long ICR1; // lqm:interrupt control register1
unsinged long ICR2; // lqm:interrupt control register2
unsinged long IMR; // lqm:interrupt mask register
unsinged long ISR; // lqm:interrupt state register
unsinged longEDGE_SEL; // lqm:edge select register
} GPIO_REG, *P_GPIO_REG;
DR表示数据寄存器,也就是IO口的高低电平. 当GPIO口设置为GPIO模式时,若设置为输出,则DR[n]返回该寄存器本身设置的值,若设置为输入,则DR[n]返回该脚外部输入的信号值。当GPIO设置为非GPIO模式时,若设置为输出,则DR[n]返回该寄存器本身设置的值,若设置为输入,则DR[n]固定返回0
GDIR表示方向寄存器,0表示输入,1表示输出, 仅当设置为gpio引脚时该寄存器才有效
PSR为只读寄存器,用户通过读取该寄存器值获取IO口的状态
ICR1,ICR2为中断控制寄存器,表明了中断触发方式
两个32-bit寄存器, 寄存器中每两位控制一条中断线,ICR1控制中断0~15, ICR2控制中断16~31
00中断是low-level触发
01中断是high-level触发
10中断是rise-edge触发
11中断时fall-edge触发
IMR为中断屏蔽寄存器,IMR对应位为0时,表示屏蔽对应GPIO的中断功能,为1时表示使能对应中断功能 , 0中断被屏蔽,
ISR 为中断状态寄存器,ISR对应位为1时,表示对应GPIO中断产生,需要通过软件清零相应位。为0时表示中断未产生。
EDGE_SEL为边沿选择寄存器,EDGE_SEL用于设置GPIO是否使用边沿触发,若对应GPIO口设置为1,表示相应GPIO采用上下沿触发,前面的ICR1,ICR2的设置将变得无效。当EDGE_SEL的对应位恢复为0时,ICR1,ICR2的相应位才会变得有效。
注意: 不论GPIO设置为输入还是输出,在读取GPIO对应的电平值时,都读取PSR的值,尽量不要读取DR的值。而设置IO口的电平时通过设置DR的值来实现。
另外在调试过程中想用P2_8来设置为输入读取高低电平, 模块编译成功且没有错误/警告, 但是在insmod的时候会发生segment fault , 原因是NULL指针
我们先来看普通的io口
gpio_direction_output(IOMUX_TO_GPIO(GPIO3_15), arg);
设置gpio模式, 并设置管脚值 1 或 0
从内核跟踪代码得出:
#define GPIO3_15 MX25_PIN_EXT_ARMCLK
MX25_PIN_EXT_ARMCLK = _MXC_BUILD_GPIO_PIN(2, 15, 0x20c, 0x0),
#define _MXC_BUILD_GPIO_PIN(gp,gi,mi,mf,pi,pf) _MXC_BUILD_PIN(gp,gi,mi,mf,pi,pf)
_MXC_BUILD_GPIO_PIN(2, 15, 0x20c, 0x0),
_MXC_BUILD_GPIO_PIN(端口-1, 引脚值, IOMUXC_SW_MUX_CTL_PAD_xxx偏移值, IOMUXC_SW_PAD_CTL_PAD_xxx偏移值), 见4-24页. 注意这里的引脚值不是全局的引脚值而是各个端口的引脚 如GPIO3-15, 这里引脚值就是15
内核为每个多路复用io组织数据的格式为:
例如 MX25_PIN_A14 引脚:
0x0010 IOMUXC_SW_MUX_CTL_PAD_A14
0x0230 IOMUXC_SW_PAD_CTL_PAD_A14
#define _MXC_BUILD__PIN(1, 0, 0x10, 0x230) ((1 << 29) | (0 << 24) | ( 0x10 << 10) | ( 0x230 << 0))
#define _MXC_BUILD_PIN(2, 15, 0x20c, 0x0) (((2) << 29) | ((15) << 24) | ((0) << 10) | ((0x20c) << 0))
P2_8不能调用mxc_iomux_set_pad 原因:
中间木有A22 这个A22就是P2_8
飞思卡尔在移植的时候这里直接给的是 0,然后代码里没有判断0 直接NULL insmod的时候就segment fault了
在arch\arm\mach-mx25\mx25_pins.h的 enum iomux_pins {...}里
像这种最后参数是0的 都不能调用 mxc_iomux_set_pad 方法 ,不然在insmod的时候会出段错误
_MXC_BUILD_GPIO_PIN(端口-1, 引脚值, IOMUXC_SW_MUX_CTL_PAD_xxx寄存器偏移值, IOMUXC_SW_PAD_CTL_PAD_xxx寄存器偏移值)
一下为追踪代码的过程: