龙芯俱乐部开源技术社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 4000|回复: 0

【PMON 研究】【08】start.S 文件详解

[复制链接]

57

主题

83

帖子

1万

积分

论坛元老

Rank: 8Rank: 8

积分
10412
发表于 2017-1-21 18:34:28 | 显示全部楼层 |阅读模式
本帖最后由 lophyxp 于 2017-1-21 18:35 编辑

心映真的空间
苦心励志 技术强国
让我们面对现实 让我们忠于理想
欢迎来到唐刚的首页

start.S 文件详解
龙芯相关 » PMON 研究 » start.S 文件详解
1

start.S文件在 /Targets/Bonito/Bonito 目录当中,是整个PMON代码的起点。我们首先研究它。

文件一开头是版权声明部分,然后是包括一些头文件,然后是一些宏定义,然后才是代码。

与CPU相关的一些宏定义有

  1. /*
  2. *   Register usage:
  3. *
  4. *    s0    link versus load offset, used to relocate absolute adresses.
  5. *    s1    free
  6. *    s2    memory size.
  7. *    s3    free.
  8. *    s4    Bonito base address.
  9. *    s5    dbg.
  10. *    s6    sdCfg.
  11. *    s7    rasave.
  12. *    s8    L3 Cache size.
  13. */

  14. #define tmpsize        s1
  15. #define msize        s2
  16. #define bonito        s4
  17. #define dbg            s5
  18. #define sdCfg        s6
复制代码

下面是程序的开头,不过并不生成实际的二进制数据,它告诉编译汇编器一些信息。

  1. .set    noreorder
  2.     .globl    _start
  3.     .globl    start
  4.     .globl    __main

  5. _start:
  6. start:
  7.     .globl    stack
  8.     stack = start - 0x4000         /* Place PMON stack below PMON start in RAM */

  9. =====================
  10. 解释:
  11. .set noreorder
  12. 是告诉汇编汇编器不要对后面的代码进行优化处理,比如重新排列执行代码。

  13. .globl _start
  14. .globl start
  15. .globl __main
  16. 这里,定义了三个全局符号。可以PMON代码中的任何地方引用它。

  17. _start:
  18. start:
  19. .globl stack
  20. stack = start - 0x4000 /* Place PMON stack below PMON start in RAM */
  21. 在这里定义了子程序的名称 _start 和 start。并定义了堆栈的栈底 stack 值,在 start 以下 16K 处。
  22. =====================
复制代码

下面是程序执行的第一条语句

  1. /* NOTE!! Not more that 16 instructions here!!! Right now it's FULL! */
  2.     mtc0    zero, COP_0_STATUS_REG
  3.     mtc0    zero, COP_0_CAUSE_REG
  4.     li    t0, SR_BOOT_EXC_VEC        /* Exception to Boostrap Location */                                
  5.     mtc0    t0, COP_0_STATUS_REG
  6.                                 /* SR's BEV bit is set so the CPU uses the ROM(kseg1) space exception entry point when reboot exception occurs
  7.     la    sp, stack               
  8.     la    gp, _gp               

  9. =====================        
  10. 解释:
  11. 由于龙芯的地址空间决定,这里的代码不能超过 16 条指令,因为后面紧跟着的是中断向量的地址。(??)

  12. 接着,就把 CP0 的状态寄存器 COP_0_STATUS_REG 和 COP_0_CAUSE_REG 寄存器全部清空为0。
  13. li t0, SR_BOOT_EXC_VEC
  14. 接着设置状态寄存器的BEV位,这样就是让 CP0 运行在没有 TLB 的模式,并且一旦发生异常,就进入ROM 的 bfc00000 位置重启。

  15. 后面两句主要设置引导程序的堆栈空间,
  16. la sp, stack 是把栈底地址给 sp 寄存器,(现在有个疑问就是 pmon的栈是往上还是往下生长的??)
  17. la gp, _gp 是把编译器中的 _gp 全局地址给 gp 寄存器,这样做法是让全局变量可以作相对寄存器寻址。
  18. 其中_gp是在连接脚本文件里定义的。
  19. =====================
复制代码

  1. bal    uncached
  2. nop
  3. bal    locate
  4. nop   

  5. uncached:
  6. or      ra, UNCACHED_MEMORY_ADDR
  7. j    ra
  8. nop

  9. =====================        
  10. 解释:
  11. 这段程序先进行一个无条件跳转连接指令,这样做的目的很明确就是想清空预取指令和流水线的指令。
  12. 这样就跳到 uncached 这里运行。
  13. 先来看看bal指令会做些什么事情,
  14. 通常bal指令会算出跳转到的目的地址相对于PC寄存器的偏移量,
  15. 然后把PC+8指令地址放到ra寄存器里,也就是把bal locate指令地址放到RA寄存器,以便可以返回。

  16. 由于龙芯2E的加电时启动地址是 0xBFC0 0000,那么放在ra里的值就是 0xBFCO 0028(第8条指令)。
  17. 后面
  18. or ra, UNCACHED_MEMORY_ADDR,这里进行是与0xA000 00000的或运算,
  19. 也就是说从ROM加载时,不会改变返回地址 ra 的值。
  20. 写这句的目的主要是保证要从ROM中运行后面的一段程序,而不是从其它地址(RAM中)运行。
  21. 所以接着就跳回来到 bal locate位置并执行 bal locate 指令,这样就跳到 locate 的位置执行程序了。
  22. =====================
复制代码

在MIPS中,异常处理入口有两套,通过 CP0 的 STATUS 寄存器位 BEV 来决定,当 BEV=1 时,异常的入口地址为 0xBFC00000 开始的地址。而 BEV=0,异常地址为 0x80000000 开始的地址,所以PMON程序段开始处是一些异常的调入口,需要跳过这段空间,程序就是通过这个 bal 指令跳到后面的

2

下面是那段被跳过去的异常代码

  1. /*
  2. *  Reboot vector usable from outside pmon.
  3. */
  4.     /* started in aligned address by 2^8=256 Bytes, that is 0xbfc00000 + 0x100 = 0xbfc00100 */
  5.     .align    8                        
  6. ext_map_and_reboot:
  7.     bal    CPU_TLBClear               
  8.     nop

  9.     li    a0, 0xc0000000
  10.     li    a1, 0x40000000
  11.     bal    CPU_TLBInit
  12.     nop
  13.     la    v0, tgt_reboot               
  14.     la    v1, start                    
  15.     subu    v0, v1                    
  16.     lui    v1, 0xffc0                    
  17.     addu    v0, v1
  18.     jr    v0
  19.     nop

  20. /*
  21. *  Exception vectors here for rom, before we are up and running. Catch
  22. *  whatever comes up before we have a fully fledged exception handler.
  23. */
  24.     /* TLB refill exception */
  25.     /* bfc00200, this code address is 0xbfc00200, 2^9 = 512 Bytes, it is a exception process function */
  26.     .align    9            

  27.     move    k0, ra            /* save ra */
  28.     la    a0, v200_msg
  29.     bal    stringserial
  30.     nop
  31.     b    exc_common

  32.     .align    7            /* bfc00280 */
  33.     move    k0, ra    #save ra
  34.     la    a0, v280_msg
  35.     bal    stringserial
  36.     nop
  37.     b    exc_common        // print the CP0 register's infomation

  38. /* Cache error handler */
  39.     .align    8            /* bfc00300 */
  40.     PRINTSTR("\r\nPANIC! Unexpected Cache Error exception! ")
  41.     mfc0    a0, COP_0_CACHE_ERR
  42.     bal    hexserial
  43.     nop
  44.     b    exc_common

  45. /* General exception handler */
  46.     .align    7            /* bfc00380 */
  47.     move    k0, ra    #save ra
  48.     la    a0, v380_msg
  49.     bal    stringserial
  50.     nop
  51.     b    exc_common

  52.     .align    8            /* bfc00400 */
  53.     move    k0, ra    #save ra
  54.     la    a0, v400_msg
  55.     bal    stringserial
  56.     nop

  57. /* when the exception occurs, do this code to present the CP0 register's content */
  58. exc_common:
  59.     PRINTSTR("\r\nCAUSE=")
  60.     mfc0    a0, COP_0_CAUSE_REG
  61.     bal    hexserial
  62.     nop
  63.     PRINTSTR("\r\nSTATUS=")
  64.     mfc0    a0, COP_0_STATUS_REG
  65.     bal    hexserial
  66.     nop
  67.     PRINTSTR("\r\nERRORPC=")
  68.     mfc0    a0, COP_0_ERROR_PC
  69.     bal    hexserial
  70.     nop
  71.     PRINTSTR("\r\nEPC=")
  72.     mfc0    a0, COP_0_EXC_PC
  73.     bal    hexserial
  74.     nop
  75.     PRINTSTR("\r\nBADVADDR=")
  76.     mfc0    a0, COP_0_BAD_VADDR
  77.     bal    hexserial
  78.     nop
  79.     PRINTSTR("\r\nRA=")
  80.     move    a0, k0
  81.     bal    hexserial
  82.     nop

  83. //    b    ext_map_and_reboot
  84.     nop

  85.     /* control the distribution of the code, here we insert a bank 256 Bytes. */
  86.     .align 8   
  87.         nop

  88.     /* handler name table */
  89.     .align 8
  90.     .word read
  91.     .word write
  92.     .word open
  93.     .word close
  94.     .word nullfunction
  95.     .word printf
  96.     .word vsprintf
  97.     .word nullfunction
  98.     .word nullfunction
  99.     .word getenv
  100.     .word nullfunction
  101.     .word nullfunction
  102.     .word nullfunction
  103.     .word nullfunction
复制代码

3

让我们看看 locate 标号之后的代码是些什么

  1. /*
  2. *  We get here from executing a bal to get the PC value of the current execute
  3. *  location into ra. Check to see if we run from ROM or if this is ramloaded.
  4. */
  5. locate:
  6.     la        s0, start               
  7.     subu    s0, ra, s0               
  8.     and        s0, 0xffff0000            

  9.     li        t0, SR_BOOT_EXC_VEC
  10.     mtc0    t0, COP_0_STATUS_REG
  11.     mtc0    zero, COP_0_CAUSE_REG   

  12.     .set noreorder
  13.     /* the varible bonito is register s4, BONITO_REG_BASE is 0x1fe00000 */
  14.      li        bonito, PHYS_TO_UNCACHED(BONITO_REG_BASE)  

  15.     bal    1f   
  16.     nop            /* now the value of ra is 0xbfc00xxx */

  17.     /* bonito endianess */
  18.     BONITO_BIC(BONITO_BONPONCFG, BONITO_BONPONCFG_CPUBIGEND)
  19.     BONITO_BIC(BONITO_BONGENCFG, BONITO_BONGENCFG_BYTESWAP|BONITO_BONGENCFG_MSTRBYTESWAP)
  20.     BONITO_BIS(BONITO_BONPONCFG, BONITO_BONPONCFG_IS_ARBITER)

  21.     /*
  22.      * In certain situations it is possible for the Bonito ASIC
  23.      * to come up with the PCI registers uninitialised, so do them here
  24.      */
  25.     BONITO_INIT(BONITO_PCICLASS,(PCI_CLASS_BRIDGE << PCI_CLASS_SHIFT) | (PCI_SUBCLASS_BRIDGE_HOST << PCI_SUBCLASS_SHIFT))
  26.     BONITO_INIT(BONITO_PCICMD, BONITO_PCICMD_PERR_CLR | BONITO_PCICMD_SERR_CLR | BONITO_PCICMD_MABORT_CLR | BONITO_PCICMD_MTABORT_CLR | BONITO_PCICMD_TABORT_CLR | BONITO_PCICMD_MPERR_CLR )
  27.     //BONITO_INIT(BONITO_PCILTIMER, 0)
  28.     BONITO_INIT(BONITO_PCILTIMER, 255)
  29.     BONITO_INIT(BONITO_PCIBASE0, 0)
  30.     BONITO_INIT(BONITO_PCIBASE1, 0)
  31.     BONITO_INIT(BONITO_PCIBASE2, 0)
  32.     BONITO_INIT(BONITO_PCIEXPRBASE, 0)
  33.     BONITO_INIT(BONITO_PCIINT, 0)

  34.     BONITO_BIS(BONITO_PCICMD, BONITO_PCICMD_PERRRESPEN)

  35.     BONITO_BIS(BONITO_PCICMD, PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE|PCI_COMMAND_MASTER_ENABLE)

  36.     BONITO_BIC(BONITO_BONGENCFG, 0x80)  #½ûÖ¹iobc

  37.     #BONITO_BIS(BONITO_BONGENCFG, BONITO_BONGENCFG_BUSERREN)

  38.     /* Set debug mode */
  39.     BONITO_BIS(BONITO_BONGENCFG, BONITO_BONGENCFG_DEBUGMODE)

  40.     /******** added to init southbridge*/
  41. #ifdef VGA_NOTEBOOK_V2
  42.     ISA_BRMW_INIT(0,0x74,0xeb,0x0)
  43.     ISA_BRMW_INIT(0,0x75,0xff,0x20)
  44.     ISABWWR_INIT(4,0x48,0xb000)
  45.     ISABBWR_INIT(4,0x41,0x80)

  46.     RMW_INIT(MOD_W,(PCI_IO_SPACE+0xb04c),0xffffffdf,0x0)
  47. #endif

  48.     // SouthBridge settings

  49.     /* Set the SMB base address */
  50.     ISABWWR_INIT(4, SMBUS_IO_BASE_ADDR, SMBUS_IO_BASE_VALUE | 0x1)
  51.     /* enable the host controller */
  52.     ISABHWR_INIT(4, SMBUS_HOST_CONFIG_ADDR, SMBUS_HOST_CONFIG_ENABLE_BIT)
  53.     /* enable the SMB IO ports */
  54.     ISABBWR_INIT(4, PCI_COMMAND_STATUS_REG, PCI_COMMAND_IO_ENABLE)

  55.     ISARD_INIT(CTC_PORT+PT_CONTROL)

  56.     /* program i8254 ISA refresh counter */
  57.     ISAWR_INIT(CTC_PORT+PT_CONTROL,PTCW_SC(PT_REFRESH)|PTCW_16B|PTCW_MODE(MODE_RG))
  58.     ISAWR_INIT(CTC_PORT+PT_REFRESH, ISAREFRESH & 0xff)
  59.     ISAWR_INIT(CTC_PORT+PT_REFRESH, ISAREFRESH >> 8)

  60.     EXIT_INIT(0)

  61. 1:   
  62.     move a0, ra            /* now the value of ra is 0xbfc00xxx */
  63. reginit:            
  64.     lw    t3, Init_Op(a0)
  65.     lw    t0, Init_A0(a0)        /* Init_A0 is 4 */
  66.     and    t4, t3, OP_MASK        /* OP_MASK is 0x000000fc, to keep 4 bytes aligned */

  67.     /*
  68.      * EXIT(STATUS)
  69.      */
  70.     bne    t4, OP_EXIT, 8f        /* OP_EXIT is 0x00000000 */
  71.     nop
  72.     move v0, t0                /* now v0 is the content of 4 bytes offset from 0xbfc000xx */
  73.     b    .done
  74.     nop

  75.     /*
  76.      * DELAY(CYCLES)
  77.      */
  78. 8:    bne    t4, OP_DELAY, 8f    /* OP_DELAY is 0x00000008 */
  79.     nop
  80. 1:    bnez    t0,1b            /* t0 不等于 0就在这死循环 */
  81.     subu    t0,1
  82.     b    .next
  83.     nop   

  84.     /*  
  85.      * READ(ADDR)
  86.      */
  87. 8:    bne    t4, OP_RD, 8f        /* OP_RD is 0x00000010 */
  88.     nop
  89.     and    t4, t3, MOD_MASK    /* MOD_MASK is 0x00000003 */

  90.     bne    t4, MOD_B, 1f        /* MOD_B is 0x00000000 ??? why not 0x01 or 0x03 */
  91.     nop
  92.     lbu    t5, 0(t0)
  93.     b    .next
  94.     nop
  95. 1:    bne    t4, MOD_H, 1f        /* MOD_H is 0x00000001 ??? why not 0x02 */
  96.     nop
  97.     lhu    t5, 0(t0)
  98.     b    .next
  99.     nop
  100. 1:    bne    t4, MOD_W, 1f        /* MOD_H is 0x00000002 ??? why not 0x00 */
  101.     nop
  102. #if __mips64
  103.     lwu    t5, 0(t0)
  104. #else
  105.     lw    t5, 0(t0)
  106. #endif
  107.     b    .next
  108.     nop
  109. 1:   
  110. #if __mips64
  111.     lw    t5,0(t0)
  112.     b    .next
  113.     nop
  114. #else
  115.     b    .fatal
  116.     nop
  117. #endif

  118.     /*
  119.      * WRITE(ADDR,VAL)
  120.      */
  121. 8:    bne    t4, OP_WR, 8f        /* OP_WR is 0x00000014 */
  122.     nop
  123.     lw    t1, Init_A1(a0)            /* Init_A1 is 8 */
  124.     and    t4, t3, MOD_MASK    /* MOD_MASK is 0x00000003 */

  125.     bne    t4, MOD_B, 1f
  126.     nop
  127.     sb    t1, 0(t0)
  128.     b    .next
  129.     nop
  130. 1:    bne    t4,MOD_H,1f
  131.     nop
  132.     sh    t1,0(t0)
  133.     b    .next
  134.     nop
  135. 1:    bne    t4,MOD_W,1f
  136.     nop
  137.     sw    t1,0(t0)
  138.     b    .next
  139.     nop

  140. 1:   
  141. #if __mips64
  142.     sd    t1,0(t0)
  143.     b    .next
  144.     nop
  145. #else
  146.     b    .fatal
  147.     nop
  148. #endif

  149.     /*
  150.      * RMW(ADDR,AND,OR)
  151.      */
  152. 8:    bne    t4,OP_RMW,8f
  153.     nop
  154.     lw    t1,Init_A1(a0)
  155.     lw    t2,Init_A2(a0)
  156.     and    t4,t3,MOD_MASK

  157.     bne    t4,MOD_B,1f
  158.     nop
  159.     lbu    t4,0(t0)
  160.     and    t4,t1
  161.     or    t4,t2
  162.     sb    t4,0(t0)
  163.     b    .next
  164.     nop
  165. 1:    bne    t4,MOD_H,1f
  166.     nop
  167.     lhu    t4,0(t0)
  168.     and    t4,t1
  169.     or    t4,t2
  170.     sh    t4,0(t0)
  171.     b    .next
  172.     nop
  173. 1:    bne    t4,MOD_W,1f
  174.     nop
  175.     lw    t4,0(t0)
  176.     and    t4,t1
  177.     or    t4,t2
  178.     sw    t4,0(t0)
  179.     b    .next
  180.     nop

  181. 1:        
  182. #if __mips64
  183.     ld    t4,0(t0)
  184.     and    t4,t1
  185.     or    t4,t2
  186.     sd    t4,0(t0)
  187.     b    .next
  188.     nop
  189. #else   
  190.     b    .fatal
  191.     nop
  192. #endif

  193.     /*
  194.      * WAIT(ADDR,MASK,VAL)
  195.      */
  196. 8:    bne    t4,OP_WAIT,8f
  197.     nop
  198.     lw    t1,Init_A1(a0)
  199.     lw    t2,Init_A2(a0)
  200.     and    t4,t3,MOD_MASK

  201.     bne    t4,MOD_B,1f
  202.     nop
  203. 3:    lbu    t4,0(t0)
  204.     and    t4,t1
  205.     bne    t4,t2,3b
  206.     nop
  207.     b    .next
  208.     nop
  209. 1:    bne    t4,MOD_H,1f
  210.     nop
  211. 3:    lhu    t4,0(t0)
  212.     and    t4,t1
  213.     bne    t4,t2,3b
  214.     nop
  215.     b    .next
  216.     nop
  217. 1:    bne    t4,MOD_W,1f
  218.     nop
  219. 3:    lw    t4,0(t0)
  220.     and    t4,t1
  221.     bne    t4,t2,3b
  222.     nop
  223.     b    .next
  224.     nop
  225. 1:        
  226. #if __mips64
  227. 3:    ld    t4,0(t0)
  228.     and    t4,t1
  229.     bne    t4,t2,3b
  230.     nop
  231.     b    .next
  232.     nop
  233. #else   
  234.     b    .fatal   
  235.     nop
  236. #endif

  237. .next:   
  238.     addu    a0, Init_Size        /* Init_Size is 16 */
  239.     b    reginit                /* a big repeatation */
  240.     nop   

  241. 8:
  242. .fatal:   
  243.     b .done
  244.     nop

  245.     bal stuck                /* these two sentences seem been ignored */
  246.     nop

  247. =====================        
  248. 解释:
  249. locate:
  250.     la        s0, start               
  251.     subu    s0, ra, s0               
  252.     and        s0, 0xffff0000        
  253. 此时,ra 中的地址值是前面 uncached 标号的地址,第二句作用是计算前面跳转时已运行过的代码的长度,最后一句把零头截掉。
  254. 这段代码是为了访问数据,因为这段汇编在Rom执行,而编译出来的数据段在 0x8002xxxx,
  255. 为了能够访问数据段的数据,需要进行一个地址的修正,s0 正是起到这种修正的目的。

  256.     li        t0, SR_BOOT_EXC_VEC
  257.     mtc0    t0, COP_0_STATUS_REG
  258.     mtc0    zero, COP_0_CAUSE_REG   
  259. 为保险起见,再清理一遍配置寄存器

  260.     .set noreorder
  261.     /* the varible bonito is register s4, BONITO_REG_BASE is 0x1fe00000 */
  262.      li        bonito, PHYS_TO_UNCACHED(BONITO_REG_BASE)  

  263.     bal    1f   
  264.     nop            /* now the value of ra is 0xbfc00xxx */
  265. 将 BONITO_REG_BASE 的物理地址值保存到 s4 寄存器
  266. (通过映射到未经缓存的地址空间里,龙芯 CPU 访问外部空间,只能用映射后的地址),
  267. 然后跳转到后面1标号处执行。

  268. 1:    move a0, ra        /* now the value of ra is 0xbfc00xxx */
  269. reginit:            /* local name */
  270.     lw    t3, Init_Op(a0)
  271.     lw    t0, Init_A0(a0)        // Init_A0 is 4
  272.     and    t4, t3, OP_MASK        // OP_MASK is 0x000000fc, to keep 4 bytes aligned
  273. 在1标号的地方,取跳转时压入的RA寄存器的值,然后通过寄存器相对寻址的方式,取得跳转指令后面保存的参数,并保存到t3, t0寄存器。

  274. 上句说的就是这些参数
  275.     /* bonito endianess */
  276.     BONITO_BIC(BONITO_BONPONCFG, BONITO_BONPONCFG_CPUBIGEND)
  277.     BONITO_BIC(BONITO_BONGENCFG, BONITO_BONGENCFG_BYTESWAP|BONITO_BONGENCFG_MSTRBYTESWAP)
  278.     BONITO_BIS(BONITO_BONPONCFG, BONITO_BONPONCFG_IS_ARBITER)

  279.     /*
  280.      * In certain situations it is possible for the Bonito ASIC
  281.      * to come up with the PCI registers uninitialised, so do them here
  282.      */
  283.     BONITO_INIT(BONITO_PCICLASS,(PCI_CLASS_BRIDGE << PCI_CLASS_SHIFT) | (PCI_SUBCLASS_BRIDGE_HOST << PCI_SUBCLASS_SHIFT))
  284.     BONITO_INIT(BONITO_PCICMD, BONITO_PCICMD_PERR_CLR | BONITO_PCICMD_SERR_CLR | BONITO_PCICMD_MABORT_CLR | BONITO_PCICMD_MTABORT_CLR | BONITO_PCICMD_TABORT_CLR | BONITO_PCICMD_MPERR_CLR )
  285.     //BONITO_INIT(BONITO_PCILTIMER, 0)
  286.     BONITO_INIT(BONITO_PCILTIMER, 255)
  287.     BONITO_INIT(BONITO_PCIBASE0, 0)
  288.     BONITO_INIT(BONITO_PCIBASE1, 0)
  289.     BONITO_INIT(BONITO_PCIBASE2, 0)
  290.     BONITO_INIT(BONITO_PCIEXPRBASE, 0)
  291.     BONITO_INIT(BONITO_PCIINT, 0)

  292.     BONITO_BIS(BONITO_PCICMD, BONITO_PCICMD_PERRRESPEN)

  293.     BONITO_BIS(BONITO_PCICMD, PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE|PCI_COMMAND_MASTER_ENABLE)

  294.     BONITO_BIC(BONITO_BONGENCFG, 0x80)  #½ûÖ¹iobc

  295.     #BONITO_BIS(BONITO_BONGENCFG, BONITO_BONGENCFG_BUSERREN)

  296.     /* Set debug mode */
  297.     BONITO_BIS(BONITO_BONGENCFG, BONITO_BONGENCFG_DEBUGMODE)

  298.     /******** added to init southbridge*/
  299. #ifdef VGA_NOTEBOOK_V2
  300.     ISA_BRMW_INIT(0,0x74,0xeb,0x0)
  301.     ISA_BRMW_INIT(0,0x75,0xff,0x20)
  302.     ISABWWR_INIT(4,0x48,0xb000)
  303.     ISABBWR_INIT(4,0x41,0x80)

  304.     RMW_INIT(MOD_W,(PCI_IO_SPACE+0xb04c),0xffffffdf,0x0)
  305. #endif

  306.     // SouthBridge settings

  307.     /* Set the SMB base address */
  308.     ISABWWR_INIT(4, SMBUS_IO_BASE_ADDR, SMBUS_IO_BASE_VALUE | 0x1)
  309.     /* enable the host controller */
  310.     ISABHWR_INIT(4, SMBUS_HOST_CONFIG_ADDR, SMBUS_HOST_CONFIG_ENABLE_BIT)
  311.     /* enable the SMB IO ports */
  312.     ISABBWR_INIT(4, PCI_COMMAND_STATUS_REG, PCI_COMMAND_IO_ENABLE)

  313.     ISARD_INIT(CTC_PORT+PT_CONTROL)

  314.     /* program i8254 ISA refresh counter */
  315.     ISAWR_INIT(CTC_PORT+PT_CONTROL,PTCW_SC(PT_REFRESH)|PTCW_16B|PTCW_MODE(MODE_RG))
  316.     ISAWR_INIT(CTC_PORT+PT_REFRESH, ISAREFRESH & 0xff)
  317.     ISAWR_INIT(CTC_PORT+PT_REFRESH, ISAREFRESH >> 8)

  318.         EXIT_INIT(0)
  319. 这些宏实际上不是语句,看定义后就知道它们只是定义了一些数据参数,在ROM中占据了一定的长度。

  320.     /*
  321.      * EXIT(STATUS)
  322.      */
  323.     bne    t4, OP_EXIT, 8f        // OP_EXIT is 0x00000000
  324.     nop
  325.     move v0, t0                // now v0 is the content of 4 bytes offset from 0xbfc000xx
  326.     b    .done
  327.     nop
  328. 接着就运行
  329. bne t4, OP_EXIT, 8f
  330. 这句了,在这里做是否初始化寄存器完成的判断,如果没有完成,就会跳到后面8标号处运行,然后经历一系列的设置(后面接着的那片代码)
  331. DELAY(CYCLES)
  332. READ(ADDR)
  333. WRITE(ADDR,VAL) RMW(ADDR,AND,OR)
  334. WAIT(ADDR,MASK,VAL)
  335. 后,直到 OP_EXIT 标志出现,才退出这个设置循环。看到前面有一行 EXIT_INIT(0),表示那个参数数据段结束了,它的宏定义如下:
  336. #define EXIT_INIT(status) .word OP_EXIT, (status); .word 0,0
  337. 所以在最后一项的数据记录被读取后,总是能退出这个初始化循环的,接着就会跳到.done这个标号里运行。

  338. 不过,这段代码到底是要设置什么?由DELAY,READ,WRITE,RMW,WAIT 这些符号所标示的代码段实现其相应的功能没有?我还不清楚。
复制代码

8

  1. la    s0, start            
  2. subu    s0, ra, s0
  3. and    s0, 0xffff0000

  4. 这段代码是为了访问数据,因为这段汇编在Rom执行,而编译出来的数据段在0x8002xxxx,为了能够访问数据段的数据,需要进行一个地址的修正,s0这是起到这种修正的目的。
复制代码

  1. la      v0, initmips
  2. jalr    v0
  3. nop

  4. 从此代码便到内存中间去了,从这开始因为可以读写内存,所以有了栈,故可以用C的代码了,所以以后的程序便是C代码了.
复制代码

4

  1. 接着看下面一段代码

  2. .done:   
  3.     bal superio_init        /* initialize the southbridge config register */
  4.     nop

  5.     bal    initserial            /* initialize the output of serial port, after this step */
  6.     nop                        /* pmon can output some infomations from COM port*/

  7.     PRINTSTR("\r\nPMON2000 MIPS Initializing. Standby...\r\n")

  8.     /* begin to check some config registers on CP0 */
  9.     PRINTSTR("ERRORPC=")
  10.     mfc0    a0, COP_0_ERROR_PC
  11.     bal    hexserial
  12.     nop

  13.     PRINTSTR(" CONFIG=")
  14.     mfc0    a0, COP_0_CONFIG
  15.     bal    hexserial
  16.     nop
  17.     PRINTSTR("\r\n")

  18.     PRINTSTR(" PRID=")
  19.     mfc0    a0, COP_0_PRID
  20.     bal    hexserial
  21.     nop
  22.     PRINTSTR("\r\n")

  23. =====================
  24. 解释:
  25. 在这段程序里,主要做了两件大事情,一是初始化南桥芯片VIA686B,一是初始化串口输出。
  26. 初始化VIA686B是调用子函数superio_init 实现的。初始化串口是调用子函数initserial实现的。
  27. 为了尽快地从串口输出调试信息,所以要先初始化VIA686B芯片,才能输出信息出来。
  28. 由于 VIA686B芯片包括所有外面接口的功能,比如串口, PS2,USB,并口,还有软盘等等。
  29. 只要能从串口输出字符,就已经是成功的第一步了。
  30. 在嵌入式的软件开发中,调试软件是最难的,只能根据芯片的管脚电平,或者串口发些调信息出来。
  31. 使用管脚调试,最简单的办法,就是加一个指示灯,这也叫“点灯大法”。
  32. 只要串口能输出字符串后,使用串口调试就成为基本的方法了。
  33. 后面,输出三个CP0寄存器的值,第一个寄存器是出错信息,第二个寄存器是CP0配置信息,第三个寄存器是CP0处理器的ID信息。
  34. =====================
复制代码

5

下面一段代码从内存条上的SPD(eeprom)中读取内存参数,并且初始化内存窗口。这段代码放到另一篇文章中专门讲解吧。这里就不多说了。

  1. /*
  2.      * Now determine DRAM configuration and size by
  3.      * reading the I2C EEROM (SPD) on the DIMMS (DDR)
  4.      */
  5.     PRINTSTR("DIMM read\r\n")

  6.     /* only one memory slot, slave address is 10100001b */
  7.     li  a1, 0x0
  8. 1:
  9.     li    a0, 0xa1    /* a0: slave address, a1: reg index to read */
  10.     bal    i2cread
  11.     nop

  12.         /* save a1 */
  13.     move t1, a1

  14.     /* print */
  15.     move a0, v0
  16.     bal  hexserial
  17.     nop

  18.     PRINTSTR("\r\n")   

  19.         /* restore a1 */
  20.     move  a1,t1
  21.     addiu a1,a1,1
  22.     li   v0, 0x20
  23.     bleu  a1, v0, 1b        /* repeat for 32 times */
  24.     nop

  25.     li    msize, 0            /* msize is register s2 */
  26.     /* set some parameters for DDR333
  27.         rank number and DDR type field will be filled later
  28.         to check: fix TCAS?
  29.     */
  30.     li    sdCfg, 0x341043df        /* sdCfg is register s6 */

  31.     /* read DIMM memory type (must be DDRAM) */
  32. #if 0
  33.     li    a0,0xa1
  34.     li    a1,2
  35.     bal    i2cread
  36.     nop
  37.     bne    v0,7,.nodimm
  38.     nop
  39.     PRINTSTR("read memory type\r\n")
  40. #endif

  41.     /* read DIMM number of rows */
  42.     li    a0, 0xa1
  43.     li    a1, 3
  44.     bal    i2cread
  45.     nop   
  46.     move    a0, v0        // v0 is the return value register
  47.     subu    v0, 12
  48.     move    s1, v0        // save for later use

  49.     bgtu    v0, 2, .nodimm        // if v0 > 2 then jump to .nodimm
  50.     nop
  51.     PRINTSTR("read number of rows\r\n")

  52. 2:    /* read DIMM number of cols */
  53.     li    a0, 0xa1
  54.     li    a1, 4
  55.     bal    i2cread
  56.     nop

  57.     subu    v0, 8                // v0 saved the return value
  58.     bgtu    v0, 4, .nodimm
  59.     nop

  60.     // read and check ddr type, the combination of t1 and v0 represents a ddr type
  61.     move    t1, s1
  62.     bne    t1, 0, 10f
  63.     nop
  64.     bne    v0, 2, 20f
  65.     nop
  66.     li    v0, 0
  67.     b    .ddrtype
  68.     nop
  69. 20:    bne    v0, 1, 21f
  70.     nop
  71.     li    v0, 1
  72.     b    .ddrtype
  73.     nop
  74. 21:    bne    v0, 0, 22f
  75.     nop
  76.     li    v0, 2
  77.     b    .ddrtype
  78.     nop
  79. 22:    bne    v0, 3, 33f
  80.     nop
  81.     li    v0, 3
  82.     b    .ddrtype
  83.     nop
  84. 10:    bne    t1, 1, 11f
  85.     nop
  86.     bne    v0, 3, 20f
  87.     nop
  88.     li    v0, 4
  89.     b    .ddrtype
  90.     nop
  91. 20:    bne    v0, 2, 21f
  92.     nop
  93.     li    v0, 5
  94.     b    .ddrtype
  95.     nop
  96. 21:    bne    v0, 1, 22f
  97.     nop
  98.     li    v0, 6
  99.     b    .ddrtype
  100.     nop
  101. 22:    bne    v0, 4, 33f
  102.     nop
  103.     li    v0, 7
  104.     b    .ddrtype
  105.     nop
  106. 11:    bne    t1, 2, 33f
  107.     nop
  108.     bne    v0, 4, 20f
  109.     nop
  110.     li    v0, 8
  111.     b    .ddrtype
  112.     nop
  113. 20:    bne    v0, 3, 21f
  114.     nop
  115.     li    v0, 9
  116.     b    .ddrtype
  117.     nop
  118. 21:    bne    v0, 2, 33f
  119.     nop
  120.     li    v0, 10
  121.     b    .ddrtype
  122.     nop
  123. 33:    PRINTSTR("DDR type not supported!\r\n");
  124. 34:    b    34b
  125.     nop

  126. .ddrtype:
  127.     #bit 25:22 is DDR type field
  128.     sll    v0, 22
  129.     and    v0, 0x03c00000
  130.     or    sdCfg, v0

  131.     /* read DIMM memory size per side */
  132.     li    a0, 0xa1
  133.     li    a1, 31
  134.     bal    i2cread
  135.     nop
  136.     beqz    v0,.nodimm
  137.     nop
  138.     sll    tmpsize,v0,22        # multiply by 4M
  139.     PRINTSTR("read memory size per side\r\n")

  140. 2:    /* read DIMM number of blocks-per-ddrram */
  141.     li    a1,17
  142.     bal    i2cread
  143.     nop
  144.     beq    v0,2,2f
  145.     nop
  146.     bne    v0,4,.nodimm
  147.     nop
  148.     PRINTSTR("read blocks per ddrram\r\n")

  149. 2:    /* read DIMM number of sides (banks) */
  150.     li    a1,5
  151.     bal    i2cread
  152.     nop
  153.     beq    v0,1,2f
  154.     nop
  155.     bne    v0,2,.nodimm
  156.     nop
  157.     sll    tmpsize,1    # msize *= 2   
  158.     or  sdCfg, 0x1<<27
  159.     PRINTSTR("read number of sides\r\n")

  160. 2:    /* read DIMM width */
  161.     li    a1,6
  162.     bal    i2cread
  163.     nop
  164.     bleu    v0,36,2f
  165.     nop
  166.     bgtu    v0,72,.nodimm
  167.     nop
  168.     PRINTSTR("read width\r\n")

  169. 2:    addu    msize,tmpsize
  170.     b    2f
  171.     nop   

  172. .nodimm:
  173.     move    dbg,a0        // dbg is s5
  174.     PRINTSTR ("\r\nNo DIMM in slot ")
  175.     move    a0,dbg
  176.     bal    hexserial
  177.     nop
  178.     PRINTSTR("\r\n")
  179.     move    a0,dbg
  180.     #li  msize,0x10000000
  181.     #li    sdCfg,0x3d9043df    #~133MHz
  182.     li  msize,0x20000000
  183.     li    sdCfg,0x3d5043df     #~133MHz

  184. 2:
  185.     PRINTSTR("DIMM SIZE=")
  186.     move    a0,msize
  187.     bal    hexserial
  188.     nop
  189.     PRINTSTR("\r\n")

  190.     li    t0, 0xbff00008
  191.     sd    sdCfg, 0(t0)
  192.     nop
  193.     nop

  194.     /* (uint32_t *)0xbfe00040 = 0x80000000
  195.      * means only address below 1G will be sent to CPU
  196.      */
  197.     lui    t0, 0xbfe0
  198.     li    t1, 0x80000000
  199.     sw    t1, 0x40(t0)
  200.     nop

  201.     #### gx 2006-03-17: mode ####
  202.     #li    t1,0x20
  203.     li    t1,0x28
  204.     li    t0, 0xbff00000
  205.     sd    t1,0(t0)
  206.     nop
  207.     li    t1,0x0
  208.     li    t0, 0xbff00000
  209.     sd    t1,0x30(t0)
  210.     nop

  211.     ##fixed base address reg##
  212.     sd    zero, 0x10(t0)
  213.     nop
  214.     lui    t1,0x2000
  215.     sd    t1,0x20(t0)
  216.     nop

  217.     li      t1, 0x10000000
  218.         blt     msize, t1, 1f
  219.     nop

  220.     ####bigger than 256MB####
  221.     sd    t1, 0x18(t0)
  222.     nop
  223.     move    a0, msize
  224.     subu    a0, t1
  225.     nop
  226.     nop
  227.     nop
  228.     sd    a0, 0x28(t0)
  229.     nop
  230.     b    2f

  231. 1:
  232.     nop
  233.     nop
  234.     sd    msize, 0x18(t0)
  235.     nop
  236.     nop
  237.     nop
  238.     sd    zero, 0x28(t0)
  239.     nop
  240.     nop
  241.     nop

  242. 2:
  243.     PRINTSTR("sdcfg=");
  244.     move    a0,sdCfg
  245.     bal    hexserial
  246.     nop
  247.     PRINTSTR("\r\n");
  248.     PRINTSTR("msize=");
  249.     move    a0,msize
  250.     bal    hexserial
  251.     nop
  252.     PRINTSTR("\r\n")

  253. skipdimm:

  254.     li    t1,0        # accumulate pcimembasecfg settings

  255.     /* set bar0 mask and translation to point to SDRAM */
  256.     sub    t0,msize,1
  257.     not    t0
  258.     srl    t0,BONITO_PCIMEMBASECFG_ASHIFT-BONITO_PCIMEMBASECFG_MEMBASE0_MASK_SHIFT
  259.     and    t0,BONITO_PCIMEMBASECFG_MEMBASE0_MASK
  260.     or    t1,t0

  261.     li    t0,0x00000000
  262.     srl    t0,BONITO_PCIMEMBASECFG_ASHIFT-BONITO_PCIMEMBASECFG_MEMBASE0_TRANS_SHIFT
  263.     and    t0,BONITO_PCIMEMBASECFG_MEMBASE0_TRANS
  264.     or    t1,t0
  265.     or    t1,BONITO_PCIMEMBASECFG_MEMBASE0_CACHED

  266.     /* set bar1 to minimum size to conserve PCI space */
  267.     li    t0, ~0
  268.     srl    t0,BONITO_PCIMEMBASECFG_ASHIFT-BONITO_PCIMEMBASECFG_MEMBASE1_MASK_SHIFT
  269.     and    t0,BONITO_PCIMEMBASECFG_MEMBASE1_MASK
  270.     or    t1,t0

  271.     li    t0,0x00000000
  272.     srl    t0,BONITO_PCIMEMBASECFG_ASHIFT-BONITO_PCIMEMBASECFG_MEMBASE1_TRANS_SHIFT
  273.     and    t0,BONITO_PCIMEMBASECFG_MEMBASE1_TRANS
  274.     or    t1,t0
  275.     or    t1,BONITO_PCIMEMBASECFG_MEMBASE1_CACHED

  276.     sw    t1,BONITO_PCIMEMBASECFG(bonito)

  277.     /* enable configuration cycles now */
  278.     lw    t0,BONITO_BONPONCFG(bonito)
  279.     and    t0,~BONITO_BONPONCFG_CONFIG_DIS
  280.     sw    t0,BONITO_BONPONCFG(bonito)

  281.     PRINTSTR("Init SDRAM Done!\r\n");
复制代码

6

下面这段是缓存配置的代码

  1. /*
  2. *  Reset and initialize caches to a known state.
  3. */
  4. #define IndexStoreTagI    0x08
  5. #define IndexStoreTagD    0x09
  6. #define IndexStoreTagS    0x0b
  7. #define IndexStoreTagT    0x0a
  8. #define FillI        0x14

  9. /*
  10. *  caches config register bits.
  11. */
  12. #define CF_7_SE         (1 << 3)        /* Secondary cache enable */
  13. #define CF_7_SC         (1 << 31)       /* Secondary cache not present */
  14. #define CF_7_TE         (1 << 12)       /* Tertiary cache enable */
  15. #define CF_7_TC         (1 << 17)       /* Tertiary cache not present */
  16. #define CF_7_TS         (3 << 20)       /* Tertiary cache size */
  17. #define CF_7_TS_AL      20              /* Shift to align */
  18. #define NOP8 nop;nop;nop;nop;nop;nop;nop;nop
  19. do_caches:
  20.     TTYDBG("Sizing caches...\r\n");

  21.     mfc0    t3, COP_0_CONFIG    /* t3 = original config */
  22.     and    t3, 0xffffeff0        /* Make sure coherency is OK */

  23.     and    t3, ~(CF_7_TE|CF_7_SE|CF_7_TC|CF_7_SC)  /* disable L2/L3 cache */
  24.     mtc0    t3, COP_0_CONFIG

  25.     li    t2, 4096

  26.     srl    t1, t3, 9
  27.     and    t1, 3
  28.     sllv    s3, t2, t1        /* s3 = I cache size */

  29. #ifdef CONFIG_CACHE_64K_4WAY
  30.         sll     s3,2
  31. #endif

  32.     and    t1, t3, 0x20
  33.     srl    t1, t1, 1
  34.     addu    s4, t1, 16        /* s4 = I cache line size */

  35.     srl    t1, t3, 6
  36.     and    t1, 3
  37.     sllv    s5, t2, t1        /* s5 = D cache size */

  38. #ifdef CONFIG_CACHE_64K_4WAY
  39.         sll     s5,2
  40. #endif

  41.     and    t1, t3, 0x10
  42.     addu    s6, t1, 16        /* s6 = D cache line size */
  43.     TTYDBG("Init caches...\r\n")

  44.     li    s7, 0                   /* no L2 cache */
  45.     li    s8, 0                   /* no L3 cache */

  46. #if 0
  47.         mfc0    a0, COP_0_PRID
  48.         li      a1, 0x6301
  49.         bne     a0,a1,1f
  50.         nop
  51. #endif
  52.     TTYDBG("godson2 caches found\r\n")
  53.         bal     godson2_cache_init
  54.         nop
  55. #####xuhua########open cp1
  56. #if 1
  57.         mfc0   t0,COP_0_STATUS_REG
  58.           and    t0,0xdbffffff
  59.          or     t0,t0,0x24000000
  60.         mtc0   t0,COP_0_STATUS_REG
  61. #endif
  62. #################

  63.     /* close L2 cache */
  64.     li      a0, 0xbfe00164
  65.         sw      zero, 0(a0);

  66.         mfc0   a0,COP_0_CONFIG
  67.         and    a0,a0,~((1<<12) | 3)
  68.     or     a0,a0,2
  69.         mtc0   a0,COP_0_CONFIG

  70. #ifdef DEBUG_LOCORE
  71.     TTYDBG("Init caches done, cfg = ")
  72.     mfc0    a0, COP_0_CONFIG
  73.     bal    hexserial
  74.     nop
  75.     TTYDBG("\r\n\r\n")
  76. #endif
复制代码

7

下面这段代码是把PMON自身从ROM中拷贝到RAM中去

  1. // copy self code segment
  2.     TTYDBG("Copy PMON to execute location...\r\n")
  3. #ifdef DEBUG_LOCORE
  4.     TTYDBG("  start = 0x")
  5.     la    a0, start
  6.     bal    hexserial
  7.     nop
  8.     TTYDBG("\r\n  s0 = 0x")
  9.     move    a0, s0
  10.     bal    hexserial
  11.     nop
  12.     TTYDBG("\r\n")
  13. #endif
  14.     la    a0, start
  15.     li    a1, 0xbfc00000
  16.     la    a2, _edata
  17.         or      a0, 0xa0000000
  18.         or      a2, 0xa0000000
  19.     subu    t1, a2, a0
  20.     srl    t1, t1, 2

  21.     move    t0, a0
  22.     move    t1, a1
  23.     move    t2, a2

  24.     /* copy text section */

  25. 1:    and    t3,t0,0x0000ffff
  26.     bnez    t3,2f
  27.     nop
  28.     move    a0,t0
  29.     bal    hexserial
  30.     nop
  31.     li    a0,'\r'
  32.     bal     tgt_putchar
  33.     nop
  34. 2:    lw    t3, 0(t1)
  35.     nop
  36.     sw    t3, 0(t0)
  37.     addu    t0, 4
  38.     addu    t1, 4
  39.     bne    t2, t0, 1b
  40.     nop

  41.     PRINTSTR("\ncopy text section done.\r\n")

  42.     /* Clear BSS */
  43.     la    a0, _edata
  44.     la    a2, _end
  45. 2:    sw    zero, 0(a0)
  46.     bne    a2, a0, 2b
  47.     addu    a0, 4

  48.     TTYDBG("Copy PMON to execute location done.\r\n")
复制代码

@@@

下面这段代码从汇编世界跳到C世界中去了。

  1. TTYDBG("sp=");
  2.     move a0, sp
  3.     bal    hexserial
  4.     nop

  5. #if 1
  6.         mfc0   a0,COP_0_CONFIG
  7.         and    a0,a0,0xfffffff8
  8.         or     a0,a0,0x3
  9.         mtc0   a0,COP_0_CONFIG
  10. #endif

  11.     li    a0, 4096*1024
  12.     sw    a0, CpuTertiaryCacheSize /* Set L3 cache size */
  13.     move    a0,msize
  14.     srl    a0,20

  15.         /* pass pointer to kseg1 tgt_putchar */
  16.         la  a1, tgt_putchar
  17.     addu a1,a1,s0            // la    s0,start
  18.                             // subu    s0,ra,s0            ??? ra is the returning address
  19.                             // and    s0,0xffff0000        ??? now what does s0 mean?

  20.         la  a2, stringserial
  21.     addu a2,a2,s0

  22.     la    v0, initmips        // further ENTRY of PMON
  23.     jalr    v0
  24.     nop
复制代码


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
=====================================
这是一条神奇的小尾巴~~~~~
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|龙芯俱乐部开源技术社区

GMT+8, 2024-11-28 07:40 , Processed in 0.153332 second(s), 22 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表