diff --git a/libuavcan_drivers/stm32/driver/include/uavcan_stm32/bxcan.hpp b/libuavcan_drivers/stm32/driver/include/uavcan_stm32/bxcan.hpp new file mode 100644 index 0000000000..af6a168e63 --- /dev/null +++ b/libuavcan_drivers/stm32/driver/include/uavcan_stm32/bxcan.hpp @@ -0,0 +1,291 @@ +/* + * Copyright (C);2014 Pavel Kirienko + * Partly from NuttX STM32 CAN driver. + */ + +#pragma once + +#include +#include + +#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(0x40006400) +#if UAVCAN_STM32_NUM_IFACES > 1 + , + reinterpret_cast(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 diff --git a/libuavcan_drivers/stm32/driver/include/uavcan_stm32/can.hpp b/libuavcan_drivers/stm32/driver/include/uavcan_stm32/can.hpp index ae1e1226ad..3e09cf14ae 100644 --- a/libuavcan_drivers/stm32/driver/include/uavcan_stm32/can.hpp +++ b/libuavcan_drivers/stm32/driver/include/uavcan_stm32/can.hpp @@ -6,24 +6,7 @@ #include #include - -#if UAVCAN_STM32_CHIBIOS -# include -#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 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 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(); diff --git a/libuavcan_drivers/stm32/driver/include/uavcan_stm32/thread.hpp b/libuavcan_drivers/stm32/driver/include/uavcan_stm32/thread.hpp index 716c46f674..38ab49b74b 100644 --- a/libuavcan_drivers/stm32/driver/include/uavcan_stm32/thread.hpp +++ b/libuavcan_drivers/stm32/driver/include/uavcan_stm32/thread.hpp @@ -6,6 +6,9 @@ #if UAVCAN_STM32_CHIBIOS # include +#elif UAVCAN_STM32_NUTTX +# include +# include #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 + } diff --git a/libuavcan_drivers/stm32/driver/src/internal.hpp b/libuavcan_drivers/stm32/driver/src/internal.hpp index f367717e83..c9d045dbfd 100644 --- a/libuavcan_drivers/stm32/driver/src/internal.hpp +++ b/libuavcan_drivers/stm32/driver/src/internal.hpp @@ -6,13 +6,22 @@ #if UAVCAN_STM32_CHIBIOS # include +#elif UAVCAN_STM32_NUTTX +# include +# include #else # error "Unknown OS" #endif -#if UAVCAN_STM32_DEBUG -# include -# include +/** + * 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 { diff --git a/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp b/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp index 71bbb466bc..025408c565 100644 --- a/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp +++ b/libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp @@ -8,18 +8,41 @@ #include #include "internal.hpp" +#if UAVCAN_STM32_CHIBIOS +# include +#elif UAVCAN_STM32_NUTTX +# include +# include +# include +#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(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(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" diff --git a/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp b/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp index 6ab92d5238..3db8babde2 100644 --- a/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp +++ b/libuavcan_drivers/stm32/driver/src/uc_stm32_clock.cpp @@ -2,12 +2,15 @@ * Copyright (C) 2014 Pavel Kirienko */ -#include -#include #include #include #include "internal.hpp" +#if UAVCAN_STM32_TIMER_NUMBER + +#include +#include + /* * Timer instance */ @@ -338,3 +341,5 @@ UAVCAN_STM32_IRQ_HANDLER(TIMX_IRQHandler) UAVCAN_STM32_IRQ_EPILOGUE(); } + +#endif diff --git a/libuavcan_drivers/stm32/driver/src/uc_stm32_thread.cpp b/libuavcan_drivers/stm32/driver/src/uc_stm32_thread.cpp index 0c94044249..bc4c2aa6c2 100644 --- a/libuavcan_drivers/stm32/driver/src/uc_stm32_thread.cpp +++ b/libuavcan_drivers/stm32/driver/src/uc_stm32_thread.cpp @@ -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 } diff --git a/libuavcan_drivers/stm32/test_stm32f107/Makefile b/libuavcan_drivers/stm32/test_stm32f107/Makefile index eacb69a5fb..d1ee135851 100644 --- a/libuavcan_drivers/stm32/test_stm32f107/Makefile +++ b/libuavcan_drivers/stm32/test_stm32f107/Makefile @@ -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)