Yamon startup分析(未整理二) 作者:makethyme 下面对arch/reset/init.S进行分析: #include <mips.h> #include <product.h> #include <init.h> #include <sys_api.h> #include <gcmp.h> #include <launch.h> /* public address for returning from call to sys_platform_early(see below) */ .global sys_platform_early_done .type sys_platform_early_done, @function /** reset_handler **/ LEAF(__reset_handler) /* this is the entry point of the endian dependent code. It is called from the reset handler(reset.S) located at bfc00000. Processor is running at uncached addresses, but this code was linked cached. this function will shift to cached when caches have been initialized. */ .set noreorder .set noat .set noat表示在汇编中不使用at这个寄存器即$1 /* Don’t touch cause if we got here from an NMI */ MFC0(k0, C0_Status) sll k0, (31-S_Status) bltz k0, 1f 如果是从NMI跳转而来,则跳到前面的标号1处 /* setup cause register (clear cause code )*/ li k0, M_CauseIV 清除Cause寄存器中除IV位的值。其中IV设定为1,表示use the specifical interrupt vector CauseIV表示使用矢量中断模式 MTC0(k0, C0_Cause) /* Early platform specific initialisation, also detects NMI. can’t do jal since we don’t want to modify ra register in case an NMI has occurred. Instead, sys_platform_early shall jump to sys_platform_early_done when it is done. sys_platform_early will set k0 = Product ID. 返回值k0中设定Product ID 1: j sys_platform_early 跳转到arch/reset/init_platform_s.S的文件函数sys_platform_early处 nop. set. at 接下来分析arch/reset/init_platform_s.S文件 #include <sysdefs.h> #include <sys_api.h> #include <mips.h> #include <init.h> #include <product.h> #include <atlas.h> #include <sead.h> #include <lcd.h> #include <core_sys.h> #include <socitsc.h> /* Is the system controller SOCitSC? */ #define ISSC(reg) li reg, HIKSEG1(MIPS_REVISION); / lw reg, LO_OFFS(MIPS_REVISION)(reg); / srl reg, MALTA_REVISION_SCON_SHF; andi reg, MALTA_REVISION_SCON_MSK >> MALTA_REVISION_SCON_SHF 在sysdefs.h中,定义了 #define HIKSEG(addr) ((KSEG1(addr) + 0x8000) & 0xffff0000) #define KSEG1(addr) (((addr) & ~KSEG_MSK) | KSEG1BASE) #define KSEG1(addr) (((addr) & ~KSEG_MSK) | KSEG1BASE) KSEG_MSK = 0xE0000000, KSEG1BASE=0xA0000000 MIPS_REVISION = 0x1FC00010 KSEG1是将地址的高三位清零,再加上KSEG1的基地址,即转换为kseg1的虚拟地址 .set noreorder LEAF(sys_platform_early) /* early platform specific initialization. Don’t use registers other than k0/k1 until after we have made sure NMI has not occurred. k0 must be set to the product ID. */ /* set k0=product ID (determined using REVISION register) */ li k0, HIKSEG1(MIPS_REVISION) 实际上就是通过计算得到kseg1的高位,此例k0=0xbfc00000 lw k0, LO_OFFS(MIPS_REVISION)(k0) LO_OFFS(addr)定义为(addr) & 0xffff),可见通过将MIPS_REVISION 分成两部分,采用基地址+偏移的方法得到Product ID的值放在k0中 srl k0, MIPS_REVISION_PROID_SHF andi k0, MIPS_REVISION_PROID_MSK >> MIPS_REVISION_PROID_SHF li k1, PRODUCT_ATLASA_ID Atlas是4Kc beq k1, k0, atlas_malta_early li k1, PRODUCT_MALTA_ID Malta支持的处理器有4Kc, 4KEc, 5Kc or a 24Kc core. beq k1, k0, atlas_malta_early li k1, PRODUCT_SEAD_ID beq k1, k0, sead_early li k1, PRODUCT_SEAD2_ID beq k1, k0, sead_early li k1, PRODUCT_SEAD3_ID beq k1, k0, sead_early nop 上述程序根据product ID,判断是什么平台? done_unknown: /* Finished – Unknown platform*/ b done branch应该是执行完其接下来的指令,再跳转。因为延迟槽的缘故 li v0, ERROR_PlATFROM_UNKNOWN done_ok: b done v0用于返回值,0表示正确执行,其他值表示有错误 move v0, zero done: 执行完毕,其中返回状态在v0中 li k0, HIKSEG1(MIPS_REVISION) lw k0, LO_OFFS(MIPS_REVISION)(k0) srl k0, MIPS_REVISION_PROID_SHF 将Product ID保存在k0中 j sys_platform_early_done 重新跳转到arch/reset/init.S的sys_platform_early_done andi k0, MIPS_REVISION_PROID_MSK >> MIPS_REVISION_PROID_SHF