首先從u-boot官網下載最新版的u-boot,這裡我下的是u-boot-2015.10。下載完成後解壓,閱讀README,在Building the Software:中得知編譯方法:如果使用交叉編譯的話要執行以下命令: CROSS_COMPILE=arm-linux- export CROSS_
首先從u-boot官網下載最新版的u-boot,這裡我下的是u-boot-2015.10。下載完成後解壓,閱讀README,在Building the Software:中得知編譯方法:如果使用交叉編譯的話要執行以下命令:
CROSS_COMPILE=arm-linux-
export CROSS_COMPILE
然後執行make NAME_defconfig,進行預設的配置。NAME為支持的開發板的名稱,最後make all 即可。這裡預設配置中和JZ2440最接近的是三星的smdk2410開發板。因此,我這裡執行make smdk2410_defconfig,然後make all。編譯成功,用JLINK燒寫到norflash中,上電啟動,發現串口無任何輸出,看來smdk2410的配置不能直接用到JZ2440開發板,需要修改代碼。可以新建一個單板目錄,但新版u-boot需要改動的地方很多,較麻煩,因此我就直接在smdk2410的代碼上改了。首先分析啟動過程,根據編譯生成的u-boot.lds發現第一個文件是arch/arm/cpu/arm920t/start.S。於是從這裡開始分析。分析到lowlevel_init函數時,發現對SDRAM進行設置時,SMRDATA中的REFCNT依賴於HCLK=60MHz,而在這之前只設置了時鐘比例,具體時鐘大小還未設置,所以估計這裡有問題。如果有openjtag可以用openjtag對SDRAM進行讀寫,就會發現讀寫有問題。於是修改代碼:在board/samsung/smdk2410/smdk2410.c的board_early_init_f中將時鐘的設置函數註釋掉,
int board_early_init_f(void)
{
struct s3c24x0_clock_power * const clk_power =
s3c24x0_get_base_clock_power();
struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
/* to reduce PLL lock time, adjust the LOCKTIME register */
//writel(0xFFFFFF, &clk_power->locktime);
/* configure MPLL */
//writel((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV, &clk_power->mpllcon);
/* some delay between MPLL and UPLL */
//pll_delay(4000)
/* configure UPLL */
//writel((U_M_MDIV << 12) + (U_M_PDIV << 4) + U_M_SDIV, &clk_power->upllcon);
/* some delay between MPLL and UPLL */
//pll_delay(8000);
在前面的start.S中自己設置時鐘:
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
/*clk config*/
#define S3C2440_MPLL_200MHZ ((0x5c<<12)|(0x01<<4)|(0x02))
ldr r0, =0x4c000004
ldr r1, =S3C2440_MPLL_200MHZ
str r1, [r0]
將board/samsung/smdk2410/lowlevel_init.S中的SRMDATA改為對應我們設置的時鐘的數值
SMRDATA:
.long 0x22011110 //BWSCON
.long 0x00000700 //BANKCON0
.long 0x00000700 //BANKCON1
.long 0x00000700 //BANKCON2
.long 0x00000700 //BANKCON3
.long 0x00000700 //BANKCON4
.long 0x00000700 //BANKCON5
.long 0x00018005 //BANKCON6
.long 0x00018005 //BANKCON7
.long 0x008C04F4 // REFRESH
.long 0x000000B1 //BANKSIZE
.long 0x00000030 //MRSRB6
.long 0x00000030 //MRSRB7
改完後編譯,串口有輸出了,但是亂碼,估計是波特率的問題。分析代碼,在board_init_r中,init_sequence_r函數數組中有一個initr_serial函數,一路追蹤下去,到serial_register(&s3c24xx_serial0_device),這個函數註冊了串口0,s3c24xx_serial0_device定義如下,
DECLARE_S3C_SERIAL_FUNCTIONS(0);
struct serial_device s3c24xx_serial0_device =
INIT_S3C_SERIAL_STRUCTURE(0, "s3ser0");
INIT_S3C_SERIAL_STRUCTURE定義如下:
#define INIT_S3C_SERIAL_STRUCTURE(port, __name) { \
.name = __name, \
.start = s3serial##port##_init, \
.stop = NULL, \
.setbrg = s3serial##port##_setbrg, \
.getc = s3serial##port##_getc, \
.tstc = s3serial##port##_tstc, \
.putc = s3serial##port##_putc, \
.puts = s3serial##port##_puts, \
}
我們看看波特率設置函數.setbrg = s3serial##port##_setbrg的定義,
#define DECLARE_S3C_SERIAL_FUNCTIONS(port) \
int s3serial##port##_init(void) \
{ \
return serial_init_dev(port); \
} \
void s3serial##port##_setbrg(void) \
{ \
serial_setbrg_dev(port); \
} \
一路跟蹤進_serial_setbrg函數,get_PCLK,get_HCLK(),發現get_HCLK()中支持2440,但要要定義CONFIG_S3C2440,於是,我們在include/configs/smdk2410.h中定義這個巨集,編譯出現錯誤,./arch/arm/include/asm/arch/s3c24x0.h:443: error: duplicate member 'gpacon' ,打開s3c24x0.h:443,發現由於定義了CONFIG_S3C2440,導致寄存器重覆定義了,刪去2410那一段即可,編譯後,燒寫程式,串口成功列印。