vivi的第一阶段
完成含依赖于CPU的体系结构硬件初始化的代码,包括禁止中断、初始化串口、复制自身到RAM等。相关代码集中在head.S(\vivi\arch\s3c2410目录下):
Head.S:
#include "config.h"
#include "linkage.h"
#include "machine.h"
@ Start of executable code
ENTRY(_start)
ENTRY(ResetEntryPoint)
@
@ Exception vector table (physical address = 0x00000000) ;异常向量表物理地址
@
@0x00: Reset ;复位
b Reset
@ 0x04: Undefined instruction exception ;未定义的指令异常
UndefEntryPoint:
b HandleUndef
@0x08: Software interrupt exception ;软件中断异常
SWIEntryPoint: b HandleSWI
@ 0x0c: Prefetch Abort (Instruction Fetch Memory Abort) ;内存操作异常
PrefetchAbortEnteryPoint: b HandlePrefetchAbort
@ 0x10: Data Access Memory Abort ;数据异常
DataAbortEntryPoint: b HandleDataAbort
@0x14: Not used ;未使用
NotUsedEntryPoint: b HandleNotUsed
@ 0x18: IRQ(Interrupt Request) exception ;慢速中断处理
IRQEntryPoint: b HandleIRQ
@ 0x1c: FIQ(Fast Interrupt Request) exception ;快速中断处理
FIQEntryPoint: b HandleFIQ
@
@ VIVI magics
@
@ 0x20: magic number so we can verify that we only put
.long 0
@ 0x24:
.long 0
@ 0x28: where this vivi was linked, so we can put it in memory in the right place
.long _start
@ 0x2C: this contains the platform, cpu and machine id
.long ARCHITECTURE_MAGIC
@ 0x30: vivi capabilities
.long 0
#ifdef CONFIG_PM ;vivi考虑不需要使用电源管理
@ 0x34:
b SleepRamProc
#endif
#ifdef CONFIG_TEST
@ 0x38:
b hmi
#endif
@
@ Start VIVI head
@
Reset:
@ disable watch dog timer ;禁止看门狗计时器
mov r1, #0x53000000 ;WTCON寄存器地址是0x53000000,清0
mov r2, #0x0
str r2, [r1]
#ifdef CONFIG_S3C2410_MPORT3 ;不符合条件,跳到下面的关中断
/**** 在/vivi/include/autoconf.h中#undef CONFIG_S3C2410_MPORT3******/
mov r1, #0x56000000 ;GPACON寄存器地址是0x56000000
mov r2, #0x00000005 str r2, [r1, #0x70] ;配置GPHCON寄存器
mov r2, #0x00000001 str r2, [r1, #0x78] ;配置GPHUP寄存器
mov r2, #0x00000001 str r2, [r1, #0x74] ;配置GPHDAT寄存器
#endif
@ disable all interrupts ;禁止全部中断
mov r1, #INT_CTL_BASE
mov r2, #0xffffffff str r2, [r1, #oINTMSK] ;掩码关闭所有中断
ldr r2, =0x7ff
str r2, [r1, #oINTSUBMSK]
@ initialise system clocks ;初始化系统时钟
mvn r2, #0xff000000
str r2, [r1, #oLOCKTIME]
@ldr r2, mpll_50mhz
@str r2, [r1, #oMPLLCON]
#ifndef CONFIG_S3C2410_MPORT1 ;满足条件,向下执行
/**** 在/vivi/include/autoconf.h中#undef CONFIG_S3C2410_MPORT1******/
@ 1:2:4
mov r1, #CLK_CTL_BASE
mov r2, #0x3
str r2, [r1, #oCLKDIVN]
mrc p15, 0, r1, c1, c0, 0 @ read ctrl register
orr r1, r1, #0xc0000000 @ Asynchronous
mcr p15, 0, r1, c1, c0, 0 @ write ctrl register
@ now, CPU clock is 200 Mhz ;CPU的频率是200MHz
mov r1, #CLK_CTL_BASE
ldr r2, mpll_200mhz
str r2, [r1, #oMPLLCON]
#else
@ 1:2:2
mov r1, #CLK_CTL_BASE
ldr r2, clock_clkdivn
str r2, [r1, #oCLKDIVN]
orr r1, r1, #0xc0000000 @ Asynchronous
mcr p15, 0, r1, c1, c0, 0 @ write ctrl register
@ now, CPU clock is 100 Mhz ;CPU的频率是100MHz
mov r1, #CLK_CTL_BASE
ldr r2, mpll_100mhz
str r2, [r1, #oMPLLCON]
#endif
bl memsetup ;跳转到memsetup函数
/*****************************
Memsetup函数的实现:
ENTRY(memsetup)
@ initialise the static memory
@ set memory control registers ;设置内存控制寄存器的初值
mov r1, #MEM_CTL_BASE
adrl r2, mem_cfg_val
/*******************
@
@ Data Area
@
@ Memory configuration values
.align 4
mem_cfg_val: ;定义好的13*4=52个字节初值
.long vBWSCON ;在/vivi/include/platform/smdk2410.h中赋值
/****** SDRAM从32位变成16位,需要修改vBWSCON的值 ******/
.long vBANKCON0
.long vBANKCON1
.long vBANKCON2
.long vBANKCON3
/********** 网卡控制器vBANKCON3的值可能需要修改 **************/
.long vBANKCON4
.long vBANKCON5
.long vBANKCON6
/****** SDRAM从32位变成16位,可能需要修改vBANKCON6的值 ******/
.long vBANKCON7
.long vREFRESH
.long vBANKSIZE
/****** SDRAM从64MB变成32MB,需要修改vBANKSIZE的值 ******/
.long vMRSRB6
.long vMRSRB7
********************/
add r3, r1, #52
1: ldr r4, [r2], #4
str r4, [r1], #4
cmp r1, r3
bne 1b ;循环操作,直到13个寄存器赋值完成
mov pc, lr
*******************************/
#ifdef CONFIG_PM ;vivi考虑不需要使用电源管理
@ Check if this is a wake-up from sleep
ldr r1, PMST_ADDR
ldr r0, [r1]
tst r0, #(PMST_SMR)
bne WakeupStart ;查看状态,判断是否需要跳转到WakeupStart
#endif
#ifdef CONFIG_S3C2410_SMDK ;SMDK开发板使用
@ All LED on ;点亮开发板上的LED
mov r1, #GPIO_CTL_BASE
add r1, r1, #oGPIO_F ;LED使用GPIOF组的管脚
ldr r2,=0x55aa ;使能EINT0,EINT1,EINT2,EINT3,
;另四个管脚配置成输出,屏蔽EINT4,5,6,7
str r2, [r1, #oGPIO_CON]
mov r2, #0xff
str r2, [r1, #oGPIO_UP] ;disable the pull-up function
mov r2, #0x00
str r2, [r1, #oGPIO_DAT]
#endif
#if 0
@ SVC
mrs r0, cpsr
bic r0, r0, #0xdf
orr r1, r0, #0xd3
msr cpsr_all, r1
#endif
@ set GPIO for UART ;设置串口
mov r1, #GPIO_CTL_BASE
add r1, r1, #oGPIO_H ;设置GPIO_H组管脚为串口
ldr r2, gpio_con_uart
str r2, [r1, #oGPIO_CON]
ldr r2, gpio_up_uart
str r2, [r1, #oGPIO_UP]
/*************************
@ inital values for GPIO
gpio_con_uart:
.long vGPHCON ;vGPHCON在/vivi/include/platform/smdk2410.h中赋值
;#define vGPHCON 0x0016faaa
;GPIO_H配置为nCTS0,nRTS0, RXD0,TXD0, RXD1,
;TXD1,nCTS1,nRTS1,
/**** 三个串口都使能,可能需要修改#define vGPHCON 0x0016aaaa ****/
gpio_up_uart:
.long Vgphup ;同上#define vGPHUP 0x000007ff
;The pull-up function is disabled.
************************/
bl InitUART ;跳转到InitUART串口初始化函数
/****************************************************
@ Initialize UART
@
@ r0 = number of UART port
InitUART:
ldr r1, SerBase
/*******************
.align 4 ;缺省情况下在vivi中只初始化了UART0
SerBase:
#if defined(CONFIG_SERIAL_UART0)
.long UART0_CTL_BASE ;基地址在/vivi/include/s3c2410.h中定义
#elif defined(CONFIG_SERIAL_UART1)
.long UART1_CTL_BASE
#elif defined(CONFIG_SERIAL_UART2)
.long UART2_CTL_BASE
#else
#error not defined base address of serial
#endif
********************/
mov r2, #0x0
str r2, [r1, #oUFCON]
str r2, [r1, #oUMCON]
mov r2, #0x3
str r2, [r1, #oULCON]
ldr r2, =0x245
str r2, [r1, #oUCON]
#define UART_BRD ((50000000 / (UART_BAUD_RATE * 16)) - 1)
mov r2, #UART_BRD
str r2, [r1, #oUBRDIV]
mov r3, #100
mov r2, #0x0
1: sub r3, r3, #0x1
tst r2, r3
bne 1b
#if 0
mov r2, #'U'
str r2, [r1, #oUTXHL]
1: ldr r3, [r1, #oUTRSTAT]
and r3, r3, #UTRSTAT_TX_EMPTY
tst r3, #UTRSTAT_TX_EMPTY
bne 1b
mov r2, #'0'
str r2, [r1, #oUTXHL]
1: ldr r3, [r1, #oUTRSTAT]
and r3, r3, #UTRSTAT_TX_EMPTY
tst r3, #UTRSTAT_TX_EMPTY
bne 1b
#endif
mov pc, lr
****************************************************/
#ifdef CONFIG_DEBUG_LL ;打印调试信息,缺省未定义
@ Print current Program Counter
ldr r1, SerBase
mov r0, #'\r'
bl PrintChar
mov r0, #'\n'
bl PrintChar
mov r0, #'@'
bl PrintChar
mov r0, pc
bl PrintHexWord
#endif
#ifdef CONFIG_BOOTUP_MEMTEST
@ simple memory test to find some DRAM flaults.
bl memtest
#endif
#ifdef CONFIG_S3C2410_NAND_BOOT ;从NAND Flash启动
bl copy_myself ;跳转到copy_myself函数
/**********************************************
@
@ copy_myself: copy vivi to ram
@
copy_myself:
mov r10, lr
@ reset NAND
mov r1, #NAND_CTL_BASE
ldr r2, =0xf830 @ initial value
str r2, [r1, #oNFCONF]
ldr r2, [r1, #oNFCONF]
bic r2, r2, #0x800 @ enable chip
str r2, [r1, #oNFCONF]
mov r2, #0xff @ RESET command
strb r2, [r1, #oNFCMD]
mov r3, #0 @ wait
1: add r3, r3, #0x1
cmp r3, #0xa
blt 1b
2: ldr r2, [r1, #oNFSTAT] @ wait ready
tst r2, #0x1
beq 2b
ldr r2, [r1, #oNFCONF]
orr r2, r2, #0x800 @ disable chip
str r2, [r1, #oNFCONF]
@ get read to call C functions (for nand_read())
ldr sp, DW_STACK_START @ setup stack pointer
mov fp, #0 @ no previous frame, so fp=0
@ copy vivi to RAM
ldr r0, =VIVI_RAM_BASE
/*********在/vivi/linux/platform/smdk2410.h中定义
#define VIVI_RAM_BASE (DRAM_BASE + DRAM_SIZE - VIVI_RAM_SIZE)
***************************************/
mov r1, #0x0
mov r2, #0x20000 ;0x20000-〉128k字节
bl nand_read_ll ;nand_read_ll在/vivi/arch/s3c2410/nand_read.c中定义
;r0,r1,r2分别为函数的三个参数
;从NANDFlash的0地址拷贝128k到SDRAM指定处
tst r0, #0x0
beq ok_nand_read
#ifdef CONFIG_DEBUG_LL
bad_nand_read:
ldr r0, STR_FAIL
ldr r1, SerBase
bl PrintWord
1: b 1b @ infinite loop
#endif
ok_nand_read:
#ifdef CONFIG_DEBUG_LL
ldr r0, STR_OK
ldr r1, SerBase
bl PrintWord
#endif
@ verify
mov r0, #0
ldr r1, =0x33f00000
mov r2, #0x400 @ 4 bytes * 1024 = 4K-bytes
go_next:
ldr r3, [r0], #4
ldr r4, [r1], #4
teq r3, r4
bne notmatch
subs r2, r2, #4
beq done_nand_read
bne go_next
notmatch:
#ifdef CONFIG_DEBUG_LL
sub r0, r0, #4
ldr r1, SerBase
bl PrintHexWord
ldr r0, STR_FAIL
ldr r1, SerBase
bl PrintWord
#endif
1: b 1b
done_nand_read:
#ifdef CONFIG_DEBUG_LL
ldr r0, STR_OK
ldr r1, SerBase
bl PrintWord
#endif
mov pc, r10 ;vivi拷贝到SDRAM完成,函数返回
*********************************/
@ jump to ram
ldr r1, =on_the_ram
add pc, r1, #0
nop
nop
1: b 1b @ infinite loop
on_the_ram:
#endif
#ifdef CONFIG_DEBUG_LL
ldr r1, SerBase
ldr r0, STR_STACK
bl PrintWord
ldr r0, DW_STACK_START
bl PrintHexWord
#endif
@ get read to call C functions
ldr sp, DW_STACK_START @ setup stack pointer
mov fp, #0 @ no previous frame, so fp=0
mov a2, #0 @ set argv to NULL
bl main @ call main
mov pc, #FLASH_BASE @ otherwise, reboot
@
@ End VIVI head
@