imx6 gpio分析

本文主要介绍如何配置IOMUX寄存器,设置IO复用寄存器,配置为GPIO功能。
参考:
  http://www.jianshu.com/p/3c2053508342
  http://www.embest-tech.com/community/index.php?topic=2822.0

查看板级文件 kernel/arch/arm/mach-mx6/board_mx6q_sabresd.c MACHINE_START(MX6Q_SABRESD, "Freescale i.MX 6Quad/DualLite/Solo Sabre-SD Board") /* Maintainer: Freescale Semiconductor, Inc. */ .boot_params = MX6_PHYS_OFFSET + 0x100, .fixup = fixup_mxc_board, .map_io = mx6_map_io, .init_irq = mx6_init_irq, .init_machine = mx6_sabresd_board_init,    //-------------------------------->>> mx6_sabresd_board_init .timer = &mx6_sabresd_timer, .reserve = mx6q_sabresd_reserve, MACHINE_END static void __init mx6_sabresd_board_init(void)  //<<<-------------------------------- mx6_sabresd_board_init { ... ... //这里这里已经将大部分寄存器都进行了配置。 if (cpu_is_mx6q()) mxc_iomux_v3_setup_multiple_pads(mx6q_sabresd_pads,    // ------------------>>> mxc_iomux_v3_setup_multiple_pads ARRAY_SIZE(mx6q_sabresd_pads));             // ----------------->>> mx6q_sabresd_pads else if (cpu_is_mx6dl()) { mxc_iomux_v3_setup_multiple_pads(mx6dl_sabresd_pads, ARRAY_SIZE(mx6dl_sabresd_pads)); } ... ... }
mx6q_sabresd_pads结构体。 kernel
/arch/arm/mach-mx6/board_mx6q_sabresd.h static iomux_v3_cfg_t mx6q_sabresd_pads[] = {          // <<<--------------------- mx6q_sabresd_pads /* AUDMUX */ MX6Q_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC, MX6Q_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD, MX6Q_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS, MX6Q_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD, MX6Q_PAD_SD1_DAT1__GPIO_1_17, /* FT5X06 RESET */ MX6Q_PAD_NANDF_CS3__GPIO_6_16, //FT5X06_INT ... ... }
文件:kernel/arch/arm/plat-mxc/include/mach/iomux-mx6q.h 以MX6Q_PAD_SD1_DAT1__GPIO_1_17举例。
//MX6Q_PAD_SD1_DAT1表示寄存器,表示IOMUXC_IOMUXC_SW_MUX_CTL_PAD_SD1_DAT1。芯片手册2160页。
//后面的GPIO_1_17表示将该引脚复用为GPIO17.
//0x0724,0x003c表示寄存器地址的偏移量。具体查看上面的参考链接和芯片手册。
#define MX6Q_PAD_SD1_DAT1__GPIO_1_17 \ (_MX6Q_PAD_SD1_DAT1__GPIO_1_17 | MUX_PAD_CTRL(MX6Q_HIGH_DRV)) #define _MX6Q_PAD_SD1_DAT1__GPIO_1_17 \ IOMUX_PAD(0x0724, 0x033C, 5, 0x0000, 0, 0) #define MUX_PAD_CTRL(x) ((iomux_v3_cfg_t)(x) << MUX_PAD_CTRL_SHIFT)

  #define _MX6Q_PAD_SD2_DAT1__USDHC2_DAT1 \
          IOMUX_PAD(0x0360, 0x004C, 0, 0x0000, 0, 0)
  #define _MX6Q_PAD_SD2_DAT1__ECSPI5_SS0 \
         IOMUX_PAD(0x0360, 0x004C, 1, 0x0834, 0, 0)
  #define _MX6Q_PAD_SD2_DAT1__WEIM_WEIM_CS_2 \
      IOMUX_PAD(0x0360, 0x004C, 2, 0x0000, 0, 0)
  #define _MX6Q_PAD_SD2_DAT1__AUDMUX_AUD4_TXFS \
      IOMUX_PAD(0x0360, 0x004C, 3, 0x07C8, 0, 0)
  #define _MX6Q_PAD_SD2_DAT1__KPP_COL_7 \
      IOMUX_PAD(0x0360, 0x004C, 4, 0x08F0, 0, 0)
  #define _MX6Q_PAD_SD2_DAT1__GPIO_1_14 \
      IOMUX_PAD(0x0360, 0x004C, 5, 0x0000, 0, 0)
  #define _MX6Q_PAD_SD2_DAT1__CCM_WAIT \
      IOMUX_PAD(0x0360, 0x004C, 6, 0x0000, 0, 0)
  #define _MX6Q_PAD_SD2_DAT1__ANATOP_ANATOP_TESTO_0 \
      IOMUX_PAD(0x0360, 0x004C, 7, 0x0000, 0, 0)


文件:kernel/arch/arm/plat-mxc/include/mach/iomux-v3.h #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))

int mxc_iomux_v3_setup_multiple_pads(iomux_v3_cfg_t *pad_list, unsigned count)   // <<<-------- mxc_iomux_v3_setup_multiple_pads() { iomux_v3_cfg_t *p = pad_list; int i; int ret; for (i = 0; i < count; i++) { ret = mxc_iomux_v3_setup_pad(*p);          // ------------------------------>>> mxc_iomux_v3_setup_pad() if (ret) return ret; p++; } return 0; } EXPORT_SYMBOL(mxc_iomux_v3_setup_multiple_pads); /* 将定义的宏解析,提取其中数据,设置到寄存器中 */ int mxc_iomux_v3_setup_pad(iomux_v3_cfg_t pad)       // <<<---------------------------- mxc_iomux_v3_setup_pad() { u32 mux_ctrl_ofs = (pad & MUX_CTRL_OFS_MASK) >> MUX_CTRL_OFS_SHIFT; u32 mux_mode = (pad & MUX_MODE_MASK) >> MUX_MODE_SHIFT; u32 sel_input_ofs = (pad & MUX_SEL_INPUT_OFS_MASK) >> MUX_SEL_INPUT_OFS_SHIFT; u32 sel_input = (pad & MUX_SEL_INPUT_MASK) >> MUX_SEL_INPUT_SHIFT; u32 pad_ctrl_ofs = (pad & MUX_PAD_CTRL_OFS_MASK) >> MUX_PAD_CTRL_OFS_SHIFT; u32 pad_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); return 0; } EXPORT_SYMBOL(mxc_iomux_v3_setup_pad);

 

IMX_GPIO_NR是**用于确定GPIO(General-Purpose Input/Output,通用输入输出)端口号的宏定义**。 在嵌入式系统开发中,特别是在使用i.MX系列处理器时,IMX_GPIO_NR用于计算特定的GPIO端口号。这个宏通常在硬件抽象层(HAL)或驱动程序中定义,以便在不同的硬件平台上对GPIO进行统一操作。具体来说,IMX_GPIO_NR的公式是`((bank) - 1) * 32 + (nr))`,其中`bank`表示GPIO所在的银行编号,而`nr`表示在该银行内的GPIO编号。 以下是一些关于IMX_GPIO_NR的关键点: 1. **函数原型**:IMX_GPIO_NR通常在头文件如`hardware.h`中定义,作为计算GPIO端口号的函数原型参数。 2. **计算方法**:通过公式`((bank) - 1) * 32 + (nr))`可以计算出具体的GPIO端口号。例如,IMX_GPIO_NR(6,4)将会计算出164作为端口号。 3. **用途**:这个宏主要用于设置GPIO的方向(输入或输出),以及读取或写入GPIO的值。例如,`gpio_direction_output(IMX_GPIO_NR(3, 0), 1);`这行代码将GPIO3_IO00设置为高电平。 4. **硬件结构**:GPIO是微控制器芯片上的一种通用可编程I/O接口,它至少包含数据寄存器和控制寄存器两个部分。数据寄存器的位直接引到芯片外部,而控制寄存器则对数据寄存器中的每一位进行独立设置。 5. **操作系统兼容性**:在Linux操作系统中,GPIO操作接口允许用户通过统一的API来操作不同的GPIO,这样可以在不同的平台上复用相同的代码。 综上所述,了解IMX_GPIO_NR对于进行嵌入式系统开发,尤其是在使用i.MX处理器系列的项目中,是非常重要的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值