原创

龙芯软件开发(18)-- 乾坤大挪移,从ROM到RAM

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://mysoft.blog.csdn.net/article/details/1474252
前面已经初始化内存和龙芯的缓存,那么现在已经差不多把新房子已经建立好了,要进入新房居住了。在SDRAM里的存取速度比ROM里快很多,并且可以随时修改数据,而在ROM是不能修改的,就算可以修改,也是非常慢的。
从上面初始化缓存回来后,就运行到下面的程序:
#####xuhua########open cp1
#if 1
        mfc0   t0,COP_0_STATUS_REG
      and    t0,0xdbffffff
      or     t0,t0,0x24000000
       mtc0   t0,COP_0_STATUS_REG
#endif
#################
上面的程序打开了CP1处理器,也就是浮点处理器。先从状态寄存器里取得32位中高4位的协处理器状态,然后先用通过0x2400 0000来打开浮点协处理器,把值改写回到状态寄存器。
 
/* close L2 cache */
    li      a0, 0xbfe00164
        sw      zero, 0(a0);
 
        mfc0   a0,COP_0_CONFIG
        and    a0,a0,~((1<<12) | 3)
    or     a0,a0,2
        mtc0   a0,COP_0_CONFIG
上面的程序关闭了二级缓存。
 
TTYDBG("Copy PMON to execute location.../r/n")
#ifdef DEBUG_LOCORE
    TTYDBG(" start = 0x")
    la a0, start
    bal hexserial
    nop
    TTYDBG("/r/n s0 = 0x")
    move   a0, s0
    bal hexserial
    nop
    TTYDBG("/r/n")
#endif
上面的代码是调试时显示当前ROM开始地址。
 
    la a0, start
    li a1, 0xbfc00000
    la a2, _edata
        or      a0, 0xa0000000
        or      a2, 0xa0000000
    subu   t1, a2, a0
    srl t1, t1, 2
 
    move   t0, a0
    move   t1, a1
    move   t2, a2
上面的代码是计算ROM里的代码开始位置和代码的长度,以及RAM里的开始。a0保存要RAM的开始地址0xa001 0000, a1保存ROM的开始地址0xbfc0 0000a2保存RAM里的结束地址。
 
    /* copy text section */
   
1: and t3,t0,0x0000ffff
    bnez   t3,2f
    nop
    move   a0,t0
    bal hexserial
    nop
    li a0,'/r'
    bal    tgt_putchar
    nop
2: lw t3, 0(t1)
    nop
    sw t3, 0(t0)
    addu   t0, 4
    addu   t1, 4
    bne t2, t0, 1b
    nop
上面的代码是首先显示拷贝的字符,然后在2标号那里用lwROM读取4字节数据,接着在后面用sw保存4字节数据到RAM里,最后判断是否拷贝数据完成。
 
    PRINTSTR("/ncopy text section done./r/n")
   
    /* Clear BSS */
    la a0, _edata
    la a2, _end
2: sw zero, 0(a0)
    bne a2, a0, 2b
    addu   a0, 4
 
    TTYDBG("Copy PMON to execute location done./r/n")
上面的代码是清空数据区。
 
TTYDBG("sp=");
    move a0, sp
    bal hexserial
    nop
 
#if 1
        mfc0   a0,COP_0_CONFIG
        and    a0,a0,0xfffffff8
        or     a0,a0,0x3
        mtc0   a0,COP_0_CONFIG
#endif
 
 
    li a0, 4096*1024
    sw a0, CpuTertiaryCacheSize /* Set L3 cache size */
上面的代码显示栈的位置,然后设置配置寄存里的kseg0的一致性算法。最后就是保存三级缓存的大小到变量里。
 
move   a0,msize
    srl a0,20
 
    /* pass pointer to kseg1 tgt_putchar */
    la a1, tgt_putchar
    addu a1,a1,s0
 
    la a2, stringserial
    addu a2,a2,s0
 
    la v0, initmips
    jalr   v0
    nop
上面代码先把内存大小msize放到参数0里,把输出字符函数指针放到参数1里,把字符串输出函数指针放到参数2里,然后取得C函数initmips入口地址,直接跳到那里运行,永远不再返回来。不过,后面还有一段防止出错的代码,如下:
 
stuck:
#ifdef DEBUG_LOCORE
    TTYDBG("Dumping GT64240 setup./r/n")
    TTYDBG("offset----data------------------------./r/n")
    li s3, 0
1:
    move   a0, s3
    bal hexserial
    nop
    TTYDBG(": ")
2:
    add a0, s3, bonito
    lw a0, 0(a0)
    bal hexserial
    addiu s3, 4
    TTYDBG(" ")
    li a0, 0xfff
    and a0, s3
    beqz   a0, 3f
    li a0, 0x01f
    and a0, s3
    bnez   a0, 2b
    TTYDBG("/r/n")
    b   1b
    nop
3:
    b   3b
    nop
 
#else
    b   stuck
    nop
#endif
 
上面主要是调试的代码,其实就是一个死循环在那里。
到这里,就已经把汇编代码看完了,进入到C的世界,就是更加方便编程和理解了,尽可能写更多的C代码,减少BUG的出现。
 
展开阅读全文

没有更多推荐了,返回首页