TN-rk3399使用swd调试系统.
1.通过阅读一些参数资料,他们都用过转接出micro_sd,通过连接标准的swd信号实现调试的。
https://crwulff.blogspot.com/p/rock64.html
http://notes.zahoryzontnik.com/
包括张银奎老师的GDK8和挥马枪的一些资料,我本人就购买了GDK8和挥马枪
https://www.nanocode.cn/#/gdk8/index
https://www.nanocode.cn/#/ntp/index
2.对于不太想折腾的来说直接使用张老师提供的套件即可了。对于喜欢捡电子垃圾的朋友,当然会追求极致性价比请继续看下去
先声明一点,基本上rk3328,rk3399,rk3566,rk3588等,他们的SWD信号都会和MICRO_SD接口的信号线复用(并且位置都是一样的),
以rk3399为例:原理图
此图十分清晰,你需要引出此二根线,下面看下标准的SDMMC接口定义图
Pin # | Pin name | Signal Function |
1 | DAT2 | Data Bit 2 |
2 | CD/DAT3 | Card Detect / Data Bit 3 |
3 | CMD | Command Line |
4 | Vdd | Supply Voltage 2.7v / 3.6v |
5 | CLK | Clock |
6 | Vss | Ground |
7 | DAT0 | Data Bit 0 |
8 | DAT1 | Data Bit 1 |
朋友们看明白没有,上面已经表清楚了脚的号码,DATA2为1号脚,DATA3为2号,VSS(地)是6号脚
你需要引出1,2,6三根线才能调试,如何引出呢?TF卡测试槽或者自己PCB画一个,我这里选择TF测试槽(买张老师GDK可以给你准备好一根转接线)
某宝搜:tf卡测试卡套
将卡套 1,2,6 号线焊接到杜邦线上,就行了,这里肯定会难住很多朋友,因为大部分的朋友跟我一样是电子白痴,纯软件出生
没有线的朋友可以找身边的会焊接的朋友帮忙焊接一下,就三根线而已,我的就是我弟帮我焊接的,丑是丑了点,但是能用
看见没有,只需要引出三根线就行了。调试的时候将sd卡槽插入被调试的机器,
或者自己从嘉立创免费打板打一个:https://oshwhub.com/shuobatian/tf-2-54
然后自己把柱子焊板子上,这个比上面操作要简单因为焊盘距离相对较远。
3.准备好硬件调试器,其实只要支持的标准的SWD协议的调试器都可以,
比如DAPLINK
https://github.com/ARMmbed/DAPLink
这个项目的arm公司开源的,支持很多单片机实现这个SWD协议,如果你想自己做板子,参考
https://oshwhub.com/hanxiaohu/daplink-hs-share
https://oshwhub.com/jixin002/daplink_jx
嘉立创开源广场自己搜,由于我只能看懂简单的原理图,是个电子废物
因此跟我一样的朋友还是上某宝上买吧,
我推荐这家,为啥,因为我自己就买的这家,并且从金华发货,到杭州很快,并且店家老板
是个硬件大佬,靠谱的,其他某宝搜的daplink,太便宜的不要买比如10几块这种基本用不了几次就会坏,
价格在30到100之间是正常的,当然我建议到这里MuseLab店子里买
4.配置openocd,openocd需要两个文件一个调试器的配置文件一个目标板的配置文件。
openocd windows下载地址:https://gnutoolchains.com/arm-eabi/openocd/
我直接到这里下载的
我这里给出两个配置文件例子吧,连线需要连接TCK/SWD_CK,TMS/SWD_IO,GND三根线到对应的位置
cmsis-dap.cfg
1 # SPDX-License-Identifier: GPL-2.0-or-later 2 3 # 4 # ARM CMSIS-DAP compliant adapter 5 # 6 # http://www.keil.com/support/man/docs/dapdebug/ 7 # 8 9 adapter driver cmsis-dap 10 11 # Optionally specify the serial number of CMSIS-DAP usb device. 12 # adapter serial 02200201E6661E601B98E3B9
rk3399.cfg
1 # SPDX-License-Identifier: GPL-2.0-or-later 2 # Rockchip RK3399 Target 3 # https://rockchip.fr/RK3399%20datasheet%20V1.8.pdf 4 # https://rockchip.fr/Rockchip%20RK3399%20TRM%20V1.4%20Part1.pdf 5 6 if { [info exists CHIPNAME] } { 7 set _CHIPNAME $CHIPNAME 8 } else { 9 set _CHIPNAME rk3399 10 } 11 12 # 13 # Main DAP 14 # 15 if { [info exists DAP_TAPID] } { 16 set _DAP_TAPID $DAP_TAPID 17 } else { 18 set _DAP_TAPID 0x5ba02477 19 } 20 21 adapter speed 12000 22 23 transport select swd 24 25 # declare the one SWD tap to access the DAP 26 swd newdap $_CHIPNAME cpu -expected-id $_DAP_TAPID -ignore-version 27 28 # create the DAP 29 dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu 30 target create $_CHIPNAME.ahb mem_ap -dap $_CHIPNAME.dap -ap-num 0 31 set _TARGETNAME $_CHIPNAME.lcore 32 # declare the 6 main application cores 33 set _smp_command "" 34 35 set $_TARGETNAME.base(0) 0x80030000 36 set $_TARGETNAME.base(1) 0x80032000 37 set $_TARGETNAME.base(2) 0x80034000 38 set $_TARGETNAME.base(3) 0x80036000 39 set $_TARGETNAME.cti(0) 0x80038000 40 set $_TARGETNAME.cti(1) 0x80039000 41 set $_TARGETNAME.cti(2) 0x8003a000 42 set $_TARGETNAME.cti(3) 0x8003b000 43 44 45 set _TARGETNAME $_CHIPNAME.bcore 46 set $_TARGETNAME.base(4) 0x80210000 47 set $_TARGETNAME.base(5) 0x80310000 48 set $_TARGETNAME.cti(4) 0x80220000 49 set $_TARGETNAME.cti(5) 0x80320000 50 51 set _cores 6 52 for { set _core 0 } { $_core < $_cores } { incr _core 1 } { 53 if {$_core < 4} { 54 set _TARGETNAME $_CHIPNAME.lcore 55 } else { 56 set _TARGETNAME $_CHIPNAME.bcore 57 } 58 59 60 cti create cti$_core -dap $_CHIPNAME.dap -baseaddr [set $_TARGETNAME.cti($_core)] -ap-num 1 61 62 target create ${_TARGETNAME}$_core aarch64 \ 63 -dap $_CHIPNAME.dap -coreid $_core -cti cti$_core \ 64 -dbgbase [set $_TARGETNAME.base($_core)] 65 66 if { $_core != 0 } { 67 ${_TARGETNAME}$_core configure -defer-examine 68 } else { 69 # uncomment to use hardware threads pseudo rtos 70 # ${_TARGETNAME}$_core configure -rtos hwthread" 71 # 0xff8c0000~0xff8d0000=0x10000 size=0x10000+0x20000 in rk3399-rockpro64.dts 72 ${_TARGETNAME}$_core configure -work-area-size 0x30000 -work-area-phys 0xff8c0000 \ 73 -work-area-backup 0 74 } 75 set _smp_command "$_smp_command ${_TARGETNAME}$_core" 76 } 77 78 target smp $_smp_command 79 80 targets rk3399.lcore0
运行openocd命令:
openocd -f cmsis-dap.cfg -f rk3399.cfg
这时肯定连不上,因为没有开启swd调试,一般板子默认是sd的功能,需要将其切换到SWD功能,
需要读参考的手册,比如rk3399
你需要将寄存器的某几个位写成相应的值,如何写?通过devmem2这个工具,我这里提供源码,C的,原版的代码有bug不建议使用
1 /* 2 * devmem2.c: Simple program to read/write from/to any location in memory. 3 * 4 * Copyright (C) 2000, Jan-Derk Bakker (jdb@lartmaker.nl) 5 * 6 * 7 * This software has been developed for the LART computing board 8 * (http://www.lart.tudelft.nl/). The development has been sponsored by 9 * the Mobile MultiMedia Communications (http://www.mmc.tudelft.nl/) 10 * and Ubiquitous Communications (http://www.ubicom.tudelft.nl/) 11 * projects. 12 * 13 * 14 * This program is free software; you can redistribute it and/or modify 15 * it under the terms of the GNU General Public License as published by 16 * the Free Software Foundation; either version 2 of the License, or 17 * (at your option) any later version. 18 * 19 * This program is distributed in the hope that it will be useful, 20 * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * GNU General Public License for more details. 23 * 24 * You should have received a copy of the GNU General Public License 25 * along with this program; if not, write to the Free Software 26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 * 28 */ 29 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <unistd.h> 33 #include <string.h> 34 #include <errno.h> 35 #include <signal.h> 36 #include <fcntl.h> 37 #include <ctype.h> 38 #include <termios.h> 39 #include <sys/types.h> 40 #include <sys/mman.h> 41 42 #define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", \ 43 __LINE__, __FILE__, errno, strerror(errno)); exit(1); } while(0) 44 45 #define MAP_SIZE 4096UL 46 #define MAP_MASK (MAP_SIZE - 1) 47 48 int main(int argc, char **argv) { 49 int fd; 50 void *map_base, *virt_addr; 51 unsigned long read_result, writeval; 52 off_t target; 53 int access_type = 'w'; 54 55 if(argc < 2) { 56 fprintf(stderr, "\nUsage:\t%s { address } [ type [ data ] ]\n" 57 "\taddress : memory address to act upon\n" 58 "\ttype : access operation type : [b]yte, [h]alfword, [w]ord, [i]nt\n" 59 "\tdata : data to be written\n\n", 60 argv[0]); 61 exit(1); 62 } 63 target = strtoul(argv[1], 0, 0); 64 65 if(argc > 2) 66 access_type = tolower(argv[2][0]); 67 68 69 if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL; 70 printf("/dev/mem opened.\n"); 71 fflush(stdout); 72 73 /* Map one page */ 74 map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target & ~MAP_MASK); 75 if(map_base == (void *) -1) FATAL; 76 printf("Memory mapped at address %p.\n", map_base); 77 fflush(stdout); 78 79 virt_addr = map_base + (target & MAP_MASK); 80 switch(access_type) { 81 case 'b': 82 read_result = *((unsigned char *) virt_addr); 83 break; 84 case 'h': 85 read_result = *((unsigned short *) virt_addr); 86 break; 87 case 'w': 88 read_result = *((unsigned long *) virt_addr); 89 break; 90 case 'i': 91 read_result = *((unsigned int *) virt_addr); 92 break; 93 default: 94 fprintf(stderr, "Illegal data type '%c'.\n", access_type); 95 exit(2); 96 } 97 //read_result = 0xffffffffffffffff; 98 printf("Value at address 0x%X (%p): 0x%lX\n", target, virt_addr, read_result); 99 fflush(stdout); 100 101 if(argc > 3) { 102 writeval = strtoul(argv[3], 0, 0); 103 switch(access_type) { 104 case 'b': 105 *((unsigned char *) virt_addr) = writeval; 106 read_result = *((unsigned char *) virt_addr); 107 break; 108 case 'h': 109 *((unsigned short *) virt_addr) = writeval; 110 read_result = *((unsigned short *) virt_addr); 111 break; 112 case 'w': 113 *((unsigned long *) virt_addr) = writeval; 114 read_result = *((unsigned long *) virt_addr); 115 break; 116 case 'i': 117 *((unsigned int *) virt_addr) = writeval; 118 read_result = *((unsigned long *) virt_addr); 119 break; 120 } 121 printf("Written 0x%lX; readback 0x%lX\n", writeval, read_result); 122 fflush(stdout); 123 } 124 125 if(munmap(map_base, MAP_SIZE) == -1) FATAL; 126 close(fd); 127 return 0; 128 }
这里有坑的是,读的时候w是8字节对齐,一般寄存器又是4字节大小,因此你需要让它对齐才行
参考手册搜这个:force_jtag,一般需要将这个位写成1才行,自己搜找到地址
因此我这里直接给出tn3399这个开发板在linux内核开启swd调试的命令
./devmem2 0xFF77e218 w 0x1000180000000000
./devmem2 0xFF77e020 w 0xffffAAAA00005555
分别是操作两个寄存器:GRF_SOC_CON7,GRF_GPIO4B_IOMUX,可以看看这个两个寄存器在芯片手册的上位置
然后我就成功的断了下来了,给大家看几张成功的图
windows需要使用gdb-multiarch才能调试,因为它gdb-multiarch才支持多架构
需要安装msys2和这个包 mingw-w64-x86_64-gdb-multiarch
https://packages.msys2.org/package/mingw-w64-x86_64-gdb-multiarch?repo=mingw64
5.结尾,大家有什么问题可以联系我,我能解答就全解答,便宜的板子哪里买?
ophub支持的板子并且是rk芯片的都可以买
https://github.com/ophub/amlogic-s9xxx-armbian
咸鱼自己去搜这些板子的型号大多非常便宜在100-200之间
记住一定要选择带TF卡槽的,接口多尽量选接口多的,有串口最好,
带千兆网的更好。
大家有什么问题随时可以联系我。