From 4c80149b23e3acf383cd879b310a263ea82d59ad Mon Sep 17 00:00:00 2001 From: David Sidrane Date: Fri, 7 Aug 2015 10:44:13 -1000 Subject: [PATCH 01/39] Adds Nuttx Support to uc_stm32_clock --- .../driver/include/uavcan_stm32/thread.hpp | 51 ++++++- .../stm32/driver/src/internal.hpp | 15 +- .../stm32/driver/src/uc_stm32_clock.cpp | 141 ++++++++++++++---- 3 files changed, 167 insertions(+), 40 deletions(-) diff --git a/libuavcan_drivers/stm32/driver/include/uavcan_stm32/thread.hpp b/libuavcan_drivers/stm32/driver/include/uavcan_stm32/thread.hpp index 1ad2d30716..e3d357fe5d 100644 --- a/libuavcan_drivers/stm32/driver/include/uavcan_stm32/thread.hpp +++ b/libuavcan_drivers/stm32/driver/include/uavcan_stm32/thread.hpp @@ -24,7 +24,6 @@ namespace uavcan_stm32 { - class CanDriver; #if UAVCAN_STM32_CHIBIOS @@ -92,6 +91,54 @@ public: void signalFromInterrupt(); }; +class Mutex +{ + pthread_mutex_t mutex_; + +public: + Mutex() + { + init(); + } + + int init() + { + return pthread_mutex_init(&mutex_, NULL); + } + + int deinit() + { + return pthread_mutex_destroy(&mutex_); + } + + void lock() + { + (void)pthread_mutex_lock(&mutex_); + } + + void unlock() + { + (void)pthread_mutex_unlock(&mutex_); + } +}; + +class MutexLocker +{ + Mutex& mutex_; + +public: + MutexLocker(Mutex& mutex) + : mutex_(mutex) + { + mutex_.lock(); + } + + ~MutexLocker() + { + mutex_.unlock(); + } +}; + #endif @@ -107,6 +154,7 @@ public: { mutex_.lock(); } + ~MutexLocker() { mutex_.unlock(); @@ -114,5 +162,4 @@ public: }; #endif - } diff --git a/libuavcan_drivers/stm32/driver/src/internal.hpp b/libuavcan_drivers/stm32/driver/src/internal.hpp index 3a63ef5de0..4b96ccd317 100644 --- a/libuavcan_drivers/stm32/driver/src/internal.hpp +++ b/libuavcan_drivers/stm32/driver/src/internal.hpp @@ -10,6 +10,8 @@ # include #elif UAVCAN_STM32_NUTTX # include +# include +# include # include #else # error "Unknown OS" @@ -20,7 +22,7 @@ */ #ifndef UAVCAN_STM32_LOG // lowsyslog() crashes the system in this context -//# if UAVCAN_STM32_NUTTX && CONFIG_ARCH_LOWPUTC +// # if UAVCAN_STM32_NUTTX && CONFIG_ARCH_LOWPUTC # if 0 # define UAVCAN_STM32_LOG(fmt, ...) lowsyslog("uavcan_stm32: " fmt "\n", ##__VA_ARGS__) # else @@ -36,13 +38,14 @@ # define UAVCAN_STM32_IRQ_HANDLER(id) CH_IRQ_HANDLER(id) # define UAVCAN_STM32_IRQ_PROLOGUE() CH_IRQ_PROLOGUE() # define UAVCAN_STM32_IRQ_EPILOGUE() CH_IRQ_EPILOGUE() - +#elif UAVCAN_STM32_NUTTX +# define UAVCAN_STM32_IRQ_HANDLER(id) int id(int irq, FAR void* context) +# define UAVCAN_STM32_IRQ_PROLOGUE() +# define UAVCAN_STM32_IRQ_EPILOGUE() return 0; #else - # define UAVCAN_STM32_IRQ_HANDLER(id) void id(void) # define UAVCAN_STM32_IRQ_PROLOGUE() # define UAVCAN_STM32_IRQ_EPILOGUE() - #endif #if UAVCAN_STM32_CHIBIOS @@ -65,7 +68,6 @@ namespace uavcan_stm32 { - #if UAVCAN_STM32_CHIBIOS struct CriticalSectionLocker @@ -94,9 +96,6 @@ struct CriticalSectionLocker namespace clock { - uavcan::uint64_t getUtcUSecFromCanInterrupt(); - } - } diff --git a/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp b/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp index 046aa30a78..8af1f4a40d 100644 --- a/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp +++ b/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp @@ -14,19 +14,35 @@ /* * Timer instance */ -#define TIMX UAVCAN_STM32_GLUE2(TIM, UAVCAN_STM32_TIMER_NUMBER) -#define TIMX_IRQn UAVCAN_STM32_GLUE3(TIM, UAVCAN_STM32_TIMER_NUMBER, _IRQn) -#define TIMX_IRQHandler UAVCAN_STM32_GLUE3(TIM, UAVCAN_STM32_TIMER_NUMBER, _IRQHandler) +# if UAVCAN_STM32_CHIBIOS +# 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 +# endif -#if UAVCAN_STM32_TIMER_NUMBER >= 2 && UAVCAN_STM32_TIMER_NUMBER <= 7 -# define TIMX_RCC_ENR RCC->APB1ENR -# define TIMX_RCC_RSTR RCC->APB1RSTR -# define TIMX_RCC_ENR_MASK UAVCAN_STM32_GLUE3(RCC_APB1ENR_TIM, UAVCAN_STM32_TIMER_NUMBER, EN) -# define TIMX_RCC_RSTR_MASK UAVCAN_STM32_GLUE3(RCC_APB1RSTR_TIM, UAVCAN_STM32_TIMER_NUMBER, RST) -# define TIMX_INPUT_CLOCK STM32_TIMCLK1 -#else -# error "This UAVCAN_STM32_TIMER_NUMBER is not supported yet" -#endif +# if UAVCAN_STM32_NUTTX +# define TIMX UAVCAN_STM32_GLUE3(STM32_TIM, UAVCAN_STM32_TIMER_NUMBER, _BASE) +# define TMR_REG(o) (TIMX + (o)) +# define TIMX_INPUT_CLOCK STM32_TIM18_FREQUENCY + +# define TIMX_IRQn UAVCAN_STM32_GLUE2(STM32_IRQ_TIM, UAVCAN_STM32_TIMER_NUMBER) +# endif +# define TIMX_IRQHandler UAVCAN_STM32_GLUE3(TIM, UAVCAN_STM32_TIMER_NUMBER, _IRQHandler) + +# if UAVCAN_STM32_TIMER_NUMBER >= 2 && UAVCAN_STM32_TIMER_NUMBER <= 7 +# define TIMX_RCC_ENR RCC->APB1ENR +# define TIMX_RCC_RSTR RCC->APB1RSTR +# define TIMX_RCC_ENR_MASK UAVCAN_STM32_GLUE3(RCC_APB1ENR_TIM, UAVCAN_STM32_TIMER_NUMBER, EN) +# define TIMX_RCC_RSTR_MASK UAVCAN_STM32_GLUE3(RCC_APB1RSTR_TIM, UAVCAN_STM32_TIMER_NUMBER, RST) +# else +# error "This UAVCAN_STM32_TIMER_NUMBER is not supported yet" +# endif + +# if (TIMX_INPUT_CLOCK % 1000000) != 0 +# error "No way, timer clock must be divisible to 1e6. FIXME!" +# endif + +extern "C" UAVCAN_STM32_IRQ_HANDLER(TIMX_IRQHandler); namespace uavcan_stm32 { @@ -34,7 +50,6 @@ namespace clock { namespace { - const uavcan::uint32_t USecPerOverflow = 65536; Mutex mutex; @@ -54,9 +69,9 @@ uavcan::MonotonicTime prev_utc_adj_at; uavcan::uint64_t time_mono = 0; uavcan::uint64_t time_utc = 0; - } + void init() { CriticalSectionLocker lock; @@ -66,6 +81,8 @@ void init() } initialized = true; + +# if UAVCAN_STM32_CHIBIOS // Power-on and reset TIMX_RCC_ENR |= TIMX_RCC_ENR_MASK; TIMX_RCC_RSTR |= TIMX_RCC_RSTR_MASK; @@ -74,9 +91,6 @@ void init() // Enable IRQ nvicEnableVector(TIMX_IRQn, UAVCAN_STM32_IRQ_PRIORITY_MASK); -#if (TIMX_INPUT_CLOCK % 1000000) != 0 -# error "No way, timer clock must be divisible to 1e6. FIXME!" -#endif // Start the timer TIMX->ARR = 0xFFFF; @@ -86,10 +100,39 @@ void init() TIMX->EGR = TIM_EGR_UG; // Reload immediately TIMX->DIER = TIM_DIER_UIE; TIMX->CR1 = TIM_CR1_CEN; // Start + +# endif + +# if UAVCAN_STM32_NUTTX + + // Attach IRQ + irq_attach(TIMX_IRQn, &TIMX_IRQHandler); + + // Power-on and reset + modifyreg32(STM32_RCC_APB1ENR, 0, TIMX_RCC_ENR_MASK); + modifyreg32(STM32_RCC_APB1RSTR, 0, TIMX_RCC_RSTR_MASK); + modifyreg32(STM32_RCC_APB1RSTR, TIMX_RCC_RSTR_MASK, 0); + + + // Start the timer + putreg32(0xFFFF, TMR_REG(STM32_BTIM_ARR_OFFSET)); + putreg16((TIMX_INPUT_CLOCK / 1000000), TMR_REG(STM32_BTIM_PSC_OFFSET)); + putreg16(BTIM_CR1_URS, TMR_REG(STM32_BTIM_CR1_OFFSET)); + putreg16(0, TMR_REG(STM32_BTIM_SR_OFFSET)); + putreg16(BTIM_EGR_UG, TMR_REG(STM32_BTIM_EGR_OFFSET)); // Reload immediately + putreg16(BTIM_DIER_UIE, TMR_REG(STM32_BTIM_DIER_OFFSET)); + putreg16(BTIM_CR1_CEN, TMR_REG(STM32_BTIM_CR1_OFFSET)); // Start + + // Prioritize and Enable IRQ + up_prioritize_irq(TIMX_IRQn, NVIC_SYSH_HIGH_PRIORITY); + up_enable_irq(TIMX_IRQn); + +# endif } static uavcan::uint64_t sampleUtcFromCriticalSection() { +# if UAVCAN_STM32_CHIBIOS UAVCAN_ASSERT(initialized); UAVCAN_ASSERT(TIMX->DIER & TIM_DIER_UIE); @@ -104,6 +147,25 @@ static uavcan::uint64_t sampleUtcFromCriticalSection() time = uavcan::uint64_t(uavcan::int64_t(time) + add); } return time + cnt; +# endif + +# if UAVCAN_STM32_NUTTX + + UAVCAN_ASSERT(initialized); + UAVCAN_ASSERT(getreg16(TMR_REG(STM32_BTIM_DIER_OFFSET)) & BTIM_DIER_UIE); + + volatile uavcan::uint64_t time = time_utc; + volatile uavcan::uint32_t cnt = getreg16(TMR_REG(STM32_BTIM_CNT_OFFSET)); + + if (getreg16(TMR_REG(STM32_BTIM_SR_OFFSET)) & BTIM_SR_UIF) + { + cnt = getreg16(TMR_REG(STM32_BTIM_CNT_OFFSET)); + const uavcan::int32_t add = uavcan::int32_t(USecPerOverflow) + + (utc_accumulated_correction_nsec + utc_correction_nsec_per_overflow) / 1000; + time = uavcan::uint64_t(uavcan::int64_t(time) + add); + } + return time + cnt; +# endif } uavcan::uint64_t getUtcUSecFromCanInterrupt() @@ -118,21 +180,34 @@ uavcan::MonotonicTime getMonotonic() CriticalSectionLocker locker; volatile uavcan::uint64_t time = time_mono; +# if UAVCAN_STM32_CHIBIOS + volatile uavcan::uint32_t cnt = TIMX->CNT; if (TIMX->SR & TIM_SR_UIF) { cnt = TIMX->CNT; - time += USecPerOverflow; - } - usec = time + cnt; +# endif +# if UAVCAN_STM32_NUTTX -#ifndef NDEBUG - static uavcan::uint64_t prev_usec = 0; // Self-test - UAVCAN_ASSERT(prev_usec <= usec); - prev_usec = usec; -#endif + volatile uavcan::uint32_t cnt = getreg16(TMR_REG(STM32_BTIM_CNT_OFFSET)); + + if (getreg16(TMR_REG(STM32_BTIM_SR_OFFSET)) & BTIM_SR_UIF) + { + cnt = getreg16(TMR_REG(STM32_BTIM_CNT_OFFSET)); +# endif + time += USecPerOverflow; } - return uavcan::MonotonicTime::fromUSec(usec); + usec = time + cnt; + +# ifndef NDEBUG + static uavcan::uint64_t prev_usec = 0; // Self-test + UAVCAN_ASSERT(prev_usec <= usec); + (void)prev_usec; + prev_usec = usec; +# endif +} + +return uavcan::MonotonicTime::fromUSec(usec); } uavcan::UtcTime getUtc() @@ -201,7 +276,8 @@ static void updateRatePID(uavcan::UtcDuration adjustment) utc_correction_nsec_per_overflow = uavcan::int32_t((USecPerOverflow * 1000) * (total_rate_correction_ppm / 1e6F)); // lowsyslog("$ adj=%f rel_rate=%f rel_rate_eint=%f tgt_rel_rate=%f ppm=%f\n", -// adj_usec, utc_rel_rate_ppm, utc_rel_rate_error_integral, target_rel_rate_ppm, total_rate_correction_ppm); +// adj_usec, utc_rel_rate_ppm, utc_rel_rate_error_integral, target_rel_rate_ppm, +// total_rate_correction_ppm); } void adjustUtc(uavcan::UtcDuration adjustment) @@ -275,7 +351,6 @@ void setUtcSyncParams(const UtcSyncParams& params) // Add some sanity check utc_sync_params = params; } - } // namespace clock SystemClock& SystemClock::instance() @@ -288,28 +363,34 @@ SystemClock& SystemClock::instance() long long _aligner_1; long double _aligner_2; } storage; + SystemClock* const ptr = reinterpret_cast(storage.buffer); if (!clock::initialized) { clock::init(); - new (ptr) SystemClock(); + new (ptr)SystemClock(); } return *ptr; } - } // namespace uavcan_stm32 /** * Timer interrupt handler */ + extern "C" UAVCAN_STM32_IRQ_HANDLER(TIMX_IRQHandler) { UAVCAN_STM32_IRQ_PROLOGUE(); +# if UAVCAN_STM32_CHIBIOS TIMX->SR = 0; +# endif +# if UAVCAN_STM32_NUTTX + putreg16(0, TMR_REG(STM32_BTIM_SR_OFFSET)); +# endif using namespace uavcan_stm32::clock; UAVCAN_ASSERT(initialized); From 9e51b2b12577bad3ab7b6bb1a9db223deefd0fbe Mon Sep 17 00:00:00 2001 From: David Sidrane Date: Sat, 8 Aug 2015 07:18:24 -1000 Subject: [PATCH 02/39] Adding mechanism to update the drivers notion of UTC from the system RTC Fixed Clock source and prescale calculation --- .../driver/include/uavcan_stm32/clock.hpp | 8 +++++ .../stm32/driver/src/uc_stm32_clock.cpp | 34 +++++++++++++++---- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/libuavcan_drivers/stm32/driver/include/uavcan_stm32/clock.hpp b/libuavcan_drivers/stm32/driver/include/uavcan_stm32/clock.hpp index 7ab754251a..b11438d787 100644 --- a/libuavcan_drivers/stm32/driver/include/uavcan_stm32/clock.hpp +++ b/libuavcan_drivers/stm32/driver/include/uavcan_stm32/clock.hpp @@ -24,6 +24,14 @@ void init(); */ uavcan::MonotonicTime getMonotonic(); +/** + * Sets the driver's notion of the system UTC. It should be called + * at startup and any time the system clock is updated from an + * external source that is not the UAVCAN Timesync master. + * This function is thread safe. + */ +void setUtc(uavcan::UtcTime time); + /** * Returns UTC time if it has been set, otherwise returns zero time. * This function is thread safe. diff --git a/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp b/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp index 8af1f4a40d..0acdf6cec9 100644 --- a/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp +++ b/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp @@ -23,7 +23,7 @@ # if UAVCAN_STM32_NUTTX # define TIMX UAVCAN_STM32_GLUE3(STM32_TIM, UAVCAN_STM32_TIMER_NUMBER, _BASE) # define TMR_REG(o) (TIMX + (o)) -# define TIMX_INPUT_CLOCK STM32_TIM18_FREQUENCY +# define TIMX_INPUT_CLOCK STM32_TIM27_FREQUENCY # define TIMX_IRQn UAVCAN_STM32_GLUE2(STM32_IRQ_TIM, UAVCAN_STM32_TIMER_NUMBER) # endif @@ -116,7 +116,7 @@ void init() // Start the timer putreg32(0xFFFF, TMR_REG(STM32_BTIM_ARR_OFFSET)); - putreg16((TIMX_INPUT_CLOCK / 1000000), TMR_REG(STM32_BTIM_PSC_OFFSET)); + putreg16(((TIMX_INPUT_CLOCK / 1000000)-1), TMR_REG(STM32_BTIM_PSC_OFFSET)); putreg16(BTIM_CR1_URS, TMR_REG(STM32_BTIM_CR1_OFFSET)); putreg16(0, TMR_REG(STM32_BTIM_SR_OFFSET)); putreg16(BTIM_EGR_UG, TMR_REG(STM32_BTIM_EGR_OFFSET)); // Reload immediately @@ -130,6 +130,23 @@ void init() # endif } +void setUtc(uavcan::UtcTime time) +{ + MutexLocker mlocker(mutex); + UAVCAN_ASSERT(initialized); + + { + CriticalSectionLocker locker; + time_utc = time.toUSec(); + } + + utc_set = true; + utc_locked = false; + utc_jump_cnt++; + utc_prev_adj = 0; + utc_rel_rate_ppm = 0; +} + static uavcan::uint64_t sampleUtcFromCriticalSection() { # if UAVCAN_STM32_CHIBIOS @@ -176,10 +193,12 @@ uavcan::uint64_t getUtcUSecFromCanInterrupt() uavcan::MonotonicTime getMonotonic() { uavcan::uint64_t usec = 0; + // Scope Critical section { CriticalSectionLocker locker; volatile uavcan::uint64_t time = time_mono; + # if UAVCAN_STM32_CHIBIOS volatile uavcan::uint32_t cnt = TIMX->CNT; @@ -187,6 +206,7 @@ uavcan::MonotonicTime getMonotonic() { cnt = TIMX->CNT; # endif + # if UAVCAN_STM32_NUTTX volatile uavcan::uint32_t cnt = getreg16(TMR_REG(STM32_BTIM_CNT_OFFSET)); @@ -195,9 +215,9 @@ uavcan::MonotonicTime getMonotonic() { cnt = getreg16(TMR_REG(STM32_BTIM_CNT_OFFSET)); # endif - time += USecPerOverflow; - } - usec = time + cnt; + time += USecPerOverflow; + } + usec = time + cnt; # ifndef NDEBUG static uavcan::uint64_t prev_usec = 0; // Self-test @@ -205,9 +225,9 @@ uavcan::MonotonicTime getMonotonic() (void)prev_usec; prev_usec = usec; # endif -} + } // End Scope Critical section -return uavcan::MonotonicTime::fromUSec(usec); + return uavcan::MonotonicTime::fromUSec(usec); } uavcan::UtcTime getUtc() From b0fef2ed1f930df3fc510745fb1b70d50e98f10f Mon Sep 17 00:00:00 2001 From: David Sidrane Date: Sat, 8 Aug 2015 09:42:59 -1000 Subject: [PATCH 03/39] Backing out setting priority of driver's clock tick under nuttx as it is hard faulting the system in IRQ --- libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp b/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp index 0acdf6cec9..e612c21df1 100644 --- a/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp +++ b/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp @@ -124,7 +124,9 @@ void init() putreg16(BTIM_CR1_CEN, TMR_REG(STM32_BTIM_CR1_OFFSET)); // Start // Prioritize and Enable IRQ - up_prioritize_irq(TIMX_IRQn, NVIC_SYSH_HIGH_PRIORITY); +// todo: Currently changing the NVIC_SYSH_HIGH_PRIORITY is HARD faulting +// need to investigate +// up_prioritize_irq(TIMX_IRQn, NVIC_SYSH_HIGH_PRIORITY); up_enable_irq(TIMX_IRQn); # endif From 9750e3f58dd6972dc2e0f90b93958e1bf438feaa Mon Sep 17 00:00:00 2001 From: David Sidrane Date: Wed, 12 Aug 2015 15:21:02 -1000 Subject: [PATCH 04/39] Initail STM32 Baremetal build --- .../driver/include/uavcan_stm32/thread.hpp | 41 ++++++++++++------- .../stm32/driver/src/internal.hpp | 27 ++++++++++++ .../stm32/driver/src/uc_stm32_can.cpp | 35 ++++++++++++++-- .../stm32/driver/src/uc_stm32_clock.cpp | 23 +++++++++-- 4 files changed, 105 insertions(+), 21 deletions(-) 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) From 06ac74bd40e6e82448b1f1b897a3eebd9c4ac76a Mon Sep 17 00:00:00 2001 From: David Sidrane Date: Fri, 14 Aug 2015 07:24:41 -1000 Subject: [PATCH 05/39] Rebased on stm32_nuttx_clock --- .../driver/include/uavcan_stm32/thread.hpp | 50 +++++++++++-------- .../stm32/driver/src/internal.hpp | 1 - .../stm32/driver/src/uc_stm32_clock.cpp | 14 ++++-- 3 files changed, 39 insertions(+), 26 deletions(-) diff --git a/libuavcan_drivers/stm32/driver/include/uavcan_stm32/thread.hpp b/libuavcan_drivers/stm32/driver/include/uavcan_stm32/thread.hpp index a358edc67d..3ad7dfe53f 100644 --- a/libuavcan_drivers/stm32/driver/include/uavcan_stm32/thread.hpp +++ b/libuavcan_drivers/stm32/driver/include/uavcan_stm32/thread.hpp @@ -93,6 +93,36 @@ public: void signalFromInterrupt(); }; +class Mutex +{ + pthread_mutex_t mutex_; + +public: + Mutex() + { + init(); + } + + int init() + { + return pthread_mutex_init(&mutex_, NULL); + } + + int deinit() + { + return pthread_mutex_destroy(&mutex_); + } + + void lock() + { + (void)pthread_mutex_lock(&mutex_); + } + + void unlock() + { + (void)pthread_mutex_unlock(&mutex_); + } +}; #elif UAVCAN_STM32_BAREMETAL class BusEvent @@ -136,27 +166,9 @@ public: }; }; -class MutexLocker -{ - Mutex& mutex_; - -public: - MutexLocker(Mutex& mutex) - : mutex_(mutex) - { - mutex_.lock(); - } - ~MutexLocker() - { - mutex_.unlock(); - } -}; - #endif -#if UAVCAN_STM32_CHIBIOS - class MutexLocker { Mutex& mutex_; @@ -173,6 +185,4 @@ public: } }; -#endif - } diff --git a/libuavcan_drivers/stm32/driver/src/internal.hpp b/libuavcan_drivers/stm32/driver/src/internal.hpp index d258c11c50..36789c2991 100644 --- a/libuavcan_drivers/stm32/driver/src/internal.hpp +++ b/libuavcan_drivers/stm32/driver/src/internal.hpp @@ -36,7 +36,6 @@ * IRQ handler macros */ #if UAVCAN_STM32_CHIBIOS - # define UAVCAN_STM32_IRQ_HANDLER(id) CH_IRQ_HANDLER(id) # define UAVCAN_STM32_IRQ_PROLOGUE() CH_IRQ_PROLOGUE() # define UAVCAN_STM32_IRQ_EPILOGUE() CH_IRQ_EPILOGUE() diff --git a/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp b/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp index 1359fd970e..b54bf1be86 100644 --- a/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp +++ b/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp @@ -50,6 +50,7 @@ namespace clock { namespace { + const uavcan::uint32_t USecPerOverflow = 65536; Mutex mutex; @@ -69,8 +70,8 @@ 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 @@ -87,8 +88,6 @@ static void nvicEnableVector(int irq, uint8_t prio) #endif - - void init() { CriticalSectionLocker lock; @@ -108,6 +107,9 @@ void init() // Enable IRQ nvicEnableVector(TIMX_IRQn, UAVCAN_STM32_IRQ_PRIORITY_MASK); +# if (TIMX_INPUT_CLOCK % 1000000) != 0 +# error "No way, timer clock must be divisible to 1e6. FIXME!" +# endif // Start the timer TIMX->ARR = 0xFFFF; @@ -168,7 +170,7 @@ void setUtc(uavcan::UtcTime time) static uavcan::uint64_t sampleUtcFromCriticalSection() { -# if UAVCAN_STM32_CHIBIOS +# if UAVCAN_STM32_CHIBIOS || UAVCAN_STM32_BARMETAL UAVCAN_ASSERT(initialized); UAVCAN_ASSERT(TIMX->DIER & TIM_DIER_UIE); @@ -390,6 +392,7 @@ void setUtcSyncParams(const UtcSyncParams& params) // Add some sanity check utc_sync_params = params; } + } // namespace clock SystemClock& SystemClock::instance() @@ -412,6 +415,7 @@ SystemClock& SystemClock::instance() } return *ptr; } + } // namespace uavcan_stm32 @@ -424,7 +428,7 @@ UAVCAN_STM32_IRQ_HANDLER(TIMX_IRQHandler) { UAVCAN_STM32_IRQ_PROLOGUE(); -# if UAVCAN_STM32_CHIBIOS +# if UAVCAN_STM32_CHIBIOS || UAVCAN_STM32_BAREMETAL TIMX->SR = 0; # endif # if UAVCAN_STM32_NUTTX From 7fc43d0cbf638c06cfd385a0dab075649159748c Mon Sep 17 00:00:00 2001 From: David Sidrane Date: Tue, 18 Aug 2015 15:35:30 -1000 Subject: [PATCH 06/39] Fixed Typo --- libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp b/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp index b54bf1be86..a94a543beb 100644 --- a/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp +++ b/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp @@ -170,7 +170,7 @@ void setUtc(uavcan::UtcTime time) static uavcan::uint64_t sampleUtcFromCriticalSection() { -# if UAVCAN_STM32_CHIBIOS || UAVCAN_STM32_BARMETAL +# if UAVCAN_STM32_CHIBIOS || UAVCAN_STM32_BAREMETAL UAVCAN_ASSERT(initialized); UAVCAN_ASSERT(TIMX->DIER & TIM_DIER_UIE); From 4dff5c2223746070a0385cdf8132c90eb06bf06a Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Wed, 2 Sep 2015 19:16:11 +0300 Subject: [PATCH 07/39] Stupid typo in allocation request manager --- .../dynamic_node_id_server/allocation_request_manager.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libuavcan/include/uavcan/protocol/dynamic_node_id_server/allocation_request_manager.hpp b/libuavcan/include/uavcan/protocol/dynamic_node_id_server/allocation_request_manager.hpp index df43c1e41d..b68a7005d6 100644 --- a/libuavcan/include/uavcan/protocol/dynamic_node_id_server/allocation_request_manager.hpp +++ b/libuavcan/include/uavcan/protocol/dynamic_node_id_server/allocation_request_manager.hpp @@ -154,7 +154,7 @@ class AllocationRequestManager } const uint8_t expected_stage = getExpectedStage(); - if (request_stage == InvalidStage) + if (expected_stage == InvalidStage) { UAVCAN_ASSERT(0); return; From 73242f39c6f453fa7b0f6185bf0da5d14c2cea6f Mon Sep 17 00:00:00 2001 From: Antoine Albertelli Date: Thu, 3 Sep 2015 17:41:01 +0200 Subject: [PATCH 08/39] Update stm32 drivers to ChibiOS 3.0 --- libuavcan_drivers/stm32/driver/src/internal.hpp | 2 +- .../stm32/driver/src/uc_stm32_thread.cpp | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libuavcan_drivers/stm32/driver/src/internal.hpp b/libuavcan_drivers/stm32/driver/src/internal.hpp index 36789c2991..1279ae2a9b 100644 --- a/libuavcan_drivers/stm32/driver/src/internal.hpp +++ b/libuavcan_drivers/stm32/driver/src/internal.hpp @@ -54,7 +54,7 @@ * Priority mask for timer and CAN interrupts. */ # ifndef UAVCAN_STM32_IRQ_PRIORITY_MASK -# define UAVCAN_STM32_IRQ_PRIORITY_MASK CORTEX_PRIORITY_MASK(CORTEX_MAX_KERNEL_PRIORITY) +# define UAVCAN_STM32_IRQ_PRIORITY_MASK CORTEX_PRIO_MASK(CORTEX_MAX_KERNEL_PRIORITY) # endif #endif diff --git a/libuavcan_drivers/stm32/driver/src/uc_stm32_thread.cpp b/libuavcan_drivers/stm32/driver/src/uc_stm32_thread.cpp index eb93cc215f..c4e5710a0a 100644 --- a/libuavcan_drivers/stm32/driver/src/uc_stm32_thread.cpp +++ b/libuavcan_drivers/stm32/driver/src/uc_stm32_thread.cpp @@ -23,13 +23,13 @@ bool BusEvent::wait(uavcan::MonotonicDuration duration) if (msec <= 0) { - ret = sem_.waitTimeout(TIME_IMMEDIATE); + ret = sem_.wait(TIME_IMMEDIATE); } else { - ret = sem_.waitTimeout((msec > MaxDelayMSec) ? MS2ST(MaxDelayMSec) : MS2ST(msec)); + ret = sem_.wait((msec > MaxDelayMSec) ? MS2ST(MaxDelayMSec) : MS2ST(msec)); } - return ret == RDY_OK; + return ret == MSG_OK; } void BusEvent::signal() @@ -39,9 +39,9 @@ void BusEvent::signal() void BusEvent::signalFromInterrupt() { - chSysLockFromIsr(); + chSysLockFromISR(); sem_.signalI(); - chSysUnlockFromIsr(); + chSysUnlockFromISR(); } /* @@ -54,7 +54,7 @@ void Mutex::lock() void Mutex::unlock() { - chibios_rt::BaseThread::unlockMutex(); + mtx_.unlock(); } #elif UAVCAN_STM32_NUTTX From 3efd9bdfd0c2ce8e659cbffadb885e1fa92d0d29 Mon Sep 17 00:00:00 2001 From: Antoine Albertelli Date: Thu, 3 Sep 2015 18:15:09 +0200 Subject: [PATCH 09/39] Correct CORTEX_MAX_KERNEL_PRIORITY use Now the NVIC minidriver always take the priority as parameter, the use of the CORTEX_PRIORITY_MASK() macro is no more required. Reference: http://www.chibios.org/dokuwiki/doku.php?id=chibios:articles:porting_from_2_to_3 --- libuavcan_drivers/stm32/driver/src/internal.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libuavcan_drivers/stm32/driver/src/internal.hpp b/libuavcan_drivers/stm32/driver/src/internal.hpp index 1279ae2a9b..9bb7ac0be7 100644 --- a/libuavcan_drivers/stm32/driver/src/internal.hpp +++ b/libuavcan_drivers/stm32/driver/src/internal.hpp @@ -54,7 +54,7 @@ * Priority mask for timer and CAN interrupts. */ # ifndef UAVCAN_STM32_IRQ_PRIORITY_MASK -# define UAVCAN_STM32_IRQ_PRIORITY_MASK CORTEX_PRIO_MASK(CORTEX_MAX_KERNEL_PRIORITY) +# define UAVCAN_STM32_IRQ_PRIORITY_MASK CORTEX_MAX_KERNEL_PRIORITY # endif #endif From a767b77de24d31583628fedf15a8bd9f572c5cb1 Mon Sep 17 00:00:00 2001 From: Michael Spieler Date: Tue, 8 Sep 2015 18:32:49 +0200 Subject: [PATCH 10/39] Keep ChibiOS 2 compatibility, fix ISR names for ChibiOS 3. --- .../stm32/driver/src/internal.hpp | 6 ++++- .../stm32/driver/src/uc_stm32_can.cpp | 13 ++++++++++- .../stm32/driver/src/uc_stm32_clock.cpp | 12 ++++++++-- .../stm32/driver/src/uc_stm32_thread.cpp | 22 +++++++++++++++++++ 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/libuavcan_drivers/stm32/driver/src/internal.hpp b/libuavcan_drivers/stm32/driver/src/internal.hpp index 9bb7ac0be7..2bdee57a66 100644 --- a/libuavcan_drivers/stm32/driver/src/internal.hpp +++ b/libuavcan_drivers/stm32/driver/src/internal.hpp @@ -54,7 +54,11 @@ * Priority mask for timer and CAN interrupts. */ # ifndef UAVCAN_STM32_IRQ_PRIORITY_MASK -# define UAVCAN_STM32_IRQ_PRIORITY_MASK CORTEX_MAX_KERNEL_PRIORITY +# if (CH_KERNEL_MAJOR == 2) +# define UAVCAN_STM32_IRQ_PRIORITY_MASK CORTEX_PRIORITY_MASK(CORTEX_MAX_KERNEL_PRIORITY) +# else // ChibiOS 3 +# define UAVCAN_STM32_IRQ_PRIORITY_MASK CORTEX_MAX_KERNEL_PRIORITY +# endif # endif #endif diff --git a/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp b/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp index b7d4defbf8..8730ca0ed0 100644 --- a/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp +++ b/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp @@ -20,7 +20,7 @@ # error "Unknown OS" #endif -#if UAVCAN_STM32_CHIBIOS || UAVCAN_STM32_BAREMETAL +#if (UAVCAN_STM32_CHIBIOS && CH_KERNEL_MAJOR == 2) || UAVCAN_STM32_BAREMETAL # if !(defined(STM32F10X_CL) || defined(STM32F2XX) || defined(STM32F4XX)) // IRQ numbers # define CAN1_RX0_IRQn USB_LP_CAN1_RX0_IRQn @@ -33,6 +33,17 @@ # endif #endif +#if (UAVCAN_STM32_CHIBIOS && CH_KERNEL_MAJOR == 3) +#define CAN1_TX_IRQHandler STM32_CAN1_TX_HANDLER +#define CAN1_RX0_IRQHandler STM32_CAN1_RX0_HANDLER +#define CAN1_RX1_IRQHandler STM32_CAN1_RX1_HANDLER +#define CAN1_SCE_IRQHandler STM32_CAN1_SCE_HANDLER +#define CAN2_TX_IRQHandler STM32_CAN2_TX_HANDLER +#define CAN2_RX0_IRQHandler STM32_CAN2_RX0_HANDLER +#define CAN2_RX1_IRQHandler STM32_CAN2_RX1_HANDLER +#define CAN2_SCE_IRQHandler STM32_CAN2_SCE_HANDLER +#endif + #if UAVCAN_STM32_NUTTX # if !defined(STM32_IRQ_CAN1TX) && !defined(STM32_IRQ_CAN1RX0) # define STM32_IRQ_CAN1TX STM32_IRQ_USBHPCANTX diff --git a/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp b/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp index a94a543beb..d772e54423 100644 --- a/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp +++ b/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp @@ -14,12 +14,21 @@ /* * Timer instance */ -# if UAVCAN_STM32_CHIBIOS || UAVCAN_STM32_BAREMETAL +# if (UAVCAN_STM32_CHIBIOS && CH_KERNEL_MAJOR == 2) || 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 # endif +# if (UAVCAN_STM32_CHIBIOS && CH_KERNEL_MAJOR == 3) +# define TIMX UAVCAN_STM32_GLUE2(STM32_TIM, UAVCAN_STM32_TIMER_NUMBER) +# define TIMX_IRQn UAVCAN_STM32_GLUE3(STM32_TIM, UAVCAN_STM32_TIMER_NUMBER, _NUMBER) +# define TIMX_IRQHandler UAVCAN_STM32_GLUE3(STM32_TIM, UAVCAN_STM32_TIMER_NUMBER, _HANDLER) +# define TIMX_INPUT_CLOCK STM32_TIMCLK1 +# else +# define TIMX_IRQHandler UAVCAN_STM32_GLUE3(TIM, UAVCAN_STM32_TIMER_NUMBER, _IRQHandler) +# endif + # if UAVCAN_STM32_NUTTX # define TIMX UAVCAN_STM32_GLUE3(STM32_TIM, UAVCAN_STM32_TIMER_NUMBER, _BASE) # define TMR_REG(o) (TIMX + (o)) @@ -27,7 +36,6 @@ # define TIMX_IRQn UAVCAN_STM32_GLUE2(STM32_IRQ_TIM, UAVCAN_STM32_TIMER_NUMBER) # endif -# define TIMX_IRQHandler UAVCAN_STM32_GLUE3(TIM, UAVCAN_STM32_TIMER_NUMBER, _IRQHandler) # if UAVCAN_STM32_TIMER_NUMBER >= 2 && UAVCAN_STM32_TIMER_NUMBER <= 7 # define TIMX_RCC_ENR RCC->APB1ENR diff --git a/libuavcan_drivers/stm32/driver/src/uc_stm32_thread.cpp b/libuavcan_drivers/stm32/driver/src/uc_stm32_thread.cpp index c4e5710a0a..d9a4ceffe6 100644 --- a/libuavcan_drivers/stm32/driver/src/uc_stm32_thread.cpp +++ b/libuavcan_drivers/stm32/driver/src/uc_stm32_thread.cpp @@ -23,13 +23,25 @@ bool BusEvent::wait(uavcan::MonotonicDuration duration) if (msec <= 0) { +# if (CH_KERNEL_MAJOR == 2) + ret = sem_.waitTimeout(TIME_IMMEDIATE); +# else // ChibiOS 3 ret = sem_.wait(TIME_IMMEDIATE); +# endif } else { +# if (CH_KERNEL_MAJOR == 2) + ret = sem_.waitTimeout((msec > MaxDelayMSec) ? MS2ST(MaxDelayMSec) : MS2ST(msec)); +# else // ChibiOS 3 ret = sem_.wait((msec > MaxDelayMSec) ? MS2ST(MaxDelayMSec) : MS2ST(msec)); +# endif } +# if (CH_KERNEL_MAJOR == 2) + return ret == RDY_OK; +# else // ChibiOS 3 return ret == MSG_OK; +# endif } void BusEvent::signal() @@ -39,9 +51,15 @@ void BusEvent::signal() void BusEvent::signalFromInterrupt() { +# if (CH_KERNEL_MAJOR == 2) + chSysLockFromIsr(); + sem_.signalI(); + chSysUnlockFromIsr(); +# else // ChibiOS 3 chSysLockFromISR(); sem_.signalI(); chSysUnlockFromISR(); +# endif } /* @@ -49,7 +67,11 @@ void BusEvent::signalFromInterrupt() */ void Mutex::lock() { +# if (CH_KERNEL_MAJOR == 2) + chibios_rt::BaseThread::unlockMutex(); +# else // ChibiOS 3 mtx_.lock(); +# endif } void Mutex::unlock() From 24c19f7cee193eba45ce7dd25b46ca1cb85ef88b Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Mon, 14 Sep 2015 14:07:26 +0200 Subject: [PATCH 11/39] DSDL update --- dsdl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dsdl b/dsdl index 1abd370556..9804a3e697 160000 --- a/dsdl +++ b/dsdl @@ -1 +1 @@ -Subproject commit 1abd370556aea6aa93dfb0683965a8a43a26a29f +Subproject commit 9804a3e6972825586be252ce08dd899f44994b14 From 50dc08663af2d9b55eae0ccf5f07c63db0ee8907 Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Mon, 21 Sep 2015 16:46:32 +0300 Subject: [PATCH 12/39] Revert "DSDL script installation removed from the top-level CMake script" This reverts commit fc997cff8844b30734703d6eb3664d06bb01f2a7. --- CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index e61b2a17f2..23597466c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,11 @@ endif() project(uavcan) +# +# DSDL definitions +# +install(DIRECTORY dsdl DESTINATION share/uavcan) + # # libuavcan # From d2a5476af1ca817f4863a41cc84f0f9074b1150d Mon Sep 17 00:00:00 2001 From: Antoine Albertelli Date: Wed, 23 Sep 2015 14:57:14 +0200 Subject: [PATCH 13/39] Fix mutex lock typo --- libuavcan_drivers/stm32/driver/src/uc_stm32_thread.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libuavcan_drivers/stm32/driver/src/uc_stm32_thread.cpp b/libuavcan_drivers/stm32/driver/src/uc_stm32_thread.cpp index d9a4ceffe6..93b8c0a85c 100644 --- a/libuavcan_drivers/stm32/driver/src/uc_stm32_thread.cpp +++ b/libuavcan_drivers/stm32/driver/src/uc_stm32_thread.cpp @@ -67,16 +67,16 @@ void BusEvent::signalFromInterrupt() */ void Mutex::lock() { -# if (CH_KERNEL_MAJOR == 2) - chibios_rt::BaseThread::unlockMutex(); -# else // ChibiOS 3 mtx_.lock(); -# endif } void Mutex::unlock() { +# if (CH_KERNEL_MAJOR == 2) + chibios_rt::BaseThread::unlockMutex(); +# else // ChibiOS 3 mtx_.unlock(); +# endif } #elif UAVCAN_STM32_NUTTX From 0f53a76b5089ed6120d81e70309d4d81cce170ee Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Fri, 25 Sep 2015 00:02:58 +0300 Subject: [PATCH 14/39] Changed API of DynamicNodeIDClient: start() accepts UniqueID instead of HardwareVersion --- .../protocol/dynamic_node_id_client.hpp | 6 ++-- .../protocol/uc_dynamic_node_id_client.cpp | 4 +-- .../test/protocol/dynamic_node_id_client.cpp | 32 +++++++++---------- .../allocation_request_manager.cpp | 12 +++---- .../centralized/server.cpp | 8 ++--- .../distributed/server.cpp | 8 ++--- .../apps/test_dynamic_node_id_client.cpp | 2 +- 7 files changed, 37 insertions(+), 35 deletions(-) diff --git a/libuavcan/include/uavcan/protocol/dynamic_node_id_client.hpp b/libuavcan/include/uavcan/protocol/dynamic_node_id_client.hpp index a54bf4632f..f63b121e7d 100644 --- a/libuavcan/include/uavcan/protocol/dynamic_node_id_client.hpp +++ b/libuavcan/include/uavcan/protocol/dynamic_node_id_client.hpp @@ -63,6 +63,8 @@ class UAVCAN_EXPORT DynamicNodeIDClient : private TimerBase void handleAllocation(const ReceivedDataStructure& msg); public: + typedef protocol::HardwareVersion::FieldTypes::unique_id UniqueID; + DynamicNodeIDClient(INode& node) : TimerBase(node) , dnida_pub_(node) @@ -71,7 +73,7 @@ public: { } /** - * @param hardware_version Hardware version information, where unique_id must be set correctly. + * @param unique_id Unique ID of the local node. Must be the same as in the hardware version struct. * @param preferred_node_id Node ID that the application would like to take; set to broadcast (zero) if * the application doesn't have any preference (this is default). * @param transfer_priority Transfer priority, Normal by default. @@ -79,7 +81,7 @@ public: * Negative error code on failure * -ErrLogic if 1. the node is not in passive mode or 2. the client is already started */ - int start(const protocol::HardwareVersion& hardware_version, + int start(const UniqueID& unique_id, const NodeID preferred_node_id = NodeID::Broadcast, const TransferPriority transfer_priority = TransferPriority::OneHigherThanLowest); diff --git a/libuavcan/src/protocol/uc_dynamic_node_id_client.cpp b/libuavcan/src/protocol/uc_dynamic_node_id_client.cpp index b07dfb491f..2889cbadee 100644 --- a/libuavcan/src/protocol/uc_dynamic_node_id_client.cpp +++ b/libuavcan/src/protocol/uc_dynamic_node_id_client.cpp @@ -144,7 +144,7 @@ void DynamicNodeIDClient::handleAllocation(const ReceivedDataStructurefirst_part_of_unique_id); ASSERT_TRUE(uavcan::equal(dynid_sub.collector.msg->unique_id.begin(), dynid_sub.collector.msg->unique_id.end(), - hwver.unique_id.begin())); + unique_id.begin())); dynid_sub.collector.msg.reset(); // Second - rate is no lower than 0.5 Hz @@ -92,7 +92,7 @@ TEST(DynamicNodeIDClient, Basic) { uavcan::protocol::dynamic_node_id::Allocation msg; msg.unique_id.resize(BytesPerRequest); - uavcan::copy(hwver.unique_id.begin(), hwver.unique_id.begin() + BytesPerRequest, msg.unique_id.begin()); + uavcan::copy(unique_id.begin(), unique_id.begin() + BytesPerRequest, msg.unique_id.begin()); std::cout << "First-stage offer:\n" << msg << std::endl; @@ -106,7 +106,7 @@ TEST(DynamicNodeIDClient, Basic) ASSERT_FALSE(dynid_sub.collector.msg->first_part_of_unique_id); ASSERT_TRUE(uavcan::equal(dynid_sub.collector.msg->unique_id.begin(), dynid_sub.collector.msg->unique_id.end(), - hwver.unique_id.begin() + BytesPerRequest)); + unique_id.begin() + BytesPerRequest)); dynid_sub.collector.msg.reset(); } @@ -116,7 +116,7 @@ TEST(DynamicNodeIDClient, Basic) { uavcan::protocol::dynamic_node_id::Allocation msg; msg.unique_id.resize(BytesPerRequest * 2); - uavcan::copy(hwver.unique_id.begin(), hwver.unique_id.begin() + BytesPerRequest * 2, msg.unique_id.begin()); + uavcan::copy(unique_id.begin(), unique_id.begin() + BytesPerRequest * 2, msg.unique_id.begin()); std::cout << "Second-stage offer:\n" << msg << std::endl; @@ -130,7 +130,7 @@ TEST(DynamicNodeIDClient, Basic) ASSERT_FALSE(dynid_sub.collector.msg->first_part_of_unique_id); ASSERT_TRUE(uavcan::equal(dynid_sub.collector.msg->unique_id.begin(), dynid_sub.collector.msg->unique_id.end(), - hwver.unique_id.begin() + BytesPerRequest * 2)); + unique_id.begin() + BytesPerRequest * 2)); dynid_sub.collector.msg.reset(); } @@ -145,7 +145,7 @@ TEST(DynamicNodeIDClient, Basic) uavcan::protocol::dynamic_node_id::Allocation msg; msg.unique_id.resize(16); msg.node_id = 72; - uavcan::copy(hwver.unique_id.begin(), hwver.unique_id.end(), msg.unique_id.begin()); + uavcan::copy(unique_id.begin(), unique_id.end(), msg.unique_id.begin()); ASSERT_FALSE(dynid_sub.collector.msg.get()); ASSERT_LE(0, dynid_pub.broadcast(msg)); @@ -169,11 +169,11 @@ TEST(DynamicNodeIDClient, NonPassiveMode) uavcan::DefaultDataTypeRegistrator _reg1; (void)_reg1; - uavcan::protocol::HardwareVersion hwver; - for (uavcan::uint8_t i = 0; i < hwver.unique_id.size(); i++) + uavcan::protocol::HardwareVersion::FieldTypes::unique_id unique_id; + for (uavcan::uint8_t i = 0; i < unique_id.size(); i++) { - hwver.unique_id[i] = i; + unique_id[i] = i; } - ASSERT_LE(-uavcan::ErrLogic, dnidac.start(hwver)); + ASSERT_LE(-uavcan::ErrLogic, dnidac.start(unique_id)); } diff --git a/libuavcan/test/protocol/dynamic_node_id_server/allocation_request_manager.cpp b/libuavcan/test/protocol/dynamic_node_id_server/allocation_request_manager.cpp index 649162bece..07894133dc 100644 --- a/libuavcan/test/protocol/dynamic_node_id_server/allocation_request_manager.cpp +++ b/libuavcan/test/protocol/dynamic_node_id_server/allocation_request_manager.cpp @@ -78,13 +78,13 @@ TEST(dynamic_node_id_server_AllocationRequestManager, Basic) /* * Client initialization */ - uavcan::protocol::HardwareVersion hwver; - for (uavcan::uint8_t i = 0; i < hwver.unique_id.size(); i++) + uavcan::protocol::HardwareVersion::FieldTypes::unique_id unique_id; + for (uavcan::uint8_t i = 0; i < unique_id.size(); i++) { - hwver.unique_id[i] = i; + unique_id[i] = i; } const uavcan::NodeID PreferredNodeID = 42; - ASSERT_LE(0, client.start(hwver, PreferredNodeID)); + ASSERT_LE(0, client.start(unique_id, PreferredNodeID)); /* * Request manager initialization @@ -102,9 +102,9 @@ TEST(dynamic_node_id_server_AllocationRequestManager, Basic) */ nodes.spinBoth(uavcan::MonotonicDuration::fromMSec(2000)); - ASSERT_TRUE(handler.matchAndPopLastRequest(hwver.unique_id, PreferredNodeID)); + ASSERT_TRUE(handler.matchAndPopLastRequest(unique_id, PreferredNodeID)); - ASSERT_LE(0, manager.broadcastAllocationResponse(hwver.unique_id, PreferredNodeID)); + ASSERT_LE(0, manager.broadcastAllocationResponse(unique_id, PreferredNodeID)); nodes.spinBoth(uavcan::MonotonicDuration::fromMSec(100)); diff --git a/libuavcan/test/protocol/dynamic_node_id_server/centralized/server.cpp b/libuavcan/test/protocol/dynamic_node_id_server/centralized/server.cpp index 5e83b19d05..932bf61c06 100644 --- a/libuavcan/test/protocol/dynamic_node_id_server/centralized/server.cpp +++ b/libuavcan/test/protocol/dynamic_node_id_server/centralized/server.cpp @@ -49,13 +49,13 @@ TEST(dynamic_node_id_server_centralized_Server, Basic) * Client */ uavcan::DynamicNodeIDClient client(nodes.b); - uavcan::protocol::HardwareVersion hwver; - for (uavcan::uint8_t i = 0; i < hwver.unique_id.size(); i++) + uavcan::protocol::HardwareVersion::FieldTypes::unique_id unique_id; + for (uavcan::uint8_t i = 0; i < unique_id.size(); i++) { - hwver.unique_id[i] = i; + unique_id[i] = i; } const uavcan::NodeID PreferredNodeID = 42; - ASSERT_LE(0, client.start(hwver, PreferredNodeID)); + ASSERT_LE(0, client.start(unique_id, PreferredNodeID)); /* * Fire diff --git a/libuavcan/test/protocol/dynamic_node_id_server/distributed/server.cpp b/libuavcan/test/protocol/dynamic_node_id_server/distributed/server.cpp index 1cae59224c..d5cbb4b626 100644 --- a/libuavcan/test/protocol/dynamic_node_id_server/distributed/server.cpp +++ b/libuavcan/test/protocol/dynamic_node_id_server/distributed/server.cpp @@ -154,13 +154,13 @@ TEST(dynamic_node_id_server_Server, Basic) * Client */ uavcan::DynamicNodeIDClient client(nodes.b); - uavcan::protocol::HardwareVersion hwver; - for (uavcan::uint8_t i = 0; i < hwver.unique_id.size(); i++) + uavcan::protocol::HardwareVersion::FieldTypes::unique_id unique_id; + for (uavcan::uint8_t i = 0; i < unique_id.size(); i++) { - hwver.unique_id[i] = i; + unique_id[i] = i; } const uavcan::NodeID PreferredNodeID = 42; - ASSERT_LE(0, client.start(hwver, PreferredNodeID)); + ASSERT_LE(0, client.start(unique_id, PreferredNodeID)); /* * Fire diff --git a/libuavcan_drivers/linux/apps/test_dynamic_node_id_client.cpp b/libuavcan_drivers/linux/apps/test_dynamic_node_id_client.cpp index d3be73197e..c5ef2e9b73 100644 --- a/libuavcan_drivers/linux/apps/test_dynamic_node_id_client.cpp +++ b/libuavcan_drivers/linux/apps/test_dynamic_node_id_client.cpp @@ -44,7 +44,7 @@ uavcan_linux::NodePtr initNodeWithDynamicID(const std::vector& ifac */ uavcan::DynamicNodeIDClient client(*node); - ENFORCE(0 <= client.start(node->getNodeStatusProvider().getHardwareVersion(), preferred_node_id)); + ENFORCE(0 <= client.start(node->getNodeStatusProvider().getHardwareVersion().unique_id, preferred_node_id)); std::cout << "Waiting for dynamic node ID allocation..." << std::endl; From 5716f3eb3e3f16e42448d1eee262cb3622503884 Mon Sep 17 00:00:00 2001 From: Antoine Albertelli Date: Wed, 23 Sep 2015 21:35:29 +0200 Subject: [PATCH 15/39] Add compatibility defines for STM32F3 --- libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp b/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp index 8730ca0ed0..77b8378a02 100644 --- a/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp +++ b/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp @@ -58,6 +58,17 @@ static int can2_irq(const int irq, void*); } #endif +/* STM32F3's only CAN inteface does not have a number. */ +#if defined(STM32F3XX) +#define RCC_APB1ENR_CAN1EN RCC_APB1ENR_CANEN +#define RCC_APB1RSTR_CAN1RST RCC_APB1RSTR_CANRST +#define CAN1_TX_IRQn CAN_TX_IRQn +#define CAN1_RX0_IRQn CAN_RX0_IRQn +#define CAN1_RX1_IRQn CAN_RX1_IRQn +#define CAN1_SCE_IRQn CAN_SCE_IRQn +#endif + + namespace uavcan_stm32 { namespace From 335cd6622a68bd8305849662051b9c7904309d8d Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Fri, 25 Sep 2015 00:38:55 +0300 Subject: [PATCH 16/39] uavcan_linux::makeApplicationID() - instance_id made optional --- libuavcan_drivers/linux/include/uavcan_linux/system_utils.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libuavcan_drivers/linux/include/uavcan_linux/system_utils.hpp b/libuavcan_drivers/linux/include/uavcan_linux/system_utils.hpp index b4d6ce0a5c..5aaa4d5eef 100644 --- a/libuavcan_drivers/linux/include/uavcan_linux/system_utils.hpp +++ b/libuavcan_drivers/linux/include/uavcan_linux/system_utils.hpp @@ -138,11 +138,11 @@ public: * It takes the following inputs: * - Unique machine ID * - Node name string (e.g. "org.uavcan.linux_app.dynamic_node_id_server") - * - Instance ID byte, e.g. node ID + * - Instance ID byte, e.g. node ID (optional) */ std::array makeApplicationID(const MachineIDReader::MachineID& machine_id, const std::string& node_name, - const std::uint8_t instance_id) + const std::uint8_t instance_id = 0) { union HalfID { From 14cdbc05949efe94676f48137a48c443d92fa46c Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Fri, 25 Sep 2015 01:45:40 +0300 Subject: [PATCH 17/39] Added some getters to the Node<> class --- libuavcan/include/uavcan/node/node.hpp | 12 ++++++++---- .../include/uavcan/protocol/node_status_provider.hpp | 6 ++++-- libuavcan/src/protocol/uc_node_status_provider.cpp | 6 +++--- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/libuavcan/include/uavcan/node/node.hpp b/libuavcan/include/uavcan/node/node.hpp index d80c05124f..6ea59a2244 100644 --- a/libuavcan/include/uavcan/node/node.hpp +++ b/libuavcan/include/uavcan/node/node.hpp @@ -150,10 +150,11 @@ public: int start(const TransferPriority node_status_transfer_priority = TransferPriority::Default); /** - * Sets the node name, e.g. "com.example.product_name". The node name can be set only once. - * Must be executed before the node is started, otherwise the node will refuse to start up. + * Gets/sets the node name, e.g. "com.example.product_name". The node name can be set only once. + * The name must be set before the node is started, otherwise the node will refuse to start up. */ - void setName(const char* name) { proto_nsp_.setName(name); } + const NodeStatusProvider::NodeName& getName() const { return proto_nsp_.getName(); } + void setName(const NodeStatusProvider::NodeName& name) { proto_nsp_.setName(name); } /** * Node health code helpers. @@ -187,11 +188,14 @@ public: } /** - * Sets the node version information. + * Gets/sets the node version information. */ void setSoftwareVersion(const protocol::SoftwareVersion& version) { proto_nsp_.setSoftwareVersion(version); } void setHardwareVersion(const protocol::HardwareVersion& version) { proto_nsp_.setHardwareVersion(version); } + const protocol::SoftwareVersion& getSoftwareVersion() const { return proto_nsp_.getSoftwareVersion(); } + const protocol::HardwareVersion& getHardwareVersion() const { return proto_nsp_.getHardwareVersion(); } + NodeStatusProvider& getNodeStatusProvider() { return proto_nsp_; } #if !UAVCAN_TINY diff --git a/libuavcan/include/uavcan/protocol/node_status_provider.hpp b/libuavcan/include/uavcan/protocol/node_status_provider.hpp index 14f0c7cbe9..6a5bb1faaf 100644 --- a/libuavcan/include/uavcan/protocol/node_status_provider.hpp +++ b/libuavcan/include/uavcan/protocol/node_status_provider.hpp @@ -51,6 +51,8 @@ public: typedef typename StorageType::Type VendorSpecificStatusCode; + typedef typename StorageType::Type NodeName; + explicit NodeStatusProvider(INode& node) : TimerBase(node) , creation_timestamp_(node.getMonotonicTime()) @@ -119,8 +121,8 @@ public: * Can be set only once before the provider is started. * The provider will refuse to start if the node name is not set. */ - const typename protocol::GetNodeInfo::Response::FieldTypes::name& getName() const { return node_info_.name; } - void setName(const char* name); + const NodeName& getName() const { return node_info_.name; } + void setName(const NodeName& name); /** * Node version information. diff --git a/libuavcan/src/protocol/uc_node_status_provider.cpp b/libuavcan/src/protocol/uc_node_status_provider.cpp index 52dfe0290b..7f4b188939 100644 --- a/libuavcan/src/protocol/uc_node_status_provider.cpp +++ b/libuavcan/src/protocol/uc_node_status_provider.cpp @@ -124,11 +124,11 @@ void NodeStatusProvider::setVendorSpecificStatusCode(VendorSpecificStatusCode co node_info_.status.vendor_specific_status_code = code; } -void NodeStatusProvider::setName(const char* name) +void NodeStatusProvider::setName(const NodeName& name) { - if ((name != NULL) && (*name != '\0') && (node_info_.name.empty())) + if (node_info_.name.empty()) { - node_info_.name = name; // The string contents will be copied, not just pointer. + node_info_.name = name; } } From 531433a3261ff1568e824c240d0f1c6ecef73be1 Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Fri, 25 Sep 2015 01:47:39 +0300 Subject: [PATCH 18/39] Fixed makeApplicationID() (rookie mistake) --- .../linux/include/uavcan_linux/system_utils.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libuavcan_drivers/linux/include/uavcan_linux/system_utils.hpp b/libuavcan_drivers/linux/include/uavcan_linux/system_utils.hpp index 5aaa4d5eef..7e1eae9940 100644 --- a/libuavcan_drivers/linux/include/uavcan_linux/system_utils.hpp +++ b/libuavcan_drivers/linux/include/uavcan_linux/system_utils.hpp @@ -140,9 +140,9 @@ public: * - Node name string (e.g. "org.uavcan.linux_app.dynamic_node_id_server") * - Instance ID byte, e.g. node ID (optional) */ -std::array makeApplicationID(const MachineIDReader::MachineID& machine_id, - const std::string& node_name, - const std::uint8_t instance_id = 0) +inline std::array makeApplicationID(const MachineIDReader::MachineID& machine_id, + const std::string& node_name, + const std::uint8_t instance_id = 0) { union HalfID { From 62e89b33993642f24ff57c1fe3fed6384f6cd342 Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Fri, 25 Sep 2015 23:01:57 +0300 Subject: [PATCH 19/39] BasicFileServerBackend typo fix --- libuavcan_drivers/linux/apps/test_file_server.cpp | 2 +- .../uavcan_posix/basic_file_server_backend.hpp | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/libuavcan_drivers/linux/apps/test_file_server.cpp b/libuavcan_drivers/linux/apps/test_file_server.cpp index bf3c8ad0be..2f38dc12be 100644 --- a/libuavcan_drivers/linux/apps/test_file_server.cpp +++ b/libuavcan_drivers/linux/apps/test_file_server.cpp @@ -48,7 +48,7 @@ uavcan_linux::NodePtr initNode(const std::vector& ifaces, uavcan::N void runForever(const uavcan_linux::NodePtr& node) { - uavcan_posix::BasicFileSeverBackend backend(*node); + uavcan_posix::BasicFileServerBackend backend(*node); uavcan::FileServer server(*node, backend); diff --git a/libuavcan_drivers/posix/include/uavcan_posix/basic_file_server_backend.hpp b/libuavcan_drivers/posix/include/uavcan_posix/basic_file_server_backend.hpp index 54fc5de6a3..772d83c102 100644 --- a/libuavcan_drivers/posix/include/uavcan_posix/basic_file_server_backend.hpp +++ b/libuavcan_drivers/posix/include/uavcan_posix/basic_file_server_backend.hpp @@ -31,7 +31,7 @@ namespace uavcan_posix /** * This interface implements a POSIX compliant IFileServerBackend interface */ -class BasicFileSeverBackend : public uavcan::IFileServerBackend +class BasicFileServerBackend : public uavcan::IFileServerBackend { enum { FilePermissions = 438 }; ///< 0o666 @@ -433,12 +433,12 @@ protected: } public: - BasicFileSeverBackend(uavcan::INode& node) : + BasicFileServerBackend(uavcan::INode& node) : fdcache_(NULL), node_(node) { } - ~BasicFileSeverBackend() + ~BasicFileServerBackend() { if (fdcache_ != &fallback_) { @@ -447,6 +447,14 @@ public: } } }; + +#if __GNUC__ +/// Typo fix in a backwards-compatible way (only for GCC projects). Will be removed someday. +typedef BasicFileServerBackend + BasicFileSeverBackend // Missing 'r' + __attribute__((deprecated)); +#endif + } #endif // Include guard From ac04e374c602fc4ace4f2409fb7c9f0c7c0166c8 Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Fri, 25 Sep 2015 23:09:28 +0300 Subject: [PATCH 20/39] BasicFileServerBackend - fixed a missing include --- .../posix/include/uavcan_posix/basic_file_server_backend.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libuavcan_drivers/posix/include/uavcan_posix/basic_file_server_backend.hpp b/libuavcan_drivers/posix/include/uavcan_posix/basic_file_server_backend.hpp index 772d83c102..2acf7d659d 100644 --- a/libuavcan_drivers/posix/include/uavcan_posix/basic_file_server_backend.hpp +++ b/libuavcan_drivers/posix/include/uavcan_posix/basic_file_server_backend.hpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include From 0410b34d0c2c6b73fbcdc34649459d323655dd3d Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Wed, 30 Sep 2015 02:14:46 +0300 Subject: [PATCH 21/39] Coverity fix 1325169 --- libuavcan/include/uavcan/marshal/array.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libuavcan/include/uavcan/marshal/array.hpp b/libuavcan/include/uavcan/marshal/array.hpp index 3f112e4ce5..41384d8a5a 100644 --- a/libuavcan/include/uavcan/marshal/array.hpp +++ b/libuavcan/include/uavcan/marshal/array.hpp @@ -521,6 +521,7 @@ class UAVCAN_EXPORT Array : public ArrayImpl { return res_sz; } + // coverity[result_independent_of_operands] if (static_cast(sz) > MaxSize_) // False 'type-limits' warning occurs here { return -ErrInvalidMarshalData; From fbab130b2e334cf249baade03b1d75758a15a625 Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Wed, 30 Sep 2015 17:53:21 +0300 Subject: [PATCH 22/39] Removed a redundant assertion check in Linux test app --- libuavcan_drivers/linux/apps/test_multithreading.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libuavcan_drivers/linux/apps/test_multithreading.cpp b/libuavcan_drivers/linux/apps/test_multithreading.cpp index b2137a8a9e..f46d5a46cf 100644 --- a/libuavcan_drivers/linux/apps/test_multithreading.cpp +++ b/libuavcan_drivers/linux/apps/test_multithreading.cpp @@ -354,10 +354,6 @@ class VirtualCanDriver : public uavcan::ICanDriver, ifaces_[frame.iface_index]->addRxFrame(frame, flags); event_.signal(); } - else - { - assert(false); - } } /** From 04897f613d25c0cd568523f9801ffdcfc4cee79e Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Fri, 2 Oct 2015 14:02:18 +0300 Subject: [PATCH 23/39] README: Note on unit testing --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index d2159855f8..d804371028 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,8 @@ make ``` Test outputs can be found in the build directory under `libuavcan`. +Note that unit tests must be executed in real time, otherwise they may produce false warnings; +this implies that they will likely fail if ran on a virtual machine or on a highly loaded system. Contributors, please follow the [Zubax Style Guide](https://github.com/Zubax/zubax_style_guide). From 0b0e7bc6cc7fa6ec22905f3a519190e24714205d Mon Sep 17 00:00:00 2001 From: James Goppert Date: Sat, 3 Oct 2015 13:16:51 -0400 Subject: [PATCH 24/39] Added cross-compiling support. --- .gitignore | 2 +- CMakeLists.txt | 76 ++++++-- README.md | 9 + cmake/Toolchain-stm32-cortex-m4.cmake | 173 ++++++++++++++++++ libuavcan/CMakeLists.txt | 4 +- libuavcan_drivers/stm32/driver/CMakeLists.txt | 18 ++ 6 files changed, 265 insertions(+), 17 deletions(-) create mode 100644 cmake/Toolchain-stm32-cortex-m4.cmake create mode 100644 libuavcan_drivers/stm32/driver/CMakeLists.txt diff --git a/.gitignore b/.gitignore index f82baaad13..4444ace738 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ lib*.so lib*.so.* *.a -build +build*/ .dep __pycache__ *.pyc diff --git a/CMakeLists.txt b/CMakeLists.txt index 23597466c7..70daa80a4f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,29 +4,75 @@ cmake_minimum_required(VERSION 2.8) -if(DEFINED CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "Debug Release RelWithDebInfo MinSizeRel") -else() - set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Debug Release RelWithDebInfo MinSizeRel") -endif() +project(uavcan C CXX) -project(uavcan) +#============================================================================= +# build options +# +# options are listed in a table format below +set(opts + # name: type: default value: string options list : description + "CMAKE_BUILD_TYPE:STRING:RelWithDebInfo:Debug Release RelWithDebInfo MinSizeRel:Build type." + "CMAKE_CXX_FLAGS:STRING:::C++ flags." + "CMAKE_C_FLAGS:STRING:::C flags." + "UAVCAN_USE_CPP03:BOOL:OFF::Use cpp03 standard." + "UAVCAN_PLATFORM:STRING:generic:generic linux stm32:Platform." + ) +foreach(_opt ${opts}) + # arguments are : delimited + string(REPLACE ":" ";" _opt ${_opt}) + list(GET _opt 0 _name) + list(GET _opt 1 _type) + list(GET _opt 2 _default) + list(GET _opt 3 _options) + list(GET _opt 4 _descr) + # options are space delimited + string(REPLACE " " ";" _options "${_options}") + # if a default has not already been defined, use default from table + if(NOT DEFINED DEFAULT_${_name}) + set(DEFAULT_${_name} ${_default}) + endif() + # option has not been set already or it is empty, set it with the default + if(NOT DEFINED ${_name} OR ${_name} STREQUAL "") + set(${_name} ${DEFAULT_${_name}}) + endif() + # create a cache from the variable and force it to set + message(STATUS "${_name}\t: ${${_name}} : ${_descr}") + set("${_name}" "${${_name}}" CACHE "${_type}" "${_descr}" FORCE) + # if an options list is provided for the cache, set it + if("${_type}" STREQUAL "STRING" AND NOT "${_options}" STREQUAL "") + set_property(CACHE ${_name} PROPERTY STRINGS ${_options}) + endif() +endforeach() +#============================================================================= +# set flags +# +include_directories( + ./libuavcan/include/ + ./libuavcan/include/dsdlc_generated + ) + +#============================================================================= +# install # # DSDL definitions -# install(DIRECTORY dsdl DESTINATION share/uavcan) +#============================================================================= +# subdirectories # -# libuavcan -# +# library add_subdirectory(libuavcan) -# -# libuavcan drivers -# -if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") +# drivers +add_subdirectory(libuavcan_drivers/posix) + +if (${UAVCAN_PLATFORM} STREQUAL "linux") message(STATUS "Adding Linux support library") - add_subdirectory(libuavcan_drivers/posix) add_subdirectory(libuavcan_drivers/linux) -endif () +elseif(${UAVCAN_PLATFORM} STREQUAL "stm32") + add_subdirectory(libuavcan_drivers/stm32/driver) +endif() + +# vim: set et ft=cmake fenc=utf-8 ff=unix sts=4 sw=4 ts=4 : diff --git a/README.md b/README.md index d804371028..4bf26cbeea 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,15 @@ make -j8 sudo make install ``` +For cross-compiling the procedure is similar. + +```bash +mkdir build +cd build +cmake .. -D CMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-stm32-cortex-m4.cmake +make -j8 +``` + The following components will be installed into the system: * Libuavcan headers and the static library diff --git a/cmake/Toolchain-stm32-cortex-m4.cmake b/cmake/Toolchain-stm32-cortex-m4.cmake new file mode 100644 index 0000000000..403c50cd11 --- /dev/null +++ b/cmake/Toolchain-stm32-cortex-m4.cmake @@ -0,0 +1,173 @@ +# defines: +# +# NM +# OBJCOPY +# LD +# CXX_COMPILER +# C_COMPILER +# CMAKE_SYSTEM_NAME +# CMAKE_SYSTEM_VERSION +# GENROMFS +# LINKER_FLAGS +# CMAKE_EXE_LINKER_FLAGS +# CMAKE_FIND_ROOT_PATH +# CMAKE_FIND_ROOT_PATH_MODE_PROGRAM +# CMAKE_FIND_ROOT_PATH_MODE_LIBRARY +# CMAKE_FIND_ROOT_PATH_MODE_INCLUDE + +include(CMakeForceCompiler) + +# this one is important +set(CMAKE_SYSTEM_NAME Generic) + +#this one not so much +set(CMAKE_SYSTEM_VERSION 1) + +# specify the cross compiler +find_program(C_COMPILER arm-none-eabi-gcc) +if(NOT C_COMPILER) + message(FATAL_ERROR "could not find arm-none-eabi-gcc compiler") +endif() +cmake_force_c_compiler(${C_COMPILER} GNU) + +find_program(CXX_COMPILER arm-none-eabi-g++) +if(NOT CXX_COMPILER) + message(FATAL_ERROR "could not find arm-none-eabi-g++ compiler") +endif() +cmake_force_cxx_compiler(${CXX_COMPILER} GNU) + +set(LINKER_FLAGS "-Wl,-gc-sections") +set(CMAKE_EXE_LINKER_FLAGS ${LINKER_FLAGS}) + +# where is the target environment +set(CMAKE_FIND_ROOT_PATH get_file_component(${C_COMPILER} PATH)) + +# search for programs in the build host directories +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +# for libraries and headers in the target directories +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +set(warnings + -Wall + -Wno-sign-compare + -Wextra + #-Wshadow # very verbose due to eigen + -Wfloat-equal + -Wpointer-arith + -Wmissing-declarations + -Wpacked + -Wno-unused-parameter + -Werror=format-security + -Werror=array-bounds + -Wfatal-errors + -Werror=unused-variable + -Werror=reorder + -Werror=uninitialized + -Werror=init-self + #-Wcast-qual - generates spurious noreturn attribute warnings, + # try again later + #-Wconversion - would be nice, but too many "risky-but-safe" + # conversions in the code + #-Wcast-align - would help catch bad casts in some cases, + # but generates too many false positives + ) + +set(max_optimization -Os) + +set(optimization_flags + -fno-strict-aliasing + -fomit-frame-pointer + -funsafe-math-optimizations + -ffunction-sections + -fdata-sections + ) + +set(c_warnings + -Wbad-function-cast + -Wstrict-prototypes + -Wmissing-prototypes + -Wnested-externs + ) + +set(c_compile_flags + -g + -fno-common + -nodefaultlibs + -nostdlib + -DCONFIG_WCHAR_BUILTIN + ) + +set(cxx_warnings + -Wno-missing-field-initializers + ) +set(cxx_compile_flags + -g + -fno-exceptions + -fno-rtti + -fno-threadsafe-statics + -DCONFIG_WCHAR_BUILTIN + -nodefaultlibs + -nostdlib + ) + +set(cpu_flags + -mcpu=cortex-m4 + -mthumb + -march=armv7e-m + -mfpu=fpv4-sp-d16 + -mfloat-abi=hard + ) + +find_path(NUTTX_EXPORT_DIR libs/libnuttx.a + PATHS + $ENV{HOME}/git/px4/Firmware/build_px4fmu-v2_default/px4fmu-v2/NuttX/nuttx-export + NO_DEFAULT_PATH + NO_CMAKE_FIND_ROOT_PATH + ) +if(NOT NUTTX_EXPORT_DIR) + message(FATAL_ERROR "failed to find NUTTX_EXPORT_DIR, please set") +else() + message(STATUS "nuttx export: ${NUTTX_EXPORT_DIR}") +endif() + +set(uavcan_extra_flags + -DUAVCAN_NO_ASSERTIONS + -DUAVCAN_STM32_NUM_IFACES=2 + -DUAVCAN_USE_EXTERNAL_SNPRINT + -DUAVCAN_MEM_POOL_BLOCK_SIZE=48 + -DUAVCAN_MAX_NETWORK_SIZE_HINT=16 + -DUAVCAN_STM32_TIMER_NUMBER=5 + -DUAVCAN_STM32_NUTTX=1 + -DUAVCAN_CPP_VERSION=UAVCAN_CPP03 + -I${NUTTX_EXPORT_DIR}/include + -I${NUTTX_EXPORT_DIR}/include/cxx + -I${NUTTX_EXPORT_DIR}/arch/chip + -I${NUTTX_EXPORT_DIR}/arch/common + ) + +set(added_c_flags + ${cpu_flags} + ${c_compile_flags} + ${warnings} + ${c_warnings} + ${max_optimization} + ${optimization_flags} + ${uavcan_extra_flags} + ) + +set(added_cxx_flags + ${cpu_flags} + ${cxx_compile_flags} + ${warnings} + ${cxx_warnings} + ${max_optimization} + ${optimization_flags} + ${uavcan_extra_flags} + ) + +string (REPLACE ";" " " DEFAULT_CMAKE_CXX_FLAGS "${added_cxx_flags}") +string (REPLACE ";" " " DEFAULT_CMAKE_C_FLAGS "${added_c_flags}") +set(DEFAULT_CMAKE_BUILD_TYPE "RelWithDebInfo") +set(DEFAULT_UAVCAN_PLATFORM "stm32") +set(DEFAULT_UAVCAN_USE_CPP03 ON) diff --git a/libuavcan/CMakeLists.txt b/libuavcan/CMakeLists.txt index 5058e65b55..0298b4b7ea 100644 --- a/libuavcan/CMakeLists.txt +++ b/libuavcan/CMakeLists.txt @@ -43,7 +43,7 @@ include_directories(${DSDLC_OUTPUT}) # if (COMPILER_IS_GCC_COMPATIBLE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wundef") - if (USE_CPP03) + if (UAVCAN_USE_CPP03) message(STATUS "Using C++03") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++03 -Wno-variadic-macros -Wno-long-long") else () @@ -128,3 +128,5 @@ if (DEBUG_BUILD) else () message(STATUS "Release build type: " ${CMAKE_BUILD_TYPE}) endif () + +# vim: set et ft=cmake fenc=utf-8 ff=unix sts=4 sw=4 ts=4 : diff --git a/libuavcan_drivers/stm32/driver/CMakeLists.txt b/libuavcan_drivers/stm32/driver/CMakeLists.txt new file mode 100644 index 0000000000..b89746c34b --- /dev/null +++ b/libuavcan_drivers/stm32/driver/CMakeLists.txt @@ -0,0 +1,18 @@ +include_directories( + ./src + ./include + ) + +add_library(uavcan_stm32_driver STATIC + ./src/uc_stm32_can.cpp + ./src/uc_stm32_clock.cpp + ./src/uc_stm32_thread.cpp + ) + +add_dependencies(uavcan_stm32_driver uavcan) + +install(DIRECTORY include/uavcan_stm32 DESTINATION include) +install(TARGETS uavcan_stm32_driver DESTINATION lib) + +# vim: set et ft=cmake fenc=utf-8 ff=unix sts=4 sw=4 ts=4 :) + From 86c3397b1b423eeed86f21c8b08c8acfbd5add96 Mon Sep 17 00:00:00 2001 From: James Goppert Date: Mon, 5 Oct 2015 17:15:43 -0400 Subject: [PATCH 25/39] Requested changes. --- cmake/Toolchain-stm32-cortex-m4.cmake | 173 ------------------ libuavcan_drivers/stm32/driver/CMakeLists.txt | 1 - 2 files changed, 174 deletions(-) delete mode 100644 cmake/Toolchain-stm32-cortex-m4.cmake diff --git a/cmake/Toolchain-stm32-cortex-m4.cmake b/cmake/Toolchain-stm32-cortex-m4.cmake deleted file mode 100644 index 403c50cd11..0000000000 --- a/cmake/Toolchain-stm32-cortex-m4.cmake +++ /dev/null @@ -1,173 +0,0 @@ -# defines: -# -# NM -# OBJCOPY -# LD -# CXX_COMPILER -# C_COMPILER -# CMAKE_SYSTEM_NAME -# CMAKE_SYSTEM_VERSION -# GENROMFS -# LINKER_FLAGS -# CMAKE_EXE_LINKER_FLAGS -# CMAKE_FIND_ROOT_PATH -# CMAKE_FIND_ROOT_PATH_MODE_PROGRAM -# CMAKE_FIND_ROOT_PATH_MODE_LIBRARY -# CMAKE_FIND_ROOT_PATH_MODE_INCLUDE - -include(CMakeForceCompiler) - -# this one is important -set(CMAKE_SYSTEM_NAME Generic) - -#this one not so much -set(CMAKE_SYSTEM_VERSION 1) - -# specify the cross compiler -find_program(C_COMPILER arm-none-eabi-gcc) -if(NOT C_COMPILER) - message(FATAL_ERROR "could not find arm-none-eabi-gcc compiler") -endif() -cmake_force_c_compiler(${C_COMPILER} GNU) - -find_program(CXX_COMPILER arm-none-eabi-g++) -if(NOT CXX_COMPILER) - message(FATAL_ERROR "could not find arm-none-eabi-g++ compiler") -endif() -cmake_force_cxx_compiler(${CXX_COMPILER} GNU) - -set(LINKER_FLAGS "-Wl,-gc-sections") -set(CMAKE_EXE_LINKER_FLAGS ${LINKER_FLAGS}) - -# where is the target environment -set(CMAKE_FIND_ROOT_PATH get_file_component(${C_COMPILER} PATH)) - -# search for programs in the build host directories -set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) -# for libraries and headers in the target directories -set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) - -set(warnings - -Wall - -Wno-sign-compare - -Wextra - #-Wshadow # very verbose due to eigen - -Wfloat-equal - -Wpointer-arith - -Wmissing-declarations - -Wpacked - -Wno-unused-parameter - -Werror=format-security - -Werror=array-bounds - -Wfatal-errors - -Werror=unused-variable - -Werror=reorder - -Werror=uninitialized - -Werror=init-self - #-Wcast-qual - generates spurious noreturn attribute warnings, - # try again later - #-Wconversion - would be nice, but too many "risky-but-safe" - # conversions in the code - #-Wcast-align - would help catch bad casts in some cases, - # but generates too many false positives - ) - -set(max_optimization -Os) - -set(optimization_flags - -fno-strict-aliasing - -fomit-frame-pointer - -funsafe-math-optimizations - -ffunction-sections - -fdata-sections - ) - -set(c_warnings - -Wbad-function-cast - -Wstrict-prototypes - -Wmissing-prototypes - -Wnested-externs - ) - -set(c_compile_flags - -g - -fno-common - -nodefaultlibs - -nostdlib - -DCONFIG_WCHAR_BUILTIN - ) - -set(cxx_warnings - -Wno-missing-field-initializers - ) -set(cxx_compile_flags - -g - -fno-exceptions - -fno-rtti - -fno-threadsafe-statics - -DCONFIG_WCHAR_BUILTIN - -nodefaultlibs - -nostdlib - ) - -set(cpu_flags - -mcpu=cortex-m4 - -mthumb - -march=armv7e-m - -mfpu=fpv4-sp-d16 - -mfloat-abi=hard - ) - -find_path(NUTTX_EXPORT_DIR libs/libnuttx.a - PATHS - $ENV{HOME}/git/px4/Firmware/build_px4fmu-v2_default/px4fmu-v2/NuttX/nuttx-export - NO_DEFAULT_PATH - NO_CMAKE_FIND_ROOT_PATH - ) -if(NOT NUTTX_EXPORT_DIR) - message(FATAL_ERROR "failed to find NUTTX_EXPORT_DIR, please set") -else() - message(STATUS "nuttx export: ${NUTTX_EXPORT_DIR}") -endif() - -set(uavcan_extra_flags - -DUAVCAN_NO_ASSERTIONS - -DUAVCAN_STM32_NUM_IFACES=2 - -DUAVCAN_USE_EXTERNAL_SNPRINT - -DUAVCAN_MEM_POOL_BLOCK_SIZE=48 - -DUAVCAN_MAX_NETWORK_SIZE_HINT=16 - -DUAVCAN_STM32_TIMER_NUMBER=5 - -DUAVCAN_STM32_NUTTX=1 - -DUAVCAN_CPP_VERSION=UAVCAN_CPP03 - -I${NUTTX_EXPORT_DIR}/include - -I${NUTTX_EXPORT_DIR}/include/cxx - -I${NUTTX_EXPORT_DIR}/arch/chip - -I${NUTTX_EXPORT_DIR}/arch/common - ) - -set(added_c_flags - ${cpu_flags} - ${c_compile_flags} - ${warnings} - ${c_warnings} - ${max_optimization} - ${optimization_flags} - ${uavcan_extra_flags} - ) - -set(added_cxx_flags - ${cpu_flags} - ${cxx_compile_flags} - ${warnings} - ${cxx_warnings} - ${max_optimization} - ${optimization_flags} - ${uavcan_extra_flags} - ) - -string (REPLACE ";" " " DEFAULT_CMAKE_CXX_FLAGS "${added_cxx_flags}") -string (REPLACE ";" " " DEFAULT_CMAKE_C_FLAGS "${added_c_flags}") -set(DEFAULT_CMAKE_BUILD_TYPE "RelWithDebInfo") -set(DEFAULT_UAVCAN_PLATFORM "stm32") -set(DEFAULT_UAVCAN_USE_CPP03 ON) diff --git a/libuavcan_drivers/stm32/driver/CMakeLists.txt b/libuavcan_drivers/stm32/driver/CMakeLists.txt index b89746c34b..ce8ef00234 100644 --- a/libuavcan_drivers/stm32/driver/CMakeLists.txt +++ b/libuavcan_drivers/stm32/driver/CMakeLists.txt @@ -1,5 +1,4 @@ include_directories( - ./src ./include ) From 562d308712cc1785d8d425754520ddaa34766463 Mon Sep 17 00:00:00 2001 From: James Goppert Date: Mon, 5 Oct 2015 17:56:48 -0400 Subject: [PATCH 26/39] Requested changes. --- CMakeLists.txt | 9 +++++++-- libuavcan/CMakeLists.txt | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 70daa80a4f..96fde08c77 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,11 @@ project(uavcan C CXX) #============================================================================= # build options # + +if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + set(DEFAULT_UAVCAN_PLATFORM "linux") +endif() + # options are listed in a table format below set(opts # name: type: default value: string options list : description @@ -66,12 +71,12 @@ install(DIRECTORY dsdl DESTINATION share/uavcan) add_subdirectory(libuavcan) # drivers -add_subdirectory(libuavcan_drivers/posix) - if (${UAVCAN_PLATFORM} STREQUAL "linux") message(STATUS "Adding Linux support library") + add_subdirectory(libuavcan_drivers/posix) add_subdirectory(libuavcan_drivers/linux) elseif(${UAVCAN_PLATFORM} STREQUAL "stm32") + add_subdirectory(libuavcan_drivers/posix) add_subdirectory(libuavcan_drivers/stm32/driver) endif() diff --git a/libuavcan/CMakeLists.txt b/libuavcan/CMakeLists.txt index 0298b4b7ea..7f16ab35e0 100644 --- a/libuavcan/CMakeLists.txt +++ b/libuavcan/CMakeLists.txt @@ -47,7 +47,7 @@ if (COMPILER_IS_GCC_COMPATIBLE) message(STATUS "Using C++03") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++03 -Wno-variadic-macros -Wno-long-long") else () - message(STATUS "Using C++11 (pass USE_CPP03=1 to override)") + message(STATUS "Using C++11 (pass UAVCAN_USE_CPP03=1 to override)") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") endif () endif () From 9fb9053b012c441ff3903c29ae79570be74de841 Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Tue, 6 Oct 2015 18:04:07 +0300 Subject: [PATCH 27/39] Minor corrections to @jgoppert's CMakeLists.txt --- CMakeLists.txt | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 96fde08c77..7ee028830e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,10 +6,9 @@ cmake_minimum_required(VERSION 2.8) project(uavcan C CXX) -#============================================================================= -# build options # - +# Build options +# if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") set(DEFAULT_UAVCAN_PLATFORM "linux") endif() @@ -20,7 +19,7 @@ set(opts "CMAKE_BUILD_TYPE:STRING:RelWithDebInfo:Debug Release RelWithDebInfo MinSizeRel:Build type." "CMAKE_CXX_FLAGS:STRING:::C++ flags." "CMAKE_C_FLAGS:STRING:::C flags." - "UAVCAN_USE_CPP03:BOOL:OFF::Use cpp03 standard." + "UAVCAN_USE_CPP03:BOOL:OFF::Use C++03 standard." "UAVCAN_PLATFORM:STRING:generic:generic linux stm32:Platform." ) foreach(_opt ${opts}) @@ -50,32 +49,33 @@ foreach(_opt ${opts}) endif() endforeach() -#============================================================================= -# set flags +# +# Set flags # include_directories( ./libuavcan/include/ ./libuavcan/include/dsdlc_generated ) -#============================================================================= -# install +# +# Install # # DSDL definitions install(DIRECTORY dsdl DESTINATION share/uavcan) -#============================================================================= -# subdirectories +# +# Subdirectories # # library add_subdirectory(libuavcan) # drivers if (${UAVCAN_PLATFORM} STREQUAL "linux") - message(STATUS "Adding Linux support library") + message(STATUS "Adding Linux platform driver") add_subdirectory(libuavcan_drivers/posix) add_subdirectory(libuavcan_drivers/linux) elseif(${UAVCAN_PLATFORM} STREQUAL "stm32") + message(STATUS "Adding STM32 platform driver") add_subdirectory(libuavcan_drivers/posix) add_subdirectory(libuavcan_drivers/stm32/driver) endif() From 70232725e6bb188dbb52562cac0ccac9d49b4764 Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Fri, 9 Oct 2015 01:45:23 +0300 Subject: [PATCH 28/39] STM32 example refactored --- .../stm32/test_stm32f107/Makefile | 14 ++- .../stm32/test_stm32f107/src/board/board.cpp | 84 ++++++++++++++++ .../stm32/test_stm32f107/src/board/board.hpp | 25 +++++ .../stm32/test_stm32f107/src/main.cpp | 98 ++++++++++--------- .../stm32/test_stm32f107/src/sys/board.c | 27 ----- 5 files changed, 169 insertions(+), 79 deletions(-) create mode 100644 libuavcan_drivers/stm32/test_stm32f107/src/board/board.cpp create mode 100644 libuavcan_drivers/stm32/test_stm32f107/src/board/board.hpp delete mode 100644 libuavcan_drivers/stm32/test_stm32f107/src/sys/board.c diff --git a/libuavcan_drivers/stm32/test_stm32f107/Makefile b/libuavcan_drivers/stm32/test_stm32f107/Makefile index c2d8ab678b..dd7fb36a2f 100644 --- a/libuavcan_drivers/stm32/test_stm32f107/Makefile +++ b/libuavcan_drivers/stm32/test_stm32f107/Makefile @@ -10,8 +10,9 @@ PROJECT = uavcan_test_stm32f107 MAIN ?= main.cpp -CPPSRC = src/$(MAIN) \ - src/dummy.cpp +CPPSRC = src/$(MAIN) \ + src/dummy.cpp \ + src/board/board.cpp # # UAVCAN library @@ -37,10 +38,15 @@ $(info $(shell $(LIBUAVCAN_DSDLC) $(UAVCAN_DSDL_DIR))) UINCDIR += dsdlc_generated # -# Platform +# Git commit hash # -CSRC += src/sys/board.c +GIT_HASH := $(shell git rev-parse --short HEAD) +UDEFS += -DGIT_HASH=0x$(GIT_HASH) + +# +# Platform +# UINCDIR += src/sys diff --git a/libuavcan_drivers/stm32/test_stm32f107/src/board/board.cpp b/libuavcan_drivers/stm32/test_stm32f107/src/board/board.cpp new file mode 100644 index 0000000000..28779986db --- /dev/null +++ b/libuavcan_drivers/stm32/test_stm32f107/src/board/board.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2015 Pavel Kirienko + */ + +#include "board.hpp" +#include +#include +#include +#include +#include +#include + +/** + * GPIO config for ChibiOS PAL driver + */ +const PALConfig pal_default_config = +{ + { VAL_GPIOAODR, VAL_GPIOACRL, VAL_GPIOACRH }, + { VAL_GPIOBODR, VAL_GPIOBCRL, VAL_GPIOBCRH }, + { VAL_GPIOCODR, VAL_GPIOCCRL, VAL_GPIOCCRH }, + { VAL_GPIODODR, VAL_GPIODCRL, VAL_GPIODCRH }, + { VAL_GPIOEODR, VAL_GPIOECRL, VAL_GPIOECRH } +}; + +namespace board +{ + +void init() +{ + halInit(); + chibios_rt::System::init(); + sdStart(&STDOUT_SD, NULL); +} + +__attribute__((noreturn)) +void die(int error) +{ + lowsyslog("Fatal error %i\n", error); + while (1) + { + setLed(false); + ::sleep(1); + setLed(true); + ::sleep(1); + } +} + +void setLed(bool state) +{ + palWritePad(GPIO_PORT_LED, GPIO_PIN_LED, state); +} + +void restart() +{ + NVIC_SystemReset(); +} + +void readUniqueID(std::uint8_t bytes[UniqueIDSize]) +{ + std::memcpy(bytes, reinterpret_cast(0x1FFFF7E8), UniqueIDSize); +} + +} + +/* + * Early init from ChibiOS + */ +extern "C" +{ + +void __early_init(void) +{ + stm32_clock_init(); +} + +void boardInit(void) +{ + AFIO->MAPR |= + AFIO_MAPR_CAN_REMAP_REMAP3 | + AFIO_MAPR_CAN2_REMAP | + AFIO_MAPR_USART2_REMAP; +} + +} diff --git a/libuavcan_drivers/stm32/test_stm32f107/src/board/board.hpp b/libuavcan_drivers/stm32/test_stm32f107/src/board/board.hpp new file mode 100644 index 0000000000..8b69596455 --- /dev/null +++ b/libuavcan_drivers/stm32/test_stm32f107/src/board/board.hpp @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2015 Pavel Kirienko + */ + +#pragma once + +#include + +namespace board +{ + +void init(); + +__attribute__((noreturn)) +void die(int error); + +void setLed(bool state); + +void restart(); + +constexpr unsigned UniqueIDSize = 12; + +void readUniqueID(std::uint8_t bytes[UniqueIDSize]); + +} diff --git a/libuavcan_drivers/stm32/test_stm32f107/src/main.cpp b/libuavcan_drivers/stm32/test_stm32f107/src/main.cpp index a5481c94a1..c8c2c113e6 100644 --- a/libuavcan_drivers/stm32/test_stm32f107/src/main.cpp +++ b/libuavcan_drivers/stm32/test_stm32f107/src/main.cpp @@ -6,6 +6,7 @@ #include #include #include +#include "board/board.hpp" namespace app { @@ -27,16 +28,9 @@ Node& getNode() return *node_; } -void ledSet(bool state) -{ - palWritePad(GPIO_PORT_LED, GPIO_PIN_LED, state); -} - void init() { - halInit(); - chibios_rt::System::init(); - sdStart(&STDOUT_SD, NULL); + board::init(); int res = 0; do @@ -54,37 +48,58 @@ void init() while (res < 0); } -#if __GNUC__ -__attribute__((noreturn)) -#endif -void die(int status) -{ - lowsyslog("Initialization failure %i\n", status); - while (1) - { - ledSet(false); - sleep(1); - ledSet(true); - sleep(1); - } -} - class : public chibios_rt::BaseStaticThread<8192> { + void configureNodeInfo() + { + Node& node = app::getNode(); + + node.setNodeID(64); + node.setName("org.uavcan.stm32_test_stm32f107"); + + /* + * Software version + * TODO: Fill other fields too + */ + uavcan::protocol::SoftwareVersion swver; + + swver.vcs_commit = GIT_HASH; + swver.optional_field_flags = swver.OPTIONAL_FIELD_FLAG_VCS_COMMIT; + + node.setSoftwareVersion(swver); + + lowsyslog("Git commit hash: 0x%08x\n", GIT_HASH); + + /* + * Hardware version + * TODO: Fill other fields too + */ + uavcan::protocol::HardwareVersion hwver; + + std::uint8_t uid[board::UniqueIDSize] = {}; + board::readUniqueID(uid); + std::copy(std::begin(uid), std::end(uid), std::begin(hwver.unique_id)); + + node.setHardwareVersion(hwver); + + lowsyslog("UDID:"); + for (auto b : hwver.unique_id) + { + lowsyslog(" %02x", unsigned(b)); + } + lowsyslog("\n"); + } + public: msg_t main() { /* * Setting up the node parameters */ + configureNodeInfo(); + Node& node = app::getNode(); - node.setNodeID(64); - node.setName("org.uavcan.stm32_test_stm32f107"); - - // TODO: fill software version info (version number, VCS commit hash, ...) - // TODO: fill hardware version info (version number, unique ID) - /* * Initializing the UAVCAN node - this may take a while */ @@ -93,25 +108,10 @@ public: // Calling start() multiple times is OK - only the first successfull call will be effective int res = node.start(); -#if !UAVCAN_TINY - uavcan::NetworkCompatibilityCheckResult ncc_result; - if (res >= 0) - { - lowsyslog("Checking network compatibility...\n"); - res = node.checkNetworkCompatibility(ncc_result); - } -#endif - if (res < 0) { lowsyslog("Node initialization failure: %i, will try agin soon\n", res); } -#if !UAVCAN_TINY - else if (!ncc_result.isOk()) - { - lowsyslog("Network conflict with %u, will try again soon\n", ncc_result.conflicting_node.get()); - } -#endif else { break; @@ -127,7 +127,7 @@ public: const int res = time_sync_slave.start(); if (res < 0) { - die(res); + board::die(res); } } @@ -146,8 +146,10 @@ public: lowsyslog("Time sync master: %u\n", unsigned(time_sync_slave.getMasterNodeID().get())); - lowsyslog("Memory usage: used=%u free=%u\n", - node.getAllocator().getNumUsedBlocks(), node.getAllocator().getNumFreeBlocks()); + lowsyslog("Memory usage: free=%u used=%u worst=%u\n", + node.getAllocator().getNumFreeBlocks(), + node.getAllocator().getNumUsedBlocks(), + node.getAllocator().getPeakNumUsedBlocks()); lowsyslog("CAN errors: %lu %lu\n", static_cast(can.driver.getIface(0)->getErrorCount()), @@ -179,7 +181,7 @@ int main() { for (int i = 0; i < 200; i++) { - app::ledSet(app::can.driver.hadActivity()); + board::setLed(app::can.driver.hadActivity()); ::usleep(25000); } diff --git a/libuavcan_drivers/stm32/test_stm32f107/src/sys/board.c b/libuavcan_drivers/stm32/test_stm32f107/src/sys/board.c deleted file mode 100644 index 9243aebdd1..0000000000 --- a/libuavcan_drivers/stm32/test_stm32f107/src/sys/board.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2014 Pavel Kirienko - */ - -#include -#include - -const PALConfig pal_default_config = { - { VAL_GPIOAODR, VAL_GPIOACRL, VAL_GPIOACRH }, - { VAL_GPIOBODR, VAL_GPIOBCRL, VAL_GPIOBCRH }, - { VAL_GPIOCODR, VAL_GPIOCCRL, VAL_GPIOCCRH }, - { VAL_GPIODODR, VAL_GPIODCRL, VAL_GPIODCRH }, - { VAL_GPIOEODR, VAL_GPIOECRL, VAL_GPIOECRH } -}; - -void __early_init(void) -{ - stm32_clock_init(); -} - -void boardInit(void) -{ - AFIO->MAPR |= - AFIO_MAPR_CAN_REMAP_REMAP3 | - AFIO_MAPR_CAN2_REMAP | - AFIO_MAPR_USART2_REMAP; -} From 47da7f17df3f19461d582ce23047d445a96f571e Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Fri, 9 Oct 2015 01:51:37 +0300 Subject: [PATCH 29/39] STM32 example: cleaner node instantiation --- .../stm32/test_stm32f107/src/main.cpp | 39 +++++++------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/libuavcan_drivers/stm32/test_stm32f107/src/main.cpp b/libuavcan_drivers/stm32/test_stm32f107/src/main.cpp index c8c2c113e6..88dcf5f1b9 100644 --- a/libuavcan_drivers/stm32/test_stm32f107/src/main.cpp +++ b/libuavcan_drivers/stm32/test_stm32f107/src/main.cpp @@ -15,17 +15,12 @@ namespace uavcan_stm32::CanInitHelper<128> can; -typedef uavcan::Node<16384> Node; +constexpr unsigned NodePoolSize = 16384; -uavcan::LazyConstructor node_; - -Node& getNode() +uavcan::Node& getNode() { - if (!node_.isConstructed()) - { - node_.construct(can.driver, uavcan_stm32::SystemClock::instance()); - } - return *node_; + static uavcan::Node node(can.driver, uavcan_stm32::SystemClock::instance()); + return node; } void init() @@ -52,10 +47,8 @@ class : public chibios_rt::BaseStaticThread<8192> { void configureNodeInfo() { - Node& node = app::getNode(); - - node.setNodeID(64); - node.setName("org.uavcan.stm32_test_stm32f107"); + getNode().setNodeID(64); + getNode().setName("org.uavcan.stm32_test_stm32f107"); /* * Software version @@ -66,7 +59,7 @@ class : public chibios_rt::BaseStaticThread<8192> swver.vcs_commit = GIT_HASH; swver.optional_field_flags = swver.OPTIONAL_FIELD_FLAG_VCS_COMMIT; - node.setSoftwareVersion(swver); + getNode().setSoftwareVersion(swver); lowsyslog("Git commit hash: 0x%08x\n", GIT_HASH); @@ -80,7 +73,7 @@ class : public chibios_rt::BaseStaticThread<8192> board::readUniqueID(uid); std::copy(std::begin(uid), std::end(uid), std::begin(hwver.unique_id)); - node.setHardwareVersion(hwver); + getNode().setHardwareVersion(hwver); lowsyslog("UDID:"); for (auto b : hwver.unique_id) @@ -98,15 +91,13 @@ public: */ configureNodeInfo(); - Node& node = app::getNode(); - /* * Initializing the UAVCAN node - this may take a while */ while (true) { // Calling start() multiple times is OK - only the first successfull call will be effective - int res = node.start(); + int res = getNode().start(); if (res < 0) { @@ -122,7 +113,7 @@ public: /* * Time synchronizer */ - static uavcan::GlobalTimeSyncSlave time_sync_slave(node); + static uavcan::GlobalTimeSyncSlave time_sync_slave(getNode()); { const int res = time_sync_slave.start(); if (res < 0) @@ -135,10 +126,10 @@ public: * Main loop */ lowsyslog("UAVCAN node started\n"); - node.setModeOperational(); + getNode().setModeOperational(); while (true) { - const int spin_res = node.spin(uavcan::MonotonicDuration::fromMSec(5000)); + const int spin_res = getNode().spin(uavcan::MonotonicDuration::fromMSec(5000)); if (spin_res < 0) { lowsyslog("Spin failure: %i\n", spin_res); @@ -147,9 +138,9 @@ public: lowsyslog("Time sync master: %u\n", unsigned(time_sync_slave.getMasterNodeID().get())); lowsyslog("Memory usage: free=%u used=%u worst=%u\n", - node.getAllocator().getNumFreeBlocks(), - node.getAllocator().getNumUsedBlocks(), - node.getAllocator().getPeakNumUsedBlocks()); + getNode().getAllocator().getNumFreeBlocks(), + getNode().getAllocator().getNumUsedBlocks(), + getNode().getAllocator().getPeakNumUsedBlocks()); lowsyslog("CAN errors: %lu %lu\n", static_cast(can.driver.getIface(0)->getErrorCount()), From 67ee9d567f949ef84743a591989aeae354c5cc1d Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Fri, 9 Oct 2015 01:53:53 +0300 Subject: [PATCH 30/39] STM32 example: cleaner node initialization --- .../stm32/test_stm32f107/src/main.cpp | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/libuavcan_drivers/stm32/test_stm32f107/src/main.cpp b/libuavcan_drivers/stm32/test_stm32f107/src/main.cpp index 88dcf5f1b9..6910edeea4 100644 --- a/libuavcan_drivers/stm32/test_stm32f107/src/main.cpp +++ b/libuavcan_drivers/stm32/test_stm32f107/src/main.cpp @@ -92,22 +92,12 @@ public: configureNodeInfo(); /* - * Initializing the UAVCAN node - this may take a while + * Initializing the UAVCAN node */ - while (true) + const int node_init_res = getNode().start(); + if (node_init_res < 0) { - // Calling start() multiple times is OK - only the first successfull call will be effective - int res = getNode().start(); - - if (res < 0) - { - lowsyslog("Node initialization failure: %i, will try agin soon\n", res); - } - else - { - break; - } - ::sleep(3); + board::die(node_init_res); } /* From c5c16e97f8e291d355ef7b51fd3b34e268248cfc Mon Sep 17 00:00:00 2001 From: "Paul A. Patience" Date: Thu, 8 Oct 2015 18:54:40 -0400 Subject: [PATCH 31/39] Fix -Wundef warning by defining UAVCAN_STM32_BAREMETAL to 0 if it is not defined --- .../stm32/driver/include/uavcan_stm32/build_config.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libuavcan_drivers/stm32/driver/include/uavcan_stm32/build_config.hpp b/libuavcan_drivers/stm32/driver/include/uavcan_stm32/build_config.hpp index 3eba3ba6bf..b3bf403594 100644 --- a/libuavcan_drivers/stm32/driver/include/uavcan_stm32/build_config.hpp +++ b/libuavcan_drivers/stm32/driver/include/uavcan_stm32/build_config.hpp @@ -15,6 +15,10 @@ # define UAVCAN_STM32_NUTTX 0 #endif +#ifndef UAVCAN_STM32_BAREMETAL +# define UAVCAN_STM32_BAREMETAL 0 +#endif + /** * Number of interfaces must be enabled explicitly */ From d773db4ffc042b30ffe900cdd2deb330bd73967c Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Fri, 9 Oct 2015 02:06:45 +0300 Subject: [PATCH 32/39] STM32 example extended with dynamic node ID allocation --- .../stm32/test_stm32f107/src/main.cpp | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/libuavcan_drivers/stm32/test_stm32f107/src/main.cpp b/libuavcan_drivers/stm32/test_stm32f107/src/main.cpp index 6910edeea4..9dc9bfb133 100644 --- a/libuavcan_drivers/stm32/test_stm32f107/src/main.cpp +++ b/libuavcan_drivers/stm32/test_stm32f107/src/main.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "board/board.hpp" namespace app @@ -47,7 +48,6 @@ class : public chibios_rt::BaseStaticThread<8192> { void configureNodeInfo() { - getNode().setNodeID(64); getNode().setName("org.uavcan.stm32_test_stm32f107"); /* @@ -83,6 +83,33 @@ class : public chibios_rt::BaseStaticThread<8192> lowsyslog("\n"); } + void performDynamicNodeIDAllocation() + { + uavcan::DynamicNodeIDClient client(getNode()); + + const int client_start_res = client.start(getNode().getHardwareVersion().unique_id); + if (client_start_res < 0) + { + board::die(client_start_res); + } + + lowsyslog("Waiting for dynamic node ID allocation...\n"); + while (!client.isAllocationComplete()) + { + const int spin_res = getNode().spin(uavcan::MonotonicDuration::fromMSec(100)); + if (spin_res < 0) + { + lowsyslog("Spin failure: %i\n", spin_res); + } + } + + lowsyslog("Dynamic node ID %d allocated by %d\n", + int(client.getAllocatedNodeID().get()), + int(client.getAllocatorNodeID().get())); + + getNode().setNodeID(client.getAllocatedNodeID()); + } + public: msg_t main() { @@ -100,6 +127,11 @@ public: board::die(node_init_res); } + /* + * Waiting for a dynamic node ID allocation + */ + performDynamicNodeIDAllocation(); + /* * Time synchronizer */ From 45eb37d905489c3ed4305ac2981959d437d84c7d Mon Sep 17 00:00:00 2001 From: "Paul A. Patience" Date: Thu, 8 Oct 2015 19:07:14 -0400 Subject: [PATCH 33/39] Use a constructor in UtcSyncParams to compile in C++03 without warnings --- .../driver/include/uavcan_stm32/clock.hpp | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/libuavcan_drivers/stm32/driver/include/uavcan_stm32/clock.hpp b/libuavcan_drivers/stm32/driver/include/uavcan_stm32/clock.hpp index b11438d787..eeceaf3d77 100644 --- a/libuavcan_drivers/stm32/driver/include/uavcan_stm32/clock.hpp +++ b/libuavcan_drivers/stm32/driver/include/uavcan_stm32/clock.hpp @@ -50,13 +50,23 @@ void adjustUtc(uavcan::UtcDuration adjustment); */ struct UtcSyncParams { - float offset_p = 0.01F; ///< PPM per one usec error - float rate_i = 0.02F; ///< PPM per one PPM error for second - float rate_error_corner_freq = 0.01F; - float max_rate_correction_ppm = 300.0F; - float lock_thres_rate_ppm = 2.0F; - uavcan::UtcDuration lock_thres_offset = uavcan::UtcDuration::fromMSec(4); - uavcan::UtcDuration min_jump = uavcan::UtcDuration::fromMSec(10); ///< Min error to jump rather than change rate + float offset_p; ///< PPM per one usec error + float rate_i; ///< PPM per one PPM error for second + float rate_error_corner_freq; + float max_rate_correction_ppm; + float lock_thres_rate_ppm; + uavcan::UtcDuration lock_thres_offset; + uavcan::UtcDuration min_jump; ///< Min error to jump rather than change rate + + UtcSyncParams() + : offset_p(0.01F) + , rate_i(0.02F) + , rate_error_corner_freq(0.01F) + , max_rate_correction_ppm(300.0F) + , lock_thres_rate_ppm(2.0F) + , lock_thres_offset(uavcan::UtcDuration::fromMSec(4)) + , min_jump(uavcan::UtcDuration::fromMSec(10)) + { } }; /** From 93fe54bb21bf09aef3ca6dcad5703357523a352a Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Fri, 9 Oct 2015 05:10:13 +0300 Subject: [PATCH 34/39] Experimental fix to CAN bus lockup bug --- libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp b/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp index 77b8378a02..6d5fa5212b 100644 --- a/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp +++ b/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp @@ -516,8 +516,12 @@ int CanIface::init(const uavcan::uint32_t bitrate, const OperatingMode mode) /* * Hardware initialization */ - can_->MCR &= ~bxcan::MCR_SLEEP; // Exit sleep mode - can_->MCR |= bxcan::MCR_INRQ; // Request init + { + CriticalSectionLocker lock; + + can_->MCR &= ~bxcan::MCR_SLEEP; // Exit sleep mode + can_->MCR |= bxcan::MCR_INRQ; // Request init + } if (!waitMsrINakBitStateChange(true)) { From 85100d67660c269117c9f69e6cd66e2cdc55a299 Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Sat, 10 Oct 2015 10:05:51 +0300 Subject: [PATCH 35/39] STM32 initOnce(), not complete yet --- .../stm32/driver/include/uavcan_stm32/can.hpp | 2 + .../stm32/driver/src/uc_stm32_can.cpp | 116 ++++++++---------- 2 files changed, 56 insertions(+), 62 deletions(-) diff --git a/libuavcan_drivers/stm32/driver/include/uavcan_stm32/can.hpp b/libuavcan_drivers/stm32/driver/include/uavcan_stm32/can.hpp index 900d90b444..e9fd446026 100644 --- a/libuavcan_drivers/stm32/driver/include/uavcan_stm32/can.hpp +++ b/libuavcan_drivers/stm32/driver/include/uavcan_stm32/can.hpp @@ -223,6 +223,8 @@ class CanDriver : public uavcan::ICanDriver, uavcan::Noncopyable const uavcan::CanFrame* (& pending_tx)[uavcan::MaxCanIfaces], uavcan::MonotonicTime blocking_deadline); + static void initOnce(); + public: template CanDriver(CanRxItem (&rx_queue_storage)[UAVCAN_STM32_NUM_IFACES][RxQueueCapacity]) diff --git a/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp b/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp index 6d5fa5212b..07ac333cc4 100644 --- a/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp +++ b/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp @@ -879,68 +879,37 @@ static void nvicEnableVector(int irq, uint8_t 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) +void CanDriver::initOnce() { - int res = 0; - - UAVCAN_STM32_LOG("Bitrate %lu", static_cast(bitrate)); - /* - * CAN1 + * CAN1, CAN2 */ { CriticalSectionLocker lock; #if UAVCAN_STM32_NUTTX - modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_CAN1EN); + modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_CAN1EN); modifyreg32(STM32_RCC_APB1RSTR, 0, RCC_APB1RSTR_CAN1RST); modifyreg32(STM32_RCC_APB1RSTR, RCC_APB1RSTR_CAN1RST, 0); +# if UAVCAN_STM32_NUM_IFACES > 1 + modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_CAN2EN); + modifyreg32(STM32_RCC_APB1RSTR, 0, RCC_APB1RSTR_CAN2RST); + modifyreg32(STM32_RCC_APB1RSTR, RCC_APB1RSTR_CAN2RST, 0); +# endif #else RCC->APB1ENR |= RCC_APB1ENR_CAN1EN; RCC->APB1RSTR |= RCC_APB1RSTR_CAN1RST; RCC->APB1RSTR &= ~RCC_APB1RSTR_CAN1RST; -#endif - } - - UAVCAN_STM32_LOG("Initing iface 0..."); - res = if0_.init(bitrate, mode); - if (res < 0) - { - UAVCAN_STM32_LOG("Iface 0 init failed %i", res); - goto fail; - } - ifaces[0] = &if0_; - - /* - * CAN2 - */ -#if UAVCAN_STM32_NUM_IFACES > 1 - { - CriticalSectionLocker lock; -# if UAVCAN_STM32_NUTTX - modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_CAN2EN); - modifyreg32(STM32_RCC_APB1RSTR, 0, RCC_APB1RSTR_CAN2RST); - modifyreg32(STM32_RCC_APB1RSTR, RCC_APB1RSTR_CAN2RST, 0); -# else +# if UAVCAN_STM32_NUM_IFACES > 1 RCC->APB1ENR |= RCC_APB1ENR_CAN2EN; RCC->APB1RSTR |= RCC_APB1RSTR_CAN2RST; RCC->APB1RSTR &= ~RCC_APB1RSTR_CAN2RST; # endif - } - - UAVCAN_STM32_LOG("Initing iface 1..."); - res = if1_.init(bitrate, mode); - if (res < 0) - { - UAVCAN_STM32_LOG("Iface 1 init failed %i", res); - goto fail; - } - ifaces[1] = &if1_; #endif + } /* * IRQ @@ -948,12 +917,9 @@ int CanDriver::init(const uavcan::uint32_t bitrate, const CanIface::OperatingMod #if UAVCAN_STM32_NUTTX # define IRQ_ATTACH(irq, handler) \ { \ - res = irq_attach(irq, handler); \ - if (res < 0) \ - { \ - UAVCAN_STM32_LOG("IRQ attach failed %i", irq); \ - goto fail; \ - } \ + const int res = irq_attach(irq, handler); \ + (void)res; \ + assert(res >= 0); \ up_enable_irq(irq); \ } IRQ_ATTACH(STM32_IRQ_CAN1TX, can1_irq); @@ -982,6 +948,47 @@ int CanDriver::init(const uavcan::uint32_t bitrate, const CanIface::OperatingMod # endif } #endif +} + +int CanDriver::init(const uavcan::uint32_t bitrate, const CanIface::OperatingMode mode) +{ + int res = 0; + + UAVCAN_STM32_LOG("Bitrate %lu mode %d", static_cast(bitrate), static_cast(mode)); + + static bool initialized_once = false; + if (!initialized_once) + { + initialized_once = true; + UAVCAN_STM32_LOG("First initialization"); + initOnce(); + } + + /* + * CAN1 + */ + UAVCAN_STM32_LOG("Initing iface 0..."); + res = if0_.init(bitrate, mode); + if (res < 0) + { + UAVCAN_STM32_LOG("Iface 0 init failed %i", res); + goto fail; + } + ifaces[0] = &if0_; + + /* + * CAN2 + */ +#if UAVCAN_STM32_NUM_IFACES > 1 + UAVCAN_STM32_LOG("Initing iface 1..."); + res = if1_.init(bitrate, mode); + if (res < 0) + { + UAVCAN_STM32_LOG("Iface 1 init failed %i", res); + goto fail; + } + ifaces[1] = &if1_; +#endif UAVCAN_STM32_LOG("CAN drv init OK"); UAVCAN_ASSERT(res >= 0); @@ -990,21 +997,6 @@ int CanDriver::init(const uavcan::uint32_t bitrate, const CanIface::OperatingMod fail: UAVCAN_STM32_LOG("CAN drv init failed %i", res); UAVCAN_ASSERT(res < 0); - - CriticalSectionLocker lock; - -#if UAVCAN_STM32_NUTTX - // TODO: Unattach and disable all IRQs - modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_CAN1EN, 0); -# if UAVCAN_STM32_NUM_IFACES > 1 - modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_CAN2EN, 0); -# endif -#else - RCC->APB1ENR &= ~RCC_APB1ENR_CAN1EN; -# if UAVCAN_STM32_NUM_IFACES > 1 - RCC->APB1ENR &= ~RCC_APB1ENR_CAN2EN; -# endif -#endif return res; } From 076104877a5988b1de319be493fc0b614001ace7 Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Sat, 10 Oct 2015 10:16:57 +0300 Subject: [PATCH 36/39] STM32 new CAN initialization --- .../stm32/driver/src/uc_stm32_can.cpp | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp b/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp index 07ac333cc4..5db7288e29 100644 --- a/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp +++ b/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp @@ -488,10 +488,26 @@ bool CanIface::waitMsrINakBitStateChange(bool target_state) int CanIface::init(const uavcan::uint32_t bitrate, const OperatingMode mode) { - int res = 0; + /* + * We need to silence the controller in the first order, otherwise it may interfere with the following operations. + */ + { + CriticalSectionLocker lock; + + can_->MCR &= ~bxcan::MCR_SLEEP; // Exit sleep mode + can_->MCR |= bxcan::MCR_INRQ; // Request init + + can_->IER = 0; // Disable interrupts while initialization is in progress + } + + if (!waitMsrINakBitStateChange(true)) + { + UAVCAN_STM32_LOG("MSR INAK not set"); + return -1; + } /* - * Object state + * Object state - interrupts are disabled, so it's safe to modify it now */ rx_queue_.reset(); error_cnt_ = 0; @@ -505,31 +521,17 @@ int CanIface::init(const uavcan::uint32_t bitrate, const OperatingMode mode) * CAN timings for this bitrate */ Timings timings; - res = computeTimings(bitrate, timings); - if (res < 0) + const int timings_res = computeTimings(bitrate, timings); + if (timings_res < 0) { - goto leave; + return timings_res; } UAVCAN_STM32_LOG("Timings: presc=%u sjw=%u bs1=%u bs2=%u", unsigned(timings.prescaler), unsigned(timings.sjw), unsigned(timings.bs1), unsigned(timings.bs2)); /* - * Hardware initialization + * Hardware initialization (the hardware has already confirmed initialization mode, see above) */ - { - CriticalSectionLocker lock; - - can_->MCR &= ~bxcan::MCR_SLEEP; // Exit sleep mode - can_->MCR |= bxcan::MCR_INRQ; // Request init - } - - if (!waitMsrINakBitStateChange(true)) - { - UAVCAN_STM32_LOG("MSR INAK not set"); - res = -1; - goto leave; - } - can_->MCR = bxcan::MCR_ABOM | bxcan::MCR_AWUM | bxcan::MCR_INRQ; // RM page 648 can_->BTR = ((timings.sjw & 3U) << 24) | @@ -549,8 +551,7 @@ int CanIface::init(const uavcan::uint32_t bitrate, const OperatingMode mode) if (!waitMsrINakBitStateChange(false)) { UAVCAN_STM32_LOG("MSR INAK not cleared"); - res = -1; - goto leave; + return -1; } /* @@ -583,8 +584,7 @@ int CanIface::init(const uavcan::uint32_t bitrate, const OperatingMode mode) can_->FMR &= ~bxcan::FMR_FINIT; } -leave: - return res; + return 0; } void CanIface::handleTxMailboxInterrupt(uavcan::uint8_t mailbox_index, bool txok, const uavcan::uint64_t utc_usec) From 3dffcc007b9d614dc4f106fef5574dab59aeb8d3 Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Sat, 10 Oct 2015 17:09:52 +0300 Subject: [PATCH 37/39] STM32 demo - bxCAN GPIO initialization fixed --- .../stm32/test_stm32f107/src/board/board.cpp | 15 +++++++++++++++ .../stm32/test_stm32f107/src/sys/board.h | 10 ++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/libuavcan_drivers/stm32/test_stm32f107/src/board/board.cpp b/libuavcan_drivers/stm32/test_stm32f107/src/board/board.cpp index 28779986db..f1e3d7a923 100644 --- a/libuavcan_drivers/stm32/test_stm32f107/src/board/board.cpp +++ b/libuavcan_drivers/stm32/test_stm32f107/src/board/board.cpp @@ -28,7 +28,9 @@ namespace board void init() { halInit(); + chibios_rt::System::init(); + sdStart(&STDOUT_SD, NULL); } @@ -79,6 +81,19 @@ void boardInit(void) AFIO_MAPR_CAN_REMAP_REMAP3 | AFIO_MAPR_CAN2_REMAP | AFIO_MAPR_USART2_REMAP; + + /* + * Enabling the CAN controllers, then configuring GPIO functions for CAN_TX. + * Order matters, otherwise the CAN_TX pins will twitch, disturbing the CAN bus. + * This is why we can't perform this initialization using ChibiOS GPIO configuration. + */ + RCC->APB1ENR |= RCC_APB1ENR_CAN1EN; +#if UAVCAN_STM32_NUM_IFACES > 1 + RCC->APB1ENR |= RCC_APB1ENR_CAN2EN; +#endif + + palSetPadMode(GPIOD, 1, PAL_MODE_STM32_ALTERNATE_PUSHPULL); + palSetPadMode(GPIOB, 6, PAL_MODE_STM32_ALTERNATE_PUSHPULL); } } diff --git a/libuavcan_drivers/stm32/test_stm32f107/src/sys/board.h b/libuavcan_drivers/stm32/test_stm32f107/src/sys/board.h index 7de04ac5e4..c0608f24c1 100644 --- a/libuavcan_drivers/stm32/test_stm32f107/src/sys/board.h +++ b/libuavcan_drivers/stm32/test_stm32f107/src/sys/board.h @@ -20,6 +20,8 @@ #define GPIO_PORT_LED GPIOB #define GPIO_PIN_LED 9 +// GPIOD 10 is configured as OUTPUT, it is used as board reboot monitor. + /* * I/O ports initial setup, this configuration is established soon after reset * in the initialization code. @@ -48,7 +50,7 @@ #define VAL_GPIOACRH 0x88888888 // 15..8 #define VAL_GPIOAODR 0x00000000 -#define VAL_GPIOBCRL 0x8B488888 +#define VAL_GPIOBCRL 0x84488888 // CAN2 TX initialized as INPUT, it must be configured later! #define VAL_GPIOBCRH 0x88888828 #define VAL_GPIOBODR 0x00000000 @@ -56,9 +58,9 @@ #define VAL_GPIOCCRH 0x88888888 #define VAL_GPIOCODR 0x00000000 -#define VAL_GPIODCRL 0x88b888B4 -#define VAL_GPIODCRH 0x88888888 -#define VAL_GPIODODR 0x00000000 +#define VAL_GPIODCRL 0x88b88844 // CAN1 TX initialized as INPUT, it must be configured later! +#define VAL_GPIODCRH 0x88888288 +#define VAL_GPIODODR ((1 << 10)) #define VAL_GPIOECRL 0x88888888 #define VAL_GPIOECRH 0x88888888 From 8c2d86d55cd670851527485765f8e0694374dc3d Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Sat, 10 Oct 2015 17:50:25 +0300 Subject: [PATCH 38/39] STM32 demo board init fix --- libuavcan_drivers/stm32/test_stm32f107/src/board/board.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libuavcan_drivers/stm32/test_stm32f107/src/board/board.cpp b/libuavcan_drivers/stm32/test_stm32f107/src/board/board.cpp index f1e3d7a923..3f9bdd86ba 100644 --- a/libuavcan_drivers/stm32/test_stm32f107/src/board/board.cpp +++ b/libuavcan_drivers/stm32/test_stm32f107/src/board/board.cpp @@ -88,12 +88,12 @@ void boardInit(void) * This is why we can't perform this initialization using ChibiOS GPIO configuration. */ RCC->APB1ENR |= RCC_APB1ENR_CAN1EN; + palSetPadMode(GPIOD, 1, PAL_MODE_STM32_ALTERNATE_PUSHPULL); + #if UAVCAN_STM32_NUM_IFACES > 1 RCC->APB1ENR |= RCC_APB1ENR_CAN2EN; -#endif - - palSetPadMode(GPIOD, 1, PAL_MODE_STM32_ALTERNATE_PUSHPULL); palSetPadMode(GPIOB, 6, PAL_MODE_STM32_ALTERNATE_PUSHPULL); +#endif } } From c08016edbcdf206e793e7e4f6843cdbaf0ae009b Mon Sep 17 00:00:00 2001 From: Ben Dyer Date: Sun, 11 Oct 2015 21:22:00 +1100 Subject: [PATCH 39/39] Changed NodeInfoRetriever to inherit publicly from NodeStatusMonitor to allow access to node status API --- libuavcan/include/uavcan/protocol/node_info_retriever.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libuavcan/include/uavcan/protocol/node_info_retriever.hpp b/libuavcan/include/uavcan/protocol/node_info_retriever.hpp index ee44312bd0..3089150f2f 100644 --- a/libuavcan/include/uavcan/protocol/node_info_retriever.hpp +++ b/libuavcan/include/uavcan/protocol/node_info_retriever.hpp @@ -88,7 +88,7 @@ public: * * Events from this class can be routed to many listeners, @ref INodeInfoListener. */ -class UAVCAN_EXPORT NodeInfoRetriever : NodeStatusMonitor +class UAVCAN_EXPORT NodeInfoRetriever : public NodeStatusMonitor , TimerBase { public: