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