uint64_t perfcounter_getcount(void) { struct stm32f4_timer_regs *tim2 = timer_get_regs(2); struct stm32f4_timer_regs *tim5 = timer_get_regs(5); uint32_t upper, lower; uint64_t count; /* * Ensure atomic read of complete upper + lower value. * * If lower overflows between reading upper and lower, the value of upper * is no longer valid, so it will not match the register, and another * attempt is made. * * The lower timer must overflow suffciently slowly! */ do { upper = raw_mem_read(&tim5->CNT); lower = raw_mem_read(&tim2->CNT); } while(upper != raw_mem_read(&tim5->CNT)); count = ((uint64_t)upper << 32) | lower; /* Return in system clock ticks */ return TIMER_PRESCALER * count; }
static inline uint64_t _ttc_get_freq(const pstimer_t *timer) { ttc_tmr_regs_t* regs = timer_get_regs(timer); uint32_t clk_ctrl = *regs->clk_ctrl; if (clk_ctrl & CLKCTRL_PRESCALE_EN) { return PCLK_FREQ >> (CLKCTRL_GET_PRESCALE_VAL(clk_ctrl) + 1); } else { return PCLK_FREQ;
/* Acts as slave timer, incrementing on update event */ static void init_tim5(void) { struct stm32f4_timer_regs *regs = timer_get_regs(5); /* Enable timer clock */ *RCC_APB1ENR |= RCC_APB1ENR_TIM5EN; /* No clock prescale, max count */ raw_mem_write(®s->PSC, 0); /* Maximum count value */ raw_mem_write(®s->ARR, UINT32_MAX); /* External clock slave mode */ raw_mem_set_bits(®s->SMCR, TIM_SMCR_SMS_EXT); /* Enable timer */ raw_mem_set_bits(®s->CR1, TIM_CR1_CEN); }
/* Acts as master timer, sends update event */ static void init_tim2(void) { struct stm32f4_timer_regs *regs = timer_get_regs(2); /* Enable timer clock */ *RCC_APB1ENR |= RCC_APB1ENR_TIM2EN; /* No clock prescale, max count */ raw_mem_write(®s->PSC, 0); /* Maximum count value */ raw_mem_write(®s->ARR, UINT32_MAX); /* Set update event as output in master control reg */ raw_mem_set_mask(®s->CR2, TIM_CR2_MMS_MASK, TIM_CR2_MMS_UP); /* Enable timer */ raw_mem_set_bits(®s->CR1, TIM_CR1_CEN); }