STM32 NuttX support. Doesn't work though, hardfaults in IRQ handler.

This commit is contained in:
Pavel Kirienko
2014-05-06 18:27:04 +04:00
parent 87402b9701
commit 6e8cad20c6
8 changed files with 610 additions and 98 deletions
@@ -0,0 +1,291 @@
/*
* Copyright (C);2014 Pavel Kirienko <pavel.kirienko@gmail.com>
* Partly from NuttX STM32 CAN driver.
*/
#pragma once
#include <uavcan/uavcan.hpp>
#include <stdint.h>
#ifndef UAVCAN_CPP_VERSION
# error UAVCAN_CPP_VERSION
#endif
#if UAVCAN_CPP_VERSION < UAVCAN_CPP11
// #undef'ed at the end of this file
# define constexpr const
#endif
#if !defined(UAVCAN_STM32_NUM_IFACES) || (UAVCAN_STM32_NUM_IFACES != 1 && UAVCAN_STM32_NUM_IFACES != 2)
# error UAVCAN_STM32_NUM_IFACES
#endif
namespace uavcan_stm32
{
namespace bxcan
{
struct TxMailboxType
{
volatile uint32_t TIR;
volatile uint32_t TDTR;
volatile uint32_t TDLR;
volatile uint32_t TDHR;
};
struct RxMailboxType
{
volatile uint32_t RIR;
volatile uint32_t RDTR;
volatile uint32_t RDLR;
volatile uint32_t RDHR;
};
struct FilterRegisterType
{
volatile uint32_t FR1;
volatile uint32_t FR2;
};
struct CanType
{
volatile uint32_t MCR; /*!< CAN master control register, Address offset: 0x00 */
volatile uint32_t MSR; /*!< CAN master status register, Address offset: 0x04 */
volatile uint32_t TSR; /*!< CAN transmit status register, Address offset: 0x08 */
volatile uint32_t RF0R; /*!< CAN receive FIFO 0 register, Address offset: 0x0C */
volatile uint32_t RF1R; /*!< CAN receive FIFO 1 register, Address offset: 0x10 */
volatile uint32_t IER; /*!< CAN interrupt enable register, Address offset: 0x14 */
volatile uint32_t ESR; /*!< CAN error status register, Address offset: 0x18 */
volatile uint32_t BTR; /*!< CAN bit timing register, Address offset: 0x1C */
uint32_t RESERVED0[88]; /*!< Reserved, 0x020 - 0x17F */
TxMailboxType TxMailbox[3]; /*!< CAN Tx MailBox, Address offset: 0x180 - 0x1AC */
RxMailboxType RxMailbox[2]; /*!< CAN FIFO MailBox, Address offset: 0x1B0 - 0x1CC */
uint32_t RESERVED1[12]; /*!< Reserved, 0x1D0 - 0x1FF */
volatile uint32_t FMR; /*!< CAN filter master register, Address offset: 0x200 */
volatile uint32_t FM1R; /*!< CAN filter mode register, Address offset: 0x204 */
uint32_t RESERVED2; /*!< Reserved, 0x208 */
volatile uint32_t FS1R; /*!< CAN filter scale register, Address offset: 0x20C */
uint32_t RESERVED3; /*!< Reserved, 0x210 */
volatile uint32_t FFA1R; /*!< CAN filter FIFO assignment register, Address offset: 0x214 */
uint32_t RESERVED4; /*!< Reserved, 0x218 */
volatile uint32_t FA1R; /*!< CAN filter activation register, Address offset: 0x21C */
uint32_t RESERVED5[8]; /*!< Reserved, 0x220-0x23F */
FilterRegisterType FilterRegister[28]; /*!< CAN Filter Register, Address offset: 0x240-0x31C */
};
/**
* CANx register sets
*/
CanType* const Can[UAVCAN_STM32_NUM_IFACES] =
{
reinterpret_cast<CanType*>(0x40006400)
#if UAVCAN_STM32_NUM_IFACES > 1
,
reinterpret_cast<CanType*>(0x40006800)
#endif
};
/* CAN master control register */
constexpr unsigned long MCR_INRQ = (1 << 0); /* Bit 0: Initialization Request */
constexpr unsigned long MCR_SLEEP = (1 << 1); /* Bit 1: Sleep Mode Request */
constexpr unsigned long MCR_TXFP = (1 << 2); /* Bit 2: Transmit FIFO Priority */
constexpr unsigned long MCR_RFLM = (1 << 3); /* Bit 3: Receive FIFO Locked Mode */
constexpr unsigned long MCR_NART = (1 << 4); /* Bit 4: No Automatic Retransmission */
constexpr unsigned long MCR_AWUM = (1 << 5); /* Bit 5: Automatic Wakeup Mode */
constexpr unsigned long MCR_ABOM = (1 << 6); /* Bit 6: Automatic Bus-Off Management */
constexpr unsigned long MCR_TTCM = (1 << 7); /* Bit 7: Time Triggered Communication Mode Enable */
constexpr unsigned long MCR_RESET = (1 << 15);/* Bit 15: bxCAN software master reset */
constexpr unsigned long MCR_DBF = (1 << 16);/* Bit 16: Debug freeze */
/* CAN master status register */
constexpr unsigned long MSR_INAK = (1 << 0); /* Bit 0: Initialization Acknowledge */
constexpr unsigned long MSR_SLAK = (1 << 1); /* Bit 1: Sleep Acknowledge */
constexpr unsigned long MSR_ERRI = (1 << 2); /* Bit 2: Error Interrupt */
constexpr unsigned long MSR_WKUI = (1 << 3); /* Bit 3: Wakeup Interrupt */
constexpr unsigned long MSR_SLAKI = (1 << 4); /* Bit 4: Sleep acknowledge interrupt */
constexpr unsigned long MSR_TXM = (1 << 8); /* Bit 8: Transmit Mode */
constexpr unsigned long MSR_RXM = (1 << 9); /* Bit 9: Receive Mode */
constexpr unsigned long MSR_SAMP = (1 << 10);/* Bit 10: Last Sample Point */
constexpr unsigned long MSR_RX = (1 << 11);/* Bit 11: CAN Rx Signal */
/* CAN transmit status register */
constexpr unsigned long TSR_RQCP0 = (1 << 0); /* Bit 0: Request Completed Mailbox 0 */
constexpr unsigned long TSR_TXOK0 = (1 << 1); /* Bit 1 : Transmission OK of Mailbox 0 */
constexpr unsigned long TSR_ALST0 = (1 << 2); /* Bit 2 : Arbitration Lost for Mailbox 0 */
constexpr unsigned long TSR_TERR0 = (1 << 3); /* Bit 3 : Transmission Error of Mailbox 0 */
constexpr unsigned long TSR_ABRQ0 = (1 << 7); /* Bit 7 : Abort Request for Mailbox 0 */
constexpr unsigned long TSR_RQCP1 = (1 << 8); /* Bit 8 : Request Completed Mailbox 1 */
constexpr unsigned long TSR_TXOK1 = (1 << 9); /* Bit 9 : Transmission OK of Mailbox 1 */
constexpr unsigned long TSR_ALST1 = (1 << 10);/* Bit 10 : Arbitration Lost for Mailbox 1 */
constexpr unsigned long TSR_TERR1 = (1 << 11);/* Bit 11 : Transmission Error of Mailbox 1 */
constexpr unsigned long TSR_ABRQ1 = (1 << 15);/* Bit 15 : Abort Request for Mailbox 1 */
constexpr unsigned long TSR_RQCP2 = (1 << 16);/* Bit 16 : Request Completed Mailbox 2 */
constexpr unsigned long TSR_TXOK2 = (1 << 17);/* Bit 17 : Transmission OK of Mailbox 2 */
constexpr unsigned long TSR_ALST2 = (1 << 18);/* Bit 18: Arbitration Lost for Mailbox 2 */
constexpr unsigned long TSR_TERR2 = (1 << 19);/* Bit 19: Transmission Error of Mailbox 2 */
constexpr unsigned long TSR_ABRQ2 = (1 << 23);/* Bit 23: Abort Request for Mailbox 2 */
constexpr unsigned long TSR_CODE_SHIFT = (24); /* Bits 25-24: Mailbox Code */
constexpr unsigned long TSR_CODE_MASK = (3 << TSR_CODE_SHIFT);
constexpr unsigned long TSR_TME0 = (1 << 26);/* Bit 26: Transmit Mailbox 0 Empty */
constexpr unsigned long TSR_TME1 = (1 << 27);/* Bit 27: Transmit Mailbox 1 Empty */
constexpr unsigned long TSR_TME2 = (1 << 28);/* Bit 28: Transmit Mailbox 2 Empty */
constexpr unsigned long TSR_LOW0 = (1 << 29);/* Bit 29: Lowest Priority Flag for Mailbox 0 */
constexpr unsigned long TSR_LOW1 = (1 << 30);/* Bit 30: Lowest Priority Flag for Mailbox 1 */
constexpr unsigned long TSR_LOW2 = (1 << 31);/* Bit 31: Lowest Priority Flag for Mailbox 2 */
/* CAN receive FIFO 0/1 registers */
constexpr unsigned long RFR_FMP_SHIFT = (0); /* Bits 1-0: FIFO Message Pending */
constexpr unsigned long RFR_FMP_MASK = (3 << RFR_FMP_SHIFT);
constexpr unsigned long RFR_FULL = (1 << 3); /* Bit 3: FIFO 0 Full */
constexpr unsigned long RFR_FOVR = (1 << 4); /* Bit 4: FIFO 0 Overrun */
constexpr unsigned long RFR_RFOM = (1 << 5); /* Bit 5: Release FIFO 0 Output Mailbox */
/* CAN interrupt enable register */
constexpr unsigned long IER_TMEIE = (1 << 0); /* Bit 0: Transmit Mailbox Empty Interrupt Enable */
constexpr unsigned long IER_FMPIE0 = (1 << 1); /* Bit 1: FIFO Message Pending Interrupt Enable */
constexpr unsigned long IER_FFIE0 = (1 << 2); /* Bit 2: FIFO Full Interrupt Enable */
constexpr unsigned long IER_FOVIE0 = (1 << 3); /* Bit 3: FIFO Overrun Interrupt Enable */
constexpr unsigned long IER_FMPIE1 = (1 << 4); /* Bit 4: FIFO Message Pending Interrupt Enable */
constexpr unsigned long IER_FFIE1 = (1 << 5); /* Bit 5: FIFO Full Interrupt Enable */
constexpr unsigned long IER_FOVIE1 = (1 << 6); /* Bit 6: FIFO Overrun Interrupt Enable */
constexpr unsigned long IER_EWGIE = (1 << 8); /* Bit 8: Error Warning Interrupt Enable */
constexpr unsigned long IER_EPVIE = (1 << 9); /* Bit 9: Error Passive Interrupt Enable */
constexpr unsigned long IER_BOFIE = (1 << 10);/* Bit 10: Bus-Off Interrupt Enable */
constexpr unsigned long IER_LECIE = (1 << 11);/* Bit 11: Last Error Code Interrupt Enable */
constexpr unsigned long IER_ERRIE = (1 << 15);/* Bit 15: Error Interrupt Enable */
constexpr unsigned long IER_WKUIE = (1 << 16);/* Bit 16: Wakeup Interrupt Enable */
constexpr unsigned long IER_SLKIE = (1 << 17);/* Bit 17: Sleep Interrupt Enable */
/* CAN error status register */
constexpr unsigned long ESR_EWGF = (1 << 0); /* Bit 0: Error Warning Flag */
constexpr unsigned long ESR_EPVF = (1 << 1); /* Bit 1: Error Passive Flag */
constexpr unsigned long ESR_BOFF = (1 << 2); /* Bit 2: Bus-Off Flag */
constexpr unsigned long ESR_LEC_SHIFT = (4); /* Bits 6-4: Last Error Code */
constexpr unsigned long ESR_LEC_MASK = (7 << ESR_LEC_SHIFT);
constexpr unsigned long ESR_NOERROR = (0 << ESR_LEC_SHIFT);/* 000: No Error */
constexpr unsigned long ESR_STUFFERROR = (1 << ESR_LEC_SHIFT);/* 001: Stuff Error */
constexpr unsigned long ESR_FORMERROR = (2 << ESR_LEC_SHIFT);/* 010: Form Error */
constexpr unsigned long ESR_ACKERROR = (3 << ESR_LEC_SHIFT);/* 011: Acknowledgment Error */
constexpr unsigned long ESR_BRECERROR = (4 << ESR_LEC_SHIFT);/* 100: Bit recessive Error */
constexpr unsigned long ESR_BDOMERROR = (5 << ESR_LEC_SHIFT);/* 101: Bit dominant Error */
constexpr unsigned long ESR_CRCERRPR = (6 << ESR_LEC_SHIFT);/* 110: CRC Error */
constexpr unsigned long ESR_SWERROR = (7 << ESR_LEC_SHIFT);/* 111: Set by software */
constexpr unsigned long ESR_TEC_SHIFT = (16); /* Bits 23-16: LS byte of the 9-bit Transmit Error Counter */
constexpr unsigned long ESR_TEC_MASK = (0xff << ESR_TEC_SHIFT);
constexpr unsigned long ESR_REC_SHIFT = (24); /* Bits 31-24: Receive Error Counter */
constexpr unsigned long ESR_REC_MASK = (0xff << ESR_REC_SHIFT);
/* CAN bit timing register */
constexpr unsigned long BTR_BRP_SHIFT = (0); /* Bits 9-0: Baud Rate Prescaler */
constexpr unsigned long BTR_BRP_MASK = (0x03ff << BTR_BRP_SHIFT);
constexpr unsigned long BTR_TS1_SHIFT = (16); /* Bits 19-16: Time Segment 1 */
constexpr unsigned long BTR_TS1_MASK = (0x0f << BTR_TS1_SHIFT);
constexpr unsigned long BTR_TS2_SHIFT = (20); /* Bits 22-20: Time Segment 2 */
constexpr unsigned long BTR_TS2_MASK = (7 << BTR_TS2_SHIFT);
constexpr unsigned long BTR_SJW_SHIFT = (24); /* Bits 25-24: Resynchronization Jump Width */
constexpr unsigned long BTR_SJW_MASK = (3 << BTR_SJW_SHIFT);
constexpr unsigned long BTR_LBKM = (1 << 30);/* Bit 30: Loop Back Mode (Debug);*/
constexpr unsigned long BTR_SILM = (1 << 31);/* Bit 31: Silent Mode (Debug);*/
constexpr unsigned long BTR_BRP_MAX = (1024); /* Maximum BTR value (without decrement);*/
constexpr unsigned long BTR_TSEG1_MAX = (16); /* Maximum TSEG1 value (without decrement);*/
constexpr unsigned long BTR_TSEG2_MAX = (8); /* Maximum TSEG2 value (without decrement);*/
/* TX mailbox identifier register */
constexpr unsigned long TIR_TXRQ = (1 << 0); /* Bit 0: Transmit Mailbox Request */
constexpr unsigned long TIR_RTR = (1 << 1); /* Bit 1: Remote Transmission Request */
constexpr unsigned long TIR_IDE = (1 << 2); /* Bit 2: Identifier Extension */
constexpr unsigned long TIR_EXID_SHIFT = (3); /* Bit 3-31: Extended Identifier */
constexpr unsigned long TIR_EXID_MASK = (0x1fffffff << TIR_EXID_SHIFT);
constexpr unsigned long TIR_STID_SHIFT = (21); /* Bits 21-31: Standard Identifier */
constexpr unsigned long TIR_STID_MASK = (0x07ff << TIR_STID_SHIFT);
/* Mailbox data length control and time stamp register */
constexpr unsigned long TDTR_DLC_SHIFT = (0); /* Bits 3:0: Data Length Code */
constexpr unsigned long TDTR_DLC_MASK = (0x0f << TDTR_DLC_SHIFT);
constexpr unsigned long TDTR_TGT = (1 << 8); /* Bit 8: Transmit Global Time */
constexpr unsigned long TDTR_TIME_SHIFT = (16); /* Bits 31:16: Message Time Stamp */
constexpr unsigned long TDTR_TIME_MASK = (0xffff << TDTR_TIME_SHIFT);
/* Mailbox data low register */
constexpr unsigned long TDLR_DATA0_SHIFT = (0); /* Bits 7-0: Data Byte 0 */
constexpr unsigned long TDLR_DATA0_MASK = (0xff << TDLR_DATA0_SHIFT);
constexpr unsigned long TDLR_DATA1_SHIFT = (8); /* Bits 15-8: Data Byte 1 */
constexpr unsigned long TDLR_DATA1_MASK = (0xff << TDLR_DATA1_SHIFT);
constexpr unsigned long TDLR_DATA2_SHIFT = (16); /* Bits 23-16: Data Byte 2 */
constexpr unsigned long TDLR_DATA2_MASK = (0xff << TDLR_DATA2_SHIFT);
constexpr unsigned long TDLR_DATA3_SHIFT = (24); /* Bits 31-24: Data Byte 3 */
constexpr unsigned long TDLR_DATA3_MASK = (0xff << TDLR_DATA3_SHIFT);
/* Mailbox data high register */
constexpr unsigned long TDHR_DATA4_SHIFT = (0); /* Bits 7-0: Data Byte 4 */
constexpr unsigned long TDHR_DATA4_MASK = (0xff << TDHR_DATA4_SHIFT);
constexpr unsigned long TDHR_DATA5_SHIFT = (8); /* Bits 15-8: Data Byte 5 */
constexpr unsigned long TDHR_DATA5_MASK = (0xff << TDHR_DATA5_SHIFT);
constexpr unsigned long TDHR_DATA6_SHIFT = (16); /* Bits 23-16: Data Byte 6 */
constexpr unsigned long TDHR_DATA6_MASK = (0xff << TDHR_DATA6_SHIFT);
constexpr unsigned long TDHR_DATA7_SHIFT = (24); /* Bits 31-24: Data Byte 7 */
constexpr unsigned long TDHR_DATA7_MASK = (0xff << TDHR_DATA7_SHIFT);
/* Rx FIFO mailbox identifier register */
constexpr unsigned long RIR_RTR = (1 << 1); /* Bit 1: Remote Transmission Request */
constexpr unsigned long RIR_IDE = (1 << 2); /* Bit 2: Identifier Extension */
constexpr unsigned long RIR_EXID_SHIFT = (3); /* Bit 3-31: Extended Identifier */
constexpr unsigned long RIR_EXID_MASK = (0x1fffffff << RIR_EXID_SHIFT);
constexpr unsigned long RIR_STID_SHIFT = (21); /* Bits 21-31: Standard Identifier */
constexpr unsigned long RIR_STID_MASK = (0x07ff << RIR_STID_SHIFT);
/* Receive FIFO mailbox data length control and time stamp register */
constexpr unsigned long RDTR_DLC_SHIFT = (0); /* Bits 3:0: Data Length Code */
constexpr unsigned long RDTR_DLC_MASK = (0x0f << RDTR_DLC_SHIFT);
constexpr unsigned long RDTR_FM_SHIFT = (8); /* Bits 15-8: Filter Match Index */
constexpr unsigned long RDTR_FM_MASK = (0xff << RDTR_FM_SHIFT);
constexpr unsigned long RDTR_TIME_SHIFT = (16); /* Bits 31:16: Message Time Stamp */
constexpr unsigned long RDTR_TIME_MASK = (0xffff << RDTR_TIME_SHIFT);
/* Receive FIFO mailbox data low register */
constexpr unsigned long RDLR_DATA0_SHIFT = (0); /* Bits 7-0: Data Byte 0 */
constexpr unsigned long RDLR_DATA0_MASK = (0xff << RDLR_DATA0_SHIFT);
constexpr unsigned long RDLR_DATA1_SHIFT = (8); /* Bits 15-8: Data Byte 1 */
constexpr unsigned long RDLR_DATA1_MASK = (0xff << RDLR_DATA1_SHIFT);
constexpr unsigned long RDLR_DATA2_SHIFT = (16); /* Bits 23-16: Data Byte 2 */
constexpr unsigned long RDLR_DATA2_MASK = (0xff << RDLR_DATA2_SHIFT);
constexpr unsigned long RDLR_DATA3_SHIFT = (24); /* Bits 31-24: Data Byte 3 */
constexpr unsigned long RDLR_DATA3_MASK = (0xff << RDLR_DATA3_SHIFT);
/* Receive FIFO mailbox data high register */
constexpr unsigned long RDHR_DATA4_SHIFT = (0); /* Bits 7-0: Data Byte 4 */
constexpr unsigned long RDHR_DATA4_MASK = (0xff << RDHR_DATA4_SHIFT);
constexpr unsigned long RDHR_DATA5_SHIFT = (8); /* Bits 15-8: Data Byte 5 */
constexpr unsigned long RDHR_DATA5_MASK = (0xff << RDHR_DATA5_SHIFT);
constexpr unsigned long RDHR_DATA6_SHIFT = (16); /* Bits 23-16: Data Byte 6 */
constexpr unsigned long RDHR_DATA6_MASK = (0xff << RDHR_DATA6_SHIFT);
constexpr unsigned long RDHR_DATA7_SHIFT = (24); /* Bits 31-24: Data Byte 7 */
constexpr unsigned long RDHR_DATA7_MASK = (0xff << RDHR_DATA7_SHIFT);
/* CAN filter master register */
constexpr unsigned long FMR_FINIT = (1 << 0); /* Bit 0: Filter Init Mode */
}
}
#if UAVCAN_CPP_VERSION < UAVCAN_CPP11
# undef constexpr
#endif
@@ -6,24 +6,7 @@
#include <uavcan_stm32/thread.hpp>
#include <uavcan/driver/can.hpp>
#if UAVCAN_STM32_CHIBIOS
# include <hal.h>
#else
# error "Unknown OS"
#endif
#ifndef UAVCAN_STM32_NUM_IFACES
# if defined(STM32F10X_CL) || defined(STM32F2XX) || defined(STM32F4XX)
# define UAVCAN_STM32_NUM_IFACES 2
# else
# define UAVCAN_STM32_NUM_IFACES 1
# endif
#endif
#if UAVCAN_STM32_NUM_IFACES != 1 && UAVCAN_STM32_NUM_IFACES != 2
# error UAVCAN_STM32_NUM_IFACES
#endif
#include <uavcan_stm32/bxcan.hpp>
namespace uavcan_stm32
{
@@ -108,7 +91,7 @@ class CanIface : public uavcan::ICanIface, uavcan::Noncopyable
enum { NumFilters = 14 };
RxQueue rx_queue_;
CAN_TypeDef* const can_;
bxcan::CanType* const can_;
uavcan::uint64_t error_cnt_;
Event& update_event_;
TxItem pending_tx_[NumTxMailboxes];
@@ -134,7 +117,7 @@ class CanIface : public uavcan::ICanIface, uavcan::Noncopyable
public:
enum { MaxRxQueueCapacity = 254 };
CanIface(CAN_TypeDef* can, Event& update_event, uavcan::uint8_t self_index,
CanIface(bxcan::CanType* can, Event& update_event, uavcan::uint8_t self_index,
CanRxItem* rx_queue_buffer, uavcan::uint8_t rx_queue_capacity)
: rx_queue_(rx_queue_buffer, rx_queue_capacity)
, can_(can)
@@ -209,9 +192,9 @@ class CanDriver : public uavcan::ICanDriver, uavcan::Noncopyable
public:
template <unsigned RxQueueCapacity>
CanDriver(CanRxItem (&rx_queue_storage)[UAVCAN_STM32_NUM_IFACES][RxQueueCapacity])
: if0_(CAN1, update_event_, 0, rx_queue_storage[0], RxQueueCapacity)
: if0_(bxcan::Can[0], update_event_, 0, rx_queue_storage[0], RxQueueCapacity)
#if UAVCAN_STM32_NUM_IFACES > 1
, if1_(CAN2, update_event_, 1, rx_queue_storage[1], RxQueueCapacity)
, if1_(bxcan::Can[1], update_event_, 1, rx_queue_storage[1], RxQueueCapacity)
#endif
{
uavcan::StaticAssert<(RxQueueCapacity <= CanIface::MaxRxQueueCapacity)>::check();
@@ -6,6 +6,9 @@
#if UAVCAN_STM32_CHIBIOS
# include <ch.hpp>
#elif UAVCAN_STM32_NUTTX
# include <semaphore.h>
# include <time.h>
#else
# error "Unknown OS"
#endif
@@ -15,11 +18,11 @@
namespace uavcan_stm32
{
#if UAVCAN_STM32_CHIBIOS
class Event
{
#if UAVCAN_STM32_CHIBIOS
chibios_rt::CounterSemaphore sem_;
#endif
public:
Event() : sem_(0) { }
@@ -31,18 +34,35 @@ public:
void signalFromInterrupt();
};
class Mutex
{
#if UAVCAN_STM32_CHIBIOS
chibios_rt::Mutex mtx_;
#endif
public:
void lock();
void unlock();
};
#elif UAVCAN_STM32_NUTTX
class Event
{
sem_t sem_;
public:
Event();
bool wait(uavcan::MonotonicDuration duration);
void signal();
void signalFromInterrupt();
};
#endif
#if UAVCAN_STM32_CHIBIOS
class MutexLocker
{
@@ -60,4 +80,6 @@ public:
}
};
#endif
}
@@ -6,13 +6,22 @@
#if UAVCAN_STM32_CHIBIOS
# include <hal.h>
#elif UAVCAN_STM32_NUTTX
# include <nuttx/arch.h>
# include <syslog.h>
#else
# error "Unknown OS"
#endif
#if UAVCAN_STM32_DEBUG
# include <cstdio>
# include <cstdarg>
/**
* Debug output
*/
#ifndef UAVCAN_STM32_TRACE
# if UAVCAN_STM32_NUTTX && CONFIG_ARCH_LOWPUTC
# define UAVCAN_STM32_LOG(fmt, ...) lowsyslog("uavcan_stm32: " fmt "\n", ##__VA_ARGS__)
# else
# define UAVCAN_STM32_LOG(...) ((void)0)
# endif
#endif
/**
@@ -32,11 +41,13 @@
#endif
#if UAVCAN_STM32_CHIBIOS
/**
* 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)
# ifndef UAVCAN_STM32_IRQ_PRIORITY_MASK
# define UAVCAN_STM32_IRQ_PRIORITY_MASK CORTEX_PRIORITY_MASK(CORTEX_MAX_KERNEL_PRIORITY)
# endif
#endif
/**
@@ -44,7 +55,7 @@
* e.g. -DUAVCAN_STM32_TIMER_NUMBER=2
*/
#ifndef UAVCAN_STM32_TIMER_NUMBER
# error UAVCAN_STM32_TIMER_NUMBER
// In this case the clock driver should be implemented by the application
#endif
/**
@@ -59,12 +70,32 @@
namespace uavcan_stm32
{
#if UAVCAN_STM32_CHIBIOS
struct CriticalSectionLocker
{
CriticalSectionLocker() { chSysSuspend(); }
~CriticalSectionLocker() { chSysEnable(); }
};
#elif UAVCAN_STM32_NUTTX
struct CriticalSectionLocker
{
const irqstate_t flags_;
CriticalSectionLocker()
: flags_(irqsave())
{ }
~CriticalSectionLocker()
{
irqrestore(flags_);
}
};
#endif
namespace clock
{
@@ -8,18 +8,41 @@
#include <uavcan_stm32/clock.hpp>
#include "internal.hpp"
#if UAVCAN_STM32_CHIBIOS
# include <hal.h>
#elif UAVCAN_STM32_NUTTX
# include <nuttx/arch.h>
# include <nuttx/irq.h>
# include <arch/board/board.h>
#else
# error "Unknown OS"
#endif
#if !(defined(STM32F10X_CL) || defined(STM32F2XX) || defined(STM32F4XX))
#if !UAVCAN_STM32_NUTTX
# if !(defined(STM32F10X_CL) || defined(STM32F2XX) || defined(STM32F4XX))
// IRQ numbers
# define CAN1_RX0_IRQn USB_LP_CAN1_RX0_IRQn
# define CAN1_TX_IRQn USB_HP_CAN1_TX_IRQn
# define CAN1_RX0_IRQn USB_LP_CAN1_RX0_IRQn
# define CAN1_TX_IRQn USB_HP_CAN1_TX_IRQn
// IRQ vectors
# if !defined(CAN1_RX0_IRQHandler) || !defined(CAN1_TX_IRQHandler)
# define CAN1_TX_IRQHandler USB_HP_CAN1_TX_IRQHandler
# define CAN1_RX0_IRQHandler USB_LP_CAN1_RX0_IRQHandler
# if !defined(CAN1_RX0_IRQHandler) || !defined(CAN1_TX_IRQHandler)
# define CAN1_TX_IRQHandler USB_HP_CAN1_TX_IRQHandler
# define CAN1_RX0_IRQHandler USB_LP_CAN1_RX0_IRQHandler
# endif
# endif
#endif
#if UAVCAN_STM32_NUTTX
# if !defined(STM32_IRQ_CAN1TX) && !defined(STM32_IRQ_CAN1RX0)
# define STM32_IRQ_CAN1TX STM32_IRQ_USBHPCANTX
# define STM32_IRQ_CAN1RX0 STM32_IRQ_USBLPCANRX0
# endif
extern "C"
{
static int can1_irq(const int irq, void*);
static int can2_irq(const int irq, void*);
}
#endif
namespace uavcan_stm32
{
namespace
@@ -154,7 +177,13 @@ int CanIface::computeTimings(const uavcan::uint32_t target_bitrate, Timings& out
return -1;
}
#if UAVCAN_STM32_CHIBIOS
const uavcan::uint32_t pclk = STM32_PCLK1;
#elif UAVCAN_STM32_NUTTX
const uavcan::uint32_t pclk = STM32_PCLK1_FREQUENCY;
#else
# error "Unknown OS"
#endif
const uavcan::uint32_t prescaler_bs = pclk / target_bitrate;
// Initial guess:
@@ -212,15 +241,15 @@ uavcan::int16_t CanIface::send(const uavcan::CanFrame& frame, uavcan::MonotonicT
* Seeking for an empty slot
*/
uavcan::uint8_t txmailbox = 0xFF;
if ((can_->TSR & CAN_TSR_TME0) == CAN_TSR_TME0)
if ((can_->TSR & bxcan::TSR_TME0) == bxcan::TSR_TME0)
{
txmailbox = 0;
}
else if ((can_->TSR & CAN_TSR_TME1) == CAN_TSR_TME1)
else if ((can_->TSR & bxcan::TSR_TME1) == bxcan::TSR_TME1)
{
txmailbox = 1;
}
else if ((can_->TSR & CAN_TSR_TME2) == CAN_TSR_TME2)
else if ((can_->TSR & bxcan::TSR_TME2) == bxcan::TSR_TME2)
{
txmailbox = 2;
}
@@ -229,10 +258,10 @@ uavcan::int16_t CanIface::send(const uavcan::CanFrame& frame, uavcan::MonotonicT
/*
* Setting up the mailbox
*/
CAN_TxMailBox_TypeDef& mb = can_->sTxMailBox[txmailbox];
bxcan::TxMailboxType& mb = can_->TxMailbox[txmailbox];
if (frame.isExtended())
{
mb.TIR = ((frame.id & uavcan::CanFrame::MaskExtID) << 3) | CAN_TI0R_IDE;
mb.TIR = ((frame.id & uavcan::CanFrame::MaskExtID) << 3) | bxcan::TIR_IDE;
}
else
{
@@ -241,7 +270,7 @@ uavcan::int16_t CanIface::send(const uavcan::CanFrame& frame, uavcan::MonotonicT
if (frame.isRemoteTransmissionRequest())
{
mb.TIR |= CAN_TI0R_RTR;
mb.TIR |= bxcan::TIR_RTR;
}
mb.TDTR = frame.dlc;
@@ -255,7 +284,7 @@ uavcan::int16_t CanIface::send(const uavcan::CanFrame& frame, uavcan::MonotonicT
(uavcan::uint32_t(frame.data[1]) << 8) |
(uavcan::uint32_t(frame.data[0]) << 0);
mb.TIR |= CAN_TI0R_TXRQ; // Go.
mb.TIR |= bxcan::TIR_TXRQ; // Go.
/*
* Registering the pending transmission so we can track its deadline and loopback it as needed
@@ -308,50 +337,54 @@ int CanIface::init(uavcan::uint32_t bitrate)
{
goto leave;
}
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
*/
can_->MCR &= ~CAN_MCR_SLEEP; // Exit sleep mode
can_->MCR |= CAN_MCR_INRQ; // Request init
can_->MCR &= ~bxcan::MCR_SLEEP; // Exit sleep mode
can_->MCR |= bxcan::MCR_INRQ; // Request init
for (unsigned wait_ack = 0; wait_ack < 1000000; wait_ack++)
for (unsigned wait_ack = 0; wait_ack < 2000000; wait_ack++)
{
if ((can_->MSR & CAN_MSR_INAK) == CAN_MSR_INAK)
if ((can_->MSR & bxcan::MSR_INAK) == bxcan::MSR_INAK)
{
break;
}
}
if ((can_->MSR & CAN_MSR_INAK) != CAN_MSR_INAK)
if ((can_->MSR & bxcan::MSR_INAK) != bxcan::MSR_INAK)
{
UAVCAN_STM32_LOG("MSR INAK not set");
res = -1;
goto leave;
}
can_->MCR = CAN_MCR_ABOM | CAN_MCR_AWUM | CAN_MCR_INRQ; // RM page 648
can_->MCR = bxcan::MCR_ABOM | bxcan::MCR_AWUM | bxcan::MCR_INRQ; // RM page 648
can_->BTR = ((timings.sjw & 3) << 24) |
((timings.bs1 & 15) << 16) |
((timings.bs2 & 7) << 20) |
(timings.prescaler & 1023);
can_->IER = CAN_IER_TMEIE | // TX mailbox empty
CAN_IER_ERRIE | // Error set in ESR register
CAN_IER_LECIE | // LEC in ESR updated
CAN_IER_FMPIE0 | // RX FIFO 0 is not empty
CAN_IER_FMPIE1; // RX FIFO 1 is not empty
can_->IER = bxcan::IER_TMEIE | // TX mailbox empty
bxcan::IER_ERRIE | // Error set in ESR register
bxcan::IER_LECIE | // LEC in ESR updated
bxcan::IER_FMPIE0 | // RX FIFO 0 is not empty
bxcan::IER_FMPIE1; // RX FIFO 1 is not empty
can_->MCR &= ~CAN_MCR_INRQ; // Leave init mode
can_->MCR &= ~bxcan::MCR_INRQ; // Leave init mode
for (unsigned wait_ack = 0; wait_ack < 1000000; wait_ack++)
for (unsigned wait_ack = 0; wait_ack < 2000000; wait_ack++)
{
if ((can_->MSR & CAN_MSR_INAK) != CAN_MSR_INAK)
if ((can_->MSR & bxcan::MSR_INAK) != bxcan::MSR_INAK)
{
break;
}
}
if ((can_->MSR & CAN_MSR_INAK) == CAN_MSR_INAK)
if ((can_->MSR & bxcan::MSR_INAK) == bxcan::MSR_INAK)
{
UAVCAN_STM32_LOG("MSR INAK not cleared");
res = -1;
goto leave;
}
@@ -361,7 +394,7 @@ int CanIface::init(uavcan::uint32_t bitrate)
*/
if (self_index_ == 0)
{
can_->FMR |= CAN_FMR_FINIT;
can_->FMR |= bxcan::FMR_FINIT;
can_->FMR &= 0xFFFFC0F1;
can_->FMR |= static_cast<uavcan::uint32_t>(NumFilters) << 8; // Slave (CAN2) gets half of the filters
@@ -371,19 +404,19 @@ int CanIface::init(uavcan::uint32_t bitrate)
#if UAVCAN_STM32_NUM_IFACES > 1
can_->FS1R = 0x7ffffff; // Single 32-bit for all
can_->sFilterRegister[0].FR1 = 0; // CAN1 accepts everything
can_->sFilterRegister[0].FR2 = 0;
can_->sFilterRegister[NumFilters].FR1 = 0; // CAN2 accepts everything
can_->sFilterRegister[NumFilters].FR2 = 0;
can_->FilterRegister[0].FR1 = 0; // CAN1 accepts everything
can_->FilterRegister[0].FR2 = 0;
can_->FilterRegister[NumFilters].FR1 = 0; // CAN2 accepts everything
can_->FilterRegister[NumFilters].FR2 = 0;
can_->FA1R = 1 | (1 << NumFilters); // One filter per each iface
#else
can_->FS1R = 0x1fff;
can_->sFilterRegister[0].FR1 = 0;
can_->sFilterRegister[0].FR2 = 0;
can_->FilterRegister[0].FR1 = 0;
can_->FilterRegister[0].FR2 = 0;
can_->FA1R = 1;
#endif
can_->FMR &= ~CAN_FMR_FINIT;
can_->FMR &= ~bxcan::FMR_FINIT;
}
leave:
@@ -407,22 +440,22 @@ void CanIface::handleTxMailboxInterrupt(uavcan::uint8_t mailbox_index, bool txok
void CanIface::handleTxInterrupt(const uavcan::uint64_t utc_usec)
{
// TXOK == false means that there was a hardware failure
if (can_->TSR & CAN_TSR_RQCP0)
if (can_->TSR & bxcan::TSR_RQCP0)
{
const bool txok = can_->TSR & CAN_TSR_TXOK0;
can_->TSR = CAN_TSR_RQCP0;
const bool txok = can_->TSR & bxcan::TSR_TXOK0;
can_->TSR = bxcan::TSR_RQCP0;
handleTxMailboxInterrupt(0, txok, utc_usec);
}
if (can_->TSR & CAN_TSR_RQCP1)
if (can_->TSR & bxcan::TSR_RQCP1)
{
const bool txok = can_->TSR & CAN_TSR_TXOK1;
can_->TSR = CAN_TSR_RQCP1;
const bool txok = can_->TSR & bxcan::TSR_TXOK1;
can_->TSR = bxcan::TSR_RQCP1;
handleTxMailboxInterrupt(1, txok, utc_usec);
}
if (can_->TSR & CAN_TSR_RQCP2)
if (can_->TSR & bxcan::TSR_RQCP2)
{
const bool txok = can_->TSR & CAN_TSR_TXOK2;
can_->TSR = CAN_TSR_RQCP2;
const bool txok = can_->TSR & bxcan::TSR_TXOK2;
can_->TSR = bxcan::TSR_RQCP2;
handleTxMailboxInterrupt(2, txok, utc_usec);
}
update_event_.signalFromInterrupt();
@@ -433,7 +466,7 @@ void CanIface::handleRxInterrupt(uavcan::uint8_t fifo_index, uavcan::uint64_t ut
assert(fifo_index < 2);
volatile uavcan::uint32_t* const rfr_reg = (fifo_index == 0) ? &can_->RF0R : &can_->RF1R;
if ((*rfr_reg & CAN_RF0R_FMP0) == 0)
if ((*rfr_reg & bxcan::RFR_FMP_MASK) == 0)
{
assert(0); // Weird, IRQ is here but no data to read
return;
@@ -442,7 +475,7 @@ void CanIface::handleRxInterrupt(uavcan::uint8_t fifo_index, uavcan::uint64_t ut
/*
* Register overflow as a hardware error
*/
if ((*rfr_reg & CAN_RF0R_FOVR0) != 0)
if ((*rfr_reg & bxcan::RFR_FOVR) != 0)
{
error_cnt_++;
}
@@ -451,9 +484,9 @@ void CanIface::handleRxInterrupt(uavcan::uint8_t fifo_index, uavcan::uint64_t ut
* Read the frame contents
*/
uavcan::CanFrame frame;
const CAN_FIFOMailBox_TypeDef& rf = can_->sFIFOMailBox[fifo_index];
const bxcan::RxMailboxType& rf = can_->RxMailbox[fifo_index];
if ((rf.RIR & CAN_RI0R_IDE) == 0)
if ((rf.RIR & bxcan::RIR_IDE) == 0)
{
frame.id = uavcan::CanFrame::MaskStdID & (rf.RIR >> 21);
}
@@ -463,7 +496,7 @@ void CanIface::handleRxInterrupt(uavcan::uint8_t fifo_index, uavcan::uint64_t ut
frame.id |= uavcan::CanFrame::FlagEFF;
}
if ((rf.RIR & CAN_RI0R_RTR) != 0)
if ((rf.RIR & bxcan::RIR_RTR) != 0)
{
frame.id |= uavcan::CanFrame::FlagRTR;
}
@@ -479,7 +512,7 @@ void CanIface::handleRxInterrupt(uavcan::uint8_t fifo_index, uavcan::uint64_t ut
frame.data[6] = 0xFF & (rf.RDHR >> 16);
frame.data[7] = 0xFF & (rf.RDHR >> 24);
*rfr_reg = CAN_RF0R_RFOM0 | CAN_RF0R_FOVR0 | CAN_RF0R_FULL0; // Release FIFO entry we just read
*rfr_reg = bxcan::RFR_RFOM | bxcan::RFR_FOVR | bxcan::RFR_FULL; // Release FIFO entry we just read
/*
* Store with timeout into the FIFO buffer and signal update event
@@ -491,15 +524,15 @@ void CanIface::handleRxInterrupt(uavcan::uint8_t fifo_index, uavcan::uint64_t ut
void CanIface::handleStatusInterrupt()
{
last_hw_error_code_ = (can_->ESR & CAN_ESR_LEC) >> 4;
last_hw_error_code_ = (can_->ESR & bxcan::ESR_LEC_MASK) >> bxcan::ESR_LEC_SHIFT;
can_->ESR = 0;
can_->MSR = CAN_MSR_ERRI | CAN_MSR_WKUI | CAN_MSR_SLAKI;
can_->MSR = bxcan::MSR_ERRI | bxcan::MSR_WKUI | bxcan::MSR_SLAKI;
error_cnt_++;
}
void CanIface::discardTimedOutTxMailboxes(uavcan::MonotonicTime current_time)
{
static const uavcan::uint32_t AbortFlags[NumTxMailboxes] = { CAN_TSR_ABRQ0, CAN_TSR_ABRQ1, CAN_TSR_ABRQ2 };
static const uavcan::uint32_t AbortFlags[NumTxMailboxes] = { bxcan::TSR_ABRQ0, bxcan::TSR_ABRQ1, bxcan::TSR_ABRQ2 };
CriticalSectionLocker lock;
for (int i = 0; i < NumTxMailboxes; i++)
{
@@ -515,7 +548,7 @@ void CanIface::discardTimedOutTxMailboxes(uavcan::MonotonicTime current_time)
bool CanIface::isTxBufferFull() const
{
return (can_->TSR & CAN_TSR_TME) == 0; // Interrupts enabled
return (can_->TSR & (bxcan::TSR_TME0 | bxcan::TSR_TME1 | bxcan::TSR_TME2)) == 0; // Interrupts enabled
}
bool CanIface::isRxBufferEmpty() const
@@ -601,18 +634,28 @@ int CanDriver::init(uavcan::uint32_t bitrate)
{
int res = 0;
UAVCAN_STM32_LOG("Bitrate %lu", static_cast<unsigned long>(bitrate));
CriticalSectionLocker lock;
/*
* CAN1
*/
#if UAVCAN_STM32_NUTTX
modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_CAN1EN);
modifyreg32(STM32_RCC_APB1RSTR, 0, RCC_APB1RSTR_CAN1RST);
modifyreg32(STM32_RCC_APB1RSTR, RCC_APB1RSTR_CAN1RST, 0);
#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);
if (res < 0)
{
UAVCAN_STM32_LOG("Iface 0 init failed %i", res);
goto fail;
}
ifaces[0] = &if0_;
@@ -621,13 +664,21 @@ int CanDriver::init(uavcan::uint32_t bitrate)
* CAN2
*/
#if UAVCAN_STM32_NUM_IFACES > 1
# 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
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);
if (res < 0)
{
UAVCAN_STM32_LOG("Iface 1 init failed %i", res);
goto fail;
}
ifaces[1] = &if1_;
@@ -636,27 +687,54 @@ int CanDriver::init(uavcan::uint32_t bitrate)
/*
* IRQ
*/
#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; \
} \
up_enable_irq(irq); \
}
IRQ_ATTACH(STM32_IRQ_CAN1TX, can1_irq);
IRQ_ATTACH(STM32_IRQ_CAN1RX0, can1_irq);
IRQ_ATTACH(STM32_IRQ_CAN1RX1, can1_irq);
IRQ_ATTACH(STM32_IRQ_CAN1SCE, can1_irq);
# if UAVCAN_STM32_NUM_IFACES > 1
IRQ_ATTACH(STM32_IRQ_CAN2TX, can2_irq);
IRQ_ATTACH(STM32_IRQ_CAN2RX0, can2_irq);
IRQ_ATTACH(STM32_IRQ_CAN2RX1, can2_irq);
IRQ_ATTACH(STM32_IRQ_CAN2SCE, can2_irq);
# endif
# undef IRQ_ATTACH
#else
nvicEnableVector(CAN1_TX_IRQn, UAVCAN_STM32_IRQ_PRIORITY_MASK);
nvicEnableVector(CAN1_RX0_IRQn, UAVCAN_STM32_IRQ_PRIORITY_MASK);
nvicEnableVector(CAN1_RX1_IRQn, UAVCAN_STM32_IRQ_PRIORITY_MASK);
nvicEnableVector(CAN1_SCE_IRQn, UAVCAN_STM32_IRQ_PRIORITY_MASK);
#if UAVCAN_STM32_NUM_IFACES > 1
# if UAVCAN_STM32_NUM_IFACES > 1
nvicEnableVector(CAN2_TX_IRQn, UAVCAN_STM32_IRQ_PRIORITY_MASK);
nvicEnableVector(CAN2_RX0_IRQn, UAVCAN_STM32_IRQ_PRIORITY_MASK);
nvicEnableVector(CAN2_RX1_IRQn, UAVCAN_STM32_IRQ_PRIORITY_MASK);
nvicEnableVector(CAN2_SCE_IRQn, UAVCAN_STM32_IRQ_PRIORITY_MASK);
# endif
#endif
UAVCAN_STM32_LOG("CAN drv init OK");
assert(res >= 0);
return res;
fail:
UAVCAN_STM32_LOG("CAN drv init failed %i", res);
assert(res < 0);
RCC->APB1ENR &= ~RCC_APB1ENR_CAN1EN;
#if UAVCAN_STM32_NUM_IFACES > 1
RCC->APB1ENR &= ~RCC_APB1ENR_CAN2EN;
#if UAVCAN_STM32_NUTTX
// TODO: Unattach and disable all IRQs
modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_CAN1EN | RCC_APB1ENR_CAN2EN, 0);
#else
RCC->APB1ENR &= ~(RCC_APB1ENR_CAN1EN | RCC_APB1ENR_CAN2EN);
#endif
return res;
}
@@ -687,6 +765,63 @@ bool CanDriver::hadActivity()
extern "C"
{
#if UAVCAN_STM32_NUTTX
static int can1_irq(const int irq, void*)
{
if (irq == STM32_IRQ_CAN1TX)
{
uavcan_stm32::handleTxInterrupt(0);
}
else if (irq == STM32_IRQ_CAN1RX0)
{
uavcan_stm32::handleRxInterrupt(0, 0);
}
else if (irq == STM32_IRQ_CAN1RX1)
{
uavcan_stm32::handleRxInterrupt(0, 1);
}
else if (irq == STM32_IRQ_CAN1SCE)
{
uavcan_stm32::handleStatusInterrupt(0);
}
else
{
PANIC();
}
return 0;
}
# if UAVCAN_STM32_NUM_IFACES > 1
static int can2_irq(const int irq, void*)
{
if (irq == STM32_IRQ_CAN2TX)
{
uavcan_stm32::handleTxInterrupt(1);
}
else if (irq == STM32_IRQ_CAN2RX0)
{
uavcan_stm32::handleRxInterrupt(1, 0);
}
else if (irq == STM32_IRQ_CAN2RX1)
{
uavcan_stm32::handleRxInterrupt(1, 1);
}
else if (irq == STM32_IRQ_CAN2SCE)
{
uavcan_stm32::handleStatusInterrupt(1);
}
else
{
PANIC();
}
return 0;
}
# endif
#else // UAVCAN_STM32_NUTTX
UAVCAN_STM32_IRQ_HANDLER(CAN1_TX_IRQHandler)
{
UAVCAN_STM32_IRQ_PROLOGUE();
@@ -715,7 +850,7 @@ UAVCAN_STM32_IRQ_HANDLER(CAN1_SCE_IRQHandler)
UAVCAN_STM32_IRQ_EPILOGUE();
}
#if UAVCAN_STM32_NUM_IFACES > 1
# if UAVCAN_STM32_NUM_IFACES > 1
UAVCAN_STM32_IRQ_HANDLER(CAN2_TX_IRQHandler)
{
@@ -745,6 +880,7 @@ UAVCAN_STM32_IRQ_HANDLER(CAN2_SCE_IRQHandler)
UAVCAN_STM32_IRQ_EPILOGUE();
}
#endif
# endif
#endif // UAVCAN_STM32_NUTTX
} // extern "C"
@@ -2,12 +2,15 @@
* Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
*/
#include <cassert>
#include <cmath>
#include <uavcan_stm32/clock.hpp>
#include <uavcan_stm32/thread.hpp>
#include "internal.hpp"
#if UAVCAN_STM32_TIMER_NUMBER
#include <cassert>
#include <cmath>
/*
* Timer instance
*/
@@ -338,3 +341,5 @@ UAVCAN_STM32_IRQ_HANDLER(TIMX_IRQHandler)
UAVCAN_STM32_IRQ_EPILOGUE();
}
#endif
@@ -54,6 +54,49 @@ void Mutex::unlock()
chibios_rt::BaseThread::unlockMutex();
}
#elif UAVCAN_STM32_NUTTX
Event::Event()
: sem_()
{
(void)sem_init(&sem_, 0, 0);
}
bool Event::wait(uavcan::MonotonicDuration duration)
{
if (duration.isNegative())
{
duration = uavcan::MonotonicDuration();
}
timespec deadline = timespec();
if (clock_gettime(CLOCK_REALTIME, &deadline) < 0)
{
ASSERT(0);
return false;
}
deadline.tv_sec += duration.toUSec() / 1000000;
deadline.tv_nsec += (duration.toUSec() % 1000000) * 1000;
if (deadline.tv_nsec >= 1000000000L)
{
deadline.tv_sec += 1;
deadline.tv_nsec -= 1000000000L;
}
const int result = sem_timedwait(&sem_, &deadline);
return result >= 0;
}
void Event::signal()
{
(void)sem_post(&sem_);
}
void Event::signalFromInterrupt()
{
(void)sem_post(&sem_); // Can be called from ISR http://nuttx.org/Documentation/NuttxUserGuide.html#sempost
}
#endif
}
@@ -19,7 +19,8 @@ UDEFS = -DUAVCAN_STM32_CHIBIOS=1 \
-DUAVCAN_MEM_POOL_BLOCK_SIZE=56 \
-DUAVCAN_TOSTRING=0 \
-DUAVCAN_EXCEPTIONS=0 \
-DUAVCAN_TINY=1
-DUAVCAN_TINY=1 \
-DUAVCAN_STM32_NUM_IFACES=2
include ../../../libuavcan/include.mk
CPPSRC += $(LIBUAVCAN_SRC)