Katkestuste kasutmine

Katkestuse töölerakendamine

Katkestus kui klass

Iga katkestus on esitatud klassina, mis on tuletatud mallklassist BasicInterrupt:

template <class EnableBit> struct BasicInterrupt
{
    static inline void Enable() { EnableBit::Set(); }
    static inline void Disable() { EnableBit::Clear(); }
    static inline bool IsEnabled() { return EnableBit::IsSet(); }
 
}; // struct BasicInterrupt

Mõned katkestused on tuletatud klassist Interrupt, mis on ise tuletatud klassist BasicInterrupt.

template <class EnableBit, class FlagBit> struct Interrupt : BasicInterrupt<EnableBit>
{
    static inline void ClearFlag() { FlagBit::Set(); }
    static inline bool IsTriggered() { return FlagBit::IsSet(); }
 
}; // struct Interrupt

Lisaks on igal katkestuse klassil lisafunktsioonid. Näiteks Timer::TimerCounter1::InputCaptureInterrupt on kasutaja poolt nähtav kui:

class InputCaptureInterrupt
{
public:
    static inline void Enable();
    static inline void Disable();
    static inline bool IsEnabled();
 
    static inline void ClearFlag();
    static inline bool IsTriggered();
 
    static void Evoke();
    template <class DelegateType> static DelegateType & Me();
    template <class ControllerType> static ControllerType & Controller();
 
}; // class InputCaptureInterrupt

Katkestuse alamprogramm

Katkestuse alamprogrammis on kirjeldatud tegevus katkestuse esinemisel. Näiteks:

#include <USART.h>
#include <Interrupt.h>
#include <CppString.h>
 
using namespace AVRCpp::USART;
 
INTERRUPT_HANDLER(TIMER2_COMPA)
{
    static cstr_t text = "Interrupt occurred!\n";
 
    USART0::SendText(text, StrLength(text) );
}

INTERRUPT_HANDLER on makro, mis võtab parameetriks katkestuse nime. Katkestuse nime leiab vastava seadme andmelehelt pealkirja Interrupts alt, kus on katkestuse vektori tabel prioriteetide järjekorras. Üldjuhul kasutatakse vaid INTERRUPT_HANDLER makrot. Samas on ka eksootilisemaid variante.

Täielik nimekiri katkestuste makrodest

  • INTERRUPT_HANDLER - tavaline katkestuse alamprogramm
  • EVOCABLE_INTERRUPT_HANDLER - simuleeritava katkestuse alamprogramm. Võimaldab välja kutsuda katkestuse klassi funktsiooni Evoke.
  • RECURSIVE_INTERRUPT_HANDLER - katkestuse alamprogramm, kus katkestused on globaalselt vaikimisi lubatud.
  • EVOCABLE_RECURSIVE_INTERRUPT_HANDLER - simuleeritava katkestuse alamprogramm, kus katkestused on globaalselt vaikimisi lubatud.
  • EXCLUDE_INTERRUPT - katkestuse alamprogrammi ja delegaadi aktiveerimise keelamine.

Globaalselt katkestuste lubamine

#include <Interrupt.h>
 
int main()
{
    // Globaalselt katkestuste lubamine
    GlobalInterrupts::Enable();
 
    // Globaalselt katkestuste keelamine
    GlobalInterrupts::Disable();
}

Konkreetse katkestuse lubamine

Konkreetse katkestuse lubamiseks tuleb välja kutsuda katkestusklassi funktsiooni Enable(). Tihti on vaja enne katkestuse lubamist nullida katkestusbitt funktsiooni ClearFlag() abil. Katkesuse keelamiseks on katkestusklassi funktsioon Disable().

Andmete turvalisus

Kui teatud mälu osa on kasutuses põhiprogrammis ja katkestuse alamprogrammis, siis selle mäluosa lugemisel ja kirjutamisel tuleb põhiprogrammis katkestused selleks ajaks keelata. Keelamiseks on spetsiaalne makro INTERRUPT_SAFE.

#include <Interrupt.h>
#include <Timer.h>
 
using namespace AVRCpp;
using namespace Timer;
 
volatile static int16_t counter = 0
 
// Katkestuse alamprogramm
INTERRUPT_HANDLER(TIMER0_OVF)
{
    counter++;
}
 
int16_t ResetTimer()
{
    INTERRUPT_SAFE
    {
        counter = 0;
    }
}
 
int16_t GetTimer()
{
    int16_t temporary = 0;
 
    INTERRUPT_SAFE
    {
        temporary = counter;
    }
 
    return temporary;
}
 
typedef OutputPin0<PortC> LED;
typedef TimerCounter0 MyTimer;
 
int main()
{
    // Globaalselt katkestuste lubamine
    GlobalInterrupts::Enable();
 
    MyTimer::SelectClock(Prescaler256B);
 
    // Konkreetse katkestuse lubamine
    MyTimer::OverflowInterrupt::Enable();
 
    LED::InitOutput();
 
    while (true)
    {
        ResetTimer();
 
        while (GetTimer() < 500)
            continue;
 
        LED::Toggle();
    }
    return 0;
}