Red Magic PRO4RZ经过这段时间的加紧补作业,最终实现了在 PC 端通过 RZ/G2 使用 arm-none-eabi-gdb 完成对 stm32f103 控制器的探测和调试。项目的硬件结构框图如下:
硬件主要分为三个模块,GZ/G2 作为核心,对上和 PC 通信,完成 gdb 协议的解析和转译;对下通过虚拟的 SWDIO 接口(软件实现的)和待调试的板子通信,实现待调试芯片的底层数据交互。
而本次项目设计到软件部分涉及到两个层次,分别是内核态和用户态,内核太涉及到 USB gadget 驱动的开发,实现了设备端点在PC端枚举成 tty 设备,用户态涉及到 blackmagic 的移植,官方这部分功能是运行在 stm32 这类处理器上的,我将这部分功能移植到了 Linux 的用户态。系统软件结构框图如下:
整个软件的开发都采用 git 进行代码托管,内核态的开发仓库为 https://github.com/iysheng/myir-renesas-linux,代码提交记录截图如下:
用户态的代码开发在仓库 https://github.com/iysheng/blackmagic, 对应的提交记录截图如下:
因为前面大部分时间都在围绕 USB gadget 进行,所以用户态代码这部分的开发显示非常急促,还好我之前有对 blackmagic 这个项目的代码有过一定的拜读,所以基本功能还是实现了,目前可以探测外接芯片的信息,测试可以擦除 stm32f1 的内部 flash。
有关 blackmagic 这个调试器,我自己还是 DIY 过一个实际的调试器的,硬件我也已经开源了 https://gitee.com/iysheng/RedMagicProbe
实物是这个样子的:
现场使用 RZ/G2 实现 blackmagic probe 的工具还是有一定的挑战的,测试的现场图片如下:
从图中可以看出 RZ/G2 通过 4 根线和待调试的 STM32 的一个板子链接起来,相关的接口在原理图中我标注出来了如下所示:
在 J20 这个插座中,使用了 1 号脚 作为 3V3 给板子供电,39 作为连接板子的 GND,11 作为 SWCLK, 13 作为 SWDIO。有关 SWD 管脚部分的初始化参看代码:
- int gpio_handler_init(void)
- {
- struct gpiohandle_data data;
- char chrdev_name[20];
- int fd, ret;
- strcpy(chrdev_name, "/dev/gpiochip0");
- /* Open device: gpiochip0 for GPIO bank A */
- fd = open(chrdev_name, 0);
- if (fd == -1) {
- ret = -errno;
- fprintf(stderr, "Failed to open %s\n", chrdev_name);
- return ret;
- }
- swdp_pins[0].lineoffsets[0] = 33;
- swdp_pins[0].flags = GPIOHANDLE_REQUEST_OUTPUT;
- swdp_pins[0].lines = 1;
- memcpy(swdp_pins[0].default_values, &data, sizeof(swdp_pins[0].default_values));
- strcpy(swdp_pins[0].consumer_label, "swdio");
- ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &swdp_pins[0]);
- if (ret == -1) {
- ret = -errno;
- fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n",
- ret);
- }
- swdp_pins[1].lineoffsets[0] = 322;
- swdp_pins[1].flags = GPIOHANDLE_REQUEST_OUTPUT;
- swdp_pins[1].lines = 1;
- memcpy(swdp_pins[1].default_values, &data, sizeof(swdp_pins[1].default_values));
- strcpy(swdp_pins[1].consumer_label, "swclk");
- ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &swdp_pins[1]);
- if (ret == -1) {
- ret = -errno;
- fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n",
- ret);
- }
- if (close(fd) == -1)
- perror("Failed to close GPIO character device file");
- return ret;
- }
复制代码
最终测试的效果如图所示:
具体测试步骤如下: 从最终测试的效果图中可以看出,PC 端已经识别出来了 STM32F1 的芯片。并且在 RZ/G2 端也打印出u来来了芯片的 DPIDR 等信息。 通过这个项目,我的收获主要有以下几个方面: 通过阅读内核有关 usb gadget 驱动代码,使我对 USB gadget 的代码框架有一个一点浅薄的了解,这部分可以从我在阅读代码中添加的标注中看到,USB 部分也是我下一个阶段希望学习的方向,借着这个机会对主办方举行的活动表示感谢,如果没有这个活动,我可能还不会这么努力地去看内核 USB 的相关代码(如果缺少项目支撑,相信学习的进度不会这么快) 通过 blackmagic 到 Linux 用户态的移植让我对对底层的 gdb 调试原理以及 SWDP 协议规范有了进一步的了解。因为我作为一个嵌入式软件开发人员,我比较喜欢探求更深层次的代码实现,而不是单单完成一些库的调用,可能是我毕业就从事 Linux BSP 开发有关的缘故吧。我认为如果能够对 ARM Debug Interface 这类规范实现有更深的了解,相信对软件优化以及BUG调试会有很好的帮助。此外,如果研究的更加底层,那么肯定会有助成为一名真正的极客,这也是我作为嵌入式开发人员的个人追求。
|