diff --git a/libuavcan_drivers/stm32/driver/include/uavcan_stm32/thread.hpp b/libuavcan_drivers/stm32/driver/include/uavcan_stm32/thread.hpp index e3d357fe5d..a358edc67d 100644 --- a/libuavcan_drivers/stm32/driver/include/uavcan_stm32/thread.hpp +++ b/libuavcan_drivers/stm32/driver/include/uavcan_stm32/thread.hpp @@ -16,6 +16,7 @@ # include # include # include +#elif UAVCAN_STM32_BAREMETAL #else # error "Unknown OS" #endif @@ -24,6 +25,7 @@ namespace uavcan_stm32 { + class CanDriver; #if UAVCAN_STM32_CHIBIOS @@ -91,35 +93,47 @@ public: void signalFromInterrupt(); }; -class Mutex +#elif UAVCAN_STM32_BAREMETAL + +class BusEvent { - pthread_mutex_t mutex_; + volatile bool ready; public: - Mutex() + BusEvent(CanDriver& can_driver) + : ready(false) { - init(); + (void)can_driver; } - int init() + bool wait(uavcan::MonotonicDuration duration) { - return pthread_mutex_init(&mutex_, NULL); + bool lready = ready; + return __atomic_exchange_n (&lready, false, __ATOMIC_SEQ_CST); } - int deinit() + void signal() { - return pthread_mutex_destroy(&mutex_); + __atomic_store_n (&ready, true, __ATOMIC_SEQ_CST); } + void signalFromInterrupt() + { + __atomic_store_n (&ready, true, __ATOMIC_SEQ_CST); + } +}; + +class Mutex +{ +public: void lock() { - (void)pthread_mutex_lock(&mutex_); - } + }; void unlock() { - (void)pthread_mutex_unlock(&mutex_); - } + + }; }; class MutexLocker @@ -132,7 +146,6 @@ public: { mutex_.lock(); } - ~MutexLocker() { mutex_.unlock(); @@ -154,7 +167,6 @@ public: { mutex_.lock(); } - ~MutexLocker() { mutex_.unlock(); @@ -162,4 +174,5 @@ public: }; #endif + } diff --git a/libuavcan_drivers/stm32/driver/src/internal.hpp b/libuavcan_drivers/stm32/driver/src/internal.hpp index 4b96ccd317..d258c11c50 100644 --- a/libuavcan_drivers/stm32/driver/src/internal.hpp +++ b/libuavcan_drivers/stm32/driver/src/internal.hpp @@ -13,6 +13,8 @@ # include # include # include +#elif UAVCAN_STM32_BAREMETAL +# include #else # error "Unknown OS" #endif @@ -57,6 +59,15 @@ # endif #endif +#if UAVCAN_STM32_BAREMETAL +/** + * Priority mask for timer and CAN interrupts. + */ +# ifndef UAVCAN_STM32_IRQ_PRIORITY_MASK +# define UAVCAN_STM32_IRQ_PRIORITY_MASK 0 +# endif +#endif + /** * Glue macros */ @@ -92,6 +103,22 @@ struct CriticalSectionLocker } }; +#elif UAVCAN_STM32_BAREMETAL + +struct CriticalSectionLocker +{ + + CriticalSectionLocker() + { + __disable_irq(); + } + + ~CriticalSectionLocker() + { + __enable_irq(); + } +}; + #endif namespace clock diff --git a/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp b/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp index 7e794dc28d..b7d4defbf8 100644 --- a/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp +++ b/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp @@ -14,11 +14,13 @@ # include # include # include +#elif UAVCAN_STM32_BAREMETAL +#include #else # error "Unknown OS" #endif -#if !UAVCAN_STM32_NUTTX +#if UAVCAN_STM32_CHIBIOS || UAVCAN_STM32_BAREMETAL # if !(defined(STM32F10X_CL) || defined(STM32F2XX) || defined(STM32F4XX)) // IRQ numbers # define CAN1_RX0_IRQn USB_LP_CAN1_RX0_IRQn @@ -188,7 +190,9 @@ int CanIface::computeTimings(const uavcan::uint32_t target_bitrate, Timings& out /* * Hardware configuration */ -#if UAVCAN_STM32_CHIBIOS +#if UAVCAN_STM32_BAREMETAL + const uavcan::uint32_t pclk = STM32_PCLK1_FREQUENCY; +#elif UAVCAN_STM32_CHIBIOS const uavcan::uint32_t pclk = STM32_PCLK1; #elif UAVCAN_STM32_NUTTX const uavcan::uint32_t pclk = STM32_PCLK1_FREQUENCY; @@ -838,6 +842,22 @@ uavcan::int16_t CanDriver::select(uavcan::CanSelectMasks& inout_masks, return 1; // Return value doesn't matter as long as it is non-negative } + +#if UAVCAN_STM32_BAREMETAL + +static void nvicEnableVector(int irq, uint8_t prio) +{ + NVIC_InitTypeDef NVIC_InitStructure; + NVIC_InitStructure.NVIC_IRQChannel = irq; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = prio; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + +} + +#endif + int CanDriver::init(const uavcan::uint32_t bitrate, const CanIface::OperatingMode mode) { int res = 0; @@ -921,7 +941,7 @@ int CanDriver::init(const uavcan::uint32_t bitrate, const CanIface::OperatingMod IRQ_ATTACH(STM32_IRQ_CAN2SCE, can2_irq); # endif # undef IRQ_ATTACH -#else +#elif UAVCAN_STM32_CHIBIOS || UAVCAN_STM32_BAREMETAL { CriticalSectionLocker lock; nvicEnableVector(CAN1_TX_IRQn, UAVCAN_STM32_IRQ_PRIORITY_MASK); @@ -1044,7 +1064,7 @@ static int can2_irq(const int irq, void*) # endif #else // UAVCAN_STM32_NUTTX - +UAVCAN_STM32_IRQ_HANDLER(CAN1_TX_IRQHandler); UAVCAN_STM32_IRQ_HANDLER(CAN1_TX_IRQHandler) { UAVCAN_STM32_IRQ_PROLOGUE(); @@ -1052,6 +1072,7 @@ UAVCAN_STM32_IRQ_HANDLER(CAN1_TX_IRQHandler) UAVCAN_STM32_IRQ_EPILOGUE(); } +UAVCAN_STM32_IRQ_HANDLER(CAN1_RX0_IRQHandler); UAVCAN_STM32_IRQ_HANDLER(CAN1_RX0_IRQHandler) { UAVCAN_STM32_IRQ_PROLOGUE(); @@ -1059,6 +1080,7 @@ UAVCAN_STM32_IRQ_HANDLER(CAN1_RX0_IRQHandler) UAVCAN_STM32_IRQ_EPILOGUE(); } +UAVCAN_STM32_IRQ_HANDLER(CAN1_RX1_IRQHandler); UAVCAN_STM32_IRQ_HANDLER(CAN1_RX1_IRQHandler) { UAVCAN_STM32_IRQ_PROLOGUE(); @@ -1066,6 +1088,7 @@ UAVCAN_STM32_IRQ_HANDLER(CAN1_RX1_IRQHandler) UAVCAN_STM32_IRQ_EPILOGUE(); } +UAVCAN_STM32_IRQ_HANDLER(CAN1_SCE_IRQHandler); UAVCAN_STM32_IRQ_HANDLER(CAN1_SCE_IRQHandler) { UAVCAN_STM32_IRQ_PROLOGUE(); @@ -1075,6 +1098,7 @@ UAVCAN_STM32_IRQ_HANDLER(CAN1_SCE_IRQHandler) # if UAVCAN_STM32_NUM_IFACES > 1 +UAVCAN_STM32_IRQ_HANDLER(CAN2_TX_IRQHandler); UAVCAN_STM32_IRQ_HANDLER(CAN2_TX_IRQHandler) { UAVCAN_STM32_IRQ_PROLOGUE(); @@ -1082,6 +1106,7 @@ UAVCAN_STM32_IRQ_HANDLER(CAN2_TX_IRQHandler) UAVCAN_STM32_IRQ_EPILOGUE(); } +UAVCAN_STM32_IRQ_HANDLER(CAN2_RX0_IRQHandler); UAVCAN_STM32_IRQ_HANDLER(CAN2_RX0_IRQHandler) { UAVCAN_STM32_IRQ_PROLOGUE(); @@ -1089,6 +1114,7 @@ UAVCAN_STM32_IRQ_HANDLER(CAN2_RX0_IRQHandler) UAVCAN_STM32_IRQ_EPILOGUE(); } +UAVCAN_STM32_IRQ_HANDLER(CAN2_RX1_IRQHandler); UAVCAN_STM32_IRQ_HANDLER(CAN2_RX1_IRQHandler) { UAVCAN_STM32_IRQ_PROLOGUE(); @@ -1096,6 +1122,7 @@ UAVCAN_STM32_IRQ_HANDLER(CAN2_RX1_IRQHandler) UAVCAN_STM32_IRQ_EPILOGUE(); } +UAVCAN_STM32_IRQ_HANDLER(CAN2_SCE_IRQHandler); UAVCAN_STM32_IRQ_HANDLER(CAN2_SCE_IRQHandler) { UAVCAN_STM32_IRQ_PROLOGUE(); diff --git a/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp b/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp index e612c21df1..1359fd970e 100644 --- a/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp +++ b/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp @@ -14,7 +14,7 @@ /* * Timer instance */ -# if UAVCAN_STM32_CHIBIOS +# if UAVCAN_STM32_CHIBIOS || UAVCAN_STM32_BAREMETAL # define TIMX UAVCAN_STM32_GLUE2(TIM, UAVCAN_STM32_TIMER_NUMBER) # define TIMX_IRQn UAVCAN_STM32_GLUE3(TIM, UAVCAN_STM32_TIMER_NUMBER, _IRQn) # define TIMX_INPUT_CLOCK STM32_TIMCLK1 @@ -70,6 +70,23 @@ uavcan::MonotonicTime prev_utc_adj_at; uavcan::uint64_t time_mono = 0; uavcan::uint64_t time_utc = 0; } +# if UAVCAN_STM32_NUTTX || UAVCAN_STM32_BAREMETAL + +#if UAVCAN_STM32_BAREMETAL + +static void nvicEnableVector(int irq, uint8_t prio) +{ + NVIC_InitTypeDef NVIC_InitStructure; + NVIC_InitStructure.NVIC_IRQChannel = irq; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = prio; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + +} + +#endif + void init() @@ -82,7 +99,7 @@ void init() initialized = true; -# if UAVCAN_STM32_CHIBIOS +# if UAVCAN_STM32_CHIBIOS || UAVCAN_STM32_BAREMETAL // Power-on and reset TIMX_RCC_ENR |= TIMX_RCC_ENR_MASK; TIMX_RCC_RSTR |= TIMX_RCC_RSTR_MASK; @@ -201,7 +218,7 @@ uavcan::MonotonicTime getMonotonic() volatile uavcan::uint64_t time = time_mono; -# if UAVCAN_STM32_CHIBIOS +# if UAVCAN_STM32_CHIBIOS || UAVCAN_STM32_BAREMETAL volatile uavcan::uint32_t cnt = TIMX->CNT; if (TIMX->SR & TIM_SR_UIF)