龙芯软件开发 - - 蔡军生

2026/4/29 4:01:29

2: lw t3, 0(t1) nop

sw t3, 0(t0) addu t0, 4 addu t1, 4 bne t2, t0, 1b nop

上面的代码是首先显示拷贝的字符,然后在2标号那里用lw从ROM读取4字节数据,接着在后面用sw保存4字节数据到RAM里,最后判断是否拷贝数据完成。

PRINTSTR(\

/* Clear BSS */ la a0, _edata la a2, _end 2: sw zero, 0(a0) bne a2, a0, 2b addu a0, 4

TTYDBG(\上面的代码是清空数据区。

TTYDBG(\ 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

37

la v0, initmips jalr v0 nop

上面代码先把内存大小msize放到参数0里,把输出字符函数指针放到参数1里,把字符串输出函数指针放到参数2里,然后取得C函数initmips入口地址,直接跳到那里运行,永远不再返回来。不过,后面还有一段防止出错的代码,如下:

stuck:

#ifdef DEBUG_LOCORE

TTYDBG(\

TTYDBG(\ 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(\ b 1b nop 3:

b 3b nop #else

b stuck nop #endif

上面主要是调试的代码,其实就是一个死循环在那里。

到这里,就已经把汇编代码看完了,进入到C的世界,就是更加方便编程和理解了,尽可能写更多的C代码,减少BUG的出现。

龙芯软件开发(19)-- C函数入口

经历了漫长的汇编之路,最终走到光明的C世界了,进入高级语言环境,会让开发更方便,写更少的语句就可以实现更多的功能。从这里开始,就初始化PCI局部线所有设备,初始化南桥所有的功能,初始化IDE硬盘,初始化网络,初始化显示卡,并进入响应命令阶段。

38

下面就来分析C函数部份功能,当然它还有时需要调用汇编子函数才能实现特殊的功能。 从上次分析移动代码里,就知道代码已经移到0x8000 0000开始运行了。 void

initmips(unsigned int memsz) {

/*

* Set up memory address decoders to map entire memory. * But first move away bootrom map to high memory. */ #if 0

GT_WRITE(BOOTCS_LOW_DECODE_ADDRESS, BOOT_BASE >> 20);

GT_WRITE(BOOTCS_HIGH_DECODE_ADDRESS, (BOOT_BASE - 1 + BOOT_SIZE) >> 20); #endif

memorysize = memsz > 256 ? 256 << 20 : memsz << 20;

memorysize_high = memsz > 256 ? (memsz - 256) << 20 : 0;

上面代码,由于在汇编里就已经设置好三个参数,第一个参数为内存的大小,并且单位是字节。汇编代码如下:

move a0,msize srl a0,20

memorysize就保存低端内存的大小,小于或等256M。memorysize_high保存高于256M的内存大小。这样就知道系统内存的大小了。 #if 0 {

int start = 0x80000000;

int end = 0x80000000 + 16384;

while (start < end) {

__asm__ volatile (\ \ \ \

\ start += 32; }

__asm__ volatile ( \

\ \

\ } #endif

/*

* Probe clock frequencys so delays will work properly. */

tgt_cpufreq();

这里实现CPU频率的设置和检测。

SBD_DISPLAY(\

39

/*

* Init PMON and debug */

cpuinfotab[0] = &DBGREG; dbginit(NULL);

上面函数实现调试和大部份的功能初始化。

/*

* Set up exception vectors. */

SBD_DISPLAY(\

bcopy(MipsException, (char *)TLB_MISS_EXC_VEC, MipsExceptionEnd - MipsException); bcopy(MipsException, (char *)GEN_EXC_VEC, MipsExceptionEnd - MipsException); 上面代码实现异常向量的设置。

CPU_FlushCache(); 上面代码重新初始化缓存。

CPU_SetSR(0, SR_BOOT_EXC_VEC);

上面代码设置状态寄存器,可以执行异常处理了,启动模式已经结束,进入正常模式运行。

SBD_DISPLAY(\

printf(\ #if 0

/* memtest */ addr_tst1(); addr_tst2(); movinv1(2,0,~0);

movinv1(2,0xaa5555aa,~0xaa5555aa); printf(\#endif

/*

* Launch! */ main();

上面就进入命令交换阶段。 }

/*蔡军生 2007-1-5 于深圳*/

看C的代码,就是比看汇编简单多了,到这里,就已经看完了整个流程了。不过,在那些调用的函数里,还是实现非常复杂的功能的。比如显示卡,就是最复杂的部份,由于它的BIOS代码是为X86的CPU执行的,不能直接在龙芯2E里运行,这样就变得非常复杂了,因此龙芯2E里就要实现一个模拟X86的CPU功能才能运行显示卡的BIOS程序。不知道那天有了我们自己的显示卡厂商,才可能开发适用龙芯2E的显示卡BIOS,这样才会变得非常简单了。

40


龙芯软件开发 - - 蔡军生.doc 将本文的Word文档下载到电脑
搜索更多关于: 龙芯软件开发 - - 蔡军生 的文档
相关推荐
相关阅读
× 游客快捷下载通道(下载后可以自由复制和排版)

下载本文档需要支付 10

支付方式:

开通VIP包月会员 特价:29元/月

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信:xuecool-com QQ:370150219