1
\$\begingroup\$

I am trying to implement a simple interrupt routine, blinky led using a timer on the stm32f103 "blue pill" board.

I have been reading the datasheet, reference manual, timer cookbooks and all but I'm not able to figure this part out.

I'm using the gnu-arm cross compiler and was successful in getting a timer a started and was able to blink an led by continuously checking the 'update event' bit inside the TIMx_SR register.

Up till now, I had a look at the NVIC section in reference manual but I can't figure out exactly how to work with the vector table...

Any suggestions or resources are welcome.

\$\endgroup\$
9
  • \$\begingroup\$ Asking for help in finding external examples or resources isn't within the mission of stack exchange sites. This is a task where you want to use a traditional web search - there are more than a few pages devoted to that board, and ST themselves have the old standard peripheral library for the F100/F103 family which includes examples. When you have code you are working on, specifically stated problems supported by sufficient detail (code, wiring, etc) could be on topic here. \$\endgroup\$ – Chris Stratton Nov 28 '20 at 17:00
  • \$\begingroup\$ @ChrisStratton I understand, but in my case isn't about code to corrected or where it is going wrong, it is about specific advice on how to write code for this. I came here after failing to find a relevant source on Google. \$\endgroup\$ – nalostta Nov 28 '20 at 17:03
  • \$\begingroup\$ The "advice" you want is an example of using a timer interrupt, and finding such is again, not within the mission here. Nor is creating a custom tutorial. An on-topic question would be if you showed details of something that should work, but doesn't. As for the limited specific of the vector table, typically in such a setting, there's a default vector table of weak symbols alongside the chip specific init routines, and what you do is put a strong (ordinary) symbol of the same name for a given vector's entry in your code, which will replace it. \$\endgroup\$ – Chris Stratton Nov 28 '20 at 17:03
  • \$\begingroup\$ @ChrisStratton I had a look at the vector table, what confused me here was the term TIM2 "global" interrupt \$\endgroup\$ – nalostta Nov 28 '20 at 17:06
  • \$\begingroup\$ Does the programmer's manual indicate there should be? Is it shared with other things? Is it by category of condition? Did you find several possibilities none of which quite match your expectation? Editing a list of those vs. an explanation of your specific expectation into your question could almost make it on topic. But really for efficiency what you probably want to do is find an example of a timer ISR on this platform; have you unpacked the vendor examples archive and looked to see what is there yet? \$\endgroup\$ – Chris Stratton Nov 28 '20 at 17:08
1
\$\begingroup\$

I will attempt to answer this fairly vague question by listing the high level steps to set up a timer interrupt, to help point you in the right direction.

  • Turn on the timer peripheral by enabling it's clock. This is done via the RCC subsystem. You will find this kind of register manipulation in any STM32 code example. If you are going to use the timer for e.g. PWM waveform generation, or to measure external signals, you will also need to enable the clock for the GPIO port you are using. I assume you are past the general "blinking LED" stage and will not go into more detail about GPIO ports :)
  • Configure the timer peripheral to generate interrupts in response to specific timer events. This is not covered in the NVIC section of the manual, but in the section about timers. For the STM32F103 and probably other STM32 chips, the register is called DIER. You will likely want to set the UIE bit in this register, however don't take my word for it. You should read the whole section of the manual to understand how the timer works and how to set it up.
  • Enable the correct IRQ in the NVIC. This hardware (the NVIC) is not specific to STM32, but is common to all ARM microcontrollers. Each interrupt line on the chip (there may be one dedicated to the timer you are using, or it might be shared by several peripherals) is referred to by an integer. I usually look in the device header file for this information, and I recommend getting comfortable with looking through the vendor code for answers about the chip you're working with.
  • Implement your interrupt handler function, often referred to as an ISR (Interrupt Service Routine). In C code, you declare a function which is already named elsewhere in the vendor's initialization code. When you declare a function with that name, the compiler/linker will know to place the address of that function into a known location (the vector table, another good thing to look up). This is the part of the code where you will toggle your LED. It is important to note that each peripheral that can generate an interrupt has a status bit that your ISR should clear, to acknowledge that the ISR has been executed. This becomes important when you have an IRQ shared by multiple peripherals, or if you want to handle more than one event generated by one peripheral. For example, if you enable the "timer update" interrupt via the UIE bit, you will need to then clear the corresponding UIF bit in the status register. This is the only way the peripheral knows that the interrupt has been handled. If you don't do this, the chip will lock up because it is continuously entering the interrupt handler.

Other general advice: the book "The Definitive Guide To ARM Cortex-M3 and Cortex-M4 Processors" helped me understand a lot of this stuff, but not as much as closely reading the chip manual and vendor-provided code.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.