简体   繁体   中英

Cortex-M0+ timer prescaler is not slowing down TIM2

I am trying to measure the performance of some code using the TIM2 timer on the STM32L031K6 (Cortex-M0+). Because the M0+ only offers 16-bit counters, I want to set the prescaler of TIM2 to count slower. However, it seems to show no effect at all. The timer still runs at maximum speed, which is not desirable for my use case.

I used libopencm3 before, but now I am writing to the registers directly via pointers, because I won't have access to libopencm3 afterwards anyways. I looked through the datasheet of the STM32L0 series and read how to set up the timers directly. Setting up the timer and measuring some small code code (for loop with nops) works perfectly. But setting the prescaler won't work. I wrote the value (for example 0x1234) to the prescale register and read it again to make sure the write actually worked. I tried to trigger the update event, because it seems some buffering is going on with shadow registers but it also didn't work.

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
}

I expected that the count is lower if I set a prescaler. However, I always get the same value. For example 1326 for a loop of nops.

You need to generate an update event, you can do this by setting bit 0 of the timer's EGR register.

Your two lines where you've commented "I tried triggering an update here", you're using the ^= operator, to set bits in a register use |= instead.

You should also use the human readable defines provided by ST for the registers and their addresses. This will allow you to write something like TIM2->EGR |= TIM_EGR_UG; to generate your update event, much more readable than *( (uint32_t*) 0x40000014 ) |= 1;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM