使用的硬件是换了芯的龙芯派2代开发板,这块开发板基于龙芯2K1000的soc芯片,原芯片是mips指令集,龙芯2022年推出了这个芯片的loongarch版——2K1000LA,可原位进行替换。
替换后可以使用 pmon 或 uboot 作为加载器,加载多种类linux系统。同样开发板提供ejtag接口,使用龙芯提供的ejtag对软硬件系统进行跟踪调试。
什么是ejtag,直观的说,它是一个小盒子,一端通过专用插头连接开发板,另一端通过usb接口连接一台计算机(开发机)。用户在开发机上运行一个程序,可以交互式的运行命令,使用ejtag提供的各种功能。
ejtag的功能很多,概括的说,可以用它给目标板(目标机)刷固件,跟踪目标机的运行状态,观察寄存器和内存的数值,调试固件,调试linux内核等等,可以说,通过ejtag用户可以了解cpu运作的一切。原理也很好理解,ejtag让处理器工作在“调试模式”下,相当于一个可以登堂入室的后门,具体做什么,取决于你的想象力!
拿到ejtag之前,做了些功课,主要是收集了一些对loongarch指令集处理器的支持程度,了解是肤浅的。通过两天的折腾,总算是对ejtag有了一些认知,功能有待进一步挖掘。但有一点是确认的,龙芯的ejtag对loongarch的支持,是很完备的,现将一些认识整理如下:
1、龙芯ejtag实际上是一个处理器调试软硬件方案,包括软件和硬件。硬件不再赘述,软件是安装在开发机上,支持多系统环境下运行,比如windows,linux。也支持多架构,可以运行在x86-64、mipsel、mips64el和 loongarch 多种架构计算机上。
2、对loongarch处理器的支持,是单独的主程序la_dbg_tool_usb,和对mips的支持ejtag_debug_usb分开。支持2K500,2K1000LA、3A5000和3C5000处理器,可以说龙芯提供的软件包,支持龙芯所有可以使用ejtag的处理器产品。
cpu0 -source configs/config.ls2k
#jtag_clk 1 2
#letl clk 1
#expr 0x10000|1
#usblooptest 0x81000070 0x10001
#expr 3>2
#do if 0x1
#letl phase 2
#expr 0x20000|2
#usblooptest 0x81000070 0x20002
#end
#ret
#setconfig core.cpucount 2
#setconfig core.cpuwidth 64
#setconfig core.abisize 64
#setconfig core.nocache 1
#setconfig usb_ejtag.put_speed 0
#setenv ENV_memsize 256
#setenv ENV_highmemsize 1792
#setenv ENV_cpuclock 800000000
#setenv LOONGSON_2H 1
#setconfig jtag.jrhb 1
#setconfig jtag.jalrhb 1
#newcmd si si.h
#dellabel cache_init
#expr1 match "/home/dbhrscom/mydev/ejtag-debug/la_dbg_tool_usb" .*la.*
#do if 0x30
#let iobase 0x8000000000000000
#let cacbase 0x9000000000000000
#let ucbase 0x8000000000000000
#let spi_membase 0x1c000000
#let apbbase 0x1fe20000
#let cfgbase 0x1fe00000
#let cpuwin 0x2000
#letl ejtag_spibase 0xdb000000000fff00
#setconfig jtag.pcswidth 83
#setconfig jtag.synci 1
#setconfig put.fastdata 0
#setconfig putelf.uncached 0
#setconfig core.nocache 1
#setconfig usb_ejtag.put_speed 0
#setconfig usb_ejtag.get_speed 0
#setconfig core.abisize 64
#newfunc cache_init cache_init_la
#loop_break
#expr 0x9000000000000000+0xf000
#setconfig helpaddr 0x900000000000f000
#expr 0x1fff0220|0x8000000000000000
#setconfig spi.iobase 0x800000001fff0220
#expr "(0x1 << 16)"
#letl PLL_L1_LOCKED 0x10000
#expr "(0x1 << 2)"
#letl PLL_L1_ENA 0x4
#expr "(0x1 << 2)"
#letl PLL_MEM_ENA 0x4
#expr "(01 << 16)"
#letl PLL_MEM_LOCKED 0x10000
#letl PLL_CHANG_COMMIT 0x1
#letl DDR_REFC 4
#letl DDR_DIV 1
#letl DDR_DIV_L2 4
#letl GPU_DIV_L2 5
#letl PLL_IN 100000000
#expr 333000000/10*1*4*4/(100000000/10)
#letl DDR_LOOPC 0x35
##/* CPU @ 1000Mhz */
#letl L1_LOOPC 80
#letl L1_REFC 4
#letl L1_DIV 1
#letl L2_DIV 2
#expr 1000000000/10*1*4*2/(100000000/10)
#letl L1_LOOPC 0x50
##dc 200M
##gmac 125M
#letl DC_LOOPC 80
#letl DC_REFC 4
#letl DC_DIV 1
#letl DC_DIV_L2 8
#letl GMAC_DIV 16
##letl DC_LOOPC {250000000/10*${DC_DIV}*${DC_REFC}*${DC_DIV_L2}/(${PLL_IN}/10)}
##letl PIX0_LOOPC 109
#letl PIX0_REFC 5
#letl PIX0_DIV 1
#letl PIX0_DIV_L2 20
#expr 64000000/10*1*5*20/(100000000/10)
#letl PIX0_LOOPC 0x40
##letl PIX1_LOOPC 109
#letl PIX1_REFC 5
#letl PIX1_DIV 1
#letl PIX1_DIV_L2 20
#expr 64000000/10*1*5*20/(100000000/10)
#letl PIX0_LOOPC 0x40
#expr 0x8000000000000000+0x1fe20000+0x7800
#let rtc_reg 0x800000001fe27800
#expr 0x8000000000000000+0x1fe20000+0x1000
#letl i2creg 0x800000001fe21000
#source "scripts/gmac.cmd"
#letl phy 16
#letl base 0xffffffffbfe10000
#letl coherent_base 0x9800000000000000
#letl phy 24
##letl base {($(pci_config_read 0 0x3 0 0x10)&~0xf)|$ucbase}
#source scripts/nand.cmd
#letl nand_msize nand_osize nand_cap nand_esize 8192 256 7 0x20000
#letl ncmd 0xffffffffbfe06000
#letl orderreg 0xffffffffbfe10c00
#expr 0x8000000000000000+0x1fe20000+0x6000
#letl ncmd 0x800000001fe26000
#expr 0x8000000000000000+0x1fe00000+0x0c00
#letl orderreg 0x800000001fe00c00
#source scripts/spi.cmd
#let spibase 0xffffffffbfff0220
#let spi_cs 0
#let spi_speed 4
#expr 0x8000000000000000+0x1fff0220
#let spibase 0x800000001fff0220
#let spi_cs 0
#dellabel gdb_module_setup
##acpi_gmac_suspend()
##{
##devmem 0x4004002c 32 $(($(devmem 0x4004002c)|0x203))
##devmem 0x4005002c 32 $(($(devmem 0x4005002c)|0x203))
##devmem {$apbbase+0x702c} 32 0x70
##devmem {$apbbase+0x7028} 32 0x0000ffff
##devmem {$apbbase+0x700c} 32 0x0000ffff
##devmem {$apbbase+0x7008} 32 $(($(devmem {$apbbase+0x7008})|0x80))
##devmem {$apbbase+0x7004} 32 $(($(devmem {$apbbase+0x7004})|0x80))
##devmem {$apbbase+0x7014} 32 $(((1<<13)|(${1:-5}<<10)))
##}
3、主程序通过运行时加载一个特定的配置文件,提供对相应处理器的支持,比如2K1000LA,它的配置文件是config.ls2k。实际查看这个文件,它通过检测主程序文件名是否包含la来确定,配置的是2K1000还是2K1000LA。
4、主程序是一个命令交互程序,除了内置命令,它还可以通过命令脚本,perl、python和C进行功能扩展。运行前加载的配置文件,其实就是一个命令脚本,除了做一些初始化操作,还提供了很多function,提供诸如读写设备状态、配置和数据的功能。比阅读代码,要直观很多!
5、ejtag可以工作在gdbserver模式下,进行实时调试,也可以在交互界面调用gdb,对指定二进制模块进行调试
6、通过验证,除了可以在交互界面上执行命令,也可以集成在eclipse开发工具上进行调试。
短时间有些功能还未触及到,后续结合具体应用逐步补充。