12 #if UAVCAN_KINETIS_NUTTX 13 # include <nuttx/arch.h> 14 # include <nuttx/irq.h> 15 # include <arch/board/board.h> 24 static int can0_irq(
const int irq,
void *,
void *args);
25 #if UAVCAN_KINETIS_NUM_IFACES > 1 26 static int can1_irq(
const int irq,
void *,
void *args);
31 const uavcan::uint32_t
OSCERCLK = BOARD_EXTAL_FREQ;
32 const uavcan::uint32_t
busclck = BOARD_BUS_FREQ;
41 CanIface *ifaces[UAVCAN_KINETIS_NUM_IFACES] = {
43 #if UAVCAN_KINETIS_NUM_IFACES > 1 48 inline void handleTxInterrupt(
CanIface *can, uavcan::uint32_t iflags1)
50 UAVCAN_ASSERT(iface_index < UAVCAN_KINETIS_NUM_IFACES);
60 inline void handleRxInterrupt(
CanIface *can, uavcan::uint32_t iflags1)
78 if (overflow_cnt_ < 0xFFFFFFFF) {
85 buf_[in_].frame = frame;
86 buf_[in_].utc_usec = utc_usec;
87 buf_[in_].flags = flags;
90 if (in_ >= capacity_) {
96 if (len_ > capacity_) {
101 if (out_ >= capacity_) {
110 out_frame = buf_[out_].frame;
111 out_utc_usec = buf_[out_].utc_usec;
112 out_flags = buf_[out_].flags;
115 if (out_ >= capacity_) {
140 if (target_bitrate < 1) {
168 const uavcan::uint32_t nbt_prescaler =
flexcan::canclk / target_bitrate;
169 const int max_quanta_per_bit = 17;
177 for (uavcan::uint32_t prescaler = 1; prescaler < 256; prescaler++) {
178 if (prescaler > nbt_prescaler) {
182 if ((0 == nbt_prescaler % prescaler) && (nbt_prescaler / prescaler) < max_quanta_per_bit) {
188 const uavcan::uint32_t NBT = nbt_prescaler / out_timings.
prescaler;
197 uavcan::uint32_t sp = (7 * NBT) / 8;
203 return ((out_timings.
pseg1 <= 8) && (out_timings.
pseg2 <= 8) && (out_timings.
propseg <= 8)) ? 0 :
207 uavcan::int16_t
CanIface::send(
const uavcan::CanFrame &frame, uavcan::MonotonicTime tx_deadline,
208 uavcan::CanIOFlags flags)
210 if (frame.isErrorFrame() || frame.dlc > 8) {
229 CriticalSectionLocker
lock;
235 uavcan::uint32_t mbi = 0;
244 while (mbi < NumTxMesgBuffers) {
246 can_->IFLAG1 = mb_bit;
254 if (mbi == NumTxMesgBuffers) {
258 peak_tx_mailbox_index_ =
uavcan::max(peak_tx_mailbox_index_, (uavcan::uint8_t) mbi);
265 if (frame.isExtended()) {
267 mb.
ID.
ext = frame.id & uavcan::CanFrame::MaskExtID;
270 mb.
ID.
std = frame.id & uavcan::CanFrame::MaskStdID;
273 cs.
rtr = frame.isRemoteTransmissionRequest();
276 mb.
data.
b0 = frame.data[0];
277 mb.
data.
b1 = frame.data[1];
278 mb.
data.
b2 = frame.data[2];
279 mb.
data.
b3 = frame.data[3];
280 mb.
data.
b4 = frame.data[4];
281 mb.
data.
b5 = frame.data[5];
282 mb.
data.
b6 = frame.data[6];
283 mb.
data.
b7 = frame.data[7];
288 TxItem &txi = pending_tx_[mbi];
291 txi.
loopback = (flags & uavcan::CanIOFlagLoopback) != 0;
292 txi.
abort_on_error = (flags & uavcan::CanIOFlagAbortOnError) != 0;
296 can_->IMASK1 |= mb_bit;
300 uavcan::int16_t
CanIface::receive(uavcan::CanFrame &out_frame, uavcan::MonotonicTime &out_ts_monotonic,
301 uavcan::UtcTime &out_ts_utc, uavcan::CanIOFlags &out_flags)
304 uavcan::uint64_t utc_usec = 0;
306 CriticalSectionLocker
lock;
308 if (rx_queue_.getLength() == 0) {
312 rx_queue_.pop(out_frame, utc_usec, out_flags);
314 out_ts_utc = uavcan::UtcTime::fromUSec(utc_usec);
319 uavcan::uint16_t num_configs)
321 if (num_configs <= NumFilters) {
322 CriticalSectionLocker
lock;
325 if (!waitFreezeAckChange(
true)) {
333 if (num_configs == 0) {
335 for (uint8_t i = 0; i < NumFilters; i++) {
338 can_->RXIMR[i].w = 0;
344 for (uint8_t i = 0; i < NumFilters; i++) {
348 if (i < num_configs) {
350 const uavcan::CanFilterConfig *
const cfg = filter_configs + i;
352 if ((cfg->id & uavcan::CanFrame::FlagEFF) || !(cfg->mask & uavcan::CanFrame::FlagEFF)) {
354 filter.
ext = cfg->id & uavcan::CanFrame::MaskExtID;
355 mask.
ext = cfg->mask & uavcan::CanFrame::MaskExtID;
359 filter.
std = cfg->id & uavcan::CanFrame::MaskStdID;
360 mask.
std = cfg->mask & uavcan::CanFrame::MaskStdID;
363 filter.
rtr = cfg->id & uavcan::CanFrame::FlagRTR ? 1 : 0;
365 mask.
rtr = cfg->mask & uavcan::CanFrame::FlagRTR ? 1 : 0;
366 mask.
ide = cfg->mask & uavcan::CanFrame::FlagEFF ? 1 : 0;
372 filter.
w = 0xffffffff;
387 const unsigned Timeout = 1000;
389 for (
unsigned wait_ack = 0; wait_ack < Timeout; wait_ack++) {
390 const bool state = (can_->MCR & mask) != 0;
392 if (state == target_state) {
421 CriticalSectionLocker
lock;
459 can_->MB[i].mb.CS.w = 0x0;
460 can_->MB[i].mb.ID.w = 0x0;
461 can_->MB[i].mb.data.l = 0x0;
462 can_->MB[i].mb.data.h = 0x0;
468 can_->CTRL2 = flexcan::numberFIFOFilters |
474 can_->RXIMR[i].w = 0x0;
477 can_->RX14MASK = 0x3FFFFFFF;
478 can_->RX15MASK = 0x3FFFFFFF;
479 can_->RXMGMASK = 0x3FFFFFFF;
480 can_->RXFGMASK = 0x0;
489 if (!setEnable(
false)) {
501 if (!setEnable(
true)) {
512 served_aborts_cnt_ = 0;
513 uavcan::fill_n(pending_tx_, NumTxMesgBuffers,
TxItem());
514 peak_tx_mailbox_index_ = 0;
515 had_activity_ =
false;
521 const int timings_res = computeTimings(bitrate, timings);
523 if (timings_res < 0) {
531 unsigned(timings.
pseg2));
537 uavcan::int16_t rv = doReset(timings);
544 uavcan::uint32_t ctl1 = can_->CTRL1;
571 can_->RXIMR[mb].w = 0;
575 can_->IMASK1 = FIFO_IFLAG1;
583 UAVCAN_ASSERT(mailbox_index < NumTxMesgBuffers);
585 had_activity_ = had_activity_ || txok;
587 TxItem &txi = pending_tx_[mailbox_index];
590 rx_queue_.push(txi.
frame, utc_usec, uavcan::CanIOFlagLoopback);
601 uavcan::uint32_t aborts = pending_aborts_ & tx_iflags;
604 uavcan::uint32_t moreAborts = aborts;
607 for (uavcan::uint32_t mb = 0; moreAborts && mb < NumTxMesgBuffers; mb++) {
608 if (moreAborts & bit) {
611 pending_tx_[mb].pending = TxItem::free;
612 served_aborts_cnt_++;
618 tx_iflags &= ~aborts;
619 pending_aborts_ &= ~aborts;
627 for (uavcan::uint32_t mbi = 0; tx_iflags && mbi < NumTxMesgBuffers; mbi++) {
628 if (tx_iflags & mbBit) {
629 can_->IFLAG1 = mbBit;
632 handleTxMailboxInterrupt(mbi, txok, utc_usec);
638 update_event_.signalFromInterrupt();
640 pollErrorFlagsFromISR();
646 UAVCAN_ASSERT(fifo_index < 2);
648 uavcan::CanFrame frame;
650 if ((rx_iflags & FIFO_IFLAG1) == 0) {
673 frame.id = uavcan::CanFrame::MaskExtID & rf.
ID.
ext;
674 frame.id |= uavcan::CanFrame::FlagEFF;
677 frame.id = uavcan::CanFrame::MaskStdID & rf.
ID.
std;
681 frame.id |= uavcan::CanFrame::FlagRTR;
684 frame.dlc = rf.
CS.
dlc;
686 frame.data[0] = rf.
data.
b0;
687 frame.data[1] = rf.
data.
b1;
688 frame.data[2] = rf.
data.
b2;
689 frame.data[3] = rf.
data.
b3;
690 frame.data[4] = rf.
data.
b4;
691 frame.data[5] = rf.
data.
b5;
692 frame.data[6] = rf.
data.
b6;
693 frame.data[7] = rf.
data.
b7;
695 volatile uavcan::uint32_t idhit = can_->RXFIR;
698 can_->IFLAG1 = flexcan::CAN_FIFO_NE;
703 rx_queue_.push(frame, utc_usec, 0);
704 had_activity_ =
true;
705 update_event_.signalFromInterrupt();
709 pollErrorFlagsFromISR();
721 uavcan::uint32_t pending_aborts = 0;
725 for (
int i = 0; i < NumTxMesgBuffers; i++) {
726 TxItem &txi = pending_tx_[i];
728 uavcan::uint32_t iflag1 = 1 << mbi;
732 can_->IFLAG1 = iflag1;
733 pending_aborts |= iflag1;;
738 pending_aborts_ = pending_aborts;
745 CriticalSectionLocker
lock;
747 for (
int mbi = 0; mbi < NumTxMesgBuffers; mbi++) {
748 TxItem &txi = pending_tx_[mbi];
776 CriticalSectionLocker
lock;
778 for (
int mbi = 0; mbi < NumTxMesgBuffers; mbi++) {
779 if (pending_tx_[mbi].pending == TxItem::busy && !frame.priorityHigherThan(pending_tx_[mbi].frame)) {
789 CriticalSectionLocker
lock;
790 return rx_queue_.getLength() == 0;
795 CriticalSectionLocker
lock;
796 return error_cnt_ + rx_queue_.getOverflowCount();
801 CriticalSectionLocker
lock;
802 return rx_queue_.getLength();
807 CriticalSectionLocker
lock;
808 const bool ret = had_activity_;
809 had_activity_ =
false;
818 uavcan::CanSelectMasks msk;
821 msk.read = if0_.isRxBufferEmpty() ? 0 : 1;
823 if (pending_tx[0] != UAVCAN_NULLPTR) {
824 msk.write = if0_.canAcceptNewTxFrame(*pending_tx[0]) ? 1 : 0;
828 #if UAVCAN_KINETIS_NUM_IFACES > 1 830 if (!if1_.isRxBufferEmpty()) {
834 if (pending_tx[1] != UAVCAN_NULLPTR) {
835 if (if1_.canAcceptNewTxFrame(*pending_tx[1])) {
846 #if UAVCAN_KINETIS_NUM_IFACES == 1 847 return !if0_.isRxBufferEmpty();
848 #elif UAVCAN_KINETIS_NUM_IFACES == 2 849 return !if0_.isRxBufferEmpty() || !if1_.isRxBufferEmpty();
851 # error UAVCAN_KINETIS_NUM_IFACES 856 const uavcan::CanFrame * (&pending_tx)[uavcan::MaxCanIfaces],
857 const uavcan::MonotonicTime blocking_deadline)
859 const uavcan::CanSelectMasks in_masks = inout_masks;
862 if0_.discardTimedOutTxMailboxes(time);
864 CriticalSectionLocker cs_locker;
865 if0_.pollErrorFlagsFromISR();
868 #if UAVCAN_KINETIS_NUM_IFACES > 1 869 if1_.discardTimedOutTxMailboxes(time);
871 CriticalSectionLocker cs_locker;
872 if1_.pollErrorFlagsFromISR();
876 inout_masks = makeSelectMasks(pending_tx);
878 if ((inout_masks.read & in_masks.read) != 0 ||
879 (inout_masks.write & in_masks.write) != 0) {
883 (void)update_event_.wait(blocking_deadline - time);
884 inout_masks = makeSelectMasks(pending_tx);
895 CriticalSectionLocker
lock;
896 modifyreg32(KINETIS_SIM_SCGC6, 0, SIM_SCGC6_FLEXCAN0);
897 #if UAVCAN_KINETIS_NUM_IFACES > 1 898 modifyreg32(KINETIS_SIM_SCGC3, 0, SIM_SCGC3_FLEXCAN1);
905 #define IRQ_ATTACH(irq, handler) \ 907 const int res = irq_attach(irq, handler, NULL); \ 910 up_enable_irq(irq); \ 913 #if UAVCAN_KINETIS_NUM_IFACES > 1 923 UAVCAN_KINETIS_LOG(
"Bitrate %lu mode %d", static_cast<unsigned long>(bitrate), static_cast<int>(mode));
925 static bool initialized_once =
false;
927 if (!initialized_once) {
928 initialized_once =
true;
938 res = if0_.init(bitrate, mode);
942 ifaces[0] = UAVCAN_NULLPTR;
949 #if UAVCAN_KINETIS_NUM_IFACES > 1 952 res = if1_.init(bitrate, mode);
956 ifaces[1] = UAVCAN_NULLPTR;
963 UAVCAN_ASSERT(res >= 0);
968 UAVCAN_ASSERT(res < 0);
974 if (iface_index < UAVCAN_KINETIS_NUM_IFACES) {
975 return ifaces[iface_index];
978 return UAVCAN_NULLPTR;
983 bool ret = if0_.hadActivity();
984 #if UAVCAN_KINETIS_NUM_IFACES > 1 985 ret |= if1_.hadActivity();
997 static int can0_irq(
const int irq,
void *,
void *args)
1003 if (cif != UAVCAN_NULLPTR) {
1005 uavcan::uint32_t flags = flex->
IFLAG1 & FIFO_IFLAG1;
1008 handleRxInterrupt(cif, flags);
1012 flags = flex->
IFLAG1 & MB_IFLAG1;
1015 handleTxInterrupt(cif, flags);
1022 #if UAVCAN_KINETIS_NUM_IFACES > 1 1024 static int can1_irq(
const int irq,
void *,
void *)
1029 if (cif != UAVCAN_NULLPTR) {
1031 uavcan::uint32_t flags = flex->
IFLAG1 & FIFO_IFLAG1;
1034 handleRxInterrupt(cif, flags);
1038 flags = flex->
IFLAG1 & MB_IFLAG1;
1041 handleTxInterrupt(cif, flags);
void setFreeze(bool freeze_true)
uavcan::CanSelectMasks makeSelectMasks(const uavcan::CanFrame *(&pending_tx)[uavcan::MaxCanIfaces]) const
This function returns select masks indicating which interfaces are available for read/write.
constexpr unsigned long ESR1_FRMERR
constexpr unsigned long CTRL2_TASD_MASK
int init(const uavcan::uint32_t bitrate, const CanIface::OperatingMode mode)
Returns zero if OK.
bool waitMCRChange(uavcan::uint32_t mask, bool target_state)
constexpr unsigned long MCR_FRZACK
const uavcan::uint32_t canclk
#define UAVCAN_KINETIS_LOG(fmt,...)
Debug output.
void handleRxInterrupt(uavcan::uint32_t rx_iflags, uavcan::uint64_t utc_usec)
virtual uavcan::int16_t send(const uavcan::CanFrame &frame, uavcan::MonotonicTime tx_deadline, uavcan::CanIOFlags flags)
constexpr unsigned long MCR_FRZ
static const uavcan::int16_t ErrMcrFRZACKAckNotSet
MCR_FRZACK bit of the MCR register is not 1.
virtual uavcan::int16_t select(uavcan::CanSelectMasks &inout_masks, const uavcan::CanFrame *(&pending_tx)[uavcan::MaxCanIfaces], uavcan::MonotonicTime blocking_deadline)
constexpr unsigned long CTRL1_ROPSEG_SHIFT
void setMCR(uavcan::uint32_t mask, bool target_state)
constexpr unsigned long MCR_SRXDIS
bool hadActivity()
Whether this iface had at least one successful IO since the previous call of this method...
bool canAcceptNewTxFrame(const uavcan::CanFrame &frame) const
constexpr unsigned long MCR_MAXMB_MASK
constexpr unsigned long MCR_MDIS
void handleTxInterrupt(uavcan::uint32_t tx_iflags, uavcan::uint64_t utc_usec)
constexpr unsigned long CAN_FIFO_NE
bool hadActivity()
Whether at least one iface had at least one successful IO since previous call of this method...
constexpr unsigned long CTRL2_TASD_SHIFT
void discardTimedOutTxMailboxes(uavcan::MonotonicTime current_time)
uavcan::MonotonicTime deadline
constexpr unsigned long CTRL1_RJW_SHIFT
int init(const uavcan::uint32_t bitrate, const OperatingMode mode)
Initializes the hardware CAN controller.
uavcan::uint8_t prescaler
uavcan::MonotonicTime getMonotonic()
Returns current monotonic time since the moment when clock::init() was called.
constexpr unsigned long CTRL1_TWRNMSK
uavcan::uint64_t getUtcUSecFromCanInterrupt()
constexpr unsigned long CTRL1_PSEG1_SHIFT
constexpr unsigned long CTRL1_PSEG2_SHIFT
constexpr unsigned long MCR_IRMQ
constexpr unsigned long ESR1_BIT1ERR
void handleTxMailboxInterrupt(uavcan::uint8_t mailbox_index, bool txok, uavcan::uint64_t utc_usec)
enum uavcan_kinetis::CanIface::TxItem::@26 pending
constexpr unsigned long MCR_SUPV
constexpr unsigned long CTRL1_ERRMSK
static const uavcan::int16_t ErrMcrSOFTRSTNotCleared
MCR_SOFTRST bit of the MCR register is not 0.
virtual uavcan::int16_t receive(uavcan::CanFrame &out_frame, uavcan::MonotonicTime &out_ts_monotonic, uavcan::UtcTime &out_ts_utc, uavcan::CanIOFlags &out_flags)
virtual CanIface * getIface(uavcan::uint8_t iface_index)
constexpr unsigned long ESR2_IMB
const uavcan::uint32_t OSCERCLK
virtual uavcan::uint64_t getErrorCount() const
Total number of hardware failures and other kinds of errors (e.g.
constexpr unsigned long ESR1_CRCERR
const uavcan::uint32_t numberFIFOFilters
constexpr _Tp min(_Tp a, _Tp b)
constexpr unsigned long ESR1_ACKERR
const uavcan::uint8_t useFIFO
CanType *const Can[UAVCAN_KINETIS_NUM_IFACES]
CANx register sets.
unsigned getRxQueueLength() const
Returns the number of frames pending in the RX queue.
constexpr unsigned long ESR1_STFERR
void pollErrorFlagsFromISR()
This method is used to count errors and abort transmission on error if necessary. ...
static const uavcan::int16_t ErrMcrLPMAckNotSet
MCR_LPMACK bit of the MCR register is not 1.
static const uavcan::int16_t ErrUnsupportedFrame
Frame not supported (e.g. RTR, CAN FD, etc)
static const uavcan::int16_t ErrMcrFRZACKAckNotCleared
MCR_FRZACK bit of the MCR register is not 0.
constexpr _Tp max(_Tp a, _Tp b)
constexpr unsigned long CTRL2_RFFN_16MB(1U<< CTRL2_RFFN_SHIFT)
const uavcan::uint32_t busclck
constexpr unsigned long ESR2_LPTM_MASK
bool waitFreezeAckChange(bool target_state)
int computeTimings(uavcan::uint32_t target_bitrate, Timings &out_timings)
bool isRxBufferEmpty() const
constexpr unsigned long MCR_AEN
constexpr unsigned long CTRL1_RWRNMSK
#define IRQ_ATTACH(irq, handler)
static const uavcan::int16_t ErrInvalidBitRate
Bit rate not supported.
constexpr unsigned long CTRL1_LOM
constexpr unsigned long CAN_FIFO_WARN
static int can0_irq(const int irq, void *, void *args)
bool setEnable(bool enable_true)
constexpr unsigned long ESR1_BIT0ERR
constexpr unsigned long MCR_MAXMB_SHIFT
void push(const uavcan::CanFrame &frame, const uint64_t &utc_usec, uavcan::CanIOFlags flags)
static const uavcan::int16_t ErrFilterNumConfigs
Number of filters is more than supported.
uavcan::int16_t doReset(Timings timings)
constexpr unsigned long MCR_SOFTRST
constexpr unsigned long CTRL1_PRESDIV_SHIFT
virtual uavcan::int16_t configureFilters(const uavcan::CanFilterConfig *filter_configs, uavcan::uint16_t num_configs)
constexpr unsigned long MCR_WAKSRC
constexpr unsigned long ESR2_VPS
constexpr unsigned long MCR_RFEN
constexpr unsigned long MCR_WRNEN
constexpr unsigned long MCR_HALT
constexpr unsigned long CTRL2_RRS
constexpr unsigned long MCR_LPMACK
static const uavcan::int16_t ErrMcrLPMAckNotCleared
MCR_LPMACK bit of the MCR register is not 0.
void pop(uavcan::CanFrame &out_frame, uavcan::uint64_t &out_utc_usec, uavcan::CanIOFlags &out_flags)
constexpr unsigned long CTRL1_CLKSRC
constexpr unsigned long CAN_FIFO_OV
constexpr unsigned long CTRL2_EACEN
const uavcan::uint8_t CLOCKSEL
bool hasReadableInterfaces() const
Whether there's at least one interface where receive() would return a frame.
constexpr unsigned long MCR_SLFWAK
constexpr unsigned long ESR2_LPTM_SHIFT