Merge pull request #85 from larics/master

support for FreeRTOS
This commit is contained in:
Pavel Kirienko
2016-06-03 01:09:20 +03:00
6 changed files with 161 additions and 13 deletions
@@ -19,6 +19,10 @@
# define UAVCAN_STM32_BAREMETAL 0
#endif
#ifndef UAVCAN_STM32_FREERTOS
# define UAVCAN_STM32_FREERTOS 0
#endif
/**
* Number of interfaces must be enabled explicitly
*/
@@ -17,6 +17,8 @@
# include <ctime>
# include <cstring>
#elif UAVCAN_STM32_BAREMETAL
#elif UAVCAN_STM32_FREERTOS
# include <cmsis_os.h>
#else
# error "Unknown OS"
#endif
@@ -136,7 +138,7 @@ public:
(void)can_driver;
}
bool wait(uavcan::MonotonicDuration)
bool wait(uavcan::MonotonicDuration duration)
{
(void)duration;
bool lready = ready;
@@ -161,6 +163,42 @@ public:
void unlock() { }
};
#elif UAVCAN_STM32_FREERTOS
class BusEvent
{
SemaphoreHandle_t sem_;
BaseType_t higher_priority_task_woken;
public:
BusEvent(CanDriver& can_driver)
{
(void)can_driver;
sem_ = xSemaphoreCreateBinary();
}
bool wait(uavcan::MonotonicDuration duration);
void signal();
void signalFromInterrupt();
void yieldFromISR();
};
class Mutex
{
SemaphoreHandle_t mtx_;
public:
Mutex(void)
{
mtx_ = xSemaphoreCreateMutex();
}
void lock();
void unlock();
};
#endif
@@ -15,6 +15,9 @@
# include <syslog.h>
#elif UAVCAN_STM32_BAREMETAL
# include <chip.h>
#elif UAVCAN_STM32_FREERTOS
# include <chip.h>
# include <cmsis_os.h>
#else
# error "Unknown OS"
#endif
@@ -71,6 +74,15 @@
# endif
#endif
#if UAVCAN_STM32_FREERTOS
/**
* Priority mask for timer and CAN interrupts.
*/
# ifndef UAVCAN_STM32_IRQ_PRIORITY_MASK
# define UAVCAN_STM32_IRQ_PRIORITY_MASK configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY
# endif
#endif
/**
* Glue macros
*/
@@ -122,6 +134,22 @@ struct CriticalSectionLocker
}
};
#elif UAVCAN_STM32_FREERTOS
struct CriticalSectionLocker
{
CriticalSectionLocker()
{
taskENTER_CRITICAL();
}
~CriticalSectionLocker()
{
taskEXIT_CRITICAL();
}
};
#endif
namespace clock
@@ -16,6 +16,7 @@
# include <arch/board/board.h>
#elif UAVCAN_STM32_BAREMETAL
#include <chip.h>
#elif UAVCAN_STM32_FREERTOS
#else
# error "Unknown OS"
#endif
@@ -200,11 +201,13 @@ int CanIface::computeTimings(const uavcan::uint32_t target_bitrate, Timings& out
* Hardware configuration
*/
#if UAVCAN_STM32_BAREMETAL
const uavcan::uint32_t pclk = STM32_PCLK1_FREQUENCY;
const uavcan::uint32_t pclk = STM32_PCLK1;
#elif UAVCAN_STM32_CHIBIOS
const uavcan::uint32_t pclk = STM32_PCLK1;
#elif UAVCAN_STM32_NUTTX
const uavcan::uint32_t pclk = STM32_PCLK1_FREQUENCY;
#elif UAVCAN_STM32_FREERTOS
const uavcan::uint32_t pclk = HAL_RCC_GetPCLK1Freq();
#else
# error "Unknown OS"
#endif
@@ -454,7 +457,7 @@ uavcan::int16_t CanIface::configureFilters(const uavcan::CanFilterConfig* filter
bool CanIface::waitMsrINakBitStateChange(bool target_state)
{
#if UAVCAN_STM32_NUTTX || UAVCAN_STM32_CHIBIOS
#if UAVCAN_STM32_NUTTX || UAVCAN_STM32_CHIBIOS || UAVCAN_STM32_FREERTOS
const unsigned Timeout = 1000;
#else
const unsigned Timeout = 2000000;
@@ -471,6 +474,9 @@ bool CanIface::waitMsrINakBitStateChange(bool target_state)
#endif
#if UAVCAN_STM32_CHIBIOS
::chThdSleep(MS2ST(1));
#endif
#if UAVCAN_STM32_FREERTOS
::osDelay(1);
#endif
}
return false;
@@ -617,6 +623,10 @@ void CanIface::handleTxInterrupt(const uavcan::uint64_t utc_usec)
update_event_.signalFromInterrupt();
pollErrorFlagsFromISR();
#if UAVCAN_STM32_FREERTOS
update_event_.yieldFromISR();
#endif
}
void CanIface::handleRxInterrupt(uavcan::uint8_t fifo_index, uavcan::uint64_t utc_usec)
@@ -680,6 +690,10 @@ void CanIface::handleRxInterrupt(uavcan::uint8_t fifo_index, uavcan::uint64_t ut
update_event_.signalFromInterrupt();
pollErrorFlagsFromISR();
#if UAVCAN_STM32_FREERTOS
update_event_.yieldFromISR();
#endif
}
void CanIface::pollErrorFlagsFromISR()
@@ -861,16 +875,21 @@ uavcan::int16_t CanDriver::select(uavcan::CanSelectMasks& inout_masks,
}
#if UAVCAN_STM32_BAREMETAL
#if UAVCAN_STM32_BAREMETAL || UAVCAN_STM32_FREERTOS
static void nvicEnableVector(int irq, uint8_t prio)
static void nvicEnableVector(IRQn_Type irq, uint8_t prio)
{
#if !defined (USE_HAL_DRIVER)
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);
#else
HAL_NVIC_SetPriority(irq, prio, 0);
HAL_NVIC_EnableIRQ(irq);
#endif
}
#endif
@@ -923,7 +942,7 @@ void CanDriver::initOnce()
IRQ_ATTACH(STM32_IRQ_CAN2RX1, can2_irq);
# endif
# undef IRQ_ATTACH
#elif UAVCAN_STM32_CHIBIOS || UAVCAN_STM32_BAREMETAL
#elif UAVCAN_STM32_CHIBIOS || UAVCAN_STM32_BAREMETAL || UAVCAN_STM32_FREERTOS
{
CriticalSectionLocker lock;
nvicEnableVector(CAN1_TX_IRQn, UAVCAN_STM32_IRQ_PRIORITY_MASK);
@@ -14,7 +14,7 @@
/*
* Timer instance
*/
# if (UAVCAN_STM32_CHIBIOS && CH_KERNEL_MAJOR == 2) || UAVCAN_STM32_BAREMETAL
# if (UAVCAN_STM32_CHIBIOS && CH_KERNEL_MAJOR == 2) || UAVCAN_STM32_BAREMETAL || UAVCAN_STM32_FREERTOS
# 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
@@ -81,16 +81,21 @@ uavcan::uint64_t time_utc = 0;
}
#if UAVCAN_STM32_BAREMETAL
#if UAVCAN_STM32_BAREMETAL || UAVCAN_STM32_FREERTOS
static void nvicEnableVector(int irq, uint8_t prio)
static void nvicEnableVector(IRQn_Type irq, uint8_t prio)
{
#if !defined (USE_HAL_DRIVER)
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);
#else
HAL_NVIC_SetPriority(irq, prio, 0);
HAL_NVIC_EnableIRQ(irq);
#endif
}
@@ -106,7 +111,7 @@ void init()
initialized = true;
# if UAVCAN_STM32_CHIBIOS || UAVCAN_STM32_BAREMETAL
# if UAVCAN_STM32_CHIBIOS || UAVCAN_STM32_BAREMETAL || UAVCAN_STM32_FREERTOS
// Power-on and reset
TIMX_RCC_ENR |= TIMX_RCC_ENR_MASK;
TIMX_RCC_RSTR |= TIMX_RCC_RSTR_MASK;
@@ -178,7 +183,7 @@ void setUtc(uavcan::UtcTime time)
static uavcan::uint64_t sampleUtcFromCriticalSection()
{
# if UAVCAN_STM32_CHIBIOS || UAVCAN_STM32_BAREMETAL
# if UAVCAN_STM32_CHIBIOS || UAVCAN_STM32_BAREMETAL || UAVCAN_STM32_FREERTOS
UAVCAN_ASSERT(initialized);
UAVCAN_ASSERT(TIMX->DIER & TIM_DIER_UIE);
@@ -228,7 +233,7 @@ uavcan::MonotonicTime getMonotonic()
volatile uavcan::uint64_t time = time_mono;
# if UAVCAN_STM32_CHIBIOS || UAVCAN_STM32_BAREMETAL
# if UAVCAN_STM32_CHIBIOS || UAVCAN_STM32_BAREMETAL || UAVCAN_STM32_FREERTOS
volatile uavcan::uint32_t cnt = TIMX->CNT;
if (TIMX->SR & TIM_SR_UIF)
@@ -435,7 +440,7 @@ UAVCAN_STM32_IRQ_HANDLER(TIMX_IRQHandler)
{
UAVCAN_STM32_IRQ_PROLOGUE();
# if UAVCAN_STM32_CHIBIOS || UAVCAN_STM32_BAREMETAL
# if UAVCAN_STM32_CHIBIOS || UAVCAN_STM32_BAREMETAL || UAVCAN_STM32_FREERTOS
TIMX->SR = 0;
# endif
# if UAVCAN_STM32_NUTTX
@@ -7,6 +7,7 @@
#include <uavcan_stm32/can.hpp>
#include "internal.hpp"
namespace uavcan_stm32
{
@@ -79,6 +80,59 @@ void Mutex::unlock()
# endif
}
#elif UAVCAN_STM32_FREERTOS
bool BusEvent::wait(uavcan::MonotonicDuration duration)
{
static const uavcan::int64_t MaxDelayMSec = 0x000FFFFF;
const uavcan::int64_t msec = duration.toMSec();
BaseType_t ret;
if (msec <= 0)
{
ret = xSemaphoreTake( sem_, ( TickType_t ) 0 );
}
else
{
ret = xSemaphoreTake( sem_, (msec > MaxDelayMSec) ? (MaxDelayMSec/portTICK_RATE_MS) : (msec/portTICK_RATE_MS));
}
return ret == pdTRUE;
}
void BusEvent::signal()
{
xSemaphoreGive( sem_ );
}
void BusEvent::signalFromInterrupt()
{
higher_priority_task_woken = pdFALSE;
xSemaphoreGiveFromISR( sem_, &higher_priority_task_woken );
}
void BusEvent::yieldFromISR()
{
portYIELD_FROM_ISR( higher_priority_task_woken );
}
/*
* Mutex
*/
void Mutex::lock()
{
xSemaphoreTake( mtx_, portMAX_DELAY );
}
void Mutex::unlock()
{
xSemaphoreGive( mtx_ );
}
#elif UAVCAN_STM32_NUTTX
const unsigned BusEvent::MaxPollWaiters;