diff --git a/os/hal/platforms/STM32/can_lld.c b/os/hal/platforms/STM32/can_lld.c index 7a9970c30..3c8a17b84 100644 --- a/os/hal/platforms/STM32/can_lld.c +++ b/os/hal/platforms/STM32/can_lld.c @@ -59,6 +59,8 @@ CH_IRQ_HANDLER(Vector8C) { /* No more events until a message is transmitted.*/ CAN1->TSR = CAN_TSR_RQCP0 | CAN_TSR_RQCP1 | CAN_TSR_RQCP2; + while (chSemGetCounterI(&CAND1.cd_txsem) < 0) + chSemSignalI(&CAND1.cd_txsem); chEvtBroadcastI(&CAND1.cd_txempty_event); CH_IRQ_EPILOGUE(); @@ -77,6 +79,8 @@ CH_IRQ_HANDLER(Vector90) { if ((rf0r & CAN_RF0R_FMP0) > 0) { /* No more receive events until the queue 0 has been emptied.*/ CAN1->IER &= ~CAN_IER_FMPIE0; + while (chSemGetCounterI(&CAND1.cd_rxsem) < 0) + chSemSignalI(&CAND1.cd_rxsem); chEvtBroadcastI(&CAND1.cd_rxfull_event); } if ((rf0r & CAN_RF0R_FOVR0) > 0) { diff --git a/os/hal/src/can.c b/os/hal/src/can.c index 3cd10126d..7359e57b7 100644 --- a/os/hal/src/can.c +++ b/os/hal/src/can.c @@ -98,6 +98,9 @@ void canStop(CANDriver *canp) { "canStop(), #1", "invalid state"); can_lld_stop(canp); + chSemResetI(&canp->cd_rxsem, 0); + chSemResetI(&canp->cd_txsem, 0); + chSchRescheduleS(); canp->cd_state = CAN_STOP; canp->cd_status = 0; chSysUnlock(); @@ -129,7 +132,7 @@ msg_t canTransmit(CANDriver *canp, const CANTxFrame *ctfp, systime_t timeout) { chDbgAssert((canp->cd_state == CAN_READY) || (canp->cd_state == CAN_SLEEP), "canTransmit(), #1", "invalid state"); - if ((canp->cd_state == CAN_SLEEP) || !can_lld_can_transmit(canp)) { + while ((canp->cd_state == CAN_SLEEP) || !can_lld_can_transmit(canp)) { msg_t msg = chSemWaitTimeoutS(&canp->cd_txsem, timeout); if (msg != RDY_OK) { chSysUnlock(); @@ -169,7 +172,7 @@ msg_t canReceive(CANDriver *canp, CANRxFrame *crfp, systime_t timeout) { chDbgAssert((canp->cd_state == CAN_READY) || (canp->cd_state == CAN_SLEEP), "canReceive(), #1", "invalid state"); - if ((canp->cd_state == CAN_SLEEP) || !can_lld_can_receive(canp)) { + while ((canp->cd_state == CAN_SLEEP) || !can_lld_can_receive(canp)) { msg_t msg = chSemWaitTimeoutS(&canp->cd_rxsem, timeout); if (msg != RDY_OK) { chSysUnlock();