PMON的解读和开发

提示:龙芯2K1000PMON相关记录

文章目录

  • [1 PMON的发展和编译环境](#1 PMON的发展和编译环境)
  • [2 PMON2000的目录结构](#2 PMON2000的目录结构)
  • [3 Targets目录的组成](#3 Targets目录的组成)
  • [4 PMON编译环境的建立](#4 PMON编译环境的建立)
  • [5 PMON2000的框架](#5 PMON2000的框架)
  • [6 异常向量表](#6 异常向量表)
  • [7 Pmon的空间分配](#7 Pmon的空间分配)
  • [8 PMON的汇编部分(starto.S或sbdreset.S)的解读](#8 PMON的汇编部分(starto.S或sbdreset.S)的解读)
  • [9 Bonito的空间分配](#9 Bonito的空间分配)
  • [10 PCI的空间分配](#10 PCI的空间分配)
  • 开发时需要注意的问题

1 PMON的发展和编译环境

PMON

  • 科大那个PMON就是这个版本的。该版本的功能有:shell, net, load, debug。不支持硬盘,显卡。并且扩展性不好。
  • 该版本的编译器是sde-gcc.

PMON2000

  • 现在龙芯1和2用的BIOS, 在原来的PMON的基础上添加了硬盘支持,文件系统ext2的支持,显卡的支持。修复了debug功能,扩展性也得到提高。比较容易移植到新的系统。
  • 编译器为mips-elf-gcc

2 PMON2000的目录结构



3 Targets目录的组成

每个系统一个目录,我们拿Bonito来为例子,主要有下列文件:

  • start.S 位于Targets/Bonito/Bonito目录下,是C环境建立之前的汇编代码,使整个BIOS运行的起点。
  • tgt_machdep.c位于Targets/Bonito/Bonito目录下,一些板子相关的函数。
  • pci_machdep.c进行Targets/Bonito/pci空间分配的一些函数
  • Targets/Bonito/dev目录下一些板子特殊的设备的驱动。
  • Targets/Bonito/conf目录下是一些编译环境建立需要的一些文件

4 PMON编译环境的建立

  • 将comp.tar.gz在/usr/local解开
  • 将/usr/local/comp/mips-elf/gcc-2.95.3/bin加入到PATH目录下
  • 进入pmon2000的tools目录下make,建立一些conf需要的工具。
  • 进入pmon2000的Targets/Bonito/conf目录中
  • 编辑conf目录下Bonito文件,选择需要编译的模块
  • tools/pmoncfg/pmoncfg Bonito(conf类型文件)。形成目标主目录下的compiler目录
  • 进入Targets/Bonito/compiler/Bonito的目录,make形成pmon。
  • Makefile是根据Targets/Bonito/conf/Makefile.Bonito文件形成的。
  • 链接脚本是为Targets/Bonito/conf/ld.script。

5 PMON2000的框架

6 异常向量表

7 Pmon的空间分配

8 PMON的汇编部分(starto.S或sbdreset.S)的解读

Start.S

当整个板子起电后,CPU将从0xBFC00000取指令开始执行,而ROM在系统中的地址就是从该地址开始的,所以其中的第一条指令就是整个CPU的第一个指令,在MIPS中,异常处理入口有两套,通过CP0的STATUS寄存器位BEV来决定,当BEV=1时,异常的入口地址为0xBFC00000开始的地址,而BEV=0,异常地址为0x80000000开始的地址,所以PMON程序段开始处是一些异常的调入口,需要跳过这段空间,程序通过一个跳转bal指令跳到后面.

c 复制代码
       bal     locate 
       nop
       bal		uncached
       nop
       bal		locate
       nop	
uncached:
        or      ra, UNCACHED_MEMORY_ADDR
        j       ra
        nop

此处是可以从cache空间转换到uncache的空间,ra中保留的是bal locate这条指令的地址,然后或上UNCACHED_MEMORY_ADDR,该地址就变成uncache的地址了.

c 复制代码
  la      s0, start            
  subu    s0, ra, s0
  and     s0, 0xffff0000 

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

  • 初始化CPU内的寄存器,清TLB.
  • 初始化一些北桥的基本配置,以确保uart能够正常工作.
  • 初始化uart,主要是设置波特率.
  • 初始化内存(主要通过I2C协议从内存的EEPROM读取内存参数来进行设置).
  • 初始化cache.
    拷贝pmon的代码到内存,然后通过
bash 复制代码
la      v0, initmips
jalr    v0
nop 

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

C代码部分

Ram中运行,入口为initmips

在文件Targets/Boniton/Bonito/tgt_machdep.c中

c 复制代码
void initmips(unsigned int memsz)
{
	...
	tgt_cpufreq();
	cpuinfotab[0] = &DBGREG;
        dbginit(NULL);
                                                                                                                              
	 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);
	main();
}

主要初始化在dbginit函数中执行。

dbginit

c 复制代码
 void dbginit (char *adr)
{
	__init();       /* Do all constructor initialisation */
	envinit ();                                                                                                                   
	tgt_devinit();                                                                                                                        
#ifdef INET
	init_net (1);
#endif                                                                                                                        
#if NCMD_HIST > 0
	histinit ();
#endif
#if NMOD_SYMBOLS > 0
	syminit ();
#endif
 #ifdef DEMO
	demoinit ();
#endif                                                                                                          
	initial_sr |= tgt_enable (tgt_getmachtype ());                                                                                                             
#ifdef SR_FR
        Status = initial_sr & ~SR_FR; /* don't confuse naive clients */
#endif
	ioctl(STDIN, TCGETA, &consterm);
...
...
...
}//gdbinit 
复制代码
 __init();初始化一些数据结构.
Envinit ();初始化环境变量.
tgt_init();初始化与板级相关的过程,在我们系统中主要是初始化北桥和PCI.
inet_init();初始化网络.
Hisinit();初始化命令历史记录.
Ioctl(STDIN,TCGETA,&consterm);建立终端.	

9 Bonito的空间分配

10 PCI的空间分配

tgt_devinit()

_pci_businit()

_pci_hwinit

pci_hwinit() 为Pmon主要初始化PCI在北桥的窗口的函数 ,这个函数在Target/Ev64240/pci/pci_machdep.c中定义

c 复制代码
    pd = pmalloc(sizeof(struct pci_device));
    pb = pmalloc(sizeof(struct pci_bus));                                                                                                                   
    pd->pa.pa_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED;
    pd->pa.pa_iot = pmalloc(sizeof(bus_space_tag_t));
    pd->pa.pa_iot->bus_reverse = 1;
    pd->pa.pa_iot->bus_base = PCI0_IO_SPACE_BASE - PCI0P_IO_SPACE_BASE;
    pd->pa.pa_memt = pmalloc(sizeof(bus_space_tag_t));
    pd->pa.pa_memt->bus_reverse = 1;
      
    pd->pa.pa_memt->bus_base = 0;
    pd->pa.pa_dmat = &bus_dmamap_tag;
    pd->bridge.secbus = pb;
    _pci_head = pd;
	pb->minpcimemaddr  = PCI0P_MEM_SPACE_BASE;
    pb->nextpcimemaddr = PCI0P_MEM_SPACE_BASE + PCI0_MEM_SPACE_SIZE;
    pb->minpciioaddr  = PCI0P_IO_SPACE_BASE;
    pb->nextpciioaddr = PCI0P_IO_SPACE_BASE + PCI0_IO_SPACE_SIZE;
    pb->pci_mem_base   = PCI0_MEM_SPACE_BASE;
    pb->pci_io_base    = PCI0_IO_SPACE_BASE;

建立PCI的空间分配的数据结构.其中pci_mem_base为Memory空间的基地址,pci_io_base 为IO空间的基地址. minipciioaddr 为IO空间的最小可以分配地址, minipcimemaddr 为 Memory 空间的最小可以分配地址. nextpcimemaddr 为PCI的 Memory 空间的下一个分配地址, nextpciioaddr 为PCI的IO空间的下一个分配地址,在pmon的中地址分配是逆序分配的.

c 复制代码
pb->max_lat = 255;
pb->fast_b2b = 1;
pb->prefetch = 1;
pb->bandwidth = 4000000;
pb->ndev = 1;
_pci_bushead = pb;
_pci_bus[_max_pci_bus++] = pd;

开发时需要注意的问题

  • Debug的方法
    -- 在串口设备没有初始化前, 利用逻辑分析仪进行测试。该方法debug很艰难,所以应该尽早初始化串口。
    -- 串口工作后,可以利用串口进行类似printf的Debug方法。
    -- 初始化BIOS系统的Shell后,可以利用BIOS系统中的Debug系统进行测试。
  • 地址空间是否正确,北桥上的窗口分配是否正确。
  • 中断问题。
  • 充分利用Pmon所带的调试手段。pmon>h可以看到pmon提供的命令,通过这些命令来检查地址分配是否正确。
相关推荐
国科安芯3 小时前
ASP4644芯片低功耗设计思路解析
网络·单片机·嵌入式硬件·安全
广药门徒3 小时前
Linux驱动开发与BuildRoot是什么关系与其的应用场景
linux·运维·驱动开发
充哥单片机设计3 小时前
【STM32项目开源】基于STM32的智能厨房火灾燃气监控
stm32·单片机·嵌入式硬件
CiLerLinux10 小时前
第四十九章 ESP32S3 WiFi 路由实验
网络·人工智能·单片机·嵌入式硬件
时光の尘10 小时前
【PCB电路设计】常见元器件简介(电阻、电容、电感、二极管、三极管以及场效应管)
单片机·嵌入式硬件·pcb·二极管·电感·三极管·场效应管
Lu Zelin10 小时前
单片机为什么不能跑Linux
linux·单片机·嵌入式硬件
驱动开发00711 小时前
虚拟麦克风驱动下载,支持将手机话筒映射成PC端麦克风
驱动开发·安全
宁静致远202111 小时前
stm32 freertos下基于hal库的模拟I2C驱动实现
stm32·嵌入式硬件·freertos
Wave84516 小时前
STM32--智能小车
stm32·单片机·嵌入式硬件
驱动开发00716 小时前
虚拟摄像头VirtualUSB UVC CAMERA下载 支持将手机摄像头映射成PC端摄像头
驱动开发·安全·电脑