嵌入式學習筆記_第1頁
嵌入式學習筆記_第2頁
嵌入式學習筆記_第3頁
嵌入式學習筆記_第4頁
嵌入式學習筆記_第5頁
已閱讀5頁,還剩109頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、nand 啟動時 bank0 失效,即用不了NOP FLASHnand flash 前4K被強制復制到片內 SRAM 4K內存中,然后CPU會從零地址(SRAM)開始執(zhí)行。nor 啟動時 nor flash 零地址在nor flash cpu從零地址執(zhí)行。nor flash特征是可以像內存一樣讀數據,但是不能像內存一樣直接寫數據, 要通過命令先擦除后才能寫數據。 GPIO實驗:main 沒什么特別的,一樣要被別人調用,執(zhí)行往也要返回。啟動文件: 調用 main,調用完之后要返回,所以要設置返回地址。最后要進行一些清理工作。軟件初始化: 設置棧 /*設置棧就是把棧指針SP指向某個內存,假如指向S

2、DRAM則要先初始化SDRAM才能設置棧 */設置返回地址 /*bl指令會跳轉到main函數,并且把返回地址保存在LR寄存器里面。*/調用main清理工作硬件初始化:關看門狗 /*上電時候看門狗啟動,會倒數計時三秒內沒有關閉就會重啟系統。所以要關掉*/初始化時鐘 /*想要跑的更快要初始化時鐘*/初始化SDRAM/*/設置返回地址:blmain /*bl指令會跳轉到main函數,并且把返回地址保存在LR寄存器里面。*/ /*bl 指令會把返回地址存在lr寄存器里面。*/#defineGPFCON (*(volatile unsigned long *)0x56000050) /* volatil

3、e讓編譯器不要優(yōu)化變量*/ #defineGPF4_out(1<<(4*2)#defineGPF5_out(1<<(5*2)#defineGPF6_out(1<<(6*2)#defineGPF7_out(1<<(7*2) GPFCON |= GPF4_out|GPF5_out|GPF6_out;/ 將LED1-3對應的GPF4/5/6三個引腳設為輸出按位操作:想要清零 : 按位與 /*例如清bit3 則 a&=(1<<3)*/想要置“1” : 按位或 /*例如置bit3 則 a|= (1<<3)*/SRAM在芯片手

4、冊里面稱為 steppingstoneCPU通過存儲管理器才知道怎么訪問外部的設備 例如 SDRAM DM9000網卡等想訪問一個芯片,需要哪些條件1:地址線(例如SDRAM 行地址13位,列地址9位) 看芯片手冊2:數據線 /* 8/16/32位 數據寬度 例如SDRAM 位寬32位 SDRAM32位,所以 ADDR0,ADDR1就不需要使用。 */ 看原理圖3:時鐘/頻率 (刷新周期 8192/64ms 即刷新8192次需要64ms)看芯片手冊4:芯片相關:例如SDRAM(行地址,列地址,Bank) 看芯片手冊SDRAM32位,所以 ADDR0,ADDR1就不需要使用。因為2440的地址的

5、單位是byte(8位),所以CPU發(fā)出的0,1,2,3這四個地址都是訪問到SDRAM地址中的同一個單元。返回都是返回同一個四字節(jié)(32位)的數據。假如訪問的芯片去16位的,則ADDR0 就不需要使用。想要訪問某個芯片(如SDRAM)先要配置存儲管理器(位寬,行列地址,刷新周期)。所謂配置也就是設置寄存器。2440可以接8個外設(SDRAM,DM9000網卡,NOR FLASH等等),因為有8個Bank,有8條片選信號(CS信號)。 Bank05都是一樣的結構。Bank67比較特別,它們可以接SDRAM。 內存可以分為SRAM,SDRAM,DDR等等。SRAM很快但是比較貴,使用方法簡單,直接發(fā)

6、地址信號就可以了。SDRAM比較便宜且訪問比較復雜,它的地址還分為Bank地址,行地址,列地址。還要不斷的刷新SDRAM(REFRESH寄存器就是用來設置刷新周期的),不刷新數據就會丟失。網卡,NOR FLASH它們的接口跟根SRAM的接口是一樣的,術語上稱為 RAM like。每個Bank可以外接128M的東西,尋址空間是128M。bank7/bank6可以組(128M/128M,64M/64M,32M/32M等)大程序啟動過程:1:一上電nand flash前4K被拷貝到SRAM中。2:程序會先關看門狗,初始化存儲管理寄存器,SDRAM。3:拷貝到SRAM中的4K代碼再把nand flas

7、h中的代碼拷貝到SDRAM中去,然后繼續(xù)執(zhí)行(在SDRAM中運行)。arm-linux-ld -Ttext 0x3000000 -g led_on.o -o led_on_elf (Ttext 0x3000000 是鏈接地址)所謂鏈接地址就是說,運行時程序“應該”位于哪里。所以head.s 就應該從片內SRAM拷到SDRAM中去。當前PC值 = 當前指令的地址 + 8 / pc = 當前指令地址 + 8MMU:權限管理,地址映射。使用MMU時,使用CPU發(fā)出的地址是虛擬地址?;蛘呤钦鎸嵉奈锢淼刂?。CPU發(fā)出的是物理地址還是虛擬地址CPU是不在乎的,CPU沒有虛擬地址和物理地址概念。寫程序的時候

8、,我們說的地址例如鏈接地址,也沒有虛擬地址,物理地址概念。就是一個單純的地址。地址只是從CPU角度看到的。虛擬地址(VA)怎么轉換為物理地址(PA)。 對于mips架構來說 VA=0xA000,0000 + PA /* VA=fun(PA)*/對于ARM結構來說:表格: 一級頁表,二級頁表。 對于ARM來說有兩種映射:段和頁段映射: 表格里面每一個表項對應一段,表示大小是 1M。假如CPU的地址數是4G,則需要的表格數位4G/1M=4*1024=4096個。創(chuàng)建頁表:啟動前和啟動瞬間,地址要連續(xù)。A:所以04096的虛擬地址要對應04096的物理地址使用MMU會加快程序的運行速度,因為有DCA

9、CH,ZCACH。這些會加快程序運行速度。1,MMU首先知道你創(chuàng)建的這些頁表項都放在哪里;2,MMU通過虛擬地址的高12位可以找到對應的頁表項,并且這個頁表項的高12位就是物理地址的高12位;3,虛擬地址的低20位就是物理地址的低20位;4,頁表項的高12位+虛擬地址的低20位=物理地址。SDRAM程序中mem_cfg_val結構體中的的數字為寄存器BWSCON,BANKCON0,BANKCON1,BANKCON2,BANKCON3,BANKCON4,BANKCON5,BANKCON6,BANKCON7,REFRESH,BANKSIZE,MRSRB6,MRSRB7寄存器賦值。目的是初始化SDR

10、AM。unsigned long *p = (unsigned long *)MEM_CTL_BASE; 此語句是將指針P指向寄存器 0x48000000MMU代碼:/*復制第二段代碼到SDRAM中*/void copy_2th_to_sdram(void) unsigned int *pdwSrc = (unsigned int *)2048; unsigned int *pdwDest = (unsigned int *)0x30004000;/*地址為0x30004000是因為前16K用來存放頁表 */ while (pdwSrc < (unsigned int *)4096) *

11、pdwDest = *pdwSrc; pdwDest+; pdwSrc+; 寄存器: NFCMMD NFADDR NFDATANand flash 沒有地址總線跟CPU相連,不同于SDRAM,DM9000網卡,SRAM,寄存器等都有地址總線與CPU相連,所以SDRAM,DM9000網卡,SRAM,寄存器與Nand flash的尋址方式不一樣。SDRAM,DM9000網卡,SRAM,寄存器的地址是CPU發(fā)出來的,或稱為CPU統一編址。 而Nand flash 的地址是Nand flash 自己編址的,CPU “看不到”的。 所以CPU說的“0”地址與Nand flash 說的“0”地址不是一個概

12、念。那Nand flash 是怎么編址的呢?從原理圖上,Nand flash 與CPU相連的只有 數據總線,控制總線。所以CPU發(fā)出的 地址,命令都是由數據總線進行傳輸。但是如何分辨是 地址還是命令呢?顯然是通過控制總線進行區(qū)分。 CLE(高電平) 信號是命令, ALE(高電平) 信號是地址, 兩個信號都無效的話 傳輸的就是數據。 是讀數據 還是寫數據 又由 nFWE(讀) 引腳 nFRE(寫)引腳控制。Nand flash 的典型結構是 大頁,一個大頁有2K 也就是2048字節(jié)。有64頁。 注意:每一個大頁中都有一個叫 OOB的空間(64字節(jié))。一般來說用不到OOB這個空間,例如我們要訪問第

13、2049這個字節(jié)空間,不會訪問到OOB這個空間而是訪問第二頁開始的第二個字節(jié)。所以真實的一頁是 2K+64字節(jié)。只是64字節(jié)基本上不用。那怎么訪問 Nand flash ?1:發(fā)出命令 CLE NFCMMD 寄存器2:發(fā)出地址 ALE NFADDR 寄存器3:發(fā)出數據 R/W NFDATA 寄存器4:狀態(tài) NFSTAT 寄存器 /發(fā)出擦除命令不可能馬上就擦除成功,用狀態(tài)寄存器確定NAND FLASH的狀態(tài)判斷是否擦除成功代碼: ldr r0, =0x30000000 1. 目標地址=0x30000000,這是SDRAM的起始地址 mov r1, #4096 2. 源地址 = 4096,連接的時

14、候,main.c中的代碼都存在NAND Flash地址4096開始處 mov r2, #2048 3. 復制長度= 2048(bytes),對于本實驗的main.c,這是足夠了 bl nand_read 匯編和C語言傳遞參數: 如上例子,r0為傳遞給C函數(nand_read)的第一個參數,r1為第二個,r2為第三個。 void nand_read(unsigned char *buf, unsigned long start_addr, int size);中斷:ARM體系CPU的7種工作模式:用戶模式(usr):ARM處理器正常的程序執(zhí)行狀態(tài)該模式下的寄存器:r0 r1 r2 r3 r4

15、r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15(pc)系統模式(sys):運行具有特權的操作系統任務該模式下的寄存器:r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15(pc)快速中斷模式(fiq):用于高速數據傳輸或通道處理該模式下的寄存器:r0 r1 r2 r3 r4 r5 r6 r7 “r8_fiq” “r9_fiq” “r10_fiq” “r11_fiq” “r12_fiq” “r13_fiq” “r14_fiq” r15(pc)中斷模式(irq):用于通用的中斷處理該模式下的寄存器:r0 r1 r2

16、 r3 r4 r 5 r6 r7 r8 r9 r10 r11 r12 “r13_irq” “r14_irq” r15(pc)管理模式(svc):操作系統使用的保護模式該模式下的寄存器:r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 “r13_svc” “r14_svc” r15(pc)數據訪問終止模式(abt):當數據或指令預取終止時進入該模式,可用于虛擬存儲及存儲保護該模式下的寄存器:r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 “r13_abt” “r14_abt” r15(pc)未定義指令中止模式(und):當未定

17、義的指令執(zhí)行時進入該模式,可用于支持硬件協處理器的軟件仿真該模式下的寄存器:r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 “r13_und” “r14_und” r15(pc)由上可知除了系統模式和用戶模式的寄存器相同,其余的5個模式下的寄存器不相同。其中 快中斷模式 擁有7個獨立寄存器,其余模式都是 r13 r14 兩個寄存器獨立。中斷也是一種異常發(fā)生了異常之后:1:CPU 強制進入異常模式,就是切換寄存器(如上) /*這里就是說發(fā)生異常之后CPU進入異常模式 2:PC(r15) = 異常入口 然后程序自動跳到異常入口*/設置棧,棧 sp 就是 r13。

18、異常入口是什么: 就是CPU固定的地址。 如下:* 異常向量,本程序中,除Reset和HandleIRQ外,其它異常都沒有使用* .extern main.text .global _start _start: _start 表示0地址入口復位異常的入口就是0地址,發(fā)生復位之后CPU自動跳到0地址取指執(zhí)行 b Reset 0x04: 未定義指令中止模式的向量地址HandleUndef: b HandleUndef /*死循環(huán)*/ 0x08: 管理模式的向量地址,通過SWI指令進入此模式HandleSWI: b HandleSWI /*死循環(huán)*/ 0x0c: 指令預取終止導致的異常的向量地址Ha

19、ndlePrefetchAbort: b HandlePrefetchAbort /*死循環(huán)*/ 0x10: 數據訪問終止導致的異常的向量地址HandleDataAbort: b HandleDataAbort /*死循環(huán)*/ 0x14: 保留HandleNotUsed: b HandleNotUsed /*死循環(huán)*/ 0x18: 中斷模式的向量地址 b HandleIRQ 0x1c: 快中斷模式的向量地址HandleFIQ: b HandleFIQ /*死循環(huán)*/Reset: ldr sp, =4096 設置棧指針,以下都是C函數,調用前需要設好棧 bl disable_watch_dog

20、關閉WATCHDOG,否則CPU會不斷重啟 msr cpsr_c, #0xd2 進入中斷模式 ldr sp, =3072 設置中斷模式棧指針 msr cpsr_c, #0xd3 進入管理模式 ldr sp, =4096 設置管理模式棧指針, 其實復位之后,CPU就處于管理模式, 前面的“l(fā)dr sp, =4096”完成同樣的功能,此句可省略 bl init_led 初始化LED的GPIO管腳 bl init_irq 調用中斷初始化函數,在init.c中 msr cpsr_c, #0x53 設置I-bit=0,開IRQ中斷 ldr lr, =halt_loop 設置返回地址 ldr pc, =m

21、ain 調用main函數halt_loop: b halt_loopHandleIRQ: sub lr, lr, #4 計算返回地址 /*這個是ARM架構決定的,所以就是這個。*/ stmdb sp!, r0-r12,lr 保存使用到的寄存器 注意,此時的sp是中斷模式的sp 初始值是上面設置的3072 ldr lr, =int_return 設置調用ISR即EINT_Handle函數后的返回地址 ldr pc, =EINT_Handle 調用中斷服務函數,在interrupt.c中int_return: ldmia sp!, r0-r12,pc 中斷返回, 表示將spsr的值復制到cpsr怎

22、么用中斷? “被中斷”1:中斷發(fā)生。 要做什么事情? “保存”“別人”的狀態(tài) 先初始化引腳等,然后使能中斷2:中斷處理 分辨中斷源,根據中斷源進行不同的處理,然后進行清理工作(清中斷)3:恢復“別人”的狀態(tài) 就是恢復寄存器。中斷控制器:1:使能中斷 2:狀態(tài)寄存器(分辨中斷源) 3:設置 高電平 低電平 上升沿 下降沿 等觸發(fā)。4:引腳設置 設置為輸入,輸出,中斷。 5:優(yōu)先級寄存器 設置棧,棧 sp 就是 r13。 切換到中斷模式(或其他異常模式)時,要重新設置棧,因為r13 (sp)是每個模式下獨有的。怎么進入中斷? msr cpsr_c, #0xd2 進入中斷模式,運行這個msr cps

23、r_c 指令就可以進入中 斷,而x0d2表示進入哪個中斷。具體如下。0xd2 二進制為:110 10010除r0 r15 這16個寄存器外 還有第17個寄存器 cpsr(當前狀態(tài)寄存器) (詳見MSR和MRS文本)控制位:(以0xd2 為例)I中斷禁止位 F快速中斷禁止位 TCPU狀態(tài)位 M4工作模式位 M3工作模式位 M2工作模式位 M1工作模式位 M0工作模式位1 1 0 1 0 0 1 0以上就是表示中斷模式。M4:010000 User 表示用戶模式10001 FIQ 表示快中斷模式10010 IRQ 表示中斷模式10011 Supervisor 表示管理模式10111 Abort 表

24、示數據訪問中止模式11011 Undefined 表示未定義指令中止模式11111 System 表示系統模式系統時鐘:2440 CPU : 400M (FCLK) 如果什么都不設置,CPU 是以晶振的頻率 12M HZ 在跑。SDRAM,MD900,NOR FLASH等: 100M 133M (HCLK)UART,定時器,I2C等 : 50M (PCLK)2440 的晶振只有12M設置 PLL 寄存器 設置頻率怎么設置 FCLK PCLK HCLK1:晶振PLL400M HZ PLL (LOCKTIME)鎖定時間寄存器(使用默認值就可以了),MPLLCON 設置晶振頻率的寄存器2:400M

25、HZ 分頻(HCLK PCLK) 分頻寄存器 CLKDIVN 設置 波特率 UBRDIVn(n=01) 有一個公式 看數據手冊位置相關:PCnew = 某個絕對值引入一個新的概念:位置無關碼 bl和b 指令就是位置無關碼。 PCnew = PC(當前) +偏移 /*偏移值是編譯器幫我們算好的。*/ PCnew = (4+8) + 0x28 =0x34 /* +8是ARM架構決定的。 */那怎么寫位置無關碼的代碼?1:匯編中使用 bl或 b 指令進行跳轉2:C語言中不使用全局變量,靜態(tài)變量 當PC指針跳到應該位于的位置時 就不用考慮全局變量,靜態(tài)變量這些限制 以上詳情看 視頻例子 UART 的代

26、碼。關于位置無關的一些心得:當程序被拷貝到4K RAM里面開始執(zhí)行。如果用位置無關碼寫程序,程序之間的跳轉都是用相對跳轉的(PC = 當前地址 + XXX)。而不是用絕對地址(鏈接地址)也就是說,當程序再4K里面運行的時候,PC的值就是在這4K里面,當用相對跳轉的時候,要跳轉的地址也就只能出現在4K。但是如果用了位置相關碼,那么一跳轉就到SDRAM了LCD原理圖:有哪些信號:1:垂直方向的同步信號 VSYNC2:水平方向的同步信號 HSYNC3:使能信號 VDEN4:背光信號 LED- LED+ GPB0 輸出高電平 背光芯片才會工作 LCD才會點亮。 所以第一步就是要設置 GPB0 為輸出高

27、電平5:時鐘信號 VCLK6:數據信號 VD0 VD23寫程序:1:打開背光2:時序設置3:在Frame Buffer寫數據LCD選定之后,像素寬度是固定的。 JZ2440的 LCD的像素寬度就是 16bpp(一個像素用16位數據表示)JZ2440 LCD 上每一個像素對應 Frame Buffer 里的2字節(jié)(因為16bpp)。那要使LCD的像素與 Frame Buffer 對應? 設置BSWP HWSWP兩個寄存器。詳情見手冊。因為LCD 的像素寬度是固定的16bpp,但是如果硬是要使用 8bpp。就要涉及 “調色板(Palette)”。8bpp 的數據寬度可以有 256 種顏色。 所以調

28、色板(Palette)中也是256中顏色,但是為了跟LCD的 16bpp 對應。所以調色板(Palette)上 用16位來存一種顏色。要使用調色板,需要將調色板初始化 LCD 控制器: LCDCONn (n=15)清屏: 可以將一種顏色 發(fā)給 TPAL寄存器,然后使能 TPAL寄存器。之后 2440 LCD控制器就會從TPAL寄存器取顏色發(fā)給LCD(全屏)LCD 代碼中 LCDSADDR1 = (LCDFRAMEBUFFER>>22)<<21) | LOWER21BITS(LCDFRAMEBUFFER>>1); LCDSADDR2 = LOWER21BITS

29、(LCDFRAMEBUFFER+ (LINEVAL_TFT_240320+1)*(HOZVAL_TFT_240320+1)*2)>>1); LCDSADDR3 = (0<<11) | (LCD_XSIZE_TFT_240320*2/2);這一段是2440要我們怎么做我們就怎么做 沒什么好說的。UBOOT 的最終目的是要 啟動內核 1:從flash 讀出內核,放到SDRAM 2:啟動內核所以UBOOT要實現的核心功能:1:讀flash,寫flash。2:初始化SDRAM,初始化時鐘,關看門狗。3:從flash 讀出內核4:啟動內核為了開發(fā)方便: 開發(fā)功能:1:燒寫flas

30、h2:初始化網卡(用網絡下載文件)3:初始化USB(用USB下載文件)4:初始化串口(在PC機上中斷操作UBOOT)UBOOT make 的時候為什么知道要先 make 100ask_24x0.config? 是因為UBOOT文件中有一個 README 文件。里面寫有了關于UBOOT的約定。分析UBOOT文件源碼時首先要分析 MakeFile 找到鏈接地址,然后根據鏈接地址找到第一個源文件,然后根據源文件一路分析貫通。 視頻以后多看幾遍。UBOOT heads.S 完成步驟1:設為svc 管理模式2:關看門狗3:屏蔽中斷4:初始化SDRAM5:設置棧6:初始化時鐘7:重定位(將代碼從 nand

31、 flash 中拷到 SDRAM )8:清bss段。所謂bss段就是,未定義的一些靜態(tài)變量,全局變量。以免占用內存。9:調用 start_armboot C函數。UBOOT的核心是命令,讀出內核以及啟動內核都是需要命令的。所以可以想象到UBOOT的代碼中一定有一個命令的結構體,這個結構體中包含了所有的命令,當我們在UBOOT界面上輸入命令是會去匹配,匹配到哪個命令就執(zhí)行哪個命令。內核啟動流程分析:1:解壓縮2:打補丁 打補丁用 patch 命令 patch -p_ <某個目錄下的補丁文件3:配置 配置有三種方式 a:make menuconfig b:使用默認配置在上面修改 c:使用廠家

32、提供的配置文件 如果直接 make menuconfig 的話里面成千上萬的配置選項,是很復雜的。所以我們用默認的配置文件。那我們不知道默認的配置文件怎么辦呢? 可以再終端輸入 fine -name "*defconfig*"查找有哪些默認的配置文件的目錄,然后在相應目錄下找到自己需要的配置文件。2440開發(fā)板 用的配置文件是 s3c2410_defconfig。然后執(zhí)行 make s3c2410_defconfig。最后執(zhí)行 make menuconfig執(zhí)行完 make menuconfig 后就會在s3c2410_defconfig 的基礎上出現一個配置菜單,然后就可

33、以自己修改配置項了。由上述的步驟可以知道,當執(zhí)行 make s3c2410_defconfig 后,終端提示 所有的配置項被寫入.config里面。所以make menuconfig 是去.config里面讀取需要的配置項。所以使用廠家的配置文件,只需要將廠家的配置文件CP成.config就行了。(cp config_ok .config)結合makefile進行分析以一個配置項為例:CONFIG_DM90001:c源碼中定義了 CONFIG_DM9000 是個宏 宏對C語言來說只能在C語言和頭文件中定義。所以這個宏來源于autoconfig.h2:子目錄下Makefile :drivers/

34、net/makefile3:include/config/autoconfig 中定義了 CONFIG_DM9000 。4:include/linux/autoconfig.h 由名字可以知道autoconfig.h是配置的時候自動根據.config生成的。查看autoconfig.h的時候發(fā)現里面的宏大部分都被定義為“1”。也就是說在配置內核的時候無論配置項(DM9000)被設置為“Y” “N” 還是“M”都被定義為“1”。那么 Y N M 之間的差別怎么體現呢?竟然C語言和頭文件中不能體現區(qū)別,那么只能在子目錄中的Makefile中體現。這里插講一下子目錄的Makefile。 格式比較簡單

35、 obj-y +=xxx.o 表明xxx.c這個文件最后會編譯進內核 obj-m += yyy.o 表示 yyy.c這個文件最后會變編譯成一個可加載的模塊。所以子目錄中的Makefile 寫成 obj-$(config_DM9000) +=dm9000.o 分析內核的Makefile 可以找到第一個文件,還有鏈接腳本。第一個文件 arch/arm/kernel/head.s鏈接腳本 arch/arm/kernel/vmlinux.lds內核: 最終目的是要運行應用程序1:處理UBOOT傳入的參數 a:判斷是否支持這個CPU b:判斷是否支持這個單板(UBOOT啟動內核時傳入的機器ID) c:使

36、能MMU d:跳到start_kernel2:掛接根文件系統內核怎樣啟動第一個應用程序1:打開一個設備open(dev/console) /*這三個程序代表 printf scanf err() */ sys_dup(0) sys_dup(0)2:然后用run_init_process(某個目錄下的程序); 例如:run_init_process(“/sbin/init”); 這個函數啟動某個程序busybox:ls cp cd等等的組合 我們執(zhí)行l(wèi)s cp cd 等命令時,實際上就是執(zhí)行busybox這個程序 ls cp cd 等都是指向busybox內核的最終目的不是啟動第一個文件 sbi

37、n/init 而是要啟動用戶程序。但是怎么知道要啟動什么程序呢? 做手機的啟動手機程序 做監(jiān)控的啟動監(jiān)控程序。 所以需要一個配置文件 指定應用程序還有指定何時執(zhí)行。 而內核的配置文件一般來說在etc/目錄下如果沒有配置文件的話,內核會自動執(zhí)行一個默認的配置項。busybox-> init_main parse_inittab() file = fopen(INITTAB,"r"); /打開配置文件 /etc/inittab 如果沒有配置文件的話,內核會自動執(zhí)行一個默認的配置項 如果有的話就會對配置文件進行解析,例如 #開頭的忽略當做注釋,為id加個/dev/的前綴。

38、解析完之后最終要調用 new_init_action(a->action,command,id) new_init_action 要做什么事情 1:創(chuàng)建一個init_action結構,這個結構的內容用new_init_action(a->action,command,id)中的參數進行填充。 2:把這結構放入init_action_list鏈表 run_actions(SYSINIT); /*執(zhí)行*/ waitfor(a,0); /*執(zhí)行程應用序,等待它執(zhí)行完畢*/ run(a); /*創(chuàng)建子進程,子進程就是process里面指定的應用程序*/ waitpid(runpid,&am

39、p;status,0); /* 等待它結束*/ delete_init_action(a); /*把init_action結構在init_action_list鏈表里刪掉,所以用run_actions(SYSINIT); 定義的程序 執(zhí)行一次就被刪掉了。*/ run_actions(WAIT); waitfor(a,0); /*執(zhí)行程應用序,等待它執(zhí)行完畢*/ run(a); /*創(chuàng)建子進程,子進程就是process里面指定的應用程序*/ waitpid(runpid,&status,0); /* 等待它結束*/ delete_init_action(a); /*把init_actio

40、n結構在init_action_list鏈表里刪掉,所以用run_actions(SYSINIT); 定義的程序 執(zhí)行一次就被刪掉了。*/ run_actions(ONCE); /*ONCE 跟前面的 SYSINIT,WAIT有點不一樣,因為沒有 waitpid(runpid,&status,0); 所以init進程不會等待它執(zhí)行完畢。*/ run(a); delete_init_action(a); while(1) run_actions(RESPAWN); if (a->pid = 0) a->pid = run(a); run_actions(ASKFIRST);

41、if (a->pid = 0) a->pid = run(a); wpid = wait(NULL); /*等待子進程退出*/ while(wpid>0) a->pid = 0; /*退出后,就這是pid=0*/ inittab格式:<id>:<runlevels>:<action>:<process>id-> /dev/id :用作終端,stdin,stdout,stderr: printf scanf err /*<id>: WARNING: This field has a non-traditio

42、nal meaning for BusyBox init!*/runlevels :忽略 /*The runlevels field is completely ignored.*/action :執(zhí)行時機 /*Valid actions include: sysinit, respawn, askfirst, wait, once, restart, ctrlaltdel, and shutdown.*/process :應用程序或腳本 /* Specifies the process to be executed and it's command line.*/由上可知,一個最小的

43、根文件系統需要的項:1: /dev/console /dev/null2:init->busybox3:/etc/inittab /*配置文件*/4: 配置文件里指定的應用程序5:庫 init本身,即busybox 編譯busybox在源碼中找到“INSTALL”文件,閱讀文件知道怎么編譯busybox make menuconfig # This creates a file called ".config" make # This creates the "busybox" executable make install # or make C

44、ONFIG_PREFIX=/path/from/root install /*默認是安裝到PC機中的文件系統的,為了避免破壞整個系統。 所以我們應該安裝到我們指定的目錄里面*/ 配置 busybox 的時候 配置上 Tab completion 以后使用的時候比較好用。 Tab completion (Tab 補全) 輸入命令的時候按 tab鍵會自動補全命令 例如:cd /work/ cd/wo此時按tab鍵 會自動補全為 cd /work/ make menuconfig 后 make 編譯busybox 的時候可能會出現錯誤,出現措錯誤的話就重新編譯,將出現錯誤的命令配置項去掉。如果實在是

45、想要用這個命令就上網搜。解決辦法。make好之后千萬不要直接 make install 因為默認安裝到 PC機,這樣會破壞我們的電腦。先創(chuàng)建一個目錄(/work/nfs_root/first_root/tmp),然后 make CONFIG_PREFIX=/work/nfs_root/tmp install根據這五項:1: /dev/console /dev/null2:init->busybox3:/etc/inittab /*配置文件*/4: 配置文件里指定的應用程序5:庫 創(chuàng)建最小的根文件系統(在 /work/nfs_root 目錄下)第一 創(chuàng)建 /dev/console /dev

46、/null 這兩個設備文件。怎么創(chuàng)建呢? 用sudo mknod console 【設備類型】 【主設備號】 【次設備號】先看看PC機上/dev/console /dev/null 這兩個文件是怎么回事。 用 ls /dev/console /dev/null -l 命令行查看設備的 主設備號 次設備號 crw-1 root root 5,1 2010-11-26-07:47 /dev/console /*開頭的“C”表示該設備是字符設備,“5”是主設備號,“1”是次設備號*/ crw-rw-rw-1 root root 1,3 2010-11-26-07:47 /dev/null /*開頭的

47、“C”表示該設備是字符設備,“1”是主設備號,“3”是次設備號*/由上可知 sudo mknod console c 5 1 sudo mknod null c 1 3 第二 要構造一個 inittab第三 安裝glibc庫mkdir /work/nfs_root/first_root/libcd /work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib 進入含有glibc庫的目錄下。cp *.so* /work/nfs_root/first_root/lib -d 將glibc庫拷貝到 最小根文件系統目錄下。注意拷貝的時候要加個“-d”選項,否則庫文件會很大。至此我們已經做好了最少根文

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論