ARM_minimal.
Třídy | Funkce | Proměnné
Dokumentace souboru main.cpp

Demontrace použití softwarového přerušení pro STM32F0. ...

#include "softintr.h"
#include "gpio.h"

Třídy

class  MySoft
 

Funkce

static GpioClass ledb (GpioPortC, 8)
 
void SysTick_Handler (void)
 
int main (void)
 

Proměnné

static MySoft soft (GpioPortC, 9)
 
static volatile uint32_t SysCount = 0
 
static volatile uint32_t LedCount = 0
 
static volatile uint32_t MainCount = 0
 

Detailní popis

Demontrace použití softwarového přerušení pro STM32F0.

Softwarové přerušení

Někdy je potřeba vyvolat přerušení přímo z programu. Jednoduchý příklad by byl třeba při příjmu dat v přerušení - přijmeme byte, zasuneme ho do fronty a skončíme obsluhu přerušení. Přerušení od periferie pak trvá jen krátkou dobu, což je právě žádoucí. Data však musíme nějak zpracovat. Obvykle se to dělá tak, že se fronta v hlavní smyčce testuje a pokud je dostatek dat k další činnosti, tato se provede.

Někdy může nastat situace, že je potřeba nechat hlavní smyčku volnou například pro volné použití uživatelského procesu. To lze řešit tak, že v přerušení od periferie po zasunutí dat do fronty vyvoláme další přerušení na nízké prioritě. Přerušení od periferie doběhne do konce a po jeho skončení (pokud nenastane jiné s vyšší prioritou) procesor začně obsluhu tohoto "softwarového" přerušení, případně v ní pokračuje. Není to tedy něco jako pouhé volání podprogramu, spíš by se to dalo přirovnat k jednoduchému multitaskingu bez použití RTOS.

V procesorech Cortex-M je k tomuto účelu možné použít fakticky libovolný vektor od nepoužitého hardwarového přerušení (od nepoužité periferie), zde se pro STM32F0 používají nepoužité vektory, tedy ty které mají v původní tabulce vektorů 0. Není to dobře dokumentovaná funkce, ale nikde není napsáno, že se to dělat nesmí a funguje to. Je potřeba upravit tabulku vektorů, vlastní práci s přerušením dáme do třídy SoftIntr. Pokud to chceme použít, musíme si vytvořit potomka této třídy a přetížit v něm metodu SoftIntr::run() vlastním kódem.

#include "softintr.h"
#include "gpio.h"
// vytvoř potomka SoftIntr
class MySoft : public SoftIntr {
public:
MySoft (GpioPortNum const port, const uint32_t no)
: SoftIntr (SoftIntrNumber2), ledg (port, no) {};
void run (void); // a tohle v něm nutno přetížit
private:
GpioClass ledg; // můžeme sem zakomponovat třídy se kterými to bude pracovat
};
// vytvoříme instanci tt. třídy
static MySoft soft (GpioPortC, 9);
// a ledku, která bude blikat v SysTicku
static GpioClass ledb (GpioPortC, 8);
// Debug - počet průchodů
static volatile uint32_t SysCount = 0, LedCount = 0, MainCount = 0;
// obsluha SysTicku
extern "C" void SysTick_Handler (void) {
~ledb;
SysCount ++;
if (SysCount < 100)
soft.exec (); // vyvolá přerušení (s nízkou prioritou)
}
int main (void) {
SysTick_Config (9600000); // 200 ms
// Nutno zvednout prioritu SysTick, default je moc nízká (3).
NVIC_SetPriority (SysTick_IRQn, 0);
for (;;) {
MainCount ++;
}
return 0;
}
// definice obsluhy softwarového přerušení
void MySoft::run (void) { // a tohle je v tom přerušení
+ledg; // něco dělej - rozsviť led ...
LedCount ++;
volatile uint32_t tick = 100000;
while (--tick); // počkej chvíli ...
-ledg; // zhasni led
}

Zdrojáky k tomuto příkladu.

Příklad je již složitější, nastavuje periferie, používá volání statických konstruktorů a jiné vymoženosti jazyka C++.