Using CMSIS NVIC functions to set custom timer interrupt handler.
main.cpp
- Committer:
- Ladon
- Date:
- 2019-08-02
- Revision:
- 7:d93dcab712f1
- Parent:
- 6:be045fed855f
File content as of revision 7:d93dcab712f1:
#include <mbed.h>
#include <iostream>
using namespace std;
void led_init ()
{
// Led is at PA5.
// -
// Set PA5 as output.
// -
// Port Mode Register.
// -
GPIOA->MODER &= ~GPIO_MODER_MODER5;
GPIOA->MODER |= 1 << GPIO_MODER_MODER5_Pos;
}
void inline reset_timer ()
{
// Peripheral Reset Register.
// -
RCC->APB1RSTR |= RCC_APB1RSTR_TIM2RST;
RCC->APB1RSTR &= ~RCC_APB1RSTR_TIM2RST;
}
void inline clock_enable_for_timer ()
{
// Peripheral Clock Enable Register.
// TIM2 Timer Clock Enable.
// -
reset_timer();
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
}
void inline timer_downscale_by (const unsigned short& v)
{
// Prescaler.
// -
TIM2->PSC = v;
}
void inline timer_limit_counter_to (const unsigned int& v)
{
// Auto-Reload Register.
// -
TIM2->ARR = v;
}
void inline timer_set_period_to (const double& T)
{
// This function allows : 500us <= T <= 32.768
// The ^former was found by solving : 0 <= 1999 + (T - 1) * 2e3 <= 0xFFFF, for the prescaler register.
// -
timer_limit_counter_to(36000);
timer_downscale_by(1999 + (T - 1) * 2e3);
}
void inline timer_enable_interrupt ()
{
// DMA/ Interrupt Enable Register.
// Update Interrupt Enable.
// -
TIM2->DIER = TIM_DIER_UIE;
}
void inline timer_enable ()
{
// Control Register 1.
// Update Request Source | Counter Enable.
// -
TIM2->CR1 = TIM_CR1_URS | TIM_CR1_CEN;
}
void inline timer_clear_status ()
{
// Status Register.
// -
TIM2->SR = 0;
}
void led_toggle ()
{
// Output Data Register.
// -
GPIOA->ODR ^= GPIO_ODR_5;
}
/*
// I was unable to use the following handler :
// -
extern "C" void TIM2_IRQHandler (void)
{
cout << "Interrupt hit!" << endl;
clear_timer_status();
toggle_LED();
}
*/
// I couldn 't get TIM2_IRQHandler() to work; probably wrong name. Thus, I 'll use a custom handler
// and attach it using SetVector() from CMSIS : https://arm-software.github.io/CMSIS_5/Core/html/group__NVIC__gr.html.
// -
void interrupt_handler ()
{
cout << "Interrupt hit!" << endl;
timer_clear_status();
led_toggle();
}
inline void interrupt_enable ()
{
// NVIC_SetPriority(TIM2_IRQn, 250);
NVIC_SetVector(TIM2_IRQn, reinterpret_cast<uint32_t>(interrupt_handler));
NVIC_EnableIRQ(TIM2_IRQn);
// ^Definition of NVIC_SetVector() : https://arm-software.github.io/CMSIS_5/Core/html/group__NVIC__gr.html#gab43c1c59d5c081f1bc725237f4b1f916.
// -
}
//
// -
//
int main ()
{
cout << "Entered main()." << endl;
led_init();
clock_enable_for_timer();
timer_set_period_to(1.3);
timer_enable_interrupt();
timer_enable();
interrupt_enable();
/*
while (true)
{
cout << hex
<< "Status : 0x" << TIM2->SR << endl
<< "Count : 0x" << TIM2->CNT << endl;
}
*/
cout << "Exiting main().." << endl;
}
Spyros Papanastasiou