zoukankan      html  css  js  c++  java
  • ls1c-pmon启动分析

    /*    $Id: start.S,v 1.1.1.1 2006/09/14 01:59:08 root Exp $ */
    
    /*
     * Copyright (c) 2001 Opsycon AB  (www.opsycon.se)
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     * 1. Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     * 2. Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     * 3. All advertising materials mentioning features or use of this software
     *    must display the following acknowledgement:
     *    This product includes software developed by Opsycon AB, Sweden.
     * 4. The name of the author may not be used to endorse or promote products
     *    derived from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
     * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     * SUCH DAMAGE.
     *
     */
    
    #ifndef _KERNEL
    #define _KERNEL
    #endif
    
    #include <asm.h>
    #include <regnum.h>
    #include <cpu.h>
    #include <pte.h>
    
    #include "pmon/dev/ns16550.h"               //uart
    #include "target/prid.h"
    #include "target/sbd.h"
    #include "target/fcr.h"
    #include "target/via686b.h"                 //south bridge
    #include "target/i8254.h"
    #include "target/isapnpreg.h"
    #define DEBUG_LOCORE
    
    #ifndef BOOT_FROM_EJTAG
    #define  BOOT_FROM_EJTAG
    #endif
    #undef BOOT_FROM_EJTAG
    
    #ifdef DEBUG_LOCORE
    #define    TTYDBG(x) 
        .rdata;98: .asciz x; .text; la a0, 98b; bal stringserial; nop
    #else
    #define TTYDBG(x)
    #endif
    
    #define    PRINTSTR(x) 
        .rdata;98: .asciz x; .text; la a0, 98b; bal stringserial; nop
    
    /* Delay macro */
    #define    DELAY(count)    
        li v0, count;    
    99:            
        bnez    v0, 99b;
        addiu    v0, -1
    
    #define tmpsize        s1
    #define msize        s2
    #define bonito        s4
    #define dbg            s5
    #define sdCfg        s6
    
    #define CP0_CONFIG $16
    #define CP0_TAGLO  $28
    #define CP0_TAGHI  $29
    
    #define COM3_BASE_ADDR 0xbfe48000       //uart2
    /*
     *   Register usage:
     *
     *    s0    link versus load offset, used to relocate absolute adresses.
     *    s1    free
     *    s2    memory size.
     *    s3    free.
     *    s4    Bonito base address.
     *    s5    dbg.
     *    s6    sdCfg.
     *    s7    rasave.
     *    s8    L3 Cache size.
     */
    
    /*程序的开头,不过并不生成实际的二进制数据,它告诉编译汇编器一些信息*/
        //告诉编译器不要对后面代码进行优化处理
        .set    noreorder
        //三个全局符号
        .globl    _start
        .globl    start
        .globl    __main
    _start:                        //program entry  for ld.script
    start:
        .globl    stack
    stack = start - 0x4000        /* Place PMON stack below PMON start in RAM */
    /*stack 16k*/
    /*在此处首先定义了一个stack变量,用于说明pmon将来要用的栈的栈底,这个栈的位置在start程序段的起点下方0x4000处.即stack=start-0x4000.*/
    
    
    /*
    1.初始化CPU内的寄存器,清TLB.
    接下来执行一系列指令,先把cp0的状态寄存器清0,然后再把SR_BOOT_EXC_VEC载入cp0状态寄存器,即令BEV为1,进入bootstrap模式;
    然后在状态寄存器中开中断4,5,使系统可以响应中断级别4,5;把cp0的cause寄存器清0.
    再把全局变量stack的值赋给sp,即栈顶指针初始化为栈底位置.然后为全局变量指针gp赋值.
    然后把下一个要执行的pc值与上0xa0000000(实际上这一步通过子程序uncached实现).
    转换到uncached空间.然后执行locate子程序.
    */
    /* NOTE!! Not more that 16 instructions here!!! Right now it's FULL! */
        mtc0    zero, COP_0_STATUS_REG    /*disable interrupt*/
        mtc0    zero, COP_0_CAUSE_REG    /*禁止异常处理*/
        li    t0, SR_BOOT_EXC_VEC            /* Exception to Boostrap Location        load 0x00400000  to t0
                                          设置状态寄存器的BEV位,这样就是让 CP0 运行在没有 TLB 的模式,并且一旦发生异常,就进入ROM 的 bfc00000 位置重启*/
        mtc0    t0, COP_0_STATUS_REG    /*0x00400000 给 SR,BEV==1 CPU 使用 kseg1 作为入口点*/
        la    sp, stack   //la sp, stack 是把栈底地址给 sp 寄存器
        la    gp, _gp     //la gp, _gp 是把编译器中的 _gp 全局地址给 gp 寄存器,这样做法是让全局变量可以作相对寄存器寻址。
                        //其中_gp是在连接脚本文件里定义的。
    
        bal    uncached        /* Switch to uncached address space */
        nop
        /*bios 开始阶段只能只用 kseg1:0xa0000000-0xc00000000*/
        bal    locate            /* Get current execute address then goto locate*/
    /*
    在MIPS中,异常处理入口有两套,通过 CP0 的 STATUS 寄存器位 BEV 来决定,
    当 BEV=1 时,异常的入口地址为 0xBFC00000 开始的地址。
    而 BEV=0,异常地址为 0x80000000 开始的地址,所以PMON程序段开始处是一些异常的调入口,
    需要跳过这段空间,程序就是通过这个 bal 指令跳到后面的
    */
        nop
    
    uncached:
        or    ra, UNCACHED_MEMORY_ADDR    /*UNCACHED_MEMORY_ADDR=0xa0000000 */
    /*
    与0xA000 00000的或运算,也就是说从ROM加载时,不会改变返回地址 ra 的值。
    写这句的目的主要是保证要从ROM中运行后面的一段程序,而不是从其它地址(RAM中)运行
    */
        j    ra
        nop
    
    /*
     *  Reboot vector usable from outside pmon.
     */
     /*这里是例外向量,其实啥都没做,就是输出一些相关的信息, 然后跳到统一的 ex_common 出来处理,这是靠对齐来保证位于 MIPS 体系机构相应的中断向量处,
     如.align 9 则以 2^9 为间隔对齐,换成 16 进制,就是以 0x200 为间隔不知道是不是有什么规定*/
        .align    9
    ext_map_and_reboot:
        li    a0,0x10000000 /*test from 0xbfcxxxxx or 0xff20xxxx */
        and    a0,ra
        bnez    a0,1f
        la    a0,_start
        li    s0,0xbfc00000
        subu    s0,a0
    1:
        la    a0, v200_msg
        bal    stringserial
        nop
        b    exc_common
    
        .align    7            /* bfc00280 */
        la    a0, v280_msg
        bal    stringserial
        nop
        b    exc_common
    
    /* Cache error */
        .align    8            /* bfc00300 */
        PRINTSTR("
    PANIC! Unexpected Cache Error exception! ")
        mfc0    a0, COP_0_CACHE_ERR
        bal    hexserial
        nop
        b    exc_common
    
    /* General exception */
        .align    7            /* bfc00380 */
        li    a0,0x10000000 /*test from 0xbfcxxxxx or 0xff20xxxx */
        and    a0,ra
        bnez    a0,1f
        la    a0,_start
        li    s0,0xbfc00000
        subu    s0,a0
    1:
        la    a0, v380_msg
        bal    stringserial
        nop
        b    exc_common
    
        .align    9            /* bfc00400 */
        la    a0, v400_msg
        bal    stringserial
        nop
        b    exc_common
    
        .align    7            /* bfc00480 */
    #la    a0, v480_msg
    #    bal    stringserial
    #    nop
    #b    exc_common
    #if 0
        li s0,(0xbfc00000-0x81000000)
        PRINTSTR("ACPI_MEM_CEHCK=")
        li    a1, 0
        li    t0, 0xa0000000
        li    t2, 0xa0100000
    1:    lw    t1,(t0)
        addu    a1, a1, t1
        addiu t0, t0, 4
        bne    t0,t2,1b
        nop
        addu a0,a1,zero
        bal    hexserial
        nop
        PRINTSTR("
    ")
    #endif
    
        /*acpi: set ddr autorefresh and suspend */
    /*
        li    t0, 0xaffffe30
        lw    t1, 0x4(t0)
        li    t2, 0x1
        or    t1, t1, t2
        sw    t1, 0x4(t0)
    
        li    t0, 0xbfe7c008
        lw    t1, 0x0(t0)
        ori t1, t1, 0x2000
        sw    t1, 0x0(t0)
    */
        .align    8            /* bfc00500 */
    exc_common:
        PRINTSTR("
    CAUSE=")
        mfc0    a0, COP_0_CAUSE_REG
        bal    hexserial
        nop
        PRINTSTR("
    STATUS=")
        mfc0    a0, COP_0_STATUS_REG
        bal    hexserial
        nop
        PRINTSTR("
    ERRORPC=")
        mfc0    a0, COP_0_ERROR_PC
        bal    hexserial
        nop
        PRINTSTR("
    EPC=")
        mfc0    a0, COP_0_EXC_PC
        bal    hexserial
        nop
    
        PRINTSTR("
    BADADDR=")
        mfc0    a0, COP_0_BAD_VADDR
        bal    hexserial
        nop
    
    //    bal mydebug_main    //lxy
    //    nop
    1:
        b 1b
        nop
    
        .align 9
            nop
        .align 8
        .word read
        .word write
        .word open
        .word close
        .word nullfunction
        .word printf
        .word vsprintf
        .word nullfunction
        .word nullfunction
        .word getenv
        .word nullfunction
        .word nullfunction
        .word nullfunction
        .word nullfunction
        /*----------------异常处理结束----------------------*/
    
    /*
     *  We get here from executing a bal to get the PC value of the current execute
     *  location into ra. Check to see if we run from ROM or if this is ramloaded.
     */
    locate:                              /*跳转到此处,ra 记录子函数返回的入口地址*/
        la        s0,uncached            /*uncached 地址(RAM),给 S0*/
        subu    s0,ra,s0            /*RA(ROM)-S0(RAM)计算偏移量,当前代码对初始位置start的偏移量*/
    
    ////Pejoicen
        bal        CPU_TLBClear
        nop
    
    
        li    t0,SR_BOOT_EXC_VEC        /*t0=0x00400000*/
        mtc0    t0,COP_0_STATUS_REG        /*BEV=1 申明异常入口地址*/
        mtc0    zero,COP_0_CAUSE_REG    /*禁止异常处理*/
        .set    noreorder                /*防止汇编器为了在分支延迟槽中填充有用指令而打乱代码次序*/
    
    /*spi speed*/
    /*SPI 的 IO 寄存器基地址,SPI0 外部存储器的地址 0XBF000000-0XBF7FFFFF,共 8MB SPI1 外部大小 4MB*/
        li  t0, 0xbfe80000
        li  t1, 0x17        // div 4, fast_read + burst_en + memory_en
        sb  t1, 0x4(t0)        /*0x17 存入 0xbfe80004 为地址的寄存器sfc_param中*/
    
    
    //Pejoicen  Comment the PLL code
    
    //#ifdef LS1FSOC/* to adjust the DDR frequency */
    //    li v0,0xbfc00000+(NVRAM_POS+PLL_OFFS)
    //    lw a1,(v0)
    //
    //    li v0,0xffff0000
    //    and v0,a1
    //    bnez v0,1f
    //    nop
    //
    //    li  v0, 0x8888
    //    or  a1, a1, v0
    //
    //    b 2f
    //    nop
    //1:
    //#define DDRCFG_DATA (0x8888|(CPU_MULT-1)|((DDR_MULT-3)<<8))
    //    li  a1, DDRCFG_DATA   // 1fboard 25MHz
    //
    ///*************************PLL***********************************/
    ///**see clock management Loongson1B_processor_user_manual_V2.0***/
    //2:
    //    li  a0, 0xbfe78030
    //    sw  a1, 0x0(a0)
    //    nop
    //    lw    a2, 0x0(a0)
    //    xor a2,a1
    //    andi a2,0xf0f
    //    bnez a2,2b
    //    nop
    //#else        /*LS1B从这里开始执行,设置时钟寄存器*/
    /*************************PLL**********************************/
    //    li  a0, 0xbfe78030
    //    /*31:dc_div_en,30-26:dc_div,25:cpu_div_en,24-20:cpu_div,19:ddr_div_en,18-14:ddr_div*/
    //#if 0
    //    li v1,0x92298000
    //    li  a1, 0x39f0a
    //#else
    //    li v0,0xbfc00000+(NVRAM_POS+PLL_OFFS)    /*NVRAM=0x70000,PL_OFFS=512-6-10 v0=0xbfc701F0:属于 SPI*/
    //    lw v1,4(v0)
    //    lw a1,(v0)
    //
    //    li v0,0xfffc0000
    //    and v0,a1
    //    bnez v0,1f
    //    nop
    //
    //    andi v0,v1,0x3f
    //    bnez v0,1f
    //    nop
    //
    //    li v0,(1<<31)|(1<<25)|(1<<19)
    //    and a2,v0,v1
    //    bne a2,v0,1f
    //    nop
    //
    //    beqz v1,1f
    //    nop
    //    nop
    //    b 2f
    //    nop
    //1:
    //    #li v1, 0xb6188000
    //    #li v1, 0x8a290000//(1<<31)|(4<<26)|(1<<25)|(1<<20)|(1<<19)|(2<<14)|0x2a00
    //    #for new ls1b 480x272
    //    #li v1, 0xba290000//(1<<31)|(14<<26)|(1<<25)|(1<<20)|(1<<19)|(2<<14)|0x2a00
    //    #for new ls1b 800x480
    //    li v1, 0x92290000//(1<<31)|(4<<26)|(1<<25)|(1<<20)|(1<<19)|(2<<14)|0x2a00
    //    li  a1, 0x31812
    //
    //2:
    //#endif
    //    /****add by yg for low freq ***/
    //#if 0
    //    li a1,    0x8
    //#endif
    //
    //    or v1,0x2a00
    //    sw v1,4(a0)        /*设置 PLL 输出频率*/
    //    sw a1,(a0);        /*设置时钟寄存器*/
    //
    //1:
    //   lw v1,(a0)
    //   bne a1,v1,1b
    //   nop
    //    DELAY(0x3000)
    //
    //#endif
    /*--------------设置时钟频率结束------------------*/
    
        /*disable all gpio*/
        li a0,0xbfd00000        /*GPIO base addr*/
        sw zero,0x10c0(a0)        //clera register 0
        sw zero,0x10c4(a0)        // clear register 1
        //    lxy
    
        li a0,0                    // clear a0
        bal    initserial
        nop
    
    
        PRINTSTR("
    PMON2000 MIPS Initializing. Standby...
    ")
        PRINTSTR("ERRORPC=")
        mfc0    a0, COP_0_ERROR_PC        /*存储器出错处理*/
        bal    hexserial                    //use reg a0 传递  参数
        nop
    
        PRINTSTR(" CONFIG=")
        mfc0    a0, COP_0_CONFIG        /*CPU 参数寄存器*/
        bal    hexserial
        nop
        PRINTSTR("
    ")
    
        PRINTSTR(" PRID=")
        mfc0    a0, COP_0_PRID            /*CPU 参数和版本号*/
        bal    hexserial
        nop
        PRINTSTR("
    ")
    
        #zk read stop
        bnez s0,1f                /*S0=RA(ROM)-S0(RAM)计算偏移量,如果是热复位则直接跳转,如果是断电重启则调到1标号,进行代码搬家*/
        nop
        li a0,128
        PRINTSTR(" then jal initmips")//这句话就没打印出来,说明上面直接跳到了下面的标号1
        jal initmips
        nop
    1:
    //CPU WINDOW            don't know how to set
    // use only 8wins
    #define CPU_WIN_BASE 0xbfd00000
    #define CPU_WIN_MASK 0xbfd00040
    #define CPU_WIN_MMAP 0xbfd00080
    
    #define set_cpu_window(id, base, mask, mmap) 
            li      t0, CPU_WIN_BASE          ;  
            sw      $0, 0x80+id*8(t0)         ;  
            li      t1, base                  ;  
            sw      t1, 0x00+id*8(t0)         ;  
            sw      $0, 0x04+id*8(t0)         ;  
            li      t1, mask                  ;  
            sw      t1, 0x40+id*8(t0)         ;  
            sw      $0, 0x44+id*8(t0)         ;  
            li      t1, mmap                  ;  
            sw      t1, 0x80+id*8(t0)         ;  
            sw      $0, 0x84+id*8(t0)
    
    #if 1 /* fixup cpu window */
    cpu_win_fixup:
            //
            // hit         = (paddr & mask) == (mmap & mask)
            // mapped_addr =  paddr &~mask | mmap & mask
            //
            // mmap[7] -> enable
            // mmap[5] -> block trans enable,cache
            // mmap[4] -> fetch ins
            // mmap[1:0] -> destination
            //
            // NOTE: the address windows has priority, win0 > win1 > ... > win7
            set_cpu_window(0, 0x1fc00000, 0xfff00000, 0x1fc000f3) // boot rom
            set_cpu_window(1, 0x10000000, 0xf8000000, 0x10000001) // PCI mem0, mem1,    disabled
            set_cpu_window(2, 0x18000000, 0xfc000000, 0x18000001) // PCI mem2           disabled
            set_cpu_window(3, 0x1c000000, 0xffe00000, 0x1c000001) // PCI cfg/IO/header  disabled
            set_cpu_window(4, 0x1c200000, 0xffe00000, 0x1c2000d2) // gpu 1c2 /dc 1c3
            set_cpu_window(5, 0x1f000000, 0xff000000, 0x1f0000d3) // AXIMUX
            set_cpu_window(6, 0x40000000, 0xc0000000, 0x000000f0) // DDR 1GB
            set_cpu_window(7, 0x00000000, 0x00000000, 0x000000f0) // everything else
            // after this fixup, the kernel code should be compiled with
            // uncached instruction fetch patch
    #endif
    
    /* 直接手动设置DDR参数,新版本controller和过去不一样 */
    //    /*
    //     * Now determine DRAM configuration and size by
    //     * reading the I2C EEROM on the DIMMS
    //     */
    //
    //    /*
    //     * set gpio 66 to make ddr #CKE low
    //     */
    //    li    t0,0xbfd010c8
    //    li    t1,0x4
    //    sw    t1,(t0)
    //    li    t0,0xbfd010f8
    //    li    t1,0x0
    //    sw    t1,(t0)
    
    
    #ddr2config by cww 20090901
            PRINTSTR("DDR2 config begin_2
    ")
    //        bal     ddr2_config        //call ddr2_config in ddr2_config.s
        li      msize,0x10000000    //64M=0400_0000    128M=0x0800_0000 256M=0x1000_000
        /*set ddr controller */
        li t2,0xaff00000            //controller base addr
        li a0,0x01030006            // 32bit col row and bank
        sw a0,0x210(t2)
        ###########start#######
        li a0,0x1
        sw a0,0x18(t2)              // give start singal then initial phy
            nop
            PRINTSTR("DDR2 config end
    ")
    
    //    li a0,0xbfd00000
    //    lw a2,0x424(a0);
    //#ifdef CONFIG_DDR16BIT
    ///*16bit ddr and disable conf*/
    //    li a1,0x110000
    //        li      msize,0x08000000
    //#else
    ///*disable conf*/
    //    li a1,0x100000
    //        li      msize,0x10000000
    //#endif
    //    or a2,a1
    //
    ///*100M phy*/
    //    ori a2,0xf
    //#ifndef CONFIG_PHY100M
    //    xor a2,0xf
    //#endif
    //    sw a2,0x424(a0);
    
    /*--------------------初始化 cache-------------------------*/
    #define CF_7_SE         (1 << 3)        /* Secondary cache enable */
    #define CF_7_SC         (1 << 31)       /* Secondary cache not present */
    #define CF_7_TE         (1 << 12)       /* Tertiary cache enable */
    #define CF_7_TC         (1 << 17)       /* Tertiary cache not present */
    #define CF_7_TS         (3 << 20)       /* Tertiary cache size */
    #define CF_7_TS_AL      20              /* Shift to align */
    #define NOP8 nop;nop;nop;nop;nop;nop;nop;nop
    do_caches:
        TTYDBG("Init caches...
    ")
    
        li    s7, 0                   /* no L2 cache */
        li    s8, 0                   /* no L3 cache */
    
        TTYDBG("godson1 caches found
    ")
        bal     cache_init
        nop
    
        TTYDBG("Init caches done, cfg = ")  /*输出此时 CPU 的参数*/
        mfc0    a0, COP_0_CONFIG
        bal    hexserial
        nop
        TTYDBG("
    
    ")
    
    
        mfc0   a0,COP_0_CONFIG
        and    a0,a0,~((1<<12) | 3)
        or     a0,a0,2
        mtc0   a0,COP_0_CONFIG
    
    //Pejoicen comment
    /* all the acpi code unused */
    //acpi_begin:
    //
    ///* Access ACPI controller to check out if the machine is resuming from suspend
    //          Zeng Lu <zenglu@loongson.cn> */
    //#    li    t0,    0xbfe7c000                      //0xbfe7c000  UART5
    //#    lw    t1,(t0)
    //#and t1,    t1,    (1<<15)//WAK_STS
    //#    beqz    t1,    acpi_end
    //#    nop
    //    /*clear wakeup events */
    //    li    t0, 0xbfe7c000
    //    li    t1, -1
    //    sw    t1, (t0)
    //    li    t0, 0xbfe7c020
    //    li    t1, -1
    //    sw    t1, (t0)
    //
    //    li    t0,    0xbfe7c008
    //    lw    t1,    (t0)
    //#if 0 //clear slp_type if needed,this bit will be cleared in os
    //    li    t2, 0
    //    sw    t2, (t0)
    //#endif
    //
    //    srl    t1,    10
    //    and    t1,    t1,    7//SLP_TYP
    //    sub    t1,    t1,    5
    //    bnez    t1,    acpi_end    /* Resuming from suspend */
    //    nop
    //
    //    PRINTSTR("ACPI_CONTEXT=")
    //    li    t0,    0xa01ffc00
    //    li    t1,    0xa01ffc48
    //1:    lw    a0,    (t0)
    //    bal    hexserial
    //    nop
    //    PRINTSTR("
    ")
    //    addiu t0,t0,4
    //    bne t0,t1,1b
    //    nop
    //
    //     mfc0   a0,COP_0_CONFIG
    //    and    a0,a0,~((1<<12) | 3)
    //    or     a0,a0,3
     //   mtc0   a0,COP_0_CONFIG
    //
    //#if 0
    //    PRINTSTR("ACPI_MEM_CEHCK=")
    //    li    a1, 0
    //    li    t0, 0xa0000000
    //    li    t2, 0xa0100000
    //1:    lw    t1,(t0)
    //    addu    a1, a1, t1
    //    addiu t0, t0, 4
    //    bne    t0,t2,1b
    //    nop
    //    addu a0,a1,zero
    //    bal    hexserial
    //    nop
    //    PRINTSTR("
    ")
    //#endif
    //
    //
    //    bal    CPU_TLBClear
    //    nop
    //    PRINTSTR("ACPI_RESUME
    ")
    //    bal    suspend_resume
    //    nop
    //    /* Resume will never get here */
    //1:
    //    b    1b
    //    nop
    //acpi_end:/* Startup as usual */
    
    
    //PRINTSTR("begin test
    ");
    
    //#if 1
    //###close lcd backlight use pwm3
    //li a0,0xbfd010c0
    //lw a1,0x0(a0)
    //li a2,0x8
    //or a1,a2
    //sw a1,0x0(a0)
    //
    //li a0,0xbfd010d0
    //lw a1,0x0(a0)
    //li a2,0xfffffff7
    //and a1,a2
    //sw a1,0x0(a0)
    //
    //li a0,0xbfd010f0
    //lw a1,0x0(a0)
    //li a2,0xfffffff7
    //and a1,a2
    //sw a1,0x0(a0)
    //#endif
    
    //###lcd soft_reset and panel config&timing
    //    li a0,0xbc301240
    //    li a1,0x00100000
    //    sw a1,0x0(a0)
    //    li a1,0x00000000
    //    sw a1,0x0(a0)
    //
    //    li a0,0xbc3013c0
    //    li a1,0x80001111
    //    sw a1,0x0(a0)
    //    li a1,0
    //    #li a1,0x33333333
    //    sw a1,0x20(a0)
    
    
    //#define HAVE_TARGET_SETDDR
    //#include "newtest.32/mydebug.S"
    //tgt_setddr:
    //    PRINTSTR("input 0xbfe78030:");
    //    bal inputhex
    //    nop
    //    move t0,v0
    //    PRINTSTR("
    input 0xbfe78034:");
    //    bal inputhex
    //    nop
    //    li v1,0xbfe78030
    //    sw t0,(v1)
    //    sw v0,4(v1)
    //    li a0,0
    //    bal initserial
    //    nop
    //    bal ddr2_config_start
    //    nop
    //    b func_q
    //    nop
    
    bootnow:
    PRINTSTR("bootnow
    ");
    #define    FCALL_PRINTSTR(x) 
        .rdata;98: .asciz x; .text; la a0, 98b; la v0, stringserial; addu v0,s0;jalr v0; nop
    
    #undef BAL
    #define BAL(x) 
        la v0,x; 
        addu v0,s0; 
        jalr v0; 
        nop;
    
    
    
    
    
    /*copy <copy program> to sdram to make copy fast*/
    
        la t0,121f      /*读取下面 121 位置的地址*/
        addu t0,s0      /*S0=RA(ROM)-S0(RAM)*/
        la t1,122f      /*读取下面 122 位置的地址*/
        addu t1,s0      /*将121-122之间处于rom中的代码段拷贝复制到处于ram的0xa0000000*/
    
        li t2,0xa0000000    /*kseg1*/
    1:
        lw  v0,(t0)     /*S0+121 地址的内容拷给 0xa0000000*/
        sw v0,(t2)      /*循环拷贝,ROM->RAM*/
        addu t0,4
        addu t2,4
        ble t0,t1,1b       //if (t0 <= t1) goto 1b
        nop
    
        li t0,0xa0000000
           jr t0                /*jump to 0xa0000000,跳转到0xa0000000执行代码段的拷贝工作*/
        nop
    
    .align 3
      
       # jump后,121开始的代码此时就已经运行在了ram中,在ram中执行的代码段拷贝工作。
    121:
        FCALL_PRINTSTR("Copy PMON to execute location...
    ")
        la        a0, start                /*start=0x81000000,这个很重要,因为 la 的地址是 ld.script 的地址*/
        addu    a1, a0, s0                /*0x8100+偏移量*/
        la        a2, _edata                /*edata:初始化数据区的结尾*/
        or        a0, 0xa0000000            /*a0=0xa100*/
        or        a2, 0xa0000000
        subu    t1, a2, a0
        srl        t1, t1, 2                 /*右移 2 位*/
    
        move    t0, a0                    /*t0=a0=0xa100*/
        move    t1, a1                    /*0xa100+偏移量*/
        move    t2, a2                    /*已初始化的数据的位置*/
    
        /* copy text section */
    
    1:    and        t3, t0,0x0000ffff        /*t3=0?*/
        bnez    t3, 2f
        nop
        move    a0, t0                    /*a0=0x0000ffff?*/
        BAL(hexserial)
        nop
        li        a0, '
    '
        BAL(tgt_putchar)
        nop
    2:    lw        t3, 0(t1)                /*t1=t3=0xa100+偏移量?*/
        nop
        sw        t3, 0(t0)
        addu    t0, 4
        addu    t1, 4
        bne        t2, t0, 1b                /*循环拷贝初始化的数据到 0xa100 处?*/
        nop
    
        FCALL_PRINTSTR("
    copy text section done.
    ")
    
        /*BSS:用来容纳没有明确初始化声明的存储区*/
        /* Clear BSS */
        la        a0, _edata        /*未初始化数据区的开头*/
        la        a2, _end        /*未初始化数据区的结尾*/
    2:    sw        zero, 0(a0)
        bne        a2, a0, 2b
        addu    a0, 4            /*清空未初始化数据区*/
    
    
    
        FCALL_PRINTSTR("Copy PMON to execute location done.
    ")
        FCALL_PRINTSTR("sp=");
        move    a0, sp            /*当前栈地址给 a0,a0此处作为函数调用的第一个参数*/
        BAL(hexserial)            /*此处应该是把sp栈指针打印出来,sp是代码一开始设置的是代码段往下1K的地址*/
        nop
    
        li        a0, 0
        sw        a0, CpuTertiaryCacheSize /* Set L3 cache size 0 */
    
    
        //a0 a1 a2 传3个参数给initmips,不知道干嘛用。
        /* pass pointer to kseg1 tgt_putchar */
        la  a1, tgt_putchar
        addu a1,a1,s0
    
        la  a2, stringserial
        addu a2,a2,s0
    
        srl    msize,20
        move    a0,msize
    /* yishang copr  from bonito 2fdev */
        //move    a0,msize
        //srl    a0,20
    
        # 跳转到C执行
        la    v0, initmips
        jalr    v0
        nop
    
    .align 3
    122:
    
    stuck:
        b    stuck
        nop
    
    /*
     *  Clear the TLB. Normally called from start.S.
     */
    #if __mips64
    #define MTC0 dmtc0
    #else
    #define MTC0 mtc0
    #endif
    /*-----------函数调用部分,各种函数--------------*/
    /*-----------------初始化 TLB---------------------*/
    LEAF(CPU_TLBClear)
        li    a3, 0            # First TLB index.
    
        li    a2, PG_SIZE_4K
        MTC0   a2, COP_0_TLB_PG_MASK   # Whatever...
    
    1:
        MTC0   zero, COP_0_TLB_HI    # Clear entry high.
        MTC0   zero, COP_0_TLB_LO0    # Clear entry low0.
        MTC0   zero, COP_0_TLB_LO1    # Clear entry low1.
    
        mtc0    a3, COP_0_TLB_INDEX    # Set the index.
        addiu    a3, 1       /*a3=0+1=1*/
        li    a2, 64
        nop
        nop
        tlbwi                # Write the TLB
    
        bne    a3, a2, 1b      /*a3=a2=64 就清空完毕,64 个 index 都要清空*/
        nop
    
        jr    ra
        nop
    END(CPU_TLBClear)
    /*-----------------TLB 结束---------------------*/
    
    /*
     *  Set up the TLB. Normally called from start.S.
     *  没有调用???
     */
    LEAF(CPU_TLBInit)
        li    a3, 0            # First TLB index.
    
        li    a2, PG_SIZE_16M
        MTC0   a2, COP_0_TLB_PG_MASK   # All pages are 16Mb.
    
    1:
        and    a2, a0, PG_SVPN
        MTC0   a2, COP_0_TLB_HI    # Set up entry high.
    
        move    a2, a0
        srl    a2, a0, PG_SHIFT
        and    a2, a2, PG_FRAME
        ori    a2, PG_IOPAGE
        MTC0   a2, COP_0_TLB_LO0    # Set up entry low0.
        addu    a2, (0x01000000 >> PG_SHIFT)
        MTC0   a2, COP_0_TLB_LO1    # Set up entry low1.
    
        mtc0    a3, COP_0_TLB_INDEX    # Set the index.
        addiu    a3, 1
        li    a2, 0x02000000
        subu    a1, a2
        nop
        tlbwi                # Write the TLB
    
        bgtz    a1, 1b
        addu    a0, a2            # Step address 32Mb.
    
        jr    ra
        nop
    END(CPU_TLBInit)
    
    /*
     * Resume the CPU state, jump to the kernel
     */
    LEAF(suspend_resume)
        li    t0,    0xa01ffc00
        lw    ra,    (t0)
        lw    sp,    4(t0)
        lw    s8,    8(t0)
        lw    gp,    12(t0)
        lw    s0,    16(t0)
        lw    s1,    20(t0)
        lw    s2,    24(t0)
        lw    s3,    28(t0)
        lw    s4,    32(t0)
        lw    s5,    36(t0)
        lw    s6,    40(t0)
        lw    s7,    44(t0)
    
        lw    k0,    48(t0)
        lw    k1,    52(t0)
    
        lw    v0,    56(t0)
        lw    v1,    60(t0)
    
        lw    t1,    64(t0)
        mtc0    t1,    $12
        lw    t1,    68(t0)
        mtc0    t1,    $4
        lw    t1,    72(t0)
        mtc0    t1,    $5
    
        jr    ra
        nop
    END(suspend_resume)
    
    LEAF(stringserial)
        nop
        move    a2, ra
        addu    a1, a0, s0
        lbu    a0, 0(a1)
    1:
        beqz    a0, 2f
        nop
        bal    tgt_putchar
        addiu    a1, 1
        b    1b
        lbu    a0, 0(a1)
    
    2:
        j    a2
        nop
    END(stringserial)
    
    LEAF(outstring)
        move    a2, ra
        move    a1, a0
        lbu    a0, 0(a1)
    1:
        beqz    a0, 2f
        nop
        bal    tgt_putchar
        addiu    a1, 1
        b    1b
        lbu    a0, 0(a1)
    
    2:
        j    a2
        nop
    END(outstring)
    
    /*----------串口输出功能-------*/
    LEAF(hexserial)
        nop
        move    a2, ra            /*a2=跳回地址*/
        move    a1, a0            /*a0 存储待打印信息的寄存器中的值*/
        li    a3, 7
    1:
        rol    a0, a1, 4            /*a1 为待输出字符,一次循环左移 4 个单位*/
        move    a1, a0
        and    a0, 0xf
        la    v0, hexchar            /*hexchar:ascii 码的地址给 V0*/
        addu    v0, s0            /*s0 记录 uncache 的偏移量*/
        addu    v0, a0
        bal    tgt_putchar
        lbu    a0, 0(v0)
    
        bnez    a3, 1b            /*不为 0 一直循环*/
        addu    a3, -1
    
        j    a2
        nop
    END(hexserial)
    
    LEAF(tgt_putchar)
    //#ifdef CONFIG_EJTAG_SERIAL
    //    lui v0,0xff20;
    //    sb a0,0x1e0(v0);
    //    nop
    //    nop
    //    jr ra
    //    nop
    //#endif
        nop
        la    v0, COM3_BASE_ADDR      //select com
    1:
        lbu    v1, NSREG(NS16550_LSR)(v0)
        and    v1, LSR_TXRDY
        beqz    v1, 1b
        nop
    
        sb    a0, NSREG(NS16550_DATA)(v0)
        j    ra
        nop
    END(tgt_putchar)
    
    LEAF(tgt_testchar)
    #ifdef CONFIG_EJTAG_SERIAL
        lui v0,0xff20;
        lb v0,0x1e1(v0);
        jr ra
        nop
    #endif
        la    v0, COM3_BASE_ADDR  //select com
    1:
        lbu    v1, NSREG(NS16550_LSR)(v0)
        and    v0,v1, LSR_RXRDY
        jr ra
        nop
    END(tgt_testchar)
    
    LEAF(tgt_getchar)
    #ifdef CONFIG_EJTAG_SERIAL
        lui v0,0xff20;
        lb v0,0x1e0(v0);
        jr ra
        nop
    #endif
        la    v0, COM3_BASE_ADDR
    1:
        lbu    v1, NSREG(NS16550_LSR)(v0)
        and    v1, LSR_RXRDY
        beqz    v1, 1b
        nop
        lb    v0, NSREG(NS16550_DATA)(v0)
        jr ra
        nop
    END(tgt_getchar)
    
    
    /* baud rate definitions, matching include/termios.h */
    //#define B0      0
    //#define B50     50
    //#define B75     75
    //#define B110    110
    //#define B134    134
    //#define B150    150
    //#define B200    200
    //#define B300    300
    //#define B600    600
    //#define B1200   1200
    //#define B1800   1800
    //#define B2400   2400
    //#define B4800   4800
    //#define B9600   9600
    //#define B19200  19200
    //#define B38400  38400
    //#define B57600  57600
    //#define B115200 115200
    
    LEAF(initserial)
    //#ifdef CONFIG_EJTAG_SERIAL
    //    /*enable cp0 count*/
    //    mfc0 v0,$23
    //    li v1,0x200000
    //    or v0,v1
    //    mtc0 v0,$23
    //    jr ra
    //    nop
    //#endif
        la    v0, COM3_BASE_ADDR              // com3 = uart2
    //1:
        li    v1, FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_4
        sb    v1, NSREG(NS16550_FIFO)(v0)
        li    v1, CFCR_DLAB
        sb    v1, NSREG(NS16550_CFCR)(v0)
    //#ifdef LS1FSOC
    //    li a0, 0xbfe78030
    //    lw a0,(a0)
    //    and a0,0x700
    //    srl a0,8
    //    addiu a0,3
    //    li v1,APB_CLK
    //    multu a0,v1
    //    mflo v1
    //    li a0,2*16*CONS_BAUD
    //    divu v1,a0
    //    mflo v1
    // //    li    v1, ((APB_CLK*DDR_MULT)/(2*16*CONS_BAUD))     // 8MHz crystal,   M[7:3]=6     1fboard
    //#else
    //    move    v1,a0
    //    bnez    v1,2f
    //    nop
    //    li    v1,33333333
    //    li    a0,0xbfe78030
    //    lw    a1,4(a0)
    //    li    a2,0xc00
    //    and    a1,a2
    //    beq     a1,a2,2f
    //    nop
    //    lw    a1,(a0)
    //    andi    a2,a1,0x3f
    //    addiu    a2,12
    //    sll     a2,10
    //    srl a1,8
    //    andi    a1,0x3ff
    //    addu    a1,a2
    //    li    a2,(33333333>>11)
    //    multu   a1,a2
    //    mflo    v1
    //    lw    a1,4(a0)
    //    srl    a1,14
    //    andi    a2,a1,0x20
    //    beqz    a2,1f
    //    nop
    //    andi    a1,0x1f
    //    divu    v1,a1
    //    mflo    v1
    //    b 2f
    //    nop
    //1:
    //    srl v1,1
    //2:
    //#if 0
    ///*save div,for serial debug*/
    //    .set mips32
    //    mtc0 v1,$25,1               //应该是DDR clk=v1
    //    .set mips0
    //#endif
    //    li a1,2*16*CONS_BAUD        //boud rate     a1=分频锁存器的值
    //    divu v1,v1,a1
    //#endif
            li      v1,0xa3         //set div value for boud rate 9600 将v1的值给分频锁存器
        sb    v1, NSREG(NS16550_DATA)(v0)
        srl    v1, 8
        sb    v1, NSREG(NS16550_IER)(v0)
        li    v1, CFCR_8BITS
        sb    v1, NSREG(NS16550_CFCR)(v0)
        li    v1, MCR_DTR|MCR_RTS
        sb    v1, NSREG(NS16550_MCR)(v0)
        li    v1, 0x0
        sb    v1, NSREG(NS16550_IER)(v0)
    
        #disable all interrupt
        li      v1, 0x0
        sb      v1, NSREG(NS16550_IER)(v0)
    //#ifdef SERIAL1_MULTIFUNC
    //    li t1, 0xbfe78038
    //    lw t0, 0x0(t1)
    //    or t0, 0x2
    //    sw t0, 0x0(t1)
    //#endif
    //#ifdef SERIAL0_MULTIFUNC
    //    li t0, 0xbfe78038
    //    lw t1, 0x0(t0)
    //    or t1, 0x2
    //    sw t1, 0x0(t0)
    //#endif
        j    ra
        nop
    END(initserial)
    
    
    __main:
        j    ra
        nop
    
    
    /*-----------------异常打印输出------------------*/
        .rdata
    transmit_pat_msg:
        .asciz    "
    Invalid transmit pattern.  Must be DDDD or DDxDDx
    "
    v200_msg:
        .asciz    "
    PANIC! Unexpected TLB refill exception!
    "
    v280_msg:
        .asciz    "
    PANIC! Unexpected XTLB refill exception!
    "
    v380_msg:
        .asciz    "
    PANIC! Unexpected General exception!
    "
    v400_msg:
        .asciz    "
    PANIC! Unexpected Interrupt exception!
    "
    v480_msg:
        .asciz    "
    PANIC! You have been in the Ejtag Debug MOde Trap is 0!
    "
    hexchar:
        .ascii    "0123456789abcdef"
    
        .text
        .align    2
    /*
     *   I2C Functions used in early startup code to get SPD info from
     *   SDRAM modules. This code must be entirely PIC and RAM independent.
     */
    
    
    
    
    #define Index_Store_Tag_D            0x09
    #define Index_Invalidate_I            0x00
    #define Index_Writeback_Inv_D            0x01
    
    LEAF(nullfunction)
        jr ra
        nop
    END(nullfunction)
    
        .ent    cache_init
        .global cache_init
        .set    noreorder
    cache_init:
            move t1,ra          // t1保存返回值
    ####part 2####
    cache_detect_4way:
        .set mips32
            mfc0    t4, CP0_CONFIG,1
        lui    v0, 0x7             //v0 = 0x7 << 16    /*CPU 配置信息给 4*/
            and    v0, t4, v0
        srl    t3, v0, 16    #ic   //t3 = v0 >> 16  Icache组相联数 IA
    
        li    t5,0x800 #32*64
        srl    v1,t4,22            //v1 = t4 >> 22   shift right logic
        andi    v1,7            //Icache每路的组数 64x2^S IS
        sll    t5,v1   #InstCacheSetSize
        sll    t5,t3    #t5 InstCacheSize
    
    
            andi    v0, t4, 0x0380
            srl     t7, v0, 7     #dc
    
        li    t6,0x800 #32*64
        srl    v1,t4,13
        andi    v1,7
        sll    t6,v1  #DataCacheSetSize
        sll    t6,t7  #t5 DataCacheSize
    
    ####part 3####
    #    .set    mips3
        lui    a0, 0x8000
        addu    a1, $0, t5
        addu    a2, $0, t6
    cache_init_d2way:
    #a0=0x80000000, a1=icache_size, a2=dcache_size
    #a3, v0 and v1 used as local registers
        mtc0    $0, CP0_TAGHI
        addu    v0, $0, a0        //v0 = 0 + a0
        addu    v1, a0, a2        //v1 = a0 + a2
    1:    slt    a3, v0, v1          //a3 = v0 < v1 ? 1 : 0
        beq    a3, $0, 1f          //if (a3 == 0) goto 1f
        nop
        mtc0    $0, CP0_TAGLO
        cache    Index_Store_Tag_D, 0x0(v0)    # 1 way
    4:    beq    $0, $0, 1b
        addiu    v0, v0, 0x20
    1:
    cache_flush_i2way:
        addu    v0, $0, a0
        addu    v1, a0, a1
    1:    slt    a3, v0, v1
        beq    a3, $0, 1f
        nop
        cache    Index_Invalidate_I, 0x0(v0)    # 1 way
    4:    beq    $0, $0, 1b
        addiu    v0, v0, 0x20
    1:
    cache_flush_d2way:
        addu    v0, $0, a0
        addu    v1, a0, a2
    1:    slt    a3, v0, v1
        beq    a3, $0, 1f
        nop
        cache    Index_Writeback_Inv_D, 0x0(v0)     #1 way
    4:    beq    $0, $0, 1b
        addiu    v0, v0, 0x20
        .set    mips0
    
    1:
    cache_init_finish:
        jr    t1
        nop
        .set reorder
        .end     cache_init
    
    
    #define REG_ADDRESS 0x0
    #define CONFIG_BASE 0xaffffe00
    
    //#ddr2 by cww 20090901
    //#if 1
    //#include "ddr2fconfig.S"          // ddr set
    //#endif
    
    -------------------------------------- 适合自己的才是最好的!-----------------------------------------
  • 相关阅读:
    浅谈Chrome V8引擎中的垃圾回收机制
    selenium反爬机制
    03 HTTP协议与HTTPS协议
    HTTP缓存机制和原理
    python 自动发送邮件
    02 Anaconda的介绍,安装记以及使用
    01 关于jupyter的环境安装
    SQLAlchemy
    django-debug-toolbar
    flask 第十篇 after_request before_request
  • 原文地址:https://www.cnblogs.com/retry/p/14543945.html
Copyright © 2011-2022 走看看