#ifndef ARMCM0_HDEF #define ARMCM0_HDEF /** @brief SYSTICK for Cortex-M0 * Není to moc domyšlené, před tt. hlavičkou je nutné mít definován NVIC a IRQn, * což je v STM generované hlavičce většinou uděláno. NVIC_EnableIRQ je zjednodušen * jen pro CM0, jinak se tam čaruje s PRIO_BITS, tady to není potřeba. */ // tohle je jediné, co je potřeba z core_cm0.h static inline void NVIC_EnableIRQ (IRQn irq) { NVIC.ISER.R = ((1 << (static_cast(irq) & 0x1F))); } static constexpr uint32_t SysTick_LOAD_RELOAD_Msk = (0xFFFFFFUL); /*!< SysTick LOAD: RELOAD Mask */ // ////////////////////+++ SysTick +-+//////////////////// // struct SysTick_DEF { /*!< 24Bit System Tick Timer for use in RTOS */ union CSR_DEF { //!< [0000](04)[0x00000004] SysTick Control and Status Register enum ENABLE_ENUM /*: uint32_t */ { ENABLE_0 = 0, //!< disabled ENABLE_1 = 1, //!< enabled }; enum TICKINT_ENUM /*: uint32_t */ { TICKINT_0 = 0, //!< Enable SysTick Exception TICKINT_1 = 1, //!< Disable SysTick Exception }; enum CLKSOURCE_ENUM /*: uint32_t */ { CLKSOURCE_0 = 0, //!< External Clock CLKSOURCE_1 = 1, //!< CPU Clock }; struct { __IO ENABLE_ENUM ENABLE : 1; //!<[00] Enable SysTick Timer __IO TICKINT_ENUM TICKINT : 1; //!<[01] Generate Tick Interrupt __IO CLKSOURCE_ENUM CLKSOURCE : 1; //!<[02] Source to count from uint32_t UNUSED0 : 13; //!<[03] __IO ONE_BIT COUNTFLAG : 1; //!<[16] SysTick counted to zero } B; __IO uint32_t R; explicit CSR_DEF () noexcept { R = 0x00000004u; } template void setbit (F f) volatile { CSR_DEF r; R = f (r); } template void modify (F f) volatile { CSR_DEF r; r.R = R; R = f (r); } }; __IO CSR_DEF CSR ; //!< register definition union RVR_DEF { //!< [0004](04)[0x00000000] SysTick Reload Value Register struct { __IO uint32_t RELOAD : 24; //!<[00] Value to auto reload SysTick after reaching zero } B; __IO uint32_t R; explicit RVR_DEF () noexcept { R = 0x00000000u; } template void setbit (F f) volatile { RVR_DEF r; R = f (r); } template void modify (F f) volatile { RVR_DEF r; r.R = R; R = f (r); } }; __IO RVR_DEF RVR ; //!< register definition union CVR_DEF { //!< [0008](04)[0x00000000] SysTick Current Value Register struct { __IO uint32_t CURRENT : 24; //!<[00] Current value } B; __IO uint32_t R; explicit CVR_DEF () noexcept { R = 0x00000000u; } template void setbit (F f) volatile { CVR_DEF r; R = f (r); } template void modify (F f) volatile { CVR_DEF r; r.R = R; R = f (r); } }; __IO CVR_DEF CVR ; //!< register definition union CALIB_DEF { //!< [000c](04)[0x00000000] SysTick Calibration Value Register enum SKEW_ENUM /*: uint32_t */ { SKEW_0 = 0, //!< 10ms calibration value is exact SKEW_1 = 1, //!< 10ms calibration value is inexact, because of the clock frequency }; enum NOREF_ENUM /*: uint32_t */ { NOREF_0 = 0, //!< Ref Clk available NOREF_1 = 1, //!< Ref Clk not available }; struct { __I uint32_t TENMS : 24; //!<[00] Reload value to use for 10ms timing uint32_t UNUSED0 : 6; //!<[24] __I SKEW_ENUM SKEW : 1; //!<[30] Clock Skew __I NOREF_ENUM NOREF : 1; //!<[31] No Ref } B; __IO uint32_t R; explicit CALIB_DEF () noexcept { R = 0x00000000u; } template void setbit (F f) volatile { CALIB_DEF r; R = f (r); } template void modify (F f) volatile { CALIB_DEF r; r.R = R; R = f (r); } }; __IO CALIB_DEF CALIB ; //!< register definition // methods : bool Config (const uint32_t ticks) { if (ticks > SysTick_LOAD_RELOAD_Msk) return false; // Reload value impossible RVR.B.RELOAD = ticks - 1u; // set reload register NVIC_EnableIRQ (SysTick_IRQn); // Enable Interrupt CVR.B.CURRENT = 0; // Load the SysTick Counter Value CSR.modify([](CSR_DEF & r) -> auto { // Enable SysTick IRQ and SysTick Timer r.B.CLKSOURCE = CSR_DEF::CLKSOURCE_ENUM::CLKSOURCE_1; r.B.TICKINT = CSR_DEF::TICKINT_ENUM ::TICKINT_1; r.B.ENABLE = CSR_DEF::ENABLE_ENUM ::ENABLE_1; return r.R; }); return true; // Function successful } }; /* total size = 0x0010, struct size = 0x0010 */ static SysTick_DEF & SysTick = * reinterpret_cast (0xe000e010); static_assert (sizeof(struct SysTick_DEF) == 16, "size error SysTick"); #endif