测量 cortex m7 上的时钟周期计数
Measuring clock cycle count on cortex m7
我一直在测量 cortex m4 上的时钟周期数,现在想在 cortex 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,但是当我在函数的 return 之后打印它时,我得到 0x00000000,我不知道为什么。我是在正确的轨道上还是完全错误?
编辑:我认为还值得一提的是,我已经尝试过在函数中没有所有额外代码,并且只尝试更改 LAR 寄存器。
BR
古斯塔夫
再次查看文档,我现在非常怀疑 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 中的 table 看起来很有趣,正如其他文档显示您将 0xFB0 和 0xFB4 添加到基数中一样,Cortex-M7 的 DWT 的其余部分是 0xE0001xxx,确实看起来LAR 和 LSR 分别为 0xE0001FB0 和 0xE0001FB4。
我建议不要创建自己的寄存器定义,因为它们被定义为 CMSIS 的一部分 - 这样做需要文档和您对它的解释都是正确的。在这种情况下,文档似乎确实不正确,但 CMSIS headers 是正确的。自动验证 CMSIS headers 比验证文档是否正确要容易得多,所以我每次都会信任 CMSIS。
我不确定寄存器 FP_LAR
可能指的是什么,但您的地址分配指的是 ITM_LAR
,但您似乎更有可能打算使用 Cortex-M4 缺少的 DWT_LAR
.
尽管我建议相信它,但 CMSIS 4.00 省略了为 DWT_LSR
/SWT_LAR
定义掩码,但我相信它们与相应的 ITM 掩码相同。
另请注意,LAR
是一个 write-only 寄存器 - 任何读取它的尝试都是没有意义的。
您使用 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;
}
}
}
}
我一直在测量 cortex m4 上的时钟周期数,现在想在 cortex 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,但是当我在函数的 return 之后打印它时,我得到 0x00000000,我不知道为什么。我是在正确的轨道上还是完全错误?
编辑:我认为还值得一提的是,我已经尝试过在函数中没有所有额外代码,并且只尝试更改 LAR 寄存器。
BR 古斯塔夫
再次查看文档,我现在非常怀疑 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 中的 table 看起来很有趣,正如其他文档显示您将 0xFB0 和 0xFB4 添加到基数中一样,Cortex-M7 的 DWT 的其余部分是 0xE0001xxx,确实看起来LAR 和 LSR 分别为 0xE0001FB0 和 0xE0001FB4。
我建议不要创建自己的寄存器定义,因为它们被定义为 CMSIS 的一部分 - 这样做需要文档和您对它的解释都是正确的。在这种情况下,文档似乎确实不正确,但 CMSIS headers 是正确的。自动验证 CMSIS headers 比验证文档是否正确要容易得多,所以我每次都会信任 CMSIS。
我不确定寄存器 FP_LAR
可能指的是什么,但您的地址分配指的是 ITM_LAR
,但您似乎更有可能打算使用 Cortex-M4 缺少的 DWT_LAR
.
尽管我建议相信它,但 CMSIS 4.00 省略了为 DWT_LSR
/SWT_LAR
定义掩码,但我相信它们与相应的 ITM 掩码相同。
另请注意,LAR
是一个 write-only 寄存器 - 任何读取它的尝试都是没有意义的。
您使用 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;
}
}
}
}