最近一段时间在鼓捣CMSIS-DAP在CH558的移植。现在终于搞定SWD部分了,分享一下结果。
对于CMSIS-DAP,ARM官方的代码是针对32位环境优化的,对于51这种8位单片机就会导致效率很低。因此,我重写了CMSIS-DAP代码(核心部分的代码基本都是汇编写的),将其移植到CH558上,并且使用SPI进行优化(同时依然可以使用GPIO模拟引脚)。
下图是我在STM32F407上的测试结果,使用IAR下载程序(顺便一提,为了提升下载速度,我将Flash的并行编程宽度改成了32位)。
上图是Flash的测试结果,下载速度70KB/s,验证速度315KB/s。
上图是SRAM的测试结果,下载速度305KB/s。
可以看到,即使是CH558这种级别的单片机也可以跑到很高的速度,完全可以满足使用要求。实际上,我的代码大小仅为3.69KB,继续添加功能的空间还是充足的,目测把CMSIS-DAP的所有功能都做上去不成问题,甚至可以考虑做个兼容V1和V2的版本(使用Vendor Command切换版本,兼容一些不支持V2的软件)。
下一步我打算将代码移植到CH552上,毕竟CH552的性价比更高,而且需要修改的部分很少。虽然CH552的时钟频率较低(3.3V下只能跑到16MHz),但是应该对性能的影响不是特别严重(SWD接口带宽还有一定余量),值得尝试。
考虑到JTAG部分以及一些相对次要重要的功能(例如SWO和充话费送的串口)还没完成,所以暂时不放出源代码,待修改完成后再发布,敬请期待。
下文会谈一些目前的优化手段,欢迎大家交流。
最近编辑记录 metro (2020-02-27 13:34:09)
离线
顶起~,感谢楼主分享!
楼主也可以考虑下使用NUC505来搞一个试试
高速USB,价格也很便宜。
离线
顶起~,感谢楼主分享!
楼主也可以考虑下使用NUC505来搞一个试试
高速USB,价格也很便宜。
其实之前求高速USB就是在考虑做调试器,以后可以试试。
离线
上述测试结果是基于SPI优化的。这里同样给出GPIO模拟的结果,虽然速度有所损失,但是得益于51单片机操作GPIO的速度(差不多是7个周期对应一个bit),影响并不是特别大。
离线
下图是SRAM下载过程中使用逻辑分析仪抓的波形图,是基于GPIO模拟的结果。可以看到,SWD的带宽尚未跑满(大概用了3/4左右),因此乐观估计移植到CH552上的速度损失可以接受(前提是使用SPI跑到8MHz,此时和CH558使用GPIO模拟的理论速度相当)。
离线
虽然用不到,但还是期待楼主的源码,哈哈
离线
下面简单介绍一下CMSIS-DAP的特点。
CMSIS-DAP是ARM提的一套调试器协议(作为具体实现之一的DAPLink可能知名度更高?)。CMSIS-DAP的特点是融合了通用调试器(如基于FTDI的方案)和专用调试器(如ST-Link)的优势,即可单独控制输入输出波形,又对Cortex-M的高频操作封装成了固定指令。因此,CMSIS-DAP不仅通用性非常好(理论上可以兼容所有JTAG接口,当然还有自家的SWD接口),而且针对ARM设备可以达到不错的速度(前提是使用V2版本)。
上图是基于CMSIS-DAP的调试架构。CMSIS-DAP本质上是一套基于PC发送命令并进行处理的中间人,本身并没有决定何时执行哪些命令的功能,这可以简化调试器软件的设计。当然,需要集成相关功能的话也没有问题,例如DAPLink也是利用了这套框架搭了一个基于USB MSC的下载器。
另外,CMSIS-DAP的固件版本包括V1和V2,两者的主要区别在于V1用的是HID,而V2改成了Bulk传输。HID的好处是免驱,但由于HID类的限制每1ms只能传输一条指令,实际上大大限制了传输速度。V2版本则利用WinUSB实现了免驱(对Windows的版本有要求),传输速度也不再受到HID类的限制。(这里要感谢@le062分享的经验,说明了V2版本中USB速度不再是瓶颈,全速USB也是够用的,因此才有了这个想法。)
对V2版本USB部分的详细描述可以查看Configure USB Peripheral。
最近编辑记录 metro (2020-02-27 18:01:38)
离线
厉害,汇编玩的溜!我画了ch563的板子,有高速usb,芯片还没回来,楼主要不要试试,调好硬件送你一块
离线
上文提到了,CMSIS-DAP是基于命令式的处理,调试器从PC接收指令(Command/Request),在处理结束后调试器整理好结果(Response)发送回PC。由于没有Outstanding(但是可以有内部缓冲),因此指令是顺序执行的,类似于FIFO的架构。因此,CMSIS-DAP的固件内部是一个大的循环,PC端发送的数据会先置于一个FIFO中,待DAP_Thread函数读取、处理指令后,将会写回到另一个FIFO中,等待发送回PC。因此,Command/Request和Response各有一个FIFO,DAP_Thread只处理CMSIS-DAP协议本身,USB部分需要另行处理。
此时看CMSIS-DAP的代码结构(见CMSIS-DAP),就会非常清晰:
DAP.c就是DAP的核心部分,用于对指令进行解析和处理。
SW_DP.c和JTAG_DP.c用于兼容不同协议的DP(Debug Port)。
SWO.c用于SWO的部分。
DAP_vendor.c是自定义的DAP指令,可以根据需求添加。
在官方实现中,如果要移植CMSIS-DAP,只需要添加兼容CMSIS-Driver接口的驱动,并且在target或board级进行一些设定(例如I/O端口,特定的重置序列等)就可以用了,还是很方便的。
离线
厉害,汇编玩的溜!我画了ch563的板子,有高速usb,芯片还没回来,楼主要不要试试,调好硬件送你一块
不敢当不敢当,说实话我想尝试一下NUC505运行调试器的情况,到时候也会试一下的。
离线
Flash的并行编程宽度,咋设置
离线
Flash的并行编程宽度,咋设置
IAR的在这里,Keil的我没看。具体可以设置的位数和电压有关,最好参考一下Reference Manual,STM32F407在3.3V下最多可以设为32位。
最近编辑记录 metro (2020-02-27 19:00:07)
离线
其实之前求高速USB就是在考虑做调试器,以后可以试试。
刚想起来上次找最便宜的高速USB的MCU的原来是您啊,我也是看了您的那个帖子才做了个505尝试了下
然后就掉坑里了~~~
顺手记录了下505的调试过程。
https://kmcu.gitee.io/2020/02/21/NUC505/
最近编辑记录 sblpp (2020-02-27 19:01:06)
离线
刚想起来上次找最便宜的高速USB的MCU的原来是您啊,我也是看了您的那个帖子才做了个505尝试了下
然后就掉坑里了~~~
顺手记录了下505的调试过程。
https://kmcu.gitee.io/2020/02/21/NUC505/
哈哈哈,这个MCU据说坑比较多,之前我也买了块板子打算玩的,结果压箱底了,现在也暂时回不去,打算以后研究下UAC之类的。
离线
接下来说说优化思路。
首先还是得从CH558的架构说起(CH552等基本同理)。由于51的RAM有限(最大256Bytes),所以USB只能从XRAM读写数据,而众所周知51对XRAM的访问比较麻烦,只能通过DPTR寄存器进行,因此虽然访问速度很快(movx相关的指令都是单周期),但是寻址很麻烦。另外,涉及到数据搬移的部分也会消耗一定时间。
为了解决这个问题,CH55x系列单片机都支持双DPTR指针和自增指针。但是很遗憾,包括Keil(准确说是C51)和SDCC在内的编译器似乎都不支持CH55x上的这两个特性。因此,这部分代码需要按照实际执行的逻辑自己编写代码,这也是要用汇编进行优化的原因之一(另外的原因是可以在固定寄存器上传递跨函数的参数,类似于U-boot的gd指针)。
因此,结合CMSIS-DAP的特点,在我的代码里面,使用DPTR0存储Command指针,DPTR1存储Response指针。由于CH55x支持0xA5指令,这一指令等效于__asm__ ("movx a, @dptr1\ninc dptr1"),因此我们默认使用DPTR0指针。这样,我们就能使用一个周期的时间完成读取Command(通过movx a, @dptr)和写入Repsonse(通过.db 0xa5),读写效率得到了很大提高。
另外是数据搬移的问题。CMSIS-DAP可以通过设置DAP_PACKET_COUNT的方式来提升缓冲深度,可以通过提交多条指令的方式加速处理速度。如果不在这一部分进行优化,则会花费不少时间在USB DMA地址和DAP FIFO之间搬移数据。为此,我使用了一种看似麻烦的方式,就是设置USB DMA为单缓冲,并且每读一个包就切换到下一个FIFO地址(需要处理空满情况)。考虑到全速USB的Bulk最大包大小为64Bytes,这里我设置DAP_PACKET_COUNT为4,并且确保Command和Response的FIFO对齐到整256Bytes空间。这样一来,DMA的地址可以通过对低8位的部分每次累加64得到,并且在溢出时相当于循环FIFO。由于不涉及到数据搬移,因此USB中断处理流程大大加快,并且不会干扰DAP部分的执行。
顺带一提,在我测试时CH558的USB_DMA寄存器(只读,用于表示当前DMA的传输地址)似乎有问题(似乎CH552并没有这个寄存器),会在运行一段时间后出现未知的错误结果,原因不明。在我改用端点对应的UEPx_DMA寄存器之后,问题解决。
最近编辑记录 metro (2020-02-27 20:01:46)
离线
厉害,fifo地址可以随时切换吗,用关掉usb吗?
离线
厉害,fifo地址可以随时切换吗,用关掉usb吗?
不用,CH55x有个bUC_INT_BUSY,打开之后就可以保证不清中断就自动NAK后续数据包,可以在中断直接切换。
离线
最后说一下SWD的时序问题以及优化方案吧。
众所周知,SWD是简单的两线协议,是ARM为Cortex-M单片机提出的优化方案。事实上,SWD的优势不仅是占用引脚少,而且传输的指令更加简单,相对而言提升了传输效率。
SWD的波形如下图所示。
可以看到,SWD协议每次传输的数据包的位宽是相对固定的。对于Successful/OK的情况,可以分为以下6个阶段(空闲状态是SWCLK输出高电平,SWDIO输出高电平):
传输8-bit的command。实际上,有效数据是4个bit,Start用于指示开始,Parity用来提供4个bit的奇偶校验,Stop用于指示结束,而Park用于将引脚拉高。
第一个Turnaround,调试器切换到输入态,SWDIO暂时维持高电平。Turnaround的长度为1到4个bit,可以通过DLCR寄存器修改。
设备返回3-bit的response。一般的状态包括OK,FAULT,WAIT和Protocol Error。
对于Write而言,第4步需要切换到输出态,因此需要第二个Turnaround;对于Read而言,第4步用于输入32-bit数据及1-bit校验位。
对于Write而言,第5步用于输出32-bit数据及1-bit校验位;对于Read而言,第5步需要切换到输出态,因此需要第二个Turnaround。
第6步用于输出IDLE(如果有),简单来说就是在SWDIO输出若干个周期的低电平(直到下一个高电平时才开始下一个传输)。
这里我们先不探讨各种技术细节,可以看到SWD中8-bit的command和32-bit的data是比较规整的,而其它则比较零散。由于CH55x的SPI只能支持按字节传输,因此也只能对这两个部分优化(但是占比可以达到(8+32)/(8+5+32+1)≈87%,还是比较多的)。
当然,上文中针对的是SWD部分。由于SWJ接口(SWD和JTAG的共用接口)规定,TCK和SWCLK同一引脚,TMS和SWDIO统一引脚,并且不能修改(协议切换的逻辑只能在这两个引脚上进行),因此对于CH55x这种只有一个SPI和一组复用引脚的情况,必然只能选择其中一个协议应用SPI优化。
当然,JTAG也可以应用SPI优化,但是涉及到IR/DR切换等问题会比较复杂,等以后做到了再分享吧。
最近编辑记录 metro (2020-02-27 22:47:46)
离线
赶上直播了,谢谢大神分享。
离线
居然用到了汇编优化!
我想移植一个v1版本的协议到ch552,感觉对速度的要求就不是那么高了,应该就用不上这些高端的优化手段了
离线
居然用到了汇编优化!
我想移植一个v1版本的协议到ch552,感觉对速度的要求就不是那么高了,应该就用不上这些高端的优化手段了
V1的理论最高速度就是64KB/s,毕竟HID类的限制在那。不优化理论上也是够用的。
离线
厉害,汇编玩的溜!我画了ch563的板子,有高速usb,芯片还没回来,楼主要不要试试,调好硬件送你一块
关注一下调试器速度
离线
膜拜一下orz,51仿真调试stm32,果然只有想不到,没有做不
离线
膜拜啊!下载速度杠杠的
离线
论坛里面真是卧虎藏龙啊。
离线
这个速度和成本完全可以普及一下了
离线
这个速率还能再提高吗
离线
70KB,太强了。。强人
离线
低成本方案啊,不错不错 。
离线
关注不迷路
离线
掉进成本坑了,1块多钱的CH552必须用,lz太强了
离线
支持一下,最近也在研究CH552的DAP
离线
下图是SRAM下载过程中使用逻辑分析仪抓的波形图,是基于GPIO模拟的结果。可以看到,SWD的带宽尚未跑满(大概用了3/4左右),因此乐观估计移植到CH552上的速度损失可以接受(前提是使用SPI跑到8MHz,此时和CH558使用GPIO模拟的理论速度相当)。
https://whycan.cn/files/members/1510/TinyDAP-Timing.png
这款逻辑分析仪有好几个价位,你这款用的是基础版,还是高配版?多少钱入手的?
离线
这个代码体积,用CH551更划算一些
离线
期待楼主的源码,学习一下提升效率的方式。
离线
学习了。
离线
楼主现在有分享代码吗?
离线
想观摩一下楼主的源码
另外,楼主有试下CH549吗?官方的WCH-Link用的是这款芯片,但是下载速度似乎挺慢的
离线
居然移植到51单片机上了,强
离线
我也想搞一个 打算用CH559T
离线
ljbfly 说:厉害,汇编玩的溜!我画了ch563的板子,有高速usb,芯片还没回来,楼主要不要试试,调好硬件送你一块
不敢当不敢当,说实话我想尝试一下NUC505运行调试器的情况,到时候也会试一下的。
楼主考不考虑用CH573 BLE HID实现一个V1版本的无线调试器
离线
这是用两颗AIC8800M搞定的,无线是USB over TCP。同样不开源
离线
最低成本的arm仿真器
离线
想问下,资源管理器显示 link 识别,但是keil下没有 一般是什么导致的? 我看了下通信过来 没有看到HID的报告描述符的枚举额
离线
想问下,资源管理器显示 link 识别,但是keil下没有 一般是什么导致的? 我看了下通信过来 没有看到HID的报告描述符的枚举额
离线
虽然用不到,但还是期待楼主的源码
离线