RISC-V/V203F6P6/atomic/main.cpp
2025-02-20 22:07:45 +01:00

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;
}