1.回到start.S,继续
move a1, t2 //t2的值在691行赋值(当前793行)
bal reset_ht_link //返回值不为0,表示有错误发生
nop
li a0, 0xf3f3
and a0, a0, v0
beqz a0, 8f
nop
move t8, v0
TTYDBG("!!!LS3A-7A link error occur. Error status: ")
move a0, t8
bal hexserial
nop
设置a1的值作为参数。
跳转到函数,执行
之后有对v0(保存了返回值)进行验证,为0表示没有出错,继续,不为0则函数执行出错。
2.重点关注reset_ht_link函数,这也是HT配置后的第二步。
// support 1 way and 2 way connection. //支持1路和2路连接,我的硬件只有1路
// Because of the stupid bug, we have to keep all HT1 link reset together. //由于愚蠢的bug,必须要HT同步重启
//
// reset multi-times seems useless when linkup fail. //连接失败,重启多次看起来是没用的。//input:
//a1: HT bus and hard freq mode related setting //传入的参数,硬件频率设置
//[ 0]: reconnect, 0: not reconnect; 1: reconnect//output:
//v0: setup_link status: //返回值,重启连接的状态
//0: success
//!0: fail//register usage:
//t0: Node 0 LS3A HT1 cntl register base address //3A基地址
//t1: Node 0 LS7A HT1 cntl register base address //7A基地址
//t2: Node 1 LS3A HT1 cntl register base address //3A基地址,不存在多个3A,不使用
//t3: Node 1 LS7A HT1 cntl register base address //7A基地址,不存在多个7A,不使用
//t5, t6: tmp variable
//t8: store return value //t8 保存返回值
//s1: store ra //保存返回地址
注释也值得看一眼。
2.1 准备工作,不多解释了
reset_ht_link: //执行前面的config_ht_link后,马上就会跳转进来
//有一个参数a1 = ((HT1_HARD_FREQ_CFG << 12) | (HT1_HARD_FREQ_CFG << 8) | (HT1_GEN_CFG << 4) | (HT1_WIDTH_CFG << 1) | (HT1_RECONNECT << 0))
move s1, ra
reset_start:
dli t0, 0x90000efdfb000000 //注意650行的注释
dli t1, 0x90000efdfe000000
dli t2, 0x90001efdfb000000 //需要这个LS7A_2WAY_CONNECT ?? 1100行用了这个
dli t3, 0x90001efdfe000000
move t8, $0 //清零,记录错误的位号,作返回值使用
and a0, a1, 0x1 /* a1参数的最低位是否为0,不为0则继续 */
beqz a0, 88f /* 等于0,结束,函数返回,实际不等于0 */
nop
a1 = ( 9<<12 | 9<<8 | 3<<4 | 1<<1 | 1<<0)
2.2 3A端控制HT总线复位,7A应该是一起复位吧?
TTYDBG("Reset Node 0 HT1-lo bus\r\n") //开始执行
lb a0, 0x3e(t0) //3A部分设置
li a1, 0x40
or a0, a0, a1 //[6] = 1 对应 --》 0x3c [22]位
sb a0, 0x3e(t0) //总线复位 0--》1
lw a0, 0x3c(t0)
bal hexserial
nop
TTYDBG("\r\n")
//wait until HT link down
TTYDBG("Wait HT bus down.")
li t5, 0x1f //31
1:
TTYDBG(">")
addi t5, t5, -1
bnez t5, 2f
nop
TTYDBG("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b=")
li t5, 0x1f
//failed more than given time, set fail mark
or t8, t8, (0x1 << HT1_LINKDOWN_FAIL_OFFSET)
2:
lw a0, 0x44(t0) /* 链路状态控制寄存器 0x20 表示初始化完成 */
li a1, 0x20
and a0, a0, a1 /* 结果为0,才表示复位成功 */
bnez a0, 1b
nop
TTYDBG("\r\n") //信息打印
lw a0, 0x44(t0)
bal hexserial
nop
TTYDBG("\r\n")
两个寄存器,0x3e和0x44
22位,由0-->1,总线复位。
等待0x44,第[5]位为0,表示复位成功。
2.3 3A端控制HT总线解除复位
TTYDBG("\r\nDereset Node 0 HT1 bus\r\n") //执行这里
lb a0, 0x3e(t0)
li a1, 0x40
not a1, a1 //0100 -》 ffff,ffbf
and a0, a0, a1 //[6]清零
sb a0, 0x3e(t0) //总线解复位 1--》0
lw a0, 0x3c(t0) //信息打印
bal hexserial
nop
TTYDBG("\r\n")
2.4 等待HTlink重启成功。
wait_ht3_link_up:
//wait until HT link up
TTYDBG("Wait HT bus up.")
li t5, 0xff
1:
TTYDBG(">")
addi t5, t5, -1
bnez t5, 2f //不为0,跳转到1088的2标识符位置
nop
li a1, 0x1
b reset_start //跳到前面去(662行),重启cpuHT总线
nop
TTYDBG("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b=")
li t5, 0x1f
or t8, t8, (0x1 << HT1_LINKUP_FAIL_OFFSET)
2:
lw a0, 0x44(t0)
li a1, 0x20 //[5] 总线初始化是否完成
and a0, a0, a1
beqz a0, 1b /* 结果为0表示未初始化成功 */
nop //不等于0,向下继续执行
TTYDBG("\r\n") //信息打印
lw a0, 0x44(t0)
bal hexserial
nop
TTYDBG("\r\n")
lw a0, 0x68(t2) //这个是否有意义? NODE1不存在
li t5, 0x1000;
4:
addi t5, t5, -1;
bnez t5, 4b; //延时等待一下。
nop
lw a1, 0x68(t2);
beq a0, a1, 3f; //往前跳,标号3,
nop
//reset bus
dli t5, 0x90000ffdfb000000 //正常情况下,这里没有被执行。。。。。。。
sb zero, 0x3e(t5) //又重启HT总线??
sync
li a1, 0x40 //0-1 重启
sb a1, 0x3e(t5)
sync
sb zero, 0x3e(t5) //1-0 解重启????
sync
b wait_ht3_link_up //1071行,回跳?
nop
3:
这段代码只有前半截有点用,后半截没有执行,直接跳到3f了。
就是查询0x44寄存器,第5位,为1,则表示重启成功了。
2.5 频率锁定,及CRC错误检查
#ifdef CHECK_HT_PLL_LOCK //需要执行
//check HT PLL lock
move t5, $0
lw a0, LS3A_HT_PLL_CONF(t0) //0x178
srl a0, a0, 3 //逻辑右移3位
and a0, a0, 0x1 //[3] 是保留位,没意义啊?????
bnez a0, 2f
nop
PRINTSTR("\r\nError: After reconfigure, 3A HT PLL not locked!!!\r\n")
add t5, t5, 1 //出错了才加1
2:
#ifdef CHECK_7A_HT_PLL_LOCK //需要执行
lw a0, 0x1F4(t1)
srl a0, a0, 3 //逻辑右移
and a0, a0, 0x1 // PLL锁定了吗?? 为1就是锁定了
bnez a0, 2f
nop
PRINTSTR("\r\nError: After reconfigure, 7A HT PLL not locked!!!\r\n")
add t5, t5, 1 //出错了才加1
2:
#endif
bnez t5, 2b // t5 不为0 表示出错了
nop
TTYDBG("\r\nAfter reconnect, PLL check success.\r\n")
#endif
#if 1//Check if CRC error bit set and reset it
TTYDBG("Checking Node 0 HT1 CRC error.")
li t5, MAX_HT_CRC_ERR_COUNT //256
1:
TTYDBG(">")
addi t5, t5, -1
bnez t5, 2f //肯定跳转
nop
li a1, 0x1
b reset_start /* 重来一次 */
nop
or t8, t8, (0x1 << HT1_SB_CRC_FAIL_OFFSET)
li t5, MAX_HT_CRC_ERR_COUNT
2:
lw a0, 0x44(t1) //7A桥片
li a1, 0x300 //地址0x45 的[1:0]两位
and a0, a0, a1 //地址0x44 的[9:8]两位 CRC error
beqz a0, 3f //应该等于0
nop
or t8, t8, (0x1 << HT1_SB_CRC_ERR_OFFSET)
TTYDBG("\r\nCRC error found\r\n")
lw a0, 0x44(t1)
bal hexserial
nop
lw a0, 0x44(t1)
li a1, 0xfffffcff
and a0, a0, a1
sw a0, 0x44(t1)
b 1b
nop
3:
TTYDBG("\r\n")
3A端 0x178寄存器的第3位,频率已锁定。前面的文章已经提过了。
7A端 0x1f4寄存器的第3位,频率已锁定。前面的文章已经提过了。
检查3A及7A的CRC错误。
2.6 函数返回。
3.总结
这一截代码不少,很多是循环等待。
从3A端控制HT总线复位,然后等待HT重启成功,检查频率是否锁定,以及CRC错误。
理解的难度不大。建议多参考手册。