分类: 嵌入式
2011-05-11 15:44:53
由于公司的IP camera使用的是mx27(19内核),设计到7113的移植,移植过程中出现了GPIO口配置错误。所以对其GPIO口和7113所使用GPIO口 进行了分析,刚开始对mx27对于GPIO口的使用,和内核中关于GPIO口的配置方法不是很熟悉,在论坛发帖也没人回,这里做个简单总结。
mx27的GPIO口一共有6个端口,每个端口有32个引脚。看源码:
#define MUX_IO_P 29
#define MUX_IO_I 24
#define _MX27_BUILD_PIN(gp,gi) (((gp) << MUX_IO_P) | ((gi) << MUX_IO_I))
开始对于前两个宏的定义不是很理解,虽然内核注释中写明,一个用于索引GPIO的端口,一个用于在指定端口进行偏移,但是为什么一个是29一个是23,不解.
第三个宏就是找到指定的GPIO引脚。例如对于端口2的21引脚,如下索引:
#define _MX27_BUILD_PIN(1,21) ((1< 源码中定义了一个枚举完成对所有GPIO的功能索引: typedef enum iomux_pins { ...... MX27_PIN_CSI_D0 = _MX27_BUILD_PIN(1, 10), ........ } 只贴出了与摄像头功能匹配的部分。 MX27_PIN_CSI_D2 = _MX27_BUILD_PIN(1, 12), Primary
Alternate GPIO
default NVDD 11 Slow/Hyst CSI_D2 I UART6_CTS O PB12 PUEN LCDC_TEST8 PB12 可见需要将1,12设置为primary功能,与功能描述一致,可见理解是正确的。 为了将1,12(及portB的12端口)设置为primary功能可以用一下方法: gpio_request_mux(MX27_PIN_CSI_D2, GPIO_MUX_PRIMARY); gpio_request_mux的实现: int gpio_request_mux(iomux_pin_name_t pin, gpio_mux_mode_t mode) 函数中首先调用mxc_request_gpio来完成对对用pin的申请,只有在申请成功(返回为零时)才调用gpio_config_mux来完成对pin的功能配置。 mxc_request_gpio源码: int mxc_request_gpio(iomux_pin_name_t pin) if (check_gpio(gpio) < 0) port = get_gpio_port(gpio); //得到gpio的端口号 return _request_gpio(port, index); 具体功能的实现在_request_gpio中: static inline int _request_gpio(struct gpio_port *port, u32 index) 其中port结构体中的reserved_map存放着对应pin的状态,表明pin是否已经被占用。这里需要注意的是reserved_map为
1时表示该pin为保留管脚,不能被使用。如果未保留则申请成功返回零,同时设置reserved_map的值为1.也即当打印出如下信息时: GPIO port %d (0-based), pin %d is already reserved! 表示该pin不可用。 通过学习,解决了7113在19内核的移植问题。
MX27_PIN_CSI_D1 = _MX27_BUILD_PIN(1, 11),
MX27_PIN_CSI_D2 = _MX27_BUILD_PIN(1, 12),
MX27_PIN_CSI_D3 = _MX27_BUILD_PIN(1, 13),
MX27_PIN_CSI_D4 = _MX27_BUILD_PIN(1, 14),
MX27_PIN_CSI_MCLK = _MX27_BUILD_PIN(1, 15),
MX27_PIN_CSI_PIXCLK = _MX27_BUILD_PIN(1, 16),
MX27_PIN_CSI_D5 = _MX27_BUILD_PIN(1, 17),
MX27_PIN_CSI_D6 = _MX27_BUILD_PIN(1, 18),
MX27_PIN_CSI_D7 = _MX27_BUILD_PIN(1, 19),
MX27_PIN_CSI_VSYNC = _MX27_BUILD_PIN(1, 20),
MX27_PIN_CSI_HSYNC = _MX27_BUILD_PIN(1, 21),
是为了将port 2的pin 12定义为CSI_D2,查看第5章的Pin MUX Table:
{
int ret;
ret = mxc_request_gpio(pin);
if (ret == 0) {
ret = gpio_config_mux(pin, mode);
if (ret) {
mxc_free_gpio(pin);
}
}
return ret;
}
{
struct gpio_port *port;
u32 index, gpio = IOMUX_TO_GPIO(pin);
return -EINVAL;
index = GPIO_TO_INDEX(gpio); //得到gpio口在对应端口的索引号
}
{
spin_lock(&port->lock);
if (port->reserved_map & (1 << index)) {
printk(KERN_ERR
"GPIO port %d (0-based), pin %d is already reserved!\n",
port->num, index);
dump_stack();
spin_unlock(&port->lock);
return -1;
}
port->reserved_map |= (1 << index);
spin_unlock(&port->lock);
return 0;
}
struct gpio_port {
u32 num; /*!< gpio port number */
u32 base; /*!< gpio port base VA */
u16 irq; /*!< irq number to the core */
u16 virtual_irq_start; /*!< virtual irq start number */
u32 reserved_map; /*!< keep track of which pins are in use */
u32 irq_is_level_map; /*!< if a pin's irq is level sensitive. default is edge */
spinlock_t lock; /*!< lock when operating on the port */
};