Writing Kernel Image to NAND Flash

Writing Kernel Image to NAND Flash

Often times it is useful to write the image of the kernel for your device into a permanent storage media such as NAND flash. This eliminates the need to download the kernel image each time the system is booted. Below you will find steps on how to write a previously compiled kernel image into NAND flash on the following DaVinci EVMs(DVEVM).

  • DM355
  • DM644x
  • DM6467

Note: This article assumes that you already have U-Boot running on the target. If not, e.g. your board is completely empty, see the RBL, UBL and host program article for instructions on how to get U-Boot bootloader on your board first. After you did this and have U-Boot running on your board, you can go on with steps below.

Alternatively, you can program your NAND flash with JTAG. This is useful for post mortem / rejuvenation of bricked NAND images, especially if you can't change the boot device select pins easily.

Prerequisites

For this example you will need the following:

  1. A previously compiled kernel image (uImage)
  2. A tftp server for downloading the image
  3. A terminal application for communicating with the DVEVM. i.e. minicom or hyperterminal

Downloading the Kernel Image to the DVEVM

This section assumes that you have a kernel image (uImage) already compiled. For information on compiling the Linux kernel for the DVEVM please see the Getting Started Guide (GSG) for your product (section 4.5) or compiling DaVinci open source git kernel.

  • Copy the kernel image to the /tftpboot directory
   host$ cp <path to kernel image>/uImage /tftpboot

NOTE: If your tftp directory is not the default tftpboot please replace tftpboot above with the proper directory.

  • Download the Linux kernel image via TFTP
   DVEVM# setenv serverip <tftp server ip address>
   DVEVM# setenv bootfile uImage
   DVEVM# dhcp

You should see output like the following:

   BOOTP broadcast 1
   DHCP client bound to address <dvevm ip address>
   TFTP from server <tftp server ip address>; our IP address is <dvevm ip address>
   Filename 'uImage'
   Load address: 0x80700000
   Loading:
   ######################################################################################
   ######################################################################################
   .
   .
   .
   ######################################################################################
   #######################################################
   done
   Bytes transferred = 1397368 (155278 hex)

The dhcp command obtains IP settings and then downloads the Linux kernel image (as specified by the serverip and bootfile environment variables). Make a note of the Load address (0x80700000) and Bytes transferred (0x155278), as these are needed in the following steps.

Preparing to Write the Kernel Image

Since the NAND flash requires that I/O operations be done in increments of page size you must round up the size of your kernel to the next full page in order for the reads and writes to succeed.

The below example is based on the DM644x. For other EVMs it will be necessary to adjust the page sizes and write locations.

  • Determine the page size of your NAND flash. You can find this in the manufacturer datasheet for your NAND device. The table below also has the block and page sizes for the NAND devices on the DaVinci EVMs.
DaVinci EVM NAND Chips
DEVICE PART NUMBER PAGE SIZE BLOCK SIZE
DM644x K9F1208R0B 0x200 0x4000
DM355 MT29F16G08FAA 0x800 0x20000
DM355 MT29F4G08AAA 0x800 0x20000
DM6467 NAND01GW3B2AZA6 0x800 0x20000

 

  • Calculate the number of pages to be erased and written by rounding the kernel image size up to next page. For example:
    Kernel size = 0x155278
    Number of pages = 0x155278/0x200 = AA9.3C rounded up = 0xAAA
    Rounded size = <number of pages> * <page size> = 0xAAA * 0x200 = 0x155400
NOTE: Sometimes the NAND device may not like the Roundded size = <number of pages > * <page size>. Instead do the calculation in the following way.
: Kernel size = 0x155278
: Number of BLOCKS (or SECTORS) = 0x155278/0x4000 = 55.49E  ~= 56 BLOCKS (SECTORS)
: Rounded size = <number of blocks> * <size of a block> =  0x56 * 0x4000 = 0x158000
NOTE:  If you have the space available in the NAND flash you can always round up to the next block (sometimes called sector) which is always a
multiple of the page size.  To determine the block size you can use the nand info command in u-boot.

   DVEVM# nand info

You should see output like the following:

   Device 0: Samsung K9K1208Q0C at 0x2000000 (64 MB, 16 kB sector)

The sector size is listed at the end of the output from the nand info command. 

In this example the sector size is 16 kB which is 0x4000. So the following calculation can be done:

Kernel size = 0x155278
Number of sectors = 0x155278/0x4000 = 0x55.49E rounded up = 0x56
Rounded size = <number of sectors> * <sector size> = 0x56 * 0x4000 = 0x158000
  • Erase the flash where the kernel is to be written using the rounded size calculated in the previous step. For each device the kernel is written to different locations in flash. Use the table below to determine where the kernel image will be placed.

 

KERNEL OFFSET
DEVICE OFFSET
DM644x 0x2060000
DM355 0x400000
DM6467 0xa0000

 

   DVEVM# nand erase 0x2060000 0x155400

You should see output like the following:

   NAND erase: device 0 offset 393216, size 1397760 ... OK

Here the amount to erase is the size of the kernel rounded up to the next sector which was calculated above. The offset 0x2060000 was chosen to allow the first sectors to be used for the ubl and u-boot boot loaders. You MUST erase the NAND flash before writing to it.

Writing the Kernel Image into NAND Flash

Now that the NAND flash where the kernel image will be stored has been erased it is time to write the kernel image into the flash memory.

   DVEVM# nand write 0x80700000 0x2060000 0x155400

You should see output like the following:

   NAND write: device 0 offset 393216, size 1397760 ... 1397760
   bytes written: OK

The nand write command will take the image stored at 0x80700000 (this is where the kernel was downloaded above) and write 0x155400 bytes to the NAND flash at address 0x2060000.

Updating a kernel from a linux prompt

If you want to be able to update your kernel or uboot image in NAND (I'm using a DM355 platform, but this should work for others) *while* your system is running and without the use of a JTAG device, these are the commands that can be used to do this:

   /usr/sbin/flash_eraseall -j /dev/mtd2
   /usr/sbin/nandwrite -p /dev/mtd2 uImage

An example:

   root@(none):~# /usr/sbin/flash_eraseall -j /dev/mtd2
   Erasing 128 Kibyte @ 3e0000 -- 96 % complete. Cleanmarker written at 3e0000.
   root@(none):~# nandwrite -p /dev/mtd2 uImage
   Writing data to block 0
   Writing data to block 20000
   Writing data to block 40000
   Writing data to block 60000
   Writing data to block 80000
   Writing data to block a0000
   Writing data to block c0000
   Writing data to block e0000
   Writing data to block 100000
   Writing data to block 120000
   Writing data to block 140000
   Writing data to block 160000
   Writing data to block 180000

This example updates the kernel. It is assumed that /dev/mtd2 is your NAND kernel partition. Uboot would be /dev/mtd0. To find the existing NAND partitions:

   root@(none):~# cat /proc/mtd
   dev:    size   erasesize  name
   mtd0: 003c0000 00020000 "bootloader"
   mtd1: 00040000 00020000 "params"
   mtd2: 00400000 00020000 "kernel"
   mtd3: 20000000 00020000 "filesystem1"
   mtd4: 1f800000 00020000 "filesystem2"

Also if you see any bad blocks during the erase operation you'll need to make sure they don't occur in the middle of your kernel code. It seems that the bootloader doesn't understand bad blocks and will NOT skip them. So you need to have a contiguous set of good blocks for your kernel or you will see a CRC failure message when booting.

Setting u-boot to Boot the Kernel from NAND Flash

You must now tell u-boot to boot the kernel image stored in NAND flash. This means that u-boot will copy the kernel image from NAND flash into DDR memory and then boot the kernel.

  • Setting the bootcmd environment variable
   DVEVM# setenv bootcmd 'nboot 80700000 0 2060000; bootm'

The nboot command will copy the kernel image at 0x2060000 on device 0 to address 0x80700000 in DDR. The bootm command will then boot the image located in memory at address 0x80700000.

  • The system is now ready to boot the kernel from NAND Flash so save the environment variables and boot.
   DVEVM# saveenv
   DVEVM# boot
  • Note: If you have issues with the Kernel panicking because it cannot find the ROMDISK, try noinitrd:
   DVEVM# setenv bootargs 'mem=120M console=ttyS0,115200n8 root=/dev/hda1 rw init=/bin/sh noinitrd'
### NAND Flash Plane 数量架构及相关配置 NAND Flash 的存储结构通常被划分为多个平面(Plane),这种设计旨在提升设备的整体性能。具体而言,NAND Flash 厂商会将内存阵列(Memory Array)分割成两个独立的平面[^1]。每个平面对应不同的 Block 地址范围,并支持并行操作。这意味着可以在同一时间针对这两个平面中的不同 Block 执行读取、写入或擦除操作。 #### 平面划分的意义 通过将内存阵列拆分至多两个平面,NAND Flash 能够显著提高数据吞吐率。尽管单个平面内的操作仍然遵循串行原则——即无法在同一时刻对同一个平面的不同区域同时进行读取和写入操作[^2],但跨平面的操作则能够实现真正的并发处理。例如: - **读取操作**:可以从一个平面读取数据的同时,在另一个平面执行写入或擦除。 - **写入操作**:在一个平面完成编程动作期间,另一平面可以准备下一组待写入的数据。 - **擦除操作**:当某个平面正在进行区块级别的擦除时,其他平面仍可用于正常访问。 此特性使得基于双平面设计的 NAND Flash 更适合高带宽需求的应用场景,比如固态硬盘 (SSD) 或者嵌入式多媒体卡 (eMMC)。 以下是关于如何利用 Python 来模拟简单的双平面调度逻辑的一个例子: ```python class NANDFlash: def __init__(self, num_planes=2): self.planes = [{'status': 'idle'} for _ in range(num_planes)] def operate(self, plane_id, operation_type='read'): if self.planes[plane_id]['status'] == 'idle': print(f"Performing {operation_type} on Plane-{plane_id}") self.planes[plane_id]['status'] = operation_type else: print(f"Plane-{plane_id} is busy with another task.") nand_flash_device = NANDFlash() nand_flash_device.operate(plane_id=0, operation_type="write") # Writing to Plane-0 nand_flash_device.operate(plane_id=1, operation_type="read") # Reading from Plane-1 simultaneously ``` 上述代码片段展示了创建具有指定数量平面的虚拟 NAND Flash 设备类 `NANDFlash` ,并通过实例化该类来演示基本的异步 I/O 操作管理方法。 值得注意的是,虽然当前主流产品普遍采用两平面的设计方案,但在某些高端应用场合也可能存在更多平面数的产品变体。然而,增加额外平面必然会带来成本上升以及控制复杂度增高的挑战,因此实际部署需权衡利弊做出最佳决策[^3]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值