Migration to STM32 Cores. Changes in Interrupts.

Post here all questions related to STM32 core if you can't find a relevant section!
billys7
Posts: 6
Joined: Fri Apr 24, 2020 3:38 pm

Migration to STM32 Cores. Changes in Interrupts.

Post by billys7 »

Recently i add from the board manager the STM32 Cores.

I used to work with low level programming and at this time i don't want to change it.
Using the STM32 Cores the code below is not working. It hang after a while, when it enter in the interrupt. I suppose i have to replace the interrupt vector "extern "C" void __irq_tim2()". I tried "void TIM2_IRQHandler()" with the same result.

What changes I need to make, in order for the following code to work?

Code: Select all

//Toggling the onboard led on PC13 every 2 sec.

volatile boolean led = 1 ;

#define RCCAPB1ENR_  (*((volatile uint32_t *) (0x40021000+0x1C)))
#define RCCAPB2ENR_  (*((volatile uint32_t *) (0x40021000+0x18)))
#define GPIOLC      (*((volatile uint32_t *) (0x40011000)))
#define GPIOHC      (*((volatile uint32_t *) (0x40011000+0x04)))
#define ODR_C       (*((volatile uint32_t *) (0x40011000+0x0C)))
#define BSRRC_      (*((volatile uint32_t *) (0x40011000+0x10)))

#define TIM2CR1    (*((volatile uint32_t *) (0x40000000)))
#define TIM2CR2    (*((volatile uint32_t *) (0x40000000+0x04)))
#define TIM2SMCR   (*((volatile uint32_t *) (0x40000000+0x08)))
#define TIM2DIER   (*((volatile uint32_t *) (0x40000000+0x0C)))
#define TIM2SR     (*((volatile uint32_t *) (0x40000000+0x10)))
#define TIM2EGR    (*((volatile uint32_t *) (0x40000000+0x14)))
#define TIM2CCMR1  (*((volatile uint32_t *) (0x40000000+0x18)))
#define TIM2CCMR2  (*((volatile uint32_t *) (0x40000000+0x1C)))
#define TIM2CCER   (*((volatile uint32_t *) (0x40000000+0x20)))
#define TIM2CNT    (*((volatile uint32_t *) (0x40000000+0x24)))
#define TIM2PSC    (*((volatile uint32_t *) (0x40000000+0x28)))
#define TIM2ARR    (*((volatile uint32_t *) (0x40000000+0x2C)))
#define TIM2CCR1   (*((volatile uint32_t *) (0x40000000+0x34)))
#define TIM2CCR2   (*((volatile uint32_t *) (0x40000000+0x38)))
#define TIM2CCR3   (*((volatile uint32_t *) (0x40000000+0x3C)))
#define TIM2CCR4   (*((volatile uint32_t *) (0x40000000+0x40)))
#define TIM2DCR    (*((volatile uint32_t *) (0x40000000+0x48)))
#define TIM2DMAR   (*((volatile uint32_t *) (0x40000000+0x4C)))

#define IPR8_        (*((volatile uint32_t *) (0xE000E100+0x308)))
#define ISER0_       (*((volatile uint32_t *) (0xE000E100)))

void setup() 
{
  Serial.begin(250000);  
  Serial.println("Start"); 
 
  RCCAPB1ENR_ = RCCAPB1ENR_ | 0x001  ;     // Enable Timer 2 RM p114
  RCCAPB2ENR_ = RCCAPB2ENR_ | 0x10;        // In order to make changes in GPIOC, Enable port row C.  RM p112 
  GPIOHC = 0x44144444;                     // Set output mode on PC13

  asm volatile("cpsie i");                 // Enables interrupts and configurable fault handlers. p99 C
  
  TIM2CR1   = 0;
  TIM2CR2   = 0;
  TIM2SMCR  = 0;
  TIM2DIER  = 0;
  TIM2SR    = 0;
  TIM2EGR   = 0;
  TIM2CCMR1 = 0;
  TIM2CCMR2 = 0;  
  TIM2CCER  = 0;
  TIM2CNT   = 0;
  TIM2PSC   = 0;
  TIM2ARR   = 65535;                       // Always FFFF
  TIM2CCR1  = 0;
  TIM2CCR2  = 0;
  TIM2CCR3  = 0;
  TIM2CCR4  = 0;
  TIM2DCR   = 0;
  TIM2DMAR  = 0;

       //Update_event = TIM_CLK/((PSC + 1)*(ARR + 1)) = 72.000.000. / ((35999+1)*(1999+1))= 1Hz = 1 per Sec 

  TIM2PSC   = 35999;                       // Set prescaler to 35999 (PSC + 1) Means 72.000.000 / 36000 = 2.000 counts per second p417
  TIM2ARR   = 1999;                        // Auto reload value 2000. p355
  TIM2DIER  = TIM2DIER | 0x1;              // Interrupt when the counter overflow. TIM_DIER_UIE = 1. p408
  TIM2CR1   = TIM2CR1 | 0x04;              // TIM_CR1_URS = 1 Only counter overflow/underflow generates an update interrupt or DMA request if enabled. p403
  IPR8_     =  IPR8_ & 0x20FFFFFF;         // Set highest priority 2. From the table TIM2 global interrupt = 35.p204 Reference Manual, Find the suitable IPR = 35 / 4,= 8 and the suitable byte 3
                                           // 0 being highest priority and 15 being lowest p118 Programming Manual. Move it to the left 4 positions. p125 Programming Manual 
  ISER0_    = ISER0_ | 0x10000000;         // Enable interrupt TIM2 global interrupt. From the table position TIM2 global interrupt = 28. p204 Reference Manual Position bit = 28 p120 Programming Manual.   
  TIM2SR    = TIM2SR & 0xFFFFFFFE;         // clear pending interrupt UIF flag  TIM_SR_UIF=0. p409. Always before enable an interrupt we must clear any pending interrupts.  
  TIM2EGR   = TIM2EGR| 0x0001;             // Re-initialize the counter and generates an update of the registers.
  TIM2CR1   = TIM2CR1 | 0x1;               // CEN = 1 Enable timer. p337 

}

void loop() 
{

  BSRRC_  = BSRRC_ |(1 << (13 + (led * 16))); // Toggle PC13. Lower 16 bits setting while higher bits clearing. p172
  Serial.println(led);                        // Show me Led status

}

extern "C" void __irq_tim2()                 // https://github.com/rogerclarkmelbourne/Arduino_STM32/blob/master/STM32F1/cores/maple/libmaple/stm32f1/performance/vector_table.S
//void TIM2_IRQHandler()
{
  TIM2SR   = TIM2SR & 0xFFFFFFFE;          // Never try and clear the flag that caused the interrupt as the last instruction in the ISR itself. It causes the ISR to reenter immediately.
  led = !led;                              // Reverse state 
}
Vasilis

mrburnette
Posts: 168
Joined: Thu Dec 19, 2019 1:23 am

Re: Migration to STM32 Cores. Changes in Interrupts.

Post by mrburnette »

billys7 wrote:
Sat Apr 25, 2020 1:48 pm
Recently i add from the board manager the STM32 Cores.

I used to work with low level programming and at this time i don't want to change it.
...
As Roger's LibMaple-based core does not have a setup JSON, I assume you installed the "Official STM32" core from github.com/STM32duino/Arduino_Core_STM32. If so, please look down that list to Boards Available.
Over 100 different boards supported in some manner/limitation. This is done as stated:
This porting is based on:

STM32Cube MCU Packages including:
The HAL hardware abstraction layer, enabling portability between different STM32 devices via standardized API calls
The Low-Layer (LL) APIs, a light-weight, optimized, expert oriented set of APIs designed for both performance and runtime efficiency
CMSIS device defintion for STM32
CMSIS: Cortex Microcontroller Software Interface Standard (CMSIS) is a vendor-independent hardware abstraction layer for the Cortex®-M processor series and defines generic tool interfaces. It has been packaged as a module for Arduino IDE: https://github.com/stm32duino/ArduinoModule-CMSIS
GNU Arm Embedded Toolchain: Arm Embedded GCC compiler, libraries and other GNU tools necessary for bare-metal software development on devices based on the Arm Cortex-M. Packages are provided thanks The xPack GNU Arm Embedded GCC: https://github.com/xpack-dev-tools/arm- ... -gcc-xpack
You state you do not want to change your low-level programming methodology, why (why, why) do you want to use Arduino? Respectfully, it is counterintuitive to me.

The Arduino Way is to use the provided API calls.
There are numerous calls to manipulate interrupts.

Ray

PS: welcome to the forum.

User avatar
fpiSTM
Posts: 597
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 22
Location: Le Mans
Contact:

Re: Migration to STM32 Cores. Changes in Interrupts.

Post by fpiSTM »

If you want do low level programming you will have to use only some HAL module.
Because some irq handler are already used by arduino wrapping layer.

You can disable it per HAL module you want use:


https://github.com/stm32duino/wiki/wiki ... odule-only


So in your case use HAL_TIM_MODULE_ONLY because TIM2_IRQHandler is used by the HardwareTimer library:

https://github.com/stm32duino/Arduino_C ... .cpp#L1433

billys7
Posts: 6
Joined: Fri Apr 24, 2020 3:38 pm

Re: Migration to STM32 Cores. Changes in Interrupts.

Post by billys7 »

Hi, and thank you for your response.

So, I add a new tab called build-opt.h, and i typed inside -HAL_TIM_MODULE_ONLY.
When i compile it, it gives me an error "arm-none-eabi-g++: error: unrecognized command line option '-HAL_TIM_MODULE_ONLY'"
I replaced -HAL_TIM_MODULE_ONLY with -DHAL_TIM_MODULE_ONLY and i received another error "error: 'TimerCompareFormat_t' has not been declared"

What is the correct way?
I couldn't find any example.

User avatar
fpiSTM
Posts: 597
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 22
Location: Le Mans
Contact:

Re: Migration to STM32 Cores. Changes in Interrupts.

Post by fpiSTM »

You find the coorect way add a build_opt.h with -DHAL_TIM_MODULE_ONLY

Anyway, I forgot there was an issue with the 1.8.0:
https://github.com/stm32duino/Arduino_C ... issues/839

which is fixed in the master and will be available in the 1.9.0:
https://github.com/stm32duino/Arduino_C ... 2/pull/840

You can apply the fix on your installed core.

billys7
Posts: 6
Joined: Fri Apr 24, 2020 3:38 pm

Re: Migration to STM32 Cores. Changes in Interrupts.

Post by billys7 »

I did the changes that you suggest me in analog.h file. Now the sketch was uploaded with success but the timer interrupt, still is not working. When it enters in the interrupt it stops responding.

Here is my sketch

Code: Select all

//Toggling the onboard led on PC13 every 2 sec.

volatile boolean led = 1 ;

#define RCCAPB1ENR_  (*((volatile uint32_t *) (0x40021000+0x1C)))
#define RCCAPB2ENR_  (*((volatile uint32_t *) (0x40021000+0x18)))
#define GPIOLC      (*((volatile uint32_t *) (0x40011000)))
#define GPIOHC      (*((volatile uint32_t *) (0x40011000+0x04)))
#define ODR_C       (*((volatile uint32_t *) (0x40011000+0x0C)))
#define BSRRC_      (*((volatile uint32_t *) (0x40011000+0x10)))

#define TIM2CR1    (*((volatile uint32_t *) (0x40000000)))
#define TIM2CR2    (*((volatile uint32_t *) (0x40000000+0x04)))
#define TIM2SMCR   (*((volatile uint32_t *) (0x40000000+0x08)))
#define TIM2DIER   (*((volatile uint32_t *) (0x40000000+0x0C)))
#define TIM2SR     (*((volatile uint32_t *) (0x40000000+0x10)))
#define TIM2EGR    (*((volatile uint32_t *) (0x40000000+0x14)))
#define TIM2CCMR1  (*((volatile uint32_t *) (0x40000000+0x18)))
#define TIM2CCMR2  (*((volatile uint32_t *) (0x40000000+0x1C)))
#define TIM2CCER   (*((volatile uint32_t *) (0x40000000+0x20)))
#define TIM2CNT    (*((volatile uint32_t *) (0x40000000+0x24)))
#define TIM2PSC    (*((volatile uint32_t *) (0x40000000+0x28)))
#define TIM2ARR    (*((volatile uint32_t *) (0x40000000+0x2C)))
#define TIM2CCR1   (*((volatile uint32_t *) (0x40000000+0x34)))
#define TIM2CCR2   (*((volatile uint32_t *) (0x40000000+0x38)))
#define TIM2CCR3   (*((volatile uint32_t *) (0x40000000+0x3C)))
#define TIM2CCR4   (*((volatile uint32_t *) (0x40000000+0x40)))
#define TIM2DCR    (*((volatile uint32_t *) (0x40000000+0x48)))
#define TIM2DMAR   (*((volatile uint32_t *) (0x40000000+0x4C)))

#define IPR8_        (*((volatile uint32_t *) (0xE000E100+0x308)))
#define ISER0_       (*((volatile uint32_t *) (0xE000E100)))

void setup() 
{
  Serial.begin(250000);  
  Serial.println("Start"); 
 
  RCCAPB1ENR_ = RCCAPB1ENR_ | 0x001  ;     // Enable Timer 2 RM p114
  RCCAPB2ENR_ = RCCAPB2ENR_ | 0x10;        // In order to make changes in GPIOC, Enable port row C.  RM p112 
  GPIOHC = 0x44144444;                     // Set output mode on PC13

  asm volatile("cpsie i");                 // Enables interrupts and configurable fault handlers. p99 C
  
  TIM2CR1   = 0;
  TIM2CR2   = 0;
  TIM2SMCR  = 0;
  TIM2DIER  = 0;
  TIM2SR    = 0;
  TIM2EGR   = 0;
  TIM2CCMR1 = 0;
  TIM2CCMR2 = 0;  
  TIM2CCER  = 0;
  TIM2CNT   = 0;
  TIM2PSC   = 0;
  TIM2ARR   = 65535;                       // Always FFFF
  TIM2CCR1  = 0;
  TIM2CCR2  = 0;
  TIM2CCR3  = 0;
  TIM2CCR4  = 0;
  TIM2DCR   = 0;
  TIM2DMAR  = 0;

       //Update_event = TIM_CLK/((PSC + 1)*(ARR + 1)) = 72.000.000. / ((35999+1)*(1999+1))= 1Hz = 1 per Sec 

  TIM2PSC   = 35999;                       // Set prescaler to 35999 (PSC + 1) Means 72.000.000 / 36000 = 2.000 counts per second p417
  TIM2ARR   = 1999;                        // Auto reload value 2000. p355
  TIM2DIER  = TIM2DIER | 0x1;              // Interrupt when the counter overflow. TIM_DIER_UIE = 1. p408
  TIM2CR1   = TIM2CR1 | 0x04;              // TIM_CR1_URS = 1 Only counter overflow/underflow generates an update interrupt or DMA request if enabled. p403
  IPR8_     =  IPR8_ & 0x20FFFFFF;         // Set highest priority 2. From the table TIM2 global interrupt = 35.p204 Reference Manual, Find the suitable IPR = 35 / 4,= 8 and the suitable byte 3
                                           // 0 being highest priority and 15 being lowest p118 Programming Manual. Move it to the left 4 positions. p125 Programming Manual 
  ISER0_    = ISER0_ | 0x10000000;         // Enable interrupt TIM2 global interrupt. From the table position TIM2 global interrupt = 28. p204 Reference Manual Position bit = 28 p120 Programming Manual.   
  TIM2SR    = TIM2SR & 0xFFFFFFFE;         // clear pending interrupt UIF flag  TIM_SR_UIF=0. p409. Always before enable an interrupt we must clear any pending interrupts.  
  TIM2EGR   = TIM2EGR| 0x0001;             // Re-initialize the counter and generates an update of the registers.
  TIM2CR1   = TIM2CR1 | 0x1;               // CEN = 1 Enable timer. p337 

}

void loop() 
{

  BSRRC_  = BSRRC_ |(1 << (13 + (led * 16))); // Toggle PC13. Lower 16 bits setting while higher bits clearing. p172
  Serial.println(led);                        // Show me Led status

}

void TIM2_IRQHandler(void)
{
  TIM2SR   = TIM2SR & 0xFFFFFFFE;          // Never try and clear the flag that caused the interrupt as the last instruction in the ISR itself. It causes the ISR to reenter immediately.
  led = !led;                              // Reverse state 
}
and the build_opt.h

Code: Select all

-DHAL_TIM_MODULE_ONLY
What other changes do i have to do?
My board is Bluepill STM32F103C8T6.

Thank you!

stas2z
Posts: 131
Joined: Mon Feb 24, 2020 8:17 pm
Answers: 8

Re: Migration to STM32 Cores. Changes in Interrupts.

Post by stas2z »

extern "C" void TIM2_IRQHandler(void)

billys7
Posts: 6
Joined: Fri Apr 24, 2020 3:38 pm

Re: Migration to STM32 Cores. Changes in Interrupts.

Post by billys7 »

It works.
Thank you all !!!

billys7
Posts: 6
Joined: Fri Apr 24, 2020 3:38 pm

Re: Migration to STM32 Cores. Changes in Interrupts.

Post by billys7 »

What about the same set up for Timer 1 ?
The handler "extern "C" void TIM1_IRQHandler(void)" is not working.

Here is my code:

Code: Select all

//Toggling the onboard led on PC13 every 1 sec.

volatile boolean led = 1 ;

#define RCCAPB2ENR_ (*((volatile uint32_t *) (0x40021000+0x18)))
#define GPIOLC      (*((volatile uint32_t *) (0x40011000)))
#define GPIOHC      (*((volatile uint32_t *) (0x40011000+0x04)))
#define ODR_C       (*((volatile uint32_t *) (0x40011000+0x0C)))
#define BSRRC_      (*((volatile uint32_t *) (0x40011000+0x10)))

#define TIM1CR1     (*((volatile uint32_t *) (0x40012C00)))
#define TIM1CR2     (*((volatile uint32_t *) (0x40012C00+0x04)))
#define TIM1SMCR    (*((volatile uint32_t *) (0x40012C00+0x08)))
#define TIM1DIER    (*((volatile uint32_t *) (0x40012C00+0x0C)))
#define TIM1SR      (*((volatile uint32_t *) (0x40012C00+0x10)))
#define TIM1EGR     (*((volatile uint32_t *) (0x40012C00+0x14)))
#define TIM1CCMR1   (*((volatile uint32_t *) (0x40012C00+0x18)))
#define TIM1CCMR2   (*((volatile uint32_t *) (0x40012C00+0x1C)))
#define TIM1CCER    (*((volatile uint32_t *) (0x40012C00+0x20)))
#define TIM1CNT     (*((volatile uint32_t *) (0x40012C00+0x24)))
#define TIM1PSC     (*((volatile uint32_t *) (0x40012C00+0x28)))
#define TIM1ARR     (*((volatile uint32_t *) (0x40012C00+0x2C)))
#define TIM1RCR     (*((volatile uint32_t *) (0x40012C00+0x30)))
#define TIM1CCR1    (*((volatile uint32_t *) (0x40012C00+0x34)))
#define TIM1CCR2    (*((volatile uint32_t *) (0x40012C00+0x38)))
#define TIM1CCR3    (*((volatile uint32_t *) (0x40012C00+0x3C)))
#define TIM1CCR4    (*((volatile uint32_t *) (0x40012C00+0x40)))
#define TIM1BDTR    (*((volatile uint32_t *) (0x40012C00+0x44)))
#define TIM1DCR     (*((volatile uint32_t *) (0x40012C00+0x48)))
#define TIM1DMAR    (*((volatile uint32_t *) (0x40012C00+0x4C)))

#define IPR8_       (*((volatile uint32_t *) (0xE000E100+0x308)))
#define ISER0_      (*((volatile uint32_t *) (0xE000E100)))

void setup() 
{
  Serial.begin(250000);  
  Serial.println("Start"); 
  
  RCCAPB2ENR_ = RCCAPB2ENR_ | 0x0800  ;   // RM Enable Timer 1 RM p112
  RCCAPB2ENR_ = RCCAPB2ENR_ | 0x10;        // In order to make changes in GPIOC, Enable port row C.  RM p112 
  GPIOHC = 0x44144444;                            // Set output mode on PC13
   
  asm volatile("cpsie i");                           // Enables interrupts and configurable fault handlers. p99 C
  
  TIM1CR1   = 0;
  TIM1CR2   = 0;
  TIM1SMCR  = 0;
  TIM1DIER  = 0;
  TIM1SR    = 0;
  TIM1EGR   = 0;
  TIM1CCMR1 = 0;
  TIM1CCMR2 = 0;  
  TIM1CCER  = 0;
  TIM1CNT   = 0;
  TIM1PSC   = 0;
  TIM1ARR   = 65535;
  TIM1RCR   = 0;
  TIM1CCR1  = 0;
  TIM1CCR2  = 0;
  TIM1CCR3  = 0;
  TIM1CCR4  = 0;
  TIM1BDTR  = 0;
  TIM1DCR   = 0;
  TIM1DMAR  = 0;

  TIM1PSC   = 35999;                       // Set prescaler to 35999 (PSC + 1) Means 72.000.000 / 36000 = 2.000 counts per second p417
  TIM1ARR   = 1999;                        // Auto reload value 2000. p355
  TIM1DIER  = TIM1DIER | 0x1;              // interrupt overflow counter. TIM_DIER_UIE = 1. p343
  TIM1CR1   = TIM1CR1 | 0x04;              // TIM_CR1_URS = 1 Only counter overflow/underflow generates an update interrupt or DMA request if enabled. p403
  IPR8_     =  IPR8_ & 0xFFFFFF20;         // Set highest priority 2. From the table TIM1 global interrupt = 32.p204 Reference Manual, Find the suitable IPR = 32 / 4,= 8 and the suitable byte 0
                                           // 0 being highest priority and 15 being lowest p118 Programming Manual. Move it to the left 4 positions. p125 Programming Manual 
  
  ISER0_    = ISER0_ | 0x2000000;          // Enable interrupt TIM1_UP global interrupt. From the table position TIM1_UP global interrupt = 25. p204 Reference Manual Position bit = 25 p120 Programming Manual. 
  TIM1SR    = TIM1SR & 0xFFFFFFFE;         // clear pending interrupt UIF flag  TIM_SR_UIF=0. p409. Always before enable an interrupt we must clear any pending interrupts.
  TIM1EGR   = TIM1EGR| 0x0001;             // Re-initialize the counter and generates an update of the registers.
  TIM1CR1   = TIM1CR1 | 0x1;               // CEN = 1 Enable timer. p337    

}

void loop() 
{
  BSRRC_  = BSRRC_ |(1 << (13 + (led * 16))); 
  Serial.println(led);                                    
}

extern "C" void TIM1_IRQHandler(void)           
 {
  TIM1SR   = TIM1SR & 0xFFFFFFFE;                   
  led = !led;                                           // Reverse state 
}

stas2z
Posts: 131
Joined: Mon Feb 24, 2020 8:17 pm
Answers: 8

Re: Migration to STM32 Cores. Changes in Interrupts.

Post by stas2z »

tim1 have two handlers, up and cc, not only one

Post Reply

Return to “General discussion”