我一直在测量皮质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
古斯塔夫

最佳答案

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

我打赌我晚餐时会不经意地解锁ITM_LAR(或真正的FP_LAR),而DWT_LAR实际上为0xe000 1 fb0。

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 。

关于c - 在Cortex M7上测量时钟周期计数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38355831/

10-10 22:38