页次: 1
使用CH32V203G6U6进行Coremark测试,由于零等待闪存区域太小,-O3优化会爆闪存,这里使用-Os优化。
| 是否零等待区 | Coremark | 运行主频(Mhz) | Coremark/MHz |
| ----------- | -------- | ------------- | ------------ |
| 1 | 239.1396 | 144 | 1.660691 |
| 1 | 159.3494 | 96 | 1.65989 |
| 1 | 79.5574 | 48 | 1.657446 |
| 0 | 8.835473 | 144 | 0.061357 |
| 0 | 5.885135 | 96 | 0.061303 |
| 0 | 2.934796 | 48 | 0.061142 |
非零等待区与零等待区之间有27倍的性能差距,不知道大伙能不能接受。
冷知识:AT89C51 Coremark2.36分,0.11Coremark/MHz。
研究了一下手册,发现有个增强读模式,打开试试:
48MHz下Coremark分数:2.934718
FLASH不分频(直接使用HCLK):2.934718
感觉这两个选项不是给CH32V203G6U6用的。
又试了一下HCLK 2分频 :2.919156(有一点点区别)
CH32V系列,例如CH32V203G6,只有前32K字节的闪存区域是零等待区域,而总闪存区域则达到了224K,作为极低代码密度的RISC-V,32K字节的代码区域是完全不够用的。
举个例子:在使用USB CDC和串口printf的情况下,32K字节的零等待区域就用了将近一半,而此时业务代码还没有开始编写,所以把初始化等不常用的代码放在非零等待区域是很有必要的。
遗憾的是:WCH给的例程里面并没有说明如何使用非零等待区域。故在此说明
在Ld/Link.ld文件中:
// 在MEMORY大括号中,添加:
SFLASH (rx) : ORIGIN = 0x00008000, LENGTH = 192K
// 在SECTION大括号中,添加:
.stext :
{
. = ALIGN(4);
*(.stext .ssrodata)
. = ALIGN(4);
} >SFLASH
在c文件中,可以使用__attribute__((section("")))语句指定数据的存放位置:
__attribute__((section(".stext"))) void GPIO_Toggle_INIT(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
__attribute__((section(".ssrodata"))) const u8 aa[] = {1,2,3,4,5,6,7,8,9,10};
当然,也可以用宏定义简化代码。
既然能把代码放进非零等待区了,那就顺便测个性能(计算PI):
__attribute__((noinline)) __attribute__((section(".stext"))) double getpi(){
volatile double n = 200000, sum = 0;
volatile int i;
for(i = 1; i <= n; i++)
sum += 1.0/(4*i-3)-1.0/(4*i-1);
return 4.0*sum;
}
| 是否零等待区 | 运行主频 | 时间 |
| ----------- | -------- | ------- |
| 1 | 144 | 1.6016 |
| 1 | 96 | 2.4064 |
| 1 | 48 | 4.8185 |
| 0 | 144 | 4.0496 |
| 0 | 96 | 6.0822 |
| 0 | 48 | 12.1999 |
结果非常出乎意料,GD32F1x0的非零等待闪存运行速度测试 对比GD32的测试情况,运行速度只慢了2.5倍显得非常的不可思议。按照国产MCU“手册里没写就是烂到不敢写”的尿性,怀疑是测试方法存在问题。下次跑个Coremark试试。
目前软件部分已经完全编写完成,硬件部分由于手边没有电烙铁暂时作罢,等能进实验室了再说。硬件部分完全兼容@posystorage大佬的硬件,大伙可以先用大佬的硬件方案试一试。
项目的代码、预编译固件获取路径:GitHub:abgelehnt/Tiny-DAPLink
本项目在@posystorage 开源CH551/2实现的汇编优化高速DAP-Link (CMSIS-DAP v2)和@ljbfly CH552 版 CMSIS-DAP v2的基础上改进而来。
调试器的呈现方式依然为通用调试器和板载调试器,且以板载调试器为主。
通用调试器:使用5V供电,主频24Mhz。下载速度未经过详细测试,但是至少能比FullSpeed版本的CMSIS-DAP v1快。下载STM32F103C8T6需要6.5秒。硬件方面:由于CH552 所需外围电路简单,芯片体积也较小,调试器可以做得非常小。硬件主要构成为:CH552(¥2.3)、电平转换芯片SN74LVC1T45*2(¥2.8)、阻容及USB座(¥0.5)。可以说是相当便宜了。
板载调试器:使用3.3V供电,主频16Mhz。在16Mhz主频下串口不支持115200波特率,不过在板载调试器上问题倒也不是很大。如果是通用调试器不支持115200波特率的话,就显得有些鸡肋了。硬件方面:带调试器的小系统板相比不带调试器的只需要增加一个CH552、一个电容、一个USB接口而已。Tiny-DAPLink也因此得名。
代码基本的大框架没有动,不过细节部分改进甚多:
1. 串口优化
我认为串口完美可用的标志:回环测试正确,且连续发送时逻辑分析仪不会看到IDLE信号。
IDLE信号:通信线上在一个字节的时间内没有再接收到数据就会出现IDLE信号,连续发送时出现IDLE信号会导致类似HAL_UARTEx_ReceiveToIdle的功能无法正常使用。
我的代码使用ping-pong buffer的思想,利用双缓冲区进行数据搬移,相比于@posystorage的循环队列方案省去了一次性的大量数据搬移工作,把每次串口/USB收到数据后的响应时间优化为常数,解决了原版连续发送且收发并用的情况下极偶发的丢数据情况(平均200K数据丢几十字节)。现版本串口在115200波特率下完美可用。
在500000波特率下,我的版本与原版本都有丢数据情况,我的版本丢失的数据量较小,但是连续传输速度大幅满于原版本,原因:一次性的大量数据搬移工作在总响应时长上占更大优势。
2. SWD速度优化
@posystorage大佬的版本我使用下来,IO版本无法开启调试,SPI版本我甚至一次都没有下载成功过。
SPI版本的兼容性问题原因:在ADIv5手册P122中,
When the target samples SWDIO, sampling is performed on the rising edge of SWCLK. When the target drives SWDIO, or stops driving it, signal changes are performed on the rising edge of SWCLK.
也就是说在SPI读时应该使用模式2,SPI写时应该使用模式3。大佬可能没有注意到这点。不过CH552并没有模式2,所以可以使用SPI优化的部分会低于87%。
@ljbfly大佬的版本除了IO模式以外没有太大的问题,只是时序看起来占空比较高。
由于我对汇编实在是一窍不通,使用汇编进行时序刷写时总会有一些奇形怪状的问题,迫不得已才放弃了大佬现成的汇编代码。在我的版本中,只有8bit command和32bit WDATA使用SPI刷写,其余均用IO刷写。对于占空比看起来高的问题,我直接加了一堆nop粗暴解决。单次刷写消耗的时间在两位大佬之间。
3. 更正配置描述符
原先的配置描述符感觉属于“我也不知道为什么 但是它就是能跑”的状态,他多了一条接口关联描述符,并且使用了端点4。但是在USB中断中,端点4完全未被使用过。
它还存在一个偶发bug:烧写失败有可能导致Keil再也找不到CMSIS-DAP,解决方案为:设备管理器中找到此设备->卸载设备->重新拔插U盘。
我的版本空出了端点4,并且(可能)解决了这个偶发bug。
4. 中国大学式无意义创新点:新增电容键盘
此功能需要搭配特定的硬件电路才能实现。
此功能可以映射键盘上的任意一个按键,并在触摸调试器特定位置时按下一次此按键。
想象一下这样一个场景:你刚写完代码,点击编译,然后去摆弄硬件:连接杜邦线/插上排阵/开启设备电源,摆弄完硬件恰好编译完成,你可以触碰一下调试器的某处便捷的开始下载,整个过程快速而又优雅。
新增此功能是因为Keil没有类似编译后下载的按键,就会麻烦一些。
在串口工具中输入:DAT+KEY=41(大小写敏感)打开电容键盘并映射为F8。
也可以将电容键盘映射为其他按键USB HID键盘键值表。
输入DAT+KEY=FF关闭电容键盘。
5. 开启睡眠功能
一些电脑在睡眠/休眠/关机状态下不会关闭USB的5V供电,不过调试器的功耗也无关痛痒就是了。
6. 唯一序列号
设备使用芯片唯一ID作为序列号,这样就可以同时插多个调试器了。
下次写东西不再用51了,在对性能有哪怕一点点追求的地方用51都是一种错误。
页次: 1