Chinaunix首页 | 论坛 | 博客
  • 博客访问: 850411
  • 博文数量: 190
  • 博客积分: 7021
  • 博客等级: 少将
  • 技术积分: 1752
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-17 19:26
文章分类

全部博文(190)

文章存档

2014年(9)

2011年(32)

2010年(149)

我的朋友

分类: LINUX

2010-06-07 09:30:39

vivi的代码从head.S开始,也就是整个bootloader的stage1部分。这部分采用汇编语言来编写,从而达到高效,短小的目的。
首先我们需要注意的是head.S采用的是大写的后缀,而不是我们常规上面的小写。下面引用CalmArrow博客中的一段话来说明这个问题:
"首先解决一个问题,就是为什么使用head.S而不是用head.s?有了GNU AS和GNU Gcc的基础,不难理解主要原因就是为了使用C预处理器的宏替换和文件包含功能(GNU AS的预处理无法完成此项功能)。可以参考前面的总结部分。这样的好处就是可以使用C预处理器的功能来提高ARM汇编的程序设计环境,更加方便。但是因为ARM汇编和C在宏替换的细节上有所不同,为了区分,引入了__ASSEMBLY__这个变量,这是通过Makefile中AFLAGS来引入的"
查看宏展开可以使用:
GCC -E -D__ASSEMBLY__ -I./include /vivi/arch/s3c2440/head.S > charming.s

# 1 "arch/s3c2440/head.S"
# 1 ""
# 1 "<鍛戒护琛?"
# 1 "arch/s3c2440/head.S"
# 35 "arch/s3c2440/head.S"
# 1 "./include/config.h" 1
# 14 "./include/config.h"
# 1 "./include/autoconf.h" 1
# 15 "./include/config.h" 2
# 36 "arch/s3c2440/head.S" 2
# 1 "./include/linkage.h" 1
# 37 "arch/s3c2440/head.S" 2
# 1 "./include/machine.h" 1



# 1 "./include/config.h" 1
# 5 "./include/machine.h" 2
# 22 "./include/machine.h"
# 1 "./include/platform/smdk2440.h" 1

# 1 "./include/s3c2440.h" 1
# 22 "./include/s3c2440.h"
# 1 "./include/hardware.h" 1
# 23 "./include/s3c2440.h" 2
# 1 "./include/bitfield.h" 1
# 24 "./include/s3c2440.h" 2
# 3 "./include/platform/smdk2440.h" 2




# 1 "./include/sizes.h" 1
# 8 "./include/platform/smdk2440.h" 2
# 74 "./include/platform/smdk2440.h"
# 1 "./include/architecture.h" 1
# 75 "./include/platform/smdk2440.h" 2
# 23 "./include/machine.h" 2
# 38 "arch/s3c2440/head.S" 2

@ Start of executable code

.globl _start; .align 0; _start:
.globl ResetEntryPoint; .align 0; 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 ((1 << 24) | (7 << 16) | 782)
@ 0x30: vivi capabilities
 .long 0
# 103 "arch/s3c2440/head.S"
@
@ Start VIVI head
@
Reset:
 @ disable watch dog timer
 mov r1, #0x53000000
 mov r2, #0x0
 str r2, [r1]

 @ disable all interrupts
 mov r1, #0x4A000000
 mov r2, #0xffffffff
 str r2, [r1, #0x08]
 ldr r2, =0x7ff
 str r2, [r1, #0x1C]

 @ initialise system clocks
 mov r1, #0x4C000000
 mvn r2, #0xff000000
 str r2, [r1, #0x00]

 mov r1, #0x4C000000
 ldr r2, clkdivn_value
 str r2, [r1, #0x14]

 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

 mov r1, #0x4C000000
 @ldr r2, mpll_value @ clock default
 ldr r2, =0x7f021 @mpll_value_USER @ clock user set
 str r2, [r1, #0x04]
 bl memsetup
# 147 "arch/s3c2440/head.S"
 @ All LED on
 mov r1, #0x56000000
 add r1, r1, #0x50
 ldr r2,=0x55aa
 str r2, [r1, #0x0]
 mov r2, #0xff
 str r2, [r1, #0x8]
 mov r2, #0x00
 str r2, [r1, #0x4]
# 165 "arch/s3c2440/head.S"
 @ set GPIO for UART

 mov r1, #0x56000000
 add r1, r1, #0x70
 ldr r2, gpio_con_uart @0x16faaa
 str r2, [r1, #0x0]
 ldr r2, gpio_up_uart        @0x7ff,enable the up resistence
 str r2, [r1, #0x8]

 bl InitUART
# 190 "arch/s3c2440/head.S"
 bl copy_myself


 mov r1, #0x56000000
 add r1, r1, #0x50
 mov r2, #0x00
 str r2, [r1, #0x4]


 @ jump to ram
 ldr r1, =on_the_ram
 add pc, r1, #0
 nop
 nop
1: b 1b @ infinite loop

on_the_ram:
# 217 "arch/s3c2440/head.S"
@ get read to call C functions
@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@0x33defffc, there are 32k bytes stack in the vivi,the base address of the stack @is 0x33de8000
@and there are many parameter in the vivi from the base address of 0x33df0000
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 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, #0x00000000 @ otherwise, reboot

@
@ End VIVI head
@





@
@ Wake-up codes
@
# 303 "arch/s3c2440/head.S"
.globl memsetup; .align 0; memsetup:
 @ initialise the static memory

 @ set memory control registers
 mov r1, #0x48000000
 adrl r2, mem_cfg_val
 add r3, r1, #52
1: ldr r4, [r2], #4
 str r4, [r1], #4
 cmp r1, r3
 bne 1b
 mov pc, lr

1ADR伪指令--- 小范围的地址读取 

     ADR伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中。在汇编编译器编译源程序时,ADR伪指令被编译器替换成一条合适的指令。通常,编译器用一条ADD指令或SUB指令来实现该ADR伪指令的功能,若不能用一条指令实现,则产生错误,编译失败。

 

ADR伪指令格式 :ADR{cond}   register, expr

地址表达式expr的取值范围:

    当地址值是字节对齐时,其取指范围为: +255  ~ 255B

    当地址值是字对齐时,其取指范围为:   -1020 ~ 1020B

 

2ADRL伪指令----中等范围的地址读取

ADRL伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中,比ADR伪指令可以读取更大范围的地址。在汇编编译器编译源程序时,ADRL伪指令被编译器替换成两条合适的指令。若不能用两条指令实现,则产生错误,编译失败。

 

ADRL伪指令格式:ADRL{cond}   register, expr

地址表达式expr的取值范围:

    当地址值是字节对齐时,其取指范围为: -64K64K

    当地址值是字对齐时,其取指范围为:   -256K256K

 

3LDR伪指令-----大范围的地址读取

LDR伪指令用于加载32位的立即数或一个地址值到指定寄存器。在汇编编译源程序时,LDR伪指令被编译器替换成一条合适的指令。若加载的常数未超出MOVMVN的范围,则使用MOVMVN指令代替该LDR伪指令,否则汇编器将常量放入文字池,并使用一条程序相对偏移的LDR指令从文字池读出常量。


@
@ copy_myself: copy vivi to ram
@
copy_myself:
 mov r10, lr

 @ reset NAND
 mov r1, #0x4E000000
 ldr r2, =( (7<<12)|(7<<8)|(7<<4)|(0<<0) )
 str r2, [r1, #0x00]
 ldr r2, [r1, #0x00]

 ldr r2, =( (1<<4)|(0<<1)|(1<<0) ) @ Active low CE Control
 str r2, [r1, #0x04]
 ldr r2, [r1, #0x04]

 ldr r2, =(0x6) @ RnB Clear
 str r2, [r1, #0x20]
 ldr r2, [r1, #0x20]

 mov r2, #0xff @ RESET command
 strb r2, [r1, #0x08]
 mov r3, #0 @ wait
1: add r3, r3, #0x1
 cmp r3, #0xa
 blt 1b
2: ldr r2, [r1, #0x20] @ wait ready
 tst r2, #0x4
 beq 2b

 ldr r2, [r1, #0x04]
 orr r2, r2, #0x2 @ Flash Memory Chip Disable
 str r2, [r1, #0x04]

 @ 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

 mov r1, #0x56000000
 add r1, r1, #0x50
 mov r2, #0xe0
 str r2, [r1, #0x4]


 @ copy vivi to RAM
 ldr r0, =(0x30000000 + 0x04000000 - 0x00100000)
 mov r1, #0x0
 mov r2, #0x20000
 bl nand_read_ll


 mov r1, #0x56000000
 add r1, r1, #0x50
 mov r2, #0xb0
 str r2, [r1, #0x4]



 tst r0, #0x0
 beq ok_nand_read
# 386 "arch/s3c2440/head.S"
ok_nand_read:


@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@if there is any mistake while reading the nand flash,jump to the bad_nand_read
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
bad_nand_read:
    ldr r0, STR_FAIL
    ldr r1, SerBase
    bl PrintWord
1:
    b 1b        @infinite loop

ok_nand_read:
    ldr r0, STR_OK
    ldr r1, SerBase
    bl PrintWord

    @verrify

    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:
    sub r0, r0, #4
    ldr r1, SerBase
    bl PrintHexWord
    ldr r0, STR_FAIL
    ldr r1, SerBase
    pl PrintWord
1:
    b 1b

done_nand_read:
    mov r1, #GPIO_CTL_BASE
    add r1, r1, #oGPIO_F
    mov r2, #0x70
    str r2, [r1, #oGPIO_DAT]
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
PrintChar:
TXBusy:
    ldr r2, [r1, #oUTRSTAT]
    and r2, r2, #UTRSTAT_TX_EMPTY
    tst r2,#UTRSTAT_EX_EMPTY
    beq TXBusy
    str r0,[r1, #oTUXHL]
    mov pc lr

PrintWord:
    mov r3, r0
    mov r4, lr
    bl PrintChar

    mov r0, r3, LSR #8
    bl PrintChar

    mov r0, r3, LSR #16
    bl PrintChar

    mov r0, r3, LSR #24
    bl PrintChar

    mov r0, #'\r'
    bl PrintChar

    mov r0, #'\n'
    bl PrintChar

    mov pc, r4

PrintHexNibble:
    adr r2, HEX_TO_ASCII_TABLE
    and r0, r0, #0xf
    ldr r0, [r2, r0]
    b PrintChar

PrintHexWord:
    mov r4, lr
    mov r3, r0
    mov r0, r3, LSR #28
    bl PrintHexNibble
    mov r0, r3, LSR #24
    bl PrintHexNibble
    mov r0, r3, LSR #20
    bl PrintHexNibble
    mov r0, r3, LSR #16
    bl PrintHexNibble
    mov r0, r3, LSR #12
    bl PrintHexNibble
    mov r0, r3, LSR #8
    bl PrintHexNibble
    mov r0, r3, LSR #4
    bl PrintHexNibble
    mov r0, r3
    bl PrintHexNibble

    mov r0, #'\r'
    bl PrintChar
    mov r0, #'\n'
    bl PrintChar

    mov pc, r4
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@



 mov pc, r10

@ clear memory
@ r0: start address
@ r1: length
mem_clear:
 mov r2, #0
 mov r3, r2
 mov r4, r2
 mov r5, r2
 mov r6, r2
 mov r7, r2
 mov r8, r2
 mov r9, r2

clear_loop:
 stmia r0!, {r2-r9}
 subs r1, r1, #(8 * 4)
 bne clear_loop
 mov pc, lr
多寄存器寻址:
LDMIA R0!,{R1-R4}              ;R1<----[R0]
                               ;R2<----[R0+4]
                               ;R3<----[R0+8]
                               ;R4<----[R0+12]             

堆栈寻址:
STMFD入栈指令,相当于STMDB
STMFD SP!,{R2-R4}                            ;[SP-4]<---R4
                                             ;[SP-8]<---R3 
                                             ;[SP-12]<---R2   

LDMFD出栈指令,相当于LDMIA
LDMFD SP!,{R6-R8}                ;R6<----[SP]
                                 ;R7<----[SP+4]
                                 ;R8<----[SP+8]
                                   
 LDMIA / STMIA Increment After(先操作,后增加)
 LDMIB / STMIB Increment Before(先增加,后操作)
 LDMDA / STMDA Decrement After (先操作,后递减)
 LDMDB / STMDB Decrement Before(先递减,后操作)


@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@end of nand_flash_read;in this function there are something you have to do
@first: initialize the nand_flash
@1:    set the NFCONF register(NFCONF = 0X7770)
@2:    set the NFCONT register(NFCONT = 0x11)
@3:    clear the RnB bit in the NFSTAT register
@ (NFSTAT = 0X60?but i think it should be set to 0x40)
@4:    reset the nand flash {MOV R1,#0XFF
@                         STRB R1, [NFCMD]}
@5:    wait ready{2:
@             LDR R2, =NFSTAT
@                 TST R2, #0X04
@                 beq 2b}
@6:    disable_chip(NFCONT &= (~(1 << 1)))
@7:    jump to the function of nand_read_ll
@second: copy the code from the nand flash to sdram(nand_read_ll)
@third: check the data you have copyed(check if the data in the nand flash is
@        equal to the data you have copy to the sdram)
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@


@ Initialize UART
@
@ r0 = number of UART port
InitUART:
 ldr r1, SerBase
 mov r2, #0x0
 str r2, [r1, #0x08] @Disable the FIFO control register
 str r2, [r1, #0x0C] @Disable the MODULE control register        
 mov r2, #0x3
 str r2, [r1, #0x00] @normal,no parity,1 bit stop per frame,8 bits transfer
 ldr r2, =0x245
 str r2, [r1, #0x04]

 mov r2, #((50000000 / (115200 * 16)) - 1)        @0x26
 str r2, [r1, #0x28]

@
@ Wait a little while
@
 mov r3, #100
 mov r2, #0x0
1: sub r3, r3, #0x1
 tst r2, r3
 bne 1b
# 496 "arch/s3c2440/head.S"
 mov pc, lr
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@UART register:
@ULCON0 0X50000000
@ULCON1 0X50004000
@ULCON2 0X50008000
@UCONn +0X04
@UFCONn +0X08
@UMCONn +0X0C
@UTRSTAT +0X10
@UBRDIV +0X28
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@
@ Exception handling functions
@
HandleUndef:







1: b 1b @ infinite loop

HandleSWI:







1: b 1b @ infinite loop

HandlePrefetchAbort:







1: b 1b @ infinite loop

HandleDataAbort:







1: b 1b @ infinite loop

HandleIRQ:







1: b 1b @ infinite loop

HandleFIQ:







1: b 1b @ infinite loop

HandleNotUsed:







1: b 1b @ infinite loop


@
@ Low Level Debug
@
# 681 "arch/s3c2440/head.S"
@
@ Data Area
@
@ Memory configuration values
.align 4
mem_cfg_val:
 .long 0x22111110
 .long 0x00000700
 .long 0x00000700
 .long 0x00000700
 .long 0x00000700
 .long 0x00000700
 .long 0x00000700
 .long 0x00018009
 .long 0x00018009
 .long 0x008e04eb
 .long 0xB2
 .long 0x30
 .long 0x30


@ Processor clock values
.align 4
clock_locktime:
 .long 0x00ffffff
@mpll_value:
@ .long vMPLLCON_NOW
mpll_value_USER:
 .long ((0x5c << 12) | (0x1 << 4) | (0x0))
clkdivn_value:
 .long 0x5

@ initial values for serial
uart_ulcon:
 .long 0x3
uart_ucon:
 .long 0x245
uart_ufcon:
 .long 0x0
uart_umcon:
 .long 0x0
@ inital values for GPIO
gpio_con_uart:
 .long 0x0016faaa
gpio_up_uart:
 .long 0x000007ff

 .align 2
DW_STACK_START:
 .word (((((0x30000000 + 0x04000000 - 0x00100000) - 0x00100000) - 0x00004000) - (0x00004000 + 0x00004000 + 0x00004000)) - 0x00008000)+0x00008000 -4

@ =0x33DEFFFC
# 761 "arch/s3c2440/head.S"
.align 4
SerBase:

 .long 0x50000000

以上部分就是stage1的代码,我做了一些解释。这部分主要是与硬件打交道,所以主要是熟悉各种寄存器的功能和相关的配置,剩下的工作就是根据需求设置寄存器即可。其实现的功能主要是设备的初始化,和搬运工作。
做完相应的工作以后跳转到main函数的入口。
阅读(1429) | 评论(0) | 转发(0) |
0

上一篇:u-boot编译

下一篇:vivi-stage2-step1

给主人留下些什么吧!~~