前段时间写了一篇,yaffs2移植之编译,后续在nand flash和yaffs2的适配过程中又遇到如下问题:
这里在多啰嗦几句,如果想要在嵌入式方面有一定的造诣,除了C的基本功,理解linux内核架构,再就是SOC厂商的基于内核架构编写的用户指导手册、源码以及APP开发人员的源代码了。而某些国内的二次开发厂商所能做的东西或是做出的东西,我不想多说些什么。
言归正传,描述问题出处:
1. 当我poritng的yaffs2文件系统交叉编译ok后,在linux os 运行时遇到如下问题:
当我将nand flash的某一个分区,挂载为yaffs2的文件系统后
mount -t yaffs2 /dev/mtdblock7 /media/mnt
写对应的nand flash分区,就会报Cannot allocate memory 的error,这个问题我通过google以及i.MX6 SOC厂商给出的nand BCH相关的章节部分了解到,问题是出在:
nand 的OOB区,越界。以下TI论坛具有很好的参考价值:
https://e2e.ti.com/support/arm/sitara_arm/f/791/t/248756?Mount-mtdblock-as-yaffs2-not-working
http://processors.wiki.ti.com/index.php/AM335x_U-Boot_User%27s_Guide#BCH_Flash_OOB_Layout
2. 为了临时解决在写nand flash不能分配内存的问题,我们在挂载时加上参数inband-tags
mount -t yaffs2 -o "inband-tags" /dev/mtdblock7 /media/mnt inband-tags 参数的意义在于 将yaffs2 的tags 不放在OOB,将其放在flash的data区,但是这样还带来一个问题,会使nand flash的写变慢。当然作为一个临时解决方案,也可以忍受。我将yaffs2官网对inband-tags参数意义解释直接黏贴如下:
With inband tags we store the tags in the flash data area alongside the data.
There are three major penalties with inband tags:
Due to the loss of chunk alignment, all transactions must pass through the shortOpCache. This costs an extra memcpy().
Offset to chunk, free space and other calculations are no longer just shift and mask operations but instead require multiplications and divisions which can relatively expensive.
Reading tags during scanning etc can involve reading the whole page, making this slower. The impact is minimised by using checkpointing.
3. 结合IMX6ul的RM与以上TI论坛给出的解释我将我遇到问题的原因,倒推如下:(后续我转去做AI,所以这块可能不能在继续跟了)
fs/yaffs2/yaffs_tagsmarshall.c中 temp = sizeof(struct yaffs_packed_tags2) 是28bytes 这样按论坛所讲倒推 MX6 的BCH应该是BCH16()
(我在手册这一章40-BIT Correcting ECC Accelerator (BCH) 还没确定我们的设置是BCH16还是BCH8)
如果是BCH16 :(我用1G nand flash 4k pagesize)
26x(4096/512)+28 =236 > 224
所以我们用 参数-o "inband-tags" 即将yaffs tags 放到data区规避了问题
但是该参数会导致nand flash写变慢
所以我想如果修改为BCH8,就不需要在挂载是加inband-tags参数了,这里是我后续需要花时间研究的地方。
14x(4096/512)+28 =140 < 224
4. 修改fs/yaffs2/yaffs_vfs.c中一个bug
修改后:
修改前:
5. 在用户空间测试完加inband-tags 参数后,nand flash 的写就没有问题了,接下来要在u-boot中通过bootargs告诉kernel在挂载yaffs2的时候也要加上inband-tags参数:
setenv nandargs 'setenv bootargs console=ttymxc0,115200 cma=64M root=/dev/mtdblock7 rw rootfstype=yaffs2 rootflags=inband-tags'
这样OS就可以从nand flash启动了。(devtmpfs: error mounting -2 这个error就解决了)