u-boot移植(四)---代碼修改---時鐘修改、SDRAM
最開始已經建立了新單板以及配置文件,現在就需要做的是代碼的修改,配置成適合目標板使用的u-boot。
一、時鐘修改
在代碼流程分析中,我們知道,系統的啟動是:
- 設置 CPU 為管理員模式
- 關閉看門狗
- 屏蔽中斷
- 設置啟動參數:時鐘 FCLK:HCLK:PCLK = 1:2:4 FCLK=120MHZ
- flush v4 I/D caches
- disable MMU stuff and caches
- DRAM設置
在DRAM設置中,有如下定義說明:
在這段初始化步驟中,並沒有看見系統時鐘的設置。
在S3C2440的datesheet中時鐘那一章,我們可以看到如下定義:
下面的英文的意思是:盡管 MPLL僅僅只是在一個 reset 後啟動,但是直到軟件對MPLLCON寄存器寫一個有效的設置之後,MPLL才作為系統時鐘的輸出。在有效設置之前,從外部晶振源(XTlPll或EXTCLK)獲得的時候將直接用於系統時鐘。哪怕用戶不想要改變MPLLCON寄存器的值,用戶都應該寫一個相同的值進MPLLCON寄存器。
而我們外部時鐘源的管腳定義說明如下:
實際電路如下:
黃色部分為我們外部時鐘源(EXTCLK)的管腳,可以看到,外部時鐘源被3.3V電壓拉高。而管腳定義中已經說明,如果外部時鐘源沒有使用,則將此管腳拉高。
OM[3:2]管腳都被拉低,則主時鐘源和USB時鐘源都選擇的是外部晶振,外部晶振輸入則為XTIpll管腳。晶振源為12MHz。
再來看看CLK的定義:
- FCLK: 為CPU核供給時鐘信號,我們所說的cpu主頻為200MHz,就是指的這個時鐘信號,相應的,1/Fclk即為cpu時鐘周期
- HCLK: 為AHB bus peripherals供給時鐘信號,AHB為advanced high-performance bus
- PCLK: 為APB bus peripherals供給時鐘信號,APB為advanced peripherals bus
分析一下時鐘源碼:
CLKDIVN寄存器的定義如下:
#3 = 0b0011 對應寄存器可知道
DIVN_UPLL:UCLK = UPLL clock
HDIVN:01 HCLK=FCLK/2
PDIVN:0 PCLK = HCLK/2 = FCLK/4
默認FCLK 為120MHz 則HDIVN和PDIVN都不為0,在datesheet的CLOCK CONTROL LOGIC 這一小節裏面有這樣的註意:
意思就是說我們的S3C2440不支持同步總線模式,我們必須改為異步模式,那麽我們必須在時鐘設置上加上那段代母,修改CPU的總線模式,改後代碼如下:
1 /* FCLK:HCLK:PCLK = 1:2:4 */ 2 /* default FCLK is 120 MHz ! */ 3 /* 設置啟動參數:時鐘 */ 4 ldr r0, =CLKDIVN /* r0中存放時鐘寄存器地址 */ 5 mov r1, #3 /* 將立即數0存放到r1中,r1 = 0x3 */ 6 str r1, [r0] /* 將r1中的值存放到以r0中的值為地址的存儲單元中,即 CLKDIVN = 0 */ 7 8 /* MMU_SetAsyncBusMode */ 9 mrc p15,0,r0,c1,c0,0 10 orr r0,r0,0xc0000000 11 mcr p15,0,r0,c1,c0,0
同樣的,在The Clock Distribution Block Diagram (POWER MANAGEMENT )框圖中,對FCLK有如下的定義:
再來看看 normal mode和 slow mode是什麽意思:
我們CPU的啟動是在normal mode中,同樣所以此時,我們是在處於normal mode。
MPLL為鎖相環輸出頻率 ,用來給MCU提供頻率,進而再給CPU的各個模塊供應頻率。具體可以看看datesheet中的Clock Generator Block Diagram 框圖。而文檔和前面已經說過:盡管 MPLL僅僅只是在一個 reset 後啟動,但是直到軟件對MPLLCON寄存器寫一個有效的設置之後,MPLL才作為系統時鐘的輸出。在有效設置之前,從外部晶振源(XTlPll或EXTCLK)獲得的時候將直接用於系統時鐘。哪怕用戶不想要改變MPLLCON寄存器的值,用戶都應該寫一個相同的值進MPLLCON寄存器。
而我們的源碼中,在時鐘設置後,就直接跳到cpu_init_crit 去執行,在其中又跳進lowlevel_init中執行DRAM的初始化,並且註釋中HCLK的默認頻率為60MHZ,此時的HCLK是依賴於MPLL的,因此我們必須添加上MPLL的設置:
註意下面的note:當我們設置MPLL & UPLL的值的時候,我們首先必須要設置UPLL的值,然後再設置MPLL的值。
同樣,在borad_f.c 中 board_early_init_f 函數裏面,進行了時鐘的初始化代碼過程:
我們可以將MPLL的設置放入我們的start.S中,並註釋掉這裏面的MPLL設置。
修改如下:
start.S
1 /* FCLK:HCLK:PCLK = 1:4:8 */ 2 /* default FCLK is 120 MHz ! */ 3 /* 設置啟動參數:時鐘 */ 4 ldr r0, =CLKDIVN /* r0中存放時鐘寄存器地址 */ 5 mov r1, #5 /* 將立即數0存放到r1中,r1 = 0x3 */ 6 str r1, [r0] /* 將r1中的值存放到以r0中的值為地址的存儲單元中,即 CLKDIVN = 0 */ 7 8 /* MMU_SetAsyncBusMode */ 9 mrc p15,0,r0,c1,c0,0 10 orr r0,r0,0xc0000000 11 mcr p15,0,r0,c1,c0,0 12 13 /* MPLLCON = s3c2440_MPLL_400MHZ */ 14 ldr r0, =0x4c000004 15 ldr r1, =s3c2440_MPLL_400MHZ 16 str r1, [r0] 17 18 /* 啟動ICACHE */ 19 mrc p15, 0, r0, c1, c0, 0 /* read control reg */ 20 orr r0, r0, #(1<<12) 21 mcr p15, 0, r0, c1, c0, 0 /* write it back */
DRAM修改:lowlevel_init.S (board\samsung\jz2440)
/* * 初始化存儲控制器,經過此初始化之後,內存才可以使用 */ /* 地址為 0x00000eb0 */ SMRDATA: .long 0x22011110 //BWSCON .long 0x00000700 //BANKCON0 .long 0x00000700 //BANKCON1 .long 0x00000700 //BANKCON2 .long 0x00000700 //BANKCON3 .long 0x00000740 //BANKCON4 .long 0x00000700 //BANKCON5 .long 0x00018005 //BANKCON6 .long 0x00018005 //BANKCON7 .long 0x008C04F4 //REFRESH .long 0x000000B1 //BANKSIZE .long 0x00000030 //MRSRB6 .long 0x00000030 //MRSRB7
board_early_init_f(Jz2440.c (board\samsung\jz2440) ):
二、調試
完成修改後,進行編譯調試:
2.1 編譯
編譯完成後,查看文件大小:
編譯出的文件大小公有500多KB。
2.2 燒寫進jz2440開發板
2.2.1 燒寫已經制作完成好的u-boot
開發板撥碼開關先撥至nand flash啟動那端。
用openjtag工具連接電腦和開發板,啟動命令行,進入uboot-bin所在目錄:
啟動oflash:
輸入數字0,啟動openjtag:
輸入數字1,選擇S3C2440:
選擇1 Nor Flash prog
輸入文件名:
選擇開始地址為0地址:
開始燒寫。
燒寫完成後,斷開JTAG口。(JTAG 線上有復位引腳,使用 JTAG 工具燒好程序後,一定要把 JTAG 工具和開發板之間的 JTAG 排線斷開, 並給開發板重新上電,開發板上的程序才能正常啟動。 )
2.2.2 燒寫新的u-boot
連接串口線,開發板設置為nor啟動,啟動開發板。啟動過程中按空格鍵
按q退出後,輸入命令查看分區大小:
bootloader分區不夠,我們的新的u-boot.bin有500多K,無法用命令o來燒寫。只能使用命令來燒寫,接上USB線。
打開dnw工具:
輸入如下命令:
設置dnw工具:
點擊USB Port-》transmit->transmit,選擇新編譯的u-boot.bin。
此時只是把文件發送到了內存當中。
去掉nor flash的寫保護:
從0地址開始擦除:
從30000000地址把程序拷貝到nor flash的0地址。
重啟開發板,查看燒寫,串口上無任何反應。
2.3 調試
使用openjtag進行調試。連接openjtag adapter。
打開openOCD GUI工具 點擊connect。
打開telnet:
執行命令,查看信息:
查看nor flash的0地址:
執行反匯編命令,生成u-boot.dis:
結合代碼查看,start.S中是執行玩了 cpu_init_crit後,跳轉到 _main中去執行:
_main在u-boot.dis中的地址如下:
從0地址開始運行:
在telnet中設置斷點:
繼續運行:
由於代碼中那時候內存已經初始化,那麽此時內存應該是可以訪問的:
讀內存:
寫內存,並將內存讀取出來:
數據是正確的,證明我們的修改沒有問題。SDRAM 的修改沒有問題。
此時還有一個問題是,我們的串口無任何打印。留待下一個再分析
u-boot移植(四)---代碼修改---時鐘修改、SDRAM