cortex A8處理器啟動過程二引導程式碼BL1
阿新 • • 發佈:2019-01-31
BL1相當於u-boot的第一階段程式碼,主要完成如下工作:1.初始化硬體:關看門狗、設定串列埠、SDRAM、初始化Flash;2.重定位,將程式碼重定位到SDRAM;3.引導u-boot第二階段程式碼。其實如果它能引導核心,就相當於一個bootlaoder,這裡先實現上面3個功能。程式碼有點多,我還是貼出來吧,懶得看,需要編譯好的原始碼包留個郵箱我發你。
系統:ubuntu 10.04.4
單板:s5pc100(CES-C100)
編譯器:arm-linux-gcc-4.3.2
搭建開發環境詳見ubuntu 10.04.4開發環境配置。
一、編寫程式碼
檔案start.S:
- .global
- _start:
- /*1. Disable Watchdog */
- /*1.關看門狗*/
- ldr r0, =0xEA200000
- mov r1, #0
- str r1, [r0]
- bl clock_init
- //bl test
- bl mp1_x_drive_strength_init
- bl mem_ctrl_asm_init
- ldr sp, =0xD0038000
- bl init_uart
- bl nand_init
- //bl test
- ldr r0, =0x0
- ldr r1, =0x21000000
- ldr r2, =bss_start
- sub r2, r2, r1
- bl copy_code_to_sdram
- //bl test
- //b main
- clean_bss:
- ldr r0, =bss_start
- ldr r1, =bss_end
- mov r3, #0
- cmp r0, r1
- ldreq pc, =on_ddr
- clean_loop:
- str r3, [r0], #4
- cmp r0, r1
- bne clean_loop
- ldr pc, =on_ddr
- on_ddr:
- ldr sp, =0x21800000 /* ÖØгõÊŒ»¯Õ»£¬ÖžÏòÄÚŽæ */
- //bl test
- ldr pc, =main
檔案clock.S
- .globl clock_init
- clock_init:
- /* 1.設定LOCK_TIME */
- ldr r0, =0xe0100000 //CLOCK_POWER_BASE
- mov r1, #0xe00
- orr r1, r1, #0x10
- str r1, [r0, #0x0] /* APLL_LOCK */
- str r1, [r0, #0x4] /* MPLL_LOCK */
- str r1, [r0, #0x8] /* EPLL_LOCK */
- str r1, [r0, #0x0c] //HPLL_LOCK
- //#define OTHERS 0x7e00f900
- // @ set async mode /* 當CPU時鐘 != HCLK時,要設為非同步模式 */
- // ldr r0, =OTHERS
- // ldr r1, [r0]
- // bic r1, r1, #0xc0 /* 1100,0000 */
- // str r1, [r0]
- //loop1: /* 等待,直到CPU進入非同步模式 */
- // ldr r0, =OTHERS
- // ldr r1, [r0]
- // and r1, r1, #0xf00
- // cmp r1, #0
- // bne loop1
- /* SYNC667 */
- /* MISC_CON[19] = 0 */
- //#define ARM_RATIO 0 /* ARMCLK = DOUTAPLL / (ARM_RATIO + 1) */
- //#define HCLKX2_RATIO 1 /* HCLKX2 = HCLKX2IN / (HCLKX2_RATIO + 1) */
- //#define HCLK_RATIO 1 /* HCLK = HCLKX2 / (HCLK_RATIO + 1) */
- //#define PCLK_RATIO 3 /* PCLK = HCLKX2 / (PCLK_RATIO + 1) */
- //#define MPLL_RATIO 0 /* DOUTMPLL = MOUTMPLL / (MPLL_RATIO + 1) */
- // ldr r0, =0x7E00F020 /* CLK_DIV0 */
- // ldr r1, =(ARM_RATIO) | (MPLL_RATIO << 4) | (HCLK_RATIO << 8) | (HCLKX2_RATIO << 9) | (PCLK_//RATIO << 12)
- // str r1, [r0]
- /* CLK_DIV0 */
- #define APLL_RATIO 0
- #define ARM_RATIO 4
- #define D0_BUS_RATIO 8
- #define PCLKD0_RATIO 12
- #define SECSS_RATIO 16
- ldr r1, [r0, #0x300] //CLK_DIV0 Clock divider
- ldr r2, =0x3fff
- bic r1, r1, r2
- ldr r2, =(1<<APLL_RATIO) | (0<<ARM_RATIO) | (4<<D0_BUS_RATIO) | (1<<PCLKD0_RATIO) | (1<<SECSS_RATIO)
- orr r1, r1, r2
- str r1, [r0, #0x300] //CLK_DIV0
- ldr r2, =((1<<16) | (1<<12) | (1<<8) | (1<<4))
- orr r1 ,r1, r2
- str r1, [r0, #0x304] //CLD_DIV1
- /* 2.配置時鐘 */
- /* 2.1 配置APLL */
- /* 2.1.1 設定APLL
- * 2.1.2 MUXAPLL
- * 2.1.3 SYNC667
- * 2.1.4 DIVAPLL
- */
- //#define APLL_CON_VAL ((1<<31) | (266 << 16) | (3 << 8) | (1))
- // ldr r0, =0x7E00F00C
- // ldr r1, =APLL_CON_VAL
- // str r1, [r0] /* APLL_CON, FOUTAPL = MDIV * Fin / (PDIV*2^SDIV) = 266*12/(3*2^1) = 532MHz */
- #define APLL_VAL ((1<<31) | (417 << 16) | (3 << 8) | (0))
- //ldr r0, =0xe0100100 //APLL_CON
- ldr r1, =APLL_VAL
- str r1, [r0, #0x100] /* MPLL_CON, FOUTMPL = MDIV * Fin / (PDIV*2^SDIV) = 266*12/(3*2^1) = 532MHz */
- /* 2.2 配置MPLL */
- /* 2.2.1 設定MPLL
- * 2.2.2 MUXMPLL
- * 2.2.3 SYNCMUX
- * 2.2.4 SYNC667
- * 2.2.5 HCLKX2_RATIO
- * 2.2.6 PCLK_RATIO
- */
- //#define MPLL_CON_VAL ((1<<31) | (266 << 16) | (3 << 8) | (1))
- //CONFIG_CLK_833_166_66
- #define MPLL_VAL ((1<<31) | (89 << 16) | (2 << 8) | (1))
- #define EPLL_VAL ((1<<31) | (135 << 16) | (3 << 8) | (3))
- #define HPLL_VAL ((1<<31) | (96 << 16) | (6 << 8) | (3))
- ldr r1, =MPLL_VAL
- str r1, [r0, #0x104]
- ldr r1, =EPLL_VAL
- str r1, [r0, #0x108]
- ldr r1, =HPLL_VAL
- str r1, [r0, #0x10c]
- /* 3.選擇PLL的輸出作為時鐘源 */
- ldr r1, [r0, #0x200] //CLK_SRC0 0xe0100200
- ldr r2, =0x1111
- orr r1, r1, r2
- str r1, [r0, #0x200] //FOUT: APLL MPLL EPLL HPLL
- mov r1, #0x10000
- 1: subs r1, r1, #1
- bne 1b
- mov pc, lr
檔案cpu_init.S
- //#include "s5pc100.h"
- /* Port Group MP1_X Drive Strength Control */
- #define MP1_0DRV_OFFSET 0x03CC
- #define MP1_1DRV_OFFSET 0x03EC
- #define MP1_2DRV_OFFSET 0x040C
- #define MP1_3DRV_OFFSET 0x042C
- #define MP1_4DRV_OFFSET 0x044C
- #define MP1_5DRV_OFFSET 0x046C
- #define MP1_6DRV_OFFSET 0x048C
- #define MP1_7DRV_OFFSET 0x04AC
- #define MP1_8DRV_OFFSET 0x04CC
- /*
- * Bus Matrix
- */
- #define ELFIN_MEM_SYS_CFG 0x7e00f120
- /*
- * Memory controller
- */
- #define ELFIN_SROM_BASE 0xE7000000
- #define SROM_BW_REG __REG(ELFIN_SROM_BASE+0x0)
- #define SROM_BC0_REG __REG(ELFIN_SROM_BASE+0x4)
- #define SROM_BC1_REG __REG(ELFIN_SROM_BASE+0x8)
- #define SROM_BC2_REG __REG(ELFIN_SROM_BASE+0xC)
- #define SROM_BC3_REG __REG(ELFIN_SROM_BASE+0x10)
- #define SROM_BC4_REG __REG(ELFIN_SROM_BASE+0x14)
- #define SROM_BC5_REG __REG(ELFIN_SROM_BASE+0x18)
- /*
- * SDRAM Controller
- */
- #define APB_DMC_BASE 0xE6000000
- #define DMC_CONCONTROL 0x00
- #define DMC_MEMCONTROL 0x04
- #define DMC_MEMCONFIG0 0x08
- #define DMC_MEMCONFIG1 0x0C
- #define DMC_DIRECTCMD 0x10
- #define DMC_PRECHCONFIG 0x14
- #define DMC_PHYCONTROL0 0x18
- #define DMC_PHYCONTROL1 0x1C
- #define DMC_PHYCONTROL2 0x20
- #define DMC_PWRDNCONFIG 0x28
- #define DMC_TIMINGAREF 0x30
- #define DMC_TIMINGROW 0x34
- #define DMC_TIMINGDATA 0x38
- #define DMC_TIMINGPOWER 0x3C
- #define DMC_PHYSTATUS0 0x40
- #define DMC_PHYSTATUS1 0x44
- #define DMC_CHIP0STATUS 0x48
- #define DMC_CHIP1STATUS 0x4C
- #define DMC_AREFSTATUS 0x50
- #define DMC_MRSTATUS 0x54
- #define DMC_PHYTEST0 0x58
- #define DMC_PHYTEST1 0x5C
- #define DMC_QOSCONTROL0 0x60
- #define DMC_QOSCONFIG0 0x64
- #define DMC_QOSCONTROL1 0x68
- #define DMC_QOSCONFIG1 0x6C
- #define DMC_QOSCONTROL2 0x70
- #define DMC_QOSCONFIG2 0x74
- #define DMC_DMC_QOSCONTROL3 0x78
- #define DMC_QOSCONFIG3 0x7C
- #define DMC_QOSCONTROL4 0x80
- #define DMC_QOSCONFIG4 0x84
- #define DMC_QOSCONTROL5 0x88
- #define DMC_QOSCONFIG5 0x8C
- #define DMC_QOSCONTROL6 0x90
- #define DMC_QOSCONFIG6 0x94
- #define DMC_QOSCONTROL7 0x98
- #define DMC_QOSCONFIG7 0x9C
- /*
- * Memory Chip direct command
- */
- #define PRO_ID_BASE 0xE0000000
- #define PRO_ID_OFFSET 0x00
- #define OMR_OFFSET 0x04
- /*
- * GPIO
- */
- #define ELFIN_GPIO_BASE 0xE0300000
- .globl mp1_x_drive_strength_init
- /*
- * Init MP1_X Driver Strength for SDRAM
- * void mp1_x_drive_strength_init(void)
- */
- mp1_x_drive_strength_init:
- ldr r0, =ELFIN_GPIO_BASE
- ldr r1, =0xaaaa
- str r1, [r0, #MP1_0DRV_OFFSET]
- str r1, [r0, #MP1_1DRV_OFFSET]
- str r1, [r0, #MP1_2DRV_OFFSET]
- str r1, [r0, #MP1_3DRV_OFFSET]
- str r1, [r0, #MP1_4DRV_OFFSET]
- str r1, [r0, #MP1_5DRV_OFFSET]
- str r1, [r0, #MP1_6DRV_OFFSET]
- str r1, [r0, #MP1_7DRV_OFFSET]
- str r1, [r0, #MP1_8DRV_OFFSET]
- mov pc, lr
- .globl mem_ctrl_asm_init
- mem_ctrl_asm_init:
- ldr r0, =APB_DMC_BASE @APB_DMC_BASE 0xE6000000
- ldr r1, =PRO_ID_BASE
- ldr r2, [r1, #PRO_ID_OFFSET]
- bic r2, #0xfffffdff
- mov r2, r2, lsr #9
- cmp r2, #0x1
- beq onenand_pop
- single:
- /************ delay loop *************/
- #if 0
- ldr r1, =0x10000000
- mov r2, #0
- loop1:
- cmp r2, r1
- addne r2, r2, #0x1
- bne loop1
- #endif
- /************ DLL initialization *************/
- ldr r1, =0x6A101000 @ Phycontrol0 DLL parameter setting
- str r1, [r0, #DMC_PHYCONTROL0]
- ldr r1, =0x000084F4 @Phycontrol1 DLL parameter setting
- str r1, [r0, #DMC_PHYCONTROL1]
- ldr r1, =0x00000000 @Phycontrol2 DLL parameter setting
- str r1, [r0, #DMC_PHYCONTROL2]
- ldr r1, =0x6A101002 @DLL on
- str r1, [r0, #DMC_PHYCONTROL0]
- ldr r1, =0x6A101003 @Dll start
- str r1, [r0, #DMC_PHYCONTROL0]
- ldr r2, = 0xE6000040 @DMC_PHYSTATUS0
- loop1:
- ldr r1, [r2] @Check DLL lock
- ands r1, r1, #4
- beq loop1
- ldr r1, [r2]
- mov r1, r1, LSR #(0x6)
- and r1, r1, #(0xff)
- mov r1, r1, LSL #(0x18)
- ldr r2, = 0xE6000018 @DMC_PHYCONTROL0
- ldr r3, [r2]
- bic r3, r3, #(0xff000000)
- orr r1, r3, r2
- str r1, [r2]
- ldr r1, =0x6A101003 @Force Value locking
- str r1, [r0, #DMC_PHYCONTROL0]
- ldr r1, =0x6A101009 @Dll off
- str r1, [r0, #DMC_PHYCONTROL0]
- #if 0
- ldr r1, =0x6A101000 @ Phycontrol0 DLL parameter setting
- str r1, [r0, #DMC_PHYCONTROL0]
- ldr r1, =0x00008484 @Phycontrol1 DLL parameter setting
- str r1, [r0, #DMC_PHYCONTROL1]
- ldr r1, =0x00000000 @Phycontrol2 DLL parameter setting
- str r1, [r0, #DMC_PHYCONTROL2]
- #endif
- /************ DLL initialization - END *************/
- ldr r1, =0x0FF01010 @auto refresh off
- str r1, [r0, #DMC_CONCONTROL]
- ldr r1, =0x00202400 @ BL=4 , 1 chip , DDR2
- str r1, [r0, #DMC_MEMCONTROL]
- #if 1 // add xxs 256MB enable
- ldr r1, =0x20F01323
- str r1, [r0, #DMC_MEMCONFIG0]
- ldr r1, =0x40F00323
- str r1, [r0, #DMC_MEMCONFIG1]
- #else // 128MB enable
- ldr r1, =0x20F81313
- str r1, [r0, #DMC_MEMCONFIG0]
- ldr r1, =0x40F80313
- str r1, [r0, #DMC_MEMCONFIG1]
- #endif
- ldr r1, =0x20000000
- str r1, [r0, #DMC_PRECHCONFIG]
- ldr r1, =0x00100004 @ PwrdnConfig
- str r1, [r0, #DMC_PWRDNCONFIG]
- #ifdef CONFIG_HCLKD0_222
- ldr r1, =0x000006c3 @7.8us*222MHz=0x6c3, 7.8us*166MHz=1294(0x50E)
- str r1, [r0, #DMC_TIMINGAREF]
- /* T-rfc 127.5nS/5ns 64 */
- ldr r1, =0x202332C8 @TimingRow @222MHz
- str r1, [r0, #DMC_TIMINGROW]
- ldr r1, =0x24450304 @CL=5
- str r1, [r0, #DMC_TIMINGDATA]
- #else
- ldr r1, =0x0000050E
- str r1, [r0, #DMC_TIMINGAREF]
- ldr r1, =0x16233297 @TimingRow @166MHz
- str r1, [r0, #DMC_TIMINGROW]
- @; ldr r1, =0x24250304 @CL=5
- ldr r1, =0x23230000 @CL=3
- str r1, [r0, #DMC_TIMINGDATA]
- #endif
- ldr r1, =0x07c80232 @ Timing Power
- str r1, [r0, #DMC_TIMINGPOWER]
- /* Direct Command for DDR2 */
- ldr r1, =0x07000000 @chip0 Deselect
- str r1, [r0, #DMC_DIRECTCMD]
- ldr r1, =0x01000000 @chip0 PALL
- str r1, [r0, #DMC_DIRECTCMD]
- ldr r1, =0x00020000 @chip0 EMRS2
- str r1, [r0, #DMC_DIRECTCMD]
- ldr r1, =0x00030000 @chip0 EMRS3
- str r1, [r0, #DMC_DIRECTCMD]
- ldr r1, =0x00010400 @chip0 EMRS1 (MEM DLL on = DQS# disable)
- str r1, [r0, #DMC_DIRECTCMD]
- @; ldr r1, =0x00000552 @chip0 MRS (MEM DLL reset) CL=5, Burst Length=4
- ldr r1, =0x00000532 @chip0 MRS (MEM DLL reset) CL=3, Burst Length=4
- str r1, [r0, #DMC_DIRECTCMD]
- ldr r1, =0x01000000 @chip0 PALL
- str r1, [r0, #DMC_DIRECTCMD]
- ldr r1, =0x05000000 @chip0 REFA
- str r1, [r0, #DMC_DIRECTCMD]
- ldr r1, =0x05000000 @chip0 REFA
- str r1, [r0, #DMC_DIRECTCMD]
- @; ldr r1, =0x00000452 @chip0 MRS (MEM DLL unreset) , BL=4 , CL=5
- ldr r1, =0x00000432 @chip0 MRS (MEM DLL unreset) , BL=4 , CL=3
- str r1, [r0, #DMC_DIRECTCMD]
- ldr r1, =0x00010780 @chip0 EMRS1 (OCD default)
- str r1, [r0, #DMC_DIRECTCMD]
- // ldr r1, =0x00010400 @chip0 EMRS1 (OCD exit)
- ldr r1, =0x00010402 @chip0 EMRS1 (OCD exit) Reduced Strength
- // ldr r1, =0x00010000 @chip0 EMRS1 (OCD exit) ODT Disabled
- str r1, [r0, #DMC_DIRECTCMD]
- /* Direct Command for LPDDR - END */
- ldr r1, =0x00FF20B0 @ConControl auto refresh on
- str r1, [r0, #DMC_CONCONTROL]
- #if 0
- ldr r1, =0x001000FF @ PwrdnConfig
- str r1, [r0, #DMC_PWRDNCONFIG]
- #endif
- ldr r1, =0x00212413 @ MemControl
- str r1, [r0, #DMC_MEMCONTROL]
- b exit_cpu_init
- onenand_pop:
- ldr r1, =0x50101000 @Phycontrol0 DLL parameter setting
- str r1, [r0, #DMC_PHYCONTROL0]
- ldr r1, =0x000000F4 @Phycontrol1 DLL parameter setting
- str r1, [r0, #DMC_PHYCONTROL1]
- ldr r1, =0x00000000 @Phycontrol2 DLL parameter setting
- str r1, [r0, #DMC_PHYCONTROL2]
- ldr r1, =0x50101002 @Dll on
- str r1, [r0, #DMC_PHYCONTROL0]
- ldr r1, =0x50101003 @dll start
- str r1, [r0, #DMC_PHYCONTROL0]
- ldr r1, =0x50101003 @Force Value locking
- str r1, [r0, #DMC_PHYCONTROL0]
- ldr r1, =0x50101001 @Dll off
- str r1, [r0, #DMC_PHYCONTROL0]
- ldr r1, =0xFF001010 @auto refresh off
- str r1, [r0, #DMC_CONCONTROL]
- ldr r1, =0x00212100 @Dll off
- str r1, [r0, #DMC_MEMCONTROL]
- @; ldr r1, =0x28F80222
- ldr r1, =0x28F00222
- str r1, [r0, #DMC_MEMCONFIG0]
- ldr r1, =0x20F80222
- str r1, [r0, #DMC_MEMCONFIG1]
- ldr r1, =0x20000000
- str r1, [r0, #DMC_PRECHCONFIG]
- ldr r1, =0x0000050E
- str r1, [r0, #DMC_TIMINGAREF]
- ldr r1, =0x0C233287 @TimingRow @133MHz
- str r1, [r0, #DMC_TIMINGROW]
- ldr r1, =0x32330303
- str r1, [r0, #DMC_TIMINGDATA]
- ldr r1, =0x04141433 @Timing Power
- str r1, [r0, #DMC_TIMINGPOWER]
- ldr r1, =0x07000000 @chip0 Deselect
- str r1, [r0, #DMC_DIRECTCMD]
- ldr r1, =0x01000000 @chip0 PALL
- str r1, [r0, #DMC_DIRECTCMD]
- ldr r1, =0x05000000 @chip0 REFA
- str r1, [r0, #DMC_DIRECTCMD]
- ldr r1, =0x05000000 @chip0 REFA
- str r1, [r0, #DMC_DIRECTCMD]
- ldr r1, =0x00000032 @chip0 MRS
- str r1, [r0, #DMC_DIRECTCMD]
- ldr r1, =0x07100000 @chip1 Deselect
- str r1, [r0, #DMC_DIRECTCMD]
- ldr r1, =0x01100000 @chip1 PALL
- str r1, [r0, #DMC_DIRECTCMD]
- ldr r1, =0x05100000 @chip1 REFA
- str r1, [r0, #DMC_DIRECTCMD]
- ldr r1, =0x05100000 @chip1 REFA
- str r1, [r0, #DMC_DIRECTCMD]
- ldr r1, =0x00100032 @chip1 MRS
- str r1, [r0, #DMC_DIRECTCMD]
- ldr r1, =0xFF002030 @ConControl auto refresh on
- str r1, [r0, #DMC_CONCONTROL]
- ldr r1, =0x00100002 @PwrdnConfig
- str r1, [r0, #DMC_PWRDNCONFIG]
- @; ldr r1, =0xFF212113 @MemControl
- ldr r1, =0xFF212100 @MemControl
- str r1, [r0, #DMC_MEMCONTROL]
- b exit_cpu_init
- exit_cpu_init:
- mov pc, lr
檔案uart.c:
- #define ULCON0 (*((volatile unsigned long *)0xEC000000))
- #define UCON0 (*((volatile unsigned long *)0xEC000004))
- #define UFCON0 (*((volatile unsigned long *)0xEC000008))
- #define UMCON0 (*((volatile unsigned long *)0xEC00000C))
- #define UTRSTAT0 (*((volatile unsigned long *)0xEC000010))
- #define UFSTAT0 (*((volatile unsigned long *)0xEC000018))
- #define UTXH0 (*((volatile unsigned char *)0xEC000020))
- #define URXH0 (*((volatile unsigned char *)0xEC000024))
- #define UBRDIV0 (*((volatile unsigned long *)0xEC000028))
- #define UDIVSLOT0 (*((volatile unsigned long *)0xEC00002C))
- #define GPACON (*((volatile unsigned long *)0xE0300000))
- #define ENABLE_FIFO
- void init_uart(void)
- {
- GPACON &= ~0xffff;
- GPACON |= 0x2222;
- /* ULCON0 */
- ULCON0 = 0x3; /* 資料位:8, 無較驗, 停止位: 1, 8n1 */
- UCON0 = 0x5; /* 使能UART傳送、接收 */
- #ifdef ENABLE_FIFO
- UFCON0 = 0x07; /* FIFO enable */
- #else
- UFCON0 = 0x00; /* FIFO disable */
- #endif
- UMCON0 = 0;
- /* 波特率 */
- /* DIV_VAL = (PCLK / (bps x 16 ) ) - 1
- * bps = 115200
- * DIV_VAL = (66500000 / (115200 x 16 ) ) - 1
- * = 35.08
- */
- UBRDIV0 = 35;
- /* x/16 = 0.08
- * x = 1
- */
- UDIVSLOT0 = 3;
- UTXH0 = 0x4f4f4f4f;
- }
- #define ENABLE_FIFO
- static void delay1(void)
- {
- volatile int i = 10;
- while (i--);
- }
- unsigned char getc(void)
- {
- #ifdef ENABLE_FIFO
- while ((UFSTAT0 & (1<<6)) == 0 && (UFSTAT0 & 0x3f) == 0)delay1();
- #else
- while ((UTRSTAT0 & (1<<0)) == 0);
- #endif
- return URXH0;
- }
- int getc_nowait(unsigned char *pChar)
- {
- #ifdef ENABLE_FIFO
- if ((UFSTAT0 & (1<<6)) == 0 && (UFSTAT0 & 0x3f) == 0)
- #else
- if ((UTRSTAT0 & (1<<0)) == 0)
- #endif
- {
- return -1;
- }
- else
- {
- *pChar = URXH0;
- return 0;
- }
- }
- void putc(char c)
- {
- #ifdef ENABLE_FIFO
- if(c == '\r')
- {
- while (UFSTAT0 & (1<<14))delay1();
- UTXH0 = '\n';
- }
- if(c == '\n')
- {
- while (UFSTAT0 & (1<<14))delay1();
- UTXH0 = '\r';
- }
- //while(!(UTRSTAT0&(1<<1)));
- while (UFSTAT0 & (1<<14))delay1();
- #else
- while ((UTRSTAT0 & (1<<2)) == 0);
- #endif
- UTXH0 = c;
- }
檔案uart.h:
- void init_uart(void);
- unsigned char getc(void);
- int getc_nowait(unsigned char *pChar);
- void putc(char c);
檔案command.c:
- #include "lib.h"
- #include "nand.h"
- #include "setup.h"
- int help(int argc, char * argv[])
- {
- printf("do_command <%s> \n", argv[0]);
- printf("help message: \n");
- printf("md - memory dispaly \n");
- printf("mw - memory write \n");
- printf("nand read - nand read sdram_addr nand_addr size\n");
- printf("nand write - nand write sdram_addr nand_addr size\n");
- printf("bootm - boot zImage\n");
- return 0;
- }
- int md(int argc, char * argv[])
- {
- unsigned long *p = (unsigned long *)0;
- int i, j;
- printf("do_command <%s> \n", argv[0]);
- if (argc <= 1) {
- printf ("Usage:\n%s\n", "md address");
- return 1;
- }
- if (argc >= 2)
- p = (unsigned long *)atoi(argv[1]);
- for (j = 0; j < 16; j++)
- {
- printf("%x: ", p);
- for (i = 0; i < 4; i++)
- printf("%x ", *p++);
- puts("\n");
- }
- return 0;
- }
- int mw(int argc, char * argv[])
- {
- unsigned long *p = (unsigned long *)0;
- int v = 0;
- printf("do_command <%s> \n", argv[0]);
- if (argc <= 2) {
- printf ("Usage:\n%s\n", "md address data");
- return 1;
- }
- if (argc >= 2)
- p = (unsigned long *)atoi(argv[1]);
- if (argc >= 3)
- v = atoi(argv[2]);
- *p = v;
- printf("do_command mw finished!\n");
- return 0;
- }
- int nand(int argc, char *argv[])
- {
- unsigned int nand_addr, sdram_addr;
- unsigned int size;
- char *cmd;
- if (argc < 5)
- {
- printf("nand read nand_addr sdram_addr size\n");
- printf("nand write nand_addr sdram_addr size\n");
- return 0;
- }
- nand_addr = atoi(argv[2]);
- sdram_addr = atoi(argv[3]);
- size = atoi(argv[4]);
- //cmd = argv[1];
- //putc(*cmd);
- //printf("*cmd = %x\n", *cmd);
- //printf("do_command <%s> \n", argv[0]);
- //printf("nand <%s> \n", argv[1]);
- puts("\n");
- printf("nand_addr = %x, sdram_addr = %x, size = %x\n", nand_addr, sdram_addr, size);
- if (strcmp(argv[1], "read") == 0)
- {
- nand_read_dis(nand_addr, sdram_addr, size);
- printf("nand <%s> \n", argv[1]);
- }
- if (strcmp(cmd, "write") == 0)
- nand_write_dat(nand_addr, (unsigned char *)sdram_addr, size);
- printf("nand %s finished!\n", argv[1]);
- return 0;
- }
- //const char cmd[] = "root=/dev/nfs nfsroot=192.168.1.104:/work/nfs_root/wy_fs ip=192.168.1.17 cons//ole=ttySAC0";
- const char cmd[] = "root=/dev/mtdblock2 rw rootfstype=yaffs2 mem=256m init=/init console=ttySAC0,115200 androidboot.console=s3c2410_serial0";
- void init_tag(int addr)
- {
- struct tag * p;
- int i;
- p = (struct tag*) addr;
- p->hdr.tag = ATAG_CORE;
- p->hdr.size = tag_size(tag_core);
- p->u.core.flags = 0;//1;
- p->u.core.pagesize = 0;//4096;
- p->u.core.rootdev = 0x00000000;
- p = tag_next(p);
- p->hdr.tag = ATAG_CMDLINE;
- p->hdr.size = (sizeof (cmd) + sizeof(struct tag_header) + 3) >>2;
- for(i=0; i< sizeof (cmd); i++)
- p->u.cmdline.cmdline[i] = cmd[i];
- p = tag_next(p);
- p->hdr.tag = ATAG_MEM;
- p->hdr.size = tag_size(tag_mem32);
- p->u.mem.start = 0x20000000;
- p->u.mem.size = 256*1024*1024;
- p = tag_next(p);
- p->hdr.tag = ATAG_NONE;
- p->hdr.size = 0;
- }
- int bootm(int argc, char * argv[])
- {
- int addr = 0x20008000;
- void (*fp)(int, int, int);
- int taglist_mem_address = 0x20000100;
- printf("loading linux from 0x100000 to 0x20008000...\n");
- nand_read(0x100000, 0x20008000, 0x200000);
- fp = (void (*)(int, int, int))addr;
- init_tag(taglist_mem_address);
- printf("boot linux ...\n");
- fp(0, 1826, taglist_mem_address);
- printf("boot linux error!\n");
- return 0;
- }
- void run_command(int argc, char * argv[])
- {
- switch(argc){
- case 0:
- case 1:
- if (strcmp(argv[0], "help") == 0)
- {
- help(argc, argv);
- return;
- }
- else if (strcmp(argv[0], "bootm") == 0)
- {
- bootm(argc, argv);
- return;
- }
- else //(argc >= 1)
- printf("Unknown command '%s' - try 'help' \n",argv[0]);
- case 2:
- if (strcmp(argv[0], "md") == 0)
- {
- md(argc, argv);
- return;
- }
- else if (strcmp(argv[0], "mw") == 0)
- {
- mw(argc, argv);
- return;
- }
- else //(argc >= 1)
- printf("Unknown command '%s' - try 'help' \n",argv[0]);
- default:
- /* if (strcmp(argv[1], "read") == 0)
- {
- nand(argc, argv);
- return;
- }
- else if (strcmp(argv[1], "write") == 0)
- {
- nand(argc, argv);
- return;
- }
- */
- if (argc == 5)
- {
- nand(argc, argv);
- return;
- }
- else //(argc >= 1)
- printf("Unknown command '%s' - try 'help' \n",argv[0]);
- return;
- }
- }
- 檔案command.h:
void run_command(int argc, char * argv[]);
檔案lib.c:
- #include "uart.h"
- int getchar(void)
- {
- int c;
- c = (int)getc();
- if (c == '\r')
- return '\n';
- return c;
- }
- void puts(char *str)
- {
- int i = 0;
- while (str[i])
- {
- putc(str[i]);
- i++;
- }
- }
- char * gets(char * s)
- {
- char * p = s;
- while ((*p = getchar()) != '\n')
- {
- if (*p != '\b')
- putc(*p++);
- else
- if (p > s)
- {
- puts ("\b \b");
- p--;
- }
- }
- *p = '\0';
- putc('\n');
- return s;
- }
- void test()
- {
- puts("init: OK\n\r");
- }
- void puthex(unsigned int val)
- {
- // 0x1234abcd
- int i;
- int j;
- puts("0x");
- for (i = 0; i < 8; i++)
- {
- j = (val >> ((7-i)*4)) & 0xf;
- if ((j >= 0) && (j <= 9))
- putc('0' + j);
- else
- putc('A' + j - 0xa);
- }
- }
- void putbyte(unsigned char val)
- {
- /* 0x1234abcd */
- int i;
- int j;
- puts("0x");
- for (i = 0; i < 2; i++)
- {
- j = (val >> ((1-i)*4)) & 0xf;
- if ((j >= 0) && (j <= 9))
- putc('0' + j);
- else
- putc('A' + j - 0xa);
- }
- }
- char * itoa(int a, char * buf)
- {
- int num = a;
- int i = 0;
- int len = 0;
- do
- {
- buf[i++] = num % 10 + '0';
- num /= 10;
- } while (num);
- buf[i] = '\0';
- len = i;
- for (i = 0; i < len/2; i++)
- {
- char tmp;
- tmp = buf[i];
- buf[i] = buf[len-i-1];
- buf[len-i-1] = tmp;
- }
- return buf;
- }
- int strlen(char *str)
- {
- int i = 0;
- while (str[i])
- {
- i++;
- }
- return i;
- }
- int strcmp(const char * s1, const char * s2)
- {
- while (*s1 == *s2)
- {
- //putc(*s1);
- if (*s1 == '\0')
- {
- //s1 -= strlen(s2);
- return 0;
- }
- //putc(*s2);
- s1++;
- s2++;
- }
- //putc(*s1);
- //putc(*s2);
- return *s1 - *s2;
- }
- /*int strcmp(const char * cs,const char * ct)
- {
- register signed char __res;
- while (1) {
- if ((__res = *cs - *ct++) != 0 || !*cs++)
- break;
- }
- return __res;
- }*/
- int atoi(char * buf)
- {
- int value = 0;
- int base = 10;
- int i = 0;
- if (buf[0] == '0' && buf[1] == 'x')
- {
- base = 16;
- i = 2;
- }
- // 123 = (1 * 10 + 2) * 10 + 3
- // 0x1F = 1 * 16 + F(15)
- while (buf[i])
- {
- int tmp;
- if (buf[i] <= '9' && buf[i] >= '0')
- tmp = buf[i] - '0';
- else
- tmp = buf[i] - 'a' + 10;
- value = value * base + tmp;
- i++;
- }
- return value;
- }
- typedef int * va_list;
- #define va_start(ap, A)(ap = (int *)&(A) + 1)
- #define va_arg(ap, T)(*(T *)ap++)
- #define va_end(ap)((void)0)
- int printf(const char * format, ...)
- {
- char c;
- va_list ap;
- va_start(ap, format);
- while ((c = *format++) != '\0')
- {
- switch (c)
- {
- case '%':
- c = *format++;
- switch (c)
- {
- char ch;
- char * p;
- int a;
- char buf[100];
- case 'c':
- ch = va_arg(ap, int);
- putc(ch);
- break;
- case 's':
- p = va_arg(ap, char *);
- puts(p);
- break;
- case 'x':
- a = va_arg(ap, int);
- puthex(a);
- break;
- case 'd':
- a = va_arg(ap, int);
- itoa(a, buf);
- puts(buf);
- break;
- default:
- break;
- }
- break;
- default:
- putc(c);
- break;
- }
- }
- return 0;
- }
- void delay(void)
- {
- volatile int i = 0x200000;
- while (i--);
- }
檔案lib.h
- void delay(void);
- void puts(char *str);
- //int puts(const char * s);
- void test();
- void puthex(unsigned int val);
- int getchar(void);
- char * gets(char * s);
- //void puthex(int a);
- void putbyte(unsigned char val);
- char * itoa(int a, char * buf);
- int strlen(char *str);
- int strcmp(const char * s1, const char * s2);
- int atoi(char * buf);
- int printf(const char * format, ...);
檔案nand.c:
- //#define MEM_SYS_CFG (*((volatile unsigned long *)0x7E00F120))
- #define NFCONF (*((volatile unsigned long *)0xE7200000))
- #define NFCONT (*((volatile unsigned long *)0xE7200004))
- #define NFCMMD (*((volatile unsigned long *)0xE7200008))
- #define NFADDR (*((volatile unsigned long *)0xE720000C))
- #define NFDATA (*((volatile unsigned char *)0xE7200010))
- #define NFSTAT (*((volatile unsigned long *)0xE7200028))
- void nand_read(unsigned int nand_start, unsigned int ddr_start, unsigned int len);
- void copy_code_to_sdram(unsigned int src, unsigned int dest, unsigned int len)
- {
- //int i = 0;
- /*如果是Nor啟動*/ <