AnsweredAssumed Answered

Timer Input Capture and systick issue

Question asked by lee.paul.003 on Mar 22, 2015
Latest reply on Mar 23, 2015 by lee.paul.003
Hi,

I am trying to timestamp my frequency capture module with the systick register value but everytime, the systick register gets reloaded with a new value during a frequency capture. as shown below. I have loaded it with a large value as previously the systick was just setup as 1ms timer but the issue still occurs.

940518
940273
940019
939751
1001952
1001712

I am using g++ and the code are shown below.

Regards
Paul

#include "freqcounter.h"
#include "stm32f10x.h"
#include <stdlib.h>
 
static uint16_t IC2Value = 0;
static freq_cnt_callback registered_callback = NULL;
 
 
static void RCC_Configuration(void);
static void GPIO_Configuration(void);
static void NVIC_Configuration(void);
 
void init_freqcounter(void)
{
    RCC_Configuration();
    GPIO_Configuration();
    NVIC_Configuration();
 
    // Use the 36 MHz clock for the timer by setting the prescaler to 2.
    // Lowest frequency it can measured is 36 MHz / 65535 = 549.325 Hz.
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
    TIM_TimeBaseStructure.TIM_Prescaler = 0;
    TIM_TimeBaseStructure.TIM_Period = 65535; // Full range
    TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
 
 
    /* TIM2 configuration: PWM Input mode ------------------------
     The external signal is connected to TIM2 CH2 pin (PA.01),
     The Rising edge is used as active edge,
     The TIM2 CCR2 is used to compute the frequency value
    ------------------------------------------------------------ */
    TIM_ICInitTypeDef  TIM_ICInitStructure;
 
    TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
    TIM_ICInitStructure.TIM_ICFilter = 0x0;
 
    TIM_ICInit(TIM2, &TIM_ICInitStructure);
 
    // /* Select the TIM2 Input Trigger: TI2FP2 */
    TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2);
 
    /* Select the slave Mode: Reset Mode */
    TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);
 
    /* Enable the Master/Slave Mode */
    TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable);
 
    /* Enable the CC2 Interrupt Request */
    TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);
 
    /* TIM enable counter */
    TIM_Cmd(TIM2, ENABLE);
}
 
void register_freqcnt_callback(freq_cnt_callback callback_func) {
    registered_callback = callback_func;
}
 
uint32_t get_system_clock(void) {
  return SystemCoreClock;
}
 
static void RCC_Configuration(void)
{
    /* TIM2 clock enable */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
}
 
static void GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 
    GPIO_Init(GPIOA, &GPIO_InitStructure);
 
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);
}
 
static void NVIC_Configuration(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
 
    /* Enable the TIM2 global Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}
 
void TIM2_IRQHandler(void)
{
    if (TIM_GetITStatus(TIM2, TIM_IT_CC2) == SET)
    {
        /* Clear TIM2 Capture compare interrupt pending bit */
        TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);
 
        /* Get the Input Capture value */
        IC2Value = TIM_GetCapture2(TIM2);
 
        if (registered_callback != NULL) {
          registered_callback(IC2Value);
        }
    }
}

#include "stm32f10x.h"
#include <string.h>
 
#include "timer.h"
 
/*-------------------------------Global Variables-----------------------------*/
 
 
/*--------------------------------Module Setup--------------------------------*/
 
// Called before the main loop
void initialise_timer(void)
{
    milliSeconds = 0;
    microSeconds = 0;
    sysTickMicroValue = 0;
    prevMicroSeconds = 0;
 
    sysTickHandlerIndex = 0;
 
    // Set the systick for 1ms interrupts.
    SysTick_Config(2500000);
 
    //set systick interrupt priority
    //4 bits for preemp priority 0 bit for sub priority
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
     
    //i want to make sure systick has highest priority amount all other interrupts
    NVIC_SetPriority(SysTick_IRQn, 4);
}
 
/*------------------------------External Functions----------------------------*/
 
uint32_t get_systick(void)
{
    return SysTick->VAL;
}

#include "driver_adaptors/FreqCounterAdaptor.h"
 
 
namespace cfreqcounter {
extern "C" {
#include "freqcounter.h"
}
}
 
Queue <FreqLists> FreqCounterAdaptor::rxFifo;
ITimer * FreqCounterAdaptor::system_timer = 0;
 
FreqCounterAdaptor::FreqCounterAdaptor(ITimer &timer) {
  this->system_timer = &timer;
  cfreqcounter::init_freqcounter();
  cfreqcounter::register_freqcnt_callback(interrupt_callback);
}
 
bool FreqCounterAdaptor::get_last_freqlist(FreqLists * item) {
  if (rxFifo.isEmpty())
  {
    return false;
  }
  *item = rxFifo.dequeue();
 
  return true;
}
 
void FreqCounterAdaptor::interrupt_callback(uint16_t cnt_value) {
  FreqLists newData;
  newData.data = cnt_value;
  newData.timestamp = system_timer->get_systick();
  rxFifo.enqueue(newData);
}

int main(void) {
  TimerAdaptor timer_adaptor;
  FreqCounterAdaptor frequency_counter(timer_adaptor);
  UsartAdaptor usart;
 
  while (1) {
 
    FreqLists newData;
    if (frequency_counter.get_last_freqlist(&newData))
    {
      char freq_string[10] = { 0 };
      snprintf(freq_string, 10, "%lu,", frequency_counter.get_system_clock()/newData.data);
 
      while (!usart.transmit_data(std::string(freq_string)));
 
      snprintf(freq_string, 10, "%lu,", newData.microseconds_stamp);
 
      while (!usart.transmit_data(std::string(freq_string)));
    }
  }
}

Outcomes