Cortex-M0+ 定时器预分频器不会减慢 TIM2
Cortex-M0+ timer prescaler is not slowing down TIM2
我正在尝试使用 STM32L031K6 (Cortex-M0+) 上的 TIM2 计时器测量某些代码的性能。
因为M0+只提供16位计数器,所以我想把TIM2的预分频器设置得慢一些。但是,它似乎根本没有显示出任何效果。定时器仍然以最大速度运行,这对我的用例来说是不可取的。
我之前用的是libopencm3,现在是直接通过指针写入寄存器,因为反正之后我就不能访问libopencm3了。
我翻阅了STM32L0系列的数据表,阅读了如何直接设置定时器。设置定时器和测量一些小代码(for loop with nops)工作得很好。但是设置预分频器是行不通的。我将值(例如 0x1234)写入预分频寄存器并再次读取以确保写入确实有效。我试图触发更新事件,因为影子寄存器似乎正在进行一些缓冲,但它也没有用。
void __attribute__ ((noinline)) timer_setup()
{
*( (uint32_t*) 0x40021038 ) |= 1; //Enable Timer in RCC_APB1ENR (Bit 0)
*( (uint32_t*) 0x40000028 ) = 0x1234; //Some prescaler
*( (uint32_t*) 0x4000002C ) = 0xFFFF; //Auto-Reload to max 2**16
// *( (uint32_t*) 0x40000000 ) ^= 2; //I tried triggering an update here
// *( (uint32_t*) 0x40000014 ) ^= 1; //But it also didn't work
*( (uint32_t*) 0x40000000 ) ^= 1; //Enable the timer
}
void __attribute__ ((noinline)) timer_stop()
{
*( (uint32_t*) 0x40000000 ) ^= 1; //Stop the timer
}
int __attribute__ ((noinline)) timer_value()
{
return *( (uint32_t*) 0x40000024 ); //Read the counter
}
我预计如果设置预分频器,计数会更低。但是,我总是得到相同的值。例如 1326 表示一个 nops 循环。
您需要生成一个更新事件,您可以通过设置计时器 EGR
寄存器的位 0 来实现。
你评论的两行 "I tried triggering an update here",你正在使用 ^=
运算符,要在寄存器中设置位,请改用 |=
。
您还应该使用 ST 为寄存器及其地址提供的人类可读定义。这将允许您编写类似 TIM2->EGR |= TIM_EGR_UG;
的内容来生成您的更新事件,比 *( (uint32_t*) 0x40000014 ) |= 1;
更具可读性
我正在尝试使用 STM32L031K6 (Cortex-M0+) 上的 TIM2 计时器测量某些代码的性能。 因为M0+只提供16位计数器,所以我想把TIM2的预分频器设置得慢一些。但是,它似乎根本没有显示出任何效果。定时器仍然以最大速度运行,这对我的用例来说是不可取的。
我之前用的是libopencm3,现在是直接通过指针写入寄存器,因为反正之后我就不能访问libopencm3了。 我翻阅了STM32L0系列的数据表,阅读了如何直接设置定时器。设置定时器和测量一些小代码(for loop with nops)工作得很好。但是设置预分频器是行不通的。我将值(例如 0x1234)写入预分频寄存器并再次读取以确保写入确实有效。我试图触发更新事件,因为影子寄存器似乎正在进行一些缓冲,但它也没有用。
void __attribute__ ((noinline)) timer_setup()
{
*( (uint32_t*) 0x40021038 ) |= 1; //Enable Timer in RCC_APB1ENR (Bit 0)
*( (uint32_t*) 0x40000028 ) = 0x1234; //Some prescaler
*( (uint32_t*) 0x4000002C ) = 0xFFFF; //Auto-Reload to max 2**16
// *( (uint32_t*) 0x40000000 ) ^= 2; //I tried triggering an update here
// *( (uint32_t*) 0x40000014 ) ^= 1; //But it also didn't work
*( (uint32_t*) 0x40000000 ) ^= 1; //Enable the timer
}
void __attribute__ ((noinline)) timer_stop()
{
*( (uint32_t*) 0x40000000 ) ^= 1; //Stop the timer
}
int __attribute__ ((noinline)) timer_value()
{
return *( (uint32_t*) 0x40000024 ); //Read the counter
}
我预计如果设置预分频器,计数会更低。但是,我总是得到相同的值。例如 1326 表示一个 nops 循环。
您需要生成一个更新事件,您可以通过设置计时器 EGR
寄存器的位 0 来实现。
你评论的两行 "I tried triggering an update here",你正在使用 ^=
运算符,要在寄存器中设置位,请改用 |=
。
您还应该使用 ST 为寄存器及其地址提供的人类可读定义。这将允许您编写类似 TIM2->EGR |= TIM_EGR_UG;
的内容来生成您的更新事件,比 *( (uint32_t*) 0x40000014 ) |= 1;