1. 程式人生 > >u-boot移植(四)---代碼修改---時鐘修改、SDRAM

u-boot移植(四)---代碼修改---時鐘修改、SDRAM

port write 啟動 tro nor ble 大小 pro 正常

  最開始已經建立了新單板以及配置文件,現在就需要做的是代碼的修改,配置成適合目標板使用的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