打印

请高手用中文注解 vivi(head.S)s3c2440

[复制链接]
3826|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
avocationA|  楼主 | 2008-6-8 08:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/*
 * vivi/arch/s3c2440/head.S:
 *   Initialise hardware
 *
 * Copyright (C) 2001 MIZI Research, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License 
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *
 * Author: Janghoon Lyu <nandy@mizi.com>
 * Date  : $Date: 2004/02/04 06:22:24 $
 *
 * $Revision: 1.1.1.1 $
 *
 *
 * History:
 *
 * 2002-05-14: Janghoon Lyu <nandy@mizi.com>
 *   - Initial code
 *
 */

#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
@ 0x34:
    b    SleepRamProc
#endif
#ifdef CONFIG_TEST
@ 0x38:
@    b    hmi
#endif


@
@ Start VIVI head
@
Reset:
    @ disable watch dog timer
    mov    r1, #0x53000000
    mov    r2, #0x0
    str    r2, [r1]

    @ 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
    mov    r1, #CLK_CTL_BASE
    mvn    r2, #0xff000000
    str    r2, [r1, #oLOCKTIME]
    
    mov    r1, #CLK_CTL_BASE
    ldr    r2, clkdivn_value
    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

    mov    r1, #CLK_CTL_BASE
    @ldr    r2, mpll_value            @ clock default
    ldr     r2, =0x7f021    @mpll_value_USER         @ clock user set
    str    r2, [r1, #oMPLLCON]
    bl    memsetup


#ifdef CONFIG_PM
    @ Check if this is a wake-up from sleep
    ldr    r1, PMST_ADDR
    ldr    r0, [r1]
    tst    r0, #(PMST_SMR)
    bne    WakeupStart
#endif

    @ All LED on
    mov    r1, #GPIO_CTL_BASE
    add    r1, r1, #oGPIO_F
    ldr    r2,=0x55aa
    str    r2, [r1, #oGPIO_CON]
    mov    r2, #0xff
    str    r2, [r1, #oGPIO_UP]
    mov    r2, #0x00
    str    r2, [r1, #oGPIO_DAT]

#if 0
    @ SVC
    mrs    r0, cpsr
    bic    r0, r0, #0xdf
    orr    r1, r0, #0xd3
    msr    cpsr_all, r1
#endif

    @ set GPIO for UART
#ifdef CONFIG_S3C2440_SMDK
    mov    r1, #GPIO_CTL_BASE
    add    r1, r1, #oGPIO_H
    ldr    r2, gpio_con_uart    
    str    r2, [r1, #oGPIO_CON]
    ldr    r2, gpio_up_uart
    str    r2, [r1, #oGPIO_UP]    
#endif
    bl    InitUART

#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_S3C2440_NAND_BOOT
    bl    copy_myself

#if 1
    mov    r1, #GPIO_CTL_BASE
    add    r1, r1, #oGPIO_F
    mov    r2, #0x00
    str    r2, [r1, #oGPIO_DAT]
#endif

    @ 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
@

/*
 * subroutines
 */

@
@ Wake-up codes
@
#ifdef CONFIG_PM
WakeupStart:
    @ Clear sleep reset bit
    ldr    r0, PMST_ADDR
    mov    r1, #PMST_SMR
    str    r1, [r0]

    @ Release the SDRAM signal protections
    ldr    r0, PMCTL1_ADDR
    ldr    r1, [r0]
    bic    r1, r1, #(SCLKE | SCLK1 | SCLK0)
    str    r1, [r0]

    @ Go...
    ldr    r0, PMSR0_ADDR    @ read a return address
    ldr    r1, [r0]
    mov    pc, r1
    nop
    nop
1:    b    1b        @ infinite loop

SleepRamProc:
    @ SDRAM is in the self-refresh mode */
    ldr    r0, REFR_ADDR
    ldr    r1, [r0]
    orr    r1, r1, #SELF_REFRESH
    str    r1, [r0]

    @ wait until SDRAM into self-refresh
    mov    r1, #16
1:    subs    r1, r1, #1    
    bne    1b

    @ Set the SDRAM singal protections
    ldr    r0, PMCTL1_ADDR
    ldr    r1, [r0]
    orr    r1, r1, #(SCLKE | SCLK1 | SCLK0)
    str    r1, [r0]

    /* Sleep... Now */
    ldr    r0, PMCTL0_ADDR
    ldr    r1, [r0]
    orr    r1, r1, #SLEEP_ON
    str    r1, [r0]    
1:    b    1b

#ifdef CONFIG_TEST
hmi:
    ldr    r0, PMCTL0_ADDR
    ldr    r1, =0x7fff0
    str    r1, [r0]
    
    @ All LED on
    mov    r1, #GPIO_CTL_BASE
    add    r1, r1, #oGPIO_F
    ldr    r2,=0x55aa
    str    r2, [r1, #oGPIO_CON]
    mov    r2, #0xff
    str    r2, [r1, #oGPIO_UP]
    mov    r2, #0xe0
    str    r2, [r1, #oGPIO_DAT]
1:    b    1b
#endif

#endif

ENTRY(memsetup)
    @ initialise the static memory 

    @ set memory control registers
    mov    r1, #MEM_CTL_BASE
    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


#ifdef CONFIG_S3C2440_NAND_BOOT
@
@ copy_myself: copy vivi to ram
@
copy_myself:
    mov    r10, lr

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

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

    ldr    r2, =(0x6)        @ RnB Clear
    str    r2, [r1, #oNFSTAT]
    ldr    r2, [r1, #oNFSTAT]
    
    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, #0x4
    beq    2b

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

    @ 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, #GPIO_CTL_BASE
    add    r1, r1, #oGPIO_F
    mov    r2, #0xe0
    str    r2, [r1, #oGPIO_DAT]


    @ copy vivi to RAM
    ldr    r0, =VIVI_RAM_BASE
    mov     r1, #0x0
    mov    r2, #0x20000
    bl    nand_read_ll

#if 1
    mov    r1, #GPIO_CTL_BASE
    add    r1, r1, #oGPIO_F
    mov    r2, #0xb0
    str    r2, [r1, #oGPIO_DAT]
#endif


    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

#if 1
    mov    r1, #GPIO_CTL_BASE
    add    r1, r1, #oGPIO_F
    mov    r2, #0x70
    str    r2, [r1, #oGPIO_DAT]
#endif

    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

#endif @ CONFIG_S3C2440_NAND_BOOT


@ Initialize UART
@
@ r0 = number of UART port
InitUART:
    ldr    r1, SerBase
    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 ((UART_PCLK  / (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


@
@ Exception handling functions
@
HandleUndef:
#ifdef CONFIG_DEBUG_LL
    mov    r12, r14
    ldr    r0, STR_UNDEF
    ldr    r1, SerBase
    bl    PrintWord
    bl    PrintFaultAddr
#endif
1:    b    1b        @ infinite loop

HandleSWI:
#ifdef CONFIG_DEBUG_LL
    mov    r12, r14
    ldr    r0, STR_SWI
    ldr    r1, SerBase
    bl    PrintWord
    bl    PrintFaultAddr
#endif
1:    b    1b        @ infinite loop

HandlePrefetchAbort:
#ifdef CONFIG_DEBUG_LL
    mov    r12, r14
    ldr    r0, STR_PREFETCH_ABORT
    ldr    r1, SerBase
    bl    PrintWord
    bl    PrintFaultAddr
#endif
1:    b    1b        @ infinite loop

HandleDataAbort:
#ifdef CONFIG_DEBUG_LL
    mov    r12, r14
    ldr    r0, STR_DATA_ABORT
    ldr    r1, SerBase
    bl    PrintWord
    bl    PrintFaultAddr
#endif
1:    b    1b        @ infinite loop

HandleIRQ:
#ifdef CONFIG_DEBUG_LL
    mov    r12, r14
    ldr    r0, STR_IRQ
    ldr    r1, SerBase
    bl    PrintWord
    bl    PrintFaultAddr
#endif
1:    b    1b        @ infinite loop

HandleFIQ:
#ifdef CONFIG_DEBUG_LL
    mov    r12, r14
    ldr    r0, STR_FIQ
    ldr    r1, SerBase
    bl    PrintWord
    bl    PrintFaultAddr
#endif
1:    b    1b        @ infinite loop

HandleNotUsed:
#ifdef CONFIG_DEBUG_LL
    mov    r12, r14
    ldr    r0, STR_NOT_USED
    ldr    r1, SerBase
    bl    PrintWord
    bl    PrintFaultAddr
#endif
1:    b    1b        @ infinite loop


@
@ Low Level Debug
@
#ifdef CONFIG_DEBUG_LL

@
@ PrintFaultAddr: Print falut address
@
@ r12: contains address of instruction + 4
@
PrintFaultAddr:
    mov    r0, r12            @ Print address of instruction + 4
    ldr    r1, SerBase
    bl    PrintHexWord
    mrc    p15, 0, r0, c6, c0, 0    @ Read fault virtual address
    ldr    r1, SerBase
    bl    PrintHexWord
    mov    pc, lr

@ PrintHexNibble : prints the least-significant nibble in R0 as a
@ hex digit
@   r0 contains nibble to write as Hex
@   r1 contains base of serial port
@   writes ro with XXX, modifies r0,r1,r2
@   TODO : write ro with XXX reg to error handling
@   Falls through to PrintChar
PrintHexNibble:
    adr    r2, HEX_TO_ASCII_TABLE
    and    r0, r0, #0xF
    ldr    r0, [r2, r0]    @ convert to ascii
    b    PrintChar

@ PrintChar : prints the character in R0
@   r0 contains the character
@   r1 contains base of serial port
@   writes ro with XXX, modifies r0,r1,r2
@   TODO : write ro with XXX reg to error handling
PrintChar:
TXBusy:
    ldr    r2, [r1, #oUTRSTAT]
    and    r2, r2, #UTRSTAT_TX_EMPTY
    tst    r2, #UTRSTAT_TX_EMPTY
    beq    TXBusy    
    str    r0, [r1, #oUTXHL]
    mov    pc, lr

@ PrintWord : prints the 4 characters in R0
@   r0 contains the binary word
@   r1 contains the base of the serial port
@   writes ro with XXX, modifies r0,r1,r2
@   TODO : write ro with XXX reg to error handling
PrintWord:
    mov    r3, r0
    mov    r4, lr
    bl    PrintChar

    mov    r0, r3, LSR #8        /* shift word right 8 bits */
    bl    PrintChar

    mov    r0, r3, LSR #16        /* shift word right 16 bits */
    bl    PrintChar
    
    mov    r0, r3, LSR #24        /* shift word right 24 bits */
    bl    PrintChar

    mov    r0, #'\r'
    bl    PrintChar

    mov    r0, #'\n'
    bl    PrintChar

    mov    pc, r4

@ PrintHexWord : prints the 4 bytes in R0 as 8 hex ascii characters
@   followed by a newline
@   r0 contains the binary word
@   r1 contains the base of the serial port
@   writes ro with XXX, modifies r0,r1,r2
@   TODO : write ro with XXX reg to error handling
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
#endif
    
@
@ Data Area
@
@ Memory configuration values
.align 4
mem_cfg_val:
    .long    vBWSCON
    .long    vBANKCON0
    .long    vBANKCON1
    .long    vBANKCON2
    .long    vBANKCON3
    .long    vBANKCON4
    .long    vBANKCON5
    .long    vBANKCON6
    .long    vBANKCON7
    .long    vREFRESH
    .long    vBANKSIZE
    .long    vMRSRB6
    .long    vMRSRB7


@ Processor clock values
.align 4
clock_locktime:
    .long    vLOCKTIME
@mpll_value:
@    .long    vMPLLCON_NOW
mpll_value_USER:
    .long   vMPLLCON_NOW_USER
clkdivn_value:
    .long    vCLKDIVN_NOW

@ initial values for serial
uart_ulcon:
    .long    vULCON
uart_ucon:
    .long    vUCON
uart_ufcon:
    .long    vUFCON
uart_umcon:
    .long    vUMCON
@ inital values for GPIO
gpio_con_uart:
    .long    vGPHCON
gpio_up_uart:
    .long    vGPHUP

    .align    2
DW_STACK_START:
    .word    STACK_BASE+STACK_SIZE-4

#ifdef CONFIG_DEBUG_LL
    .align    2
HEX_TO_ASCII_TABLE:
    .ascii    "0123456789ABCDEF"
STR_STACK:
    .ascii    "STKP"
STR_UNDEF:
    .ascii    "UNDF"
STR_SWI:
    .ascii    "SWI "
STR_PREFETCH_ABORT:
    .ascii    "PABT"
STR_DATA_ABORT:
    .ascii    "DABT"
STR_IRQ:
    .ascii    "IRQ "
STR_FIQ:
    .ascii    "FIQ"
STR_NOT_USED:
    .ascii    "NUSD"
    .align 2
STR_OK:
    .ascii    "OK  "
STR_FAIL:
    .ascii    "FAIL"
STR_CR:
    .ascii  "\r\n"
#endif

.align 4
SerBase:
#if defined(CONFIG_SERIAL_UART0)
    .long UART0_CTL_BASE
#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

#ifdef CONFIG_PM
.align 4
PMCTL0_ADDR:
    .long 0x4c00000c
PMCTL1_ADDR:
    .long 0x56000080
PMST_ADDR:
    .long 0x560000B4
PMSR0_ADDR:
    .long 0x560000B8
REFR_ADDR:
    .long 0x48000024
#endif

相关帖子

沙发
avocationA|  楼主 | 2008-6-8 08:54 | 只看该作者

转网上的()望高手在完善下.

Vivi 是韩国mizi 公司开发的bootloader, 适用于ARM9处理器。 Vivi有两种工作模式:启动加载模式和下载模式。启动加载模式可以在一段时间后(这个时间可更改)自行启动linux内核,这时vivi的默认模式。在下载模式下,vivi为用户提供一个命令行接口,通过接口可以使用vivi提供的一些命令,见下表: 
 

命令 
 功能
 
   Load
 把二进制文件载入Flash或RAM
 
   Part
 操作MTD分区信息。显示、增加、删除、复位、保存MTD分区
 
   Param
 设置参数
 
   Boot
 启动系统
 
   Flash
 管理Flash,如删除Flash的数据
 

 

 

 

 

1.2 vivi的配置与编译
1.2.1 建立交叉开发环境
1、在宿主机上安装标准Linux 操作系统:Redhat 9.0 ( 主机系统为win2000,用虚拟机vmware安装的Redhat 9.0,内核版本为2.4.18) 。

2、宿主机上安装交叉编译器。

我这边的2410开发板提供的光盘上已附交叉编译器工具:arm-linux-gcc-2.95.3(源码为cross-2.95.3.tar.bz2)。

先以root 用户的身份登陆到linux 下。

进入/usr/local 目录,创建名为arm的目录:

cd /usr/local

mkdir arm

将光盘提供的cross-2.95.3.tar.bz2解压到/usr/local/arm目录:

tar jxvf cross-2.95.3.tar.bz2 –C /usr/local/arm

 

然后修改修改PATH 变量:为了可以方便使用arm-linux-gcc编译器系统, 把arm-linux工具链目录加入到环境变量PATH中:

修改/etc/profile文件,添加pathmunge /usr/local/arm/2.95.3/bin即可。

# Path manipulation

if [ `id -u` = 0 ]; then

        pathmunge  /sbin

        pathmunge  /usr/sbin

        pathmunge  /usr/local/sbin

        pathmunge  /usr/local/arm/2.95.3/bin 

fi

                                                                                

pathmunge /usr/X11R6/bin after

设置环境变量后,最好是重启或注销一下,这样设置的环境变量才能生效。

 

1.2.2 配置和编译vivi
如果vivi的源代码已根据开发板作了相应改动,则需要对源代码进行配置和编译,以生成烧入flash的vivi 二进制映象文件。

由于vivi要用到kernel的一些头文件,所以需要kernel的源代码,所以先要把linux的kernel准备好。将vivi和kernel都解到相应目录下(例如我将光盘提供的vivi源代码解压到/home/chenjun目录下,光盘提供的Linux kernel源码kernel-h2410eb.041024.tar.gz也解压到/home/chenjun目录下,解压后的文件名为kerne-h2410eb)。

然后需修改/vivi/Makefile里的一些变量设置:

Ø        LINUX_INCLUDE_DIR = /kernel/include/

(LINUX_INCLUDE_DIR 为kernel/include的对应目录,我的是/home/chen/kerne-h2410eb /include/)

因此修改为:

LINUX_INCLUDE_DIR = /home/chenjun/ kerne-h2410eb/include/

 

Ø        CROSS_COMPILE   = /usr/local/arm/2.95.3/bin/arm-linux- 

(CROSS_COMPILE 为arm-linux安装的相应目录,我的是/usr/local/arm/2.95.3/bin/arm-linux-)

因此修改为:

CROSS_COMPILE   = /usr/local/arm/2.95.3/bin/arm-linux-

 

Ø        ARM_GCC_LIBS     = /usr/local/arm/2.95.3/lib/gcc-lib/arm-linux/2.95.3

(需根据你arm-linux的安装目录修改,我的是/usr/local/arm/2.95.3/lib/gcc-lib/arm-linux/2.95.3)

 

进入/vivi目录执行make distclean。(目的是确保编译的有效性,在编译之前将vivi里所有的“*.o”和“*.o.flag”文件删掉)

进入/vivi目录里,输入“make menuconfig”,开始选择配置。可以Load一个写好的配置文件也可以自己修改试试。注意Exit时一定要选“Yes”保存配置。

再输入“make”正式开始编译,一会儿就完了。如果不报错,在/vivi里面就有你自己的“vivi”了。这个就是后面要烧写到flash中的bootloader。

1.3 vivi代码分析
vivi的代码包括arch,init,lib,drivers和include等几个目录,共200多条文件。

Vivi主要包括下面几个目录:

       arch:此目录包括了所有vivi支持的目标板的子目录,例如s3c2410目录。

       drivers:其中包括了引导内核需要的设备的驱动程序(MTD和串口)。MTD目录下分map、nand和nor三个目录。

       init:这个目录只有main.c和version.c两个文件。和普通的C程序一样,vivi将从main函数开始执行。

       lib:一些平台公共的接口代码,比如time.c里的udelay()和mdelay()。

       include:头文件的公共目录,其中的s3c2410.h定义了这块处理器的一些寄存器。Platform/smdk2410.h定义了与开发板相关的资源配置参数,我们往往只需要修改这个文件就可以配置目标板的参数,如波特率、引导参数、物理内存映射等。

 

 

 

 

1.4 vivi的运行
vivi的运行也可以分为两个阶段:

1.4.1 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                                              ;初始化系统时钟

       mov r1, #CLK_CTL_BASE

       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]

 

    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 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

@

 

 

1.4.2 vivi的第二阶段
vivi的第二阶段是从main()函数开始,同一般的C语言程序一样,该函数在/init/main.c文件中,总共可以分为8个步骤。

(1)    函数开始,通过putstr(vivi_banner)打印出vivi的版本。Vivi_banner在/init/version.c文件中定义

(2)    对开发板进行初始化(board_init函数),board_init是与开发板紧密相关的,这个函数在/arch/s3c2410/smdk.c文件中。开发板初始化主要完成两个功能,时钟初始化(init_time())和通用IO口设置(set_gpios())。

void set_gpios(void)

{

                            GPACON  = vGPACON;

                            GPBCON  = vGPBCON;

                            GPBUP   = vGPBUP; 

                            GPCCON  = vGPCCON;

                            GPCUP   = vGPCUP; 

                            GPDCON  = vGPDCON;

                            GPDUP   = vGPDUP; 

                            GPECON  = vGPECON;

                            GPEUP   = vGPEUP; 

                            GPFCON  = vGPFCON;

                            GPFUP   = vGPFUP; 

                            GPGCON  = vGPGCON;

                            GPGUP   = vGPGUP; 

                            GPHCON  = vGPHCON;

                            GPHUP   = vGPHUP; 

                            EXTINT0 = vEXTINT0;

                            EXTINT1 = vEXTINT1;

                            EXTINT2 = vEXTINT2;

}

其中,GPIO口在smdk2410.h(\vivi\include\platform\目录下)文件中定义。

(3)    内存映射初始化和内存管理单元的初始化工作:

mem_map_init();

mmu_init();

这两个函数都在/arch/s3c2410/mmu.c文件中。

void mem_map_init(void)

{

#ifdef CONFIG_S3C2410_NAND_BOOT

  mem_map_nand_boot();

#else

  mem_map_nor();

#endif

  cache_clean_invalidate();

  tlb_invalidate();

}

 

如果配置vivi时使用了NAND作为启动设备,则执行mem_map_nand_boot(),否则执行mem_map_nor()。这里要注意的是,如果使用NOR启动,则必须先把vivi代码复制到RAM中。这个过程是由copy_vivi_to_ram()函数来完成的。代码如下:
     static void copy_vivi_to_ram(void)

{

  putstr_hex("Evacuating 1MB of Flash to DRAM at 0x", VIVI_RAM_BASE);

  memcpy((void *)VIVI_RAM_BASE, (void *)VIVI_ROM_BASE, VIVI_RAM_SIZE);

}

VIVI_RAM_BASE、VIVI_ROM_BASE、VIVI_RAM_SIZE这些值都可以在smdk2410.h中查到,并且这些值必须根据自己开发板的RAM实际大小修改。这也是在移植vivi的过程中需要注意的一个地方。

mmu_init()函数中执行了arm920_setup函数。这段代码是用汇编语言实现的,针对arm920t核的处理器。

 

(4)    初始化堆栈,heap_init()。(定义在\vivi\lib\heap.c文件中)

int heap_init(void)

{

                            return mmalloc_init((unsigned char *)(HEAP_BASE), HEAP_SIZE); 

}

(5)    初始化mtd设备,mtd_dev_init()。

int mtd_init(void)

{

                     int ret;

 

#ifdef CONFIG_MTD_CFI

                            ret = cfi_init();

#endif

#ifdef CONFIG_MTD_SMC

                            ret = smc_init();

#endif

#ifdef CONFIG_S3C2410_AMD_BOOT

                            ret = amd_init();

#endif

 

                     if (ret) {

                            mymtd = NULL;

                            return ret;

                                   }

                     return 0;

}

这几个函数可以在/drivers/mtd/maps/s3c2410_flash.c里找到。

(6)    初始化私有数据,init_priv_data()。(定义在\vivi\lib\priv_data\rw.c文件中)

(7)    初始化内置命令,init_builtin_cmds()。

通过add_command函数,加载vivi内置的几个命令。

(8)    启动boot_or_vivi()。

启动成功后,将通过vivi_shell()启动一个shell(如果配置了CONFIG_SERIAL_TERM),此时vivi的任务完成。

使用特权

评论回复
板凳
walnutcy| | 2008-6-9 01:37 | 只看该作者

看起来头晕,,

使用特权

评论回复
地板
Ice_River| | 2008-6-10 17:22 | 只看该作者

搜索VIVI 开发笔记!

会有收获的~

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

123

主题

935

帖子

0

粉丝