Spyros Papanastasiou
/
General_purpose_timer_TIM2__custom_interrupt_handler
Using CMSIS NVIC functions to set custom timer interrupt handler.
Diff: main.cpp
- Revision:
- 5:3ee6e0113b41
- Parent:
- 4:c52637c8d084
- Child:
- 6:be045fed855f
diff -r c52637c8d084 -r 3ee6e0113b41 main.cpp --- a/main.cpp Fri Aug 02 04:25:43 2019 +0000 +++ b/main.cpp Fri Aug 02 05:19:08 2019 +0000 @@ -1,92 +1,104 @@ -//#include <mbed.h> -#include "stm32f303xe.h" +#include <mbed.h> #include <iostream> -#include <iomanip> using namespace std; -// Timer functions: -// - - -void inline timer_enable () +void led_init () { - TIM2->CR1 = TIM_CR1_URS | TIM_CR1_CEN; + // 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 timer_enable_interrupt () +void inline reset_timer () { - TIM2->DIER = TIM_DIER_UIE; + // Peripheral Reset Register. + // - + RCC->APB1RSTR |= RCC_APB1RSTR_TIM2RST; + RCC->APB1RSTR &= ~RCC_APB1RSTR_TIM2RST; } -void inline timer_clear_status () +void inline clock_enable_for_timer () { - TIM2->SR = 0; + // Peripheral Clock Enable Register. + // TIM2 Timer Clock Enable. + // - + reset_timer(); + RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; } void inline timer_downscale_by (const unsigned short& v) { - cout << "Downscaling counter by : 0x" << hex << 1 + v << endl; + // Prescaler. + // - TIM2->PSC = v; } -void inline timer_downscale_by_max () -{ - timer_downscale_by(0xFFFF); -} - void inline timer_limit_counter_to (const unsigned int& v) { - cout << "Limiting counter to : 0x" << hex << v << endl; + // Auto-Reload Register. + // - TIM2->ARR = v; } -void inline timer_set_interrupt_period_to (const double& T) +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); - // ^This allows : 500us <= T <= 32.768 - // The ^former was found by solving : 0 <= 1999 + (T - 1) * 2e3 <= 0xFFFF, for the prescaler register. - // - } -// GPIOA functions: -// - +void inline timer_enable_interrupt () +{ + // DMA/ Interrupt Enable Register. + // Update Interrupt Enable. + // - + TIM2->DIER = TIM_DIER_UIE; +} -void led_init () +void inline timer_enable () { - GPIOA->MODER &= ~GPIO_MODER_MODER5; - // Set as output. + // Control Register 1. + // Update Request Source | Counter Enable. // - - GPIOA->MODER |= 1 << GPIO_MODER_MODER5_Pos; + 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; } -// Other functions: -// - - -void inline clock_enable_for_timer () -{ - RCC->APB1RSTR |= RCC_APB1RSTR_TIM2RST; - RCC->APB1RSTR &= ~RCC_APB1RSTR_TIM2RST; - RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; -} +/* + // I was unable to use the following handler : + // - + extern "C" void TIM2_IRQHandler (void) + { + cout << "Interrupt hit!" << endl; + clear_timer_status(); + toggle_LED(); + } +*/ -// NVIC functions: -// - -/* -// I couldn 't get TIM2_IRQHandler() to work; probably wrong name. +// 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. // - -extern "C" void TIM2_IRQHandler (void) -{ - cout << "Interrupt hit!" << endl; - clear_timer_status(); - toggle_LED(); -} -*/ void interrupt_handler () { cout << "Interrupt hit!" << endl; @@ -98,7 +110,9 @@ { // NVIC_SetPriority(TIM2_IRQn, 250); NVIC_EnableIRQ(TIM2_IRQn); - NVIC_SetVector(TIM2_IRQn, (uint32_t) &interrupt_handler); + NVIC_SetVector(TIM2_IRQn, (uint32_t) interrupt_handler); + // ^Definition of NVIC_SetVector() : https://arm-software.github.io/CMSIS_5/Core/html/group__NVIC__gr.html#gab43c1c59d5c081f1bc725237f4b1f916. + // - } // @@ -110,31 +124,17 @@ cout << "Entered main()." << endl; led_init(); clock_enable_for_timer(); - TIM2->ARR = 0xffffffff; - TIM2->CR1 = TIM2->CR2 = TIM2->SMCR = TIM2->DIER = TIM2->SR = TIM2->CCMR1 = TIM2->CCMR2 - = TIM2->CCER = TIM2->CNT = TIM2->PSC = TIM2->CCR1 = TIM2->CCR2 = TIM2->CCR3 - = TIM2->CCR4 = TIM2->DCR = TIM2->DMAR = 0; - TIM2->CR1 |= TIM_CR1_UDIS; - timer_downscale_by_max(); - timer_limit_counter_to(0x1000); - // ^ LED stays open for 0.5 and closed for 0.5 with a total of 1 sec. - // - - timer_clear_status(); + 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; - cout << endl; - cout << hex - << "Status : 0x" << TIM2->SR << endl - << "Count : 0x" << TIM2->CNT << endl; - TIM2->CR1 &= ~TIM_CR1_UDIS; - while (true) - { - cout << hex - << "Status : 0x" << TIM2->SR << endl - << "Count : 0x" << TIM2->CNT << endl; - if (TIM2->CNT > 2) - TIM2->SR = 0; - } } \ No newline at end of file