i.mx257的gpio简要理解

来源:互联网 发布:软件测试技能需求 编辑:程序博客网 时间:2024/05/28 16:16

飞思卡尔的芯片与三星的芯片有很大的不同, 从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寄存器偏移值) 


一下为追踪代码的过程:

/********************************************************************************************************************/gpio_direction_output(IOMUX_TO_GPIO(GPIO3_15), arg);#define MUX_IO_P29#define MUX_IO_I24#define IOMUX_TO_GPIO(pin) ((((unsigned int)pin >> 29) << 5) + ((pin >> 24) & ((1 << (29 - 24)) -1)))#define GPIO3_15 MX25_PIN_EXT_ARMCLKMX25_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),#define _MXC_BUILD_PIN(gp, gi, mi, pi)  (((2) << 29) | ((15) << 24) | ((0) << 10) | ((0x20c) << 0))gpio_direction_output((((2 << 29) | (15 << 24) | (0x20c << 0) | (0 << 10)) & (0xff << 9)) >> 9), 0)struct gpio_chip {  int(*direction_output)(struct gpio_chip *chip, unsigned offset, int value);port[i].chip.direction_output = mxc_gpio_direction_output;static int mxc_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value){mxc_gpio_set(chip, offset, value);_set_gpio_direction(chip, offset, 1);return 0;}static void mxc_gpio_set(struct gpio_chip *chip, unsigned offset, int value){struct mxc_gpio_port *port = container_of(chip, struct mxc_gpio_port, chip);void __iomem *reg = port->base + GPIO_DR;//mx25.h第438行  #define GPIO_DR  0x00u32 l;l = (__raw_readl(reg) & (~(1 << offset))) | (value << offset);__raw_writel(l, reg);}static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset, int dir){struct mxc_gpio_port *port =container_of(chip, struct mxc_gpio_port, chip);u32 l;l = __raw_readl(port->base + GPIO_GDIR);if (dir)l |= 1 << offset;elsel &= ~(1 << offset);__raw_writel(l, port->base + GPIO_GDIR);}/********************************************************************************************************************//********************************************************************************************************************/http://blog.csdn.net/maopig/article/details/7428561mxc_request_iomux(MX25_PIN_EB0, MUX_CONFIG_ALT4); /*SSI4_STXD*/iomux_config_mux(pin, cfg);__raw_writel(cfg, mux_reg);gpio_request(IOMUX_TO_GPIO(pin), NULL);/********************************************************************************************************************/mxc_iomux_set_pad(MX25_PIN_A14, PAD_CTL_PKE_ENABLE );mxc_iomux_set_pad分析记录http://www.xuebuyuan.com/642369.htmlvoid mxc_iomux_set_pad(iomux_pin_name_t pin, u32 config){void *pad_reg = IOMUXGPR + PIN_TO_IOMUX_PAD(pin);=> mux_reg = base + 0x00000230BUG_ON((pad_reg > IOMUXSW_PAD_END) || (pad_reg < IOMUXSW_PAD_CTL));__raw_writel(config, pad_reg);}/********************************************************************************************************************///1 选择io口的功能//配置IOMUX寄存器,把MX51_PIN_AUD3_BB_CK引脚配置为GPIOmxc_request_iomux(MX51_PIN_AUD3_BB_CK,IOMUX_CONFIG_GPIO);  //linux系统通用的GPIO的操作函数,她的入口是个int的整型的数,所以需要使用IOMUX_TO_GPIO(MX51_PIN_AUD3_BB_CK)函数来转换。 “BB_CK”只是一个字符标记,填写什么内容都可以gpio_request(IOMUX_TO_GPIO(MX51_PIN_AUD3_BB_CK), "BB_CK");//设置GPIO的方向gpio_direction_output(IOMUX_TO_GPIO((MX51_PIN_AUD3_BB_CK), ), 0);gpio_set_value(IOMUX_TO_GPIO((MX51_PIN_AUD3_BB_CK)), 1);  //IO置高的操作gpio_set_value(IOMUX_TO_GPIO((MX51_PIN_AUD3_BB_CK)), 0);  //IO置低的操作/*bug P2_8*/printk (KERN_ALERT "IOMUXGPR + PIN_TO_IOMUX_PAD(pin) = %p", IO_ADDRESS(0x43fac000) + PIN_TO_IOMUX_PAD(GPIO2_8));GPIO2_8 _MXC_BUILD_GPIO_PIN(1, 8, 0x30, 0x0)_MXC_BUILD_PIN(1, 8, 0x30, 0x0)((1 << 29) | (8 << 24) | (0x30 << 0) | (0 << 10)) => 0x28000030#define PIN_TO_IOMUX_PAD(0x28000030) ((0x28000030 >> 10) & ((1<<(21 - 10)) - 1))


0 0
原创粉丝点击