mtdparts: mtdparts=nand0:0x200000@0x0(u-boot),0x1400000@0x200000(kernel),-(rootfs)
Erasing at 0x7fe0000 -- 100% complete.
以老莫这种又笨又懒的人,肯定是不会用新唐官方的nuwriter, 不断的拔拨码开关,不断重虚拟机COPY文件到WINDONS, 用nuwriter去刷NAND ,写NAND;
通过在源码中查找 “UBI init error” 字段和分析定位
终于在\drivers\mtd\ubi\Build.c 文件中函数 io_init()发现异常的位置
ubi->max_write_size = ubi->mtd->writebufsize;
if (ubi->max_write_size < ubi->min_io_size ||
ubi->max_write_size % ubi->min_io_size ||
!is_power_of_2(ubi->max_write_size)) {
ubi_err(ubi, "bad write buffer size %d for %d min. I/O unit",
ubi->max_write_size, ubi->min_io_size);
return -EINVAL;
}
控制台打印出:
ubi0: bad write buffer size 0 for 2048 min. I/O unit
ubi->max_write_size 即>max_write_size == 0; 在座的吃瓜群众们在上幼儿园时已经知道凡是MAX的玩意等于0都是有幺蛾子的 ^_^
(老莫小时候在你们上幼儿园时还在家里玩鸡屎呢)
找到代码退出的地方,问题是不是就解决呢? 肯定不是呢,现在只是知道挂载异常的原因是 max_write_size变量为0,还要找出哪里导致改变量变为0。
吃瓜群众们脑海里不要有妹子答应和你们去吃饭看电影,你们惦记着哪里的酒店环境比较好的想法!
上面的代码有一句 ubi->max_write_size = ubi->mtd->writebufsize;
也就是要找 ubi->mtd->writebufsize为啥为0, 然后源码查找 ubi->mtd->writebufsize 变量;
控制台敲出 “ubi part rootfs ”命令后, UBOOT 即执行U_BOOT_CMD ( )函数
U_BOOT_CMD(
ubi, 6, 1, do_ubi,
"ubi commands",
"detach"
" - detach ubi from a mtd partition\n"
"ubi part [part] [offset]\n"
" - Show or set current partition (with optional VID"
" header offset)\n"
"ubi info [l[ayout]]"
" - Display volume and ubi layout information\n"
"ubi check volumename"
" - check if volumename exists\n"
"ubi create[vol] volume [size] [type] [id]"
" - create volume name with size\n"
"ubi write[vol] address volume size"
" - Write volume from address with size\n"
"ubi write.part address volume size [fullsize]\n"
" - Write part of a volume from address\n"
"ubi read[vol] address volume [size]"
" - Read volume to address with size\n"
"ubi remove[vol] volume"
" - Remove volume\n"
"[Legends]\n"
" volume: character name\n"
" size: specified in bytes\n"
" type: s[tatic] or d[ynamic] (default=dynamic)"
);
函数的调用过程如下
//cmd\ubi.c
static int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
int ubi_part(char *part_name, const char *vid_header_offset) <--------- (从队列中获取MTD设备数据)
-->
ubi_dev_scan(struct mtd_info *info, char *ubidev,
const char *vid_header_offset)
-->
add_mtd_partitions(info, &mtd_part, 1);
-->
//drivers\mtd\ubi\Build.c
int ubi_init(void)
-->
int ubi_attach_mtd_dev()
-->
err = io_init(ubi, max_beb_per1024); (报告错误所在的函数)
do_ubi 函数是通过过控制台传入的命令“ubi part rootfs ”中的rootfs分区名字,去扫描已经注册的MTD设备,
是否和分区名字匹配,然后在提取MTD信息,包括上文中提及的 writebufsize 变量信息;
//cmd\ubi.c
int ubi_part(char *part_name, const char *vid_header_offset)
{
int err = 0;
char mtd_dev[16];
struct mtd_device *dev;
struct part_info *part;
u8 pnum;
ubi_detach();
/*
* Search the mtd device number where this partition
* is located
*/
if (find_dev_and_part(part_name, &dev, &pnum, &part)) {
printf("Partition %s not found!\n", part_name);
return 1;
}
sprintf(mtd_dev, "%s%d", MTD_DEV_TYPE(dev->id->type), dev->id->num);
ubi_dev.mtd_info = get_mtd_device_nm(mtd_dev); //获取MTD设备数据,
在ubi_part()函数中打印出writebufsize 变量 依旧为0;也就是在设备注册以前这个变量已经是错的了;
然后翻查spi_nand_init()函数,该函数的后面会调用nand_register()注册设备;
//dirvers\mtd\spi\spi_nand.c
int spi_nand_init(void)
{
struct spi_flash *flash;
struct mtd_info *mtd;
struct nand_chip *chip;
struct ipq40xx_spinand_info *info;
int ret;
info = (struct ipq40xx_spinand_info *)malloc(
sizeof(struct ipq40xx_spinand_info));
if (!info) {
printf ("Error in allocating mem\n");
return -ENOMEM;
}
memset(info, '0', sizeof(struct ipq40xx_spinand_info));
flash = spi_flash_probe(0, 0, 30000000, 3);
if (!flash) {
free(info);
spi_print("Id could not be mapped\n");
return -ENODEV;
}
//mtd = nand_info[0];
mtd = (struct mtd_info *)malloc(
sizeof(struct mtd_info));
if (!mtd) {
printf ("Error in allocating mem\n");
return -ENOMEM;
}
memset(info, '0', sizeof(struct ipq40xx_spinand_info));
chip = &nand_chip[0];
mtd->priv = chip;
mtd->writesize = flash->page_size;
mtd->erasesize = spi_nand_flash_tbl[0].erase_size;
mtd->oobsize = spi_nand_flash_tbl[0].oob_size;
mtd->size = flash->size;
mtd->type = MTD_NANDFLASH;
mtd->flags = MTD_CAP_NANDFLASH;
#ifndef __UBOOT__
mtd->_point = NULL;
mtd->_unpoint = NULL;
#endif
mtd->_read = spi_nand_read;
mtd->_write = spi_nand_write;
mtd->_erase = spi_nand_erase;
mtd->_read_oob = spi_nand_read_oob;
mtd->_write_oob = spi_nand_write_oob;
mtd->_block_isbad = spi_nand_block_isbad;
mtd->_block_markbad = spi_nand_block_markbad;
chip->page_shift = ffs(mtd->writesize) - 1;
chip->phys_erase_shift = ffs(mtd->erasesize) - 1;
chip->chipsize = flash->size;
chip->pagemask = (chip->chipsize >> chip->page_shift) - 1;
chip->badblockpos = 0;
chip->buffers = kmalloc(sizeof(*chip->buffers), GFP_KERNEL);
chip->oob_poi = chip->buffers->databuf + mtd->writesize;
/* One of the NAND layer functions that the command layer
* tries to access directly.
*/
chip->scan_bbt = spi_nand_scan_bbt_nop;
// an ugly hack. cannot register our own probe function to set params, so assign correct one here.
info->params = &spi_nand_flash_tbl[0];//params;
info->flash = flash;
info->mtd = mtd;
info->chip = chip;
chip->priv = info;
mtd->writebufsize = mtd->writesize; // 这行是我加进去的
//注册MTD 设备
if ((ret = nand_register(/*CONFIG_IPQ_SPI_NAND_INFO_IDX*/0, mtd)) < 0) {
free(info);
spi_print("Failed to register with MTD subsystem\n");
return ret;
}
ret = spinand_unlock_protect(mtd);
if (ret) {
free(info);
printf("Failed to unlock blocks\n");
return -1;
}
spinand_internal_ecc(mtd, 1);
return 0;
}
我对比过nand init (并行nand ) 和 spi_nand_init()
并行nand初始化函数中,在MTD设备注册前会调用 nand_scan_tail()去设置MTD设备的参数
其中就包括了>writebufsize 参数,
函数中有该行代码:
mtd->writebufsize = mtd->writesize;
即设置>writebufsize 参数;
而SPI 函数是没有调用nand_scan_tail()函数的;
后来我在spi_nand_init()函数中加上mtd->writebufsize = mtd->writesize;
重新编译UOOT, 该问题就解决了
QQ交流群:761781147