背景
很久之前,编写Uboot驱动的时候,在折腾sd/mmc的初始化的时候,遇到一个问题:
虽然代码,感觉都写对了,但是结果始终是:
nand flash始终不工作。
后来经过用逻辑分析仪去抓取信号,结果发现:
其中有两个pin脚,始终都是没有信号变化。
后来,终于搞清楚,原来是有两个pin脚复用,被后来的mmc复用,而重新初始化,而导致后续的nand flash中,对应的针脚,无效,使得nand flash不工作。
所以,此处,专门去整理一下,关于引脚复用方面的事情。
什么是引脚复用
引脚复用的叫法
引脚复用,也可以叫做:
引脚多路复用
pin脚复用
管脚复用
引脚重映射
等等。
没有引脚复用时是什么样的
正常的系统,尤其是嵌入式系统中,当芯片设计时,
有足够的空间,足够的引脚资源够使用的话
是不同的引脚之前,不会重合的,都是分离的
各自有各自的作用。
比如某某引脚,是对应的USB的那些pin;
某某引脚是对应的SD卡的那些pin;
等等。
为何要有引脚复用
当:
- 芯片上的引脚资源不够用;
- 芯片上,为了更高效率的利用引脚资源;
就可能会出现引脚复用:
物理上,同样的一组引脚,pin脚;
可以被设置(通过软件配置对应的寄存器去控制)为不同的功能
这样就可以实现
可以根据实际需要,在不同的情况下,使用同一组引脚,实现不同的功能,用于不同的功能。
举例说明什么是引脚复用
比如,我之前接触过的AMS的SoC:AS3536中的引脚复用图:
其中,对于:
XPI,XPJ,XPK,XPL
就有三种用途:
alternative 1,alternative 2,alternative 3
就可以根据需要,去配置,作为
IDE,Nand Flash,SD卡
的引脚。
当然,很明显,同一时刻,
XPI,XPJ,XPK,XPL
只能被配置为某种模式,即:
无法同时使用上述的XPI,XPJ,XPK,XPL去用于IDE,Nand Flash,SD卡。
同一时刻只能使用其中一种。
注:
关于GPIO,不了解的可以参考:
举例说明:如何配置对应复用的引脚
下面,通过实际的代码来解释,如何去配置对应的复用的引脚,
而实现某种对应的工作模式的。
此处,先说Uboot中的相关这部分的代码的逻辑:
Uboot中,先执行了Nand Flash的初始化,再去执行了开发板后续初始化中的mmc的初始化
当前的CPU是arm的,所以Uboot中初始化,是先去执行:
Board.c (lib_arm) 14903 2009/9/10 |
中的:
void start_armboot (void) { //... #if defined(CONFIG_CMD_NAND) puts ("NAND: "); nand_init(); /* go init the NAND */ #endif //... #ifdef BOARD_LATE_INIT board_late_init (); #endif //... }
可见,是先去执行:
nand_init
再去执行:
board_late_init
而此处是:
Uboot中的关于Nand Flash的初始化
drivers\mtd\nand\Nand.c
中的:
nand_init -> board_nand_init
此处是:
board\ams\as3536\As353x_nand.c
中的board_nand_init
Uboot中的关于mmc的初始化
关于mmc的部分是:
board\ams\as3536\As353x_nand.c
中的:
board_late_init –>
drivers\mmc\mmc.c
->
board\ams\as3536\As353x_nand.c
中的:
board_mmc_init –> board_mmc_hw_init
解释NAF(Nand Flash)部分的去配置复用的引脚的逻辑
解释配置复用引脚的逻辑之前,先要加上对应的,datasheet中,关于Nand Flash寄存器的含义解释:
其中,board_nand_init中关于Nand Flash部分的配置如下:
int board_nand_init(struct nand_chip *nand) { //... /* select xpi, xpj, xpk and xpl pins to be used in naf mode, do this after configuring NAF to have defined values */ ccuSetAlternativeModeBitForNaf(); WReg32( GPIOI_AFSEL, 0xFF ); /* use all 8 pins for data[0..7] */ WReg32( GPIOJ_AFSEL, 0xFF ); /* use all 8 pins for data[8..15] */ WReg32( GPIOK_AFSEL, 0xFF ); /* use all 8 pins for naf control lines (cle, ale, etc.) */ SetRegBits32( GPIOL_AFSEL, 0x21 ); /* use bit 0 and 5 for ce_3 and busy */ SetRegBits32( CCUP_REG_XPK, CCUP__DS ); /* increase driver output strength */ //... return 0; }
对于上述的Nand Flash部分:
此处,去配置为对应的,I,J,K,L的GPIO,即xpi,xpj,xpk,xpl,全都用到Nand Flash了
(当然,参照上面的pin脚复用图,可知:就没法同时去用SD卡,以及IDE了)
且注意到:
对应的还会去调用:
ccuSetAlternativeModeBitForNaf
表示这部分的gpio是用于Nand Flash了。
对应到寄存器,就是上面的NAF寄存器中的bit16==naf_mode的值,以此实现对应的:
select alternate function for xpi/xpj/xpk/xpl |
即将此4个GPIO都用于Nand Flash。
解释SD/MMC部分的去配置复用的引脚的逻辑
解释配置复用引脚的逻辑之前,先要加上对应的,datasheet中,关于SD寄存器的含义解释:
其中,board_mmc_hw_init中,关于mmc,即SD的引脚复用的部分的配置如下:
void board_mmc_hw_init(void) { #if AS3536_SUPPORT_SDMMC /* do necessary hw settings, such as GPIO setting, ccu reg setting ... */ /* if later will use NAF, then do not disable GPIO I J K L here */ /* turn off pulldowns on port I, K */ ClrRegBits32(CCUP_REG_XPI, CCUP__PE); ClrRegBits32(CCUP_REG_XPK, CCUP__PE); /* double Drive Strength */ SetRegBits32(CCUP_REG_XPI, CCUP__DS); SetRegBits32(CCUP_REG_XPK, CCUP__DS); /* if later will use NAF, not do set GPIO I(crd2), K (crd2h) to Storage Card Mode here */ SetRegBits32(CCUP_REG_CRD, CCUP_CRD_2_MODE); SetRegBits32(CCUP_REG_CRD, CCUP_CRD_2H_MODE); /* if later will use NAF, not do setting GPIO I J K L ,here */ ModRegBits32(GPIOK_AFSEL, 0x0F, 0x0F); ModRegBits32(GPIOI_AFSEL, 0xBF, 0xBF); #endif }
对于此处的mmc部分的代码,主要是:
/* if later will use NAF, not do setting GPIO I J K L ,here */ ModRegBits32(GPIOK_AFSEL, 0x0F, 0x0F); ModRegBits32(GPIOI_AFSEL, 0xBF, 0xBF);
可见:
其去配置了
GPIOI_AFSEL
GPIOK_AFSEL
即:
I和K的GPIO,
即xpi,xpk
对应着上述pin脚复用中的:
Card Interface 2
和
Card Interface 2 Extension
而对于:
/* if later will use NAF, not do set GPIO I(crd2), K (crd2h) to Storage Card Mode here */ SetRegBits32(CCUP_REG_CRD, CCUP_CRD_2_MODE); SetRegBits32(CCUP_REG_CRD, CCUP_CRD_2H_MODE);
中去配置对应的
CCUP_REG_CRD
去配置的值:
#define CCUP_CRD_2_MODE 0x10000 #define CCUP_CRD_2H_MODE 0x20000
对应着bit16和bit17,对应着是I和K这两个GPIO
所以,此处的配置,和上面刚刚解释的,去配置GPIO的对应的位,是一致。
即:
先去把对应的SD卡的寄存器的对应模式,设置为使用GPIO的I和K,即xpi和xpk
然后再去配置对应的GPIO的位、
真正的将其用于SD卡。
结论:
所以,此处就很明显可以发现,之前遇到问题的根本原因了:
先是在board_nand_init中,将GPIO的I,J,K,L,都配置为Nand Flash模式了。
结果又在后面执行到的board_mmc_hw_init中将GPIO中的I,K配置为SD卡模式了。
从而导致:
后续的Nand Flash无法正常工作
对应的GPIO的I和K所对应的引脚,都无信号变化。
关于引脚复用的每个引脚的含义是什么:是需要看对应的原理图才知道的
继续用上面的例子,比如对于前面的:
将XPI,XPJ,XPK,XPL用于IDE时的引脚功能和含义说明
XPI,XPJ,XPK,XPL,用于IDE时,上面显示共29个引脚。
但是具体每个引脚的作用,以及是如何计算出来一共29个引脚的,
则是需要去看对应的IDE部分的原理图schematic:
才看出来的。
由上图可见:
对应的Compat Flash,此处即为IDE时
对应的XPI到XPL,即对应的:
XPI_D0-XPI_D7:共8个引脚
XPJ_D0-XPJ_D7:共8个引脚
XPK_D0-XPK_D7:共8个引脚
和
XPL_D0-XPL_D4:共5个引脚
加起来,就是对应的29个引脚。
以及:
每个对应的引脚,其含义如何,对照着原理图,都可以看得很清楚。
将XPI,XPJ,XPK,XPL用于Nand Flash时的引脚功能和含义说明
类似的,将XPI,XPJ,XPK,XPL用于Nand Flash时
其引脚的含义和功能,也是需要去看对应的原理图:
才知道:
上图中,可以看清的一些引脚是:
U16中的:
(和下面的U17类似)
U17中的:
- XPL_D5:接的是R/B4_n,R/B3_n,R/B2_n,表示的是Ready/Busy的4,3,2的三个信号,negative低电平有效
- XPK_D6:接的是RE_n,表示Nand Flash中的Read Enable,negative低电平有效
- XPK_D2:接的是CLE,Command Latch Enable
- XPK_D1:接的是ALE,Address Latch Enable
- XPK_D7:接的是WE_n,Write Enable,negative低电平有效
- XPK_D0:接的是WP_n,Write Protect,negative低电平有效
- XPI_D0到XPI_D7:分别对应着Nand Flash的I/O0到I/O7
其他的一些暂时看不出对应的映射关系
包括XPL_D0
但是,也基本上,可以看懂,对应的原先的board_nand_init中代码:
/* select xpi, xpj, xpk and xpl pins to be used in naf mode, do this after configuring NAF to have defined values */ ccuSetAlternativeModeBitForNaf(); WReg32( GPIOI_AFSEL, 0xFF ); /* use all 8 pins for data[0..7] */ WReg32( GPIOJ_AFSEL, 0xFF ); /* use all 8 pins for data[8..15] */ WReg32( GPIOK_AFSEL, 0xFF ); /* use all 8 pins for naf control lines (cle, ale, etc.) */ SetRegBits32( GPIOL_AFSEL, 0x21 ); /* use bit 0 and 5 for ce_3 and busy */ SetRegBits32( CCUP_REG_XPK, CCUP__DS ); /* increase driver output strength */
中的那些注释了:
- /* use all 8 pins for data[0..7] */ :表示用GPIO的8个针脚,用于nand flash的data0到data7,即上面的I/O0到I/O7
- /* use all 8 pins for data[8..15] */ :同上。不过貌似是对应的,当Nand Flash设置位宽bit width为16的时候,才用到此bit的8-15
- /* use all 8 pins for naf control lines (cle, ale, etc.) */ :其中可以看懂的是,前面总结的XPK的用法:
- XPK_D0,XPK_D1,XPK_D2,XPK_D7
- 分别连到了
- WP_n,ALE,CLE,WE_n
- 上了。
- /* use bit 0 and 5 for ce_3 and busy */ :只看懂了:其说的bit5,即XPL_D5连到了(2,3,4三个公用的)R/B_n
至此,才算是:
基本上,真正的搞懂了
对应的各个GPIO的每个引脚的含义,
以及如何去配置成对应的Nand Flash模式。
注:
常见的Nand Flash的芯片的引脚名称和含义,虽然找个nand flash的datasheet参考一下即可。
比如:
http://www.hynix.com/datasheet/pdf/flash/HY27UF084G2M%20Series%28Rev.0.3%29.pdf
中的:
将XPI,XPL用于Nand Flash时的引脚功能和含义说明
对应的,找到SD/MMC的原理图:
从中可以看出,最右边的SD/MMC的原理图中,画的很清楚,对应的是:
- XPI_D7:接了WP
- XPL_D3:接的是CD
- XPI_D5:接的是CMD
- XPI_D4:接的是CLK
- XPI_D0:接的是DATA0
- XPI_D1:接的是DATA1
- XPI_D2:接的是DATA2
- XPI_D3:接的是DATA3
此时,很明显:
当使用SD/MMC时,就要用到对应的:
XPI和XPL
更详细点就是:
用到XPI的bit:0,1,2,3,4,5,7和XPL的bit3
所以,之前的代码,才会用:
/* if later will use NAF, not do setting GPIO I J K L ,here */ ModRegBits32(GPIOK_AFSEL, 0x0F, 0x0F); ModRegBits32(GPIOI_AFSEL, 0xBF, 0xBF);
去设置对应的:
XPI和XPL,用于SD卡。
也就看懂了:
- /* if later will use NAF, not do setting GPIO I J K L ,here */ :如果后续用到Nand Flash的话,此处就不要去设置对应的GPIO的,I,J,K,L了。
- 因为:此处如果设置GPIO的I和L,用于SD的话,后续Nand Flash也就很明显,无法工作了。
至此,才算真正的,越来越清楚,GPIO的复用的设置逻辑,和代码上如何写了。
引脚复用注意事项
1.在用到复用的引脚的时候,确保你在配置其用于某种功能的同时
别人(在你的代码之前和之后的位置)是否也有对此配置进行改动。
否则,就会出现我这里的:
在开始的代码中配置GPIO的I,J,K,L用于Nand Flash,结果之后被mmc初始化时配置了GPIO的I,K用于SD卡了。
导致后面的nand flash无法正常工作。
2.
其他资料
找了点,关于引脚复用方面的资料,供参考:
Texas Instruments 配置具有引脚多路复用的 Stellaris®微处理器
转载请注明:在路上 » 【整理】什么是引脚复用+引脚复用的作用+举例说明如何配置复用的引脚