关于nand flash的MTD分区与uboot中分区的理解
linux内核(2.6.18)分区的定义在arch/arm/davinci/board-dm365-ipnc.c的nand_partition这个变量中。
static struct mtd_partition nand_partitions[] = {
/* bootloader (UBL, U-Boot, BBT) in sectors: */
{
.name = "bootloader",
.offset = 0,
.size = 24 * NAND_BLOCK_SIZE, //3M by lml
.mask_flags = MTD_WRITEABLE, /* force read-only */
},
/* bootloader params in the next sector */
{
.name = "params",
.offset = MTDPART_OFS_APPEND,
.size = 16 * NAND_BLOCK_SIZE,//2M by lml
.mask_flags = MTD_WRITEABLE, /* force read-only */
},
/* kernel in sectors: */
{
.name = "kernel",
.offset = MTDPART_OFS_APPEND,
.size = SZ_2M, //2M by lml
.mask_flags = 0
},
{
.name = "filesystem",
.offset = MTDPART_OFS_APPEND,
.size = SZ_16M + SZ_8M, //24M
.mask_flags = 0
},
{
.name = "data1",
.offset = MTDPART_OFS_APPEND,
.size = SZ_2M,
.mask_flags = 0
},
{
.name = "data2",
.offset = MTDPART_OFS_APPEND,
.size = MTDPART_SIZ_FULL,
.mask_flags = 0
}
};其中
MTDPART_OFS_APPEND表示追加,即该分区地址追加到前一个分区中去;
MTDPART_SIZ_FULL表示占用剩余的全部空间
内核参数为bootargs 'mem=48M noinitrd console=ttyS0,115200n8 root=/dev/mtdblock3rootfstype=cramfs '中的mtdblock3表示MTD的第四个分区,起始地址为0x70 0000,第一个编号为0.由此可以确定,文件系统必须烧写到nand flash的偏移地址0x70 0000上,否则内核会找不到文件系统。比如我把文件系统烧写到flash的0x80 0000上,启动后会提示:No filesystem could mount root, tried: cramfs。Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(31,3) 错误。
烧写到0x70 0000后,可以挂在文件系统,但是提示:
Warning: unable to open an initial console.
Kernel panic - not syncing: No init found. Try passing init= option to kernel。
linux内核地址:
arch/arm/Makefile
内核运行虚拟地址 TEXTADDR = 0xC0008000
(虚拟地址,内核地址空间 0xc0000000)
0x8000:用于存放页表文件.
----------------------------------------------
arch/arm/boot/Makefile
内核加载地址 ZRELADDR = 0x20008000
---------------------------------------------
arch/arm/boot/compressed/Makefile
自解压程序地址 ZTEXTADDR = 0x00000000
启动参数存储地址(跟uboot中定义的对应)
在内核源码arch/arm/match-davinci/board-dm365-ipnc.c的最后有定义:
MACHINE_START(DAVINCI_DM365_EVM, "DaVinci DM368 IPNC")
/* Maintainer: MontaVista Software */
.phys_io = IO_PHYS,
.io_pg_offst = (io_p2v(IO_PHYS) >> 18) & 0xfffc,
.boot_params = (DAVINCI_DDR_BASE + 0x100), //0x8000 0100 .map_io = davinci_map_io,
.init_irq = davinci_dm368_ipnc_irq_init,
.timer = &davinci_timer,
.init_machine = davinci_init,
MACHINE_END
在uboot中的定义:
/* adress of boot parameters */
gd->bd->bi_boot_params = LINUX_BOOT_PARAM_ADDR; //0x8000 0100
这两个地址必须一致,否则就不能实现内核参数的传递。内核参数即uboot的环境变量中bootargs部分,在bootm.c的do_bootm_linux函数中,通过语句
char *commandline = getenv ("bootargs");获得内核参数,然后通过一系列setup_XXX_tags()函数建立内核参数链表,通过阅读源码可知,链表的起始地址就是gd->bd->bi_boot_params 。然后通过theKernel (0, machid, bd->bi_boot_params);命令就实现了uboot内核参数向linux内核的传递。
boot命令对应cmd_bootm.c中的do_bootd()函数,作用就是运行命令行参数bootcmd中的的命令,我们的板子,就是bootcmd 'nboot 0x80700000 0 0x400000;bootm 0x80700000',即nboot(对应cmd_nand.c中的do_nandboot()函数)先从nand flash 的偏移地址0x40 0000处把内核拷贝到ram的0x8070 0000地址处,然后bootm(对应cmd_bootm.c的do_bootm()函数,内核参数传递就在这里)从ram的0x8070 0000地址处开始运行内核。
系统启动挂载根文件系统时Kernel panic
uboot 引导内核时出现下面的问题:
Warning: unable to open an initial console
Kernel panic - not syncing: No init found. Try passing init= option to kernel.
也有网友说是由于内核参数传递的问题和nandflash分区的问题。具体解决方法还没有找到。