Linux系統移植

Linux系統移植
目 錄
第一部分 前言...................................................................................................................................8
1 硬件環境.....................................................................................................................................8
1.1主機硬件環境.......................................................................................................................8
1.2 目標板硬件環境...................................................................................................................8
1.3工具介紹...............................................................................................................................8
2軟件環境......................................................................................................................................8
2.1主機軟件環境.......................................................................................................................8
2.1.1 Windows 操作系統.......................................................................................................8
2.1.2 Linux操作系統 .......................................................................................................8
2.1.3 目標板最後運行的環境...............................................................................................9
2.2 Linux下工作用戶及環境....................................................................................................9
2.2.1 交叉工具的安裝...........................................................................................................9
2.2.2 uboot
移植工作目錄....................................................................................................9
2.2.3 內核及應用程序移植工作...........................................................................................9
2.3 配置系統服務.....................................................................................................................10
2.3.1 tftp服務器的配置.......................................................................................................10
2.4 工具使用.............................................................................................................................12
2.4.1 minicom的使用..........................................................................................................12
3 作者介紹...................................................................................................................................13
3.1 策劃, 組織, 指導, 發佈者...................................................................................................13
3.2 ADS bootloader部分..........................................................................................................13
3.3 交叉工具部分.....................................................................................................................13
3.4 uboot部分...........................................................................................................................13
3.5 內核部分.............................................................................................................................13
3.6 應用程序部分.....................................................................................................................13
3.7 網卡驅動部分.....................................................................................................................13
3.8 Nand Flash 驅動部分.........................................................................................................13
第二部分 系統啓動bootloader的編寫(ADS).................................................................................14
1 工具介紹...................................................................................................................................14
1.1 ADS 命令行命令介紹........................................................................................................14
1.1.1 armasm........................................................................................................................14
1.1.2 armcc, armcpp.............................................................................................................14
1.1.3 armlink........................................................................................................................14
2 基本原理...................................................................................................................................15
2.1 可執行文件組成及內存映射.............................................................................................15
2.1.1 可執行文件的組成.....................................................................................................15
2.1.2 裝載過程.....................................................................................................................16
2.1.3 啓動過程的彙編部分.................................................................................................17
2.1.4 啓動過程的C部分.....................................................................................................17
3 AXD的使用以及源代碼說明...................................................................................................18
3.1 源代碼說明.........................................................................................................................18
3.1.1 彙編源代碼說明.........................................................................................................18
3.1.2 C語言源代碼說明......................................................................................................23
3.1.3 源代碼下載.................................................................................................................23
3.2 AXD的使用.......................................................................................................................23
3.2.1 配置仿真器.................................................................................................................23
3.2.2 啓動AXD 配置開發板...............................................................................................23
第三部分 GNU交叉工具鏈.............................................................................................................25
1 設置環境變量,準備源碼及相關補丁...................................................................................25
1.1 設置環境變量.....................................................................................................................25
1. 2 準備源碼包............................................................................................................................25
1.2.1 binuils.........................................................................................................................25
1.2.2 gcc..............................................................................................................................25
1.2.3 glibc............................................................................................................................25
1.2.4 linux kernel..................................................................................................................26
1.3 準備補丁.............................................................................................................................26
1.3.1 ioperm.c.diff................................................................................................................26
1.3.2 flow.c.diff....................................................................................................................26
1.3.3 tlinux.
diff....................................................................................................................26
1.4 編譯 GNU binutils...........................................................................................................26
1.5 準備內核頭文件.................................................................................................................26
1.5.1 使用當前平臺的gcc編譯內核頭文件......................................................................26
1.5.2 複製內核頭文件.........................................................................................................27
1.6 譯編glibc頭文件.............................................................................................................27
1.7 編譯gcc第一階段............................................................................................................27
1.8 編譯完整的glibc..............................................................................................................27
1.9 編譯完整的gcc.................................................................................................................28
2 GNU交叉工具鏈的下載...........................................................................................................28
2.1 ARM官方網站...................................................................................................................28
2.2 本文檔提供的下載.............................................................................................................28
3 GNU交叉工具鏈的介紹與使用...............................................................................................29
3.1 常用工具介紹.....................................................................................................................29
3.2.1 armlinuxgcc
的使用.................................................................................................29
3.2.2 armlinuxar
和 armlinuxranlib
的使用..................................................................30
3.2.3 armlinuxobjdump
的使用.........................................................................................30
3.2.4 armlinuxreadelf
的使用............................................................................................31
3.2.6 armlinuxcopydump
的使用......................................................................................32
4 ARM GNU常用彙編語言介紹.................................................................................................32
4.1 ARM GNU常用匯編僞指令介紹.....................................................................................32
4.2 ARM GNU專有符號.........................................................................................................33
4.3 操作碼................................................................................................................................33
5 可執行生成說明........................................................................................................................33
5.1 lds文件說明.......................................................................................................................33
5.1.1 主要符號說明.............................................................................................................33
5.1.2 段定義說明.................................................................................................................34
第四部分 uboot
的移植...................................................................................................................35
1 uboot
的介紹及系統結構.........................................................................................................35
1.1 uboot
介紹.........................................................................................................................35
1.2 獲取uboot.........................................................................................................................
35
1.3 uboot
體系結構.................................................................................................................35
1.3.1 uboot
目錄結構..........................................................................................................35
2 uboot的啓動過程及工作原理...................................................................................................36
2.1 啓動模式介紹.....................................................................................................................36
2.2 階段1介紹.........................................................................................................................36
2.2.1 定義入口.....................................................................................................................36
2.2.2 設置異常向量.............................................................................................................37
2.2.3 設置CPU的模式爲SVC模式..................................................................................37
2.2.4 關閉看門狗.................................................................................................................37
2.2.5 禁掉所有中斷.............................................................................................................37
2.2.6 設置以CPU的頻率....................................................................................................37
2.2.7 設置CP15...................................................................................................................37
2.2.8 配置內存區控制寄存器.............................................................................................38
2.2.9 安裝UBOOT
使的棧空間........................................................................................38
2.2.10 BSS段清0................................................................................................................38
2.2.11 搬移Nand Flash代碼...............................................................................................39
2.2.12 進入C代碼部分.......................................................................................................39
2.3 階段2的C語言代碼部分 .............................................................................................39
2.3.1調用一系列的初始化函數.........................................................................................39
2.3.2 初始化網絡設備.........................................................................................................41
2.3.3 進入主UBOOT命令行..............................................................................................41
2.4 代碼搬運.............................................................................................................................41
3 uboot的移植過程.......................................................................................................................42
3.1 環境....................................................................................................................................42
3.2 步驟....................................................................................................................................42
3.2.1 修改Makefile..............................................................................................................42
3.2.2 在board子目錄中建立crane2410.............................................................................42
3.2.3 在include/configs/中建立配置頭文件......................................................................42
3.2.4 指定交叉編譯工具的路徑.........................................................................................42
3.2.5 測試編譯能否成功.....................................................................................................42
3.2.6 修改lowlevel_init.S文件...........................................................................................43
3.2.9 UBOOT的Nand Flash移植......................................................................................45
3.2.8重新編譯uboot..........................................................................................................
45
3.2.9 把uboot
燒入flash....................................................................................................45
4 UBOOT
命令的使用................................................................................................................46
4.1 UBOOT
命令的介紹.........................................................................................................46
4.1.1 獲得幫助信息.............................................................................................................46
4.2 常用命令使用說明.............................................................................................................47
4.2.1 askenv(F).....................................................................................................................47
4.2.2 autoscr........................................................................................................................47
4.2.3 base ...........................................................................................................................47
4.2.4 bdinfo..........................................................................................................................47
4.2.5 bootp...........................................................................................................................47
4.2.8 tftp(tftpboot)................................................................................................................48
4.2.9 bootm..........................................................................................................................48
4.2.10 go..............................................................................................................................48
4.2.11 cmp .........................................................................................................................48
4.2.12 coninfo .....................................................................................................................48
4.2.13 cp..............................................................................................................................48
4.2.14 date...........................................................................................................................49
4.2.15 erase(F)......................................................................................................................49
4.2.16 flinfo(F).....................................................................................................................49
4.2.17 iminfo........................................................................................................................49
4.2.18 loadb..........................................................................................................................49
4.2.19 md.............................................................................................................................49
4.2.20 mm ............................................................................................................................50
4.2.21 mtest .......................................................................................................................50
4.2.22 mw.............................................................................................................................50
4.2.23 nm ...........................................................................................................................50
4.2.24 printenv......................................................................................................................50
4.2.25 ping ..........................................................................................................................51
4.2.26 reset..........................................................................................................................51
4.2.27 run ...........................................................................................................................51
4.2.28 saveenv(F).................................................................................................................51
4.2.29 setenv.........................................................................................................................51
4.2.30 sleep..........................................................................................................................51
4.2.31 version.......................................................................................................................51
4.2.32 nand info....................................................................................................................51
4.2.33 nand device <n>........................................................................................................51
4.2.34 nand bad....................................................................................................................51
4.2.35 nand read...................................................................................................................52
4.2.36 nand erease................................................................................................................52
4.2.37 nand write..................................................................................................................52
4.3 命令簡寫說明.....................................................................................................................52
4.4 把文件寫入NandFlash.......................................................................................................53
4.5 下載提供.............................................................................................................................53
5 參考資料...................................................................................................................................53
第五部分 linux 2.6內核的移植.......................................................................................................53
1 內核移植過程............................................................................................................................53
1.1 下載linux內核...................................................................................................................53
1.2 修改Makefile.....................................................................................................................53
1.3 設置flash分區...................................................................................................................54
1.3.1指明分區信息.............................................................................................................54
1.3.2 指定啓動時初始化.....................................................................................................56
1.3.3 禁止Flash ECC校驗 ................................................................................................56
1.4 配置內核.............................................................................................................................56
1.4.1 支持啓動時掛載devfs................................................................................................56
1.4.2配置內核產生.config文件.........................................................................................57
1.4.3編譯內核.....................................................................................................................58
1.4.4 下載zImage到開發板................................................................................................58
2 創建uImage...............................................................................................................................61
2.1 相關技術背景介紹.............................................................................................................61
2.2 在內核中創建uImage的方法...........................................................................................61
2.2.1 獲取mkimage工具.....................................................................................................61
2.2.2 修改內核的Makefile文件.........................................................................................61
3追加實驗記錄.............................................................................................................................62
3.1移植linux2.6.15.7..............................................................................................................
62
3.2移植linux2.6.16.21............................................................................................................
62
3.3 移植linux2.6.17................................................................................................................
62
4 參考資料...................................................................................................................................62
第六部分 應用程序的移植..............................................................................................................63
1構造目標板的根目錄及文件系統.............................................................................................63
1.1 建立一個目標板的空根目錄.............................................................................................63
1.2 在my_rootfs中建立Linux目錄樹...................................................................................63
1.3 創建linuxrc文件................................................................................................................63
2 移植Busybox............................................................................................................................64
2.1 下載busybox......................................................................................................................64
2.3 編譯並安裝Busybox..........................................................................................................65
3 移植TinyLogin..........................................................................................................................66
3.1 下載....................................................................................................................................66
3.2 修改tinyLogin的Makefile................................................................................................66
3.3 編譯並安裝.........................................................................................................................66
4 相關配置文件的創建................................................................................................................66
4.1 創建帳號及密碼文件.........................................................................................................66
4.2 創建profile文件................................................................................................................67
4.4 創建fstab文件...................................................................................................................67
4.5 創建inetd.conf配置文件...................................................................................................67
5 移植inetd...................................................................................................................................67
5.1 inetd的選擇及獲取............................................................................................................67
5.1.1 獲取inetd....................................................................................................................67
5.2 編譯inetd...........................................................................................................................67
5.2.1 修改configure文件....................................................................................................67
5.2.2 編譯 ...........................................................................................................................68
5.3 配置inetd...........................................................................................................................68
5.3.1 拷貝inetd到根文件系統的usr/sbin目錄中.............................................................68
6 移植thttpd Web服務器.............................................................................................................69
6.1 下載....................................................................................................................................69
6.2 編譯thttpd..........................................................................................................................69
6.3 配置....................................................................................................................................69
6.3.1 拷貝thttpd二進制可執行文件到根文件系統/usr/sbin/目錄中...............................69
6.3.2 修改thttpd配置文件..................................................................................................69
6.3.3 轉移到根文件系統目錄,創建相應的文件.............................................................69
7 建立根目錄文件系統包............................................................................................................70
7.1 建立CRAMFS包...............................................................................................................70
7.1.1 下載cramfs工具........................................................................................................70
7.1.2 製作cramfs包............................................................................................................70
7.1.3 寫cramfs包到Nand Flash.........................................................................................70
8 參考資料...................................................................................................................................70
第七部分 Nand flash驅動的編寫與移植........................................................................................71
1 Nand flash工作原理..................................................................................................................71
1.1 Nand flash芯片工作原理..................................................................................................71
1.1.1 芯片內部存儲佈局及存儲操作特點.........................................................................71
1.1.2 重要芯片引腳功能.....................................................................................................71
1.1.3 尋址方式.....................................................................................................................71
1.1.4 Nand flash主要內設命令詳細介紹...........................................................................72
1.2 Nand Flash 控制器工作原理.............................................................................................72
1.2.1 Nand Flash控制器特性..............................................................................................72
1.2.2 Nand Flash控制器工作原理......................................................................................72
1.3 Nand flash 控制器中特殊功能寄存器詳細介紹 ............................................................72
1.4 Nand Flash 控制器中的硬件ECC介紹............................................................................73
1.4.1 ECC產生方法............................................................................................................73
1.4.2 ECC生成器工作過程................................................................................................74
1.4.3 ECC的運用................................................................................................................74
2 在ADS下flash燒寫程序.........................................................................................................74
2.1 ADS下flash燒寫程序原理及結構...................................................................................74
2.2 第三層實現說明.................................................................................................................74
2.1.1 特殊功能寄存器定義.................................................................................................74
2.1.2 操作的函數實現.........................................................................................................74
2.3 第二層實現說明.................................................................................................................75
2.3.1 Nand Flash 初始化......................................................................................................75
2.3.3 獲取Nand flash ID......................................................................................................75
2.3.4 Nand flash寫入...........................................................................................................76
2.3.5 Nand flash讀取...........................................................................................................77
2.3.6 Nand flash標記壞塊...................................................................................................78
2.3.7 Nand Flash檢查壞塊..................................................................................................79
2.3.8 擦除指定塊中數據.....................................................................................................79
2.4 第一層的實現....................................................................................................................80
3 在UBOOT
對Nand Flash的支持............................................................................................82
3.1 UBOOT
對從Nand Flash啓動的支持.............................................................................82
3.1.1 從Nand Flash啓動UBOOT
的基本原理................................................................82
3.1.2 支持Nand Flash啓動代碼說明.................................................................................82
3.2 UBOOT
對Nand Flash命令的支持.................................................................................84
3.2.1 主要數據結構介紹.....................................................................................................84
3.2.2 支持的命令函數說明.................................................................................................85
4 在Linux對Nand Flash的支持.................................................................................................87
4.1 Linux下Nand Flash調用關係..........................................................................................87
4.1.1 Nand Flash設備添加時數據結構包含關係..............................................................87
4.1.2 Nand Flash設備註冊時數據結構包含關係..............................................................87
4.2 Linux下Nand Flash驅動主要數據結構說明..................................................................88
4.2.1 s3c2410專有數據結構...............................................................................................88
4.2.2 Linux 通用數據結構說明..........................................................................................89
4.3.1 註冊driver_register....................................................................................................94
4.3.2 探測設備probe...........................................................................................................94
4.3.3 初始化Nand Flash控制器.........................................................................................94
4.3.4 移除設備.....................................................................................................................94
4.3.5 Nand Flash芯片初始化..............................................................................................94
4.3.6 讀Nand Flash............................................................................................................95
4.3.7 寫Nand Flash.............................................................................................................95
第八部分 Cs8900a網卡驅動的編寫與移植...................................................................................95
1 Cs8900a工作原理......................................................................................................................95
2 在ADS下cs8900a的實現........................................................................................................95
2.1 在cs8900a下實現的ping 工具.........................................................................................95
3 在uboot
下cs8900a的支持......................................................................................................96
3.1 uboot
下cs8900a的驅動介紹...........................................................................................96
3.2 uboot
下cs8900a的移植說明...........................................................................................96
4 在linux下cs8900a驅動的編寫與移植....................................................................................96
4.1 Linux下cs8900a的驅動說明............................................................................................96
4.2 Linux 下cs8900a的移植說明...........................................................................................96
4.2.1 爲cs8900a建立編譯菜單..........................................................................................96
4.2.2 修改S3C2410相關信息............................................................................................97

該文檔的目的是總結我們在工作中的一些經驗,並把它們分享給喜歡ARM和Linux的朋友, 如有錯誤
之處,請大家多多指點. 同樣, 我們也希望更多人能把自己的工作經驗和體會加入該文檔,讓大家共同進步.
該文檔是一份交流性文檔, 只供個人學習與交流,不允許公司和企業用於商業行爲.
第一部分 前言
1 硬件環境
1.1主機硬件環境
開發機:Pentium-4 CPU
內存: 512MB
硬盤: 60GB
1.2 目標板硬件環境
CPU: S3C2410
SDRAM: HY57V561620
Nand flash: K9F1208U0B(64MB)
以太網芯片:CS8900A (10M/100MB)
1.3工具介紹
仿真器:Dragon-ICE
電纜:串口線,並口線
2軟件環境
2.1主機軟件環境
2.1.1 Windows 操作系統
ADS編譯工具:ADS1.2
仿真器軟件: Dragon-ICE daemon程序
2.1.2 Linux操作系統
GNU交叉編譯工具:
2.95.3:
作用:編譯u-boot
3.3.2, 3.4.4:
作用:編譯內核和應用程序
其它工作:
tree工具:
作用:查看文件目錄樹
下載:從ftp://mama.indstate.edu/linux/tree/下載編譯
2.1.3 目標板最後運行的環境
啓動程序:
u-boot-1.1.4
內核:
linux-2.6.14.1
應用程序:
1. busybox-1.1.3
2. TinyLogin-1.4
3. Thttpd-2.25
2.2 Linux下工作用戶及環境
2.2.1 交叉工具的安裝
工具鏈的編譯過程請參考第三部分.
1. 下載交叉工具
2.95.3 下載地址:ftp://ftp.arm.linux.org.uk/pub/armlinux/toolchain/cross-
2.95.3.tar.bz2
3.3.4 下載地址:
2. 編譯交叉工具
[root@localhost ~]mkdir /usr/local/arm
[root@localhost ~]cd /usr/local/arm
把cross-2.95.2.tar.bz2, cross-3.4.4.tar.gz 拷貝到/usr/local/arm目錄中。解壓這兩個包。
[root@localhost ~]tar -xjvf cross-2.95.2.tar.bz2
[root@localhost ~]tar -xzvf cross-3.4.4.tar.gz
2.2.2 u-boot移植工作目錄
1. 添加工作用戶
[root@localhost ~]#useradd -G root -g root -d/home/uboot uboot
2. 建立工作目錄
[uboot@localhost ~]$mkdir dev_home
[uboot@localhost ~]$cd dev_home
[uboot@localhost dev_home]$mkdir doc mybootloader uboot
.
|-- doc
|-- mybootloader
`-- uboot
3. 建立環境變量
[uboot@localhost ~]vi ~/.bashrc
export PATH=/usr/local/arm/2.95.3/bin:$PATH
2.2.3 內核及應用程序移植工作
1. 添加工作用戶
[root@localhost ~]#useradd -G root -g root -d/home/arm arm
2. 建立工作目錄
[arm@localhost arm]$mkdir dev_home
[arm@localhost arm]$cd dev_home
[arm@localhost arm]$mkdir bootldr btools debug doc images kernel localapps /
rootfs sysapps tmp tools
[arm@localhost arm]$tree -L 1
.
|-- bootldr
|-- btools
|-- debug
|-- doc
|-- images
|-- kernel
|-- localapps
|-- rootfs
|-- sysapps
|-- tmp
`-- tools
可以看到如上樹形結構。
注:tree命令
3. 建立環境變量設置腳本
[arm@localhost arm]$vi env_sh
#!/bin/bash
PRJROOT=~/dev_home
KERNEL=$PRJROOT/kernel
ROOTFS=$PRJROOT/rootfs
LAPP=$PRJROOT/localapps
DOC=$PRJROOT/doc
TMP=$PRJROOT/tmp
export PRJROOT KERNEL LAPP ROOTFS
export PATH=/usr/local/arm/3.4.4/bin:$PATH
4. 登陸時啓動環境變量
[arm@localhost arm]$vi ~/.bashrc
. ~/dev_home/env_sh
重新登陸arm用戶,環境變量生效
[arm@localhost arm]$su arm
2.3 配置系統服務
2.3.1 tftp服務器的配置
如果用下面一條命令能夠看到服務已經啓動, 則不用安裝, 否則需要按1或2點安裝tftp-server服務器.
[arm@localhost arm]#netstat -a | grep tftp
udp 0 0 *:tftp *:*
1. 從RPM包安裝tftp-server
從對應Linux操作系統版本的安裝光盤上找到tftp-server的安裝包.
下面tftp-server-0.32-4.i386.rpm包爲例,把rpm包拷貝到dev_home/btools/下.
[arm@localhost arm]#cp tftp-server-0.32-4.i386.rpm /home/arm/dev_home/btools/
[arm@localhost arm]#su root
[root@localhost arm]#rpm -q tftp-server
如果沒有安裝tftp-server,就要用下面命令安裝,否則,直接進入第2步配置服務.
[root@localhost arm]#cd /home/arm/dev_home/btools/
[root@localhost btools]#rpm -ivh tftp-server-0.32-4.i386.rpm
建立tftp的主工作目錄
[root@localhost btools]#mkdir /tftpboot
2. 修改配置文件並啓動服務
備份配置文件
[root@localhost btools]#if [ -f /etc/xinetd.d/tftp ]
> then
> cp /etc/xinetd.d/tftp /etc/xinetd.d/tftp.old
> fi
修改配置文件
[root@localhost btools]#vi /etc/xinetd.d/tftp
service tftp
{
disable = no
socket_type = dgram
protocol = udp
wait = yes
user = root
server = /usr/sbin/in.tftpd
server_args = -s /tftpboot
per_source = 11
cps = 100 2
flags = IPv4
}
檢查tftp服務是否打開
[root@localhost btools]#chkconfig --list
如果tftp的服務沒有打開,則用下面命令打開tftp服務開關
[root@localhost btools]#chkconfig tftp on
重啓服務
#/etc/init.d/xinetd restart
#netstat -a | grep tftp
udp 0 0 *:tftp *:*
2.3.2 NFS服務器的配置
1. 安裝NFS服務器
[root@localhost btools]#rpm -q nfs-utils
如果沒有安裝,從對應Linux操作系統版本的安裝光盤上找到nfs-utils的安裝包.Fedora 5中的安裝包
名稱爲nfs-utils-1.0.8.rc2-4.FC5.2.i386.rpm。下面以該安裝包爲例說明:
[root@localhost btools]#rpm -ivh nfs-utils-1.0.8.rc2-4.FC5.2.i386.rpm
2. 配置NFS服務器
[root@localhost btools]#vi /etc/exports
#加入要允許被另外計算機mount的目錄:
#/home/arm/dev_home/tmp 爲被另外計算機mount的目錄
#192.168.1.134 允許另外計算機mount的IP
#rw,sync,no_root_squash表示訪問限制,更詳細說明見相關手冊.
/home/arm/dev_home/tmp 192.168.1.134(rw,sync,no_root_squash)
3. 啓動NFS服務器
第一啓動NFS服務器時用下面命令.
[root@localhost btools]#/etc/init.d/nfs start
如果你已經啓動了NFS服務器時,並且重新修改了/etc/exports文件,用如下命令使新加入的目錄生效:
[root@localhost btools]#/etc/init.d/nfs reload
4. 測試NFS服務器
[root@localhost btools]#netstat -a | grep nfs
5. 顯示被export出的目錄列表
[root@localhost btools]#exportfs
2.4 工具使用
2.4.1 minicom的使用
1.切換到root用戶.
[root@localhost btools]#su -
2. 查找有效的串設備.
[root@localhost ~]#cat /proc/devices
...
4 ttyS
...
188 ttyUSB
...
如果是普通串口設備, 設備名前綴爲ttyS, 第一串口爲ttyS0, 第二串口爲ttyS1,依次類推.
如果是USB轉串口的設備, 設備名前綴爲ttyUSB, 第一串口爲ttyUSB0.
3. 配置ttyUSB設備
[root@localhost ~]#minicom -s ttyUSB0
會出現一個configuration窗口,
┌──[configuration]────┐
│ Filenames and paths │
│ File transfer protocols │
│ Serial port setup │
│ Modem and dialing │
│ Screen and keyboard │
│ Save setup as ttyUSB0 │
│ Save setup as.. │
│ Exit │
│ Exit from Minicom │
└───────────────┘
選擇Serial port setup配置. 會出現如下窗口:
┌────────────────────────────────────────────┐
│ A - Serial Device : /dev/ttyUSB0 │
│ B - Lockfile Location : /var/lock │
│ C - Callin Program : │
│ D - Callout Program : │
│ E - Bps/Par/Bits : 115200 8N1 │
│ F - Hardware Flow Control : No │
│ G - Software Flow Control : No │
│ │
│ Change which setting? │
└───────────────────────────────────────────┘
我的設置如上所示, 設置完成後, Change which setting?項上按回車退出當前窗口, 回到第一個窗口.按 Save
setup as ttyUSB0保存設置. 再按Exit from Minicom退出Minicom.
4. 啓動minicom
[root@localhost ~]#minicom
3 作者介紹
3.1 策劃, 組織, 指導, 發佈者
劉勇
email: [email protected]
如果您有新的內容,請發到這個電子郵件,我們會把您的內容加入文檔,並在作者列表中加入您的名字.
3.2 ADS bootloader部分
作者:劉勇
email: [email protected]
3.3 交叉工具部分
作者:孫賀
email: [email protected]
3.4 uboot部分
作者:聶強
email: [email protected]
作者:孫賀
email: [email protected]
3.5 內核部分
作者:聶大鵬
email:[email protected]
作者:牛須樂(8900a網卡移植部分)
email:[email protected]
3.6 應用程序部分
作者:聶大鵬
email:[email protected]
3.7 Nand Flash 驅動部分
作者:孫磊,劉勇
email:[email protected]
4 支持企業
4.1 尚觀科技
爲我們提供統許多套遠峯公司的ARM開發板, 才能讓我們做出統一的文檔.
第部分 系統啓動bootloader的編寫(ADS)
1 工具介紹
1.1 ADS 命令行命令介紹
1.1.1 armasm
1. 命令:armasm [選項] -o 目標文件 源文件
2. 選項說明
-Errors 錯誤文件名 ;指定一個錯誤輸出文件
-I 目錄[,目錄] ;指定源文件搜索目錄
-PreDefine 預定義宏 ;指定預定義的宏
-NOCache ;編譯源代碼時禁止使用Cache進行優化
-MaxCache <n> ;編譯源代碼時使用Cache進行優化
-NOWarn ;關閉所有的警告信息
-G ;輸出調試表
-keep ;在目標文件中保存本地符號表
-LIttleend ;生成小端(Little-endian) ARM代碼
-BIgend ;生成大端(Big-endian) ARM代碼
-CPU <target-cpu> ;設立目標板ARM核類型,如: arm920t.
-16 ;建立16位的thumb指令.
-32 ;建立32位的ARM指令.
3. 編譯一個彙編文件
c:/adsloader>armasm -LIttleend -cpu ARM920T -32 bdinit.s
把彙編語言編譯成小端, 32位, ARM920T CPU.
1.1.2 armcc, armcpp
1. 命令:armcc [選項] 源文件1 源文件2 ... 源文件n
2. 選項說明
-c ;編譯但是不連接
-D ;指定一個編譯時使用的預定義宏常量
-E ;僅僅對C源文件做預處理
-g ;產生調試信息表
-I ;指頭文件的搜索路徑
-o<file> ;指定一個輸出的目標文件
-O[0/1/2] ;指定源代碼的優化級別
-S ;輸出彙編代碼來代替目標文件
-CPU <target-cpu> ;設立目標板ARM核類型,如: arm920t.
3.編譯一個C程序
c:/adsloader>armcc -c -O1 -cpu ARM920T bdisr.c
編譯不連接, 二級優化, ARM920T CPU.
1.1.3 armlink
1. 命令:armlink [選項] 輸入文件
2. 選項說明
-partial ;合併目標文件
-Output 文件 ;指定輸出文件名
-scatter 文件 ;按照指定的文件爲可執行文件建立內存映射
-ro-base 地址值 ;只讀代碼段的起始地址
-rw-base 地址值 ;RW/ZI段的起始地址
3. 把多個目標文件合併成一個目標文件
c:/adsloader>armlink -partial bdmain.o bdport.o bdserial.o bdmmu.o bdisr.o -o
bd.o
4. 把幾個目標文件編譯一個可執地文件
c:/adsloader>armlink bd.o bdinit.o -scatter bdscf.scf -o bd.axf
1.1.4 fromelf
1. 命令:fromelf [選項] 輸入文件
2. 選項說明
-bin 二進制文件名 ;產生的二進制文件
-elf elf文件名 ;產生一個elf文件
-text text文件名 ;產生text文件
3. 產生一個可執行的二進制代碼
c:/adsloader>fromelf bd.axf bin
o
bd.bin
2 基本原理
2.1 可執行文件組成及內存映射
2.1.1 可執行文件的組成
在ADS下,可執行文件有兩種,一種是.axf文件,帶有調試信息,可供AXD調試工具使用.另一種是.bin
文件,可執行的二進制代碼文件。我們重點是講描.bin文件的組成。
我們把可執行文件分爲兩種情況:分別爲存放態和運行態。
1. 存放態
存放態是指可執行文件通過fromelf產生後,在存儲介質(flash或磁盤)上的分佈. 此時可執行文件一
般由兩部分組成:分別是代碼段和數據段。代碼段又分爲可執行代碼段(.text)和只讀數據段(.rodata),
數據段又分爲初始化數據段(.data)和未初始化數據段(.bss)。可執行文件的存放態如下:
+-------------+-----------
| .bss |
+-------------+-- 數據段
| .data |
+-------------+-----------
| .rodata |
|_____________| 代碼段
| .text |
+-------------+-----------
2. 運行態
可執行文件通過裝載過程, 搬入到RAM中運行, 這時候可執行文件就變成運行態。在ADS下對可執行代
碼各段有另一個名稱:
| ... |
+-------------+-----------
| .bss | ZI 段
+-------------+-- 數據段
| .data | RW 段
+-------------+-----------
| .rodata |
|_____________| 代碼段(RO 段)
| .text |
+-------------+-----------
| ... |
裝載前
當可執行文件裝載後, 在RAM中的分佈如下:
| ... |
+-------------+-- ZI段結束地址
| ZI 段 |
+-------------+-- ZI段起始地址
| 保留區2 |
+-------------+-- RW段結束地址
| RW 段 |
+-------------+-- RW段起始地址
| 保留區1 |
+-------------+-- RO段結束地址
| RO 段 |
+-------------+-- RO段起始地址
| ... |
裝載後
所以裝載過程必須完成把執行文件的各個段從存儲介質上搬到RAM指定的位置。而這個裝載過程由誰來完
成呢?由我們的啓動程序來完成.
2.1.2 裝載過程
在ADS中,可以通過兩種方式來指定可執行代碼各段在RAM中的位置,一個是用armlink來指定,一種是
用scatter文件來指定.RAM區的起始地址:0x30000000.
1. armlink指定代碼段地址
我們通常的代碼,只用指定兩個段開始地址, RO段的起始地址和RW段的起始地址, ZI段緊接在RW段之
後.示例見該部分的1.1.3.
2. scatter指定代碼段地址
我們也可以通過scatter文件指定可執行文件各段的詳細地址. Scatter文件如下:
MYLOADER 0x30000000
;MYLOADER: 爲可執行文件的名稱, 可自定義
;0x3000000: 起始地址
{
RO 0x30000000
;RO 只讀代碼段的名稱
;0x30000000: 只讀代碼段的起始地址
{
init.o (Init, +First)
; Init代碼段爲可執行文件的第一部分.
* (+RO) ;所有其它的代碼段和只讀數據段放在該部分
}
RW +0
;RW: RW段的名稱
;+0: 表示RW段緊接着RO段
{
* (+RW) ;所有RW段放在該部分
}
ZI +0
;ZI: ZI段的名稱
;+0: 表示ZI段緊接着RW段
{
*(+ZI) ;所有ZI段放在該部分
}
}
3. ADS產生的各代碼段宏
|Image$$RO$$Base| /* RO代碼段起始地址 */
|Image$$RO$$Limit| /* RO 代碼段結束地址 */
|Image$$RW$$Base| /* RW代碼段起始地址 */
|Image$$RW$$Limit| /* RW 代碼段結束地址 */
|Image$$ZI$$Base| /* ZI 代碼段起始地址 */
|Image$$ZI$$Limit| /* ZI 代碼段結束地址 */
注意:在兩個$$之間的名稱, 與scatter中指定的段的名稱相同.
4. 裝載過程說明
當從NorFlash啓動時, 要把flash芯片的首地址映射到0x00000000位置, 系統啓動後, 啓動程序本身把自己從
flash中搬到RAM中運行. 搬移後的各段起始地址, 由以上宏來確定.
當從NandFlash啓動時, S3C2410會自動把前NandFlash的前4k搬到S3C2410的內部RAM中,並把內部
RAM的首地址設爲0x00000000,CPU從0x00000000開始執行. 所以, 在nandFlash的前4k程序中,必須包含從
NandFlash把BootLoader的其餘部分裝入RAM的程序.
2.1.3 啓動過程的彙編部分
當系統啓動時, ARM CPU會跳到0x00000000去執行。一般BootLoader都包括如下幾個部分:
1. 建立中斷向量異常表
2. 顯示的切換到SVC且32指令模式
3. 關閉S3C2410的內部看門狗
4. 禁止所有的中斷
5. 配置系統時鐘頻率和總線頻率
6. 設置內存區的控制寄存器
7. 初始化中斷
8. 安裝中斷向表量
9. 把可執行文件的各個段搬到運行態的各個位置
10. 跳到C代碼部分執行
2.1.4 啓動過程的C部分
1. 初始化MMU
2.初始化外部端口
3. 中斷處理程序表初始化
4. 串口初始化
5. 其它部分初始化(可選)
6. 主程序循環
3 AXD的使用以及源代碼說明
3.1 源代碼說明
3.1.1 彙編源代碼說明
;===============================================================================
; 引用頭文件
;===============================================================================
get bdinit.h
;===============================================================================
; 引用標準變量
;===============================================================================
IMPORT |Image$$RO$$Base| ; Base address of RO section
IMPORT |Image$$RO$$Limit| ; End address of RO section
IMPORT |Image$$RW$$Base| ; Base address of RW section
IMPORT |Image$$RW$$Limit| ; End address of RW section
IMPORT |Image$$ZI$$Base| ; Base address of ZI section
IMPORT |Image$$ZI$$Limit| ; End addresss of ZI section
IMPORT bdmain ; The entry function of C program
;===============================================================================
; 宏定義
;===============================================================================
; macro HANDLER
MACRO
$HandlerLabel HANDLER $HandleLabel
$HandlerLabel
sub sp,sp,#4 ;Decrement sp (to store jump address)
stmfd sp!,{r0} ;PUSH the work register to stack
ldr r0,=$HandleLabel;Load the address of HandleXXX to r0
ldr r0,[r0] ;Load the contents(service routine start address) of HandleXXX
str r0,[sp,#4] ;Store the contents(ISR) of HandleXXX to stack
ldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR)
MEND
;===============================================================================
; 彙編語言的入口代碼
;===============================================================================
AREA Init,CODE,READONLY
CODE32
ENTRY
;=====================
; 建立中斷向量表
;=====================
b reset_handler ;0x00000000: Reset (SVC)
b undef_handler ;0x00000004: Undefined instruction (Undef)
b swi_handler ;0x00000008: Software Interrupt (SVC)
b iabr_handler ;0x0000000C: Instruction Abort (Abort)
b dabr_handler ;0x00000010: Data Abort (Abort)
b no_handler ;0x00000014:
b irq_handler ;0x00000018: IRQ (IRQ)
b fiq_handler ;0x0000001C: FIQ (FIQ)
LTORG
undef_handler HANDLER HandleUndef
swi_handler HANDLER HandleSWI
iabr_handler HANDLER HandlePabort
dabr_handler HANDLER HandleDabort
no_handler HANDLER HandleReserved
irq_handler HANDLER HandleIRQ
fiq_handler HANDLER HandleFIQ
;=============================
; 復位時運行的主程序
;=============================
reset_handler
;Set the cpu to SVC32 mode
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr_cxsf,r0
;Turn off watchdog
ldr r0,=WTCON
ldr r1,=0x0
str r1,[r0]
;Disable all the first level interrupts
ldr r0,=INTMSK
ldr r1,=0xffffffff
str r1,[r0]
;Disable all the second level interrupts
ldr r0,=INTSUBMSK
ldr r1,=0x7ff
str r1,[r0]
;Configure MPLL
ldr r0,=MPLLCON
ldr r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV) ;Fin=12MHz,Fout=200MHz
str r1,[r0]
;Set FCLK:HCLK:PCLK = 1:2:4
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
;Set memory control registers
ldrr0,=SMRDATA
ldr r1,=BWSCON
add r2, r0, #52 ;End address of SMRDATA
0
ldr r3, [r0], #4
str r3, [r1], #4
cmp r2, r0
bne %B0
;Initialize stacks
bl InitStacks
;Setup IRQ handler
ldr r0,=HandleIRQ ;This routine is needed
ldr r1,=IsrIRQ
str r1,[r0]
;Copy RW/ZI section into RAM
ldr r0, =|Image$$RO$$Limit|;Get pointer to ROM data
ldr r1, =|Image$$RW$$Base| ;and RAM copy
ldr r3, =|Image$$ZI$$Base|
cmp r0, r1 ; Check that they are different
beq %F2
1
cmp r1, r3 ; Copy init data
ldrcc r2, [r0], #4 ;--> LDRCC r2, [r0] + ADD r0, r0, #4
strcc r2, [r1], #4 ;--> STRCC r2, [r1] + ADD r1, r1, #4
bcc %B1
2
ldr r1, =|Image$$ZI$$Limit| ; Top of zero init segment
mov r2, #0
3
cmp r3, r1 ; Zero init
strcc r2, [r3], #4
bcc %B3
bl bdmain ;Jump to the main function
;Dead loop
1
nop
b %B1
;===============================================================================
; 初始中斷處理程序
;===============================================================================
IsrIRQ
sub sp,sp,#4 ;reserved for PC
stmfd sp!,{r8-r9}
ldr r9,=INTOFFSET
ldr r9,[r9]
ldr r8,=HandleEINT0
add r8,r8,r9,lsl #2
ldr r8,[r8]
str r8,[sp,#8]
ldmfd sp!,{r8-r9,pc}
;===============================================================================
; 初始化各個模式下堆棧
;===============================================================================
InitStacks
mrs r0,cpsr
bic r0,r0,#MODEMASK
orr r1,r0,#UNDEFMODE|NOINT
msr cpsr_cxsf,r1 ;UndefMode
ldr sp,=UndefStack
orr r1,r0,#ABORTMODE|NOINT
msr cpsr_cxsf,r1 ;AbortMode
ldr sp,=AbortStack
orr r1,r0,#IRQMODE|NOINT
msr cpsr_cxsf,r1 ;IRQMode
ldr sp,=IRQStack
orr r1,r0,#FIQMODE|NOINT
msr cpsr_cxsf,r1 ;FIQMode
ldr sp,=FIQStack
bic r0,r0,#MODEMASK|NOINT
orr r1,r0,#SVCMODE
msr cpsr_cxsf,r1 ;SVCMode
ldr sp,=SVCStack
mov pc,lr ;Return the call routine
LTORG
;===============================================================================
; 內存區控制寄存器值表; 你可根據需要修改bdinit.h文件, 下面代碼不用做任何改動
;===============================================================================
SMRDATA DATA
DCD
(0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(
B7_BWSCON<<28))
DCD
((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC)) ;GCS0
DCD
((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC)) ;GCS1
DCD
((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC)) ;GCS2
DCD
((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC)) ;GCS3
DCD
((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC)) ;GCS4
DCD
((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC)) ;GCS5
DCD ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN)) ;GCS6
DCD ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN)) ;GCS7
DCD ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
DCD 0x32 ;SCLK power saving mode, BANKSIZE 128M/128M
DCD 0x30 ;MRSR6 CL=3clk
DCD 0x30 ;MRSR7
ALIGN
;===============================================================================
; 異常及中斷向量表空間; 安裝異常或中斷處理程序在bdisr.c中,isr_setup()來完成.
;===============================================================================
AREA RamData, DATA, READWRITE
^ _ISR_STARTADDRESS ;表示下面數據區從_ISR_STARTADDRESS指定的位置開始
HandleReset # 4
HandleUndef # 4
HandleSWI # 4
HandlePabort # 4
HandleDabort # 4
HandleReserved # 4
HandleIRQ # 4
HandleFIQ # 4
;=============================
; The Interrupt table
;=============================
HandleEINT0 # 4
HandleEINT1 # 4
HandleEINT2 # 4
HandleEINT3 # 4
HandleEINT4_7 # 4
HandleEINT8_23 # 4
HandleRSV6 # 4
HandleBATFLT # 4
HandleTICK # 4
HandleWDT # 4
HandleTIMER0 # 4
HandleTIMER1 # 4
HandleTIMER2 # 4
HandleTIMER3 # 4
HandleTIMER4 # 4
HandleUART2 # 4
HandleLCD # 4
HandleDMA0 # 4
HandleDMA1 # 4
HandleDMA2 # 4
HandleDMA3 # 4
HandleMMC # 4
HandleSPI0 # 4
HandleUART1 # 4
HandleRSV24 # 4
HandleUSBD # 4
HandleUSBH # 4
HandleIIC # 4
HandleUART0 # 4
HandleSPI1 # 4
HandleRTC # 4
HandleADC # 4
END
3.1.2 C語言源代碼說明
void bdmain(void)
{
/* 禁止Cache 和MMU */
cache_disable();
mmu_disable();
/* 端口初始化 */
port_init();
/* 中斷處理程序 */
isr_init();
/* 串口初始化 */
serial_init(0, 115200);
/* 輸出信息進行主循環 */
serial_printf("is ok!/n");
while(1) {
}
}
通常基本ADS的測試程序都可以在這個架構上加入自己的代碼.
3.2 AXD的使用
3.2.1 配置仿真器
1. 爲仿真器安裝Server
一般的仿真器都對應有一個Server程序,所以在使用在線仿真之前,必須先安裝這個Server程序。我使用
是DragonICE
仿真器, 所以先要安裝DragonICE
Server程序。
2. 連接仿真器
把dragonICE
仿真器的JTAG口連接上ARM板(注意:ARM板要斷電連接), 另一端通過並口連接到PC上,
有的仿真器是通過USB口連接到PC上, 這與仿真器的硬件相關。連接好後, 打開ARM電源,啓動ARM板。
當ARM通電啓動後,啓動DragonICE
Server檢測ARM板,詳細步驟及設置參見對應的仿真器手冊。我的
dragonICE
Server啓動, 按”自動檢測”可以檢測到ARM920T。
3.2.2 啓動AXD 配置開發板
1. 啓動AXD
先啓動DragonICE
Server程序.
按如下步聚啓動AXD:
開始>
所有程序>
ARM Developer Suite v1.2>
AXD Debugger
2. 裝載仿真器庫文件
從AXD菜單的Options>
Configure Target...啓動”Choose Target”目標板配置窗口.
在”Choose Target”窗口中,點擊”Add”按鈕,選擇仿真器的庫文件. 我的仿真器服務器程序安裝在
c:/DragonICE
下,所以選擇項c:/DragonICE/
dragonice.
dll文件.
3. 爲AXD在線仿真配置仿真器
在"Target Environments"中選中DragonICE
中,點擊右邊的"Configure"按鈕.
在”FJB DragonICE
Release v1.2”窗口點擊"This computer..."按鈕,再點擊"OK"按鈕。
回到”Choose Target”窗口,點擊"OK"按鈕。完成配置.
回到主界面, 在右邊的”Target”窗口會出現ARM920T_0.這表明AXD已經進入ARM板的在線仿真狀態.
點擊菜單"System Views">"
Controls Monitors".會出現"ARM920TRegister"
窗口.此時,會顯示當前ARM板上所
有寄存器的狀態。
4. 配置ARM板
如果ARM板通電後,沒有程序運行並把內存區控制寄存器配置好的說,外部RAM是不能使用的. 所以必須
通過仿真器來設置這些寄存器. 如果ARM板已經有啓動程序並且已經配置好, 這一步可以省略.
首先把2410cfg.txt拷貝到c:/下.
回到AXD主界面, 從菜單”System Views” >
“Command Line Interface”。會出現一個Command Line
Interface的調試命令行窗口,並顯示如下提示符:
Debug >
輸入obey c:/2410cfg.txt裝載所有配置命令.
Debug >obey c:/2410cfg.txt
5. 2410cfg.txt文件說明
sreg psr, 0x00000013
;設置當前CPSR的值, 把CPU的模式切換到SVC模式和32位指令集, 關閉IRQ和FIQ。
smem 0x53000000,0,32
;設置看門狗控制寄存器WTCON
;禁止看門狗定時器
smem 0x4C000004,((0x74<<12)+(0x3<<4)+0x1),32
;設置主頻率設置寄存器MPLLCON
;目前CPU的工作頻率FCLK是124.00MHz
smem 0x4C000014,0x3,32
;設置時鐘分頻寄存器CLKDIVN
;設置FCLK/HCLK/PCLK 的頻率比例1:2:4
smem 0x48000000,((2<<28)+(2<<24)+(1<<20)+(1<<16)+(1<<12)+(1<<8)+(1<<4)+0),32
;設置內存總線控制BWSCON
;SDRAM BANK 6&7 is 32位
;其它BANK is 16位
smem 0x48000004,((3<<13)+(3<<11)+(7<<8)+(3<<6)+(3<<4)+(3<<2)+3),32
;設置寄存器區0控制寄存器:BANKCON0
smem 0x4800001c,((3<<15)+(1<<2)+1),32
;設置寄存器區6控制寄存器: BANKCON6(SDRAM)
;RAS to CAS 延時3 時鐘週期
;列地址是9位
smem 0x48000020,((3<<15)+(1<<2)+1),32
;設置寄存器區7控制寄存器: BANKCON7(SDRAM)
;RAS to CAS 延時 3 時鐘週期
;列地址是9位
smem 0x48000024,((1<<23)+(3<<18)+(2<<16)+1113),32
;set 外部RAM刷新寄存器:REFRESH
;允許自刷新
;HCLK=FCLK/2, 60MHz,刷新計算器是1113
smem 0x48000028,0x31,32
;設置寄存器的大小
;禁止burst操作
;允許SDRAM power down模式
;SCLK在訪問期間仍在活動狀態
;SDRAM模式寄存器設置
smem 0x4800002c,0x30,32
smem 0x48000030,0x30,32
3.2.3 使用AXD在線仿真調試程序
1. 裝載可執行的文件
AXD只支持.axf格式的可執行文件.
啓動AXD, 在菜單的File中,選擇Load Image..., 選擇c:/adsbloadter/prj/prj_Data/DebugRel/prj.axf加載執行
image. 就可以執行並調試了. AXD提供了非常方便的調試手段, 包括在線單步, 自由設置斷點等.
第三部分 GNU交叉工具鏈
1 設置環境變量,準備源碼及相關補丁
1.1 設置環境變量
[arm@localhost arm]#vi ~/.bashrc
export PREFIX=/usr/local/arm/3.4.4
export TARGET=armlinux
export SYSROOT=${PREFIX}/sysroot
export ARCH=arm
export CROSS_COMPILE=${TARGET}export
PATH=${PREFIX}/bin:$PATH
export SRC=/home/arm/dev_home/btools/tchain3.4.4
1. 2 準備源碼包
1.2.1 binuils
名稱:binutils2.16.
tar.gz
下載地址:http://ftp.gnu.org/gnu/binutils/binutils2.16.
tar.gz
1.2.2 gcc
名稱:gcc3.4.4.
tar.bz2
下載地址:http://ftp.gnu.org/gnu/gcc/gcc3.4.4/
gcc3.4.4.
tar.bz2
1.2.3 glibc
名稱:glibc2.3.5.
tar.gz
glibclinuxthreads2.3.5.
tar.gz
下載地址: http://ftp.gnu.org/gnu/glibc/glibc2.3.5.
tar.gz
http://ftp.gnu.org/gnu/glibc/glibclinuxthreads2.3.5.
tar.gz
1.2.4 linux kernel
名稱:linux2.6.14.1.
tar.gz
下載地址: http://ftp.kernel.org/pub/linux/kernel/v2.6/linux2.6.14.1.
tar.gz
1.3 準備補丁
1.3.1 ioperm.c.diff
作用:打修正ioperm()函數.
下載地址:http://frank.harvard.edu/~coldwell/toolchain/ioperm.c.diff
1.3.2 flow.c.diff
作用:該補丁用於產生crti.o和crtn.o文件。
下載地址:http://gcc.gnu.org/cgibin/
cvsweb.cgi/gcc/gcc/flow.c.diff?cvsroot=gcc&only_with_tag=cslarmbranch&
r1=1.563.4.2&r2=1.563.4.3
1.3.3 t-linux.diff
作用:修改gcc一處bug
下載地址:http://frank.harvard.edu/~coldwell/toolchain/tlinux.
diff
1.4 編譯 GNU binutils
重新以arm用戶登陸,讓新設置的環境變量起作用.
[arm@localhost arm]#su arm
[arm@localhost arm]#cd ${SRC}
[arm@localhost tchain3.4.4]#tar xzvf binutils2.16.
tar.gz
[arm@localhost tchain3.4.4]#mkdir p
BUILD/binutils2.16
[arm@localhost binutils2.16]#
cd BUILD/binutils2.16
[arm@localhost binutils2.16]#
../../binutils2.16/
configure prefix=${
PREFIX} target=${
TARGET} /
withsysroot=${
SYSROOT}
[arm@localhost binutils2.16]#
make
[arm@localhost binutils2.16]#
su root
[root@localhost binutils2.16]#
make install
[root@localhost binutils2.16]#
exit
[arm@localhost binutils2.16]#
1.5 準備內核頭文件
1.5.1 使用當前平臺的gcc編譯內核頭文件
[arm@localhost tchain3.4.4]#cd ${KERNEL}
[arm@localhost kernel]#tar xvfz linux2.6.14.1.
tar.gz
[arm@localhost kernel]#cd linux2.6.14.1
[arm@localhost linux2.6.14.1]#
make ARCH=arm menuconfig
[arm@localhost linux2.6.14.1]#
make
1.5.2 複製內核頭文件
[arm@localhost kernel]#su root
[root@localhost kernel]#mkdir p
${SYSROOT}/usr/include
[root@localhost kernel]#cp a
include/linux ${SYSROOT}/usr/include/linux
[root@localhost kernel]#cp a
include/asmi386
${SYSROOT}/usr/include/asm
[root@localhost kernel]#cp a
include/asmgeneric
${SYSROOT}/usr/include/asmgeneric
[root@localhost kernel]#exit
[arm@localhost kernel]#
1.6 譯編glibc頭文件
[arm@localhost kernel]#cd ${SRC}
[arm@localhost chain3.4.4]#tar xvfz glibc2.3.5.
tar.gz
[arm@localhost chain3.4.4]#patch d
glibc2.3.5
p1
< ioperm.c.diff
[arm@localhost glibc2.3.5]#
cd glibc2.3.5
[arm@localhost glibc2.3.5]#
tar xvfz ../glibclinuxthreads2.3.5.
tar.gz
[arm@localhost chain3.4.4]#cd ..
[arm@localhost chain3.4.4]#mkdir BUILD/glibc2.3.5headers
[arm@localhost chain3.4.4]#cd BUILD/glibc2.3.5headers
[arm@localhost glibc2.3.5headers]#../../
glibc2.3.5/
configure prefix=/
usr host=${
TARGET} /
enableaddons=
linuxthreads –withheaders=${
SYSROOT}/usr/include
[arm@localhost glibc2.3.5headers]#
su root
[root@localhost glibc2.3.5headers]#
make crosscompiling=
yes install_root=${SYSROOT} installheaders
[root@localhost glibc2.3.5headers]#
touch ${SYSROOT}/usr/include/gnu/stubs.h
[root@localhost glibc2.3.5headers]#
touch ${SYSROOT}/usr/include/bits/stdio_lim.h
[root@localhost glibc2.3.5headers]#
exit
[arm@localhost glibc2.3.5headers]#
注意: prefix=/
usr :是gcc尋找庫的搜索路徑。
1.7 編譯gcc第一階段
[arm@localhost glibc2.3.5headers]#
cd ${SRC}
[arm@localhost chain3.4.4]#tar xjvf gcc3.4.4.
tar.bz2
[arm@localhost chain3.4.4]#patch d
gcc3.4.4
p1
< flow.c.diff
[arm@localhost chain3.4.4]#patch d
gcc3.4.4
p1
< tlinux.
diff
[arm@localhost chain3.4.4]#mkdir p
BUILD/gcc3.4.4stage1
[arm@localhost chain3.4.4]#cd BUILD/gcc3.4.4stage1
[arm@localhost gcc3.4.4stage1]#../../
gcc3.4.4/
configure prefix=${
PREFIX} target=${
TARGET} /
enablelanguages=
c withsysroot=${
SYSROOT}
注意:不能加上"disableshared"
選項。
[arm@localhost gcc3.4.4stage1]#
make allgcc
[arm@localhost gcc3.4.4stage1]#
su root
[root@localhost gcc3.4.4stage1]#
make installgcc
[root@localhost gcc3.4.4stage1]#
exit
[arm@localhost gcc3.4.4stage1]#
1.8 編譯完整的glibc
[arm@localhost gcc3.4.4stage1]
#cd ${SRC}
[arm@localhost tchain3.4.4]#mkdir BUILD/glibc2.3.5
[arm@localhost tchain3.4.4]#cd BUILD/glibc2.3.5
[arm@localhost glibc2.3.5]#
BUILD_CC=gcc CC=${CROSS_COMPILE}gcc AR=${CROSS_COMPILE}ar /
RANLIB=${CROSS_COMPILE}ranlib AS=${CROSS_COMPILE}as LD=${CROSS_COMPILE}ld /
../../glibc2.3.5/
configure prefix=/
usr build=
i386redhatlinux
host=
armunknownlinuxgnu
/
target=
armunknownlinuxgnu
without__
thread enableaddons=
linuxthreads /
withheaders=${
SYSROOT}/usr/include
說明:
prefix:
指定安裝路徑。
target:
指定目標平臺。
host:
指定當前平臺。
build:
指定編譯平臺。
withsysroot:
用於指定編譯所需要的頭文件,及鏈接庫。
enableaddons:
加入其它的庫,如線程庫等。
enablelanguages:
指定gcc所支持的語言。
[arm@localhost glibc2.3.5]#
make
[arm@localhost glibc2.3.5]#
su root
[root@localhost glibc2.3.5]#
make install_root=${SYSROOT} install
[root@localhost glibc2.3.5]#
exit
[arm@localhost glibc2.3.5]#
1.9 編譯完整的gcc
[arm@localhost glibc2.3.5]#
cd ${SRC}
[arm@localhost tchain3.4.4]#mkdir BUILD/gcc3.4.4
[arm@localhost tchain3.4.4]#cd BUILD/gcc3.4.4
[arm@localhost gcc3.4.4]#../../
gcc3.4.4/
configure prefix=${
PREFIX} target=${
TARGET} /
enablelanguages=
c withsysroot=${
SYSROOT}
[arm@localhost gcc3.4.4]#
make
[arm@localhost gcc3.4.4]#
su root
[root@localhost gcc3.4.4]#
make install
[root@localhost gcc3.4.4]#
exit
[arm@localhost gcc3.4.4]#
2 GNU交叉工具鏈的下載
2.1 ARM官方網站
工具鏈的官方下載地址:
http://www.arm.linux.org.uk
可以從該站點下載2.95.3, 3.0以及3.2工具鏈
ftp://ftp.arm.linux.org.uk/pub/armlinux/toolchain/cross2.95.3.
tar.bz2
ftp://ftp.arm.linux.org.uk/pub/armlinux/toolchain/cross3.0.
tar.bz2
ftp://ftp.arm.linux.org.uk/pub/armlinux/toolchain/cross3.2.
tar.bz2
3 GNU交叉工具鏈的介紹與使用
3.1 常用工具介紹
名稱歸屬作用
armlinuxas
binutils 編譯ARM彙編程序
armlinuxar
binutils 把多個.o合併成一個.o或靜態庫(.a)
armlinuxranlib
binutils 爲庫文件建立索引,相當於armlinuxar
s
armlinuxld
binutils 連接器(Linker), 把多個.o或庫文件連接成一個可執行文件
名稱歸屬作用
armlinuxobjdump
binutils 查看目標文件(.o)和庫(.a)的信息
armlinuxobjcopy
binutils 轉換可執行文件的格式
armlinuxstrip
binutils 去掉elf可執行文件的信息. 使可執行文件變小
armlinuxreadelf
binutils 讀elf可執行文件的信息
armlinuxgcc
gcc 編譯.c或.S開頭的C程序或彙編程序
armlinuxg++
gcc 編譯c++程序
3.2 主要工具的使用
3.2.1 arm-linux-gcc的使用
1. 編譯C文件,生成elf可執行文件
h1.c 源文件
#include <stdio.h>
void hellofirst(void)
{
printf("The first hello! /n");
}
h2.c 源文件
#include <stdio.h>
void hellosecond(void)
{
printf("The second hello! /n");
}
hello.c 源文件
#include <stdio.h>
void hellosecond(void);
void hellofirst(void);
int main(int argc, char *argv[])
{
hellofirst();
hellosecond();
return(0);
}
編譯以上3個文件,有如下幾種方法:
方法1:
[arm@localhost gcc]#armlinuxgcc
c
h1.c
[arm@localhost gcc]#armlinuxgcc
c
h2.c
[arm@localhost gcc]#armlinuxgcc
o
hello hello.c h1.o h2.o
方法2:
[arm@localhost gcc]#armlinuxgcc
c
h1.c h2.c
[arm@localhost gcc]#armlinuxgcc
o
hello hello.c h1.o h2.o
方法3:
[arm@localhost gcc]#armlinuxgcc
c
o
h1.o h1.c
[arm@localhost gcc]#armlinuxgcc
c
o
h1.o h1.c
[arm@localhost gcc]#armlinuxgcc
o
hello hello.c h1.o h2.o
方法4:
[arm@localhost gcc]#armlinuxgcc
o
hello hello.c h1.c h2.c
c:
只編譯不連接。
o:
編譯且連接。
2. 產生一個預處理文件
當要看一個宏在源文件中產生的結果時,比較合適。
[arm@localhost gcc]#armlinuxgcc
E
h1.i h1.c
E:
產生一個預處理文件.
3. 產生一個動態庫
動態庫是在運行時需要的庫。
[arm@localhost gcc]#armlinuxgcc
c
fpic
h1.c h2.c
[arm@localhost gcc]#armlinuxgcc
shared
h1.o h2.o o
hello.so
[arm@localhost gcc]#armlinuxgcc
o
hello hello.c hello.so
把hello.so拷貝到目標板的/lib目錄下,把可執行文件拷貝目標板的/tmp目錄下,在目標板上運行hello.
#/tmp/hello
或把hello.so和hello一起拷貝到/tmp目標下,並設置LD_LIBRARY_PATH環境變量
#export LD_LIBRARY_PATH =/tmp:$LD_LIBRARY_PATH
#/tmp/hello
3.2.2 arm-linux-ar 和 arm-linux-ranlib的使用
靜態庫是在編譯時需要的庫。
1. 建立一個靜態庫
[arm@localhost gcc]#armlinuxar
r
libhello.a h1.o h2.o
2. 爲靜態庫建立索引
[arm@localhost gcc]#armlinuxar
s
libhello.a
[arm@localhost gcc]#armlinuxranlib
libhello.a
3. 由靜態庫產生可執行文件
[arm@localhost gcc]#armlinuxgcc
o
hello hello.c lhello
L./
[arm@localhost gcc]#armlinuxgcc
o
hello hello.c libhello.a
hello文件可以直接拷貝到/tmp目錄下運行,不需libhello.a.
3.2.3 arm-linux-objdump的使用
1. 查看靜態庫或.o文件的組成文件
[arm@localhost gcc]$ armlinuxobjdump
a
libhello.a
2. 查看靜態庫或.o文件的絡組成部分的頭部分
[arm@localhost gcc]$ armlinuxobjdump
h
libhello.a
3. 把目標文件代碼反彙編
[arm@localhost gcc]$ armlinuxobjdump
d
libhello.a
3.2.4 arm-linux-readelf的使用
1. 讀elf文件開始的文件頭部
[arm@localhost gcc]$ armlinuxreadelf
h
hello
ELF Header:
Magic: 7f 45 4c 46 01 01 01 61 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: ARM
ABI Version: 0
Type: EXEC (Executable file)
Machine: ARM
Version: 0x1
Entry point address: 0x82b4
Start of program headers: 52 (bytes into file)
Start of section headers: 10240 (bytes into file)
Flags: 0x2, has entry point
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 6
Size of section headers: 40 (bytes)
Number of section headers: 28
Section header string table index: 25
2. 讀elf文件中所有ELF 的頭部:
[arm@localhost gcc]#armlinuxreadelf
e
hello
......
3. 顯示整個文件的符號表
[arm@localhost gcc]#armlinuxreadelf
s
hello
......
4. 顯示使用的動態庫
[arm@localhost gcc]#armlinuxreadelf
d
hello
......
3.2.5 arm-linux-strip的使用
1. 移除所有的符號信息
[arm@localhost gcc]#cp hello hello1
[arm@localhost gcc]#armlinuxstrip
stripall
hello
stripall:
是移除所有符號信息
[arm@localhost gcc]#ll
rwxrxrx
1 arm root 2856 7月 3 15:14 hello
rwxrxrx
1 arm root 13682 7月 3 15:13 hello1
被strip後的hello程序比原來的hello1程序要小很多。
2. 移除調試符號信息
[arm@localhost gcc]#armlinuxstrip
g
hello
[arm@localhost gcc]#ll
rwxrxrx
1 arm root 4501 7月 3 15:17 hello
rwxrxrx
1 arm root 13682 7月 3 15:13 hello1
3.2.6 arm-linux-copydump的使用
生成可以執行的2進制代碼
[arm@localhost gcc]#armlinuxcopydump
O
binary hello hello.bin
4 ARM GNU常用彙編語言介紹
4.1 ARM GNU常用匯編僞指令介紹
1. abort
.abort: 停止彙編
.align absexpr1,
absexpr2:
以某種對齊方式,在未使用的存儲區域填充值. 第一個值表示對齊方式,4, 8,16或32. 第
二個表達式值表示填充的值.
2. if...else...endif
.if
.else
.endif: 支持條件預編譯
3. include
.include "file": 包含指定的頭文件, 可以把一個彙編常量定義放在頭文件中.
4. comm
.comm symbol, length:在bss段申請一段命名空間,該段空間的名稱叫symbol, 長度爲length. Ld連接器在連接會
爲它留出空間.
5. data
.data subsection: 說明接下來的定義歸屬於subsection數據段.
6. equ
.equ symbol, expression: 把某一個符號(symbol)定義成某一個值(expression).該指令並不分配空間.
7. global
.global symbol: 定義一個全局符號, 通常是爲ld使用.
8. ascii
.ascii "string": 定義一個字符串併爲之分配空間.
9. byte
.byte expressions: 定義一個字節, 併爲之分配空間.
10. short
.short expressions: 定義一個短整型, 併爲之分配空間.
11. int
.int expressions: 定義一個整型,併爲之分配空間.
12 long
.long expressions: 定義一個長整型, 併爲之分配空間.
13 word
.word expressions: 定義一個字,併爲之分配空間, 4bytes.
14. macro/endm
.macro: 定義一段宏代碼, .macro表示代碼的開始, .endm表示代碼的結束.
15. req
name .req register name: 爲寄存器定義一個別名.
16. code
.code [16|32]: 指定指令代碼產生的長度, 16表示Thumb指令, 32表示ARM指令.
17. ltorg
.ltorg: 表示當前往下的定義在歸於當前段,併爲之分配空間.
4.2 ARM GNU專有符號
1. @
表示註釋從當前位置到行尾的字符.
2. #
註釋掉一整行.
3. ;
新行分隔符.
4.3 操作碼
1. NOP
nop
空操作, 相當於MOV r0, r0
2. LDR
ldr <register> , = <expression>
相當於PC寄存器或其它寄存器的長轉移.
3.ADR
adr <register> <label>
相於PC寄存器或其它寄存器的小範圍轉移.
ADRL
adrl <register> <label>
相於PC寄存器或其寄存器的中範圍轉移.
5 可執行生成說明
5.1 lds文件說明
5.1.1 主要符號說明
1. OUTPUT_FORMAT(bfdname)
指定輸出可執行文件格式.
2. OUTPUT_ARCH(bfdname)
指定輸出可執行文件所運行CPU平臺
3. ENTRY(symbol)
指定可執行文件的入口段
5.1.2 段定義說明
1. 段定義格式
SECTIONS { ...
段名 : {
內容
}
...
}
5.1.3 uboot.
lds 文件說明
OUTPUT_FORMAT("elf32littlearm",
"elf32littlearm",
"elf32littlearm")
;指定輸出可執行文件是elf格式,32位ARM指令,小端
OUTPUT_ARCH(arm)
;指定輸出可執行文件的平臺爲ARM
ENTRY(_start)
;指定輸出可執行文件的起始代碼段爲_start.
SECTIONS
{
. = 0x00000000 ; 從0x0位置開始
. = ALIGN(4) ; 代碼以4字節對齊
.text : ;指定代碼段
{
cpu/arm920t/start.o (.text) ; 代碼的第一個代碼部分
*(.text) ;其它代碼部分
}
. = ALIGN(4)
.rodata : { *(.rodata) } ;指定只讀數據段
. = ALIGN(4);
.data : { *(.data) } ;指定讀/寫數據段
. = ALIGN(4);
.got : { *(.got) } ;指定got段, got段式是uboot自定義的一個段, 非標準段
__u_boot_cmd_start = . ;把__u_boot_cmd_start賦值爲當前位置, 即起始位置
.u_boot_cmd : { *(.u_boot_cmd) } ;指定u_boot_cmd段, uboot把所有的uboot命令放在該段.
__u_boot_cmd_end = .;把__u_boot_cmd_end賦值爲當前位置,即結束位置
. = ALIGN(4);
__bss_start = .; 把__bss_start賦值爲當前位置,即bss段的開始位置
.bss : { *(.bss) }; 指定bss段
_end = .; 把_end賦值爲當前位置,即bss段的結束位置
}
第四部分 u-boot的移植
1 u-boot的介紹及系統結構
1.1 u-boot介紹
Uboot
是德國DENX小組的開發用於多種嵌入式CPU的bootloader程序, UBoot
不僅僅支持嵌入式Linux
系統的引導,當前,它還支持NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS嵌入式操作系統。UBoot

了支持PowerPC系列的處理器外,還能支持MIPS、 x86、ARM、NIOS、XScale等諸多常用系列的處理器。
1.2 獲取u-boot
以uboot用戶登陸.
[uboot@localhost ~]#mkdir p
dev_home/uboot
[uboot@localhost ~]#cd dev_home/uboot
從下面地址下載uboot
的源代碼。
http://sourceforge.net/projects/uboot
[uboot@localhost uboot]#tar xjvf
uboot1.1.4.
tar.bz2
[uboot@localhost uboot]#cd uboot1.1.4
1.3 u-boot體系結構
1.3.1 u-boot目錄結構
1. 目錄樹
[uboot@localhost uboot1.1.4]#
tree L
1 d
.
|board
|common
|cpu
|disk
|doc
|drivers
|dtt
|examples
|fs
|include
|lib_
arm
|lib_
generic
|lib_
i386
|lib_
m68k
|lib_
microblaze
|lib_
mips
|lib_
nios
|lib_
nios2
|lib_
ppc
|net
|post
|rtc
`tools
2. board:和一些已有開發板有關的文件. 每一個開發板都以一個子目錄出現在當前目錄中,比如說:SMDK2410,
子目錄中存放與開發板相關的配置文件.
3. common:實現uboot
命令行下支持的命令,每一條命令都對應一個文件。例如bootm命令對應就是
cmd_bootm.c。
4. cpu:與特定CPU架構相關目錄,每一款Uboot
下支持的CPU在該目錄下對應一個子目錄,比如有子目錄
arm920t等。
5. disk:對磁盤的支持。
5. doc:文檔目錄。Uboot
有非常完善的文檔,推薦大家參考閱讀。
6. drivers:Uboot
支持的設備驅動程序都放在該目錄,比如各種網卡、支持CFI的Flash、串口和USB等。
7. fs: 支持的文件系統,Uboot
現在支持cramfs、fat、fdos、jffs2和registerfs。
8. include:Uboot
使用的頭文件,還有對各種硬件平臺支持的彙編文件,系統的配置文件和對文件系統支持的
文件。該目錄下configs目錄有與開發板相關的配置頭文件,如smdk2410.h。該目錄下的asm目錄有與CPU體
繫結構相關的頭文件,asm對應的是asmarm.
9. lib_xxxx: 與體系結構相關的庫文件。如與ARM相關的庫放在lib_arm中。
10. net:與網絡協議棧相關的代碼,BOOTP協議、TFTP協議、RARP協議和NFS文件系統的實現。
11. tools:生成Uboot
的工具,如:mkimage, crc等等。
2 uboot的啓動過程及工作原理
2.1 啓動模式介紹
大多數 Boot Loader 都包含兩種不同的操作模式:"啓動加載"模式和"下載"模式,這種區別僅對於開發人
員纔有意義。但從最終用戶的角度看,Boot Loader 的作用就是用來加載操作系統,而並不存在所謂的啓動加
載模式與下載工作模式的區別。
啓動加載(Boot loading)模式:這種模式也稱爲"自主"(Autonomous)模式。也即 Boot Loader 從目標機
上的某個固態存儲設備上將操作系統加載到 RAM 中運行,整個過程並沒有用戶的介入。這種模式是 Boot
Loader 的正常工作模式,因此在嵌入式產品發佈的時侯,Boot Loader 顯然必須工作在這種模式下。
下載(Downloading)模式:在這種模式下,目標機上的 Boot Loader 將通過串口連接或網絡連接等通信手
段從主機(Host)下載文件,比如:下載內核映像和根文件系統映像等。從主機下載的文件通常首先被 Boot
Loader 保存到目標機的 RAM 中,然後再被 BootLoader 寫到目標機上的FLASH 類固態存儲設備中。Boot
Loader 的這種模式通常在第一次安裝內核與根文件系統時被使用;此外,以後的系統更新也會使用 Boot
Loader 的這種工作模式。工作於這種模式下的 Boot Loader 通常都會向它的終端用戶提供一個簡單的命令
行接口。
UBoot
這樣功能強大的 Boot Loader 同時支持這兩種工作模式,而且允許用戶在這兩種工作模式之間進行
切換。
大多數bootloader都分爲階段1(stage1)和階段2(stage2)兩大部分,uboot
也不例外。依賴於CPU體系結構
的代碼(如CPU初始化代碼等)通常都放在階段1中且通常用彙編語言實現,而階段2則通常用C語言來實
現,這樣可以實現複雜的功能,而且有更好的可讀性和移植性。
2.2 階段1介紹
uboot
的stage1代碼通常放在start.s文件中,它用彙編語言寫成,其主要代碼部分如下:
2.2.1 定義入口
由於一個可執行的Image必須有一個入口點,並且只能有一個全局入口,通常這個入口放在ROM(Flash)的0x0
地址,因此,必須通知編譯器以使其知道這個入口,該工作可通過修改連接器腳本來完成。
1. board/crane2410/uboot.
lds: ENTRY(_start) ==> cpu/arm920t/start.S: .globl _start
2. uboot代碼區(TEXT_BASE = 0x33F80000)定義在board/crane2410/config.mk
2.2.2 設置異常向量
_start: b reset @ 0x00000000
ldr pc, _undefined_instruction @ 0x00000004
ldr pc, _software_interrupt @ 0x00000008
ldr pc, _prefetch_abort @ 0x0000000c
ldr pc, _data_abort @ 0x00000010
ldr pc, _not_used @ 0x00000014
ldr pc, _irq @ 0x00000018
ldr pc, _fiq @ 0x0000001c
當發生異常時,執行cpu/arm920t/interrupts.c中定義的中斷處理函數。
2.2.3 設置CPU的模式爲SVC模式
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr,r0
2.2.4 關閉看門狗
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
ldr r0, =pWTCON
mov r1, #0x0 @ 根據三星手冊進行調置。
str r1, [r0]
2.2.5 禁掉所有中斷
mov r1, #0xffffffff
ldr r0, =INTMSK
str r1, [r0]
# if defined(CONFIG_S3C2410)
ldr r1, =0x3ff
ldr r0, =INTSUBMSK
str r1, [r0]
2.2.6 設置以CPU的頻率
默認頻率爲 FCLK:HCLK:PCLK = 1:2:4,默認FCLK的值爲120 MHz,該值爲S3C2410手冊的推薦值。
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
2.2.7 設置CP15
設置CP15, 失效指令(I)Cache和數據(D)Cache後, 禁止MMU與Cache。
cpu_init_crit:
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 /* 失效I/D cache, 見S3C2410手冊附錄的2-16 */
mcr p15, 0, r0, c8, c7, 0 /* 失效TLB, 見S3C2410手冊附錄的2-18 */
/*
* 禁止 MMU 和caches, 詳見S3C2410手冊附錄2-11
*/
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002300 /* 清除 bits 13, 9:8 (--V- --RS)
* Bit 8: Disable System Protection
* Bit 7: Disable ROM Protection
* Bit 13: 異常向量表基地址: 0x0000 0000
*/
bic r0, r0, #0x00000087 /* 清除 bits 7, 2:0 (B--- -CAM)
* Bit 0: MMU disabled
* Bit 1: Alignment Fault checking disabled
* Bit 2: Data cache disabled
* Bit 7: 0 = Little-endian operation
*/
orr r0, r0, #0x00000002 /* set bit 2 (A) Align, 1 = Fault checking enabled */
orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache, 1 = Instruction cache enabled
*/
mcr p15, 0, r0, c1, c0, 0
2.2.8 配置內存區控制寄存器
配置內存區控制寄存器,寄存器的具體值通常由開發板廠商或硬件工程師提供. 如果您對總線週期及外圍
芯片非常熟悉, 也可以自己確定, 在UBOOT
中的設置文件是board/crane2410/lowlevel_init.S, 該文件包含
lowleve_init程序段. 詳細寄存器設置及值的解釋見3.2.2 啓動AXD 配置開發板一節中的第5點.
mov ip, lr
bl lowlevel_init
mov lr, ip
2.2.9 安裝U-BOOT使的棧空間
下面這段代碼只對不是從Nand Flash啓動的代碼段有意義,對從Nand Flash啓動的代碼,沒有意義。因爲
從Nand Flash中把UBOOT執行代碼搬移到RAM,由2.1.9中代碼完成.
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
...
#endif
stack_setup:
ldr r0, _TEXT_BASE /* 代碼段的起始地址 */
sub r0, r0, #CFG_MALLOC_LEN /* 分配的動態內存區 */
sub r0, r0, #CFG_GBL_DATA_SIZE /* UBOOT開發板全局數據存放 */
#ifdef CONFIG_USE_IRQ
/* 分配IRQ和FIQ棧空間 */
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
sub sp, r0, #12 /* 留下3個字爲Abort */
2.2.10 BSS段清0
clear_bss:
ldr r0, _bss_start /* BSS段的起始地址 */
ldr r1, _bss_end /* BSS段的結束地址 */
mov r2, #0x00000000 /* BSS段置0 */
clbss_l:str r2, [r0] /* 循環清除BSS段 */
add r0, r0, #4
cmp r0, r1
ble clbss_l
2.2.11 搬移Nand Flash代碼
從Nand Flash中, 把數據拷貝到RAM, 是由copy_myself程序段完成, 該程序段詳細解釋見:第七部分的3.1節.
#ifdef CONFIG_S3C2410_NAND_BOOT
bl copy_myself
@ jump to ram
ldr r1, =on_the_ram
add pc, r1, #0
nop
nop
1: b 1b @ infinite loop
on_the_ram:
#endif
2.2.12 進入C代碼部分
ldr pc, _start_armboot
_start_armboot: .word start_armboot
2.3 階段2的C語言代碼部分 
lib_arm/board.c中的start armboot是C語言開始的函數,也是整個啓動代碼中C語言的主函數,同時還是整個
uboot(
armboot)的主函數,該函數主要完成如下操作:
2.3.1調用一系列的初始化函數
1. 指定初始函數表:
init_fnc_t *init_sequence[] = {
cpu_init, /* cpu的基本設置 */
board_init, /* 開發板的基本初始化 */
interrupt_init, /* 初始化中斷 */
env_init, /* 初始化環境變量 */
init_baudrate, /* 初始化波特率 */
serial_init, /* 串口通訊初始化 */
console_init_f, /* 控制檯初始化第一階段 */
display_banner, /* 通知代碼已經運行到該處 */
dram_init, /* 配製可用的內存區 */
display_dram_config,
#if defined(CONFIG_VCMA9) || defined (CONFIG_CMC_PU2)
checkboard,
#endif
NULL,
};
執行初始化函數的代碼如下:
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) {
hang ();
}
}
2. 配置可用的Flash區
flash_init ()
3. 初始化內存分配函數
mem_malloc_init()
4. nand flash初始化
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
puts ("NAND:");
nand_init(); /* 初始化 NAND */
見第七部分3.2.3 節中的第3點nand_init()函數.
5. 初始化環境變量
env_relocate ();
6. 外圍設備初始化
devices_init()
7. I2C總線初始化
i2c_init();
8. LCD初始化
drv_lcd_init();
9. VIDEO初始化
drv_video_init();
10. 鍵盤初始化
drv_keyboard_init();
11. 系統初始化
drv_system_init();
2.3.2 初始化網絡設備
初始化相關網絡設備,填寫IP、MAC地址等。
1. 設置IP地址
/* IP Address */
gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
/* MAC Address */
{
int i;
ulong reg;
char *s, *e;
uchar tmp[64];
i = getenv_r ("ethaddr", tmp, sizeof (tmp));
s = (i > 0) ? tmp : NULL;
for (reg = 0; reg < 6; ++reg) {
gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
if (s)
s = (*e) ? e + 1 : e;
}
}
2.3.3 進入主UBOOT命令行
進入命令循環(即整個boot的工作循環),接受用戶從串口輸入的命令,然後進行相應的工作。
for (;;) {
main_loop (); /* 在common/main.c */
}
2.4 代碼搬運
  爲了支持NAND flash起動,S3C2410內建了內部的4k的SRAM緩存“Steppingstone”。當起動時,NAND
flash最初的4k字節將被讀入”Steppingstone”然後開始執行起動代碼。通常起動代碼會把NAND flash中的內容
拷到SDRAM中以便執行主代碼。
  使用硬件的ECC, NAND flash中的數據的有效性將會得到檢測。
功能
1. NAND flash 模式:支持讀/刪除/編程 NAND Flash
2. 自動起動模式:在復位時起動代碼將被讀入”Steppingstone”中,然後開始執行起動代碼。
3. 硬件ECC檢測模塊(硬件檢測,軟件糾正)
4. “Steppingstone” 4KB
內部SRAM在起動後可以另外使用。
3 uboot的移植過程
3.1 環境
詳細環境設置參見:第一部分的2.2.2.
1. 工作用戶
uboot
2. uboot
版本1.1.4
獲取uboot1.1.4
請看1.2
3. 工具鏈2.95.3
3.2 步驟
我們爲開發板取名叫: crane2410, 並在uboot
中建立自己的開發板類型
3.2.1 修改Makefile
[uboot@localhost uboot]#vi Makefile
#爲crane2410建立編譯項
crane2410_config : unconfig
@./mkconfig $(@:_config=) arm arm920t crane2410 NULL s3c24x0
各項的意思如下:
arm: CPU的架構(ARCH)
arm920t: CPU的類型(CPU),其對應於cpu/arm920t子目錄。
crane2410: 開發板的型號(BOARD),對應於board/crane2410目錄。
NULL: 開發者/或經銷商(vender)。
s3c24x0: 片上系統(SOC)。
3.2.2 在board子目錄中建立crane2410
[uboot@localhost uboot]#cp rf
board/smdk2410 board/crane2410
[uboot@localhost uboot]#cd board/crane2410
[uboot@localhost crane2410]#mv smdk2410.c crane2410.c
3.2.3 在include/configs/中建立配置頭文件
[uboot@localhost crane2410]#cd ../..
[uboot@localhost uboot]#cp include/configs/smdk2410.h include/configs/crane2410.h
3.2.4 指定交叉編譯工具的路徑
[uboot@localhost uboot]#vi ~/.bashrc
export PATH=/usr/local/arm/2.95.3/bin:$PATH
3.2.5 測試編譯能否成功
[uboot@localhost uboot]#make crane2410_config
[uboot@localhost uboot]#make CROSS_COMPILE=armlinux3.2.6
修改lowlevel_init.S文件
依照開發板的內存區的配置情況, 修改board/crane2410/lowlevel_init.S文件,我的更改如下:
#include <config.h>
#include <version.h>
#define BWSCON 0x48000000
/* BWSCON */
#define DW8 (0x0)
#define DW16 (0x1)
#define DW32 (0x2)
#define WAIT (0x1<<2)
#define UBLB (0x1<<3)
#define B1_BWSCON (DW16)
#define B2_BWSCON (DW16)
#define B3_BWSCON (DW16 + WAIT + UBLB)
#define B4_BWSCON (DW16)
#define B5_BWSCON (DW16)
#define B6_BWSCON (DW32)
#define B7_BWSCON (DW32)
/* BANK0CON */
#define B0_Tacs 0x3 /* 0clk */
#define B0_Tcos 0x3 /* 0clk */
#define B0_Tacc 0x7 /* 14clk */
#define B0_Tcoh 0x3 /* 0clk */
#define B0_Tah 0x3 /* 0clk */
#define B0_Tacp 0x3
#define B0_PMC 0x3 /* normal */
/* BANK1CON */
#define B1_Tacs 0x3 /* 0clk */
#define B1_Tcos 0x3 /* 0clk */
#define B1_Tacc 0x7 /* 14clk */
#define B1_Tcoh 0x3 /* 0clk */
#define B1_Tah 0x3 /* 0clk */
#define B1_Tacp 0x3
#define B1_PMC 0x0
#define B2_Tacs 0x0
#define B2_Tcos 0x0
#define B2_Tacc 0x7
#define B2_Tcoh 0x0
#define B2_Tah 0x0
#define B2_Tacp 0x0
#define B2_PMC 0x0
#define B3_Tacs 0x0 /* 0clk */
#define B3_Tcos 0x3 /* 4clk */
#define B3_Tacc 0x7 /* 14clk */
#define B3_Tcoh 0x1 /* 1clk */
#define B3_Tah 0x0 /* 0clk */
#define B3_Tacp 0x3 /* 6clk */
#define B3_PMC 0x0 /* normal */
#define B4_Tacs 0x0 /* 0clk */
#define B4_Tcos 0x0 /* 0clk */
#define B4_Tacc 0x7 /* 14clk */
#define B4_Tcoh 0x0 /* 0clk */
#define B4_Tah 0x0 /* 0clk */
#define B4_Tacp 0x0
#define B4_PMC 0x0 /* normal */
#define B5_Tacs 0x0 /* 0clk */
#define B5_Tcos 0x0 /* 0clk */
#define B5_Tacc 0x7 /* 14clk */
#define B5_Tcoh 0x0 /* 0clk */
#define B5_Tah 0x0 /* 0clk */
#define B5_Tacp 0x0
#define B5_PMC 0x0 /* normal */
#define B6_MT 0x3 /* SDRAM */
#define B6_Trcd 0x1
#define B6_SCAN 0x1 /* 9bit */
#define B7_MT 0x3 /* SDRAM */
#define B7_Trcd 0x1 /* 3clk */
#define B7_SCAN 0x1 /* 9bit */
/* REFRESH parameter */
#define REFEN 0x1 /* Refresh enable */
#define TREFMD 0x0 /* CBR(CAS before RAS)/Auto refresh */
#define Trp 0x0 /* 2clk */
#define Trc 0x3 /* 7clk */
#define Tchr 0x2 /* 3clk */
#define REFCNT 1113 /* period=15.6us, HCLK=60Mhz, (2048+1-15.6*60) */
/**************************************/
_TEXT_BASE:
.word TEXT_BASE
.globl lowlevel_init
lowlevel_init:
/* memory control configuration */
/* make r0 relative the current location so that it */
/* reads SMRDATA out of FLASH rather than memory ! */
ldr r0, =SMRDATA
ldr r1, _TEXT_BASE
sub r0, r0, r1
ldr r1, =BWSCON /* Bus Width Status Controller */
add r2, r0, #13*4
0:
ldr r3, [r0], #4
str r3, [r1], #4
cmp r2, r0
bne 0b
/* everything is fine now */
mov pc, lr
.ltorg
/* the literal pools origin */
SMRDATA:
.word
(0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(
B7_BWSCON<<28))
.word
((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
.word
((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
.word
((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
.word
((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
.word
((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
.word
((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
.word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
.word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
.word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
.word 0x31
.word 0x30
.word 0x30
3.2.9 UBOOT的Nand Flash移植
UBOOT的Nand Flash支持見第七部分的第3節.
3.2.8重新編譯u-boot
[uboot@localhost uboot1.1.4]make CROSS_COMPILE=armlinux3.2.9
把u-boot燒入flash
1. 通過仿真器燒入uboot
通過仿真器uboot
燒寫到flash中就可以從NAND flash啓動了.
2. 通過JTAG接口,由工具燒入flash
4 U-BOOT命令的使用
4.1 U-BOOT命令的介紹
UBOOT
常用命令
通常使用help(或者只使用問號?),來查看所有的UBOOT
命令。將會列出在當前配置下所有支持的命令。
但是我們要注意,儘管UBOOT
提供了很多配置選項,並不是所有選項都支持各種處理器和開發板,有些選項
可能在你的配置中並沒有被選上。
4.1.1 獲得幫助信息
通過help可以獲得當前開發板的UBOOT
中支持的命令.
CRANE2410 # help
? - alias for 'help'
autoscr - run script from memory
base - print or set address offset
bdinfo - print Board Info structure
boot - boot default, i.e., run 'bootcmd'
bootd - boot default, i.e., run 'bootcmd'
bootelf - Boot from an ELF image in memory
bootm - boot application image from memory
bootp - boot image via network using BootP/TFTP protocol
bootvx - Boot vxWorks from an ELF image
cmp - memory compare
coninfo - print console devices and information
cp - memory copy
crc32 - checksum calculation
date - get/set/reset date & time
dcache - enable or disable data cache
echo - echo args to console
erase - erase FLASH memory
flinfo - print FLASH memory information
go - start application at address 'addr'
help - print online help
icache - enable or disable instruction cache
iminfo - print header information for application image
imls - list all images found in flash
itest - return true/false on integer compare
loadb - load binary file over serial line (kermit mode)
loads - load S-Record file over serial line
loop - infinite loop on address range
md - memory display
mm - memory modify (auto-incrementing)
mtest - simple RAM test
mw - memory write (fill)
nand - NAND sub-system
nboot - boot from NAND device
nfs - boot image via network using NFS protocol
nm - memory modify (constant address)
ping - send ICMP ECHO_REQUEST to network host
printenv- print environment variables
protect - enable or disable FLASH write protection
rarpboot- boot image via network using RARP/TFTP protocol
reset - Perform RESET of the CPU
run - run commands in an environment variable
saveenv - save environment variables to persistent storage
setenv - set environment variables
sleep - delay execution for some time
tftpboot- boot image via network using TFTP protocol
version - print monitor version
4.2 常用命令使用說明
4.2.1 askenv(F)
在標準輸入(stdin)獲得環境變量。
4.2.2 autoscr
從內存(Memory)運行教本。(注意,從下載地址開始,例如我們的開發板是從0x30008000處開始運
行).
CRANE2410 # autoscr 0x30008000
## Executing script at 30008000
4.2.3 base
打印或者設置當前指令與下載地址的地址偏移。
4.2.4 bdinfo
打印開發板信息
CRANE2410 # bdinfo
-arch_number = 0x000000C1 (CPU體系結構號)
-env_t = 0x00000000 (環境變量)
-boot_params = 0x30000100 (啓動引導參數)
-DRAM bank = 0x00000000 (內存區)
--> start = 0x30000000 (SDRAM起始地址)
--> size = 0x04000000 (SDRAM大小)
-ethaddr = 01:23:45:67:89:AB (以太網地址)
-ip_addr = 192.168.1.5 (IP地址)
-baudrate = 115200 bps (波特率)
4.2.5 bootp
通過網絡使用Bootp或者TFTP協議引導境像文件。
CRANE2410 # help bootp
bootp [loadAddress] [bootfilename]
4.2.6 bootelf
默認從0x30008000引導elf格式的文件(vmlinux)
CRANE2410 # help bootelf
bootelf [address] - load address of ELF image.
4.2.7 bootd(=boot)
引導的默認命令,即運行U-BOOT中在“include/configs/smdk2410.h” 中設置的“bootcmd” 中
的命令。如下:
#define CONFIG_BOOTCOMMAND "tftp 0x30008000 uImage; bootm 0x30008000";
在命令下做如下試驗:
CRANE2410 # set bootcmd printenv
CRANE2410 # boot
bootdelay=3
baudrate=115200
ethaddr=01:23:45:67:89:ab
CRANE2410 # bootd
bootdelay=3
baudrate=115200
ethaddr=01:23:45:67:89:ab
4.2.8 tftp(tftpboot)
即將內核鏡像文件從PC中下載到SDRAM的指定地址,然後通過bootm來引導內核,前提是所用PC要安裝設
置tftp服務。
下載信息:
CRANE2410 # tftp 0x30008000 zImage
TFTP from server 10.0.0.1; our IP address is 10.0.0.110
Filename 'zImage'.
Load address: 0x30008000
Loading: #################################################################
#################################################################
#################################################
done
Bytes transferred = 913880 (df1d8 hex)
4.2.9 bootm
內核的入口地址開始引導內核。
CRANE2410 # bootm 0x30008000
## Booting image at 30008000 ...
Starting kernel ...
Uncompressing
Linux......................................................................
done, .
4.2.10 go
直接跳轉到可執行文件的入口地址,執行可執行文件。
CRANE2410 # go 0x30008000
## Starting application at 0x30008000 ...
4.2.11 cmp
對輸入的兩段內存地址進行比較。
CRANE2410 # cmp 0x30008000 0x30008040 64
word at 0x30008000 (0xe321f0d3) != word at 0x30008040 (0xc022020c)
Total of 0 words were the same
CRANE2410 # cmp 0x30008000 0x30008000 64
Total of 100 words were the same
4.2.12 coninfo
打印所有控制設備和信息,例如
-List of available devices:
-serial 80000003 SIO stdin stdout stderr
4.2.13 cp
內存拷貝,cp 源地址 目的地址 拷貝大小(字節)
CRANE2410 # help cp
cp [.b, .w, .l] source target count
ANE2410 # cp 0x30008000 0x3000f000 64
4.2.14 date
獲得/設置/重設日期和時間
CRANE2410 # date
Date: 2006-6-6 (Tuesday) Time: 06:06:06
4.2.15 erase(F)
擦除FLASH MEMORY, 由於該ARM板沒有Nor Flash, 所有不支持該命令.
CRANE2410 # help erase
erase start end
- erase FLASH from addr 'start' to addr 'end'
erase start +len
- erase FLASH from addr 'start' to the end of sect w/addr 'start'+'len'-1
erase N:SF[-SL]
- erase sectors SF-SL in FLASH bank # N
erase bank N
- erase FLASH bank # N
erase all
- erase all FLASH banks
4.2.16 flinfo(F)
打印Nor Flash信息, 由於該ARM板沒有Nor Flash, 所有不支持該命令.
4.2.17 iminfo
打印和校驗內核鏡像頭, 內核的起始地址由CFG_LOAD_ADDR指定:
#define CFG_LOAD_ADDR 0x30008000 /* default load address */
該宏在include/configs/crane2410.h中定義.
CRANE2410 # iminfo
## Checking Image at 30008000 ...
Image Name: Linux-2.6.14.1
Created: 2006-06-28 7:43:01 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1047080 Bytes = 1022.5 kB
Load Address: 30008000
Entry Point: 30008040
Verifying Checksum ... OK
4.2.18 loadb
從串口下載二進制文件
CRANE2410 # loadb
## Ready for binary (kermit) download to 0x30008000 at 115200 bps...
## Total Size = 0x00000000 = 0 Bytes
## Start Addr = 0x30008000
4.2.19 md
顯示指定內存地址中的內容
CRANE2410 # md 0
00000000: ea000012 e59ff014 e59ff014 e59ff014 ................
00000010: e59ff014 e59ff014 e59ff014 e59ff014 ................
00000020: 33f80220 33f80280 33f802e0 33f80340 [email protected]
00000030: 33f803a0 33f80400 33f80460 deadbeef ...3...3`..3....
00000040: 33f80000 33f80000 33f9c0b4 33fa019c ...3...3...3...3
00000050: e10f0000 e3c0001f e38000d3 e129f000 ..............).
00000060: e3a00453 e3a01000 e5801000 e3e01000 S...............
00000070: e59f0444 e5801000 e59f1440 e59f0440 D.......@...@...
00000080: e5801000 e59f043c e3a01003 e5801000 ....<...........
00000090: eb000051 e24f009c e51f1060 e1500001 Q.....O.`.....P.
000000a0: 0a000007 e51f2068 e51f3068 e0432002 ....h ..h0... C.
000000b0: e0802002 e8b007f8 e8a107f8 e1500002 . ............P.
000000c0: dafffffb e51f008c e2400803 e2400080 ..........@...@.
000000d0: e240d00c e51f0094 e51f1094 e3a02000 ..@.......... ..
000000e0: e5802000 e2800004 e1500001 dafffffb . ........P.....
000000f0: eb000006 e59f13d0 e281f000 e1a00000 ................
4.2.20 mm
順序顯示指定地址往後的內存中的內容,可同時修改,地址自動遞增。
CRANE2410 # mm 0x30008000
30008000: e1a00000 ? fffff
30008004: e1a00000 ? eeeeee
30008008: e1a00000 ? q
CRANE2410 # md 30008000
30008000: 000fffff 00eeeeee e1a00000 e1a00000 ................
30008010: e1a00000 e1a00000 e1a00000 e1a00000 ................
30008020: ea000002 016f2818 00000000 000df1d8 .....(o.........
30008030: e1a07001 e3a08000 e10f2000 e3120003 .p....... ......
4.2.21 mtest
簡單的RAM檢測
CRANE2410 # mtest
Pattern FFFFFFFD Writing... Reading...
4.2.22 mw
向內存地址寫內容
CRANE2410 # md 30008000
30008000: ffffdffd ffffdffc ffffdffb ffffdffa ................
CRANE2410 # mw 30008000 0 4
CRANE2410 # md 30008000
30008000: 00000000 00000000 00000000 00000000 ................
4.2.23 nm
修改內存地址, 地址不遞增
CRANE2410 # nm 30008000
30008000: de4c457f ? 00000000
30008000: 00000000 ? 11111111
30008000: 11111111 ?
4.2.24 printenv
打印環境變量
CRANE2410 # printenv
bootdelay=3
baudrate=115200
ethaddr=01:23:45:67:89:ab
ipaddr=10.0.0.110
serverip=10.0.0.1
netmask=255.255.255.0
stdin=serial
stdout=serial
stderr=serial
Environment size: 153/65532 bytes
4.2.25 ping
ping主機
CRANE2410 # ping 10.0.0.1
host 10.0.0.1 is alive
4.2.26 reset
復位CPU
4.2.27 run
運行已經定義好的U-BOOT的命令
CRANE2410 # set myenv ping 10.0.0.1
CRANE2410 # run myenv
host 10.0.0.1 is alive
4.2.28 saveenv(F)
保存設定的環境變量
4.2.29 setenv
設置環境變量
CRANE2410 # setenv ipaddr 10.0.0.254
CRANE2410 # printenv
ipaddr=10.0.0.254
4.2.30 sleep
命令延時執行時間
CRANE2410 # sleep 1
4.2.31 version
打印U-BOOT版本信息
CRANE2410 # version
U-Boot 1.1.4 (Jul 4 2006 - 12:42:27)
4.2.32 nand info
打印nand flash信息
CRANE2410 # nand info
Device 0: Samsung K9F1208U0B at 0x4e000000 (64 MB, 16 kB sector)
4.2.33 nand device <n>
顯示某個nand設備
CRANE2410 # nand device 0
Device 0: Samsung K9F1208U0B at 0x4e000000 (64 MB, 16 kB sector)
... is now current device
4.2.34 nand bad
CRANE2410 # nand bad
Device 0 bad blocks:
4.2.35 nand read
nand read InAddr FlAddr size
InAddr: 從nand flash中讀到內存的起始地址。
FlAddr: nand flash 的起始地址。
size: 從nand flash中讀取的數據的大小。
CRANE2410 # nand read 0x30008000 0 0x100000
NAND read: device 0 offset 0, size 1048576 ...
1048576 bytes read: OK
4.2.36 nand erease
nand erase FlAddr size
FlAddr: nand flash 的起始地址
size: 從nand flash中擦除數據塊的大小
CRANE2410 # nand erase 0x100000 0x20000
NAND erase: device 0 offset 1048576, size 131072 ... OK
4.2.37 nand write
nand write InAddr FlAddr size
InAddr: 寫到Nand Flash中的數據在內存的起始地址
FlAddr: Nand Flash的起始地址
size: 數據的大小
CRANE2410 # nand write 0x30f00000 0x100000 0x20000
NAND write: device 0 offset 1048576, size 131072 ...
131072 bytes written: OK
4.2.37 nboot
u-boot-1.1.4代碼對於nboot命令的幫助不正確,修改如下:
正確的順序爲:
nboot InAddr dev FlAddr
InAddr: 需要裝載到的內存的地址。
FlAddr: 在nand flash上uImage存放的地址
dev: 設備號
需要提前設置環境變量,否則nboot不會調用bootm
CRANE2410 #setenv autostart yes
CRANE2410 # nboot 30008000 0 100000
Loading from device 0: <NULL> at 0x4e000000 (offset 0x100000)
Image Name: Linux-2.6.14.3
Created: 2006-07-06 7:31:52 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 897428 Bytes = 876.4 kB
Load Address: 30008000
Entry Point: 30008040
Automatic boot of image at addr 0x30008000 ...
## Booting image at 30008000 ...
Starting kernel ...
4.3 命令簡寫說明
所以命令都可以簡寫,只要命令前面的一部分不會跟其它命令相同,就可以不用寫全整個命令.
save命令
CRANE2410 # sa
Saving Environment to Flash...
Un-Protected 1 sectors
Erasing Flash...Erasing sector 10 ... Erased 1 sectors
4.4 把文件寫入NandFlash
如果把一個傳到內存中的文件寫入到Nand Flash中, 如:新的uboot.bin, zImage(內核),
rootfs等, 如果做呢?我們可以用Nand Flash命令來完成. 但是Nand Flash寫時,必須先要把Nand
Flash的寫入區全部擦除後,才能寫. 下面以把內存0x30008000起長度爲0x20000的內容寫到Nand
Flash中的0x100000爲例.
CRANE2410 # nand erase 0x100000 20000
NAND erase: device 0 offset 1048576, size 131072 ... OK
CRANE2410 # nand write 0x30008000 0x100000 0x20000
NAND write: device 0 offset 1048576, size 131072 ...
131072 bytes written: OK
5 參考資料
1. uboot
在s3c2410開發板上移植(NAND Flash Boot)過程
http://dev.csdn.net/article/84/84538.shtm
第五部分 linux 2.6內核的移植
1 內核移植過程
1.1 下載linux內核
http://www.kernel.org/pub/linux/kernel/v2.6/linux2.6.14.1.
tar.bz2
下載linux2.6.14.1
內核至home/arm/dev_home/kernel.
[root@localhost ~]#su arm
[arm@localhost ~]#cd $KERNEL
[arm@localhost kernel]#tar xzvf
linux2.6.14.1.
tar.gz
[arm@localhost kernel]# pwd
/home/arm/dev_home/kernel
[arm@localhost kernel]# cd linux2.6.14
進入內核解壓後的目錄,以後示例中,只要是相對路徑全部是相對於
/home/arm/dev_home/kernel/linux2.6.14/
此目錄
1.2 修改Makefile
修改內核目錄樹根下的的Makefile,指明交叉編譯器
[arm@localhost linux2.6.14]#
vi Makefile
找到ARCH和CROSS_COMPILE,修改
ARCH ?= arm
CROSS_COMPILE ?= armlinux
然後設置你的PATH環境變量,使其可以找到你的交叉編譯工具鏈
[arm@localhost linux2.6.14]#
echo $PATH
/usr/local/arm/3.4.4/bin:/usr/kerberos/bin:/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/home/ly/bin
如果/usr/local/arm/3.4.4/bin搜索路徑, 加入下面語句在~/.bashrc中
[arm@localhost linux2.6.14]#
vi ~/.bashrc
export PATH=/usr/local/arm/3.4.4/bin:$PATH
再重新登陸.
[arm@localhost linux2.6.14]#
su arm
1.3 設置flash分區
此處一共要修改3個文件,分別是:
1.3.1指明分區信息
在arch/arm/machs3c2410/
devs.c文件中:
[arm@localhost linux2.6.14]$
vi arch/arm/machs3c2410/
devs.c
添加如下內容:
#include <linux/mtd/partitions.h>
#include <linux/mtd/nand.h>
#include <asm/arch/nand.h>
...
/* NAND Controller */
1.建立Nand Flash分區表
/* 一個Nand Flash總共64MB, 按如下大小進行分區 */
static struct mtd_partition partition_info[] ={
{ /* 1MB */
name: "bootloader",
size: 0x00100000,
offset: 0x0,
},{ /* 3MB */
name: "kernel",
size: 0x00300000,
offset: 0x00100000,
}, { /* 40MB */
name: "root",
size: 0x02800000,
offset: 0x00400000,
}, { /* 20MB */
name: "user",
size: 0x00f00000,
offset: 0x02d00000,
}
};
name: 代表分區名字
size: 代表flash分區大小(單位:字節)
offset: 代表flash分區的起始地址(相對於0x0的偏移)
目標板計劃分4個區,分別存放bootloader, kernel, rootfs以及以便以後擴展使用的用戶文件系統空間。
各分區在Nand flash中起始地址. 分區大小. 記錄如下:
bootloader:
start: 0x00000000
len: 0x00100000
1MB
kernel:
start: 0x00100000
len: 0x00300000
3MB
rootfs:
start: 0x00400000
len: 0x02800000
40MB
User:
start: 0x02c00000
len: 0x01400000
20MB
2. 加入Nand Flash分區
struct s3c2410_nand_set nandset ={
nr_partitions: 4, /* the number of partitions */
partitions: partition_info, /* partition table */
};
nr_partitions: 指明partition_info中定義的分區數目
partitions: 分區信息表
3. 建立Nand Flash芯片支持
struct s3c2410_platform_nand superlpplatform={
tacls:0,
twrph0:30,
twrph1:0,
sets: &nandset,
nr_sets: 1,
};
tacls, twrph0, twrph1的意思見S3C2410手冊的63,
這3個值最後會被設置到NFCONF中,見S3C2410手冊66.
sets: 支持的分區集
nr_set:分區集的個數
4. 加入Nand Flash芯片支持到Nand Flash驅動
另外,還要修改此文件中的s3c_device_nand結構體變量,添加對dev成員的賦值
struct platform_device s3c_device_nand = {
.name = "s3c2410nand",
/* Device name */
.id = 1,
/* Device ID */
.num_resources = ARRAY_SIZE(s3c_nand_resource),
.resource = s3c_nand_resource, /* Nand Flash Controller Registers */
/* Add the Nand Flash device */
.dev = {
.platform_data = &superlpplatform
}
};
name: 設備名稱
id: 有效設備編號,如果只有唯一的一個設備爲1,
有多個設備從0開始計數.
num_resource: 有幾個寄存器區
resource: 寄存器區數組首地址
dev: 支持的Nand Flash設備
1.3.2 指定啓動時初始化
kernel啓動時依據我們對分區的設置進行初始配置
修改arch/arm/machs3c2410/
machsmdk2410.
c文件
[arm@localhost linux2.6.14]$
vi arch/arm/machs3c2410/
machsmdk2410.
c
修改smdk2410_devices[].指明初始化時包括我們在前面所設置的flash分區信息
static struct platform_device *smdk2410_devices[] __initdata = {
&s3c_device_usb,
&s3c_device_lcd,
&s3c_device_wdt,
&s3c_device_i2c,
&s3c_device_iis,
/* 添加如下語句即可 */
&s3c_device_nand,
};
保存,退出。
1.3.3 禁止Flash ECC校驗
我們的內核都是通過UBOOT寫到Nand Flash的, UBOOT通過的軟件ECC算法產生ECC校驗碼, 這與內核
校驗的ECC碼不一樣, 內核中的ECC碼是由S3C2410中Nand Flash控制器產生的. 所以, 我們在這裏選擇禁止
內核ECC校驗.
修改drivers/mtd/nand/s3c2410.c 文件:
[arm@localhost linux2.6.14]$
vi drivers/mtd/nand/s3c2410.c
找到s3c2410_nand_init_chip()函數,在該函數體最後加上一條語句:
chip>
eccmode = NAND_ECC_NONE;
保存,退出。
OK.我們的關於flash分區的設置全部完工.
1.4 配置內核
1.4.1 支持啓動時掛載devfs
爲了我們的內核支持devfs以及在啓動時並在/sbin/init運行之前能自動掛載/dev爲devfs文件系統,修改
fs/Kconfig文件
[arm@localhost linux2.6.14]$
vi fs/Kconfig
找到menu "Pseudo filesystems"
添加如下語句:
config DEVFS_FS
bool "/dev file system support (OBSOLETE)"
default y
config DEVFS_MOUNT
bool "Automatically mount at boot"
default y
depends on DEVFS_FS
1.4.2配置內核產生.config文件
[arm@localhost linux2.6.14]$
cp arch/arm/configs/smdk2410_defconfig .config
[arm@localhost linux2.6.14]$
make menuconfig
在smdk2410_defconfig基礎上,我所增刪的內核配置項如下:
Loadable module support >
[*] Enable loadable module support
[*] Automatic kernel module loading
System Type >
[*] S3C2410 DMA support
Boot options >
Default kernel command string:
noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0,115200
#說明:mtdblock2代表我的第3個flash分區,它是我的rootfs
# console=ttySAC0,115200使kernel啓動期間的信息全部輸出到串口0上.
# 2.6內核對於串口的命名改爲ttySAC0,但這不影響用戶空間的串口編程。
# 用戶空間的串口編程針對的仍是/dev/ttyS0等
Floating point emulation >
[*] NWFPE math emulation
This is necessary to run most binaries!!!
#接下來要做的是對內核MTD子系統的設置
Device Drivers >
Memory Technology Devices (MTD) >
[*] MTD partitioning support
#支持MTD分區,這樣我們在前面設置的分區纔有意義
[*] Command line partition table parsing
#支持從命令行設置flash分區信息,靈活
RAM/ROM/Flash chip drivers >
<*> Detect flash chips by Common Flash
Interface (CFI) probe
<*> Detect nonCFI
AMD/JEDECcompatible
flash chips
<*> Support for Intel/Sharp flash chips
<*> Support for AMD/Fujitsu flash chips
<*> Support for ROM chips in bus mapping
NAND Flash Device Drivers >
<*> NAND Device Support
<*> NAND Flash support for S3C2410/S3C2440 SoC
Character devices >
[*] Nonstandard
serial port support
[*] S3C2410 RTC Driver
#接下來做的是針對文件系統的設置,本人實驗時目標板上要上的文件系統是cramfs,故做如下配置
File systems >
<> Second extended fs support #去除對ext2的支持
Pseudo filesystems >
[*] /proc file system support
[*] Virtual memory file system support (former shm fs)
[*] /dev file system support (OBSOLETE)
[*] Automatically mount at boot (NEW)
#這裏會看到我們前先修改fs/Kconfig的成果,devfs已經被支持上了
Miscellaneous filesystems >
<*> Compressed ROM file system support (cramfs)
#支持cramfs
Network File Systems >
<*> NFS file system support
保存退出,產生.config文件.
.config文件能從提供的2.4.14.1的內核包中找到,文件名爲config.back.
1.4.3編譯內核
[arm@localhost linux2.6.14]$
make zImage
注意:若編譯內核出現如下情況
LD .tmp_vmlinux1
armlinuxld:
arch/arm/kernel/vmlinux.lds:1439: parse error
make: *** [.tmp_vmlinux1] Error 1
解決方法:修改arch/arm/kernel/vmlinux.lds
[arm@localhost linux2.6.14]$
vi arch/arm/kernel/vmlinux.lds
將文件尾2條的ASSERT註釋掉(1439行)
/* ASSERT((__proc_info_end __
proc_info_begin), "missing CPU support") */
/* ASSERT((__arch_info_end __
arch_info_begin), "no machine record defined") */
然後重新make zImage即可
1.4.4 下載zImage到開發板
CRANE2410 # tftp 0x30008000 zImage
TFTP from server 192.168.1.6; our IP address is 192.168.1.5
Filename 'zImage'.
Load address: 0x30008000
Loading: #################################################################
#################################################################
#################################################################
#############################
done
Bytes transferred = 1142856 (117048 hex)
CRANE2410 # bootm 0x30008000
1.4.5 目標板啓動信息如下
IRQ Stack: 33fc149c
FIQ Stack: 33fc249c
1
1
DRAM Configuration:
Bank #0: 30000000 64 MB
1
NAND:64 MB
In: serial
Out: serial
Err: serial
Hit any key to stop autoboot: 0
zImage magic = 0x016f2818
NOW, Booting Linux......
Uncompressing Linux............................................................................ don.Linux version 2.6.14.1 (arm@dozec) (gcc
version 3.3.2) #15 Thu Jul 6 14:26:29 CST 2006
CPU: ARM920Tid(wb) [41129200] revision 0 (ARMv4T)
Machine: SMDK2410
Warning: bad configuration page, trying to continue
Memory policy: ECC disabled, Data cache writeback
CPU S3C2410A (id 0x32410002)
S3C2410: core 202.800 MHz, memory 101.400 MHz, peripheral 50.700 MHz
S3C2410 Clocks, (c) 2004 Simtec Electronics
CLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL on
CPU0: D VIVT writeback
cache
CPU0: I cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets
CPU0: D cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets
Built 1 zonelists
Kernel command line: noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0,115200
irq: clearing subpending status 00000002
PID hash table entries: 128 (order: 7, 2048 bytes)
timer tcon=00500000, tcnt a509, tcfg 00000200,00000000, usec 00001e4c
Console: colour dummy device 80x30
Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
Inodecache
hash table entries: 2048 (order: 1, 8192 bytes)
Memory: 16MB = 16MB total
Memory: 13712KB available (1927K code, 422K data, 104K init)
Mountcache
hash table entries: 512
CPU: Testing write buffer coherency: ok
softlockup thread 0 started up.
NET: Registered protocol family 16
S3C2410: Initialising architecture
SCSI subsystem initialized
usbcore: registered new driver usbfs
usbcore: registered new driver hub
S3C2410 DMA Driver, (c) 20032004
Simtec Electronics
DMA channel 0 at c1800000, irq 33
DMA channel 1 at c1800040, irq 34
DMA channel 2 at c1800080, irq 35
DMA channel 3 at c18000c0, irq 36
NetWinder Floating Point Emulator V0.97 (double precision)
devfs: 20040131
Richard Gooch ([email protected])
devfs: boot_options: 0x1
Console: switching to colour frame buffer device 80x25
fb0: Virtual frame buffer device, using 1024K of video memory
S3C2410 RTC, (c) 2004 Simtec Electronics
s3c2410_serial0 at MMIO 0x50000000 (irq = 70) is a S3C2410
s3c2410_serial1 at MMIO 0x50004000 (irq = 73) is a S3C2410
s3c2410_serial2 at MMIO 0x50008000 (irq = 76) is a S3C2410
io scheduler noop registered
io scheduler anticipatory registered
io scheduler deadline registered
io scheduler cfq registered
RAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksize
Cirrus Logic CS8900A driver for Linux (Modified for SMDK2410)
eth0: CS8900A rev E at 0xe0000300 irq=53, no eeprom , addr: 08: 0:3E:26:0A:5B
S3C24XX NAND Driver, (c) 2004 Simtec Electronics
s3c2410nand:
mapped registers at c1980000
s3c2410nand:
timing: Tacls 10ns, Twrph0 30ns, Twrph1 10ns
NAND device: Manufacturer ID: 0xec, Chip ID: 0x76 (Samsung NAND 64MiB 3,3V 8bit)
NAND_ECC_NONE selected by board driver. This is not recommended !!
Scanning device for bad blocks
Creating 4 MTD partitions on "NAND 64MiB 3,3V 8bit":
0x000000000x00100000
: "bootloader"
0x001000000x00500000
: "kernel"
0x005000000x02d00000
: "root"
0x02d000000x03c00000
: "User"
usbmon: debugfs is not available
116x: driver isp116xhcd,
05 Aug 2005
s3c2410ohci
s3c2410ohci:
S3C24XX OHCI
s3c2410ohci
s3c2410ohci:
new USB bus registered, assigned bus number 1
s3c2410ohci
s3c2410ohci:
irq 42, io mem 0x49000000
usb usb1: Product: S3C24XX OHCI
usb usb1: Manufacturer: Linux 2.6.14.1 ohci_hcd
usb usb1: SerialNumber: s3c24xx
hub 10:
1.0: USB hub found
hub 10:
1.0: 2 ports detected
sl811: driver sl811hcd,
19 May 2005
usbcore: registered new driver cdc_acm
drivers/usb/class/cdcacm.
c: v0.23:USB Abstract Control Model driver for USB modems and ISDN
adaptesdrivers/usb/class/bluetty.c: USB Bluetooth support registered
usbcore: registered new driver bluetty
drivers/usb/class/bluetty.c: USB Bluetooth tty driver v0.13
usbcore: registered new driver usblp
drivers/usb/class/usblp.c: v0.13: USB Printer Device Class driver
Initializing USB Mass Storage driver...
usbcore: registered new driver usbstorage
USB Mass Storage support registered.
mice: PS/2 mouse device common for all mice
NET: Registered protocol family 2
IP route cache hash table entries: 256 (order: 2,
1024 bytes)
TCP established hash table entries: 1024 (order: 0, 4096 bytes)
TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
TCP: Hash tables configured (established 1024 bind 1024)
TCP reno registered
TCP bic registered
NET: Registered protocol family 1
NET: Registered protocol family 17
Reading data from NAND FLASH without ECC is not recommended
VFS: Mounted root (cramfs filesystem) readonly.
Mounted devfs on /dev
Freeing init memory: 104K
Reading data from NAND FLASH without ECC is not recommended
mount /etc as ramfs
recreate
the /etc/mtab entries
mount
/dev/shm as tmpfs
mount
/proc as proc
mount
/sys as sysfs
init started: BusyBox v1.1.3 (2006.07.0303:
43+0000) multicall
binary
Starting pid 28, console /dev/tts/0: '/etc/init.d/rcS'
in /etc/init.d/rcS
/
sbin/ifconfig eth0 192.168.1.5
Please press Enter to activate this console.
#
1.5 Linux 下cs8900a的移植說明
1.5.1 爲cs8900a建立編譯菜單
1. 拷貝到文件
把cs8900a的壓縮包拷貝到arm用戶下的dev_home/localapps/
[arm@localhost localapps]$ tar xzvf
cs8900a.tar.gz
[arm@localhost localapps]$cd cs8900a
[arm@localhost cs8900a]$cp cs8900a.c $KERNEL/linux2.6.14.1/
drivers/net/
[arm@localhost cs8900a]$cp cs8900.h $KERNEL/linux2.6.14.1/
drivers/net/
2. 修改Kconfig文件
[arm@localhost cs8900a]$vi $KERNEL/linux2.6.14.1/
drivers/net/Kconfig
#加入如下內容
config CS8900a
tristate "CS8900a support"
depends on NET_ETHERNET && ARM && ARCH_SMDK2410
helpSupport
for CS8900A chipset based Ethernet cards. If you have a network (Ether
net) card of this type, say Y and read the EthernetHOWTO,
available from as
well as.
To compile this driver as a module, choose M here and read.
The module will be called cs8900.o.
3. 修改Makefile文件
[arm@localhost cs8900a]$vi $KERNEL/linux2.6.14.1/
drivers/net/Makefile
#加入如下內容
obj$(
CONFIG_CS8900a) += cs8900a.o
1.5.2 修改S3C2410相關信息
1. 加入CS8900A在內存中的起始位置
[arm@localhost cs8900a]$cp regcs8900.
h $KERNEL/linux2.6.14.1/
include/asmarm/
archs3c2410/
cs8900.h的內容如下:
#ifndef _INCLUDE_CS8900A_H_
#define _INCLUDE_CS8900A_H_
#include <linux/config.h>
#define pSMDK2410_ETH_IO 0x19000000 /* S3C2410_CS3 0x18000000 */
#define vSMDK2410_ETH_IO 0xE0000000
#define SMDK2410_ETH_IRQ IRQ_EINT9
#endif
2. 加入cs8900A的物理地址到虛擬地址的映射
[arm@localhost cs8900a]$vi $KERNEL/linux2.6.14.1/
arch/arm/machs3c2410/
machsmdk2410.
c
/* 加入如下內容 */
static struct map_desc smdk2410_iodesc[] __initdata = {
{vSMDK2410_ETH_IO, 0x19000000, SZ_1M, MT_DEVICE} /* Add this line */
};
2 創建uImage
2.1 相關技術背景介紹
前面已經介紹了內核編譯後,生成zImage的內核鏡像文件。該鏡像文件可以通過UBOOT
提供的go命令,
跳轉執行,引導內核。同時在uboot1.1.4
的tools目錄下,提供了生成uImage的工具mkimage命令,在生成
uboot
的二進制鏡像文件的同時,mkimage命令會同時編譯生成,無需另外編譯。通過mkimage命令,在
zImage中加入頭文件(鏡像頭長0x40,真正的內核入口向後偏移了0x40大小),生成uImage鏡像文件,該文
件就是執行bootm所需的內核鏡像文件。
2.2 在內核中創建uImage的方法
2.2.1 獲取mkimage工具
2.6內核樹的Makefile提供了創建uImage的方法,但需要我們提供相應的mkimage命令。
所以首先拷貝uboot
中tools目錄下編譯後生成的mkimage到/usr/bin/下,然後便可以在內核根目錄下通過
make uImage
來創建uImage文件。該文件生成在arch/arm/boot/下。
2.2.2 修改內核的Makefile文件
[arm@localhost linux2.6.14.1]$
vi arch/arm/boot/Makefile
#MKIMAGE變量記錄mkimage命令的路徑mkuboot.sh腳本文件可以scripts目錄中找到
MKIMAGE := $(srctree)/scripts/mkuboot.sh
#zreladdry
與params_physy
可以在arch/arm/machs3c2410/
Makefile.boot當中找到
ZRELADDR := $(zreladdry)
PARAMS_PHYS := $(params_physy)
INITRD_PHYS := $(initrd_physy)
#生成uImage的mkImage命令行,其中需要關注的就是a
與 e
參數。
#參數a:
指明uImage加載的SDRAM地址,內核默認指定加載地址爲0x30008000。
# uboot
引導時,bootm命令跳到與上相同位置執行,檢查完鏡像頭後,它會跳到內核真正的入口點開
始執行。
#參數e:
指明uImage中刨去鏡像頭後真正的內核入口地址。
# 鏡像頭爲0x40長,故此處指定爲0x30008040。
# uboot
引導時,go命令可以直接指定此位置。go命令不檢查鏡像頭。
quiet_cmd_uimage = UIMAGE $@
cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) A
arm O
linux T
kernel /
C
none a
$(ZRELADDR) e
0x30008040 /
n
'Linux$(
KERNELRELEASE)' d
$< $@
3追加實驗記錄
以同樣方式移植其他2.6主線內核,出現問題如下:
3.1移植linux-2.6.15.7
編譯通過,啓動時顯示:
VFS: Cannot open root device "mtdblock2" or unknownblock(
31,2)
Please append a correct "root=" boot option
Kernel panic not
syncing: VFS: Unable to mount root fs on unknownblock(
31,2)
3.2移植linux-2.6.16.21
編譯通過,啓動時顯示:
VFS: Cannot open root device "mtdblock2" or unknownblock(
31,2)
Please append a correct "root=" boot option
Kernel panic not
syncing: VFS: Unable to mount root fs on unknownblock(
31,2)
3.3 移植linux-2.6.17
編譯失敗
4 參考資料
1. Porting kernel 2.6.11.7 to S3C2410
http://superlp.blogchina.com/1391393.html
非常感謝此篇文檔的作者
2. devfs介紹
http://www128.
ibm.com/developerworks/cn/linux/filesystem/lfs4/
index.html#resources
3. <<BUILDING EMBEDDED LINUX SYSTEMS>>
中文名:<<構建嵌入式Linux系統>>
第六部分 應用程序的移植
1構造目標板的根目錄及文件系統
1.1 建立一個目標板的空根目錄
我們將在這裏構建構建根文件系統,創建基礎目錄結構. 存放交叉編譯後生成的目標應用程序
(BUSYBOX,TINYLOGIN),存放庫文件等。
[arm@localhost rootfs]# mkdir my_rootfs
[arm@localhost rootfs]# pwd
/home/arm/dev_home/rootfs/my_rootfs
[arm@localhost rootfs]# cd my_rootfs
[arm@localhost my_rootfs]#
1.2 在my_rootfs中建立Linux目錄樹
[arm@localhost my_rootfs]#mkdir bin dev etc home lib mnt proc sbin sys tmp root usr
[arm@localhost my_rootfs]#mkdir mnt/etc
[arm@localhost my_rootfs]#mkdir usr/bin usr/lib usr/sbin
[arm@localhost my_rootfs]#touch linuxrc
[arm@localhost my_rootfs]#tree
|bin
|dev
|etc
|home
|lib
|linuxrc
/* 此文件爲啓動腳本,是一shell腳本文件。本文後面有專門介紹 */
|mnt
| `etc
|proc
|sbin
|sys
|tmp
|root
`usr
|bin
|lib
`sbin
權限參照你的linux工作站即可,基礎目錄介紹參見本文參考資料(未尾)。
需要說明的一點就是etc目錄存放配置文件,這個目錄通常是需要修改的,所以在linuxrc腳本當中將etc目錄
掛載爲ramfs文件系統,然後將mnt/etc目錄中的所有配置文件拷貝到etc目錄當中,這在下一節的linuxrc腳本
文件當中會有體現。
1.3 創建linuxrc文件
1. 創建linuxrc,加入如下內容:
[arm@localhost my_rootfs]#vi linuxrc
#!/bin/sh
#掛載/etc爲ramfs, 並從/mnt/etc下拷貝文件到/etc目錄當中
echo "mount /etc as ramfs"
/bin/mount n
t
ramfs ramfs /etc
/bin/cp a
/mnt/etc/* /etc
echo "recreate
the /etc/mtab entries"
# recreate
the /etc/mtab entries
/bin/mount f
t
cramfs o
remount,ro /dev/mtdblock/2 /
#mount some file system
echo "mount
/dev/shm as tmpfs"
/bin/mount n
t
tmpfs tmpfs /dev/shm
#掛載/proc爲proc文件系統
echo "mount
/proc as proc"
/bin/mount n
t
proc none /proc
#掛載/sys爲sysfs文件系統
echo "mount
/sys as sysfs"
/bin/mount n
t
sysfs none /sys
exec /sbin/init
2. 修改權限
[arm@localhost my_rootfs]#chmod 775 linuxrc
[arm@localhost my_rootfs]#ls linuxrc al
rwxrwxrx
1 root root 533 Jun 4 11:19 linuxrc
當編譯內核時,指定命令行參數如下
Boot options >
Default kernel command string: 我的命令行參數如下
noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0,115200
其中的init指明kernel執行後要加載的第一個應用程序,缺省爲/sbin/init,此處指定爲/linuxrc
2 移植Busybox
2.1 下載busybox
http://www.busybox.net/downloads/busybox1.1.3.
tar.gz/下載busybox1.1.3
到/tmp目錄當中,並解壓.
2.2 進入解壓後的目錄,配置Busybox
[arm@localhost busybox1.1.3]$
make menuconfig
Busybox Settings >
General Configuration >
[*] Support for devfs
Build Options >
[*] Build BusyBox as a static binary (no shared libs)
/* 將busybox編譯爲靜態連接,少了啓動時找動態庫的麻煩 */
[*] Do you want to build BusyBox with a Cross Compiler?
(/usr/local/arm/3.3.2/bin/armlinux)
Cross Compiler prefix
/* 指定交叉編譯工具路徑 */
Init Utilities >
[*] init
[*] Support reading an inittab file
/* 支持init讀取/etc/inittab配置文件,一定要選上 */
Shells >
Choose your default shell (ash) >
/* (X) ash 選中ash,這樣生成的時候纔會生成bin/sh文件
* 看看我們前頭的linuxrc腳本的頭一句:
* #!/bin/sh 是由bin/sh來解釋執行的
*/
[*] ash
Coreutils >
[*] cp
[*] cat
[*] ls
[*] mkdir
[*] echo (basic SuSv3 version taking no options)
[*] env
[*] mv
[*] pwd
[*] rm
[*] touch
Editors >
[*] vi
Linux System Utilities >
[*] mount
[*] umount
[*] Support loopback mounts
[*] Support for the old /etc/mtab file
Networking Utilities >
[*] inetd
/*
* 支持inetd超級服務器
* inetd的配置文件爲/etc/inetd.conf文件,
* "在該部分的4: 相關配置文件的創建"一節會有說明
*/
2.3 編譯並安裝Busybox
[arm@localhost busybox1.1.3]$
make TARGET_ARCH=arm CROSS=armlinux/
PREFIX=/home/arm/dev_home/rootfs/my_rootfs/ all install
PREFIX指明安裝路徑:就是我們根文件系統所在路徑。
*這裏需要注意一點的是,只要install busybox,我們根文件系統下先前建好的linuxrc就會被覆蓋爲一同名二進
制文件。
所以要事先備份我們自己的linuxrc,在安裝完busybox後,將linuxrc複製回去就好。
3 移植TinyLogin
3.1 下載
http://tinylogin.busybox.net/downloads/tinylogin1.4.
tar.bz2 下載tinylogin1.4
到/tmp目錄當中,並解壓.
3.2 修改tinyLogin的Makefile
[arm@localhost tinylogin1.4]$
vi Makefile
修改記錄如下:
指明靜態編譯,不連接動態庫
DOSTATIC = true
指明tinyLogin使用自己的算法來處理用戶密碼
USE_SYSTEM_PWD_GRP = false
USE_SYSTEM_SHADOW = false
3.3 編譯並安裝
[root@localhost tinylogin1.4]#
make CROSS=armlinuxPREFIX=/
home/arm/dev_home/rootfs/my_rootfs all install
PREFIX指明根文件路徑
4 相關配置文件的創建
進入mnt/etc中, 這裏是我們存放配置文件的路徑
[arm@localhost my_rootfs]$ cd mnt/etc
4.1 創建帳號及密碼文件
[arm@localhost etc]$ cp /etc/passwd .
[arm@localhost etc]$ cp /etc/shadow .
[arm@localhost etc]$ cp /etc/group .
這3個文件是從你工作站當中拷貝過來的,刪除其中絕大部分不需要的用戶,經過刪減後的上述3個文件如下。
那麼現在root的登陸密碼
和你工作站上的登陸口令一致了,這可能透露你工作站的信息
[arm@localhost etc]$ cat passwd
root:x:0:0:root:/root:/bin/sh /* 改爲/bin/sh */
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[arm@localhost etc]$ cat shadow
root:$1$2LG20u89$UCEEUzBhElYpKMNZQPU.e1:13303:0:99999:7:::
bin:*:13283:0:99999:7:::
daemon:*:13283:0:99999:7:::
[arm@localhost etc]$ cat group
root:x:0:root
bin:x:1:root,bin,daemon
daemon:x:2:root,bin,daemon
4.2 創建profile文件
[arm@localhost etc]$ vi profile
# Set search library path
# 這條語句設置動態庫的搜索路徑,極其重要!!!
echo "Set search library path int /etc/profile"
export LD_LIBRARY_PATH=/lib:/usr/lib
# Set user path
echo "Set user path in /etc/profile"
PATH=/bin:/sbin:/usr/bin:/usr/sbin
export PATH
4.4 創建fstab文件
[arm@localhost etc]$ vi fstab
none /proc proc defaults 0 0
none /dev/pts devpts mode=0622 0 0
tmpfs /dev/shm tmpfs defaults 0 0
4.5 創建inetd.conf配置文件
此處只是一個經過修改的示例配置文件,用於代理監聽telnetd的23端口。
讀者可以根據自己需求進行修改。該配置文件可以從busybox的examples目錄中獲得
[arm@localhost etc]$ vi inetd.conf
# <service_name> <sock_type> <proto> <flags> <user> <server_path> <args>
#ftp stream tcp nowait root /usr/sbin/ftpd
telnet stream tcp nowait root /usr/sbin/telnetd
5 移植inetd
5.1 inetd的選擇及獲取
Busybox1.1.3提供了inetd支持。如果讀者使用的是較低版本的不提供inetd的Busybox,那麼可以考慮使
用netkit套件來提供網絡服務。強烈建議使用高版本的Busybox。此節後半部分介紹如果編譯佈署netkit當中的
inetd。
5.1.1 獲取inetd
Netkit套件可以從ftp://ftp.uk.linux.org/pub/linux/Networking/netkit/下載。
其中netkitbase0.17
中包括inetd程序。下載netkitbase0.17
到/tmp目錄並解壓。
5.2 編譯inetd
5.2.1 修改configure文件
開始配置netkitbase
之前需要先修改configure腳本以免它在主機上執行測試程序。
[arm@localhost netkitbase0.17]#
vi configure
將每一行出現的 ./__conftest || exit 1;
修改成:
# ./__conftest || exit 1;
5.2.2 編譯
[arm@localhost netkitbase0.17]$
CC=armlinuxgcc
./configure
[arm@localhost netkitbase0.17]$
make
5.3 配置inetd
5.3.1 拷貝inetd到根文件系統的usr/sbin目錄中
[arm@localhost netkitbase0.17]$
cp inetd/inetd /home/arm/dev_home/rootfs/my_rootfs/usr/sbin/
拷貝inetd的配置文件inetd.conf到根文件系統的/mnt/etc目錄中
[arm@localhost netkitbase0.17]$
cp etc.sample/inetd.conf /home/arm/dev_home/rootfs/my_rootfs/mnt/etc
5.3.2 根據需要,修改inetd.conf配置文件
例如:支持telnetd的inetd.conf配置文件如下
# <service_name> <sock_type> <proto> <flags> <user> <server_path> <args>
telnet stream tcp nowait root /usr/sbin/telnetd
5.3.3 拷貝配置文件
etc.sample目錄下有許多網絡相關配置文件,其中有一些需要拷貝到根文件系統的etc目錄當中,記錄如下:
[arm@localhost netkitbase0.17]$
cd etc.sample/
[arm@localhost etc.sample]$ cp host.conf /home/arm/dev_home/rootfs/my_rootfs/mnt/etc/
[arm@localhost etc.sample]$ cp hosts /home/arm/dev_home/rootfs/my_rootfs/mnt/etc/
[arm@localhost etc.sample]$ cp networks /home/arm/dev_home/rootfs/my_rootfs/mnt/etc/
[arm@localhost etc.sample]$ cp protocols /home/arm/dev_home/rootfs/my_rootfs/mnt/etc/
[arm@localhost etc.sample]$ cp resolv.conf /home/arm/dev_home/rootfs/my_rootfs/mnt/etc/
[arm@localhost etc.sample]$ cp services /home/arm/dev_home/rootfs/my_rootfs/mnt/etc/
以上重要配置文件說明如下:
host.conf:在系統中同時存在着DNS域名解析和/etc/hosts的主機表機制時,由文件/etc/host.conf來說明了解析器
的查詢順序
hosts:記錄主機名到IP地址的映射
protocols:記錄常用網絡協議及端口別名關係,網絡應用程序依賴於此文件
resolv.conf:指定DNS服務器
services:記錄知名網絡服務及端口,網絡編程依賴於此文件
6 移植thttpd Web服務器
6.1 下載
http://www.acme.com/software/thttpd/ 下載thttpd到/tmp目錄當中,並解壓.
6.2 編譯thttpd
[arm@localhost thttpd2.25b]$
CC=armlinuxgcc
./configure host=
armlinux
[arm@localhost thttpd2.25b]$
vi Makefile
指定靜態鏈接二進制文件
LDFLAGS = static
[arm@localhost thttpd2.25b]$
make LDFLAGS="static"
6.3 配置
6.3.1 拷貝thttpd二進制可執行文件到根文件系統/usr/sbin/目錄中
[arm@localhost thttpd2.25b]$
cp thttpd /home/arm/dev_home/rootfs/my_rootfs/usr/sbin/
6.3.2 修改thttpd配置文件
[arm@localhost thttpd2.25b]$
vi contrib/redhatrpm/
thttpd.conf
# This section overrides defaults
dir=/etc/thttpd/html #指明WebServer存放網頁的根目錄路徑
chroot
user=root #以root身份運行thttpd
logfile=/etc/thttpd/log/thttpd.log #日誌文件路徑
pidfile=/etc/thttpd/run/thttpd.pid #pid文件路徑
拷貝thttpd.conf配置文件到根文件系統的mnt/etc/目錄,
系統加載後,linuxrc腳本會自動將mnt/etc/下的所有文件拷貝到/etc目錄中。
[arm@localhost thttpd2.25b]$
cp contrib/redhatrpm/
thttpd.conf /home/arm/dev_home/rootfs/my_rootfs/mnt/etc/
6.3.3 轉移到根文件系統目錄,創建相應的文件
[arm@localhost etc]$ cd /home/arm/dev_home/rootfs/my_rootfs
[arm@localhost my_rootfs]$ cd mnt/etc/
創建thttpd目錄
[arm@localhost etc]$ mkdir thttpd
[arm@localhost etc]$ cd thttpd
thttpd目錄下的目錄結構
|html
| `index.
html Web Server網頁根目錄下的默認HTML文件
|log
| `thttpd.
log 創建一個空文件就可
`run
`thttpd.
pid 創建一個空文件就可
html目錄下的index.html文件內容如下:
<html>
<head>
<title> Welcome to here^^ </title>
</head>
<body>
<marquee>
<font color=red>
Welcome to here^^!!!
</font>
</marquee>
</body>
</html>
7 建立根目錄文件系統包
7.1 建立CRAMFS包
7.1.1 下載cramfs工具
http://prdownloads.sourceforge.net/cramfs/cramfs1.1.
tar.gz 下載源代碼包.
把下載包拷貝到dev_home/tools下.
[arm@localhost tools]$tar xzvf
cramfs1.1.
tar.gz
[arm@localhost tools]$cd cramfs1.1
[arm@localhost tools]$make
[arm@localhost tools]$su root
[root@localhost tools]$cp mkcramfs /usr/bin
[arm@localhost tools]$exit
注意:如果你的系統中已經安裝了mkcramfs工具, 則在/usr/bin目錄下是一個軟link, 請先刪除該文件之後, 再拷
貝該mkcramfs到/usr/bin下.
7.1.2 製作cramfs包
[arm@localhost tools]$mkcramfs my_rootfs my_rootfs.cramfs
7.1.3 寫cramfs包到Nand Flash
[arm@localhost tools]$su root
[root@localhost tools]$cp my_rootfs.cramfs /tftpboot/
打開minicom, 進行ARM板的終端模式:
CRANE2410 #
8 參考資料
1. linux目錄結構介紹
http://www.uplooking.com/content/view/1487/2/
2. <<BUILDING EMBEDDED LINUX SYSTEMS>>
中文名:<<構建嵌入式Linux系統>>
第七部分 Nand flash驅動的編寫與移植
1 Nand flash工作原理
S3C2410板的Nand Flash支持由兩部分組成:Nand Flash控制器(集成在S3C2410 CPU)和Nand Flash存儲
芯片(K9F1208U0B)兩大部分組成。當要訪問Nand Flash中的數據時,必須通過Nand Flash控制器發送命
令才能完成。所以, Nand Flash相當於S3C2410的一個外設,而不位於它的內存地址區.
1.1 Nand flash芯片工作原理
Nand flash芯片型號爲Samsung K9F1208U0B,數據存儲容量爲64MB,採用塊頁式存儲管理。8個I/O
引腳充當數據、地址、命令的複用端口。
1.1.1 芯片內部存儲佈局及存儲操作特點
一片Nand flash爲一個設備(device), 其數據存儲分層爲:
1設備(Device) = 4096 塊(Blocks)
1塊(Block) = 32頁/行(Pages/rows) ;頁與行是相同的意思,叫法不一樣
1塊(Page) = 528字節(Bytes) = 數據塊大小(512Bytes) + OOB塊大小(16Bytes)
在每一頁中,最後16個字節(又稱OOB)用於Nand Flash命令執行完後設置狀態用,剩餘512個字節又
分爲前半部分和後半部分。可以通過Nand Flash命令00h/01h/50h分別對前半部、後半部、OOB進行定位通過
Nand Flash內置的指針指向各自的首地址。
存儲操作特點:
1. 擦除操作的最小單位是塊。
2. Nand Flash芯片每一位(bit)只能從1變爲0,而不能從0變爲1,所以在對其進行寫入操作之前要一定將相應
塊擦除(擦除即是將相應塊得位全部變爲1).
3. OOB部分的第六字節(即517字節)標誌是否是壞塊,如果不是壞塊該值爲FF,否則爲壞塊。
4. 除OOB第六字節外,通常至少把OOB的前3個字節存放Nand Flash硬件ECC碼(關於硬件ECC碼請參看
Nandflash 控制器一節).
1.1.2 重要芯片引腳功能
I/O0I/
O7:複用引腳。可以通過它向nand flash芯片輸入數據、地址、nand flash命令以及輸出數據和操作
狀態信息。
CLE(Command Latch Enable): 命令鎖存允許
ALE(Address Lactch Enable): 地址鎖存允許
CE:
芯片選擇
RE:
讀允許
WE:
寫允許
WP:
在寫或擦除期間,提供寫保護
R/B:
讀/忙輸出
1.1.3 尋址方式
Samsung K9F1208U0B Nand Flash 片內尋址採用26位地址形式。從第0位開始分四次通過I/O0-I/O7進行
傳送,並進行片內尋址。具體含義如下:
0-7位:字節在上半部、下半部及OOB內的偏移地址
8位:值爲0代表對一頁內前256個字節進行尋址
值爲1代表對一頁內後256個字節進行尋址
9-13位:對頁進行尋址
14-25位:對塊進行尋址
當傳送地址時,從位0開始
1.1.4 Nand flash主要內設命令詳細介紹
Nand Flash命令執行是通過將命令字送到Nand Flash控制器的命令寄存器來執行。
Nand Flash的命令是分週期執行的,每條命令都有一個或多個執行週期,每個執行週期都有相映代碼表示該周
期將要執行的動作。
主要命令有:Read 1、Read 2、Read ID、Reset、Page Program、Block Erase、Read Status。
詳細介紹如下:
1. Read 1:
功能:表示將要讀取Nand flash存儲空間中一個頁的前半部分,並且將內置指針定位到前半部分的第一個字節。
命令代碼:00h
2. Read 2:
功能:表示將要讀取Nand flash存儲空間中一個頁的後半部分,並且將內置指針定位到後半部分的第一個字節。
命令代碼:01h
3. Read ID:
功能:讀取Nand flash芯片的ID號
命令代碼:90h
4. Reset:
功能:重啓芯片。
命令代碼:FFh
5. Page Program:
功能:對頁進行編程命令, 用於寫操作。
命令代碼:首先寫入00h(A區)/01h(B區)/05h(C區), 表示寫入那個區; 再寫入80h開始編程模式(寫入模式),接
下來寫入地址和數據; 最後寫入10h表示編程結束.
6. Block Erase
功能:塊擦除命令。
命令代碼:首先寫入60h進入擦寫模式,然後輸入塊地址; 接下來寫入D0h, 表示擦寫結束.
7. Read Status
功能:讀取內部狀態寄存器值命令。
命令代碼:70h
1.2 Nand Flash 控制器工作原理
對Nand Flash存儲芯片進行操作, 必須通過Nand Flash控制器的專用寄存器才能完成。所以,不能對Nand
Flash進行總線操作。而Nand Flash的寫操作也必須塊方式進行。對Nand Flash的讀操作可以按字節讀取。
1.2.1 Nand Flash控制器特性
1. 支持對Nand Flash芯片的讀、檢驗、編程控制
2. 如果支持從Nand Flash啓動, 在每次重啓後自動將前Nand Flash的前4KB數據搬運到ARM的內部RAM中
3. 支持ECC校驗
1.2.2 Nand Flash控制器工作原理
Nand Flash控制器在其專用寄存器區(SFR)地址空間中映射有屬於自己的特殊功能寄存器,就是通過將Nand
Flash芯片的內設命令寫到其特殊功能寄存器中,從而實現對Nand flash芯片讀、檢驗和編程控制的。特殊功能
寄存器有:NFCONF、NFCMD、NFADDR、NFDATA、NFSTAT、NFECC。寄存詳細說明見下一節。
1.3 Nand flash 控制器中特殊功能寄存器詳細介紹
1. 配置寄存器(NFCONF)
功能:用於對Nand Flash控制器的配置狀態進行控制。
在地址空間中地址:0x4E000000,其中:
Bit15:Nand Flash控制器使能位,置0代表禁止Nand Flash控制器,置1代表激活Nand Flash控制器;
要想訪問Nand Flash芯片上存儲空間,必須激活Nand Flash控制器。在復位後該位自動置0,因此在初始化時
必須將該位置爲1。
Bit12:初始化ECC位,置1爲初始化ECC;置0爲不初始化ECC。
Bit11:Nand Flash芯片存儲空間使能位,置0代表可以對存儲空間進行操作;置1代表禁止對存儲空
間進行操作。在復位後,該位自動爲1。
Bit10-8:TACLS位。根據此設定CLE&ALE的週期。TACLS的值範圍在0-7之間。
Bit6-4、2-0分別爲:TWRPH0、TWRPH1位。設定寫操作的訪問週期。其值在0-7之間。
2. 命令寄存器(NFCMD)
功能:用於存放Nand flash芯片內設的操作命令。
在地址空間中地址:0x4E000004,其中:
Bit0-7:存放具體Nand flash芯片內設的命令值。其餘位保留以後用。
3. 地址寄存器(NFADDR)
功能:用於存放用於對Nand flash芯片存儲單元尋址的地址值。
在地址空間中地址:0x4E000008,其中:
Bit0-7:用於存放地址值。因爲本款Nand flash芯片只有I/O0-7的地址/數據複用引腳且地址是四周
期每次8位送入的,所以這裏只用到8位。其餘位保留待用。
4. 數據寄存器(NFDATA)
功能:Nand flash芯片所有內設命令執行後都會將其值放到該寄存器中。同時,讀出、寫入Nand flash
存儲空間的值也是放到該寄存器。
在地址空間中地址:0x4E00000C,其中:
Bit0-7:用於存放需要讀出和寫入的數據。其餘位保留代用。
5. 狀態寄存器(NFSTAT)
功能:用於檢測Nand flash芯片上次對其存儲空間的操作是否完成。
在地址空間中地址:0x4E000010,其中:
Bit0:置0表示Nand flash芯片正忙於上次對存儲空間的操作;置1表示Nand flash芯片準備好接收新
的對存儲空間操作的請求。
6. ECC校驗寄存器(NFECC)
功能:ECC校驗寄存器
在地址空間中地址:0x4E000014,其中:
Bit0Bit7:
ECC0
Bit8Bit15:
ECC1
Bit16Bit23:
ECC2
1.4 Nand Flash 控制器中的硬件ECC介紹
1.4.1 ECC產生方法
ECC是用於對存儲器之間傳送數據正確進行校驗的一種算法,分硬件ECC和軟件ECC算法兩種,在
S3C2410的Nand Flash 控制器中實現了由硬件電路(ECC 生成器)實現的硬件ECC。
1.4.2 ECC生成器工作過程
當寫入數據到Nand flash存儲空間時, ECC生成器會在寫入數據完畢後自動生成ECC碼,將其放入到
ECC0-ECC2。當讀出數據時Nand Flash 同樣會在讀數據完畢後,自動生成ECC碼將其放到ECC0-ECC2當
中。
1.4.3 ECC的運用
當寫入數據時,可以在每頁寫完數據後將產生的ECC碼放入到OOB指定的位置(Byte 6)去,這樣就完成了
ECC碼的存儲。這樣當讀出該頁數據時,將所需數據以及整個OOB讀出,然後將指定位置的ECC碼與讀出數
據後在ECC0-ECC1的實際產生的ECC碼進行對比,如果相等則讀出正確,若不相等則讀取錯誤需要進行重
讀。
2 在ADS下flash燒寫程序
2.1 ADS下flash燒寫程序原理及結構
基本原理:在windows環境下藉助ADS仿真器將在SDRAM中的一段存儲區域中的數據寫到Nand flash存
儲空間中。燒寫程序在縱向上分三層完成:
第一層: 主燒寫函數(完成將在SDRAM中的一段存儲區域中的數據寫到Nand flash存儲空間中);
第二層: 爲第一層主燒寫函數提供支持的對Nand flash進行操作的頁讀、寫,塊擦除等函數;
第三層:爲第二層提供具體Nand flash控制器中對特殊功能寄存器進行操作的核心函數,該層也是真正的
將數據能夠在SDRAM和Nand flash之間實現傳送的函數。
下面對其三層進行分述:
2.2 第三層實現說明
2.1.1 特殊功能寄存器定義
#define rNFCONF (*(volatile unsigned int *)0x4e000000)
#define rNFCMD (*(volatile unsigned char *)0x4e000004)
#define rNFADDR (*(volatile unsigned char *)0x4e000008)
#define rNFDATA (*(volatile unsigned char *)0x4e00000c)
#define rNFSTAT (*(volatile unsigned int *)0x4e000010)
#define rNFECC (*(volatile unsigned int *)0x4e000014)
#define rNFECC0 (*(volatile unsigned char *)0x4e000014)
#define rNFECC1 (*(volatile unsigned char *)0x4e000015)
#define rNFECC2 (*(volatile unsigned char *)0x4e000016)
2.1.2 操作的函數實現
1. 發送命令
#define NF_CMD(cmd) {rNFCMD=cmd;}
2. 寫入地址
#define NF_ADDR(addr) {rNFADDR=addr;}
3. Nand Flash芯片選中
#define NF_nFCE_L() {rNFCONF&=~(1<<11);}
4. Nand Flash芯片不選中
#define NF_nFCE_H() {rNFCONF|=(1<<11);}
5. 初始化ECC
#define NF_RSTECC() {rNFCONF|=(1<<12);}
6. 讀數據
#define NF_RDDATA() (rNFDATA)
7. 寫數據
#define NF_WRDATA(data) {rNFDATA=data;}
8. 獲取Nand Flash芯片狀態
#define NF_WAITRB() {while(!(rNFSTAT&(1<<0)));}
0/假: 表示Nand Flash芯片忙狀態
1/真:表示Nand Flash已經準備好
2.3 第二層實現說明
2.3.1 Nand Flash 初始化
void NF_Init(void)
{
/* 設置Nand Flash配置寄存器, 每一位的取值見1.3節 */
rNFCONF=(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);
/* 復位外部Nand Flash芯片 */
NF_Reset();
}
2.3.2 Nand flash復位
static void NF_Reset(void)
{
int i;
NF_nFCE_L(); /* 片選Nand Flash芯片*/
NF_CMD(0xFF); /* 復位命令 */
for(i=0;i<10;i++); /* 等待tWB = 100ns. */
NF_WAITRB(); /* wait 200~500us; */
NF_nFCE_H(); /* 取消Nand Flash 選中*/
}
2.3.3 獲取Nand flash ID
返回值爲Nand flash芯片的ID號
unsigned short NF_CheckId(void)
{
int i;
unsigned short id;
NF_nFCE_L(); /* 片選Nand Flash芯片*/
NF_CMD(0x90); /* 發送讀ID命令到Nand Flash芯片 */
NF_ADDR(0x0); /* 指定地址0x0,芯片手冊要求 */
for(i=0;i<10;i++); /* 等待tWB = 100ns. */
id=NF_RDDATA()<<8; /* 廠商ID(K9S1208V:0xec) */
id|=NF_RDDATA(); /* 設備ID(K9S1208V:0x76) */
NF_nFCE_H(); /* 取消Nand Flash 選中*/
return id;
}
2.3.4 Nand flash寫入
以頁爲單位寫入.
參數說明:block 塊號
page 頁號
buffer 指向內存中待寫入Nand flash中的數據起始位置
返回值: 0:寫錯誤
1:寫成功
static int NF_WritePage(unsigned int block, unsigned int page, unsigned char *buffer)
{
int i;
unsigned int blockPage = (block<<5)+page;
unsigned char *bufPt = buffer;
NF_RSTECC(); /* 初始化 ECC */
NF_nFCE_L(); /* 片選Nand Flash芯片*/
NF_CMD(0x0); /* 從A區開始寫 */
NF_CMD(0x80); /* 寫第一條命令 */
NF_ADDR(0); /* A0~A7 位(Column Address) */
NF_ADDR(blockPage&0xff); /* A9A16,
(Page Address) */
NF_ADDR((blockPage>>8)&0xff); /* A17A24,
(Page Address) */
NF_ADDR((blockPage>>16)&0xff); /* A25, (Page Address) */
for(i=0;i<512;i++)
{
NF_WRDATA(*bufPt++); /* 寫一個頁512字節到Nand Flash芯片 */
}
/*
* OOB一共16 Bytes, 每一個字節存放什麼由程序員自己定義, 通常,
* 我們在Byte0Byte2
存ECC檢驗碼. Byte6 存放壞塊標誌.
*/
seBuf[0]=rNFECC0; /* 讀取ECC檢驗碼0 */
seBuf[1]=rNFECC1; /* 讀取ECC檢驗碼1 */
seBuf[2]=rNFECC2; /* 讀取ECC檢驗碼2 */
seBuf[5]=0xff; /* 非壞塊標誌 */
for(i=0;i<16;i++)
{
NF_WRDATA(seBuf[i]); /* 寫該頁的OOB數據塊 */
}
NF_CMD(0x10); /* 結束寫命令 */
/* 等待Nand Flash處於準備狀態 */
for(i=0;i<10;i++);
NF_WAITRB();
/* 發送讀狀態命令給Nand Flash */
NF_CMD(0x70);
for(i=0;i<3;i++);
if (NF_RDDATA()&0x1)
{ /*如果寫有錯, 則標示爲壞塊 */
NF_nFCE_H(); /* 取消Nand Flash 選中*/
NF_MarkBadBlock(block);
return 0;
} else { /* 正常退出 */
NF_nFCE_H(); /* 取消Nand Flash 選中*/
return 1;
}
}
2.3.5 Nand flash讀取
參數說明:block:塊號
page:頁號
buffer:指向將要讀取到內存中的起始位置
返回值:1:讀成功
0:讀失敗
static int NF_ReadPage(unsigned int block, unsigned int page, unsigned char *buffer)
{
int i;
unsigned int blockPage;
unsigned char ecc0, ecc1, ecc2;
unsigned char *bufPt=buffer;
unsigned char se[16];
page=page&0x1f;
blockPage=(block<<5)+page;
NF_RSTECC(); /* 初始化 ECC */
NF_nFCE_L(); /* 片選Nand Flash芯片*/
NF_CMD(0x00); /* 從A區開始讀 */
NF_ADDR(0); /* A0~A7 位(Column Address) */
NF_ADDR(blockPage&0xff); /* A9A16,
(Page Address) */
NF_ADDR((blockPage>>8)&0xff); /* A17A24,
(Page Address) */
NF_ADDR((blockPage>>16)&0xff); /* A25, (Page Address) */
/* 等待Nand Flash處於再準備狀態 */
for(i=0;i<10;i++);
NF_WAITRB(); /*等待 tR(max 12us) */
/* 讀整個頁, 512字節 */
for(i=0;i<512;i++)
{
*bufPt++=NF_RDDATA();
}
/* 讀取ECC碼 */
ecc0=rNFECC0;
ecc1=rNFECC1;
ecc2=rNFECC2;
/* 讀取該頁的OOB塊 */
for(i=0;i<16;i++)
{
se[i]=NF_RDDATA();
}
NF_nFCE_H(); /* 取消Nand Flash 選中*/
/* 校驗ECC碼, 並返回 */
if(ecc0==se[0] && ecc1==se[1] && ecc2==se[2])
return 1;
else
return 0;
}
2.3.6 Nand flash標記壞塊
如果是壞塊, 通過寫OOB塊的Byte6把該塊標記爲壞塊。
參數說明:block塊號
返回值:1:ok,成功完成標記。
0:表示寫OOB塊正確.
static int NF_MarkBadBlock(unsigned int block)
{
int i;
unsigned int blockPage=(block<<5);
seBuf[0]=0xff;
seBuf[1]=0xff;
seBuf[2]=0xff;
seBuf[5]=0x44; /* 設置壞塊標記 */
NF_nFCE_L(); /* 片選Nand Flash芯片*/
NF_CMD(0x50); /* 從C區開始寫 */
NF_CMD(0x80); /* 發送編程命令, 讓Nand Flash處理寫狀態 */
NF_ADDR(0x0); /* A0~A7 位(Column Address) */
NF_ADDR(blockPage&0xff); /* A9A16,
(Page Address) */
NF_ADDR((blockPage>>8)&0xff); /* A17A24,
(Page Address) */
NF_ADDR((blockPage>>16)&0xff); /* A25, (Page Address) */
/* 寫OOB數據塊 */
for(i=0;i<16;i++)
{
NF_WRDATA(seBuf[i]);
}
NF_CMD(0x10); /* 結束寫命令 */
/* 等待NandFlash準備好 */
for(i=0;i<10;i++); /* tWB = 100ns. */
NF_WAITRB();
/*讀NandFlash的寫狀態 */
NF_CMD(0x70);
for(i=0;i<3;i++); /* twhr=60ns */
if (NF_RDDATA()&0x1)
{
NF_nFCE_H(); /* 取消Nand Flash 選中*/
return 0;
} else {
NF_nFCE_H(); /* 取消Nand Flash 選中*/
}
return 1;
}
2.3.7 Nand Flash檢查壞塊
檢查指定塊是否是壞塊.
參數說明:block:塊號
返回值:1:指定塊是壞塊
0:指定塊不是壞塊。
static int NF_IsBadBlock(U32 block)
{
int i;
unsigned int blockPage;
U8 data;
blockPage=(block<<5);
NF_nFCE_L(); /* 片選Nand Flash芯片*/
NF_CMD(0x50); /* Read OOB數據塊 */
NF_ADDR(517&0xf); /* A0~A7 位(Column Address) */
NF_ADDR(blockPage&0xff); /* A9A16,
(Page Address) */
NF_ADDR((blockPage>>8)&0xff); /* A17A24,
(Page Address) */
NF_ADDR((blockPage>>16)&0xff); /* A25, (Page Address) */
/* 等待NandFlash準備好 */
for(i=0;i<10;i++); /* wait tWB(100ns) */
NF_WAITRB();
/* 讀取讀出值 */
data=NF_RDDATA();
NF_nFCE_H(); /* 取消Nand Flash 選中*/
/* 如果data不爲0xff時, 表示該塊是壞塊 */
if(data != 0xff)
return 1;
else
return 0;
}
2.3.8 擦除指定塊中數據
參數說明:block 塊號
返回值:0:擦除錯誤。(若是壞塊直接返回0;若擦除出現錯誤則標記爲壞塊然後返回0)
1:成功擦除。
static int NF_EraseBlock(unsigned int block)
{
unsigned int blockPage=(block<<5);
int i;
/* 如果該塊是壞塊, 則返回 */
if(NF_IsBadBlock(block))
return 0;
NF_nFCE_L(); /* 片選Nand Flash芯片*/
NF_CMD(0x60); /* 設置擦寫模式 */
NF_ADDR(blockPage&0xff); /* A9A16,
(Page Address) , 是基於塊擦*/
NF_ADDR((blockPage>>8)&0xff); /* A17A24,
(Page Address) */
NF_ADDR((blockPage>>16)&0xff); /* A25, (Page Address) */
NF_CMD(0xd0); /* 發送擦寫命令, 開始擦寫 */
/* 等待NandFlash準備好 */
for(i=0;i<10;i++); /* tWB(100ns) */
NF_WAITRB();
/* 讀取操作狀態 */
NF_CMD(0x70);
if (NF_RDDATA()&0x1)
{
NF_nFCE_H(); /* 取消Nand Flash 選中*/
NF_MarkBadBlock(block); /* 標記爲壞塊 */
return 0;
} else {
NF_nFCE_H(); /* 取消Nand Flash 選中*/
return 1;
}
}
2.4 第一層的實現
2.4.1 NandFlash燒寫主函數說明
參數說明: block 塊號
srcAddress SDRAM中數據起始地址
fileSize 要燒寫的數據長度
返回值: 無
void K9S1208_Program(unsigned int block, unsigned int srcAddress, unsigned int fileSize)
{
int i;
int programError=0;
U32 blockIndex;
U8 *srcPt, *saveSrcPt;
srcPt=(U8 *)srcAddress; /* 文件起始地址 */
blockIndex = block; /* 塊號 */
while(1)
{
saveSrcPt=srcPt;
/* 如果當前塊是壞塊, 跳過當前塊 */
if(NF_IsBadBlock(blockIndex))
{
blockIndex++; /* 到下一個塊 */
continue;
}
/* 在寫之前, 必須先擦除, 如果擦除不成功, 跳過當前塊 */
if(!NF_EraseBlock(blockIndex))
{
blockIndex++; /* 到下一個塊 */
continue;
}
/* 寫一個塊, 一塊有32頁 */
for(i=0;i<32;i++)
{
/* 寫入一個頁, 如果出錯, 停止寫當前塊 */
if(!NF_WritePage(blockIndex,i,srcPt))
{
programError=1;
break;
}
/* 如果操作正常, 文件的寫位置加上1頁偏移,到下一頁的起始位置 */
srcPt+=512;
/* 如果寫地址沒有超過文件長度, 繼續; 超出則終止寫 */
if((U32)srcPt>=(srcAddress+fileSize))
break;
}
/* 如果寫一個塊時, 其中某一頁寫失敗, 則把寫地址恢復寫該塊之前, 並跳過當前塊 */
if(programError==1)
{
blockIndex++;
srcPt=saveSrcPt;
programError=0;
continue;
}
/* 如果寫地址沒有超過文件長度, 繼續; 超出則終止寫 */
if((U32)srcPt >= (srcAddress+fileSize))
break;
/* 如果正常寫成功, 繼續寫下一個塊 */
blockIndex++;
}
}
3 在U-BOOT對Nand Flash的支持
3.1 U-BOOT對從Nand Flash啓動的支持
3.1.1 從Nand Flash啓動U-BOOT的基本原理
1. 前4K的問題
如果S3C2410被配置成從Nand Flash啓動(配置由硬件工程師在電路板設置), S3C2410的Nand Flash控制器
有一個特殊的功能, 在S3C2410上電後, Nand Flash控制器會自動的把Nand Flash上的前4K數據搬移到4K內部
RAM中, 並把0x00000000設置內部RAM的起始地址, CPU從內部RAM的0x00000000位置開始啓動。這個過
程不需要程序干涉。
程序員需要完成的工作,是把最核心的啓動程序放在Nand Flash的前4K中。
2. 啓動程序的安排
由於Nand Flash控制器從Nand Flash中搬移到內部RAM的代碼是有限的,所以, 在啓動代碼的前4K裏,我
們必須完成S3C2410的核心配置以及把啓動代碼(UBOOT)剩餘部分搬到RAM中運行。以UBOOT爲例, 前4K
完成的主要工作, 見第四部分的2.2節。
3.1.2 支持Nand Flash啓動代碼說明
首先在include/configs/crane2410.h中加入CONFIG_S3C2410_NAND_BOOT, 如下:
#define CONFIG_S3C2410_NAND_BOOT 1
支持從Nand Flash中啓動.
1. 執行Nand Flash初始化
下面代碼在cpu/arm920t/start.S中
#ifdef CONFIG_S3C2410_NAND_BOOT
copy_myself:
mov r10, lr
ldr sp, DW_STACK_START @安裝棧的起始地址
mov fp, #0 @初始化幀指針寄存器
bl nand_reset @跳到復位C函數去執行
...
DW_STACK_START:
.word STACK_BASE+STACK_SIZE4
2. nand_reset C代碼
下面代碼被加在/board/crane2410/crane2410.c中
void nand_reset(void)
{
int i;
/* 設置Nand Flash控制器 */
rNFCONF=(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);
/* 給Nand Flash芯片發送復位命令 */
NF_nFCE_L();
NF_CMD(0xFF);
for(i=0; i<10; i++);
NF_WAITRB();
NF_nFCE_H();
}
3. 從Nand Flash中把UBOOT拷貝到RAM
@read UBOOT
from Nand Flash to RAM
ldr r0, =UBOOT_RAM_BASE @ 設置第1個參數: UBOOT在RAM中的起始地址
mov r1, #0x0 @ 設置第2個參數:Nand Flash的起始地址
mov r2, #0x20000 @ 設置第3個參數: UBOOT的長度(128KB)
bl nand_read_whole @ 調用nand_read_whole(), 該函數在board/crane2410/crane2410.c中
tst r0, #0x0 @ 如果函數的返回值爲0,表示執行成功.
beq ok_nand_read @ 執行內存比較
4. 從Nand Flash中把數據讀入到RAM中
int nand_read_whole(unsigned char *buf, unsigned long start_addr, int size)
{
int i, j;
/* 如果起始地址和長度不是512字節(1頁)的倍數, 則返回錯誤代碼 */
if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {
return 1;
}
/* 激活Nand Flash */
NF_nFCE_L();
for(i=0; i<10; i++);
i = start_addr;
while(i < start_addr + size) {
/* 讀A區 */
rNFCMD = 0;
/* 寫入讀取地址 */
rNFADDR = i & 0xff;
rNFADDR = (i >> 9) & 0xff;
rNFADDR = (i >> 17) & 0xff;
rNFADDR = (i >> 25) & 0xff;
NF_WAITRB();
/* 讀出一頁(512字節) */
for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {
*buf = (rNFDATA & 0xff);
buf++;
}
}
/* 停止驅動Nand Flash */
NF_nFCE_H();
return 0;
}
5. 校查搬移後的數據
把RAM中的前4K與內部中前4K進行比較, 如果完全相同, 則表示搬移成功.
ok_nand_read:
mov r0, #0x00000000 @內部RAM的起始地址
ldr r1, =UBOOT_RAM_BASE @UBOOT在RAM中的起始地址
mov r2, #0x400 @比較1024次, 每次4字節, 4 bytes * 1024 = 4Kbytes
go_next: @ 比較1024次, 每次4個字節
ldr r3, [r0], #4
ldr r4, [r1], #4
teq r3, r4
bne notmatch
subs r2, r2, #4
beq done_nand_read
bne go_next
notmatch:
1:b 1b
done_nand_read:
mov pc, r10
3.2 U-BOOT對Nand Flash命令的支持
在UBOOT
下對Nand Flash的支持主要是在命令行下實現對nand flash的操作。對nand flash實現的命令
爲:nand info、nand device、nand read、nand write、nand erease、nand bad。
用到的主要數據結構有:struct nand_flash_dev、struct nand_chip。前者包括主要的芯片型號、存儲容量、
設備ID、I/O總線寬度等信息;後者是具體對nand flash進行操作時用到的信息。
3.2.1 主要數據結構介紹
1. struct nand_flash_dev數據結構
該數據結構在include/linux/mtd/nand.h中定義,在include/linux/mtd/nand_ids.h中賦初值。
struct nand_flash_dev {
char *name; /* 芯片名稱 */
int manufacture_id; /* 廠商ID */
int model_id; /* 模式ID */
int chipshift; /* Nand Flash地址位數 */
char page256; /* 表明是否時256字節一頁。1:是;0:否。*/
char pageadrlen; /* 完成一次地址傳送需要往NFADDR中傳送幾次。*/
unsigned long erasesize; /* 一次塊擦除可以擦除多少字節 */
int bus16; /* 地址線是否是16位,1:是;0:否 */
};
2. struct nand_chip數據結構
該數據結構在include/linux/mtd/nand.h中定義. 該結構體定義出一個Nand Flash設備數組:
struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
該數組在nand_probe()中對其進行初始化.
struct nand_chip {
int page_shift; /* Page 地址位數 */
u_char *data_buf; /* 本次讀出的一頁數據 */
u_char *data_cache; /* 讀出的一頁數據 */
int cache_page; /* 上次操作的頁號 */
u_char ecc_code_buf[6]; /* ECC校驗碼 */
u_char reserved[2];
char ChipID; /* 芯片ID號 */
struct Nand *chips; /* Nand Flash芯片列表, 表示支持幾個芯片爲一個設備*/
int chipshift;
char* chips_name; /* Nand Flash芯片名稱 */
unsigned long erasesize; /* 塊擦寫的大小 */
unsigned long mfr; /* 廠商ID */
unsigned long id; /* 模式ID */
char* name; /* 設備名稱 */
int numchips; /* 有幾塊Nand Flash芯片 */
char page256; /* 一頁是256字節, 還是512字節 */
char pageadrlen; /* 頁地址的長度 */
unsigned long IO_ADDR; /* 用於對nand flash進行尋址的地址值存放處 */
unsigned long totlen; /* Nand Flash總共大小 */
uint oobblock; /* 一頁的大小。本款nand flash爲512 */
uint oobsize; /* spare array大小。本款nand flash爲16 */
uint eccsize; /* ECC 大小 */
int bus16; /* 地址線是否是16位,1:是;0:否 */
};
3.2.2 支持的命令函數說明
1. nand info/nand device
功能:顯示當前nand flash芯片信息。
函數調用關係如下(按先後順序):
static void nand_print(struct nand_chip *nand) ;
2. nand erase
功能:擦除指定塊上的數據。
函數調用關係如下(按先後順序):
int nand_erase(struct nand_chip* nand, size_t ofs, size_t len, int clean);
3. nand bad
功能:顯示壞塊。
函數調用關係如下(按先後順序):
static void nand_print_bad(struct nand_chip* nand);
int check_block (struct nand_chip *nand, unsigned long pos);
4. nand read
功能:讀取nand flash信息到SDRAM。
函數調用關係如下(按先後順序):
int nand_rw (struct nand_chip* nand, int cmd,size_t start, size_t len, size_t * retlen, u_char * buf);
static int nand_read_ecc(struct nand_chip *nand, size_t start, size_t len,
size_t * retlen, u_char *buf, u_char *ecc_code);
static void NanD_ReadBuf (struct nand_chip *nand, u_char * data_buf, int cntr);
READ_NAND(adr);
5. nand write
功能:從SDRAM寫數據到nand flash中。
函數調用關係如下(按先後順序):
int nand_rw (struct nand_chip* nand, int cmd,size_t start, size_t len, size_t * retlen, u_char * buf);
static int nand_write_ecc (struct nand_chip* nand, size_t to, size_t len,
size_t * retlen, const u_char * buf, u_char * ecc_code);
static int nand_write_page (struct nand_chip *nand, int page, int col, int last, u_char * ecc_code);
WRITE_NAND(d , adr);
3.2.3 U-BOOT支持Nand Flash命令移植說明
1. 設置配置選項
在CONFIG_COMMANDS中, 打開CFG_CMD_NAND選項.
#define CONFIG_COMMANDS /
(CONFIG_CMD_DFL | /
CFG_CMD_CACHE | /
CFG_CMD_NAND | /
/*CFG_CMD_EEPROM |*/ /
/*CFG_CMD_I2C |*/ /
/*CFG_CMD_USB |*/ /
CFG_CMD_PING | /
CFG_CMD_REGINFO | /
CFG_CMD_DATE | /
CFG_CMD_ELF)
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
#define CFG_NAND_BASE 0x4E000000 /* Nand Flash控制器在SFR區中起始寄存器地址 */
#define CFG_MAX_NAND_DEVICE 1 /* 支持的最在Nand Flash數據 */
#define SECTORSIZE 512 /* 1頁的大小 */
#define NAND_SECTOR_SIZE SECTORSIZE
#define NAND_BLOCK_MASK (NAND_SECTOR_SIZE – 1) /* 頁掩碼 */
#define ADDR_COLUMN 1 /* 一個字節的Column地址 */
#define ADDR_PAGE 3 /* 3字節的頁塊地址, A9A25*/
#define ADDR_COLUMN_PAGE 4 /* 總共4字節的頁塊地址 */
#define NAND_ChipID_UNKNOWN 0x00 /* 未知芯片的ID號 */
#define NAND_MAX_FLOORS 1
#define NAND_MAX_CHIPS 1
/* Nand Flash命令層底層接口函數 */
#define WRITE_NAND_COMMAND(d, adr) do {rNFCMD = d;} while(0)
#define WRITE_NAND_ADDRESS(d, adr) do {rNFADDR = d;} while(0)
#define WRITE_NAND(d, adr) do {rNFDATA = d;} while(0)
#define READ_NAND(adr) (rNFDATA)
#define NAND_WAIT_READY(nand) {while(!(rNFSTAT&(1<<0)));}
#define NAND_DISABLE_CE(nand) {rNFCONF |= (1<<11);}
#define NAND_ENABLE_CE(nand) {rNFCONF &= ~(1<<11);}
/* 下面一組操作對Nand Flash無效 */
#define NAND_CTL_CLRALE(nandptr)
#define NAND_CTL_SETALE(nandptr)
#define NAND_CTL_CLRCLE(nandptr)
#define NAND_CTL_SETCLE(nandptr)
/* 允許Nand Flash寫校驗 */
#define CONFIG_MTD_NAND_VERIFY_WRITE 1
#endif /* CONFIG_COMMANDS & CFG_CMD_NAND*/
2. 加入自己的Nand Flash芯片型號
在include/linux/mtd/ nand_ids.h中的對如下結構體賦值進行修改:
static struct nand_flash_dev nand_flash_ids[] = {
......
{"Samsung K9F1208U0B", NAND_MFR_SAMSUNG, 0x76, 26, 0, 4, 0x4000, 0},
.......
}
這樣對於該款Nand Flash芯片的操作才能正確執行。
3. 編寫自己的Nand Flash初始化函數
在board/crane2410/crane2410.c中加入nand_init()函數.
void nand_init(void)
{
/* 初始化Nand Flash控制器, 以及Nand Flash 芯片 */
nand_reset();
/* 調用nand_probe()來檢測芯片類型 */
printf ("%4lu MB/n", nand_probe(CFG_NAND_BASE) >> 20);
}
該函數在啓動時被start_armboot()調用.
4 在Linux對Nand Flash的支持
4.1 Linux下Nand Flash調用關係
4.1.1 Nand Flash設備添加時數據結構包含關係
struct mtd_partition partition_info[]
--> struct s3c2410_nand_set nandset
--> struct s3c2410_platform_nand superlpplatfrom
--> struct platform_device s3c_device_nand
在該數據結構的name字段的初始化值"s3c2410-nand",必須與Nand Flash設備驅動註冊時
struct device_driver結構中的name字段相同,因爲platfrom bus是依靠名字來匹配的.
--> struct platform_device *smdk2410_devices[]
4.1.2 Nand Flash設備註冊時數據結構包含關係
struct device_driver s3c2410_nand_driver
-->struct device *dev
該數據構由系統分配.
-->struct platform_device *pdev
-->struct s3c2410_platform_nand *plat
-->struct s3c2410_nand_set nset
-->struct mtd_partition
4.1.3 當發生系統調用時數據結構調用關係
struct mtd_info
它的*priv指向chip
-->struct nand_chip
它的*priv指向nmtd
-->struct s3c2410_nand_mtd
它是s3c2410_nand_info的一個字段
-->s3c2410_nand_info
它被設爲Nand Flash設備驅動的私有數據結構,在Nand Flash設備驅動註冊時分配空間.
-->struct device
4.2 Linux下Nand Flash驅動主要數據結構說明
4.2.1 s3c2410專有數據結構
1. s3c2410_nand_set
struct s3c2410_nand_set {
int nr_chips; /* 芯片的數目 */
int nr_partitions; /* 分區的數目 */
char *name; /* 集合名稱 */
int nr_map; /* 可選, 底層邏輯到物理的芯片數目 */
struct mtd_partition partitions; /* 分區列表 */
};
2. s3c2410_platform_and
struct s3c2410_platform_nand {
/* timing information for controller, all times in nanoseconds */
int tacls; /* 從CLE/ALE有效到 nWE/nOE的時間 */
int twrph0; /* nWE/nOE的有效時間 */
int twrph1; /* 從釋放CLE/ALE到nWE/nOE不活動的時間 */
int nr_sets; /* 集合數目 */
struct s3c2410_nand_set sets; /* 集合列表 */
/* 根據芯片編號選擇有效集合 */
void (*select_chip)(struct s3c2410_nand_set , int chip);
};
3. s3c2410_nand_mtd
在drivers/mtd/nand/s3c2410.c中,
struct s3c2410_nand_mtd {
struct mtd_info mtd; /* MTD 信息 */
struct nand_chip chip; /* nand flash 芯片信息 */
struct s3c2410_nand_set set; /* nand flash 集合 */
struct s3c2410_nand_info *info; /* nand flash 信息 */
int scan_res;
};
4. s3c2410_nand_info
struct s3c2410_nand_info {
/* mtd info */
struct nand_hw_control controller; /* 硬件控制器 */
struct s3c2410_nand_mtd *mtds; /* MTD 設備表 */
struct s3c2410_platform_nand platform; /* Nand 設備的平臺 */
/* device info */
struct device *device; /* 設備指針 */
struct resource *area; /* 資源指針 */
struct clk *clk; /* Nand Flash 時鐘 */
void __iomem *regs; /* 寄存器基地址(map後的邏輯地址) */
int mtd_count; /* MTD的數目 */
unsigned char is_s3c2440;
};
5. struct clk
在arch/arm/machs3c2410/
clock.h中
struct clk {
struct list_head list; /* clock 列表結點 */
struct module *owner; /* 所屬模塊 */
struct clk *parent; /* 父結點 */
const char *name; /* 名稱 */
int id; /* 編號 */
atomic_t used; /* 使用者計數 */
unsigned long rate; /* 時鐘速率 */
unsigned long ctrlbit; /* 控制位 */
int (*enable)(struct clk *, int enable); /* Clock打開方法 */
};
4.2.2 Linux 通用數據結構說明
1. device_driver
include/linux/device.h
struct device_driver {
const char * name; /* 驅動名稱 */
struct bus_type * bus; /* 總線類型 */
struct completion unloaded; /* 卸載事件通知機制 */
struct kobject kobj; /* sys中的對象 */
struct klist klist_devices; /* 設備列表 */
struct klist_node knode_bus; /* 總線結點列表 */
struct module * owner;/* 所有者 */
/* 設備驅動通用方法 */
int (*probe) (struct device * dev); /* 探測設備 */
int (*remove) (struct device * dev); /* 移除設備 */
void (*shutdown) (struct device * dev); /* 關閉設備 */
/* 掛起設備 */
int (*suspend) (struct device * dev, pm_message_t state, u32 level);
int (*resume) (struct device * dev, u32 level); /* 恢復 */
};
2. platform_device
include/linux/device.h
struct platform_device {
const char * name; /* 名稱 */
u32 id; /* 設備編號, -1表示不支持同類多個設備 */
struct device dev; /* 設備 */
u32 num_resources; /* 資源數 */
struct resource * resource; /* 資源列表 */
};
3. resource
struct resource {
const char name; /* 資源名稱 */
unsigned long start, end; /* 開始位置和結束位置 */
unsigned long flags; /* 資源類型 */
/* 資源在資源樹中的父親,兄弟和孩子 */
struct resource *parent, *sibling, *child;
};
4. device
include/linux/device.h
struct device {
struct klist klist_children; /* 在設備列表中的孩子列表 */
struct klist_node knode_parent; /* 兄弟結點 */
struct klist_node knode_driver; /* 驅動結點 */
struct klist_node knode_bus; /* 總線結點 */
struct device parent; /* 父親 */
struct kobject kobj; /* sys結點 */
char bus_id[BUS_ID_SIZE];
struct semaphore sem; /* 同步驅動的信號量 */
struct bus_type * bus; /* 總線類型 */
struct device_driver *driver; /* 設備驅動 */
void *driver_data; /* 驅動的私有數據 */
void *platform_data; /* 平臺指定的數據,爲device核心驅動保留 */
void *firmware_data; /* 固件指定的數據,爲device核心驅動保留 */
struct dev_pm_info power; /* 設備電源管理信息 */
u64 *dma_mask; /* DMA掩碼 */
u64 coherent_dma_mask;
struct list_head dma_pools; /* DMA緩衝池 */
struct dma_coherent_mem *dma_mem; /* 連續DMA內存的起始位置 */
void (*release)(struct device * dev); /* 釋放設置方法 */
};
5. nand_hw_control
include/linux/mtd/nand.h
struct nand_hw_control {
spinlock_t lock; /* 自旋鎖,用於硬件控制 */
struct nand_chip *active; /* 正在處理MTD設備 */
wait_queue_head_t wq; /* 等待隊列 */
};
6. nand_chip
include/linux/mtd/nand.h
struct nand_chip {
void __iomem *IO_ADDR_R; /* 讀地址 */
void __iomem *IO_ADDR_W; /* 寫地址 */
/* 字節操作 */
u_char (*read_byte)(struct mtd_info *mtd); /* 讀一個字節 */
void (*write_byte)(struct mtd_info *mtd, u_char byte); /* 寫一個字節 */
/* 雙字節操作 */
u16 (*read_word)(struct mtd_info mtd); /* 讀一個字 */
void (*write_word)(struct mtd_info *mtd, u16 word); /* 寫一個字 */
/* buffer操作 */
void (*write_buf)(struct mtd_info *mtd, const u_char *buf, int len);
void (*read_buf)(struct mtd_info *mtd, u_char *buf, int len);
int (*verify_buf)(struct mtd_info *mtd, const u_char *buf, int len);
/* 選擇一個操作芯片 */
void (*select_chip)(struct mtd_info *mtd, int chip);
/* 壞塊檢查操作 */
int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
/* 壞塊標記操作 */
int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
/* 硬件控制操作 */
void (*hwcontrol)(struct mtd_info *mtd, int cmd);
/* 設備準備操作 */
int (*dev_ready)(struct mtd_info *mtd);
/* 命令發送操作 */
void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int
page_addr);
/* 等待命令完成 */
int (*waitfunc)(struct mtd_info *mtd, struct nand_chip *this, int state);
/* 計算ECC碼操作 */
int (*calculate_ecc)(struct mtd_info *mtd, const u_char *dat, u_char
*ecc_code);
/* 數據糾錯操作 */
int (*correct_data)(struct mtd_info *mtd, u_char *dat, u_char *read_ecc,
u_char *calc_ecc);
/* 開啓硬件ECC */
void (*enable_hwecc)(struct mtd_info *mtd, int mode);
/* 擦除操作 */
void (*erase_cmd)(struct mtd_info *mtd, int page);
/* 檢查壞塊表 */
int (*scan_bbt)(struct mtd_info *mtd);
int eccmode; /* ECC模式 */
int eccsize; /* ECC 計算時使用的字節數 */
int eccbytes; /* ECC 碼的字節數 */
int eccsteps; /* ECC 碼計算的步驟數 */
int chip_delay; /* 芯片的延遲時間 */
spinlock_t chip_lock; /* 芯片訪問的自旋鎖 */
wait_queue_head_t wq; /* 芯片訪問的等待隊列 */
nand_state_t state; /* Nand Flash狀態 */
int page_shift; /* 頁右移的位數,即column地址位數 */
int phys_erase_shift; /* 塊右移的位數, 即column和頁一共的地址位數 */
int bbt_erase_shift; /* 壞塊頁表的位數 */
int chip_shift; /* 該芯片總共的地址位數 */
u_char *data_buf; /* 數據緩衝區 */
u_char *oob_buf; /* oob緩衝區 */
int oobdirty; /* oob緩衝區是否需要重新初始化 */
u_char *data_poi; /* 數據緩衝區指針 */
unsigned int options; /* 芯片專有選項 */
int badblockpos;/* 壞塊標示字節在OOB中的位置 */
int numchips; /* 芯片的個數 */
unsigned long chipsize; /* 在多個芯片組中, 一個芯片的大小 */
int pagemask; /* 每個芯片頁數的屏蔽字, 通過它取出每個芯片包含多少個頁 */
int pagebuf; /* 在頁緩衝區中的頁號 */
struct nand_oobinfo *autooob; /* oob信息 */
uint8_t *bbt; /* 壞塊頁表 */
struct nand_bbt_descr *bbt_td; /* 壞塊表描述 */
struct nand_bbt_descr *bbt_md; /* 壞塊表鏡像描述 */
struct nand_bbt_descr *badblock_pattern; /* 壞塊檢測模板 */
struct nand_hw_control *controller; /* 硬件控制 */
void *priv; /* 私有數據結構 */
/* 進行附加錯誤檢查 */
int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int
status, int page);
};
7. mtd_info
include/linux/mtd/mtd.h
struct mtd_info {
u_char type; /* 設備類型 */
u_int32_t flags; /* 設備標誌位組 */
u_int32_t size; /* 總共設備的大小 */
u_int32_t erasesize; /* 擦除塊的大小 */
u_int32_t oobblock; /* OOB塊的大小,如:512個字節有一個OOB */
u_int32_t oobsize; /* OOB數據的大小,如:一個OOB塊有16個字節 */
u_int32_t ecctype; /* ECC校驗的類型 */
u_int32_t eccsize; /* ECC碼的大小 */
char *name; /* 設備名稱 */
int index; /* 設備編號 */
/* oobinfo信息,它可以通過 MEMSETOOBINFO ioctl命令來設置 */
struct nand_oobinfo oobinfo;
u_int32_t oobavail; /* OOB區的有效字節數,爲文件系統提供 */
/* 數據擦除邊界信息 */
int numeraseregions;
struct mtd_erase_region_info *eraseregions;
u_int32_t bank_size; /* 保留 */
/* 擦除操作 */
int (*erase) (struct mtd_info *mtd, struct erase_info *instr);
/* 指向某個執行代碼位置 */
int (*point) (struct mtd_info *mtd, loff_t from,
size_t len, size_t *retlen, u_char **mtdbuf);
/* 取消指向 */
void (*unpoint) (struct mtd_info *mtd, u_char * addr, loff_t from, size_t len);
/* 讀/寫操作 */
int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
int (*write) (struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf);
/* 帶ECC碼的讀/寫操作 */
int (*read_ecc) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
int (*write_ecc) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
/* 帶OOB碼的讀/寫操作 */
int (*read_oob) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
u_char *buf);
int (*write_oob) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
const u_char *buf);
/* 提供訪問保護寄存器區的方法 */
int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf);
int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf);
int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf);
int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len);
/* 提供readv和writev方法 */
int (*readv) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count,
loff_t from, size_t *retlen);
int (*readv_ecc) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count,
loff_t from, size_t *retlen, u_char *eccbuf,
struct nand_oobinfo *oobsel);
int (*writev) (struct mtd_info *mtd, const struct kvec *vecs,
unsigned long count, loff_t to, size_t *retlen);
int (*writev_ecc) (struct mtd_info *mtd, const struct kvec *vecs,
unsigned long count, loff_t to, size_t *retlen,
u_char *eccbuf, struct nand_oobinfo *oobsel);
/* 同步操作 */
void (*sync) (struct mtd_info *mtd);
/* 芯片級支持的加/解鎖操作 */
int (*lock) (struct mtd_info *mtd, loff_t ofs, size_t len);
int (*unlock) (struct mtd_info *mtd, loff_t ofs, size_t len);
/* 電源管理操作 */
int (*suspend) (struct mtd_info *mtd);
void (*resume) (struct mtd_info *mtd);
/* 壞塊管理操作 */
int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);
int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);
/* 重啓前的通知事件 */
struct notifier_block reboot_notifier;
void *priv; /* 私有數據結構 */
struct module *owner; /* 模塊所有者 */
int usecount; /* 使用次數 */
};
4.3 Linux下Nand Flash驅動說明
4.3.1 註冊driver_register
通過module_init(s3c2410_nand_init);註冊Nand Flash驅動. 在 s3c2410_nand_init ()中通過driver_register()註冊
s3c2410_nand_driver驅動程序,如下所示:
static struct device_driver s3c2410_nand_driver = {
.name = "s3c2410-nand",
.bus = &platform_bus_type, /* 在drivers/base/platform.c中定義 */
.probe = s3c2410_nand_probe,
.remove = s3c2410_nand_remove,
};
4.3.2 探測設備probe
在註冊的Nand Flash驅動程序中, probe方法爲s3c2410_nand_probe(). s3c2410_nand_probe()再調用
s3c24xx_nand_probe(). 在該函數中, 把*info作爲Nand Flash驅動的私有數據結構, 並通過dev_set_drvdata(dev,
info)把*info保存在*device的*driver_data字段中.然後通過clk_get(dev, "nand")獲取Nand Flash的時鐘資
源, clk_use(info->clk)增加時鐘資源的使用計數, clk_enable(info->clk)開啓資源.填寫*info的其它字段,
其中包括:
1. 通過request_mem_region()爲Nand Flash寄存器區申請I/O內存地址空間區,並通過ioremap()把它映射到虛
擬地址空間.
2. 調用s3c2410_nand_inithw()初始化Nand Flash控制器.
3. 爲mtd設備分配設備信息的存儲空間.
4. 對當前mtd設備,調用s3c2410_nand_init_chip()進行初始化.
5. 對當前mtd設備, 調用nand_scan()檢測Nand Flash芯片, nand_scan()函數在drivers/mtd/nand/nand_base.c中
定義.該函數的作用是初始化struct nand_chip中一些方法, 並從Nand Flash中讀取芯片ID, 並初始化struct
mtd_info中的方法.
6. 對當前mtd設備,加入其分區信息.
7. 如果還有更多mtd設備,到4執行.
4.3.3 初始化Nand Flash控制器
s3c2410_nand_inithw()函數會初始化Nand Flash控制器, 通過設置Nand Flash控制寄存器(S3C2410_NFCONF)來
完成, 這裏最重要的是根據S3C2410的PCLK計算出tacls, twrph0以及twrph1值.
4.3.4 移除設備
s3c2410_nand_remove()當設備被移除時,被device核心驅動調用.它完成的主要工作如下:
1. 把*device的*driver_data字段置空.
2. 釋放mtd設備信息.
3. 釋放clk資源.
4. 通過iounmap()取消映地址空間.
5. 釋放申請的I/O內存資源.
6. 釋放設備私有數據*info的空間.
4.3.5 Nand Flash芯片初始化
s3c2410_nand_init_chip()初始化struct nand_chip中的一些主要字段以及方法.其中主要包括的方法有:
1. s3c2410_nand_hwcontrol(); 硬件控制
2. s3c2410_nand_devready(); 設備是否準備好
3. s3c2410_nand_write_buf(); 寫一個buffer到nand flash
4. s3c2410_nand_read_buf(); 讀一個buffer到nand flash
5. s3c2410_nand_select_chip(); 選擇操作芯片
如果支持ECC硬件校驗,還設置如下方法:
1. s3c2410_nand_correct_data(); 通過ECC碼校正數據
2. s3c2410_nand_enable_hwecc(); 開啓硬件ECC檢查
3. s3c2410_nand_calculate_ecc(); 計算ECC碼
4.3.6 讀Nand Flash
當對nand flash的設備文件(nand flash在/dev下對應的文件)執行系統調用read(),或在某個文件系統中對該
設備進行讀操作時. 會調用struct mtd_info中的read方法,他們缺省調用函數爲nand_read(),在
drivers/mtd/nand/nand_base.c中定義.nand_read()調用nand_do_read_ecc(),執行讀操作. 在
nand_do_read_ecc()函數中,主要完成如下幾項工作:
1. 會調用在nand flash驅動中對struct nand_chip重載的select_chip方法,即
s3c2410_nand_select_chip()選擇要操作的MTD芯片.
2. 會調用在struct nand_chip中系統缺省的方法cmdfunc發送讀命令到nand flash.
3. 會調用在nand flash驅動中對struct nand_chip重載的read_buf(),即s3c2410_nand_read_buf()
從Nand Flash的控制器的數據寄存器中讀出數據.
4. 如果有必要的話,會調用在nand flash驅動中對struct nand_chip重載的
enable_hwecc,correct_data以及calculate_ecc方法,進行數據ECC校驗。
4.3.7 寫Nand Flash
當對nand flash的設備文件(nand flash在/dev下對應的文件)執行系統調用write(),或在某個文件系統中對該設備
進行讀操作時, 會調用struct mtd_info中write方法,他們缺省調用函數爲nand_write(),這兩個函數在
drivers/mtd/nand/nand_base.c中定義. nand_write()調用nand_write_ecc(),執行寫操作.在
nand_do_write_ecc()函數中,主要完成如下幾項工作:
1. 會調用在nand flash驅動中對struct nand_chip重載的select_chip方法,即
s3c2410_nand_select_chip()選擇要操作的MTD芯片.
2. 調用nand_write_page()寫一個頁.
3. 在nand_write_page()中,會調用在struct nand_chip中系統缺省的方法cmdfunc發送寫命令
到nand flash.
4. 在nand_write_page()中,會調用在nand flash驅動中對struct nand_chip重載的
write_buf(),即s3c2410_nand_write_buf()從Nand Flash的控制器的數據寄存器中寫入數據.
5. 在nand_write_page()中,會調用在nand flash驅動中對struct nand_chip重載waitfunc方法,
該方法調用系統缺省函數nand_wait(),該方法獲取操作狀態,並等待nand flash操作完成.等
待操作完成,是調用nand flash驅動中對struct nand_chip中重載的dev_ready方法,即
s3c2410_nand_devready()函數.


本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/bird67/archive/2008/02/21/2111034.aspx

發佈了79 篇原創文章 · 獲贊 3 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章