長篇連載
arm linux演藝
序
滾滾長江東四水
浪花淘淨英雄
大家好
許多人和我一樣
正在苦讀linux源代碼
希望有照一日
寶典在手
天下我有
小弟不才
也讀了兩年
寫的幾首歪詩
從本級開始
把我所理解的linux如何啟動貼出來
不懂之處大家討論一番
也希望把linux從頭到尾討論一遍
計劃寫它
回
三年寫完(笑
)
歡迎大家動員一些牛人來參與討論
提高人氣
增加流量
小弟用的是arm
T
跑LINUX
下面是第一回
長篇連載
arm linux演藝
第一回
話說
(噓聲
入正題把!
)
好好
首先
porting linux的時候要規劃內存影像
如小弟的系統有
m SDRAM
地址從
x
x
bff ffff
m flash
地址從
x
c
x
dff ffff
規劃如下
bootloader
linux kernel
rootdisk放在flash裡
具體從
x
c
開始的第一個
M放bootloader
x
c
開始的
m放linux kernel
從
x
c
開始都給rootdisk
啟動
首先
啟動後arm
T將地址
x
c
映射到
(可通過跳線設置)
實際上從
x
c
啟動
進入我們的bootloader
但由於flash速度慢
所以bootloader前面有一小段程序把bootloader拷貝到SDRAM 中的
x
AFE
再從
x
運行bootloader
我們叫這段小程序為flashloader
flashloader必須要首先初始化SDRAM
不然往那放那些東東
equ SOURCE
x
C
bootloader的存放地址
equ TARGET
x
AFE
目標地址
equ SDCTL
x
SDRAM控制器寄存器
// size is stored in location
x
C
FC
global _start
_start: //入口點
//;***************************************
//;* Init SDRAM
//;***************************************
// ;***************
// ;* SDRAM
// ;***************
LDR r
=SDCTL
//
// ; Set Precharge Command
LDR r
=
x
//ldr r
=
x
STR r
[r
]
// ; Issue Precharge All Commad
LDR r
=
x
LDR r
[r
]
// ; Set AutoRefresh Command
LDR r
=
xA
STR r
[r
]
// ; Issue AutoRefresh Command
LDR r
=
x
LDR r
[r
]
LDR r
[r
]
LDR r
[r
]
LDR r
[r
]
LDR r
[r
]
LDR r
[r
]
LDR r
[r
]
LDR r
[r
]
// ; Set Mode Register
LDR r
=
xB
STR r
[r
]
// ; Issue Mode Register Command
LDR r
=
x
//; Mode Register Value
LDR r
[r
]
// ; Set Normal Mode
LDR r
=
x
STR r
[r
]
//;***************************************
//;* End of SDRAM and SyncFlash Init *
//;***************************************
// copy code from FLASH to SRAM
_CopyCodes:
ldr r
=SOURCE
ldr r
=TARGET
sub r
r
#
ldr r
[r
]
_CopyLoop:
ldr r
[r
]
str r
[r
]
add r
r
#
add r
r
#
sub r
r
#
teq r
#
beq _EndCopy
b _CopyLoop
_EndCopy:
ldr r
=TARGET
mov pc
r
欲知後事如何
下回分解
長篇連載
arm linux演藝
第二回
上回書說到flashloader把bootloader load到
x
AFE
然回跳了過去
其實
x
AFE
就是燒在flash
x
C
中的真正的bootloader:
bootloader 有幾個文件組成
先是START
s
也是唯一的一個匯編程序
其余的都是C寫成的
START
s主要初始化堆棧
_start:
ldr r
=StackInit
ldr sp
[r
]
b main
//此處我們跳到了C代碼的main函數
當C代碼執行完後
還要調用
//下面的JumpToKernel
x跳到LINXU kernel運行
equ StackInitValue
__end_data+
x
//
K __end_data在連結腳本中指定
StackInit:
long StackInitValue
global JumpToKernel
JumpToKernel:
// jump to the copy code (get the arguments right)
mov pc
r
global JumpToKernel
x
// r
= jump address
// r
r
= arguments to use (these get shifted)
JumpToKernel
x:
// jump to the copy code (get the arguments right)
mov r
r
mov r
r
mov r
r
mov r
r
mov r
r
mov pc
r
section
data
boot
section
bss
boot
欲知bootloader中的c代碼如何運行
請看下集
長篇連載
arm linux演藝
第三回
書接上回
下面讓我們看看bootloader的c代碼干了些什麼
main函數比較長
讓我們分段慢慢看
int main()
{
U
*pSource
*pDestin
count;
U
countDown
bootOption;
U
delayCount;
U
fileSize
i;
char c;
char *pCmdLine;
char *pMem;
init(); //初始化FLASH控制器和CPU時鐘
EUARTinit(); //串口初始化
EUARTputString(
\n\nDBMX
Linux Bootloader ver
\n
);
EUARTputString(
Copyright (C)
Motorola Ltd
\n\n
);
EUARTputString((U
*)cmdLine);
EUARTputString(
\n\n
);
EUARTputString(
Press any key for alternate boot
up options
);
小弟的bootloader主要干這麼幾件事:init(); 初始化硬件
打印一些信息和提供一些操作選項
Program bootloader image
Program kernel image
Program root
disk image
Download kernel and boot from RAM
Download kernel and boot with ver
x bootloader format
Boot a ver
x kernel
Boot with a different command line
也就是說
可以在bootloader裡選擇重新下載kernel
rootdisk並寫入flash
下載的方法是用usb連接
m的rootdisk也就刷的一下
關於usb下載的討論請參看先前的貼子
為arm開發平台增加usb下載接口
如果不選
直接回車
就開始把整個linux的內核拷貝到SDRAM中運行
列位看官
可能有人要問
在flashloader中不是已經初始化過sdram控制器了嗎?怎麼init(); 中還要初始化呢
各位有所不知
小弟用的是syncflash
可以直接使用sdram控制器的接口
切記
在flash中運行的代碼是不能初始化連接flash的sdram控制器的
不然絕對死掉了
所以
當程序在flash中運行的時候
去初始化sdram
而現在在sdram中運行
可放心大膽地初始化flash了
主要是設定字寬
行列延時
因為缺省都是最大的
另外
如果列位看官的cpu有足夠的片內ram
完全可以先把bootloader放在片內ram
干完一切後再跳到LINUX
小弟著也是不得已而為之啊
今天太晚了
回去睡覺了
長篇連載
arm linux演藝
第四回
如果直接輸入回車
進入kernel拷貝工作
EUARTputString(
Copying kernel from Flash to RAM
\n
);
count =
x
; //
Mbytes
pSource = (U
*)
x
C
;
pDestin = (U
*)
x
;
do
{
*(pDestin++) = *(pSource++);
count
=
;
} while (count >
);
}
EUARTputString(
Booting kernel
\n\n
);
這一段沒有什麼可說的
運行完後kernel就在
x
了
至於為什麼要
空出
x
的一段
主要是放kelnel的一些全局數據結構
如內核頁表
arm的頁目錄要有
k大
我們知道
linux內核啟動的時候可以傳入參數
如在PC上
如果使用LILO
當出現LILO
我們可以輸入root=/dev/hda
或mem=
M等指定文件系統的設備或內存大小
在嵌入式系統上
參數的傳入是要靠bootloader完成的
pMem = (char *)
x
FF
; //參數字符串的目標存放地址
pCmdLine = (char *)&cmdLine; //定義的靜態字符串
while ((*(pMem++)=*(pCm
From:http://tw.wingwit.com/Article/program/Oracle/201311/16703.html