2010年7月31日 星期六

dirve PL2303 in Linux

source: http://ubuntuforums.org/showthread.php?t=190124
Under 6.06 the USB device number corresponds to the USB device number -1. (i.e USB0 = 1st USB port) Therefore if you use dev/ttyUSB0 as a comms port, then you haev to be plugged into the first USB port on your machine.

e.g. I have 4 USB port (as per device manager listing). I plugged my USB serial cable into port 1 (the lowest and first port) and minicom worked. I then plugged it into the 4th port. Minicom failed.

I then added a tty device called USB3. I plugged in th serial cable into port 4 and bingo it work. It is quite reminiscent of the old way windows used to work with comm ports.

Anyway problem resolved for me. Hope this tip helps somebofy else.

I have read your post "upgd breezy -> dapper. now I cannot open ttyUSB0 via MINICOM"

and I have the same problem than you.

If I open "minicom" using ttyS0 then it works
If I open "minicom" using ttyUSB0 then I get "cannot open /dev/ttyUSB0: No such device" even if "ttyUSB0" appears in my /dev list.

Reading your post, you say that plugging your USB serial cable into one of the USB then you are able to make it works. I do not have yet any USB serial cable to connect into the USB and to test what you did, but I am wondering that if "minicom using ttyS0" works without any cable connected into the RS232 interfaz, why "minicom using ttyUSB0 does not work if there is not any cable connected".

I ask this, because I am doing an application where I need to connect two devices into the 2 serial ports, but my laptop has only one, so the second one has to be used through the USB (so I need to buy the cable to convert RS232 into USB).
Before having the cable I have tested this:
open("/dev/ttyS0",O_RDWR|O_NOCTTY|O_NDELAY|O_NONBLOCK); //works
open("/dev/ttyUSB0",O_RDWR|O_NOCTTY|O_NDELAY|O_NONBLOCK); //receiving "open error 2 no such file or directory"

So after that I tried minicom resulting the above of the post.

So my question is: "ttyUSB0" can be only opened when there is something connected on it?
(because with ttyS0 you can open even if there is nothing connected on it)

2010年7月29日 星期四

U-boot 啟動內容及基礎指令使用介紹

來源: welkin的小窩 U-boot 啟動內容及基礎指令使用介紹

1.1 u-boot 啟動內容解譯
U-Boot 1.1.4 (Sep 23 2008 - 10:58:00) //u-boot 本版資訊及編譯時間
U-Boot code: 30700000 -> 3071B11C BSS: -> 3071F5C4 //存放u-boot 資料和程式碼的位址

IRQ Stack: 306daf74
FIQ Stack: 306dbf74 //中斷Stack 位址,u-boot 可不需要使用中斷
RAM Configuration:
Bank #0: 30000000 32 MB //32MB 的SDRAM 位址起始位址為 30000000
Flash: 2 MB //2MB 的Norflash 位址,其實位址為20000000
NAND: 64 MB //64MB 的Nandflash
*** Warning - bad CRC, using default environment //由于是第一次燒寫,flash 中還沒有儲存環境變數,因此使用預設換機變數
In: serial
Out: serial
Err: serial //匯入匯出串列方式
Set the MAC successful! //成功配置網路
Hit any key to stop autoboot: 0 //延時幾秒後自動執行
# //主控台,用戶可匯入指令


1.2 print 指令——檢視u-boot環境變數

由於是第一次燒錄,此時的環境變數為預設值。


1.3 u-boot 環境參數解譯

#print

bootargs= //這個參數將會傳遞給 Linux 作業系統,現在空白,以後詳解
bootcmd=bootm 20000 f0000 //啟動指令,將在啟動延時之後執行位址的指令
bootdelay=5 //啟動延時,建議修改為1
baudrate=115200 //鮑率 115200
ethaddr=00:50:c2:1e:af:fb //網卡的 mac 位址
ipaddr=172.17.22.189 //開發板的 ip 位址
serverip=172.17.22.183 //伺服器(PC 機)的ip 位址
gatewayip=172.17.22.1 //閘道位址(直連可以不填)
netmask=255.255.255.0 //網路遮罩
bootfile="B2-rootfs/usr/B2-zImage.u-boot" //無用,可移除
stdin=serial
stdout=serial
stderr=serial
Environment size: 261/16380 bytes //環境變數容量


1.4 set 指令——設定環境變數

使用方法如下:
如果一個參數帶有多條指令,需要如下設定:
用 print 檢視察看效果:


1.5 save 指令——儲存環境變數

設定完環境變數後需要使用 save 指令來儲存環境變數,這樣開機後就不會環境變數錯誤的查看警告了。


1.6 修改適合 S3C4510 開發板的環境變數

為了方便交流和測試,開發時希望能夠統一 ip 位址,設定如下:

主機:192.168.0.1
開發板:192.168.0.2
虛擬機:192.168.0.3

#save
Saving Environment to Flash...
Un-Protected 1 sectors
Erasing Flash...
done
Erased 1 sectors
Writing to Flash... done
Protected 1 sectors



(兩條指令用"\;"隔開)

set [參數][內容]\;[參數][內容]
--------------------
例如:
#set bootcmd tftp vmlinux.img 30007fc0\; bootm 30007fc0

set [參數] [內容]
--------------------
例如:
#set bootdelay 1

其中 bootargs 和 bootcmd 參數需要額外說明:

(1) bootargs 參數
bootargs 參數是啟動時傳遞給 Linux 作業系統的資訊,其配置敘述為:

set bootargs root=/dev/mtdblock2 console=ttyS0,115200 rootfstype=cramfs mem=32mb

root:/dev/mtdblock2 表示從nand 的第三個割區啟動檔案系統,Linux 啟動后會自動搜索 nand 分割區資訊。
console:表示 Linux 作業系統使用的主控台,我們使用第一個序列埠,因此是ttyS0,後面跟的 115200 表示序列埠使用的鮑率。
rootfstype:表示檔案系統的格式,我們燒錄在 nand 中的檔案系統使用cramfs,所以在這裡要填寫cramfs,否則 linux 會嘗試自動掛載,可能會出錯。
mem:表示 Linux 作業系統的記憶體容量,目前開發板掛載32MB記憶體,因此填32MB。

(2) bootcmd 參數
bootcmd 參數表示開發板開機之後,bootdelay 結束後執行的指令。

上面範例的含義是用 tftp 這條指令,將主機上的vmlinux.img(即Linux 核心)掛載到記憶體的 30007fc0 這個位址,

然後從 30007fc0 啟動核心。(如果將 Linux 核心燒錄到 Nandflash 上,則指令又有不同)


1.7 ping 指令——測試網路指令

功能很簡單,比 pc 上的弱很多,如下:

#ping 192.168.0.1
host 192.168.0.1 is alive

U-boot 初探

來源: welkin的小窩 U-boot的一些指令

來源:大體上跟著 http://www.denx.de/wiki/publish/DULG/DULG-tqm8xxl.html 作一次就 OK 了!!

1. 在安裝 U-boot 之前要先安裝它的 ELDK 套件(全名為 Embedded Linux Development Kits),主要包含了 cross compiler 工具。
除了 cross compiler 之外,ELDK 還包含許多套件。


2. U-boot 的 compile
-----------------------------------------------------------------
2-1. 下載 u-boot-1.20,tar.bz2, 解壓縮
2-2. cd u-boot
2-3. make distclean
2-4. grep -Rl arm9 * (找出 arm9 的 board)
2-5. make netstar_config
2-6. make all
2-7. make ap946es_config
----------------------------------------------------------------
make netstar_config
是針對你要 compile 的目標。(這個 target 可以在 u-boot/Makefile 找到)
你可以把它當成 Linux kernel 的 configuration。

以 board/integratorap/ 裏的 ap946es_config 為例:

1. 決定 include/config.h 以下三個 macro:
#define CONFIG_INTEGRATOR
#define CONFIG_ARCH_INTEGRATOR 1
#define CONFIG_CM946E_S 1
2. 選擇並修改
board/integratorap/u-boot.lds
因為 integrator 支援好幾種 CPU,所以它會呼叫 boards/integratorap/split_by_variant.sh 來針對 arm946es 修改。
u-boot.lds, 就是要它去找 start.o 時,要去找 cpu/arm946es/start.o 等會我們會再探討,start.o 就是 U-boot 的 entry point。
3. 呼叫 u-boot/mkconfig 來設定一些等會 make all 時會用到的參數,
其中以 ARCH, CPU, BOARD, VENDOR, SOC 最重要!
因為它會影響到 cross compiler 的選用 (如果你不只一個 cross compiler),
compile 和 link flag 的設定,以及到哪個目錄去找你要的東西。

在 u-boot 下面,有不少和以上參數有關的目錄和檔案:
u-boot/
ppc_config.mk
i386_config.mk
....
include/
lib_arm/
lib_avr32/
....
cpu/
74xx_7xx/
arm1136/
....
....
這些參數指引 make 到哪些目去抓

make all
會真正 build 出 u-boot.bin,它的 object 最主要由下面幾個 component 組成:
start.o
start16.o resetvec.o
reset.o
routine get from libraries
最後會產生 u-boot.hex 和 u-boot.srec 及 u-boot.bin。

由上可以看出,中間左邊是 i386,右邊是 power pc,還有其它,那是和 CPU 有關的一些 routine。
最主要就是 start.o 和一些其它所用的函式。
其它所有東西都 build 成 library,在 configure 之後,在 link 時從 library 抓進就可以了。

----------------------------------------------------------------
開機流程,以 cpu/arm946es/start.S 為例:

U-boot 的 start_armboot 到 _bss_start,從 Flash 複製到 RAM,然後 setup 好 stack,
然後就到 start_armboot。(start_armboot 在 lib_arm/board.c 中)

因為 stack 已經設好了,所以這段是用 C 寫了。

進入 start_armboot(),一堆 #ifdef / #ifndef CFG_xxxx,表示要用哪些 ap,driver,都是一些 initialization 的 code,

然後最後就進入一個 main_loop() 中!!
----------------------------------------------------------------

1.jpg


開機流程簡圖


其中左上方是 assembly,而從 start_armboot 之後就是 C code。

值得注意的有以下幾點:
1.
因為這個 bootcode 是由 ARM 的 integrator 提供。

這個 bootcode 有一個假設:
它認為在板子或 CPU 架構中,有一塊 RAM 的位址是 hardware boot 時就可以動了。
因此它有一個 copy 到 RAM 的動作。

在 CPU 或 ASIC 內部先包一塊 RAM 在某些 architecture 有,但是有的 ASIC 並沒有。

對於沒有一開機就有可用的 RAM,勢必要修改這段 code。

此外如果在開機階段有做 memory remapping 的 board 而言,有兩種方法
(1) 一開始就 remapping,再 copy U-boot 到 RAM。
(2) copy 到一個不受 remapping 影響的位址。

U-boot 可以改寫成 XIP 嗎?

但是我目前所知,它是要在 RAM 中執行。


2.
在進入 C code 的 start_armboot()之後,它第一件事就是初始化一個稱為 gd 的 global 指標。
(它的實作是十分 architecture dependent 的)。

參考 include/asm-arm/global_data.h

它的宣告是:

register volatile gd_t *gd asm("r8")

是一個放在 register 的指標!!

它將這個指標指到 RAM 的指定位址,然後清為 0

之所以指定它為 register,是要讓它在這個最初階段,可以讓我們任意指定它指到 RAM 的位址初使化它。

這個 global variable 在 u-boot 中用來存放一些最開始初始化時所需要用的參數。(這些動作一定要在 RAM 完成)


3.
第一階段的初始化:藉由一個個執行 init_sequence[] 所指到的函式來完成。

目前有的函式為:
cpu_init
board_init
interrupt_init
env_init
init_baudrate
serial_init
console_init_f
display_banner
dram_init
display_dram_config

其中每個函式都回傳 0 表示正確執行,其中 env_init 是去哪裏取得環境變數,

可以是一個固定的陣列,flash,環境變數的資料,會放在 gd 所指的資料結構之中。

由以上看來,因為每個都是 function pointer,各分別屬於在 configuration 階段會指定的目錄中。

如 CPU, BOARD 所指定的目錄,
換言之,我們只要為這些 function pointer 實作出適合我們板子的內容,就可以把融入 U-boot 之中。


4.
在 init_sequence[] 之後, 我把它稱作是第二階段的 initialization。

看來有點亂,一堆 #ifdef,而且有的和前面似乎有重複或矛盾,想是不同 board 的差異太太的關係。

大體上就是 initialize 更多的 device 或是前面 intialization 的第二階段。

U-boot的一些指令

來源:welkin的小窩 U-boot的一些指令

U-boot的一些指令

Printenv 列印環境變數
--------------------
Uboot> printenv
baudrate=115200
ipaddr=192.168.1.1
ethaddr=12:34:56:78:9A:BC
serverip=192.168.1.5
Environment size: 80/8188 bytes

Setenv 設定新的變數
--------------------
Uboot> setenv myboard AT91RM9200DK
Uboot> printenv
baudrate=115200
ipaddr=192.168.1.1
ethaddr=12:34:56:78:9A:BC
serverip=192.168.1.5
myboard=AT91RM9200DK
Environment size: 102/8188 bytes

Saveenv 儲存變數
--------------------
命令將當前定義的所有的變數及其值存入flash中。用來存儲變數及其值的空間只有8k位元組,應不要超過。

Tftp 透過網路下載程式,需要先設定好網路配置
--------------------
Uboot> setenv ethaddr 12:34:56:78:9A:BC
Uboot> setenv ipaddr 192.168.1.1
Uboot> setenv serverip 192.168.1.254 (tftp伺服器的位址)

Uboot> tftp 20000000 application.bin (application.bin應位於tftp服務程式的目錄)
下載bin檔案到位址0x20000000處。

Uboot> tftp 32000000 vmlinux
把server(IP=環境變數中設定的serverip)中/tftpdroot/下的vmlinux透過TFTP讀入到物理內存32000000處。

Loadb 透過串口Kermit協議下載二進製數據。
--------------------

Bootm 執行Memory 中的二進製代碼
--------------------
要求二進製代碼為製定格式的。通常為mkimage處理過的二進製檔案。
起動UBOOT TOOLS製作的壓縮LINUX內核, bootm 3200000

Bootp 透過網路啟動,需要提前設定好硬體位址。
--------------------

run 執行設定好的腳本
--------------------
Uboot> setenv flashit tftp 20000000 mycode.bin\; erase 10020000 1002FFFF\;
cp.b 20000000 10020000 8000
Uboot> saveenv
Uboot> run flashit

bootcmd 保留的環境變數,也是一種腳本(如果定義了該變數,在autoboot模式下,將會執行該腳本的內容。)
--------------------

Protect 寫保護操作
--------------------
protect on 1:0-3(就是對第一塊FLASH的0-3扇區進行保護)
protect off 1:0-3取消寫保護

Erase 清除扇區
--------------------
erase: 刪除FLASH的扇區
erase 1:0-2(就是對每一塊FLASH的0-2扇區進行刪除)

對DataFlash的操作
--------------------
U-Boot在引導時如果發現NPCS0和NPCS3上連有DataFlash,就會分發虛擬的位址給它,具體為 ︰
0xC0000000---NPCS0
0xD0000000---NPCS3

Go 執行Memory中的二進製代碼,一個簡單的跳轉到指定位址
--------------------

? 得到所有命令清單
--------------------

help help usb, 列出USB功能的使用說明
--------------------

ping 注︰只能在開發板上去PING別的機器
--------------------

Cp 拷貝一塊Memory到另一塊
--------------------

Cmp 比較兩塊Memory區
--------------------
這些Memory 操作命令後都可加一個後綴表示操作數據的大小,比如cp.b表示按位元組拷貝。

Md 顯示Memory的內容。
--------------------

Mm 修改Memory,位址自動遞增。
--------------------

Nm 修改Memory,位址不自動遞增。
--------------------

Mw 用模型填充Memory
--------------------
mw 32000000 ff 10000(把Memory 0x32000000開始的0x10000位元組設為0xFF)

usb
--------------------
usb start: 起動usb 功能
usb info: 列出設備
usb scan: 掃描usb storage(usb碟)設備

kgo 起動沒有壓縮的linux內核
--------------------
kgo 32000000

fatls 列出DOS FAT檔案系統
--------------------
fatls usb 0列出第一塊U盤中的檔案

fatload 讀入FAT中的一個檔案
--------------------
fatload usb 0:0 32000000 aa.txt 把USB中的aa.txt 讀到物理Memory 0x32000000處﹗

flinfo 列出flash的訊息
--------------------

nfs
--------------------
nfs 32000000 192.168.0.2:aa.txt
把192.168.0.2(LINUX 的NFS檔案系統)中的NFS檔案系統中的aa.txt 讀入Memory 0x32000000處。

Embedded Linux 技術與概念解析

引言

Embedded Linux技術基於開放源碼的資源,並且已經是當今最重要的嵌入式應 用技術之一。Embedded Linux是燒錄在目標裝置上的系統,1個Embedded Linux系統包含Linux kernel與 root filesystem 2大部分,Embedded Linux系統到底包含哪些組成要素構成,本文將由概念的層面進行解析。

本文

由於目前的目標裝置,都必須嵌入極為複雜的功能,所以嵌入式操作系統(Embedded system)成為嵌入式系統不可或缺的要素。由於嵌入式系統是功能導向的系統,因此必須設計、選擇或購買正確(或適合)的目標裝置,才能開始實作並嵌入嵌入式系統。因此,嵌入式系統技術是以功能、與目標裝置為分類的1種技術。

例如,與PDA相關的目標裝置(即硬件)、與MP3播放器相關的目標裝置、與3G手機相關的目標裝置...等等;使用這些目標裝置所開發的特定功能系統,便是PDA的嵌入式系統、MP3音樂播放的嵌入式系統、3G手機的嵌入式系統。

Embedded Linux其實並不是1個操作系統,而是代表應用Linux系統於Embedded system的名詞。Embedded Linux的技術核心主軸是在研究如何將Linux系統嵌入至嵌入式目標裝置裡。

Embedded Linux是基於Linux系統的特殊應用,當然也要符合眾多標準才行。LSB與FHS標準是重要的2大標準,跟隨標準不但可以提供系統間的兼容性,也可以提供我們1個Linux系統的建構依據。

GNU/Linux的2個標準

由FSG (Free Standards Group) 所主持的 LSB (Linux Standard Base) 項目即是在制定 GNU/Linux 標準。根據LSB標準所發展的GNU/Linux系統,才能提供應用程序最小的可執行環境,並且可在依循LSB標準的Linux distributions上執行無誤。例如,我們可以在符合LSB標準的Red Hat Linux上發展應用程序,只要自行發展的Embedded Linux系統符合LSB標準所訂定的規範,應用程序就可以順利移植到Embedded Linux上執行。

LSB標準提供我們發展Embedded Linux的依據,雖然Embedded Linux系統是最小化的Linux,但因為Embedded Linux是嵌入式系統的軟件平台,所以我們不能任意精簡Linux系統,在精簡的過程中仍要保留最基本的操作系統環境,而LSB的標準正是在制定這些基本的需求。

FHS全名為Filesystem Hierarchy Standard,是定義檔案與目錄標準的文件,FHS的標準,定義了目錄與檔案的擺放位置,而UNIX-like的系統則是根據這個標準,管理整個檔案結構。因此,不管是系統廠商、Linux/UNIX distribution發展者、應用程序作者、套件管理者、系統維護人員都應該要依照FHS的標準來管理UNIX系統的目錄與檔案。

Embedded Linux的特色是大量使用自由軟件、與開放源碼軟件(FOSS- Free & Open Source Softwar)資源,任何你想要的軟件,幾乎都能在網絡上找到自由軟件已經成為Embedded Linux技術的重要支柱。自由軟件資源包山包海,舉凡應用程序、系統工具、網絡工具、鏈接庫、圖形接口、小型瀏覽器、程序發展工具...等等都能找得 到。

Busybox

Busybox是重要的Embedded Linux工具箱,這個工具箱提供基本的UNIX指令、系統程序(daemon)與開機程序(init process)。Busybox用來建造1個基本、最小化且可開機的Linux系統,由於Busybox裡的指令與工具都經過最小化處理,因此已經是目前主要應用在Embedded Linux實作上的開放源碼項目了。

Embedded Linux的組成

圖 Embedded Linux整體架構

Embedded Linux平台除了Linux kernel外,還包含共享鏈接庫(shared library)。shared libraries是Linux kernel的重要支持,並且也是Linux架構裡獨立的1層。在應用程序方面,許多現存的開放源碼項目都可以直接移植到ARM9平台。但這裡所指的移植 是對原始碼進行跨平台編譯(cross compile),並不是BSP(board support package)的移植。

跨平台編譯

因為開放源碼開發工具的特性,在應用程序級別的移植工具上,可以有1套比較系統化的方法,也有相關的工具與環境可以使用,目前最熱門的跨平台編譯環境為 OpenEmbedded。開放源碼軟件採用GNU Autoconf與GNU Automake來撰寫編譯法則(Makefile),因此實務上,要將應用程序移植到ARM9平台,大部分案例只需要做跨平台編譯即可。要瞭解如何將原 始碼移植到ARM9平台,需要學會GNU Autoconf以及GNU Automake的使用。

GNU Autoconf

Autoconf是m4宏的擴充套件,可以用來自動設定軟件套件的原始碼。Autoconf會產生1個協助程序編譯的設定文稿執行檔 (configuration script),以方便編譯原始碼前進行系統檢查與設定,使用GNU Autoconf時,必須安裝GNU m4套件。

GNU Automake

Automake是自動產生Makefile.in的工具,需配合Autoconf使用,以產生可以讓GNU Make自動編譯原始碼的」Makefile」檔案。

GNU Make

GNU Make會根據「Makefile」來自動編譯程序,而編譯完成的程序為執行文件。GNU Make的重要特點,是沒有特定程序語言限制,甚至可以應用在非程序語言編譯的環境中,例如:系統維護工作與套件安裝,因此GNU Make可以說是系統自動化的好工具。

GNU Make根據「Makefile」檔案裡所定義的規則,執行Unix命令,簡單的Makefile規格,可以利用編輯器手動撰寫,但較複雜且與針對不同平 台的設定,則建議採用GNU Autoconf/GNU Automake來產生「Makefile」。當我們能夠產生使用cross toolchain的Makefile時,就可以將套件編譯成ARM9的執行檔。

ARM 平台的選擇與支持

嵌入式裝置的硬件選擇當然沒有所謂的標準,但若是談論到嵌入式Linux的 應用,在平台的選擇上就會有一些考慮。最重要的考慮因素,當然就是處理器對於操作系統的支持,如此一來,沒有MMU(內存管理單元)的ARM7平台,就不 在主要的選擇範圍內。以下列出幾個目前普遍使用的ARM9應用程序處理器(application processor):

在選擇解決方案時,若是決定採用Linux做為嵌入式操作系統,首先當然就是要確定廠商是否提供完整的BSP。不過,由於Linux是由社群所維護髮展,因此,選擇目前Linux kernel內有支持的平台,將會是較好的選擇,這也是為什麼有許多大廠,主動貢獻並提交BSP給kernel.org的原因。

目前在kernel社群比較活躍的ARM9廠商,或是社群主動積極協助維護的SOC平台,像是ATMEL、Samsung與TI OMAP等,這些都是kernel.org的Linux kernel就有支持的處理器,這表示讓Linux支持這些平台的方式也很簡單,就是到kernel.org下載官方的Linux kernel即可。

Crosstool

針對ARM9或是其它平台的開發,最重要的工具就是Cross Toolchain。Cross Toolchain的製作一直是Embedded Linux開發者的夢靨,大多數人選擇由網絡下載現成的開發工具,但經常會遇到缺乏鏈接庫的編譯錯誤。完整的Cross Toolchain包含1套基本的gcc cross compiler以及其它的應用鏈接庫;Cross Toolchain是製作基本gcc cross compiler的工具,透過crosstool即可製作ARM9的基本toolchain。

Root Filesystem概念

Root filesystem的建置,即是在建立1個基本的Linux系統(base system),讓kernel在完成開機後,進入user mode執行使用者程序。Root filesystem的建置主要是以Busybox為主,並加入(移植)客制化的開放源碼(open source)與自由軟件(free software)。

因為嵌入式Linux的root filesystem是依照需求加入套件,與桌面環境的Linux distribution不同,因此都是用從頭打造的方式做起。在建立root filesystem時,鏈接庫相依 (library dependencies) 的議題是相當重要的項目。當root filesystem缺少必要的library時,程序當然無法執行,甚至系統也會無法順利啟動。分析應用程序所需的相依鏈接庫,觀念如下:

(1)先利用Cross Toolchain的objdump指令觀察ELF格式裡的「NEEDED」項目。

(2)必須再檢查這些library是否相依其它library。

1個基本且可開機的root filesystem,也稱做bootstrap root filesystem,1個可用的bootstrap root filesystem只需要包含busybox與libc即可。傳統的Embedded Linux應用,大多是以NFS的方式來測試目標裝置的完整root filesystem(full root filesystem)。以NFS進行Embedded Linux開發測試,主要是針對目標裝置的full root filesystem做立即(right now)的系統執行測試(run-time),免除不斷打包image file、開機的惡夢。這是1種流行很久的Embedded Linux系統測試與開發方式,其概念如下:

(1)將target的完整root filesystem(例如ARM9 root filesystem)建置後,存放於host端的某個目錄下,例如/home/rootfs。

(2)為target製作1個NFS root filesystem,也就是bootstrap root filesystem+ NFS功能,並使用NFS root filesystem將目標裝置開機。

(3)設定host端為NFS server。

(4)以NFS mount方式將host端上的root filesystem目錄mount進來,即可在目標裝置上執行full root filesystem裡的應用程序。

這種方式不但簡單,而且方便,需要的基礎建設如下:

1.目標裝置使用的kernel必須支持NFS。

2.製作bootstrap root filesystem時,需要加入mount指令,並且開啟mount指令的NFS功能。

3.加入NFS functionality至bootstrap root filesystem。

4.設定NFS server。

製作完成的root filesystem必須做打包的動作,將整個root filesystem包裝成1個映像檔(image file)。根據目標裝置的不同,我們可以將映像檔包裝成ROM fs、Compress ROM fs、ext2fs或是compress RAM fs。

ROM file system

ROM file system(romfs)是1種只讀的檔案系統,在Embedded Linux裡的主要應用為製作romfs格式的檔案系統映像文件。我們將root filesystem製作成romfs filesystem的image檔。開機後,整個filesystem僅能讀取。要使用romfs filesystem必須將Linux kernel裡的CONFIG_ROMFS_FS功能選項打開。製作ROM fs映像檔所使用的工具為genromfs。

Compressed ROM file system

Compressed ROM file system(cromfs)即是壓縮過的ROM file system,其製作方式相當簡單,只要使用gzip將ROM file system的映像檔壓縮即可。

製作ext2fs映像檔

製作ext2fs映像檔的方式有2種。1種是使用dd指令產生1個空白的映像檔,接著再將此映像檔以mkfs.ext2指令格式化成ext2的格式。製作 好的空白映像檔再以loopback mount方式掛載到1個目錄下,再將root filesystem整個複製到此目錄下,即可完成ext2fs映像檔的製作。

另外1種建立ext2fs映像檔的方式是使用genext2fs工具,此工具的好處是,當我們需要在root filesystem裡預先建立(pre-built)裝置文件時(device file),只需要編寫1個裝置文件表格,genext2fs工具會在打包映像檔時,自動在root filesystem裡建立裝置文件。

Initial RAM disk(initrd)

RAM disk是存在於內存中的虛擬磁盤,也就是將RAM拿來當成磁盤使用。在Embedded Linux的應用中,我們通常會將ramdisk當成暫存目錄來使用。例如將/dev/ram1附掛到/tmp目錄,以便能讓應用程序存放暫時性檔案。 /dev/ram?為ramdisk的device file。由於整個root filesystem是從真正的儲存裝置讀取並加載至ramdisk,因此有1個重要的特性是對file system所做的任何修改,都不會影響到真正root filesystem的內容。

initrd全名為initialize RAM disk,是1個特殊的RAM disk。bootloader會將initrd載至內存,Linux kernel則可在/dev/ram0找到initrd。initrd會在Linux kernel開機前就加載,initrd正式的用途是用來存放開機時所需要的驅動程序(因root filesystem尚未mount進來)。在Embedded Linux應用上,我們會利用initrd來存放整個檔案系統(root filesystem),也就是將root filesystem製作成ext2或romfs格式(或其它檔案系統)的映像文件,並在開機時由bootloader加載內存,initrd均位於 /dev/ram0。要使用RAM disk與initrd,必須將Linux kernel的CONFIG_BLK_DEV_RAM以及CONFIG_BLK_DEV_INITRD)。

使用initrd做為root filesystem裝置

將initial RAM disk當成root filesystem來使用,是在Embedded Linux應用上是相當常見的技巧,如果我們想將initial RAM disk當成存放root filesystem的裝置來使用,在開機時,只需要配合root=的kernel開機參數即可。

initramfs

Linus本人在Linux 2.6時代所提出的 "initramfs" ,是1種更好的 "root=" 做法。簡單來說,initramfs就是kernel 2.6 的 initrd,initramfs是屬於1種compressed ramfs(ram filesystem)的映像檔。

C鏈接庫

在C鏈接庫方面,除了標準的glibc也被廣泛應用在嵌入式系統領域外,也有一些專門針對嵌入式系統應用所發展的C鏈接庫,像是uClibc以及Diet libc。但是由於現在的ARM9處理器計算效能都很快,平台也多搭載大容量NAND閃存,所以許多實作都直接使用libc來實作root filesystem。

Linux驅動程序

由於嵌入式系統整體來看,除了軟件開發外,也包含硬件客制化,因此驅動程序在嵌入式系統技 術領域中,佔了舉足輕重的地位。學習驅動程序需要確實瞭解硬件的規格與微處理器架構,並且工程師還要能分得清楚哪些東西是接口 (interfacing),也就是與硬件無關的程序(machine-independent);以及哪些是站在第一線做硬件控制的程序 (machine-dependent)。各種軟件硬接口與匯流排也都要精通。

瞭解Linux驅動程序的架構,是進入嵌入式Linux領域的重點功課,因為許多針對ARM9平台的驅動程序都是參考框架、或是針對特定開發板的實作,因此必須瞭解Linux驅動程序的架構,並進行修改,以符合自己的開發板與外圍規格。

Linux驅動程序,採取嚴謹的分層式架構設計(layered architecture),利用分層的架構設計來徹底區分generic device driver(machine independent)與machine dependent driver。

Linux驅動程序透過註冊與回呼的機制來清楚區分每1層的關係。分層架構的實作必須在下層將自己註冊給上層,上層再回呼下層;上層的驅動程序必須提供註冊函數供下層呼叫,下層驅動程序所使用的註冊函數也將決定自己的上層架構。

與user application如何互動,是撰寫驅動程序時所要考慮的重要一環,因此撰寫驅動程序時,要提供什麼功能給應用程序引用,就必須事先定義清楚。 Linux的 generic device driver層已經幫我們把這些功能定義清楚了。Linux驅動程序如何透過I/O port或I/O memory來控制裝置,也就是與芯片組的溝通,方式是使用Linux kernel所提供的I/O函數來存取並控制實體硬件裝置。

Linux驅動程序的裝置文件

Device files是UNIX系統的獨特觀念,在UNIX系統底下我們把外部的周邊裝置均視為1個檔案,並透過此檔案與實體硬件溝通,這樣的檔案就叫做device files或special files。

Device file的major number代表1個特定的裝置,例如major number 1為」null」虛擬裝置,major number定義於kernel文件目錄Documentation/devices.txt。Minor number代表裝置上的子裝置,例如同1個硬盤上的分割區就用不同的major number來代表,但其major number相同。

我們在設計device driver時,會先透過1個「註冊」(register)的動作,將自己註冊到kernel裡,註冊時,我們會指定1個major number參數,以指定此驅動程序所要實作的外圍裝置。當user開啟device file時,kernel便會根據device file的 major number找到對應的驅動程序響應使用者。Minor number則是device driver內部所使用,kernel並不會處理不同的minor number。

Linux 2.6的kobject模型

Linux 2.6在驅動程序的架構方面,加入kobject的概念。kobject以更有系統、組織的方式維護系統裡的driver(集中式管理),但並非改變現有 (kernel 2.4以來)的driver架構。在kobject的模型下,可以看到1個platform driver觀念。所謂「platform driver」就是machine- dependent driver,當驅動程序設計師在kernel 2.6底下實作machine-dependent driver時,就要以platform driver的架構來實作。例如,針對我們的目標裝置進行硬件層的驅動程序撰寫時,就要以platform driver的方式來撰寫,實作上,只是多1個註冊到platform driver層的動作而已。

Flash裝置的支持

針對嵌入式系統經 常使用的閃存(Flash)儲存裝置,Linux kernel支持JFFS2與NFTL 2個專門針對快閃記億體設計的檔案系統。JFFS2(Journaling Flash File System version 2)是專門針對 NOR 型閃存所設計的檔案系統。NFTL(NAND Flash Translation Layer)則是專門針對NAND型閃存設計的檔案系統。

結論

綜合而言,Embedded Linux是1個平台、也是一些工具的集合、也是1個嵌入式軟件的開發環境;實作上,Embedded Linux除了會進行kernel的修改、驅動程序的移植或開發外,也會是系統管理與系統整合的再應用,這是一門集大成的技術,並不只是1個嵌入式操作系統,也不只是1套開發工具。

(本文為Jollen’s Consulting, Inc.技術顧問撰寫http://www.jollen.org/consulting)

2010年7月28日 星期三

建立 Linux 檔案系統 (使用 Busybox )

建立Linux檔案系統

參考來源
http://flykof.pixnet.net/blog/post/24242728

檔案系統是Linux不可缺少的一部份,不過在Embedded System上資源有限,不可能建立像PC那麼大的檔案系統,系統工具程式必須經過精簡化將檔案縮小這樣才可節省Embedded System資源。

現在在Embedded Linux上最常用的檔案系統為 "Busybox" "Buzybox"整合的各種系統工具程式(ex: ls, mkdir, rmdir, mount, ifconfig, kill ...)成為一個單一執行檔,大大縮減了系統使用容量。以下介紹 使用 "Busybox" 來建立檔案系統。

busybox可以在官方網站(http://www.busybox.net/)下載。

依照以下步驟建立Linux檔案系統

1、 解壓縮並編譯busybox

#tar jxf busybox-1.13.1.tar.bz2
#export PATH=/usr/local/arm/3.4.1/bin:$PATH (arm-linux-gcc的路徑加入PATH環境變數)
#make menuconfig (busybox組態)
(設定以下組態,指定Cross Compiler prefix使用arm-linux-來編譯出ARM的執行檔,由於考慮到nand flash大小的限制,所以在此只選擇必要且重要的選項。)
重要選項:
Busybox Settings--->
    Build Options --->
               [*] Build BusyBox as a static binary (no shared libs)   
               [ ] Build with Large File Support (for accessing files > 2 GB)  
        (arm-linux-) Cross Compiler prefix
(其他選項可依據需求增加或刪減)
 
#make
#make install PREFIX=安裝資料夾
(編譯完成的檔案如果沒有透過PREFIX設定基本上會放在 _install 目錄下,這幾乎就是我們要的檔案系統了,不過還需要建立一些目錄與檔案)
#mkdir _install/proc
#mkdir _install/sys
#mkdir _install/lib
(複製共用函式庫本例使用的ARM cross compiler安裝於 /usr/local/arm/3.4.1)
#cp -ax /usr/local/arm/3.4.1/arm-linux/lib/libc-2.3.2.so _install/lib   (複製C函式庫)
#cp -ax /usr/local/arm/3.4.1/arm-linux/lib/libc.* _install/lib
#cp -ax /usr/local/arm/3.4.1/arm-linux/lib/libm-2.3.2.so _install/lib   (複製數學函式庫)
#cp -ax /usr/local/arm/3.4.1/arm-linux/lib/libm.* _install/lib
#cp -ax /usr/local/arm/3.4.1/arm-linux/lib/ld-* _install/lib          (複製linux程式載入函式庫)
#cp -ax /usr/local/arm/3.4.1/arm-linux/lib/libthread_db* _install/lib (複製thread函式庫)
#rm -f _install/lib/*a (刪除連結檔 ".a"  ".la"這些檔只有在連結時才會用到執行時不用)
#mkdir _install/tmp
#chmod 777 _install/tmp
#mkdir _install/var
(建立裝置檔)
#mkdir _install/dev
#mknod _install/dev/console c 5 1
#mknod _install/dev/ttyS0 c 204 64
#mknod _install/dev/ttySAC0 c 204 64
#mkdir _install/etc

2、 啟動命令稿編輯

可依需求再加上啟動時要執行的指令ex: 網路設定啟動畫面顯示等。

inittab用來規劃軟體的執行環境,包刮系統的主機名稱、網路設定、語系處理、檔案系統格式及其他服務的啟動等。

#vi _install/etc/inittab

(編輯內容如下)

::sysinit:/etc/init.d/rcS //準備系統執行環境的腳本執行檔

::askfirst:-/bin/sh //開啟一個無需登入驗證的shell

::restart:/sbin/init

::ctrlaltdel:/sbin/reboot //當按下CRTL+ALT+DEL時執行命令reboot

::shutdown:/bin/umount -a –r //指定關機時執行的操作

::shutdown:/sbin/swapoff –a //指定關機時執行的操作

rcS為系統執行環境的腳本執行檔。

#mkdir _install/etc/init.d

#vi _install/etc/init.d/rcS

(編輯內容如下)

#/bin/sh

echo "-----------Run rcS-----------"

ifconfig lo 127.0.0.1

echo "Set IP 192.168.0.10"

ifconfig eth0 192.168.0.10

mount -t proc proc /proc

mount -t sysfs sysfs /sys

profile是每個使用者登入取得bash時一定會讀取的設定檔。

#cd _install/etc

#vi _install/etc/profile

echo "Set search library path in /etc/profile"

export LD_LIBRARY_PATH=/lib:/usr/lib:/opt/Qtopia/lib

# Set user path

echo "Set user path in /etc/profile"

PATH=/bin:/sbin:/usr/bin:/usr/sbin:/opt/Qtopia/bin:/usr/local/bin

export PATH

3、 掛載Linux檔案系統

掛載檔案系統通常有兩種常用的方法,一個是建立成映像檔,另一個方法是透過網路建立NFS檔案系統。以開發階段而言,透過NFS連線方式建立起來的檔案系統,無疑能夠節省很多的時間,編寫好的程式或是修改過的檔案系統都能夠即時的做測試,而不需等待重複燒寫到flash中。

1、 製作映像檔

在嵌入式LINUX中,根檔案系統至關重要,它是所有文件和設備節點的起始點,決定了系統能否正常啟動的關鍵。

選擇檔案系統

爲根檔案系統選擇檔案系統是個困難的過程。最後通常是檔案系統的能力與目標板的用途之間折衷的結果。舉例來說,如果目標版根本不需要永久性的儲存任何資料,那麼選擇可以提供永久性寫入儲存的檔案系統毫無用處。對這類目標板來說,一個不具永久性儲存功能的檔案系統,例如CRAMFS,是比較好的選擇。

檔案系統特性

要爲特定的應用選擇最佳的檔案系統或最佳的檔案系統組合,我們需要一組可用來比較檔案系統的特性。透過下面幾個問題,可以描繪出每種檔案系統的特性:

可被寫入

這個檔案系統可以被寫入嗎?

具永久性

重開機之後這個檔案系統可以保存修改過的內容嗎?

具斷電可靠度

晶變動的檔案系統可以在斷電之後恢復過來嗎?

經過壓縮

經掛載的檔案系統,其內容有經過壓縮嗎?

存在於RAM

檔案系統的內容再被掛載之前會先從儲存裝置取珠並放在RAM中嗎?

Root Files System其類型相當的多,如:romfsext2ext3ext4cramfscromfsinitrdinitramfsyaffs2…等等。

對於目標版所要燒入的映像檔還需要注意到,Linux kernel是否有支援相對應的格式,若無,啟動時將會出問題。

在此我們所需要的檔案格式為yaffs2,執行命令如下:

#mkyaffs2image 目標資料夾 映像檔名稱

製作好的映像檔可以透過bootload寫入flash中,之後設定Linux啟動時掛載flash為根目錄即可。

2、 NFS掛載

NFSNetwork FileSystem)是實現兩機間進行通訊訪問的一種簡單方法。在嵌入式Linux實驗中,我们通過配置NFS實現個人電腦和開發平台之间的溝通。

   原理是在個人電腦的Linux中開啟NFS服務,設定一個共享目錄,所有的源碼編輯改動都可以在個人電腦中進行方便的修改。在實驗環境中,將個人電腦的目錄遠程mount到本地,實現兩機間的同步讀寫訪問,這樣程式就可以方便的在 PC中運作測試。簡單說來,目的就是設定一個共享目錄,在個人電腦中進行編輯,在開發板中進行運作調試。

在開發的過程中,因為僅只個人電腦與開發板的連接,無須考慮到共享資料夾的安全與權限問題。因此,在這裡只需要做一些簡單的設定即可。

NFS掛載目錄及權限由/etc/exports檔案定義,開發板啟動時所要掛載個人電腦上的開機的根目錄就必須在此作設定。

#vi /etc/exports

在檔案中加入下面這一行

資料夾完整路徑 *(rw,sync,no_root_squash)

bootloader的啟動參數也需要設定連接的IP與目標資料夾才能正確啟動。我所使用的bootloaderu-boot,設定方式如下:

setenv bootargs console=ttySAC0 root=/dev/nfs rw nfsroot=NFS主機的IP:欲掛載的資料夾完整路徑 ip=開發板IP: NFS主機的IP: Gateway IP:255.255.255.0

4、 啟動Root File System

當一切都設定完成之後,啟動開發板進入系統。如下圖所示:

busybox_啟動畫面.JPG


參考資料:

[1]http://linux.vbird.org/linux_basic/0510osloader.php

[2]http://linux.vbird.org/linux_basic/0340bashshell-scripts.php#script

[3]http://www.study-area.org/cyril/scripts/scripts/node6.html

[4]http://www.mgt.ncu.edu.tw/~dino/script/

[5]http://linux.vbird.org/linux_basic/0320bash.php#settings_bashrc_profile

[6]http://linux.vbird.org/linux_server/0330nfs.php#What_NFS_0

[7]建構式嵌入式LINUX系統8.1.1

2010年7月27日 星期二

基於Nandflash的Bootloader的設計與實現

基於Nandflash的Bootloader的設計與實現

2010-06-18 15:21:44 作者:郝衛東 劉溯奇 來源:電子發燒友

0 引言

Bootloader通常稱為系統引導加載程序,是系統加電或復位後執行第一段代碼[ 1 ]。一般它只在系統啟動時運行非常短時間,但對於嵌入式系統來說,這是一個非常重要系統組成部分。通過這段小程序,可以初始化硬件設備、建立內存空間映射 圖,從而將系統軟硬件環境帶到一個合適狀態,以便為調用操作系統內核準備好正確環境,並同時提供基本輸入、輸出系統監控功能和程序調試功能。

Bootloader是嚴重地依賴於硬件而實現。每種不同體系結構處理器都有不同Bootloader。除了依賴於處理器體系結構以 外,Bootloader實際上也依賴於具體嵌入式板級設備配置,也就是說,對於兩塊不同嵌入式板而言,即使它們是基於同一種處理器而構建,要想讓運行在 一塊板子上Bootloader程序也能運行在另一塊板子上,通常也都需要修改與目標硬件相關代碼。因此有必要分析Bootloader,並理解和找出其 中原理和規律,就其特定嵌入式系統,移植或開發屬於自己Bootloader。

1 系統硬件平台簡介

本系統採用是SamSung公司S3C2410處理器[ 2 ],它是專門為移動手持設備提供高性價比和高性能嵌入式微處理器解決方案。其內核是ARM920T,最高能工作在202.8MHz,為了減少系統總成本和 減少外圍器件,它集成了如下部件:分別為16KB指令和數據Cahce、1個LCD控制器、SDRAM控制器、NANDFLASH控制器、3通道 UART、4通道DMA、4個具有PWM功能計時器和1個內部時鐘、8通道10位ADC、觸摸屏接口、I²S總線接口,2個USB主機接口、1個USB設 備接口,2個SPI接口、SD和MMC卡接口、看門狗定時器、117位通用IO口、24位外部中斷源、8通道10位AD控制器等。本文涉及S3C2410 開發板硬件結構如圖1所示,本文主要闡述從Nandflash引導操作系統要完成主要任務和實現方法,至於從Norflash引導操作系統,不打算具體實 現。


圖1 S3C2410硬件結構圖

2 存儲空間分佈和映射圖

硬件平台Nandflash(型號是:K9F1208U0M[ 3])空間為64MB,SDRAM(型號是:HY57V561620[ 4 ],32Mx2)空間為64M(0x30000000-0x33ffffff),採用如圖2所示存儲空間分佈圖,因為Nandflash只能存儲程序,無 法運行程序。為了能夠從Nandflash啟動,上電復位時,S3C2410通過硬件邏輯把Nandflash前4KB內容複製到片內SRAM中,而片內 SRAM被映射到地址0x0,這樣就可以從地址0x0處取到有效指令,開始執行bootloader,完成把Nandflash中內核代碼複製到 sdram中等工作。


圖2 引導代碼和操作系統內核在Nandflash和存儲空間中分佈情況

3 Bootloader設計流程

Bootloader引導程序是硬件上電復位後首先運行代碼,由它來加載嵌入式操作系統。然後由操作系統接管整個系統,進行進程管理、內存管理、磁盤管理 和各個外設管理等工作。 BootLoader是操作系統內核運行之前一段自舉程序,用來初始化硬件設備、改變處理器運行模式和重組中斷向量,建立內存空間映射圖,將系統軟硬件環 境帶到一個由用戶定製特定狀態,然後加載操作系統內核。從操作系統角度來看,Bootloader總目標就是正確地調用內核來執行。Bootloader 一般分為stage1和stage2兩大部分[ 5 ],對於依賴於CPU體系結構代碼,比如設備初始化代碼等,通常都放在stage1中,而且通常都用彙編語言來實現,以達到短小精悍目,也就是前面說啟動 代碼。而stage2則通常用C語言來實現,這樣可以實現複雜功能,而且代碼會具有更好可讀性和可移植性。

3.1 Bootloaderstage1

這部分代碼必須首先完成一些基本硬件初始化。為stage2 執行以及隨後內核執行準備好一些基本硬件環境。Bootloader stage1 一般通用內容包括:

(1)設置中斷和異常向量;(2)禁止看門狗;(3) 屏蔽所有中斷, 在Boot Loader 執行全過程中可以不必響應任何中斷, 中斷屏蔽可以通過寫CPU 中斷屏蔽寄存器或狀態寄存器CPSR 寄存器來完成;(4) 設置CPU 速度和時鐘頻率;(5) 對RAM進行初始化, 包括正確設置系統內存控制器功能寄存器等;(6)初始化LED或UART,就是通過GPIO來驅動LED,也可以通過初始化UART向串口打印 Bootloader調試信息來表明系統狀態是OK還是ERROR,以便跟蹤系統運行情況;(7)關閉CPU 內部指令/數據高速緩存(cache);(8)為加載Bootloaderstage2準備RAM空間;(9)設置好堆棧;(10)跳轉到stage2C 入口點;其流程圖如圖3所示。


圖3 Bootloaderstage1實現

3.2 Bootloaderstage2

為了讓程序跳入C 語言「main」函數, 我們採用直接跳轉到「main」函數方法, 實現代碼如下:
b Main
進入main 函數後即可以開始本階段stage2 初始化任務, 這包括:
(1) 如果在stage1沒有初始化UART,這時候至少初始化一個串口, 以便和終端用戶進行交互,當然也可以繼續點亮或熄滅LED來判斷程序執行情況;
(2) 修改時鐘頻率;
(3) 使能指令Cache;
(5) 從串口中打印一些必要交互信息,瞭解系統狀態;
(6) 初始化中斷, 包括屏蔽中斷, 清除中斷懸掛標誌, 初始化中斷向量表, 註冊需要中斷處理函數等;
(8)打印版本、時間等信息,並從Nandflash複製內核到SDRAM中;
(9)修改指針,直接跳到內核在SDRAM中首地址處,至此,完成了Bootloader全部運行加載工作;

下面是main()函數和從Nandflash複製內核到SDRAM中ReadImageFromNandflash()函數具體實現,但省略了一些具體細節,包括從串口打印啟動、交互、調試信息和一些具體函數實現。一些具體函數實現可以參考三星評估版源代碼。
void Main(void)
{
JumpAddr=0x30200000; //拷貝內核到sdram中起始地址,也是內核開始執行地址
ChangeClockDivider(1,1); //1:2:4
ChangeMPllValue(0x5c,0x1,0x1); // FCLK=202.8MHz
MMU_EnableICache(); //使能指令Cache
Uart_Init(); // 初始化串口
Port_Init(); //初始化I/O口
NF_Init(); //初始化Nandflash控制器
NF_ReadID(); //讀取Nandflash存儲器ID號
ReadImageFromNandflash();//把存儲在Nandflash中內核拷貝到SDRAM中
rINTMSK=BIT_ALLMSK; //屏蔽所有中斷
Launch(JumpAddr); //跳轉到sdram中內核開始處,並運行內核
}
從Nandflash(Flash是K9F1208U0M)拷貝內核到SDRAM函數具體實現如下:
void ReadImageFromNandflash(void)
{
U8 Image_Buf[512];
U32 Sram_Space=0;
U32 j,k, numberblock;
static U32 i, SECTOR_SIZE=512;
static U8 isbad;
volatile U32 IMAGE_BASE=0x30200000; //內核在sdram中運行開始地址
rINTMSK = BIT_ALLMSK; //屏蔽所有中斷
i=2; //從第2個block開始拷貝內核,第0個用於存儲本文bootloader,第1個沒用到
numberblock=2047; //拷貝多少個block到sdram中,視內核大小設置此值
while(1)
{
nextblock:
isbad=0;
isbad=NF_IsBadBlock(i); //判斷正在拷貝block是否是壞block
if (isbad) //是壞block,就進行相應處理;否則就忽略此處,進行下面拷貝
{
i=i 1; //調整,指向下一個block
isbad=0;
if(i>= numberblock) //判斷是否拷貝完了所需block
{
Launch(JumpAddr); //拷貝完了所需block,就跳到sdram中內核開始處
}
goto nextblock;
}
for(k=0;k<32;k block="32">

{ // FMD_ReadSector()函數實現從Nandflash存儲器中讀取數據到數據緩衝區中
FMD_ReadSector(i, (U8 *)&Image_Buf, k);
for (j=0;j= numberblock) //判斷是否拷貝完了所需block
{
Launch(JumpAddr); //拷貝完了所需block,就跳到sdram中內核開始處
}
}
}

4 試驗結果

由於三星公司S3C2410集成了Nandflash控制器,它通過硬件邏輯把Nandflash前4KB內容,即把Bootloader複製到片內 sram中,並被映射到地址0x0處。通過跳線設置默認從nandflash啟動,那麼,系統每次上電或復位後,首先開始運行就是Bootloader。 使用ADS1.2集成開發環境建立Bootloader應用工程,添加必需文件並設置好編譯環境,如BootloaderRO_Base設置為 0x0,RW_Base設置為0x33ff0000等,調試並最後生成可執行二進制文件,通過JTAG接口把Bootloader燒寫到 Nandflash第0個block地址開始處,通過usb下載工具把操作系統燒寫到第2個block地址開始處,復位啟動系統運行後結果如圖4所示,該 程序用於基於uCOS操作系統圖像採集系統引導。用同樣方法燒寫不同操作系統內核應用程序,試驗結果每一次表明:Bootloader運行良好,啟動加載 內核快,且簡單、實用、可靠。


圖4 Bootloader引導運行系統

5 結論

Bootloader設計與實現是一個非常複雜過程,因此要根據具體硬件和軟件需求分析來進行移植或設計。本文設計Bootloader完成主要功能包 括:試驗板硬件初始化、串口初始化、時鐘頻率修改以及從Nandflash複製操作系統到SDRAM中運行等,並通過PC機上超級終端顯示了正確啟動運行 信息,且可執行代碼只有3K左右。因此,本文所詳細描述Bootloader啟動運行全過程,對理解、設計和移植Bootloader具有一定參考意義。

U-Boot bootloader 至 Nor Flash 方式

U-Boot bootloader 至 Nor Flash 方式:

From Jollen's Wiki

Jump to: navigation, search
  • JK2410 已附一副 J-TAG adapter ,約 15~20 cm - 20pin 雙接頭排線及 1.5m 長的Parallel Printer cable 一條。
  • 專用 J-TAG adapter 的pin assignment 是相容於 SJF2410
  • 若Host 為 Linux 環境:
  • 若Host 為WinXP 環境:
    • Step 1:請自行上 google 找尋可用之 SJF2410 軟體,下載
    • Step 2:請自行上 google 找尋 giveio.zip (解開後應包含 最基本的 giveio.sys,giveio.INI,giveio.sys 三個檔案)
    • Step 3:安裝 giveio,方法如下:
      • (1) Copy the giveio.sys file to C:\WINDOWS\system32\drivers.
      • (2) 開啟控制台 -> 新增硬體 -> 下一步 -> 是,我已連結硬體 -> 新增硬體裝置 ->安裝我從清單中手動選取的硬體(建議選項)(M) -> 下一步 ->連接埠(COM和LPT) ->從磁片安裝 -> 從磁片安裝(選擇gvioio.inf ) -> 下一步 完成。
    • 將 J-TAG adapter,排線 及 Parallel Printer cable 分別接上,並各自接到 JK2410 的 CON5 - JTAG/Multi-ICE 及 Host (一般是PC desktop 或 NB) 的 printer port;
    • JK2410的CON04 指撥開關,調整到 Nor Flash boot up mode,即 "01"
    • 接上電源線,並開機。
      • 此時,讓 Host 進入 commond mode,在 SJF2410 安裝的目錄底下,執行 SJF2410,指令如下:指令格式 >sjf2410 /f:
        • c:\sjf>sjf2410 /f:ub-nor.bin
        • 此時,畫面應出現:

$ sjf2410 f/:ub-nor.bin

+------------------------------------+

| SEC JTAG FLASH(SJF) v 0.4 |

| (S3C2410X & SMDK2410 B/D) |

+------------------------------------+

Usage: SJF /f: /d=

S3C2410X(ID=0x0032409d) is detected.

[SJF Main Menu]

0:K9S1208 prog     1:28F128J3A prog   2:AM29LV800 Prog   3:Memory Rd/Wr   
4:Exit

Select the function to test:2

.... Input target offset : "0" <-offset key in "0" 即可,

之後,應該就可以進行燒錄了! 視 Code size ,以現有的 ub-nor.bin ,大約要燒 半個小時左右,請耐心等候。

Free TFTP server for WinXP

embeded system 常用輩分或傳輸 image 的工具。
SolarWinds-TFTP-Server
TFTPD32 by Philippe JOUNIN

2010年7月13日 星期二

LED現在替代傳統照明是錯誤的產業方向

LED現在替代傳統照明是錯誤的產業方向

上網時間:2010年07月09日

source: LED現在替代傳統照明是錯誤的產業方向


LED作為一種新型光源,節能、長壽命、無污染而受到大家的廣泛關注。尤其中國奧運會成功運用大量LED技術,效果非凡,各地方政府紛紛扶持LED產業, 建立了大量的LED示範單元,與此同時,大量的企業也涉足該領域,就連做電池起家,汽車成名的BYD公司再次提出LED世界第一的口號。

LED 真的就進入繁榮時期了麼?

我個人認為,這只是一個方向不明的亂戰時期。

在人類歷史長河 中,從沒有哪個照明設備像LED這樣還沒有成熟就被寄予厚望,但是緩慢的發展,也使的LED產品過於概念化,缺乏客戶基礎。即便現在政府正在以LED路燈 為突破口試圖扶持LED的成長,可LED無論是民用還是商用的客戶群依舊沒有形成。在這個時候有一個危險的信號:LED廠商已經把壓縮成本作為第一要務! 很多公司將LED的電流做大以在維持亮度不變的情況下減少燈芯數量以節約成本,或者壓縮PCB面積,抑或是減少安規器件等方法,當然大家要相信中國的公司 在壓縮成本方面的先天優勢。暫且不說這樣做對於產品安全問題的影響,就產業群而言,LED在還沒有市場的情況下就進入了價格洗牌的局面,這對整個產業來說 是不利的,資金大頭的進入會加劇中小企業的衰亡。

這是一個危險的局面,一方面LED的技術發展將會停滯甚至於退化,另一方面 成本的壓縮,或者說過多的關注成本無法保證最終產品特質,將很大的程度上不能展示LED的優勢。因此我斗膽,認為此時的LED產業發展方向錯了。

現 在的LED產業為了打開民用市場,多是將LED燈具設計成可替換方式,即直接替換現有的燈具。但是在燈具發展的過程中,除了緊湊型燈管直接替換白熾燈以外,鮮有直接替換的模式,像T8、吸頂燈幾乎是螢光燈的專利,而 吊燈依舊是鎢絲燈的天下,LED為什麼一定要走替換的道路?

現有的替換燈具這種設計方式有什麼缺點?

1.散熱

LED的耐熱很差是人所共知的,必然會帶來燈芯壽命的問題。 現有的LED燈的設計往往散熱難以達到要求,在一個散熱要求非常苛刻的領域,卻使用十分低劣的被動散熱方式,而且多是風冷,甚至是封閉式的風冷。像一些燈 具在驅動板和鋁散熱片之間要加塑料套管以增加絕緣的可靠性,還需要灌散熱硅膠以提高散熱能力。而T8的燈管燈管還是封閉的,燈芯只能依靠空氣對流傳熱到燈 管背面的鋁管上進行散熱。一般這類燈的內部溫度都會有七八十度。並且要是兼顧散熱,重量又是問題;兼顧重量,散熱難以保證,這在現有設計中是兩難的選擇, 尚沒有可行的標準。

2.壽命

LED燈芯壽命隨溫度的升高而呈指數降低;電解電容溫度每升高十度壽命降低一半;MOS溫度升高,內阻增加,損耗增加,溫度又會升高 (恆流模式),最終燒燬。當然,國內的廠商沒有給出具體LED燈具的壽命,宣傳的時候只是提到LED燈芯壽命十萬小時,但是LED的壽命瓶頸在系統驅動 板,往往LED燈芯沒有損壞,系統驅動已經掛掉了。

另外 LED的光衰是非常嚴重的,所以燈具的壽命應該也要考慮視覺感受,就是經過多長時間燈具的亮度降低到視覺上覺得暗的程度,可以認為壽命到了,客戶就會考慮 更換燈具,這個壽命是廠商都沒有給出來(或者沒有辦法給出),但這非常重要。

再而言之,現有的LED家用照明多數受體積限 制,防護方面很難做的很好,在電壓波動較大,干擾嚴重的區域,現有的低功率的設計是一個考驗。

而最重要的是,LED的壽命和 公司的壽命是否成正比,假若宣傳10年的LED燈具2年就壞了,而半年前這家公司已經關門大吉,用戶是否會去冒這個風險?

3.重量

螺旋類接口的燈具中,螢光燈的重量只有LED燈具的數分之一,由於沒有了散熱 片的問題,螢光燈的重量對燈座來說可以忽略不計,但是LED的重量對燈座是一個很嚴重的考驗,尤其是7.8W的螺旋接口LED燈,其重量是很危險的,這一 點又有哪個商家考慮了?

4.價格

一般的 LED驅動板在70度的溫度下可能壽命僅5年(家用),遠沒有達到LED燈芯10年的「概念」。所以相對比同等亮度的螢光燈來說,即便螢光燈只有1年的壽 命,1W1元的螢光燈要遠遠比1W10元的LED划算得多。尤其是LED 燈具損壞往往燈芯沒壞,卻要整個燈更換。算一算因為十分之一的驅動板卻要丟棄剩下十分之九的燈(燈芯和散熱片佔了整個燈具絕大部分的成本),如果每一個廠 商都沒有做好回收再利用的話,客戶是不會喜歡這樣的產品的。

5.效率

也許有人會很奇怪,LED 是節能產品,為什麼要考慮效率的問題?我在這裡提到兩點,一個是PF值,一個是系統效率。由於現有的 LED設計多數都是低功率的,受成本的壓力均採用被動PFC(填谷式),PF可能最高90,遠遠小於主動PFC動輒99的效率,對國家而言用LED取代發 光效率非常接近的螢光燈是個壓力。

由於LED的燈具現有的設計(除了路燈之外)多數都是小功率的,像是4.8W,7.2W 等,器件的損耗佔了很大的比例,隔離方式的必然很低,為了提高效率而採用非隔離方式不但要在安全上做很好的設計,而且效率也僅僅在80左右,很不理想。並 且,現有的LED生產廠商到底 LED的光照度做到了多少,都沒有提供準確的數值,往往發光亮度遠遠小於標稱值。

6.光感

光 感,就是人眼對LED發光的視感——視覺感受。因為LED燈作為一個照明的產品,其視感是非常重要的。LED一個優勢是光譜純淨,但是這在視覺上面卻是一 個非常嚴重的劣勢。人的眼睛是不能長時間觀測一個單色譜的光源,尤其是發育期的嬰幼兒、兒童等,市場上推出的純冷白光的兒童護眼燈是不合適的,即便是不閃 的,在這方面暖色調的全光譜的白熾燈才是相對最合適的(以太陽光為參考,不可否認,太陽光才是生命最需要的)(如果大家有瞭解LED植物生長燈的,就應該 考慮一下既然植物生長都需要調製的光源,人眼更需要)。當然,LED可以調製,但是比較麻煩,比較專業,需要理論和大量的調研數據支持,是很多均光材料廠 商或者LED光源廠商抑或是方案供應商難以實現的。

LED是點光源,所以一般LED的燈具顆粒感都比較明顯,並且其發光位置 比較集中,目視燈具的時候會有刺痛感,這種感覺在其他光源中一般只有大功率的才會出現。所以LED需要在均光上面做更好的設計,以實現在保證亮度的情況 下,將點光源儘量擴展成面光源,提高眼睛的舒適度。

再有就是很多產品都會做LED調光設計,以節約能源,且不說低功率的時候 效率的問題,由於線圈中的電流的存在,會導致調光設計中灰階變化不連續,也就是說按比例調節的過程中,LED的亮度會慢慢變亮再突然變亮,視感很不舒服, 調光技術還是需要開發。

從這幾方面說,LED燈具的設計還需要進一步的開發。

個人的建議:

對於LED的燈具開發,我並沒有接觸整燈的設計,僅僅做過驅動電源的設 計,所以這裡面的說法僅僅代表個人的想法。

LED有什麼優勢?除了光效率高,節能,無污染之外還有一個非常特別而常常被忽略 的優勢——低電壓驅動。之所以提到這一點,是LED可以作為低電壓的安全照明來使用,將電源和燈芯,高壓的部分就不會和用戶直接接觸,而避免一些安全問題 的出現,例如現有的燈具在破損的時候更換而出現的安全問題。但是現有的很多LED設計採用非隔離模式以提高效率,使得燈頭依舊是高壓,十分的不安全。

相 比較現有的LED家用照明電源和燈芯放在一起的設計,我更傾向於路燈上開關電源+恆流模塊+燈芯的分離式設計。使用開關電源可以保證PF和效率,而且在防 護方面可以輕易做得非常好。

若是所有的4.8W的光源全部採用一個開關電源供電,首先正常運作的時候PF、效率都可以保證 的,即便是加上線上的損耗(使用23號線過1A電流,大約損耗0.7W/10m)這遠遠低於4.8W的現有設計的損耗(0.3A14V,效率約80,損耗 近1.5W)。簡單地說,將家裡面能用到的所有LED小功率的燈具全部使用一個開關電源,用銅線將低壓直流電送到燈芯上面,即便考慮走線的長度帶來的損 耗,也遠比現有的方案經濟。

散熱上面如果可以採用CPU上面使用的主動散熱設計,效果絕對是滿足要求的,要知道CPU對溫度 比 LED燈芯更敏感。單獨為LED開發散熱片模具的費用就是問題,還不保證公司是否具備散熱設計的專業資格,而使用CPU的散熱器則相對好得多,當然樣式上 不是那麼的正式。在淘寶上面有一家DIY模式的店舖,50WLED的用了CPU的風扇。

這樣來說,效率和散熱的問題都可以得 到很好的解決,不但解決了壽命的影響,更換起來也十分方便,LED燈芯亦是工作在安全電壓之下,即便直接觸摸也不會產生危險,也許是一個可行的選擇?

LED 是一個不閃的光源,為了節能非得要閃,雖然對眼睛好不好沒有定論,但是畢竟是丟西瓜撿芝麻。我倒認為可以採用8421這樣的比例直接用開關控制多少個燈 亮,倒是個調光的好選擇。

不過,我個人看現在的LED市場,單純依靠替換、模仿是走不出去的。電源的設計可以學習,可以採用 某某方案,但是替換式的燈具永遠不可能佔據主流市場(除非有一個非常的優勢,無論是光效還是價格,這點LED都不具備)。LED在替換式的設計中已經走向 了牛角尖,在還沒有打開市場的情況下,廠商又把原因歸結到價格因素,拚命地壓縮成本,實際上是錯誤的,螢光燈一個20元(緊湊型,使用MOSFET驅 動,T8燈管約4元),而相同亮度的白熾燈只要8角,這麼大的價格差距螢光燈卻依舊佔據了主流市場,是因為螢光燈走出了與白熾燈不一樣的,更方便的、獨有 的結構,如果當初螢光燈只想到完全替換白熾燈,沒有U燈管,T8等燈管的樣式,相信螢光燈依舊會是慘淡經營。所以LED並不依賴於成本而生存,而需要一個 公司能夠有新的LED凸顯優勢的產品,該公司必須懂得LED的特性和客戶的需求,這樣的公司很少。在現有的盲目競爭的狀態下,眾多企業蜂擁而上,全部都是 相同的架構,相同的外觀,LED燈具到底該如何設計,卻少有人真正去考慮這一點。

所以,在這種市場狀態下,開發出透光度更 高,均光效果更好的材料也許是眾多公司的一個不錯的選擇方向。

作者:憶輕狂

《電子工程專輯》博客博主

2010年7月10日 星期六

中華電、秀傳合建醫療雲,首創iPad影像傳輸

《通信網路》中華電、秀傳合建醫療雲,首創iPad影像傳輸

  • 2010-07-08 16:57
  • 時報資訊
  • 【時報記者何美如台北報導】
 中華電信(2412)與 秀傳醫療體系攜手合作,首創利用push mail MO(mobile office)服務與時下熱門iPad結合,即時傳送高解析醫療影像,建立雲端醫療應用平台,讓醫師準確判斷病患病情,執行最正確的醫療服務,為中華電信 的第一朵醫療私雲。中華電信將為秀傳醫療體系客製iPhone的「簡訊廣播」服務應用程式(AP),秀傳黃明和總裁表示,秀傳醫療體系醫生約5百人,未來 將向中華電採購5百台iPAD,並願意將醫療應用服務系統開放給其他醫療體系,未來這朵私雲可望逐漸擴大發展為公雲。

為讓醫療服務更完善,未來雙方將合作邁向更多行動化服務,中華電信近年積極跨足雲端市場,期許運用IDC整合服務提供秀傳醫療體系專業的雲端醫療應用平 台,如電子簽核做為醫療院所內部流程管理,讓醫療產業發展邁入新的里程碑,或導入中華電信MDVPN((Mobile Data Virtual Private Network行動數據群組企業網路)服務。

秀傳醫療體系為首度引進iPad做為醫療影像傳輸使用的醫療院所,透過中華電信MO服務,以push mail方式直接傳送病患的醫療影像(例如:心電圖、電腦斷層及X光片等)。在院內的醫師只要透過iPad即可瀏覽高解析圖像立即診斷,提高遠端醫療判診 的即時性與精準度。在急診室案例中,值班醫師並非專科醫師,若遇緊急特殊病況常急需專科醫師會診,而不在院內的的專科醫師就可透過手上的iPad連上無線 網路接收醫療影像做即時專業判斷,回覆院內急診醫生專業建議,掌握黃金搶救時間。

為解決院方僅能透過電腦發送群組傳呼的不便,中華電信為秀傳醫療體系客製化開發了iPhone簡訊廣播的應用功能。醫院管理者不必坐在電腦前,隨時隨地即 可透過iPhone傳送群組訊息與院內醫生或其他服務人員溝通,在病患就醫第一時間,即可迅速整合值班團隊接受任務指派,即刻更新病患狀況,掌握即時醫療 的重要關鍵。

為提升行動醫療品質並提供健康照護更完善的環境,中華電信與秀傳醫療體系共同打造健康雲,中華電信提供雲端平台、秀傳負責開發醫療應用服務系統,雙方著手 合作導入更多行動化服務。運用雲端技術讓醫療流程管理更即時,在防護醫療M化的管理上,透過MDVPN(行動數據群組企業網路)以行動電子化簽核來進行醫 療院所內部流程管理,及提供專屬於客戶資料管理的安全機制,解除病患個資洩漏的擔憂,不僅提升醫療行政資源整合效率,讓行動醫療服務更具完整,也將讓病患 獲得最大保障。

2010年7月8日 星期四

製作ARM9的Bootstrap Root Filesystem

JollenRoot Filesystem置技術系列》

製作ARM9Bootstrap Root Filesystem

作者/陳俊宏

http://www.jollen.org

引用自:http://www.jollen.org/cgi-bin/mt3/mt-tb.cgi/339

更新日期:2007/1/23

在「完整註明出處」的前提下(註明方式說明),您能立即擁有轉貼與引用的授權,且毋需知會作者。

目的

製作 bootstrap root filesystembase root filesystem)以提供一個最簡單、陽春且可開機的環境;製作完成的系統可開機到shell模式,並可使用 busybox 提供的指令。

準備工作

首先,您必須準備一台 host 開發環境,並安裝好 cross toolchain;接著,由於本文是做實機測試,因此,如果您沒有 ARM9 開發板,可以考慮使用 Qemu 來做模擬測試。

以下的操作示範,只節錄重點指令片段,您可能必須根據自己的整體實作流程,來微調指令的順序,或是參數等。

Step 1:建立工作目錄

建立一個專用的工作目錄,命名為 arm9.so-busybox/

# mkdir arm9.so-busybox/

# cd arm9.so-busybox/

接著在 arm9.so-busybox/ 目錄下建立 4 個子目錄:

# mkdir src/ install/ mnt/ pub/ build/

實際進行 root filesystem 實作時,我們應該養成將檔案分類擺放的好習慣。以本專案為例,build/ 目錄用來編譯程式,src/ 目錄用來存放原始程式碼,install/ 目錄則用來擺放我們最後的 root filesystem

Step 2:建立目錄架構

根據 FHS 的目錄架構標準,在 root filesystem 目錄下(install/)建立目錄階層架構:

# cd install/

# mkdir bin/ dev/ etc/ mnt/ proc/ sbin/ usr/

另外還有二個必要的目錄:/var /tmp,由於這二個目錄都需要具備寫入權限,所以在這裡我們是以 ramdisk 的做法來 mount 這二個目錄。

Step 3:建立裝置檔

root filesystem dev/ 目錄下建立必要的裝置檔:

crw------- 1 root root 5 1 1 1 1970 console

crw------- 1 root root 29 0 1 1 1970 fb0

crw------- 1 root root 1 3 1 1 1970 null

brw------- 1 root root 1 0 1 1 1970 ram0

crw------- 1 root root 5 0 1 1 1970 tty

crw------- 1 root root 4 0 1 1 1970 tty0

此階段使用 mknod 指令來完成。請先切換到 root filesystem dev/ 目錄下,接著執行以下指令:

# mknod console c 5 1

# mknod fb0 c 29 0

# mknod null c 1 3

# mknod ram0 1 0

# mknod tty c 5 0

# mknod tty0 c 4 0

對於需要產生大量 device file 的場合來說,可以改用 genext2fs ‘-D’ 參數來製作。詳見 Jollen’s Blog[使用 genext2fs '-D'device file table)來建立 root filesystem]

Step 4:加入Busybox

編譯並安裝 Busybox(動態程式庫方式)。將取得的Busybox原始碼解壓縮至 project 目錄裡的 src/ 子目錄下,以下是幾個注意事項:

  • 本教學文件使用 Busybox 1.3.1

  • Busybox 1.3.0 開始,使 Linux Kernel Makefile(因為開始支援 CONFIG_DESKTOP)。Cross compile 時,需要修改 Makefile 如下:

ARCH ?= arm

CROSS_COMPILE ?= /opt/crosstool/gcc-3.4.1-glibc-2.3.3/arm-9tdmi-linux-gnu/bin/arm-9tdmi-linux-gnu-

CROSS_COMPILE 的設定是 cross toolchain 的「PREFIX」,視您的 toolchain 而定。您可由 http://www.jollen.org/kit/ 下載本文所使用的 GCC 3.4.1 ARM9 toolchain,以使用與本文完全相同的修改。

Busybox 整合了常用的指令與工具,我們可以設 Busybox,以勾選我們需要的功能選項。進入 Busybox 的設定選單:

# make menuconfig

請注意,init shell 是必選的項目,請檢查是否有勾選這二個功能。同時,也別忘了設定 Busybox 的安裝路徑,將安裝路徑指到我們 root filesystem 目錄下。

接著直接進行編譯(cross compile):

# make

編譯完成後,將 Busybox 安裝至我們的 root filesystem 目錄(即 Step 2 install/ 目錄):

# make install

此時,您應該可以在 root filesystem 目錄下看到 Busybox 所安裝的檔案。

Step 5:加入動態程式庫

編譯完成的 Busybox 已經是給 ARM9 執行的格式了,但我們的編譯設定是將Busybox 編譯成 shared library 架構,因此 Busybox 執行時需要以下的檔案:

˙ libc.so.6C library標準程式庫。

˙ ld-linux.so.2Native dynamic loader

請由 toolchain 將以上二個檔案複製至 root filesystem lib/ 目錄下:

# cd ../../install (切換至root filesystem根目錄)

# cp /opt/crosstool/gcc-3.4.1-glibc-2.3.3/arm-9tdmi-linux-gnu/arm-9tdmi-linux-gnu/lib/ld-linux.so.2 lib/ (複制native dynamic loader。以上命令請勿斷行)

# cp /opt/crosstool/gcc-3.4.1-glibc-2.3.3/arm-9tdmi-linux-gnu/arm-9tdmi-linux-gnu/lib/libc.so.6 lib/ (複製C library。以上命令請勿斷行)

Busybox 會因版本與功能選項設定的差異,而需要更多的程式庫。請使用 cross toolchain objdump 指令來檢查 Busybox 的程式庫相依問題(無法使用 ldd 指令),並將所需的程式庫由 toolchain 複製到 root filesystem lib/ 目錄下。

Step 6:加入系統檔案

加入2個重要的系統檔案於 etc/ 目錄下:

˙ fstabmount table

˙ inittab:系統初始表(init table)。

etc/fstab內容如下:

/dev/ram0 / ext2 defaults 1 1

none /proc proc defaults 0 0

/dev/ram1 /tmp ramfs defaults 0 0

/dev/ram2 /var ramfs defaults 0 0

fstab 第一行設定,目的在將 /dev/ram0 重新附掛成 ‘/’root),此動作用意在於重新指定 ‘/’ 的檔案系統為 ext2。最後二行的目的是為了以 ramfs mount 要的二個目錄:/var /tmp;如此一來,就算開機沒做 remount root(詳見後文說明),也能對 /tmp /var 目錄做寫入的動作

etc/inittab內容如下:

:0:sysinit:/etc/rc.d/rc.init

:0:respawn:/bin/sh

根據這個 inittab 設定,當系統開機後便會進入 run level 0,在 run level 0 模式下,init process會執行2個動作:(1) 執行 /etc/rc.d/rc.init,此即「init script」;(2) 執行 /bin/sh,即進入 shell 模式。

在此我們並沒有參照 LSB 的標準來設定 run level,而且也沒有使用 getty 來讓使用者登入(多使用者模式)。

Step 7:編寫 Initial Script

根據 inittab 的設定,我們 root filesystem init script 位於 /etc/rc.d/rc.init。以下提供一個供 Embedded Linux 使用的 init script 範本:

#!/bin/sh

# automount (/etc/fstab)

mount -a

# remount root

mount -o remount rw /

#

mkdir /var/lock

mkdir /var/lock/subsys

mkdir /var/run

# start other applications (Running application automatically during

# booting up.

# eg. /bin/thttpd –p 80 –d /var/www

當我們執行「mount –a」後,mount 便會去讀取前一步驟所設定的 fstab,並根據此表格的內容來做 mount 的動作。另外,這裡有一個 remount 的動作:

# mount -o remount rw /

此動作的目的是將 root’/’)重新 mount 成可讀寫,此動作是選擇性的,若省略不做,請務必保持 /var /tmp 目錄是能寫入的(建議以 ramdisk 方式實作為佳)。

root filesystem 未包含 inittab 設定檔,則 Busybox 會使用以下的內建設定:

::sysinit:/etc/init.d/rcS

::askfirst:/bin/sh

::ctrlaltdel:/sbin/reboot

::shutdown:/sbin/swapoff -a

::shutdown:/bin/umount -a -r

::restart:/sbin/init

不過,還是建議編寫自己的 inittab 定檔。

Step 8:製作 Root Filesystem 映像檔(Image File

截至目前為止,我們的檔案系統已經擁有基本的系統指令與工具。接下來,我們即可將建置完成的 root filesystem 製作成 ext2 格式的映像檔。

以下提供二種 ext2fs image file 的製作方式:(1) 土方法;(2) 使用 genext2fs 工具。

先說明傳統的土方法。首先,先利用dd指令做出一個空白的檔案,大小為 4Mbytes):

# dd if=/dev/zero of=ext2fs bs=1k count=4096

我們將檔案命名為 ext2fs,接著再將 ext2fs 製作成 ext2 格式的檔案系統:

# mkfs.ext2 ext2fs

mke2fs 1.3209-Nov-2002

ext2fs is not a block special device.

Proceed anyway?yny

選擇y後出現以下畫面:

Filesystem label=

OS type Linux

Block size=1024log=0

Fragment size=1024log=0

128 inodes 1024 blocks

51 blocks4.98%reserved for the super user

First data block=1

1 block group

8192 blocks per group 8192 fragments per group

128 inodes per group

Writing inode tables done

Writing superblocks and filesystem accounting information done

This filesystem will be automatically checked every 26 mounts or

180 days whichever comes first. Use tune2fs -c or -i to override.

到這裡我們已經做好一個檔案格式為 ext2 的空白映像檔,再來只要將先前做好的 root filesystem 全部複製到 ext2fs 映像檔「裡面」即可。

先將 ext2fs 附掛至任一空目錄,例如 mnt/

# mkdir mnt/

# mount -t ext2 -o loop ext2fs mnt/ (指定檔案系統為 ext2

複製檔案系統時,我們不使用 cp 指令,而是利用 tar 來完成:

# cd install/

# tar cz * > ../install.tar.gz (將檔案系統做成tarball,同時也備份 root filesystem。)

# cd ..

# cd mnt/

# tar zxvf ../install.tar.gz (再將tarball解至映像檔)

接著將映像檔 umount 並壓縮即可:

# cd ..

# umount mnt/

# gzip -9c ext2fs > pub/ext2fs.gz

最後得到的 ext2fs.gz 即是完成品。請注意,若不使用 tar 來說,也應該使用 cpio 來複製檔案,避免使用 cp 指令。

使 genext2fs

genext2fs 是一個 ext2 filesystem image file 的製作工具,可以讓我們很方便地將 root filesystem 製作成 image 檔。請由 genext2fs 的官方網站下載原始碼套件:

http://genext2fs.sourceforge.net/

編譯後可以取得 genext2fs 檔案,以下是將 install/ 目錄製作成 ext2fs image 檔的指令:

# genext2fs -b 8192 -i 1024 -d install/ ext2fs

執行後,會得到檔名為 ext2fs image 檔,大小為 8 MB(透過 ‘-b’ 參數指定 image file 大小);接著同樣再用 gzip ext2fs 檔壓縮即可。

Step 9:在 Target 端做測試

本步驟以 Jollen-Kit! 為例,Jollen-Kit! 是由 www.jollen.org 所推出的 ARM9 training board,詳細介紹請參考 [http://www.jollen.org/kit/]。請注意,本階段的操作,視 target device 的不同而不同,因此以下示範只適用於 Jollen-Kit! 或是其他的 SMDK2410 平臺。

步驟 8 所得到的 ext2.gz 必須再包裝成 U-Boot 的格式,才能透過 U-Boot 載入到 RAM,以成為 kernel initial ramdiskinitrd):

# mkimage -A arm -O linux -T ramdisk -C none -a 0x30800000 -e 0x30800000 -n ramdisk -d ext2fs.gz urootfs.img

執行後可得到 urootfs.img 檔案,在測試階段為了方便起見,我們可以直接將 urootfs.img 載到 RAM 做測試;U-Boot 指令如下:

jollen.org # tftpboot 32000000 urootfs.img; tftpboot 30F00000 uimage.img; bootm 30F00000 32000000

urootfs.img 是我們製作的 root filesystemuimage.img 則是給 Jollen-Kit! 使用的 Linux kernelpre-built)。

延伸閱讀

--jollen

引用自:http://www.jollen.org/cgi-bin/mt3/mt-tb.cgi/339