Post here all questions related to STM32 core if you can't find a relevant section!
billys7
Posts: 8 Joined: Fri Apr 24, 2020 3:38 pm
Post
by billys7 » 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.
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: 633 Joined: Thu Dec 19, 2019 1:23 am
Answers: 7
Post
by mrburnette » Sat Apr 25, 2020 10:49 pm
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.
billys7
Posts: 8 Joined: Fri Apr 24, 2020 3:38 pm
Post
by billys7 » Sun Apr 26, 2020 3:38 pm
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.
billys7
Posts: 8 Joined: Fri Apr 24, 2020 3:38 pm
Post
by billys7 » Mon Apr 27, 2020 7:30 pm
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
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
Post
by stas2z » Mon Apr 27, 2020 7:42 pm
extern "C" void TIM2_IRQHandler(void)
billys7
Posts: 8 Joined: Fri Apr 24, 2020 3:38 pm
Post
by billys7 » Mon Apr 27, 2020 7:57 pm
It works.
Thank you all !!!
billys7
Posts: 8 Joined: Fri Apr 24, 2020 3:38 pm
Post
by billys7 » Mon Apr 27, 2020 9:50 pm
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
Post
by stas2z » Tue Apr 28, 2020 4:24 am
tim1 have two handlers, up and cc, not only one