mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-29 20:53:33 +08:00
STM32: Proper critical in CAN driver initialization
This commit is contained in:
@@ -114,6 +114,8 @@ class CanIface : public uavcan::ICanIface, uavcan::Noncopyable
|
|||||||
|
|
||||||
void handleTxMailboxInterrupt(uavcan::uint8_t mailbox_index, bool txok, uavcan::uint64_t utc_usec);
|
void handleTxMailboxInterrupt(uavcan::uint8_t mailbox_index, bool txok, uavcan::uint64_t utc_usec);
|
||||||
|
|
||||||
|
bool waitMsrINakBitStateChange(bool target_state);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum { MaxRxQueueCapacity = 254 };
|
enum { MaxRxQueueCapacity = 254 };
|
||||||
|
|
||||||
@@ -135,7 +137,6 @@ public:
|
|||||||
* Assumes:
|
* Assumes:
|
||||||
* - Iface clock is enabled
|
* - Iface clock is enabled
|
||||||
* - Iface has been resetted via RCC
|
* - Iface has been resetted via RCC
|
||||||
* - Interrupts are disabled
|
|
||||||
* - Caller will configure NVIC by itself
|
* - Caller will configure NVIC by itself
|
||||||
*/
|
*/
|
||||||
int init(uavcan::uint32_t bitrate);
|
int init(uavcan::uint32_t bitrate);
|
||||||
|
|||||||
@@ -324,6 +324,27 @@ uavcan::int16_t CanIface::configureFilters(const uavcan::CanFilterConfig* filter
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CanIface::waitMsrINakBitStateChange(bool target_state)
|
||||||
|
{
|
||||||
|
#if UAVCAN_STM32_NUTTX
|
||||||
|
const unsigned Timeout = 500;
|
||||||
|
#else
|
||||||
|
const unsigned Timeout = 2000000;
|
||||||
|
#endif
|
||||||
|
for (unsigned wait_ack = 0; wait_ack < Timeout; wait_ack++)
|
||||||
|
{
|
||||||
|
const bool state = (can_->MSR & bxcan::MSR_INAK) != 0;
|
||||||
|
if (state == target_state)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#if UAVCAN_STM32_NUTTX
|
||||||
|
::usleep(2000);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int CanIface::init(uavcan::uint32_t bitrate)
|
int CanIface::init(uavcan::uint32_t bitrate)
|
||||||
{
|
{
|
||||||
int res = 0;
|
int res = 0;
|
||||||
@@ -346,14 +367,7 @@ int CanIface::init(uavcan::uint32_t bitrate)
|
|||||||
can_->MCR &= ~bxcan::MCR_SLEEP; // Exit sleep mode
|
can_->MCR &= ~bxcan::MCR_SLEEP; // Exit sleep mode
|
||||||
can_->MCR |= bxcan::MCR_INRQ; // Request init
|
can_->MCR |= bxcan::MCR_INRQ; // Request init
|
||||||
|
|
||||||
for (unsigned wait_ack = 0; wait_ack < 2000000; wait_ack++)
|
if (!waitMsrINakBitStateChange(true))
|
||||||
{
|
|
||||||
if ((can_->MSR & bxcan::MSR_INAK) == bxcan::MSR_INAK)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((can_->MSR & bxcan::MSR_INAK) != bxcan::MSR_INAK)
|
|
||||||
{
|
{
|
||||||
UAVCAN_STM32_LOG("MSR INAK not set");
|
UAVCAN_STM32_LOG("MSR INAK not set");
|
||||||
res = -1;
|
res = -1;
|
||||||
@@ -375,14 +389,7 @@ int CanIface::init(uavcan::uint32_t bitrate)
|
|||||||
|
|
||||||
can_->MCR &= ~bxcan::MCR_INRQ; // Leave init mode
|
can_->MCR &= ~bxcan::MCR_INRQ; // Leave init mode
|
||||||
|
|
||||||
for (unsigned wait_ack = 0; wait_ack < 2000000; wait_ack++)
|
if (!waitMsrINakBitStateChange(false))
|
||||||
{
|
|
||||||
if ((can_->MSR & bxcan::MSR_INAK) != bxcan::MSR_INAK)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((can_->MSR & bxcan::MSR_INAK) == bxcan::MSR_INAK)
|
|
||||||
{
|
{
|
||||||
UAVCAN_STM32_LOG("MSR INAK not cleared");
|
UAVCAN_STM32_LOG("MSR INAK not cleared");
|
||||||
res = -1;
|
res = -1;
|
||||||
@@ -636,20 +643,21 @@ int CanDriver::init(uavcan::uint32_t bitrate)
|
|||||||
|
|
||||||
UAVCAN_STM32_LOG("Bitrate %lu", static_cast<unsigned long>(bitrate));
|
UAVCAN_STM32_LOG("Bitrate %lu", static_cast<unsigned long>(bitrate));
|
||||||
|
|
||||||
CriticalSectionLocker lock;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CAN1
|
* CAN1
|
||||||
*/
|
*/
|
||||||
|
{
|
||||||
|
CriticalSectionLocker lock;
|
||||||
#if UAVCAN_STM32_NUTTX
|
#if UAVCAN_STM32_NUTTX
|
||||||
modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_CAN1EN);
|
modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_CAN1EN);
|
||||||
modifyreg32(STM32_RCC_APB1RSTR, 0, RCC_APB1RSTR_CAN1RST);
|
modifyreg32(STM32_RCC_APB1RSTR, 0, RCC_APB1RSTR_CAN1RST);
|
||||||
modifyreg32(STM32_RCC_APB1RSTR, RCC_APB1RSTR_CAN1RST, 0);
|
modifyreg32(STM32_RCC_APB1RSTR, RCC_APB1RSTR_CAN1RST, 0);
|
||||||
#else
|
#else
|
||||||
RCC->APB1ENR |= RCC_APB1ENR_CAN1EN;
|
RCC->APB1ENR |= RCC_APB1ENR_CAN1EN;
|
||||||
RCC->APB1RSTR |= RCC_APB1RSTR_CAN1RST;
|
RCC->APB1RSTR |= RCC_APB1RSTR_CAN1RST;
|
||||||
RCC->APB1RSTR &= ~RCC_APB1RSTR_CAN1RST;
|
RCC->APB1RSTR &= ~RCC_APB1RSTR_CAN1RST;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
UAVCAN_STM32_LOG("Initing iface 0...");
|
UAVCAN_STM32_LOG("Initing iface 0...");
|
||||||
res = if0_.init(bitrate);
|
res = if0_.init(bitrate);
|
||||||
@@ -664,15 +672,18 @@ int CanDriver::init(uavcan::uint32_t bitrate)
|
|||||||
* CAN2
|
* CAN2
|
||||||
*/
|
*/
|
||||||
#if UAVCAN_STM32_NUM_IFACES > 1
|
#if UAVCAN_STM32_NUM_IFACES > 1
|
||||||
|
{
|
||||||
|
CriticalSectionLocker lock;
|
||||||
# if UAVCAN_STM32_NUTTX
|
# if UAVCAN_STM32_NUTTX
|
||||||
modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_CAN2EN);
|
modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_CAN2EN);
|
||||||
modifyreg32(STM32_RCC_APB1RSTR, 0, RCC_APB1RSTR_CAN2RST);
|
modifyreg32(STM32_RCC_APB1RSTR, 0, RCC_APB1RSTR_CAN2RST);
|
||||||
modifyreg32(STM32_RCC_APB1RSTR, RCC_APB1RSTR_CAN2RST, 0);
|
modifyreg32(STM32_RCC_APB1RSTR, RCC_APB1RSTR_CAN2RST, 0);
|
||||||
# else
|
# else
|
||||||
RCC->APB1ENR |= RCC_APB1ENR_CAN2EN;
|
RCC->APB1ENR |= RCC_APB1ENR_CAN2EN;
|
||||||
RCC->APB1RSTR |= RCC_APB1RSTR_CAN2RST;
|
RCC->APB1RSTR |= RCC_APB1RSTR_CAN2RST;
|
||||||
RCC->APB1RSTR &= ~RCC_APB1RSTR_CAN2RST;
|
RCC->APB1RSTR &= ~RCC_APB1RSTR_CAN2RST;
|
||||||
#endif
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
UAVCAN_STM32_LOG("Initing iface 1...");
|
UAVCAN_STM32_LOG("Initing iface 1...");
|
||||||
res = if1_.init(bitrate);
|
res = if1_.init(bitrate);
|
||||||
@@ -710,16 +721,19 @@ int CanDriver::init(uavcan::uint32_t bitrate)
|
|||||||
# endif
|
# endif
|
||||||
# undef IRQ_ATTACH
|
# undef IRQ_ATTACH
|
||||||
#else
|
#else
|
||||||
nvicEnableVector(CAN1_TX_IRQn, UAVCAN_STM32_IRQ_PRIORITY_MASK);
|
{
|
||||||
nvicEnableVector(CAN1_RX0_IRQn, UAVCAN_STM32_IRQ_PRIORITY_MASK);
|
CriticalSectionLocker lock;
|
||||||
nvicEnableVector(CAN1_RX1_IRQn, UAVCAN_STM32_IRQ_PRIORITY_MASK);
|
nvicEnableVector(CAN1_TX_IRQn, UAVCAN_STM32_IRQ_PRIORITY_MASK);
|
||||||
nvicEnableVector(CAN1_SCE_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_TX_IRQn, UAVCAN_STM32_IRQ_PRIORITY_MASK);
|
||||||
nvicEnableVector(CAN2_RX0_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_RX1_IRQn, UAVCAN_STM32_IRQ_PRIORITY_MASK);
|
||||||
nvicEnableVector(CAN2_SCE_IRQn, UAVCAN_STM32_IRQ_PRIORITY_MASK);
|
nvicEnableVector(CAN2_SCE_IRQn, UAVCAN_STM32_IRQ_PRIORITY_MASK);
|
||||||
# endif
|
# endif
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
UAVCAN_STM32_LOG("CAN drv init OK");
|
UAVCAN_STM32_LOG("CAN drv init OK");
|
||||||
@@ -730,6 +744,8 @@ fail:
|
|||||||
UAVCAN_STM32_LOG("CAN drv init failed %i", res);
|
UAVCAN_STM32_LOG("CAN drv init failed %i", res);
|
||||||
assert(res < 0);
|
assert(res < 0);
|
||||||
|
|
||||||
|
CriticalSectionLocker lock;
|
||||||
|
|
||||||
#if UAVCAN_STM32_NUTTX
|
#if UAVCAN_STM32_NUTTX
|
||||||
// TODO: Unattach and disable all IRQs
|
// TODO: Unattach and disable all IRQs
|
||||||
modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_CAN1EN, 0);
|
modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_CAN1EN, 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user