Using CMSIS NVIC functions to set custom timer interrupt handler.

Dependencies:   mbed

main.cpp

Committer:
Ladon
Date:
2019-08-02
Revision:
4:c52637c8d084
Parent:
3:db424769ecca
Child:
5:3ee6e0113b41

File content as of revision 4:c52637c8d084:

//#include <mbed.h>
#include "stm32f303xe.h"
#include <iostream>
#include <iomanip>

using namespace std;

// Timer functions:
// -

void inline timer_enable ()
{
    TIM2->CR1 = TIM_CR1_URS | TIM_CR1_CEN;
}

void inline timer_enable_interrupt ()
{
    TIM2->DIER = TIM_DIER_UIE;
}

void inline timer_clear_status ()
{
    TIM2->SR = 0;
}

void inline timer_downscale_by (const unsigned short& v)
{
    cout << "Downscaling counter by : 0x" << hex << 1 + v << endl;
    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;
    TIM2->ARR = v;
}

void inline timer_set_interrupt_period_to (const double& T)
{
    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 led_init ()
{
    GPIOA->MODER &= ~GPIO_MODER_MODER5;
    // Set as output.
    // -
    GPIOA->MODER |= 1 << GPIO_MODER_MODER5_Pos;
}

void led_toggle ()
{
    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;
}

// NVIC functions:
// -
/* 
// I couldn 't get TIM2_IRQHandler() to work; probably wrong name.
// -
extern "C" void TIM2_IRQHandler (void)
{
    cout << "Interrupt hit!" << endl;
    clear_timer_status();
    toggle_LED();
}
*/
void interrupt_handler ()
{
    cout << "Interrupt hit!" << endl;
    timer_clear_status();
    led_toggle();
}

inline void interrupt_enable ()
{
//    NVIC_SetPriority(TIM2_IRQn, 250);
    NVIC_EnableIRQ(TIM2_IRQn);
    NVIC_SetVector(TIM2_IRQn, (uint32_t) &interrupt_handler);
}

//
// -
//

int main ()
{
    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_enable_interrupt();
    timer_enable();
    interrupt_enable();
    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;
    }
}