[STM32GENERIC] HAL Timer

Discussions about the STM32generic core
Post Reply
ChrisMicro
Posts: 308
Joined: Fri Mar 24, 2017 4:51 pm
Location: Germany

[STM32GENERIC] HAL Timer

Post by ChrisMicro » Thu May 18, 2017 10:00 am

Hello,

because for many applications a timer interrupt would be really useful, I just took the HAL-example from michaeli and tried to add the intterupt.
The code should run on a ST32F407 but the second LED in the interrupt routine is not blinking.
Are the interrupt handlers in STM32generic not set for the timer interrupts?

Code: Select all

/*

 http://www.stm32duino.com/viewtopic.php?f=42&t=1966&start=90#p27155

 Timer interrupt
 https://visualgdb.com/tutorials/arm/stm32/timers/

*/
//#include "STM32_HAL.h" not needed, auto included
uint32_t prev = 0;
int seconds = 0;

static TIM_HandleTypeDef s_TimerInstance = 
{
  .Instance = TIM2
};

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
{

  if(htim_base->Instance==TIM2)
  {
  /* USER CODE BEGIN TIM2_MspInit 0 */

  /* USER CODE END TIM2_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_TIM2_CLK_ENABLE();
    /* Peripheral interrupt init */
    HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM2_IRQn);
  /* USER CODE BEGIN TIM2_MspInit 1 */

  /* USER CODE END TIM2_MspInit 1 */
  }

}

/**
* @brief This function handles TIM2 global interrupt.
*/
void TIM2_IRQHandler(void)
{
  /* USER CODE BEGIN TIM2_IRQn 0 */

  /* USER CODE END TIM2_IRQn 0 */
  HAL_TIM_IRQHandler(&s_TimerInstance);
    toggleLed_RED();
  /* USER CODE BEGIN TIM2_IRQn 1 */

  /* USER CODE END TIM2_IRQn 1 */
}

void setup() 
{
  Serial.begin(115200); // Serial is SerialUSB
  pinMode(LED_BUILTIN,OUTPUT);
  pinMode(LED_RED,OUTPUT);

  __TIM2_CLK_ENABLE();
  s_TimerInstance.Init.Prescaler = 42000 - 1; //APB1 TIM2 has 84MHZ,
  s_TimerInstance.Init.CounterMode = TIM_COUNTERMODE_UP;
  s_TimerInstance.Init.Period = 2000 - 1; // prescaler gives 2khz time base
  s_TimerInstance.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  s_TimerInstance.Init.RepetitionCounter = 0;
  HAL_TIM_Base_Init(&s_TimerInstance);
  HAL_TIM_Base_Start(&s_TimerInstance);

  // ch: intterupt config
  HAL_TIM_Base_MspInit(&s_TimerInstance);

  
  
//TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
}

#define LEDPIN     LED_BUILTIN // Blue Pill LED
#define INITLED    pinMode(LEDPIN, OUTPUT)

#define LEDON      digitalWrite(LEDPIN, HIGH)
#define LEDOFF     digitalWrite(LEDPIN, LOW)

void toggleLed()
{
  static uint8_t flag=0;

  if(flag) LEDON;
  else     LEDOFF;

  flag^=1;
}

void toggleLed_RED()
{
  static uint8_t flag=0;

  if(flag) digitalWrite(LED_RED,HIGH);
  else     digitalWrite(LED_RED,LOW);

  flag^=1;
}

void loop() 
{
  if (__HAL_TIM_GET_COUNTER(&s_TimerInstance) == 0) 
  {
    uint32_t now = micros();
    Serial.print("diff=");
    Serial.println(now - prev);
    Serial.println(now);
    prev = micros();

    Serial.print(seconds++);
    Serial.println(" seconds");
    toggleLed();

  }
}

danieleff
Posts: 336
Joined: Thu Sep 01, 2016 8:52 pm
Location: Hungary
Contact:

Re: [STM32GENERIC] HAL Timer

Post by danieleff » Thu May 18, 2017 10:09 am

void TIM2_IRQHandler
should be
extern "C" void TIM2_IRQHandler

But because PWM is using TIM2 that, you will probably get a compile error. So try TIM3

ChrisMicro
Posts: 308
Joined: Fri Mar 24, 2017 4:51 pm
Location: Germany

Re: [STM32GENERIC] HAL Timer

Post by ChrisMicro » Thu May 18, 2017 1:09 pm

Hi Daniel,

thank you for the quick response. I just changed to TIM3 but now it does not even blink without IRQ.
Can it be that due to the usage of TIM2 for PWM there is some pre-inititalzation from the framework which is not done for TIM3 ?

Code: Select all

/*

 http://www.stm32duino.com/viewtopic.php?f=42&t=1966&start=90#p27155

 Timer interrupt
 https://visualgdb.com/tutorials/arm/stm32/timers/

*/
//#include "STM32_HAL.h" not needed, auto included
uint32_t prev = 0;
int seconds = 0;

static TIM_HandleTypeDef s_TimerInstance = 
{
  .Instance = TIM3
};

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
{

  if(htim_base->Instance==TIM3)
  {
  /* USER CODE BEGIN TIM3_MspInit 0 */

  /* USER CODE END TIM3_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_TIM3_CLK_ENABLE();
    /* Peripheral interrupt init */
    HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM3_IRQn);
  /* USER CODE BEGIN TIM3_MspInit 1 */

  /* USER CODE END TIM3_MspInit 1 */
  }

}

/**
* @brief This function handles TIM3 global interrupt.
*/
extern "C" void TIM3_IRQHandler(void)
{
  /* USER CODE BEGIN TIM3_IRQn 0 */

  /* USER CODE END TIM3_IRQn 0 */
  HAL_TIM_IRQHandler(&s_TimerInstance);
    toggleLed_RED();
  /* USER CODE BEGIN TIM3_IRQn 1 */

  /* USER CODE END TIM3_IRQn 1 */
}

void setup() 
{
  Serial.begin(115200); // Serial is SerialUSB
  pinMode(LED_BUILTIN,OUTPUT);
  pinMode(LED_RED,OUTPUT);

  __TIM3_CLK_ENABLE();
  s_TimerInstance.Init.Prescaler = 42000 - 1; //APB1 TIM3 has 84MHZ,
  s_TimerInstance.Init.CounterMode = TIM_COUNTERMODE_UP;
  s_TimerInstance.Init.Period = 2000 - 1; // prescaler gives 2khz time base
  s_TimerInstance.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  s_TimerInstance.Init.RepetitionCounter = 0;
  HAL_TIM_Base_Init(&s_TimerInstance);
  HAL_TIM_Base_Start(&s_TimerInstance);

  // ch: intterupt config
  //HAL_TIM_Base_MspInit(&s_TimerInstance);

}

#define LEDPIN     LED_BUILTIN // Blue Pill LED
#define INITLED    pinMode(LEDPIN, OUTPUT)

#define LEDON      digitalWrite(LEDPIN, HIGH)
#define LEDOFF     digitalWrite(LEDPIN, LOW)

void toggleLed()
{
  static uint8_t flag=0;

  if(flag) LEDON;
  else     LEDOFF;

  flag^=1;
}

void toggleLed_RED()
{
  static uint8_t flag=0;

  if(flag) digitalWrite(LED_RED,HIGH);
  else     digitalWrite(LED_RED,LOW);

  flag^=1;
}

void loop() 
{
  if (__HAL_TIM_GET_COUNTER(&s_TimerInstance) == 0) 
  {
    uint32_t now = micros();
    Serial.print("diff=");
    Serial.println(now - prev);
    Serial.println(now);
    prev = micros();

    Serial.print(seconds++);
    Serial.println(" seconds");
    toggleLed();

  }
}

danieleff
Posts: 336
Joined: Thu Sep 01, 2016 8:52 pm
Location: Hungary
Contact:

Re: [STM32GENERIC] HAL Timer

Post by danieleff » Thu May 18, 2017 3:52 pm

It seems that the original code was compiled in c, not c++.

HAL_TIM_Base_MspInit also needs extern "C", and HAL_TIM_Base_Start_IT starts with interrupts, not HAL_TIM_Base_Start.

The whole code seems to be quite complex for an example. This should do the same:

Code: Select all

static TIM_HandleTypeDef s_TimerInstance = {
  .Instance = TIM3
};

extern "C" void TIM3_IRQHandler(void) {
  HAL_TIM_IRQHandler(&s_TimerInstance);
  digitalWrite(LED_RED, !digitalRead(LED_RED));
}

void setup() {
  Serial.begin(115200); // Serial is whatever you select in the "Serial communication" menu option
  pinMode(LED_BUILTIN,OUTPUT);
  pinMode(LED_RED,OUTPUT);

  HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(TIM3_IRQn);

  __HAL_RCC_TIM3_CLK_ENABLE();
  s_TimerInstance.Init.Prescaler = 42000 - 1; //APB1 TIM3 has 84MHZ,
  s_TimerInstance.Init.CounterMode = TIM_COUNTERMODE_UP;
  s_TimerInstance.Init.Period = 2000 - 1; // prescaler gives 2khz time base
  s_TimerInstance.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  s_TimerInstance.Init.RepetitionCounter = 0;
  HAL_TIM_Base_Init(&s_TimerInstance);
  HAL_TIM_Base_Start_IT(&s_TimerInstance);
}

uint32_t prev = 0;

void loop() {
  if (__HAL_TIM_GET_COUNTER(&s_TimerInstance) == 0) {
    uint32_t now = micros();
    Serial.print("diff=");
    Serial.println(now - prev);
    Serial.println(now);
    prev = micros();

    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));

  }
}


ChrisMicro
Posts: 308
Joined: Fri Mar 24, 2017 4:51 pm
Location: Germany

Re: [STM32GENERIC] HAL Timer

Post by ChrisMicro » Thu May 18, 2017 4:45 pm

Thank you very much. It works :D
almost ...
The red led is blinking from the start as expected.
But the green led blinks the first 6 times very short ( I estimate~10ms ). After that time it blinks simultaneously with the red led, as expected.

So, I'm quite satisfied with the result and I will try probably on weekends to find out the reason.

About the coding style we should should discuss more after that. ;)

ChrisMicro
Posts: 308
Joined: Fri Mar 24, 2017 4:51 pm
Location: Germany

Re: [STM32GENERIC] HAL Timer

Post by ChrisMicro » Tue May 23, 2017 5:00 pm

I think the problem with the second led was the polling in the "loop" so I removed it.

I've added the example to the repo.

Probably the example could run on the most boards, not only the STM32F407.

Because it was running so well, I tried to add the IRQ to the I2S.

But this doesn't work. There seems not to be an interrupt:

Code: Select all

#include "I2S.h"

// setup  with masterclock enabled
I2SClass I2S(SPI3, PC12 /*sd*/ , PA4 /*ws*/, PC10 /*ck*/, PC7/* MCK*/); 


extern "C" void SPI3_IRQHandler(void) 
{
  HAL_I2S_IRQHandler(&I2S.handle);
  digitalWrite(LED_RED, !digitalRead(LED_RED) );
    I2S.write(1);
}

void setup()
{  
  I2S.begin(I2S_PHILIPS_MODE, 44000, 16);

  HAL_NVIC_SetPriority( SPI3_IRQn, 0, 0 );
  HAL_NVIC_EnableIRQ  ( SPI3_IRQn );
//  HAL_SPI_Base_Start_IT ( &I2S.handle );

  pinMode(LED_GREEN,OUTPUT);
  pinMode(LED_RED,OUTPUT);
}

void loop()
{
  static uint16_t dacValue;
  
  I2S.write(dacValue); 
  delay(10);
  dacValue+=300; // saw tooth
  digitalWrite(LED_GREEN, !digitalRead(LED_GREEN) );
}
Do you have any idea?

vitor_boss
Posts: 61
Joined: Wed Apr 19, 2017 9:50 am

Re: [STM32GENERIC] HAL Timer

Post by vitor_boss » Fri Jul 14, 2017 2:54 am

sorry but I'm not understanding this timer structure.
Could you provide examples on how use this with your code?

Code: Select all

  Timer3.attachInterrupt(1, ignitionSchedule1Interrupt);
  Timer3.attachInterrupt(2, ignitionSchedule2Interrupt);
  Timer3.attachInterrupt(3, ignitionSchedule3Interrupt);
  Timer3.attachInterrupt(4, ignitionSchedule4Interrupt);
this is libmaple code.
Thank you in advance

Post Reply