Using CMSIS NVIC functions to set custom timer interrupt handler.

Dependencies:   mbed

main.cpp

Committer:
Ladon
Date:
2019-08-02
Revision:
3:db424769ecca
Parent:
2:7c45a714b991
Child:
4:c52637c8d084

File content as of revision 3:db424769ecca:

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

using namespace std;

// Timer functions:
// -

void inline enable_timer ()
{
    TIM2->CR1 |= TIM_CR1_ARPE | TIM_CR1_OPM | TIM_CR1_URS | TIM_CR1_CEN;
}

void inline enable_timer_interrupt ()
{
    cout << "Setting DIER..." << endl;
    cout << "DIER was : 0x" << hex << TIM2->DIER << endl;
    cout << "Status is : 0x" << hex << TIM2->SR << endl;
    TIM2->DIER = TIM_DIER_UIE;
    cout << "Set DIER." << endl;
}

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

void inline reset_timer ()
{
    TIM2->EGR = TIM_EGR_UG;
    clear_timer_status();
}

void inline downscale_timer_by (const unsigned short& v)
{
    cout << "Downscaling counter by : 0x" << hex << 1 + v << endl;
    TIM2->PSC = v;
}

void inline downscale_timer_max ()
{
    downscale_timer_by(0xFFFF);
}

void inline limit_timer_counter_to (const unsigned int& v)
{
    cout << "Limiting counter to : 0x" << hex << v << endl;
    TIM2->ARR = v;
}

void inline set_interrupt_period_to (const double& T)
{
    limit_timer_counter_to(36000);
    downscale_timer_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.
    // -
}

void inline set_interrupt_period_to_1sec ()
{
    set_interrupt_period_to(1);
}

// GPIOA functions:
// -

void init_LED ()
{
    GPIOA->MODER &= ~GPIO_MODER_MODER5;
    // Set as output.
    // -
    GPIOA->MODER |= 1 << GPIO_MODER_MODER5_Pos;
}

void toggle_LED ()
{
    GPIOA->ODR ^= GPIO_ODR_5;
}

// Other functions:
// -

void inline enable_clock_for_timer ()
{
    RCC->APB1RSTR |= RCC_APB1RSTR_TIM2RST;
    RCC->APB1RSTR &= ~RCC_APB1RSTR_TIM2RST;
    RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
}

// NVIC functions:
// -

extern "C" void TIM2_IRQHandler (void)
{
    cout << "Interrupt hit!" << endl;
    clear_timer_status();
    toggle_LED();
}

void fun ()
{
    cout << "Interrupt hit!" << endl;
    clear_timer_status();
    toggle_LED();
}

inline void enable_interrupt ()
{
    NVIC_SetPriority(TIM2_IRQn, 250);
    cout << "TIM2_IRQn priority : " << NVIC_GetPriority(TIM2_IRQn) << endl;
    NVIC_EnableIRQ(TIM2_IRQn);
    cout << "TIM2_IRQn status   : " << NVIC_GetEnableIRQ(TIM2_IRQn) << endl;
    cout << "TIM2_IRQn pending  : " << NVIC_GetPendingIRQ(TIM2_IRQn) << endl;
    NVIC_SetVector(TIM2_IRQn, (uint32_t) &fun);
}

//
// -
//

int main ()
{
    cout << "Entered main()." << endl;
    init_LED();
    enable_clock_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;
    downscale_timer_max();
    limit_timer_counter_to(0x1000);
    // ^ LED stays open for 0.5 and closed for 0.5 with a total of 1 sec.
    // -
    clear_timer_status();
    enable_timer_interrupt();
    enable_timer();
    enable_interrupt();
    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;
    }
}