言归正传,OMAP3530的GPIO(General-purpose Interface)按照分组的原则,共有6组,每组的控制类寄存器是32bit的,代表了32个GPIO,所以总共有192个GPIO,这些是属于MPU控制的,超过192编号的GPIO是属于IVA2.2(DSP)控制的。结构框图如下:
OMAP3530的GPIO具有以下功能:
1)数据输入(捕获)/输出(驱动)
2) 带有防抖功能的键盘接口
3)外部事件检测(电平中断、边沿中断)
4) 在空闲模式下通过外部事件的睡眠唤醒功能
相关的配置需要仔细参照技术手册
接下来是WINCE下的GPIO驱动,跳过流驱动的标准框架以及MDD层框架和PDD层的与硬件相关的寄存器设置。这些和三星ARM的GPIO驱动大同小异。
着重介绍可能遇到的问题,忽略的地方:
我在编写完OMAP3530的GPIO驱动后,发现有的GPIO能够控制输入输出,有的则不能。经过同学提醒,重新看了技术手册,原来在技术手册的第7章System Control Module(SCM)中明确介绍了core modul(内核模块)和wake-up module(唤醒模块)。
SCM主要负责以下功能
1)I/O端口功能复用、多工选择
2) Pad块配置(端口上拉/下拉)
3) 设备状态
4) MPU和DSP(IVA2.2)的外围扩展设备特性
5) 静态设备配置
6)调试和观测功能IO复用
7) 存储pad块的配置
pad块配置寄存器如下:
其中pad块的配置中有一项就是端口的MODE(3bits),由于一个GPIO可能有多个功能,他们是互斥的,只能选择一个,就涉及到端口功能的选择,总共有MODE0到MODE7八个模式,默认是MODE0,MODE7是安全模式。比如GPIO143总共有实实在在的5个模式:mcbsp3_fsx/uart2_rx/gpio143/hsusb3_till_data7/safemode。所以在配置GPIO的时候需要选择成GPIO模式,不然操作GPIO就没有效果,这是问题1.
另外,上面的配置只能解决端口的输出控制,当端口配置成输入时,就不一定能读取端口电平。问题出在哪里呢,继续仔细参照技术手册的SCM模块。pad块中还有两项是GPIO的上拉/下拉选项、输入使能选项。针对当GPIO端口配置为输入时不能读取正确的引脚电平的问题,主要原因是由于GPIO端口的输入使能被关闭了。
输入使能(INPUTENABLE)(1bits)的描述如下:
1)INPUTENABLE = 0,关闭引脚输入,引脚只能够作为输出。
2) INPUTENABLE = 1,使能引脚输入,引脚具有双向端口功能,即输入/输出。
所以我们应该使能SCM中,pad块的这项功能。
具体到相关的WINCE文件有
GPIO驱动:
1) $\WINCE600\PLATFORM\TI_EVM_3530\SRC\DRIVERS\GPIO\gpio.cpp
2)$\WINCE600\PLATFORM\COMMON\SRC\SOC\OMAP35XX_TPS659XX_TI_V1\omap35xx\GPIO\omap35xx_gpio.cpp
启动时安装配置成GPIO的文件:
1)$\WINCE600\PLATFORM\TI_EVM_3530\SRC\BOOT\XLDR\platform.c
比如:
VOID GpioSetup()函数下的GPIO模式和端口方向定制:
OUTREG16(&pConfig->CONTROL_PADCONF_SDRC_D0, (INPUT_ENABLE | PULL_INACTIVE | MUX_MODE_0));
OUTREG16(&pConfig->CONTROL_PADCONF_SDRC_D1, (INPUT_ENABLE | PULL_INACTIVE | MUX_MODE_0));
OUTREG16(&pConfig->CONTROL_PADCONF_SDRC_D2, (INPUT_ENABLE | PULL_INACTIVE | MUX_MODE_0));
OUTREG16(&pConfig->CONTROL_PADCONF_SDRC_D3, (INPUT_ENABLE | PULL_INACTIVE | MUX_MODE_0));
OUTREG16(&pConfig->CONTROL_PADCONF_SDRC_D4, (INPUT_ENABLE | PULL_INACTIVE | MUX_MODE_0));
OUTREG16(&pConfig->CONTROL_PADCONF_SDRC_D5, (INPUT_ENABLE | PULL_INACTIVE | MUX_MODE_0));
OUTREG16(&pConfig->CONTROL_PADCONF_SDRC_D6, (INPUT_ENABLE | PULL_INACTIVE | MUX_MODE_0));
OUTREG16(&pConfig->CONTROL_PADCONF_SDRC_D7, (INPUT_ENABLE | PULL_INACTIVE | MUX_MODE_0));
OUTREG16(&pConfig->CONTROL_PADCONF_SDRC_D8, (INPUT_ENABLE | PULL_INACTIVE | MUX_MODE_0));
综上所述:SCM模块决定了端口的功能,而GPIO模块控制了端口的GPIO功能;GPIO只是端口功能的一个子集。