在皮质 m7 上测量时钟周期数

Posted

技术标签:

【中文标题】在皮质 m7 上测量时钟周期数【英文标题】:Measuring clock cycle count on cortex m7 【发布时间】:2016-11-16 06:52:26 【问题描述】:

我一直在测量皮质 m4 上的时钟周期数,现在想在皮质 m7 上进行测量。我用的板子是STM32F746ZG。

对于 m4,一切都适用:

volatile unsigned int *DWT_CYCCNT;
volatile unsigned int *DWT_CONTROL;
volatile unsigned int *SCB_DEMCR;

void reset_cnt()
    DWT_CYCCNT   = (volatile unsigned int *)0xE0001004; //address of the register
    DWT_CONTROL  = (volatile unsigned int *)0xE0001000; //address of the register
    SCB_DEMCR    = (volatile unsigned int *)0xE000EDFC; //address of the register
    *SCB_DEMCR   = *SCB_DEMCR | 0x01000000;
    *DWT_CYCCNT  = 0; // reset the counter
    *DWT_CONTROL = 0; 


void start_cnt()
    *DWT_CONTROL = *DWT_CONTROL | 0x00000001 ; // enable the counter


void stop_cnt()
     *DWT_CONTROL = *DWT_CONTROL & 0xFFFFFFFE ; // disable the counter    


unsigned int getCycles()
    return *DWT_CYCCNT;

问题是当我在 m7 上运行时 DWT_CTRL 寄存器没有更改,并且保持 0x40000000 而不是更改为 0x40000001,因此循环计数始终为零。从我在其他帖子中读到的内容看来,您似乎需要将 FP_LAR 寄存器设置为 0xC5ACCE55 才能更改 DWT_CTRL。

我添加了这些定义(已尝试以下两个 FP_LAR_PTR 地址):

#define FP_LAR_PTR ((volatile unsigned int *) 0xe0000fb0) //according to reference
//#define FP_LAR_PTR ((volatile unsigned int *) 0xe0002fb0) //according to guy on the internet
// Lock Status Register lock status bit
#define DWT_LSR_SLK_Pos                1
#define DWT_LSR_SLK_Msk                (1UL << DWT_LSR_SLK_Pos)
// Lock Status Register lock availability bit
#define DWT_LSR_SLI_Pos                0
#define DWT_LSR_SLI_Msk                (1UL << DWT_LSR_SLI_Pos)
// Lock Access key, common for all
#define DWT_LAR_KEY                    0xC5ACCE55

还有这个功能:

void dwt_access_enable(unsigned int ena)
    volatile unsigned int *LSR;
    LSR = (volatile unsigned int *) 0xe0000fb4;
    uint32_t lsr = *LSR;;
    //printf("LSR: %.8X - SLI MASK: %.8X\n", lsr, DWT_LSR_SLI_Msk);

    if ((lsr & DWT_LSR_SLI_Msk) != 0) 
        if (ena) 
            //printf("LSR: %.8X - SLKMASK: %.8X\n", lsr, DWT_LSR_SLK_Msk);
            if ((lsr & DWT_LSR_SLK_Msk) != 0)     //locked: access need unlock
                *FP_LAR_PTR = DWT_LAR_KEY;
                printf("FP_LAR directly after change: 0x%.8X\n", *FP_LAR_PTR);
            
         else 
            if ((lsr & DWT_LSR_SLK_Msk) == 0)    //unlocked
                *FP_LAR_PTR = 0;
                 //printf("FP_LAR directly after change: 0x%.8X\n", *FP_LAR_PTR);
            
        
    

当我调用未注释的打印时,我得到 0xC5ACCE55,但是当我在函数返回后打印它时,我得到 0x00000000,我不知道为什么。我是在正确的轨道上还是完全错了?

编辑:我认为最好提一下我已经尝试在函数中不使用所有额外代码,而只尝试更改 LAR 寄存器。

BR 古斯塔夫

【问题讨论】:

根据 Cortex-M7 TRM,DWT_LAR is a write-only register... 哦,我的错,我没有注意到这一点,但有时我似乎可以从中读取。无论如何,如果我们忽略了我的错误,我仍然会得到 0 个时钟周期:启动计数器 -> 调用我要测量的函数 -> 停止计数器 -> 读取时钟周期。我已经尝试过不从 LAR 寄存器中读取任何内容,如果那样会破坏它,但它仍然不起作用。 您的 cortex-m7 是否实现了该功能?还有其他计时器(systick),如果实施也可以计算 ARM 核心时钟。 当我阅读 DWT_CTRL 时,它显示 0x40000000,根据web.eecs.umich.edu/~prabal/teaching/eecs373-f10/readings/… 页 C1-48 和 C1-49,如果不支持 CYCCNT,则第 25 位 NOCYCCNT 应该为 1,在这种情况下为 0。希望我回答了你的问题。 嗯到目前为止,当我读到 0xE0001000 时,我得到 0x00000000,当我读到 0xE00FF004 时,我得到 0xFFF02003 【参考方案1】:

再次查看文档,我现在非常怀疑 ARM TRM 中的拼写错误或复制粘贴错误。 0xe0000fb0 作为 ITM_LAR、DWT_LAR FP_LSR 的地址给出(对于 *_LSR 也是等效的)。由于所有其他 ITM 寄存器在页面 0xe0000000 中,看起来很像负责 Cortex-M7 文档的那部分的人采用了 Cortex-M4 寄存器定义,添加了新的 LAR 和 LSR到 ITM 页面,然后将它们复制到 DWT 和 FPB 页面,更新名称但忽略更新地址。

我敢打赌,你无意中解锁了 ITM_LAR(或真正的 FP_LAR),而 DWT_LAR 实际上位于 0xe0001fb0。

由 dwelch 编辑

某人欠某人一顿晚餐。

hexstring(GET32(0xE0001FB4));
hexstring(GET32(0xE0001000));
hexstring(GET32(0xE0001004));
hexstring(GET32(0xE0001004));

PUT32(0xE000EDFC,0x01000000);

hexstring(GET32(0xE0001FB4));
hexstring(GET32(0xE0001000));
hexstring(GET32(0xE0001004));
hexstring(GET32(0xE0001004));

PUT32(0xE0001000,0x40000001);

hexstring(GET32(0xE0001FB4));
hexstring(GET32(0xE0001000));
hexstring(GET32(0xE0001004));
hexstring(GET32(0xE0001004));

PUT32(0xE0001FB0,0xC5ACCE55);
PUT32(0xE0001000,0x40000001);

hexstring(GET32(0xE0001FB4));
hexstring(GET32(0xE0001000));
hexstring(GET32(0xE0001004));
hexstring(GET32(0xE0001004));

输出

00000000
00000000
00000000
00000000
00000003
40000000
00000000
00000000
00000003
40000000
00000000
00000000
00000001
40000001
0000774F
0000B311

TRM 中的表格看起来很有趣,正如其他文档显示的那样,您将 0xFB0 和 0xFB4 添加到基数中,Cortex-M7 的 DWT 的其余部分是 0xE0001xxx,而且看起来 LAR 和 LSR 确实被吃掉了0xE0001FB0 和 0xE0001FB4。

【讨论】:

好的,我一定会在星期一回来并回复您时尝试一下。我还在其他地方读到引用错误,但他建议改用 0xe0002fb0 但我试过了,但没有用。 是的,e0002fb0 看起来是 FPB 单元的相应锁,正如我所暗示的那样。似乎中间的那个人是唯一没有人尝试过的人;) 是的,我也想我应该将代码中的FP_LAR_PTR 更改为DWT_LAR_PTR,我在研究这个时感到困惑:) @Notlikethat 我编辑了你的答案而不是添加我自己的这是你的发现我只是比 OP 早几天做了实验。请根据自己的喜好重新编辑(或者一起删除我的编辑,无论如何)。 0xe0001fb0 也为我工作!现在唯一的问题是,与 m4 相比,它实际上显示了 dft 和 fft 操作的更多时钟周期,但这是一个不同的问题 :)【参考方案2】:

我建议不要在将它们定义为 CMSIS 的一部分时创建您自己的寄存器定义 - 这样做需要文档和您对它的解释都是正确的。在这种情况下,文档似乎确实不正确,但 CMSIS 标头是正确的。自动验证 CMSIS 标头比验证文档是否正确要容易得多,所以我每次都会信任 CMSIS。

我不确定FP_LAR 可能指的是哪个寄存器,但您的地址分配指的是ITM_LAR,但您似乎更可能打算使用Cortex-M4 缺少的DWT_LAR

尽管我建议相信它,但 CMSIS 4.00 省略了为 DWT_LSR/SWT_LAR 定义掩码,但我相信它们与相应的 ITM 掩码相同。

还要注意LAR 是一个只写寄存器 - 任何读取它的尝试都是没有意义的。

您使用 CMSIS 的代码是:

#include "core_cm7.h"  // Applies to all Cortex-M7

void reset_cnt()

    CoreDebug->DEMCR |= 0x01000000;
    DWT->CYCCNT = 0; // reset the counter
    DWT->CTRL = 0; 


void start_cnt()

    DWT->CTRL |= 0x00000001 ; // enable the counter


void stop_cnt()

     DWT->CTRL &= 0xFFFFFFFE ; // disable the counter    


unsigned int getCycles()

    return DWT->CYCCNT ;


// Not defined in CMSIS 4.00 headers - check if defined
// to allow for possible correction in later versions
#if !defined DWT_LSR_Present_Msk 
    #define DWT_LSR_Present_Msk ITM_LSR_Present_Msk
#endif
#if !defined DWT_LSR_Access_Msk 
    #define DWT_LSR_Access_Msk ITM_LSR_Access_Msk
#endif
#define DWT_LAR_KEY 0xC5ACCE55

void dwt_access_enable( unsigned ena )

    uint32_t lsr = DWT->LSR;;

    if( (lsr & DWT_LSR_Present_Msk) != 0 ) 
    
        if( ena ) 
        
            if ((lsr & DWT_LSR_Access_Msk) != 0) //locked: access need unlock
                
                DWT->LAR = DWT_LAR_KEY;
            
         
        else 
        
            if ((lsr & DWT_LSR_Access_Msk) == 0) //unlocked
               
                DWT->LAR = 0;
            
        
    

【讨论】:

您假设 CMSIS 是正确的。假设文档是正确的,这同样是坏/好。有人使用某些资源编写了 CMSIS 标头。对公司而言,明智的做法是拥有一个信息数据库并从中生成文档地址和头文件。我敢打赌这是例外而不是规则。 CMSIS 有自己的包袱,如有疑问,可能会从其中剪切和粘贴,但不要认为它比文档更正确。 同样,如果没有人阅读文档,如何修复它们?我已经张贴了一张票来武装这个,会看看它的去向,但至少有人已经得到通知。 @dwelch :我没有假设;我只是说 CMSIS 能够以文档不具备的方式进行自动化单元测试和验证。即使 CMSIS 与文档相匹配,它也不会比文档中用户实现的代码差 - 为什么要重新发明它?此外,core_cmX 是整个 CMSIS 的基础,并被数千个项目使用 - 比可能阅读到该详细级别的文档的开发人员要多得多。在 CMSIS 中,DWT_LAR/LSR 与文档(和 ITM)不同,这更合理。 @dwelch :您仍然需要阅读文档以了解寄存器的用途以及它们的工作原理 - CMSIS 不会告诉您。在这种情况下,使用 CMSIS 确实可以避免该问题。如果我使用 CMSIS 并发现问题,我会以相同的方式(反向)交叉检查文档,但从 CMSIS 开始工作会更少。 @Clifford FWIW,FP_LAR 是 Flash Patch/Breakpoint Unit 的 CoreSight LAR(它实际上并不支持它主要命名的东西,去看看......)

以上是关于在皮质 m7 上测量时钟周期数的主要内容,如果未能解决你的问题,请参考以下文章

数字频率计简单介绍

无法在STM32H7上正确设置Cortex M7 ITM

如何将 CUDA 时钟周期转换为毫秒?

NXP iMX8M Plus M7核心FreeRTOS开发

NXP iMX8M Plus M7核心FreeRTOS开发

基于stm32的多功能时钟2——DHT11测量温湿度