研究生
最后登录1970-1-1
在线时间 小时
注册时间2018-1-18
|
因为自己的板子需要用到nandflash,官方的板子是没有nandflash的,所以SDK里边,SEMC那里只有亲娘生的SDRAM才有历程,后娘养的nandflash是没有人疼爱的。
以前用STM32的芯片或者NXP自己的芯片,操作nandflash其实都是把nandflash当做外挂的比较讨人厌烦的SRAM来操作的,自己算好行列数据,一次次地发送给nandflash,第一次发C0,第二次发C1,第三次发ROW0,第四次发ROW1,第五次发ROW2,然后就开始不断地从8位数据口拿数据。
NXP的工程师,估计是看不惯别人这么欺骗nandflash,所以,在RT那里开辟了一个叫做IP命令以及AXI命令操作的方式来操作将上述的命令序列整合起来,让SEMC模块来和nandflash沟通,不需要代码一行行地去计算欺骗nandflash了。
抛砖引石头,和大家分享一下使用IP方式读取nandflash 的芯片ID。
在此感谢大神 @caiday 的帮助。
一步步来:1.初始化;2.使用IP指令;3.得到数据;
1.初始化
这部分初始化,就使用火哥SDK里边提供的nandflash的初始化,不过caiday讲,
/* Configure NAND FLASH. */
nandconfig.cePinMux = kSEMC_MUXCSX0;
nandconfig.axiAddress = 0x9e000000;
nandconfig.axiMemsize_kbytes = 128 * 1024*2; /* W29N01GV PageSize*PageCountEachBlck*Blocks=2048*64*1024=128M B */
nandconfig.ipgAddress = 0x9e000000;
nandconfig.ipgMemsize_kbytes = 128 * 1024*2; /* W29N01GV PageSize*PageCountEachBlck*Blocks=2048*64*1024=128M B */
这里要将大小翻倍,我仍旧想不明白,希望大家解答。
2.使用IP指令
手册上,49.4.5有讲,想要使用IP 命令,必须尊徐4个步骤;
uint32_t NAND_ReadID(void)
{
uint16_t ipCmd;
__IO uint32_t data;
status_t result = kStatus_Success;
uint8_t deviceid[5];
uint32_t id;
SEMC_ConfigureIPCommand(SEMC, 1);
ipCmd = SEMC_BuildNandIPCommand(NAND_READID, kSEMC_NANDAM_ColumnCA0, kSEMC_NANDCM_CommandAddress);
result = SEMC_SendIPCommand(SEMC, kSEMC_MemType_NAND, NAND_ADDRESS, ipCmd, 0, NULL);
result = SEMC_IPCommandNandRead(SEMC, NAND_ADDRESS, deviceid, 5);
id=*(unsigned long *)deviceid;
return id;
}
4行核心代码代表了4个步骤;
1.SEMC_ConfigureIPCommand(SEMC, 1); 配置指令操作的数据长度;
2.ipCmd = SEMC_BuildNandIPCommand(NAND_READID, kSEMC_NANDAM_ColumnCA0, kSEMC_NANDCM_CommandAddress); 这个其实只是组装一个命令而已,不涉及任何的操作。
3.result = SEMC_SendIPCommand(SEMC, kSEMC_MemType_NAND, NAND_ADDRESS, ipCmd, 0, NULL); 关键的地方来了,这一行代码,会将读取nandflash的ID的命令通过数据总线传送出去(除了数据还有别的吗?有啊,有读写信号。上图)
图小的话,我管不着,大家将就着看,实在看不清楚的,找别的资料再看看。
4.result = SEMC_IPCommandNandRead(SEMC, NAND_ADDRESS, deviceid, 5); 这行代码会读取5个字节的数据,传说中的5个字节的ID(真的就这么简单地到来了吗?没错,真的就这么简单地就到来了!上图,没图说个叼!)
大家没看错,能够发出数据变化,让总线有波动的其实就两个函数,这两个函数组装,就会对应了nandflash数据手册上的波形。
完了吗?好像完了,数据都读出来了,你还想怎么样?能不能再深入一点?那我们深入一点?
能深入的地方,我也只能再把SEMC_IPCommandNandRead这个函数展开了
status_t SEMC_IPCommandNandRead(SEMC_Type *base, uint32_t address, uint8_t *data, uint32_t size_bytes)
{
assert(data);
status_t result = kStatus_Success;
uint8_t dataSize = base->NANDCR0 & SEMC_NANDCR0_PS_MASK;
uint16_t ipCmd;
uint32_t tempData = 0;
/* Configure IP command data size. */
SEMC_ConfigureIPCommand(base, SEMC_IPCOMMANDDATASIZEBYTEMAX);
/* Read command built */
ipCmd = SEMC_BuildNandIPCommand(0, kSEMC_NANDAM_ColumnRow, kSEMC_NANDCM_Read);
while (size_bytes >= SEMC_IPCOMMANDDATASIZEBYTEMAX)
{
result = SEMC_SendIPCommand(base, kSEMC_MemType_NAND, address, ipCmd, 0, (uint32_t *)data);
if (result != kStatus_Success)
{
break;
}
data += SEMC_IPCOMMANDDATASIZEBYTEMAX;
size_bytes -= SEMC_IPCOMMANDDATASIZEBYTEMAX;
}
if ((result == kStatus_Success) && size_bytes)
{
SEMC_ConfigureIPCommand(base, size_bytes);
result = SEMC_SendIPCommand(base, kSEMC_MemType_NAND, address, ipCmd, 0, &tempData);
while (size_bytes)
{
*(data + size_bytes) = (tempData >> (SEMC_BYTE_NUMBIT * (size_bytes - 1))) & 0xFFU;
size_bytes--;
}
}
SEMC_ConfigureIPCommand(base, dataSize);
return result;
}
各位,前后对比一下,又回到了之前一开始的地方,
1.设置命令操作长度
2.组装命令
3.调用SEMC_SendIPCommand
4.完事。
再讲就啰嗦了。
有必要的话,调试读写操作的时候,再更新一波。
|
|