STM32: Fixed critical sections, removed clock interface for can driver

This commit is contained in:
Pavel Kirienko
2014-04-05 00:11:21 +04:00
parent f66338d329
commit 6341be88fd
5 changed files with 34 additions and 43 deletions
@@ -17,11 +17,6 @@ namespace clock
*/ */
void init(); void init();
/**
* For CAN timestamping.
*/
uavcan::uint64_t getUtcUSecFromInterrupt();
/** /**
* For general usage. * For general usage.
*/ */
@@ -48,28 +43,17 @@ uavcan::uint32_t getUtcAjdustmentJumpCount();
} }
/**
* Clock interface for CAN driver.
*/
class ICanTimestampingClock : public uavcan::ISystemClock
{
public:
virtual uavcan::uint64_t getUtcUSecFromInterrupt() const = 0;
};
/** /**
* Trivial system clock implementation; can be redefined by the application. * Trivial system clock implementation; can be redefined by the application.
* Uses a simple 16-bit hardware timer for both UTC and monotonic clocks. * Uses a simple 16-bit hardware timer for both UTC and monotonic clocks.
*/ */
class SystemClock : public ICanTimestampingClock, uavcan::Noncopyable class SystemClock : public uavcan::ISystemClock, uavcan::Noncopyable
{ {
SystemClock() { } SystemClock() { }
public: public:
static SystemClock& instance(); static SystemClock& instance();
virtual uavcan::uint64_t getUtcUSecFromInterrupt() const { return clock::getUtcUSecFromInterrupt(); }
virtual uavcan::MonotonicTime getMonotonic() const { return clock::getMonotonic(); } virtual uavcan::MonotonicTime getMonotonic() const { return clock::getMonotonic(); }
virtual uavcan::UtcTime getUtc() const { return clock::getUtc(); } virtual uavcan::UtcTime getUtc() const { return clock::getUtc(); }
virtual void adjustUtc(uavcan::UtcDuration adjustment) { clock::adjustUtc(adjustment); } virtual void adjustUtc(uavcan::UtcDuration adjustment) { clock::adjustUtc(adjustment); }
@@ -21,14 +21,8 @@
#if UAVCAN_STM32_CHIBIOS #if UAVCAN_STM32_CHIBIOS
# define UAVCAN_STM32_IRQ_HANDLER(id) CH_IRQ_HANDLER(id) # define UAVCAN_STM32_IRQ_HANDLER(id) CH_IRQ_HANDLER(id)
# define UAVCAN_STM32_IRQ_PROLOGUE() CH_IRQ_PROLOGUE()
# define UAVCAN_STM32_IRQ_PROLOGUE() \ # define UAVCAN_STM32_IRQ_EPILOGUE() CH_IRQ_EPILOGUE()
CH_IRQ_PROLOGUE(); \
chSysLockFromIsr()
# define UAVCAN_STM32_IRQ_EPILOGUE() \
chSysUnlockFromIsr(); \
CH_IRQ_EPILOGUE()
#else #else
@@ -93,4 +87,11 @@ struct CriticalSectionLock
~CriticalSectionLock() { chSysEnable(); } ~CriticalSectionLock() { chSysEnable(); }
}; };
namespace clock
{
uavcan::uint64_t getUtcUSecFromCanInterrupt();
}
} }
@@ -23,7 +23,7 @@ CanIface* ifaces[UAVCAN_STM32_NUM_IFACES] =
inline void handleTxInterrupt(uavcan::uint8_t iface_index) inline void handleTxInterrupt(uavcan::uint8_t iface_index)
{ {
uavcan::uint64_t utc_usec = clock::getUtcUSecFromInterrupt(); uavcan::uint64_t utc_usec = clock::getUtcUSecFromCanInterrupt();
if (utc_usec > 0) if (utc_usec > 0)
{ {
utc_usec--; utc_usec--;
@@ -41,7 +41,7 @@ inline void handleTxInterrupt(uavcan::uint8_t iface_index)
inline void handleRxInterrupt(uavcan::uint8_t iface_index, uavcan::uint8_t fifo_index) inline void handleRxInterrupt(uavcan::uint8_t iface_index, uavcan::uint8_t fifo_index)
{ {
uavcan::uint64_t utc_usec = clock::getUtcUSecFromInterrupt(); uavcan::uint64_t utc_usec = clock::getUtcUSecFromCanInterrupt();
if (utc_usec > 0) if (utc_usec > 0)
{ {
utc_usec--; utc_usec--;
@@ -23,9 +23,6 @@
# error "This UAVCAN_STM32_TIMER_NUMBER is not supported yet" # error "This UAVCAN_STM32_TIMER_NUMBER is not supported yet"
#endif #endif
#define TIMX_IRQ_ENABLE() TIMX->DIER = TIM_DIER_UIE
#define TIMX_IRQ_DISABLE() TIMX->DIER = 0
namespace uavcan_stm32 namespace uavcan_stm32
{ {
namespace clock namespace clock
@@ -85,13 +82,11 @@ void init()
/** /**
* Callable from any context * Callable from any context
*/ */
static uavcan::uint64_t sampleSpecifiedTime(const volatile uavcan::uint64_t* const value) static uavcan::uint64_t sampleFromCriticalSection(const volatile uavcan::uint64_t* const value)
{ {
assert(initialized); assert(initialized);
assert(TIMX->DIER & TIM_DIER_UIE); assert(TIMX->DIER & TIM_DIER_UIE);
TIMX_IRQ_DISABLE();
volatile uavcan::uint64_t time = *value; volatile uavcan::uint64_t time = *value;
volatile uavcan::uint32_t cnt = TIMX->CNT; volatile uavcan::uint32_t cnt = TIMX->CNT;
@@ -110,19 +105,21 @@ static uavcan::uint64_t sampleSpecifiedTime(const volatile uavcan::uint64_t* con
time += USecPerOverflow; time += USecPerOverflow;
} }
TIMX_IRQ_ENABLE();
return time + cnt; return time + cnt;
} }
uavcan::uint64_t getUtcUSecFromInterrupt() uavcan::uint64_t getUtcUSecFromCanInterrupt()
{ {
return utc_set ? sampleSpecifiedTime(&time_utc) : 0; return utc_set ? sampleFromCriticalSection(&time_utc) : 0;
} }
uavcan::MonotonicTime getMonotonic() uavcan::MonotonicTime getMonotonic()
{ {
const uavcan::uint64_t usec = sampleSpecifiedTime(&time_mono); uavcan::uint64_t usec = 0;
{
CriticalSectionLock locker;
usec = sampleFromCriticalSection(&time_mono);
}
#if !NDEBUG #if !NDEBUG
static uavcan::uint64_t prev_usec = 0; // Self-test static uavcan::uint64_t prev_usec = 0; // Self-test
assert(prev_usec <= usec); assert(prev_usec <= usec);
@@ -133,7 +130,16 @@ uavcan::MonotonicTime getMonotonic()
uavcan::UtcTime getUtc() uavcan::UtcTime getUtc()
{ {
return utc_set ? uavcan::UtcTime::fromUSec(sampleSpecifiedTime(&time_utc)) : uavcan::UtcTime(); if (utc_set)
{
uavcan::uint64_t usec = 0;
{
CriticalSectionLock locker;
usec = sampleFromCriticalSection(&time_utc);
}
return uavcan::UtcTime::fromUSec(usec);
}
return uavcan::UtcTime();
} }
void adjustUtc(uavcan::UtcDuration adjustment) void adjustUtc(uavcan::UtcDuration adjustment)
@@ -172,15 +178,13 @@ void adjustUtc(uavcan::UtcDuration adjustment)
if (adjustment.isNegative() && if (adjustment.isNegative() &&
uavcan::uint64_t(adjustment.getAbs().toUSec()) > time_utc) uavcan::uint64_t(adjustment.getAbs().toUSec()) > time_utc)
{ {
TIMX_IRQ_DISABLE(); CriticalSectionLock locker;
time_utc = 1; time_utc = 1;
TIMX_IRQ_ENABLE();
} }
else else
{ {
TIMX_IRQ_DISABLE(); CriticalSectionLock locker;
time_utc += adjustment.toUSec(); time_utc += adjustment.toUSec();
TIMX_IRQ_ENABLE();
} }
if (utc_set) if (utc_set)
@@ -30,7 +30,9 @@ void Event::signal()
void Event::signalFromInterrupt() void Event::signalFromInterrupt()
{ {
chSysLockFromIsr();
sem_.signalI(); sem_.signalI();
chSysUnlockFromIsr();
} }
#endif #endif