6208|10

76

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

我的STM32到底跑多快? [复制链接]

我的 STM32 到底跑多快?
我在 STM32F103RB 的开发板上, 写如下代码:

  uint32_t x = 0x009CF260, y;
  while (1)  {
   if (--x ==0) {
  x = 0x009CF260;
  y = 1;
  if(GPIOA->IDR & 1) y <<= 16;
  GPIOA->BSRR = y;
}
  }
为什么  x = 0x009CF260? 这是推算出来的, 目的是1秒钟翻转一次 PA0.
怎么推算的呢?
  if (SysTick_Config(SystemFrequency / 8)) { while(1);}
  设定 1/8 秒一次 SysTick 中断. 由调试器读取寄存器的值.
  0x008961ae,0x0075c362,0x00622516...
             0x00139E4C,0x00139E4C...
             0x00139E4C * 8 = 0x009CF260
那么在  0x00139E4C 个循环里, 到底执行了多少条指令呢? 看下面的编译结果           
;;;72       while (1)  {
;;;73        if (--x ==0) {
;;;74       x = 0x009CF260;
;;;75       y = 1;
;;;76       if(GPIOA->IDR & 1) y <<= 16;
000070  4909              LDR      r1,|L1.152|
000072  4625              MOV      r5,r4                 ;53
000074  f44f3280          MOV      r2,#0x10000
000078  e000              B        |L1.124|
                  |L1.122|
00007a  e7fe              B        |L1.122|
                  |L1.124|
00007c  1e64              SUBS     r4,r4,#1              ;73
00007e  d1fd              BNE      |L1.124|
000080  f8d13808          LDR      r3,[r1,#0x808]
000084  462c              MOV      r4,r5                 ;74
000086  2001              MOVS     r0,#1                 ;75
000088  07db              LSLS     r3,r3,#31
00008a  d000              BEQ      |L1.142|
00008c  4610              MOV      r0,r2
                  |L1.142|
;;;77       GPIOA->BSRR = y;
00008e  f8c10810          STR      r0,[r1,#0x810]
000092  e7f3              B        |L1.124|
;;;78      }
;;;79       }
;;;80     }
    分析: 从上面的编译结果, 可以看到, 变量 x 被分配给寄存器 R4,
在标号 |L1.124| 后面两条指令, 就执行了 减1 不为零, 再循环的任务.
也就是说, 1 秒钟, 就执行了 0x009CF260 = 10285664 个循环.
    通过 SysTick_Config 函数, 可以肯定, 现在的执行频率是 72MHz.
据此推算, 这两条指令的循环需要 7 个周期,
也就是说, 后面的分支跳转指令需要 6 个周期?  有这么慢?
我的 JLINK V8 没有告诉我!
此帖出自stm32/stm8论坛

最新回复

phb
                                 如果楼主要研究STM32的指令周期,请仔细阅读ARM的相关文件,你这样只靠实验,花费了很多时间和精力,也很难得出正确的结论。  详情 回复 发表于 2010-2-8 10:49
点赞 关注
 

回复
举报

82

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
                                 这个计算需要考虑流水线和Flash的插入等待周期效应。
此帖出自stm32/stm8论坛
 
 

回复

64

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
发现更为奇怪的结果了: 看下面的修改的代码
  while (1)  {
          if ((--x)&&(--x ==0)) {
                x = SPEED1S;                 
                y = 1;
                if(GPIOA->IDR & 1) y *= 0x10000;
                GPIOA->BSRR = y;
        }
  }
  
;;;75       while (1)  {
;;;76               if ((--x)&&(--x ==0)) {
;;;77                     x = SPEED1S;                 
;;;81                     y = 1;
;;;82                     if(GPIOA->IDR & 1) y *= 0x10000;
000072  490b              LDR      r1,|L1.160|
000074  4625              MOV      r5,r4                 ;54
000076  f44f3280          MOV      r2,#0x10000
00007a  e000              B        |L1.126|
                  |L1.124|
00007c  e7fe              B        |L1.124|
                  |L1.126|
00007e  1e64              SUBS     r4,r4,#1              ;76
000080  d0fd              BEQ      |L1.126|
000082  1e64              SUBS     r4,r4,#1              ;76
000084  d1fb              BNE      |L1.126|
000086  f8d13808          LDR      r3,[r1,#0x808]
00008a  462c              MOV      r4,r5                 ;77
00008c  2001              MOVS     r0,#1                 ;81
00008e  07db              LSLS     r3,r3,#31
000090  d000              BEQ      |L1.148|
000092  4610              MOV      r0,r2
                  |L1.148|
;;;83                     GPIOA->BSRR = y;
000094  f8c10810          STR      r0,[r1,#0x810]
000098  e7f1              B        |L1.126|
;;;84             }
;;;85       }

    分析: 从上面的编译结果, 可以看到, 变量 x 仍被分配给寄存器 R4,
在标号 |L1.126| 后面四条指令, 就执行了两次减1 后判断的循环任务.
这两个分支, 一个不需要跳转, 另一个需要跳转. 接下来看测试的结果.
下面是每次 Systick 中断中读取到的 x(R4) 的值.

  0x0075c35e,0x004e86c6,0x00274a2e,0x00000d96
差值       ,0x00273c98,0x00273c98,0x00273c98

也就是说, 1 秒钟, 执行了 0x273c98 * 4 = 0x9CF260 个循环.
对, 仍然是 0x9CF260 , 写这里的时候, 我反复过 n 次了.
有人要说了,  1/8 秒不是要乘以 8 嘛, 但是一次循环里执行了两次减1.

据此推算, 这四条指令的循环一次需要 7 个周期,
难道说减法指令和分支不跳转不需要时间, 光那条分支后跳转指令需要 7 个周期?
此帖出自stm32/stm8论坛
 
 

回复

72

帖子

0

TA的资源

一粒金砂(初级)

4
 
                                 分支后跳转指令需要清空流水线和重新加载流水线,重新加载流水线需要读Flash,这些都需要时间。
此帖出自stm32/stm8论坛
 
 
 

回复

68

帖子

0

TA的资源

一粒金砂(初级)

5
 
                                 主要是看你的程序优化的效率
此帖出自stm32/stm8论坛
 
 
 

回复

73

帖子

0

TA的资源

一粒金砂(初级)

6
 
                                 在处理复杂的算法上好像没啥优势
此帖出自stm32/stm8论坛
 
 
 

回复

59

帖子

0

TA的资源

一粒金砂(初级)

7
 
                                 不能这么测速度吧
此帖出自stm32/stm8论坛
 
 
 

回复

64

帖子

0

TA的资源

一粒金砂(初级)

8
 
                                 学到新东西了……
此帖出自stm32/stm8论坛
 
 
 

回复

69

帖子

0

TA的资源

一粒金砂(初级)

9
 
                                 速度够用就行了,一般对速度的要求没那么高,再说ST的速度已经很快了
此帖出自stm32/stm8论坛
 
 
 

回复

66

帖子

0

TA的资源

一粒金砂(初级)

10
 
看样子, 调试器通信是需要时间的. 问题一定在调试器上面;
为此, 重新修改 Systick 中断服务程序, 将上面的计数器 x 记录下来保存到内存,
若干次后看保存的结果. 相信这样能脱离调试器的影响了吧.
哦, 获取寄存器的值是 C 所难办到的事情, 我使用下面的汇编代码来完成.

__inline __asm  unsigned long getdat(void) {
        mov r0, R4;
        bx         lr;
}  

下面是 Systick 中断服务程序, 取 4 次的值, 然后在把断点放在 改变 PA1 的地方.

volatile unsigned char ucnt;  
unsigned long ldat[16];
void SysTick_Handler(void) {
        unsigned long cnt, dat = getdat();
        unsigned long dsp = 2;
        cnt = ucnt;
        ldat[cnt] = dat;
        cnt = (ucnt +1)%4; ucnt = cnt;
        if (cnt ==0) {
                if(GPIOA->IDR&2) dsp <<= 16;
                GPIOA->BSRR = dsp;
        }
}

    下面是记录到的连续 4 个数据.
  0x861CA0,0x6F394B,0x5855F5,0x41729F
差值      0x16E355,0x16E356,0x16E356  * 8 = B71AB0  (11999920)

这样的结果应该比较真实.两条指令共 6 个周期, 分支跳转使用 5 个周期.      
    下面是使用后面的代码 (四条指令一个循环) 记录到的连续 4 个数据.
      
  0x7E7B80,0x5FF70E,0x323062,0x13ABF0
差值      0x1E8472,0x2DC6AC,0x1E8472  * 4 = 7A11C8  (7999944)
      
     这里有个过分超差的值, 剩余 2 个是比较合理, 计算结果为 9 个周期.
估计应该是运算指令 1 个周期, 分支跳转 5 个周期, 分支不跳转 2 个周期.      
     另外发现一个过分超差的值, 经过多次调试, 发现会若干次后出现一次.
会不会就是前面提到的调试器的影响呢?
此帖出自stm32/stm8论坛
 
 
 

回复

78

帖子

0

TA的资源

一粒金砂(初级)

11
 
                                 如果楼主要研究STM32的指令周期,请仔细阅读ARM的相关文件,你这样只靠实验,花费了很多时间和精力,也很难得出正确的结论。
此帖出自stm32/stm8论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表