mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-15 07:23:35 +08:00
STM32 NuttX support. Doesn't work though, hardfaults in IRQ handler.
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user