會想寫這個東西的介紹是因為之前在酷學園看到有人提到如何在embedded system上做firmware upgrade, firmware upgrade每家公司的做法都不一樣,但目標都差不多,不外乎bootloader , linux kernel , file system upgrade,有強一點的公司還有做upgrade failure save的功能,而我這邊舉一個很簡單的例子,示範如何在embedded device上做linux kernel的upgrade,並且用jffs2 file system當我們的根檔案系統

JFFS2自2.6開始支援NAND Flash, NAND Flash與NOR Flash的設計理念差很多,為了cost down, NAND flash減少了在NOR Flash上不必要的位址線,改為page read/write方式存取,以QT2410的NAND Flash為例,一次的讀/寫,都是以512 byte為單位,所以Linux為了NAND Flash新增了NFTL(NAND Flash Transition Layer),NFTL最主要的目的,是讓EXT2,EXT3…等不是FLASH專屬的file system讀寫nand flash,而JFFS2或YAFFS都可以不透過NFTL進行FLASH read/write(2009.1.19修改),而細節部份小弟不多說了,google一找都一堆資料

我這邊的範例都是以QT2410為我的目標板,首先下載linux-2.6.26,修改Makefile,把ARCH改為arm,CROSS_COMPILE改為arm-linux-,修改完後,輸入指令make arch/arm/configs/s3c2410_defconfig,進入menuconfig並在MTD選單中選取NFTL support,接著再修改arch/arm/plat-s3c24xx/common-smdk.c這個檔案(修改於2008.9.23),找到smdk_default_nand_part並把這個structure內容修改如下(這邊的動作就是修改flash partition table,第一個partition是bootloader,第二個是linux kernel image,第三個是root file system)

static struct mtd_partition smdk_default_nand_part[] = { 
[0] = { 
.name = "Boot Agent",
.offset = 0,
.size = SZ_256K,
.mask_flags = MTD_CAP_ROM,
},
[1] = { 
.name = "S3C2410 flash partition 1(Kernel)",
.offset = SZ_2M,
.size = SZ_4M,
.mask_flags = MTD_CAP_ROM,
},
[2] = { 
.name = "S3C2410 flash partition 2(File system)",
.offset = SZ_8M,
.size =SZ_8M,
//.mask_flags = 0,
} 
}

修改完後就試著編譯kernel

接著開始製做jffs2 root file system,先cross compile busybox,再製作device符號表,這邊要特別注意device符號表中的mtd0,mtd1,mtd2和mtdblock0, mtdblock1, mtdblock2,上述的符號表一定要有,而且mtd0, mtd1, mtd2的minor number為0, 2 ,4(如果不這樣設定,無法進行flash erase),請參考下面圖片

下載mtd utility,並cross-compile,把flase_eraseall和nandwrite拷貝到root file system的/bin資料夾下,用mkfs.jffs2這個工具製做root file system,請參考下面範例

mkfs.jffs2 --pad=0x00800000 --eraseblock=0x4000 -l -n --root=fs/ -o root.jffs2

mkfs.jffs的參數說明如下

(1)-r : 指定要做成image的源資料夾.
(2)-o : 指定輸出image檔案的文件名.
(3)-e : 每一塊要抹除的block size,預設是64KB.要注意,不同的flash, 其block size會不一樣.
(4)–pad (-p): 用16進制來表示所要輸出檔案的大小,也就是root.jffs2的size。很重要的是, 為了不浪費flash空間, 這個值最好符合flash driver所規劃的區塊大小.

最後修正u-boot的環境變數和kernel command,請參考下面範例

wk=nand erase 200000 400000;tftp 30000000 uImage;nand write 30000000 200000 400000 
wf=nand erase 800000 3e00000;tftp 32000000 root.jffs2;nand write 32000000 800000 0x00800000;tftp 30008000 uImage;bootm 
bootcmd=nand read 30008000 200000 400000; bootm 30008000 
bootargs=mem=64M console=ttySAC0 root=/dev/mtdblock2 rootfstype=jffs2

以我的flash partition table為例,我把kernel擺在mtd1,所以我只要針對這塊區域進行firmware upgrade即可,這邊假設新的kernel image為/usr/uImage,用以下步驟進行firmware upgrade
1. flash_eraseall /dev/mtd1
2. nandwrite -p /dev/mtd1 /usr/uImage
執行畫面如下所示

整個過程大致上是這樣,因為我還沒把網路驅動起來,所以先擺個kernel image在usr資料夾下,等下次有空再介紹cs8900a的linux drvier撰寫方式,和搭配web server做remote firmware upgrade

最後修改日期: 3 6 月, 2022

作者

留言

撰寫回覆或留言

發佈留言必須填寫的電子郵件地址不會公開。