分类:
2009-11-20 15:55:32
romInit 主要完成:CPU核心寄存器初始配置、初始化内存系统、堆栈指针和跳转romStart()(C代码)入口执行
下面定义几个带参的宏,方便后面使用。
1.#define WRITEADR(reg1,reg2,addr32,val) \ 字
lis reg1, HI(addr32); \
ori reg1, reg1, LO(addr32); \
lis reg2, HI(val); \
ori reg2, reg2, LO(val); \
stw reg2, 0(reg1) stw RS,d(RA)
带参的宏: 将val的32bit写到addr32指向的地址中 其中:EA= RA d = addr32
#define WRITEADRH(reg1,reg2,addr32,val) \ 半字
lis reg1, HI(addr32); \
ori reg1, reg1, LO(addr32); \
lis reg2, HI(val); \
ori reg2, reg2, LO(val); \
sth reg2, 0(reg1) sth RS,d(RA)
带参的宏: 将val的低16位写到addr32指向的地址中 其中:EA= RA d = addr32
#define WRITEADRB(reg1,reg2,addr32,val) \字节
lis reg1, HI(addr32); \
ori reg1, reg1, LO(addr32); \
lis reg2, HI(val); \
ori reg2, reg2, LO(val); \
stb reg2, 0(reg1) stb RS,d(RA)
带参的宏: 将val的低8位内容存储到有效地址为EA的存储器中 其中:EA= RA d = addr32
#define WRITEADRR(reg1,reg2,addr32,reg3) \
lis reg1, HI(addr32); \
ori reg1, reg1, LO(addr32); \
stb reg3, 0(reg1)
带参的宏: 将reg3的内容存储到有效地址为EA的存储器中 其中:EA= RA d = addr32 0
#define WRITEOFFSET(regbase,reg2,offset,val) \
lis reg2, HI(val); \
ori reg2, reg2, LO(val); \
stw reg2, offset(regbase);
带参的宏: 将val的内容存储到有效地址为EA的存储器中 其中:EA= regbase offset
#define DDR_DEBUG /* be supported by GXP */
/* internals */ 内部函数声明
FUNC_EXPORT(_romInit) /* start of system code */
FUNC_EXPORT(romInit) /* start of system code */
/* externals */ 外部函数声明
.extern romStart /* system initialization routine */
.text
/*
下面按照硬件手册配置硬件配置字,以MPC8360为例
Hard Reset Configuration Word (HRCW) See config.h/ads834x.h/target.ref for
more info
*/
.fill 8,1,HRCW_LOW_BYTE0 拷贝8个字节,8个字节为一组,每组最高4个字节为0,最低4个字节为HRCW_LOW_BYTE0 ,由于HRCW_LOW_BYTE0 只有一个
.fill 8,1,HRCW_LOW_BYTE1 字节,则最低字节为HRCW_LOW_BYTE0,剩下的7个字节为0
.fill 8,1,HRCW_LOW_BYTE2
.fill 8,1,HRCW_LOW_BYTE3
.fill 8,1,HRCW_HIGH_BYTE0
.fill 8,1,HRCW_HIGH_BYTE1
.fill 8,1,HRCW_HIGH_BYTE2
.fill 8,1,HRCW_HIGH_BYTE3
.fill 1,1,BOOT_VERSION
.fill 191,1,0 /* The rest of the space are filled with zeros */
.fill 表达式
形式:
.fill repeat,size,value
其中,repeat、size、和value都是常量表达式。Fill的含义是反复拷贝size个字节。Repeat可以大于等于0。size也可以大于等于0,但不能超过8,如果超过8,也只取8。把repeat个字节以8个为一组,每组的最高4个字节内容为0,最低4字节内容置为value。
size和value为可选项。如果第二个逗号和value值不存在,则假定value为0.如果第一个逗号和size不存在,则假定size为1。
所以上述配置字的填写如下表所示。8个字节中只有最低的字节是硬件配置字。
系统复位时,到flash的基地址处读取HRCW来进行基本配置,读取的方式是:每次读64bit,但只有前8bit有效,最开始的4个reads中的前8bit,组成一个32bit的HRCWL,接下来的4个reads的前8bit,组成一个32bit的HRCWH。
/******************************************************************************
*
* romInit - entry point for VxWorks in ROM
*
*
* romInit
* (
* int startType /@ only used by 2nd entry point @/
* )
*/
_romInit:
romInit:
bl cold /* jump to the cold boot initialization */ 跳转到 cold标号处
nop /*空指令*/
bl warm /* jump to the warm boot initialization */ 跳转到warm标号处
/* copyright notice appears at beginning of ROM (in TEXT segment) */
.ascii "Copyright 1984-2005 Wind River Systems, Inc."
.align 2
cold:
li r3, BOOT_COLD /* set cold boot as start type */ 加载寄存器R3 ,值为 BOOT_COLD ,BOOT_COLD = 2
用通用寄存器r3记录启动类型
/*
* initialize the IMMR register before any non-core registers
* modification. The default IMMR base address was 0xFF400000,
* as originally programmed in the Hard Reset Configuration Word.
*/
li移动的是低16位,lis移动的是高16位
lis r4, HI (CCSBAR) r4的高16位是 CCSBAR的高16位
ori r4, r4, LO (CCSBAR) r4与CCSBAR的低16位进行或运算后,将结果存储在r4寄存器中,即用r4保存CCSBAR
lis r8,HIADJ(CCSBAR_INIT) /* IMMR was at 0xff400000 */ r8为初始IMMR的值
ori r8, r8, LO(CCSBAR_INIT) /* IMMR now at CCSBAR */
stw r4,0(r8) 将r4的内容写到r8指向的地址,即用r8的地址用来保存r4的值的内存地址
isync
sync
/* CPUU errata ARB1:
Set HID2[10] to 1, SPCR[14] to 1 and ACR[10:11] to 01/10,
immediately after boot up depending on CSB/CPU clk ratio
HID2 - 0x00200000
SPCR - 0x00020000
ACR - 0x00100000
*/
lis r5, 0x0020 /* set HID2[10] to 1: enable bus interface unit pipeline extension */
lis:将0x0020移到r5的高16位,低位为0,故r5:0x00200000 用r5来保存 HID2寄存器
sync
isync
mtspr 1011, r5 mtspr:将通用寄存器r5的内容拷到特定寄存器1011,此1011是特殊寄存器,代表HID2寄存器
/* system prioriy and configuration */
/* set SPCR[10:11] to 11: core CSB request priority = level 3, highest */
/* set SPCR[14] to 1: not defined */
lis r5, 0x0032 用r5来暂时保存SPCR寄存器的值,稍后写到内存中
stw r5, M83XX_SPCR(0)(r4) 将r5的内容写到M83XX_SPCR(0)(r4)指向的地址,M83XX_SPCR(0)(r4)地址=IMMR 0X00100 0X10=0xe0000110
0xe0000110为SPCR寄存器地址
/* arbiter configuration */
lis r5, 0x0010 用r5来暂时保存ACR寄存器 ,稍后写到内存中
stw r5, M83XX_ACR(0)(r4) /* pipeline depth 1, park to e300 master */ 将r5的内容写到M83XX_ACR(0)(r4)指向的地址,
M83XX_ACR(0)(R4)地址=IMMR 0X00800 0X0=0xe0000800 0xe0000800 为ACR寄存器地址
sync
isync
/* set OR0 of CS0 */
lis r5, HIADJ(QUICC_OR0(CCSBAR))
addi r5, r5, LO(QUICC_OR0(CCSBAR))
lwz r6, 0(r5) 用通用寄存器r6保存OR0
ori r6, r6, 0xff7 r6与0xff7进行或运算后,将结果保存在r6寄存器中
stw r6, 0(r5)
isync /* synchronize */
/* ensure all of the range are accessable*/
/*set windows size*/ 下面语句是写寄存器LBLAWAR1
WRITEADR(r6,r7,M83XX_LBLAWARn(CCSBAR,1), \ M83XX_LBLAWARn(CCSBAR,1)=0xe0000000 0x24=1*0x8=0xe000002c
(LAWAR_ENABLE | LAWAR_SIZE_2GB )) LAWAR_ENABLE =0x80000000(local bus local access window enable)
LAWAR_SIZE_2GB =0x1E (window size is 2GB)
lis r6,HI(M83XX_LBLAWARn(CCSBAR,1)) R6为M83XX_LBLAWARn(CCSBAR,1)的高16位
ori r6,r6,LO(M83XX_LBLAWARn(CCSBAR,1)) R6再或上M83XX_LBLAWARn(CCSBAR,1)的低16位,则为用R6来保存M83XX_LBLAWARn(CCSBAR,1),为0xe000002c
lwz r7,0(r6) 用通用寄存器r7来保存r6,即用r7来保存0xe000002c
/* load LAW0 BOOTROM*/ /*LBC local access windows base address register*/
WRITEADR(r6,r7,M83XX_LBLAWBARn(CCSBAR,1), 0x00000000) /* config boot at 0xfff00000~0xffffffff */ 其中0xfff00000,后5个0正好是20bit
isync 上面的语句用来将0x00000000写到0xe0000028中,该寄存器前20位为local access window的基地址,后面
12bit 为0
/*set windows size*/ 设置LBC local Access window 0 即LBLAWAR0 的大小
WRITEADR(r6,r7,M83XX_LBLAWARn(CCSBAR,0), \ LAWAR_ENABLE = 0x80000000,LAWAR_SIZE_2GB=0x0000001E ,LAWAR_ENABLE|LAWAR_SIZE_2GB=0x8000001E
(LAWAR_ENABLE | LAWAR_SIZE_2GB )) 该语句是将0x8000001E写到地址M83XX_LBLAWARn(CCSBAR,0),即0xe0000000 0x24 0*0x8=0xe0000024
lis r6,HI(M83XX_LBLAWARn(CCSBAR,0)) 用r6保存地址LBLAWAR0的高16位
ori r6,r6,LO(M83XX_LBLAWARn(CCSBAR,0)) 用r6保存地址LBLAWAR0的低16位
lwz r7,0(r6) 用通用寄存器r7来保存r6
/* load LAW0 BOOTROM*/ /*LBC local access windows base address register*/
WRITEADR(r6,r7,M83XX_LBLAWBARn(CCSBAR,0), 0x80000000) /* config boot at 0xfff00000~0xffffffff */
isync 配置LBC Local access window base adder register,即LBLAWBAR0,将0x80000000,写入LBLAWBAR0,
即20位地址中的最高位为1即0xfff80000.
#if 1/* only for mpc8360 */
WRITEADRB(r6,r7,MPC83XX_UDCR1(CCSBAR),0x00) datasheet中没找到这个寄存器
#endif
WRITEADRB(r6,r7,MPC83XX_ULCR1(CCSBAR),0x80) 设置ULCR寄存器,即Line Control Register,不做奇偶校验.word length 5bit
WRITEADRB(r6,r7,MPC83XX_UAFR1(CCSBAR),0x00) 设置UAFR寄存器,波特率选择,禁止向UART1,UART2写
#if (SYS_CLK_FREQ == FREQ_333_MHZ) 系统时钟频率333M
WRITEADRB(r6,r7,MPC83XX_UDMB1(CCSBAR),0x08) /* 0x87a for 667M */ 0X87A是333MHZ时对应的波特率为9600,时divisor的配置
WRITEADRB(r6,r7,MPC83XX_UDLB1(CCSBAR),0x7a)
#elif (SYS_CLK_FREQ == FREQ_266_MHZ)
WRITEADRB(r6,r7,MPC83XX_UDMB1(CCSBAR),0x06) /* 0x6c8 for 533M */ 0x6c8是系统时钟频率为266时,波特率为9600时divisor的设置
WRITEADRB(r6,r7,MPC83XX_UDLB1(CCSBAR),0xc8)
#endif
WRITEADRB(r6,r7,MPC83XX_ULCR1(CCSBAR),0x03) 设置ULCR寄存器,不做奇偶校验,word length is 8bit
WRITEADRB(r6,r7,MPC83XX_UMCR1(CCSBAR),0x00) 设置UMCR寄存器,使ready to send 禁使能
WRITEADRB(r6,r7,MPC83XX_UFCR1(CCSBAR),0x07) 设置UFCR寄存器,清除发送FIFO,接收FIFO中所有字节,并复位发送/接收计数器指针为0,并使能发送/接收
FIFO
WRITEADRB(r6,r7,MPC83XX_UIER1(CCSBAR),0x00) /* Tx empty, Rx interrupt disable */ 屏蔽UART中某些中断,详见datasheet
sync
isync
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x73) /* output 's' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x74) /* output 't' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x61) /* output 'a' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x72) /* output 'r' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x74) /* output 't' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x0a) /* output 换行 */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x0d) /* output 回车 */
sync
isync
/*
* When the PowerPC 83xx is powered on, the processor fetches the
* instructions located at the address 0x100. We need to jump
* from the address 0x100 to the Flash space.
*/
lis r4, HIADJ(start) /* load r4 with the address */
addi r4, r4, LO(start) /* of start */ 用r4保存start的地址
lis r5, HIADJ(romInit) /* load r5 with the address */
addi r5, r5, LO(romInit) /* of romInit() */ 用r5保存romInit()的地址
lis r6, HIADJ(ROM_TEXT_ADRS) /* load r6 with the address */
addi r6, r6, LO(ROM_TEXT_ADRS) /* of ROM_TEXT_ADRS */ 用r6保存ROM_TEXT_ADRS的地址
sub r4, r4, r5 /* */
add r4, r4, r6 r4= start - romInit ROM_TEXT_ADRS
mtspr LR, r4 /* save destination address*/
/* into LR register */ 用LR(链接)寄存器来保存r4,即目的地址
blr /* jump to flash mem address */ 跳转到LR指定地址
start:
/* set the MSR register to a known state */
xor r0, r0, r0 /* clear register R0 */ 异或,相同为0,不同为1 ,用r0与r0自己异或,相同,所以将异或后的值0赋给r0,即对r0清0
isync /* synchronize */
mtmsr r0 /* clear the MSR register */ 将r0的内容存入MSR,mtmsr是超级用户指令
sync
isync /* synchronize */
/* move these code after start to ensure boot jump from 0 to CS0_BASEADDR, change by yhw */
/* set BR0 and OR0 of cs0 */
WRITEADR(r6,r7,QUICC_BR0(CCSBAR),BR0_VAL) 将BR0_VAL(0xf0000801)写到QUICC_BR0(CCSBAR)(0xe0005000)地址中
WRITEADR(r6,r7,QUICC_OR0(CCSBAR),OR0_VAL) 将OR0_VAL(0xffe00ff7)写到QUICC_OR0(CCSBAR)(0xe0005004)地址中
isync
sync /* synchronize */
/*LBC local access window 0 base address register*/
WRITEADR(r6,r7,M83XX_LBLAWBARn(CCSBAR,0), CS0_BASEADDR) 将CS0_BASEADDR(0xf0000000)写到M83XX_LBLAWBARn(CCSBAR,0)地址中,即地址0xe0000028中
WRITEADR(r6,r7,M83XX_LBLAWARn(CCSBAR,0), \ LAWAR_ENABLE = 0x80000000, LAWAR_SIZE_2MB = 0x00000014,size = 0x14 = 20
(LAWAR_ENABLE | LAWAR_SIZE_2MB)) M83XX_LBLAWARn(CCSBAR,0)= (base) 0x24 (n*0x8)= 0xe0000000 0x24=0*0x8=0xe0000024
将0x80000014写入到地址0xe0000024中,完成LBC local acess window SIze 2M(2M=2*(size 1)=2*(21个20))
/* set windows of BR1 and OR1 of cs1 */
WRITEADR(r6,r7,M83XX_LBLAWBARn(CCSBAR,1), CS1_BASEADDR)
CS1_BASEADDR = 0x30000000,M83XX_LBLAWBARn(CCSBAR,1)= 0xe0000000 0x20 1*0x8=0xe0000028
将0x30000000写入0xe0000028
WRITEADR(r6,r7,M83XX_LBLAWARn(CCSBAR,1), \ LAWAR_ENABLE = 0x80000000,LAWAR_SIZE_64MB = 0x00000019, size = 0x19 0x1=26
M83XX_LBLAWARn(CCSBAR,1) = 0xe0000000 0x24 1*0x8 = 0xe000002c
(LAWAR_ENABLE | LAWAR_SIZE_64MB)) 将0x80000019写入0xe000002c,local acess window size = 2的26次幂=64M
/* set windows of BR2 and OR2 of cs2 */
WRITEADR(r6,r7,M83XX_LBLAWBARn(CCSBAR,2), CS2_BASEADDR)
WRITEADR(r6,r7,M83XX_LBLAWARn(CCSBAR,2), \
(LAWAR_ENABLE | LAWAR_SIZE_8MB))
/* set windows of BR3 and OR3 of cs3 */
WRITEADR(r6,r7,M83XX_LBLAWBARn(CCSBAR,3), CS3_BASEADDR)
WRITEADR(r6,r7,M83XX_LBLAWARn(CCSBAR,3), \
(LAWAR_ENABLE | LAWAR_SIZE_8MB))
lis r6,HI(M83XX_LBLAWARn(CCSBAR,0)) M83XX_LBLAWARn(CCSBAR,0)= 0xe0000000 0x24 0*0x8=0xe0000024,将高16位赋给r6
ori r6,r6,LO(M83XX_LBLAWARn(CCSBAR,0)) 将r6或上M83XX_LBLAWARn(CCSBAR,0))的低16位
lwz r7,0(r6) 用通用寄存器r7记录r6
/*System I/O Configuration Register */ 初始化系统I/O配置寄存器,有两个,LOW 和HIGH
WRITEADR(r6,r7, M83XX_SICRL(CCSBAR),0x00000000) LOW /* for MDS 0xc0000000 */ 将0写到M83XX_SICRL(CCSBAR)(0xe0000000 0x00100 14)中
isync
WRITEADR(r6,r7, M83XX_SICRH(CCSBAR),0x20000000) HIGH /* for MDS 0xc0000002 */
isync
/* Initialise the Local Bus Controller */ Local bus 配置寄存器 GPCM 或UPM 不使能校验位字节选择
WRITEADR(r6,r7, QUICC_LBCR(CCSBAR),0) /* LBCTL is used as W/R control for GPCM or UPM accesses (buffer control). */
/* Parity byte select is disabled. */
isync
/* Initialize the Local Bus Clock Ratio */ 时钟速率寄存器
WRITEADR(r6,r7,QUICC_LCRR(CCSBAR),0x80000008) /* bypass DLL, local bus clock = 1/8 CSB clock,wqb */
li r6,0x0020 将0x0020赋给r6
mtctr r6 把r6放到计数器寄存器 count register
lbcdelay:
nop
bdnz lbcdelay
nop
isync
sync
/* zero-out HID0 */
mtspr 1008, r0 /* disable cache */ 将r0存到特殊目的寄存器1008中,1008应该是HID0寄存器,不使能cache
isync
/* Zero-out registers: SPRGs */
addis r0,0,0 addis r0,0,0 同 lis r0,0
isync /* synchronize */
mtspr 272,r0 把r0存到特殊寄存器272中
mtspr 273,r0 把r0存到特殊寄存器273中
mtspr 274,r0 把r0存到特殊寄存器274中
mtspr 275,r0 把r0存到特殊寄存器275中
isync /* synchronize */
/* zero-out the Segment registers */ 将段寄存器清0
mtsr SR,rS 写入段寄存器指令mtsr
将rS中的内容读入SR,这是一个超级用户层指令。MPC8360中一共有16个段寄存器,SR0~SR15
mtsr 0,r0
isync
mtsr 1,r0
isync
mtsr 2,r0
isync
mtsr 3,r0
isync
mtsr 4,r0
isync
mtsr 5,r0
isync
mtsr 6,r0
isync
mtsr 7,r0
isync
mtsr 8,r0
isync
mtsr 9,r0
isync
mtsr 10,r0
isync
mtsr 11,r0
isync
mtsr 12,r0
isync
mtsr 13,r0
isync
mtsr 14,r0
isync
mtsr 15,r0
isync
/* invalidate DBATs: clear VP and VS bits */
清0DBAT 和IBAT
mtspr 536,r0 /* Data bat register 0 upper */
isync
mtspr 538,r0 /* Data bat register 1 upper */
isync
mtspr 540,r0 /* Data bat register 2 upper */
isync
mtspr 542,r0 /* Data bat register 3 upper */
isync
/* invalidate IBATs: clear VP and VS bits */
mtspr 528,r0 /* Instruction bat register 0 upper */
isync
mtspr 530,r0 /* Instruction bat register 1 upper */
isync
mtspr 532,r0 /* Instruction bat register 2 upper */
isync
mtspr 534,r0 /* Instruction bat register 3 upper */
isync
/* invalidate TLBs: loop on all TLB entries using r7 as an index */ 用r7来索引TLB
addi r0,0,0x0020 同li r0,0x0020 将0x0020赋值给r0
mtspr 9,r0 /* Load CTR with 32 */ 将r0(0x0020)存储到9号寄存器,9号寄存器为CTR,计数器寄存器
addi r7,0,0 /* Use r7 as the tlb index */1 将0赋给r7
tlb_write_loop:
tlbie r7 /* invalidate the tlb entry */ r7对应的有效地址转换无效
sync
addi r7,r7,0x1000 /* increment the index */ r7 = r7 0x1000
bc 16,0,tlb_write_loop /* Decrement CTR, then branch if the */
/* decremented CTR is not equal to 0 */
bc BO, BI, target_addr BO: 1z00y BI:表示CR条件寄存器中的bit,计数器CTR减量,如果CTR!=0,则发生转移
/* Turn off data and instruction cache control bits */
mfspr r7, HID0 r7=1008
isync
sync /* synchronize */
andi. r7,r7,0x3FFF /* Clear DCE and ICE bits */
mtspr HID0,r7
isync
sync /* synchronize */
#if 1 /* INCLUDE_DDR_SDRAM CCI 8360 */
/* Memory mapped region base address */
WRITEADR(r6,r7,M83XX_DDRLAWBARn(CCSBAR,0), \ DDR_SDRAM_LOCAL_ADRS = 0
DDR_SDRAM_LOCAL_ADRS) 将0写入(0xe0000000 0xA0 0*0x8=0xe00000A0)地址
WRITEADR(r6,r7,M83XX_DDRLAWARn(CCSBAR,0), \ DDR local acess window size = 256M
LAWAR_ENABLE | LAWAR_SIZE_256MB) /* for MDS LAWAR_SIZE_256MB */
nop
nop
nop
nop
isync
/* Totle delay is T_delay=[int(N_nop/2) 1]*(T_boot_cs*4)*2*(N 1) */
/* Now T_boot_cs=0.568us ,When N_nop=0, T_delay=(N 1)*4.544us*/
/* This is beginning of delay */
/* li r5,0x00dd /* delay 1ms */ r5=0x00dd
/* mtctr r5 将r5存储到Ctr 计数器寄存器
DDR2_Start_delay0:
/* nop */ /* N_nop is Number of nop */
/* bdnz DDR2_Start_delay0
/* This is end of delay */
/* Initialize the DDR2 Memory controller ODT only during reads */
/* DHC_EN DSO_EN DSO_PZ DSO_NZ MDIC0_OE MDIC1_OE ODT DDR_TYPE ----------------- DRQ */
/* 0 0 1100 1100 0 0 0 0 00000000000000000 1 */
WRITEADR(r6,r7, M83XX_DDRCDR(CCSBAR),0x33000001) /* 75(Ohm) 0 ,wqb,2007.12.17 */ 设置DDRCDR寄存器
isync
lis r6, HI(DDRBA) DDRBA=0xE0002000, 将高16位赋给r6
ori r6, r6, LO(DDRBA) /* r6 = DDR reg base */ r6与DDRBA的低16位进行或运算后,将结果存在r6中
/* WRITEOFFSET(r6,r7,0xf00, 0x202c0000) */ /* CAS latency 2.5 Assumed */
WRITEOFFSET(r6,r7,(CS0_BNDS), 0x0000000F) 配置CSN_BNDS寄存器
WRITEOFFSET(r6,r7,(CS1_BNDS), 0x00000000)
WRITEOFFSET(r6,r7,(CS2_BNDS), 0x00000000)
WRITEOFFSET(r6,r7,(CS3_BNDS), 0x00000000)
/* CS_n_EN ------- AP_n_EN ODT_RD_CFG - ODT_WR_CFG BA_BITS_CS_n --- ROW_BITS_CS_n ----- COL_BITS_CS_n */
/* 1 0000000 0 000 0 001 01 000 001 00000 010 */
WRITEOFFSET(r6,r7,(CS0_CONFIG), 0x80014102) /* 13 row bits, 10 column bits */ /* P506 */ 配置CSN_CONFIG寄存器 ,13行,10列
WRITEOFFSET(r6,r7,(CS1_CONFIG), 0x00000000) not active
WRITEOFFSET(r6,r7,(CS2_CONFIG), 0x00000000) not active
WRITEOFFSET(r6,r7,(CS3_CONFIG), 0x00000000) not active
/* P508 */ /* ------------- EXT_REFREC ---------------- */
WRITEOFFSET(r6,r7,(TIMING_CFG_3), 0x00000000) /* 0000000000000 000 0000000000000000 */ /* 0 clk for 166MHz */ DDR SDRAM timing
configuration 3
/* WRITEOFFSET(r6,r7,(TIMING_CFG_3), 0x00010000) /* 0000000000000 001 0000000000000000 */ /* 16 clk for 266MHz */ 16个时钟
/* RWT WRT RRT WWT - ACT_PD_EXIT - PRE_PD_EXIT ---- ODT_PD_EXIT ---- MRS_CYC */
/* (tRTW) (tXARD and tXARDS) (tXP) (tAXPD) (tMRD) */
/* all condition */ /* 2ck 2ck 8ck 2ck */
WRITEOFFSET(r6,r7,(TIMING_CFG_0), 0x00220802) /* 00 00 00 00 0 010 0 010 0000 1000 0000 0010 */
/* TIMING_CFG_1 */ /* - PRETOACT ACTTOPRE - ACTTORW CASLAT REFREC - WRREC - ACTTOACT - WRTORD */
/* P511 */ /* (tRP) (tRAS) (tRCD) CL (tRFC) (tWR) (tRRD) (tWTR) */
/* 4ck/15ns 45ns 4ck/15ns 4ck 105ns 15ns 10ns 7.5ns/2ck */
#if (SYS_CLK_FREQ == FREQ_333_MHZ)
/*when 166MHz*/ /* 4ck/3ck 8ck 4ck/3ck 4 18ck 3ck 2ck 2ck */
WRITEOFFSET(r6,r7,(TIMING_CFG_1), 0x3837a322) /* 0 011 1000 0 011 0111 1010 0 011 0 010 0 010 */
#elif (SYS_CLK_FREQ == FREQ_266_MHZ)
/*when 133MHz*/ /* 2ck 6ck 2ck 4 14ck 2ck 2ck 1ck /2ck */
WRITEOFFSET(r6,r7,(TIMING_CFG_1), 0x26276222) /* 0 010 0110 0 010 0111 0110 0 010 0 010 0 010 */
/*when 266MHz*/ /* 4.0ck 12ck 4.0ck 4 28ck 4ck 3ck 2ck */
/* WRITEOFFSET(r6,r7,(TIMING_CFG_1), 0x4c474432) /* 0 100 1100 0 100 0111 0100 0 100 0 011 0 010 */
#endif
/* TIMING_CFG_2 */ /* - ADD_LAT CPO - WR_LAT --- RD_TO_PRE WR_DATA_DELAY - CKE_PLS FOUR_ACT */
/* P513 */ /* AL
#if (SYS_CLK_FREQ == FREQ_333_MHZ)
/*when 166MHz*/ /* 3 2ck 3 9ck */
WRITEOFFSET(r6,r7,(TIMING_CFG_2), 0x0f9848c9) /* 0 000 11111 0 011 000 010 010 0 011 001001 */
#elif (SYS_CLK_FREQ == FREQ_266_MHZ)
/*when 133MHz*/ /* 3 1ck 3 7ck */
WRITEOFFSET(r6,r7,(TIMING_CFG_2), 0x0f9828cf) /* 0 000 11111 0 011 000 001 010 0 011 001111 */
/*when 266MHz*/ /* 3 2.0ck 3 13.3ck */
/* WRITEOFFSET(r6,r7,(TIMING_CFG_2), 0x0f9848ce) /* 0 000 11111 0 011 000 010 010 0 011 001110 */
#endif
/* MEM_EN SREN ECC_EN RD_EN - SDRAM_TYPE -- DYN_PWR - 32_BE 8_BE NCAP - 2T_EN BA_INTLV_CTL -- x32_EN PCHB8 HSE - MEM_HALT BI */
/* 0 1 0 0 0 011 00 0 0 1 0 0 0 0 0000000 00 0 0 1 0 0 0 */
WRITEOFFSET(r6,r7,(DDR_SDRAM_CFG), 0x43080008) /* another after complete all config */ /* P515 */ DDR SDRAM Control Configuration
/* FRC_SR - DLL_RST_DIS - DQS_CFG --- ODT_CFG ----- NUM_PR ------- D_INIT ---- */
/* 0 0 0 0 00 000 10 00000 0001 0000000 0 0000 */
WRITEOFFSET(r6,r7,(DDR_SDRAM_CFG_2), 0x00401000) /*ODT only during reads to DRAM DLL*/ /* */ 配置DDR_SDRAM_CFG_2寄存器
/* Extended Mode Register Control for On-Die Termination // Mode Register Changes for DDR2 */
/* EMR 0 out RDQS DQS# OCDprogram Rtt AL Rtt ODS DLLen // MR 0 PD WR DLLrst TM CASLatency BT BurstLength */
#if (SYS_CLK_FREQ == FREQ_333_MHZ)
/* 00 0 0 0 1 000 0 000 1 1 0 00 0 0 010 0 0 100 0 010 */
WRITEOFFSET(r6,r7,(DDR_SDRAM_MODE_CFG), 0x04060442) DDR SDRAM MODE Configuration寄存器配置
#elif (SYS_CLK_FREQ == FREQ_266_MHZ)
/* 00 0 0 0 1 000 0 000 1 1 0 00 0 0 001 0 0 100 0 010 */
WRITEOFFSET(r6,r7,(DDR_SDRAM_MODE_CFG), 0x04060242)
#endif
WRITEOFFSET(r6,r7,(DDR_SDRAM_MODE2_CFG), 0x00000000) DDR SDRAM MODE2 Configuration寄存器配置
/* REFINT -- BSTOPRE */
/* 7.8us/85 C/3.9us */
#if (SYS_CLK_FREQ == FREQ_333_MHZ)
/* 166MHz */ /* 1294/647 ck 刷新间隔配置 */
WRITEOFFSET(r6,r7,(DDR_SDRAM_INTERVAL), 0x03ca0064)/*0x03200064 0x045b0100 for MDS*/ /* 0000001111001010 00 00000001100100 */
#elif (SYS_CLK_FREQ == FREQ_266_MHZ)
/* 133MHz */ /* 1038/519 ck */
WRITEOFFSET(r6,r7,(DDR_SDRAM_INTERVAL), 0x030a0064)/*0x03200064 0x045b0100 for MDS*/ /* 0000001100001010 00 00000001100100 */
#if 0 /* 266MHz */ /* 2075/1038 ck */
WRITEOFFSET(r6,r7,(DDR_SDRAM_INTERVAL), 0x07530064)/*0x03200064 0x045b0100 for MDS*/ /* 0000011101010011 00 00000001100100 */
WRITEOFFSET(r6,r7,(DDR_SDRAM_INTERVAL), 0x03200064)/*0x03200064 0x045b0100 for MDS*/ /* 0000001100100000 00 00000001100100 */
#endif /* 800 100 */
#endif
配置DDR SDRAM CLOCK Cotrol 寄存器 /* ----- CLK_ADJUST ----------------------- */
WRITEOFFSET(r6,r7,(DDR_SDRAM_CLK_CNTRL), 0x02000000) /* 00000 0100 00000000000000000000000 */
WRITEOFFSET(r6,r7,(DDR_SDRAM_CFG), 0xc3080008) /* 0xc2008000) for MDS */ DDR SDRAM Control Configuration 寄存器配置
sync
isync
#if 0 /* INCLUDE_SEC_DDR_SDRAM, not be used by GXP */
WRITEADR(r6,r7,M83XX_SDDRLAWBARn(CCSBAR, 0), \
SEC_DDR_BASE_ADRS)
WRITEADR(r6,r7,M83XX_SDDRLAWARn(CCSBAR, 0), \
LAWAR_ENABLE | LAWAR_SIZE_128MB)
nop
nop
isync
lis r6, HI(0xe0001800)
ori r6, r6, LO(0xe0001800) /* r6 = QUICC Engine Secondary Bus Access Windows Registers base */
WRITEOFFSET(r6,r7,(0x80), 0x00) /*Disable Local Bus Memory Controller*/
WRITEOFFSET(r6,r7,(0x84), 0x00) /*Disable Secondary DDR Memory Controller*/
WRITEOFFSET(r6,r7,(0x00), 0x0010000) /*Local Bus Memory Controller Start Address Register*/
WRITEOFFSET(r6,r7,(0x40), 0x001FFFF) /*Local Bus Memory Controller End Address Register*/
WRITEOFFSET(r6,r7,(0x04), 0x0010000) /*Secondary DDR Memory Controller Start Address Register*/
WRITEOFFSET(r6,r7,(0x44), 0x0017FFF) /*Secondary DDR Memory Controller End Address Register*/
WRITEOFFSET(r6,r7,(0x84), 0x01) /*Enable Secondary DDR Memory Controller*/
WRITEOFFSET(r6,r7,(0x80), 0x01) /*Enable Local Bus Memory Controller*/
nop
nop
isync
lis r6, HI(0xe000d000)
ori r6, r6, LO(0xe000d000) /* r6 = Second DDR base */
WRITEOFFSET(r6,r7,(CS0_BNDS), 0x00100017)
WRITEOFFSET(r6,r7,(CS1_BNDS), 0x00000000)
WRITEOFFSET(r6,r7,(CS2_BNDS), 0x00000000)
WRITEOFFSET(r6,r7,(CS3_BNDS), 0x00000000)
WRITEOFFSET(r6,r7,(CS0_CONFIG), 0x80000102) /* 13 row bits, 10 column bits */
WRITEOFFSET(r6,r7,(CS1_CONFIG), 0x00000000)
WRITEOFFSET(r6,r7,(CS2_CONFIG), 0x00000000)
WRITEOFFSET(r6,r7,(CS3_CONFIG), 0x00000000)
WRITEOFFSET(r6,r7,(TIMING_CFG_0), 0x00220802)
WRITEOFFSET(r6,r7,(TIMING_CFG_1), 0x37357322) /*0x26256222 0x37343321 for MDS ZTE orig 0x37357322*/
WRITEOFFSET(r6,r7,(TIMING_CFG_2), 0x0f9048c7) /*0x0f9028c7 0x00000800 for MDS */
WRITEOFFSET(r6,r7,(TIMING_CFG_3), 0x00000000)
WRITEOFFSET(r6,r7,(DDR_SDRAM_CFG), 0x43080000) /* DDR2 USE_32BIT_DDR*/
WRITEOFFSET(r6,r7,(DDR_SDRAM_CFG_2), 0x00401000) /*ODT only during resds */
WRITEOFFSET(r6,r7,(DDR_SDRAM_MODE_CFG), 0x44400232)
WRITEOFFSET(r6,r7,(DDR_SDRAM_MODE2_CFG), 0x8000c000)
WRITEOFFSET(r6,r7,(DDR_SDRAM_INTERVAL), 0x03200064) /*0x03200064 0x045b0100 for MDS*/
WRITEOFFSET(r6,r7,(DDR_SDRAM_CLK_CNTRL), 0x02000000)
lis r7,0x0004
mtctr r7
sync
isync
delayddr2:
nop
nop
bdnz delayddr2
WRITEOFFSET(r6,r7,(DDR_SDRAM_CFG), 0xc3080000) /* 0xc2008000 for MDS */
sync
isync
#endif /* INCLUDE_SEC_DDR_SDRAM */
#endif /* INCLUDE_DDR_SDRAM CCI 8360 */
#ifdef INCLUDE_PCI
/* PCI local access window */
WRITEADR(r6,r7, M83XX_PCILAWBARn(CCSBAR,0),0x80000000)
WRITEADR(r6,r7, M83XX_PCILAWBARn(CCSBAR,1),0x90000000)
WRITEADR(r6,r7, M83XX_PCILAWARn(CCSBAR,0),0x8000001b) /* 256MB */
WRITEADR(r6,r7, M83XX_PCILAWARn(CCSBAR,1),0x8000001b) /* 256MB */
isync
#endif /* INCLUDE_PCI */
/* Clock configuration */
OCCR:output clock control 寄存器 SCCR: system clock control 寄存器
WRITEADR(r6,r7,M83XX_OCCR(CCSBAR),0x00000000) /* reset value, disable PCI_CLK_OUT0/1/2 */
isync
WRITEADR(r6,r7,M83XX_SCCR(CCSBAR), 0x00000000) /* ENCCM = 00 PCICM = 0 */
/* disable encryption core clock */
/* enable PCI complex clock */
isync
warm:
#ifdef INCLUDE_PCI
/* Set the pciAutoconfig check to FALSE */
xor r5,r5,r5 /* Zero r5 */
lis r6,HIADJ(PCI_AUTO_CONFIG_ADRS)
addi r6,r6,LO(PCI_AUTO_CONFIG_ADRS)
stw r5,0(r6)
#endif/* INCLUDE_PCI */
#if 0
lis r6, HIADJ (BCSR1) /* Make sure flash unprotected */
lbz r5, LO(BCSR1)(r6)
ori r5, r5, BCSR1_FLASH_PRT
stb r5, LO(BCSR1)(r6)
lis r6, HIADJ (BCSR0) /* Make sure flash unprotected */
lbz r5, LO(BCSR0)(r6)
ori r5, r5, LO(~BCSR0_SIGNAL1)
stb r5, LO(BCSR0)(r6)
#endif
/* turn the instruction cache ON for faster FLASH ROM boots */
mfspr r4, HID0 r4保存 HID0
ori r4, r4, _PPC_HID0_ICE | _PPC_HID0_ICFI /* set ICE & ICFI */ 使能指令cache ICE bit
rlwinm r5, r4, 0, _PPC_HID0_BIT_ICFI 1, _PPC_HID0_BIT_ICFI - 1 /* clear the ICFI bit */
isync
/*
* The setting of the instruction cache enable (ICE) bit must be
* preceded by an isync instruction to prevent the cache from being
* enabled or disabled while an instruction access is in progress.
*/
mtspr HID0, r4 /* Enable Instr Cache & Inval cache */
sync
mtspr HID0, r5 /* using 2 consec instructions */
/* E300 core recommendation */
isync
isync
/* initialize the stack pointer */ 初始化栈指针 STACK_ADRS
lis sp, HIADJ(STACK_ADRS) 用sp保存 STACK_ADRS
addi sp, sp, LO(STACK_ADRS)
/* go to C entry point */
addi sp, sp, -FRAMEBASESZ /* get frame stack */
/*
* calculate C entry point: routine - entry point ROM base
* routine = romStart
* entry point = romInit = R7
* ROM base = ROM_TEXT_ADRS = R8
* C entry point: romStart - R7 R8
*/
#ifdef DDR_DEBUG
bl ddr_check
bl daline_check
bl sdram_check
#endif
lis r7, HIADJ(romInit) 用通用寄存器r7保存romInit
addi r7, r7, LO(romInit)
lis r8, HIADJ(ROM_TEXT_ADRS) 用通用寄存器r8保存ROM_TEXT_ADRS
addi r8, r8, LO(ROM_TEXT_ADRS)
lis r6, HIADJ(romStart) 用通用寄存器r6保存romStart
addi r6, r6, LO(romStart) /* load R6 with C entry point */
sub r6, r6, r7 /* routine - entry point */ r6 = r6 -r7
add r6, r6, r8 /* ROM base */ r6 = r6 - r7 r8
mtspr LR, r6 /* save destination address*/ 用链接寄存器LR存储r6
/* into LR register */
blr /* jump to the C entry point */ 跳转到C语言函数入口点
ddr_check:
mfspr r30, LR 用r30保存链接寄存器LR的值
lis r6, HIADJ ((LOCAL_MEM_SIZE >> 1)) /* 使用RAM SIZE的一半作为测试地址 */ LOCAL_MEM_SIZE = 2的28次幂 即256M,右移1位
addi r6, r6, LO ((LOCAL_MEM_SIZE >> 1))
lis r5, HIADJ (0xaaaaaaaa) 用r5来保存0xaaaaaaaa
addi r5, r5, LO (0xaaaaaaaa)
lis r8, HIADJ (0x55555555) 用r8来保存0x55555555
addi r8, r8, LO(0x55555555)
stw r5, 0 (r6) 将r5存储在r6指向的地址
lwz r7, 0 (r6) 用r7保存r6
cmpw r5, r7 比较r5和r7
bne ddr_error /* check aaa */
stw r8, 0 (r6) 将r8存储在r6指向的地址
lwz r9, 0 (r6) 用r9来保存r6
cmpw r8, r9 比较r8和r9
bne ddr_error /* check 555 */ 比较结果不为0,则调用ddr_error,否则执行下一条语句
bl ddr_ok 程序跳转到标号ddr_ok处,同时还将PC的值保存到LR中
mtspr LR, r30 ddr_error
bclr 20, 0 无条件跳到链接寄存器(LR)中的地址.跳转目标地址位于LR中
daline_check:
mfspr r30, LR
lis r6, HIADJ ((LOCAL_MEM_SIZE >> 1)) /* 使用RAM SIZE的一半作为测试地址 */
addi r6, r6, LO ((LOCAL_MEM_SIZE >> 1))
addis r9, 0, 0 /* test times */
lis r8, HIADJ (0x00000020) /* counter */
addi r8, r8, LO (0x00000020)
lis r5, HIADJ (0x00000001)
addi r5, r5, LO (0x00000001)
data_check:
rotlw r5, r5, 1
stw r5, 0 (r6)
lwz r7, 0 (r6)
cmpw r5, r7
bne daline_error
addi r9, r9, 1
cmpw r8, r9
bne data_check
bl daline_ok
mtspr LR, r30
bclr 20, 0
sdram_check:
mfspr r30, LR
addis r5, 0, 0 /* zero out the r5 as test data */
lis r6, HIADJ (0x00010000) /* 使用64K作为测试起始地址 */
addi r6, r6, LO(0x00010000)
lis r8, HIADJ ((LOCAL_MEM_SIZE - USER_RESERVED_MEM))
addi r8, r8, LO (LOCAL_MEM_SIZE - USER_RESERVED_MEM)
/* write the test data */
write_ram:
stw r5, 0 (r6)
addi r5, r5, 1
addi r6, r6, 4
cmpw r8, r6
bne write_ram
/* check the write data */
addis r5, 0, 0 /* zero out the r5 as test data */
lis r6, HIADJ (0x00010000) /* 使用64K作为测试起始地址 */
addi r6, r6, LO(0x00010000)
read_ram:
lwz r7, 0 (r6)
cmpw r5, r7
bne memo_error
addi r5, r5, 1
addi r6, r6, 4
cmpw r8, r6
bne read_ram
bl led_ok
/* the check is ok */
mtspr LR, r30
bclr 20, 0
memo_error:
/*lws for no led*/
bl led_error
mtspr LR, r30
bclr 20, 0
/* flash the LED if the check is ok */
led_ok:
mfspr r29, LR
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x73) /* output 's' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x64) /* output 'd' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x72) /* output 'r' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x61) /* output 'a' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x6d) /* output 'm' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x6f) /* output 'o' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x6b) /* output 'k' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x0a) /* output 换行 */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x0d) /* output 回车 */
sync
isync
mtspr LR, r29
bclr 20, 0
/* flash the LED if the check is error */
led_error:
mfspr r29, LR
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x73) /* output 's' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x64) /* output 'd' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x72) /* output 'r' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x61) /* output 'a' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x6d) /* output 'm' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x65) /* output 'e' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x72) /* output 'r' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x72) /* output 'r' */
WRITEADRR(r6,r7,MPC83XX_UTHR1(CCSBAR),r7) /* output read data */
WRITEADRR(r6,r7,MPC83XX_UTHR1(CCSBAR),r6) /* output address */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x0a) /* output 换行 */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x0d) /* output 回车 */
sync
isync
mtspr LR, r29
bclr 20, 0
ddr_ok:
mfspr r29, LR
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x64) /* output 'd' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x64) /* output 'd' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x72) /* output 'r' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x6f) /* output 'o' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x6b) /* output 'k' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x0a) /* output 换行 */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x0d) /* output 回车 */
sync
isync
mtspr LR, r29
bclr 20, 0
ddr_error:
mfspr r29, LR
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x64) /* output 'd' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x64) /* output 'd' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x72) /* output 'r' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x65) /* output 'e' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x72) /* output 'r' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x72) /* output 'r' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x0a) /* output 换行 */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x0d) /* output 回车 */
sync
isync
mtspr LR, r30 /*直接返回*/
bclr 20, 0
daline_ok:
mfspr r29, LR
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x64) /* output 'd' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x61) /* output 'a' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x74) /* output 't' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x61) /* output 'a' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x6f) /* output 'o' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x6b) /* output 'k' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x0a) /* output 换行 */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x0d) /* output 回车 */
sync
isync
mtspr LR, r29
bclr 20, 0
daline_error:
mfspr r29, LR
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x64) /* output 'd' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x61) /* output 'a' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x74) /* output 't' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x61) /* output 'a' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x65) /* output 'e' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x72) /* output 'r' */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x72) /* output 'r' */
WRITEADRR(r6,r7,MPC83XX_UTHR1(CCSBAR),r9) /* output number */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x0a) /* output 换行 */
WRITEADRB(r6,r7,MPC83XX_UTHR1(CCSBAR),0x0d) /* output 回车 */
sync
isync
mtspr LR, r30 /*直接返回*/
bclr 20, 0