45 lines
1.7 KiB
C++
45 lines
1.7 KiB
C++
#include "system.h"
|
|
#include "gpio.h"
|
|
#include "atomic.h"
|
|
////////////////////////////////////////////////////////////////////////
|
|
/* Test atomického přístupu.
|
|
* RISC-V jádra QingKe V4B mají atomické rozšíření, opravdu funguje
|
|
* i když netuším jak. U Cortex-M3 jsem to ještě zkoumal, tady už na to
|
|
* kašlu. Ono těch situací, kdy je to nezbytné zase tak moc není.
|
|
* */
|
|
////////////////////////////////////////////////////////////////////////
|
|
static constexpr unsigned ticks = SYSTEM_CORE_CLOCK / 1000u;
|
|
extern "C" [[gnu::interrupt]] void SysTick_Handler ();
|
|
////////////////////////////////////////////////////////////////////////
|
|
static inline int iabs (const int x) {
|
|
return x < 0 ? -x : +x;
|
|
}
|
|
static constexpr int INCREMENT = 16;
|
|
//static volatile int shared_cnt (0); // !!! špatně, opravdu musí být atomic
|
|
static atomic <int> shared__cnt (0);
|
|
static volatile int compare_cnt (0);
|
|
static int error_cnt (0); // čítač chyb
|
|
|
|
static GpioClass led (GPIOB, 8);
|
|
////////////////////////////////////////////////////////////////////////
|
|
void SysTick_Handler () {
|
|
SysTick.SR = 0u;
|
|
// přičítáme jakékoli větší číslo
|
|
shared__cnt += INCREMENT;
|
|
compare_cnt += INCREMENT;
|
|
// detekce chyby - rozdíl nesmí být větší než pohyb hodnoty v hlavní smyčce
|
|
if (iabs (shared__cnt - compare_cnt) > 1) {
|
|
led << false;
|
|
error_cnt += 1;
|
|
shared__cnt = compare_cnt;
|
|
}
|
|
}
|
|
int main () {
|
|
SysTick.Config (ticks);
|
|
led << true;
|
|
for (;;) { // smyčka by měla být co nejkratší
|
|
shared__cnt += 1; // Tady může vzniknout race condition, RISC sekvence RMW
|
|
shared__cnt -= 1; // vlivem přerušení zapíše špatnou hodnotu, atomic to jistí.
|
|
}
|
|
return 0;
|
|
}
|