Skip to content

Commit 3050d0a

Browse files
STM32: Fixed IRQ race condition in CAN controller initialization
1 parent 5bd641a commit 3050d0a

1 file changed

Lines changed: 10 additions & 5 deletions

File tree

libuavcan_drivers/stm32/driver/src/uc_stm32_can.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,7 @@ int CanIface::init(const uavcan::uint32_t bitrate, const OperatingMode mode)
506506
if (!waitMsrINakBitStateChange(true))
507507
{
508508
UAVCAN_STM32_LOG("MSR INAK not set");
509+
can_->MCR = bxcan::MCR_RESET;
509510
return -ErrMsrInakNotSet;
510511
}
511512

@@ -527,6 +528,7 @@ int CanIface::init(const uavcan::uint32_t bitrate, const OperatingMode mode)
527528
const int timings_res = computeTimings(bitrate, timings);
528529
if (timings_res < 0)
529530
{
531+
can_->MCR = bxcan::MCR_RESET;
530532
return timings_res;
531533
}
532534
UAVCAN_STM32_LOG("Timings: presc=%u sjw=%u bs1=%u bs2=%u",
@@ -549,11 +551,12 @@ int CanIface::init(const uavcan::uint32_t bitrate, const OperatingMode mode)
549551
bxcan::IER_ERRIE | // General error IRQ
550552
bxcan::IER_LECIE; // Last error code change
551553

552-
can_->MCR &= ~bxcan::MCR_INRQ; // Leave init mode
554+
can_->MCR &= ~bxcan::MCR_INRQ; // Leave init mode
553555

554556
if (!waitMsrINakBitStateChange(false))
555557
{
556558
UAVCAN_STM32_LOG("MSR INAK not cleared");
559+
can_->MCR = bxcan::MCR_RESET;
557560
return -ErrMsrInakNotCleared;
558561
}
559562

@@ -971,26 +974,28 @@ int CanDriver::init(const uavcan::uint32_t bitrate, const CanIface::OperatingMod
971974
* CAN1
972975
*/
973976
UAVCAN_STM32_LOG("Initing iface 0...");
974-
res = if0_.init(bitrate, mode);
975-
if (res < 0)
977+
ifaces[0] = &if0_; // This link must be initialized first,
978+
res = if0_.init(bitrate, mode); // otherwise an IRQ may fire while the interface is not linked yet;
979+
if (res < 0) // a typical race condition.
976980
{
977981
UAVCAN_STM32_LOG("Iface 0 init failed %i", res);
982+
ifaces[0] = NULL;
978983
goto fail;
979984
}
980-
ifaces[0] = &if0_;
981985

982986
/*
983987
* CAN2
984988
*/
985989
#if UAVCAN_STM32_NUM_IFACES > 1
986990
UAVCAN_STM32_LOG("Initing iface 1...");
991+
ifaces[1] = &if1_; // Same thing here.
987992
res = if1_.init(bitrate, mode);
988993
if (res < 0)
989994
{
990995
UAVCAN_STM32_LOG("Iface 1 init failed %i", res);
996+
ifaces[1] = NULL;
991997
goto fail;
992998
}
993-
ifaces[1] = &if1_;
994999
#endif
9951000

9961001
UAVCAN_STM32_LOG("CAN drv init OK");

0 commit comments

Comments
 (0)