请教一个 STM32H7 IO 翻转速度的问题

2019-12-12 18:15发布

如题,由于案子需要用到高速的IO通信,还是特殊协议的那种,担心STM32F1和STM32F4 端口速度以及数据处理速度跟不上,就买了个STM32H7 的开发板,想试一下看看H7 的 IO 翻转速度有多快。
但结果有点出乎意料,用正点原子的例程,STM32H7 主频设置到400MHz,主循环里面就下面这样:
  while(1)
         {
         GPIOB->ODR = 1;
        GPIOB->ODR = 0;
         }
IO 口示波器实测速度才 16.7MHz 左右;

然后,为了避免其他因素的干扰,我又尝试,直接把 HSI 8分频,也就是64MHz/8 = 8MHz 作为系统时钟,各路总线都不再分频,跑起来,IO 的翻转速度才670KHz 左右;
相对于 400MHz 的时候,HCLK 是系统时钟 二分频了的,也就是说总线时钟 200MHz,200MHz/8MHz * 670KHz = 16.75MHz,这个和之前的测试结果基本吻合。

网上一查,发现也有人和我遇到同样的问题,或者说是现象,但却没有寻找到有效的提高 IO 翻转速度的方法。
那么问题来了,STM32H7 这样的 IO 翻转速度表现,甚至远低于 STM23F4 的水准,这显然应该是不可能的,这里面肯定有哪里没有配置正确吧,我猜;
但是我用自己贫瘠的英语水平以及比较low的专业能力,翻看了好几天参考手册并尝试修改各种时钟配置,一直没有解决,不知道坛子里有没有遇到同样问题的人,或者有大神给指点迷津。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
64条回答
laoshuhunya
1楼-- · 2019-12-19 05:22
dudududu 发表于 2018-11-29 14:28
这位大神,为啥软件翻转一次需要6周期,硬件需要2周期,最终算出来是6*2=12周期??为啥是相乘的关系,我 ...

对此我也有疑惑。如果数据手册上“翻转一次I/O口需要两个周期”这句话表达的意思是硬件限制,那么对你上面示出的汇编代码来说确实是 6*2 = 12个周期。如果那句话表达的意思是“I/O翻转速度最高可达系统时钟的1/2”,那结论完全不同。
根据我这几天的实际测试,STM32F1软件翻转I/O口的速度最高可达系统时钟的1/4,STM32F4和STM32F7软件翻转I/O口的速度都能达到系统时钟的1/2,但我手上没有STM32H系列的测试板,无法确认它的具体情况。不过我个人认为STM32H7应该和F7系列一样。你也可以用前面我的帖子中附件那个嵌入式汇编测试下,结果就非常明确了。
vuo50z
2楼-- · 2019-12-19 08:46
参考这个帖子,翻转速率主要受总线速度影响。
https://www.amobbs.com/forum.php ... &authorid=99882
laoshuhunya
3楼-- · 2019-12-19 13:15
今天拿到一块STM32H743评估板,略略翻了相关文档,把锁相环PLL1设置为800MHz,系统时钟设置为400MHz,I/O口总线(AHB4)时钟设置为200MHz,果然不负众望,I/O输出硬件翻转速度达到了数据手册的200MHz,也符合参考手册上说的系统时钟1/2
  
但是,软件翻转I/O口的速度也达到了惊人的16.7MHz,比11年前的STM32F103还差?STM32F103软件翻转I/O口的速度可以达到18MHz
  
重新检查设置,把能开的全开了,该关的都关了,软件翻转I/O口的速度始终是稳稳的16.7MHz
  
在输出指令中插入NOP,也没有增加翻转周期,说明是总线矩阵阻碍了软件翻转I/O的速度。
  
时钟配置如下:
  1. //-------------------------------------------------------------
  2.     HWREG32(0x51043100uL) = 0x0000000FuL;    // CM7_Read_QOS = 0xF(最高优先权)
  3.     HWREG32(0x51043104uL) = 0x0000000FuL;    // CM7_Write_QOS = 0xF(最高优先权)
  4.    
  5.     SET_BIT(PWR->CR2, 0x00000001uL);    // 使能备份调压器
  6.     SET_BIT(PWR->CR3, 0x02000100uL);    // 使能USB调压器,使能VBAT电池充电
  7.     Delay(DelayTime);
  8.     SET_BIT(PWR->D3CR, 0x0000C000uL);    // VOS = 1
  9.     Delay(DelayTime);
  10.     while (!READ_BIT(PWR->CSR1, 0x00002000uL));    // 等待VOS电压稳定
  11.    
  12.     RCC->PLLCKSELR = 0x01010100uL;    // DIVM = HSI/16
  13.     RCC->PLLCFGR = 0x01FF0888uL;    // PLL1/PLL2/PLL3配置为VCOH(192 MHz 到 836 MHz)
  14.     RCC->PLL1DIVR = 0x010102C7uL;    // PLL1倍频200,VCO1配置为800MHz
  15.     RCC->PLL2DIVR = 0x01010263uL;    // PLL2倍频100,VCO2配置为400MHz
  16.     RCC->PLL3DIVR = 0x01010263uL;    // PLL3倍频100,VCO3配置为400MHz
  17.     SET_BIT(RCC->CR, 0x15000000uL);    // 开启PLL1/PLL2/PLL3
  18.    
  19.     FLASH->ACR = 0x00000022uL;    // 闪存访问等待周期2
  20.     SET_BIT(RCC->CFGR, 0x04000000uL);    // MCO2 = sys_ck/2
  21.     RCC->D1CFGR = 0x00000048uL;    // sys_d1cpre_ck = sys_ck/1,rcc_hclk3 = sys_d1cpre_ck/2,rcc_pclk3 = rcc_hclk3/2
  22.     RCC->D2CFGR = 0x00000440uL;    // rcc_pclk2 = rcc_hclk2/2,rcc_pclk1 = rcc_hclk1/2
  23.     RCC->D3CFGR = 0x00000040uL;    // rcc_pclk4 = rcc_hclk4/2
  24.    
  25.     Delay(DelayTime);
  26.     while (READ_BIT(RCC->CR, 0x3F000000uL) != 0x3F000000uL);    // 等待PLL时钟锁定
  27.     Delay(DelayTime);
  28.     SET_BIT(RCC->CFGR, 0x00000003uL);    // 切换到PLL时钟
  29.     Delay(DelayTime);
  30.     while (READ_BIT(RCC->CFGR, 0x00000038uL) != 0x00000018uL);    // 等待PLL时钟切换完成
  31. //-------------------------------------------------------------
复制代码
  
SCT文件如下,把需要加速的函数放到DTCM:
  1. LR_IROM1 0x08000000 0x00200000  {    ; load region size_region
  2.   ER_IROM1 0x08000000 0x00200000  {  ; load address = execution address
  3.    *.o (RESET, +First)
  4.    *(InRoot$Sections)
  5.    .ANY (+RO)
  6.    .ANY (+XO)
  7.   }
  8.   RW_IRAM1 0x20000000 0x00020000  {  ; RW data
  9.    _bgrtss_smapi_cm3_012_001.o (+RW +ZI)
  10.    _bgrtsystemservice_cm3_012_001.o
  11.    _bgrtscheduler_cm3_012_001.o (+RW +ZI)
  12.    _bgrtswitcher_cm4f_012_001.o
  13.    
  14.    startup_bgrtss_armcm4_rvmdk.o (+RW +ZI)
  15.    blinky.o (+RW +ZI)
  16.    io_atomicaccess_hdi_001_000.o
  17.    pid_hdp_api_003_012.o
  18.    io_atomicaccess_master1.o (+RW +ZI)
  19.    task4.o (+RW +ZI)
  20.   }
  21.   RW_IRAM2 0x24000000 0x00080000  {
  22.    .ANY (+RW +ZI)
  23.   }
  24. }
复制代码
  
CPU访问I/O口需要经过两级总线矩阵,慢是有道理的,看来H系列只能这样了:

2.PNG (621.6 KB, 下载次数: 0)

下载附件

2

2018-12-15 00:07 上传


huangqi412
4楼-- · 2019-12-19 13:15
 精彩回答 2  元偷偷看……
laoshuhunya
5楼-- · 2019-12-19 13:33
huangqi412 发表于 2018-12-15 08:59
主频几百M, 软件翻转只有16M   所有脉冲都改成定时器操作估计还快些了。

用软件模拟通讯接口基本上就I2C,而I2C速率很慢,速率较高的SPI和其他通讯接口就少有用软件模拟了。开关量输出的话16.7MHz也基本够用。
所以实际应用问题不大,估计这也是ST的设计思路。
SCREA
6楼-- · 2019-12-19 17:05
laoshuhunya 发表于 2018-11-25 12:16
此表摘自STM32F767数据手册:

最差20Mhz,一般50Mhz ,看典型值,不要只关注最大值

一周热门 更多>