ARM M4每个周期指令(IPC)计数器 [英] ARM M4 Instructions per Cycle (IPC) counters

查看:3357
本文介绍了ARM M4每个周期指令(IPC)计数器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想指望了ARM Cortex-M4每执行周期指令数(或C​​ortex-M3)处理器。

I would like to count the number of Instructions per Cycle executed on an ARM cortex-M4 (or cortex-M3) processor.

它所需要的是:的指令数的code我要分析和(在运行时执行)的周期数的code需要执行。

What it's needed is: number of instructions (executed at runtime) of the code I want to profile and number of cycles that the code takes to execute.

1 - 周期数

使用循环计数器是非常容易和简单。

Use the cycle counter is quite easy and straightforward.

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

void reset_timer(){
    DWT_CYCCNT   = (int *)0xE0001004; //address of the register
    DWT_CONTROL  = (int *)0xE0001000; //address of the register
    SCB_DEMCR    = (int *)0xE000EDFC; //address of the register
    *SCB_DEMCR   = *SCB_DEMCR | 0x01000000;
    *DWT_CYCCNT  = 0; // reset the counter
    *DWT_CONTROL = 0; 
}

void start_timer(){
    *DWT_CONTROL = *DWT_CONTROL | 1 ; // enable the counter
}

void stop_timer(){
    *DWT_CONTROL = *DWT_CONTROL | 0 ; // disable the counter    
}

unsigned int getCycles(){
    return *DWT_CYCCNT;
}

main(){
    ....
    reset_timer(); //reset timer
    start_timer(); //start timer
    //Code to profile
    ...
    myFunction();
    ...
    stop_timer(); //stop timer
    numCycles = getCycles(); //read number of cycles 
    ...
}

2 - 指令数

我发现了一些文件上网冲浪数由的ARM Cortex-M3和Cortex-M4(的链接):

I found some documentation surfing the internet to count the number of instructions executed by the arm cortex-M3 and cortex-M4 (link):

  # instructions = CYCCNT - CPICNT - EXCCNT - SLEEPCNT - LSUCNT + FOLDCNT

这是他们提到在这里寄存器一>(从11-13页),这些都是存储器地址来访问它们:

The registers that they mention are documented here (from page 11-13) and these are the memory addresses to access them:

DWT_CYCCNT   = 0xE0001004
DWT_CONTROL  = 0xE0001000
SCB_DEMCR    = 0xE000EDFC
DWT_CPICNT   = 0xE0001008
DWT_EXCCNT   = 0xE000100C
DWT_SLEEPCNT = 0xE0001010
DWT_LSUCNT   = 0xE0001014
DWT_FOLDCNT  = 0xE0001018

的DWT_CONTROL寄存器用于使计数器,特别是作为记录周期计数器这里

但是,当我试图把所有的一起算每个周期执行的指令数我没有成功。

But when I tried to put all together to count the number of instructions executed per cycle I didn't succeed.

这里中有关于如何从GDB使用它们小导。

Here there is a small guide on how to use them from gdb.

这是不容易的是,一些寄存器是8位寄存器(DWT_CPICNT,DWT_EXCCNT,DWT_SLEEPCNT,DWT_LSUCNT,DWT_FOLDCNT),当它们溢出它们触发一个事件。我没有找到一个方法来收集该事件。有没有code片段,介绍了如何做到这一点或中断例程适合为。

What is not easy is that some registers are 8 bit registers (DWT_CPICNT, DWT_EXCCNT, DWT_SLEEPCNT, DWT_LSUCNT, DWT_FOLDCNT) and when they overflow they trigger an event. I didn't find a way to collect that event. There are no code snippet that explains how to do that or interrupt routines suitable for that.

这似乎而且,关于这些寄存器的地址使用观察点从GDB不起作用。 GDB不能停止时,寄存器改变数值。例如。在DWT_LSUCNT:

It seems moreover that using watchpoints from gdb on the addresses of those registers doesn't work. gdb is not able to stop when registers change value. E.g. on DWT_LSUCNT:

(gdb) watch *0xE0001014

更新:我发现在GitHub上这一项目解释如何使用DWT,ITM和ETM单位。但我没有检查是否正常工作!我将发布更新。

Update: I found this project on GitHub explaining how to use DWT, ITM and ETM units. But I didn't check if it works! I will post updates.

这是如何使用它们的任何想法?

Any idea on how to use them?

感谢您!

推荐答案

我不知道如何使用寄存器要使用它们的方式。但是,这里是我如何处理测量循环。

I have no idea how to use the registers the way you want to use them. But, here is how I deal with measuring cycles.

请确保您启用的的 SysTick控制和状态寄存器。有了适当的标题,你应该有访问SysTick寄存器为一个结构。

Make sure you enable the counter at the SysTick Control and Status Register. With the appropriate headers, you should have access to the SysTick registers as a structure.

测量由计数器功能拍摄的周期数。这是后来从任何测量值中减去。

Measure the number of cycles taken by the counter function. This is later subtracted from any measurements.

  SysTick->VAL = 0; // set 0
  // Measure delay on measurement  
  __disable_irq();
  a = (uint32_t) SysTick->VAL;
  //... measuring zero instructions
  b = (uint32_t) SysTick->VAL;
  __enable_irq();
  measure_delay = a - b;

现在测量功能。

SysTick->VAL = 0;
__disable_irq();
a = (uint32_t) SysTick->VAL;

//Assuming this function doesn't require interruptions

// INSERT CODE TO BE PROFILED
function_to_be_examined();

b = (uint32_t) SysTick->VAL;
__enable_irq();
cycles_profiled_code = a - b - measure_delay;

我希望它能帮助。

I hope it helps.

这篇关于ARM M4每个周期指令(IPC)计数器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆