diff --git a/os/hal/include/can.h b/os/hal/include/can.h index 1d8492d28..a62aba3da 100644 --- a/os/hal/include/can.h +++ b/os/hal/include/can.h @@ -62,9 +62,9 @@ /** @} */ /** - * @brief Special TX mailbox identifier. + * @brief Special mailbox identifier. */ -#define CAN_ANY_TX_MAILBOX 0 +#define CAN_ANY_MAILBOX 0 /*===========================================================================*/ /* Driver pre-compile time settings. */ diff --git a/os/hal/platforms/STM32/can_lld.c b/os/hal/platforms/STM32/can_lld.c index 89d1b25ac..456e3e53a 100644 --- a/os/hal/platforms/STM32/can_lld.c +++ b/os/hal/platforms/STM32/can_lld.c @@ -172,16 +172,31 @@ static void can_lld_rx0_handler(CANDriver *canp) { /** * @brief Common RX1 ISR handler. - * @note Not used, must not be invoked, defaulted to an halt. * * @param[in] canp pointer to the @p CANDriver object * * @notapi */ static void can_lld_rx1_handler(CANDriver *canp) { + uint32_t rf1r; - (void)canp; - chSysHalt(); + rf1r = canp->can->RF1R; + if ((rf1r & CAN_RF1R_FMP1) > 0) { + /* No more receive events until the queue 0 has been emptied.*/ + canp->can->IER &= ~CAN_IER_FMPIE1; + chSysLockFromIsr(); + while (chSemGetCounterI(&canp->rxsem) < 0) + chSemSignalI(&canp->rxsem); + chEvtBroadcastFlagsI(&canp->rxfull_event, CAN_MAILBOX_TO_MASK(1)); + chSysUnlockFromIsr(); + } + if ((rf1r & CAN_RF1R_FOVR1) > 0) { + /* Overflow events handling.*/ + canp->can->RF1R = CAN_RF1R_FOVR1; + chSysLockFromIsr(); + chEvtBroadcastFlagsI(&canp->error_event, CAN_OVERFLOW_ERROR); + chSysUnlockFromIsr(); + } } /** @@ -467,7 +482,7 @@ void can_lld_stop(CANDriver *canp) { * @brief Determines whether a frame can be transmitted. * * @param[in] canp pointer to the @p CANDriver object - * @param[in] mailbox mailbox number, @p CAN_ANY_TX_MAILBOX for any mailbox + * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox * * @return The queue space availability. * @retval FALSE no space in the transmit queue. @@ -478,7 +493,7 @@ void can_lld_stop(CANDriver *canp) { bool_t can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox) { switch (mailbox) { - case CAN_ANY_TX_MAILBOX: + case CAN_ANY_MAILBOX: return (canp->can->TSR & CAN_TSR_TME) != 0; case 1: return (canp->can->TSR & CAN_TSR_TME0) != 0; @@ -496,7 +511,7 @@ bool_t can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox) { * * @param[in] canp pointer to the @p CANDriver object * @param[in] ctfp pointer to the CAN frame to be transmitted - * @param[in] mailbox mailbox number, @p CAN_ANY_TX_MAILBOX for any mailbox + * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox * * @notapi */ @@ -508,7 +523,7 @@ void can_lld_transmit(CANDriver *canp, /* Pointer to a free transmission mailbox.*/ switch (mailbox) { - case CAN_ANY_TX_MAILBOX: + case CAN_ANY_MAILBOX: tmbp = &canp->can->sTxMailBox[(canp->can->TSR & CAN_TSR_CODE) >> 24]; break; case 1: @@ -540,7 +555,7 @@ void can_lld_transmit(CANDriver *canp, * @brief Determines whether a frame has been received. * * @param[in] canp pointer to the @p CANDriver object - * @param[in] mailbox mailbox number + * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox * * @return The queue space availability. * @retval FALSE no space in the transmit queue. @@ -551,10 +566,12 @@ void can_lld_transmit(CANDriver *canp, bool_t can_lld_is_rx_nonempty(CANDriver *canp, canmbx_t mailbox) { switch (mailbox) { + case CAN_ANY_MAILBOX: + return (canp->can->RF0R & (CAN_RF0R_FMP0 | CAN_RF1R_FMP1)) != 0; case 1: - return (canp->can->RF0R & CAN_RF0R_FMP0) > 0; + return (canp->can->RF0R & CAN_RF0R_FMP0) != 0; case 2: - return (canp->can->RF1R & CAN_RF1R_FMP1) > 0; + return (canp->can->RF1R & CAN_RF1R_FMP1) != 0; default: return FALSE; } @@ -564,8 +581,8 @@ bool_t can_lld_is_rx_nonempty(CANDriver *canp, canmbx_t mailbox) { * @brief Receives a frame from the input queue. * * @param[in] canp pointer to the @p CANDriver object + * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox * @param[out] crfp pointer to the buffer where the CAN frame is copied - * @param[in] mailbox mailbox number * * @notapi */ @@ -574,6 +591,16 @@ void can_lld_receive(CANDriver *canp, CANRxFrame *crfp) { uint32_t rir, rdtr; + if (mailbox == CAN_ANY_MAILBOX) { + if ((canp->can->RF0R & CAN_RF0R_FMP0) != 0) + mailbox = 1; + else if ((canp->can->RF1R & CAN_RF1R_FMP1) != 0) + mailbox = 2; + else { + /* Should not happen, do nothing.*/ + return; + } + } switch (mailbox) { case 1: /* Fetches the message.*/ @@ -606,6 +633,7 @@ void can_lld_receive(CANDriver *canp, canp->can->IER |= CAN_IER_FMPIE1; break; default: + /* Should not happen, do nothing.*/ return; } diff --git a/os/hal/src/can.c b/os/hal/src/can.c index e0d47d5c5..64aaa45c8 100644 --- a/os/hal/src/can.c +++ b/os/hal/src/can.c @@ -145,7 +145,7 @@ void canStop(CANDriver *canp) { * @note Trying to transmit while in sleep mode simply enqueues the thread. * * @param[in] canp pointer to the @p CANDriver object - * @param[in] mailbox mailbox number, @p CAN_ANY_TX_MAILBOX for any mailbox + * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox * @param[in] ctfp pointer to the CAN frame to be transmitted * @param[in] timeout the number of ticks before the operation timeouts, * the following special values are allowed: @@ -164,8 +164,7 @@ msg_t canTransmit(CANDriver *canp, const CANTxFrame *ctfp, systime_t timeout) { - chDbgCheck((canp != NULL) && (ctfp != NULL) && - (mailbox <= CAN_TX_MAILBOXES), + chDbgCheck((canp != NULL) && (ctfp != NULL) && (mailbox <= CAN_TX_MAILBOXES), "canTransmit"); chSysLock(); @@ -189,7 +188,7 @@ msg_t canTransmit(CANDriver *canp, * @note Trying to receive while in sleep mode simply enqueues the thread. * * @param[in] canp pointer to the @p CANDriver object - * @param[in] mailbox mailbox number + * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox * @param[out] crfp pointer to the buffer where the CAN frame is copied * @param[in] timeout the number of ticks before the operation timeouts, * the following special values are allowed: @@ -210,8 +209,7 @@ msg_t canReceive(CANDriver *canp, CANRxFrame *crfp, systime_t timeout) { - chDbgCheck((canp != NULL) && (crfp != NULL) && - (mailbox >= 1) && (mailbox < CAN_RX_MAILBOXES), + chDbgCheck((canp != NULL) && (crfp != NULL) && (mailbox < CAN_RX_MAILBOXES), "canReceive"); chSysLock(); diff --git a/readme.txt b/readme.txt index 76c513c19..a41f50c19 100644 --- a/readme.txt +++ b/readme.txt @@ -117,6 +117,8 @@ (backported to 2.4.3). - FIX: Fixed wrong SPI path in platform_f105_f107.mk (bug 3598151). - FIX: Fixed PHY powerdown issues not fixed (bug 3596911). +- NEW: Enhanced CAN driver model, support for mailboxes has been added. STM32 + driver implementation upgraded. - NEW: Added ADC and PWM drivers for the AT91SAM7 platform, both donated by Andrew Hannam. - NEW: Added kernel support for the SAM4L, an Atmel Studio 6 demo for the diff --git a/testhal/STM32F1xx/CAN/main.c b/testhal/STM32F1xx/CAN/main.c index 2ea6b7dec..3fbda37c8 100644 --- a/testhal/STM32F1xx/CAN/main.c +++ b/testhal/STM32F1xx/CAN/main.c @@ -29,9 +29,7 @@ static const CANConfig cancfg = { CAN_MCR_ABOM | CAN_MCR_AWUM | CAN_MCR_TXFP, CAN_BTR_LBKM | CAN_BTR_SJW(0) | CAN_BTR_TS2(1) | - CAN_BTR_TS1(8) | CAN_BTR_BRP(6), - 0, - NULL + CAN_BTR_TS1(8) | CAN_BTR_BRP(6) }; /* @@ -48,7 +46,7 @@ static msg_t can_rx(void *p) { while(!chThdShouldTerminate()) { if (chEvtWaitAnyTimeout(ALL_EVENTS, MS2ST(100)) == 0) continue; - while (canReceive(&CAND1, &rxmsg, TIME_IMMEDIATE) == RDY_OK) { + while (canReceive(&CAND1, CAN_ANY_MAILBOX, &rxmsg, TIME_IMMEDIATE) == RDY_OK) { /* Process message.*/ palTogglePad(IOPORT3, GPIOC_LED); } @@ -74,7 +72,7 @@ static msg_t can_tx(void * p) { txmsg.data32[1] = 0x00FF00FF; while (!chThdShouldTerminate()) { - canTransmit(&CAND1, &txmsg, MS2ST(100)); + canTransmit(&CAND1, CAN_ANY_MAILBOX, &txmsg, MS2ST(100)); chThdSleepMilliseconds(500); } return 0; diff --git a/testhal/STM32F30x/CAN/.project b/testhal/STM32F30x/CAN/.project index a2e4698ac..a01f8a133 100644 --- a/testhal/STM32F30x/CAN/.project +++ b/testhal/STM32F30x/CAN/.project @@ -9,6 +9,58 @@ org.eclipse.cdt.managedbuilder.core.genmakebuilder clean,full,incremental, + + ?name? + + + + org.eclipse.cdt.make.core.append_environment + true + + + org.eclipse.cdt.make.core.autoBuildTarget + all + + + org.eclipse.cdt.make.core.buildArguments + -j1 + + + org.eclipse.cdt.make.core.buildCommand + make + + + org.eclipse.cdt.make.core.cleanBuildTarget + clean + + + org.eclipse.cdt.make.core.contents + org.eclipse.cdt.make.core.activeConfigSettings + + + org.eclipse.cdt.make.core.enableAutoBuild + false + + + org.eclipse.cdt.make.core.enableCleanBuild + true + + + org.eclipse.cdt.make.core.enableFullBuild + true + + + org.eclipse.cdt.make.core.fullBuildTarget + all + + + org.eclipse.cdt.make.core.stopOnError + true + + + org.eclipse.cdt.make.core.useDefaultBuildCmd + true + diff --git a/testhal/STM32F30x/CAN/main.c b/testhal/STM32F30x/CAN/main.c index 978c31c1b..59e0c99d7 100644 --- a/testhal/STM32F30x/CAN/main.c +++ b/testhal/STM32F30x/CAN/main.c @@ -45,7 +45,7 @@ static msg_t can_rx(void *p) { while(!chThdShouldTerminate()) { if (chEvtWaitAnyTimeout(ALL_EVENTS, MS2ST(100)) == 0) continue; - while (canReceive(&CAND1, 1, &rxmsg, TIME_IMMEDIATE) == RDY_OK) { + while (canReceive(&CAND1, CAN_ANY_MAILBOX, &rxmsg, TIME_IMMEDIATE) == RDY_OK) { /* Process message.*/ palTogglePad(GPIOE, GPIOE_LED3_RED); } @@ -71,7 +71,7 @@ static msg_t can_tx(void * p) { txmsg.data32[1] = 0x00FF00FF; while (!chThdShouldTerminate()) { - canTransmit(&CAND1, CAN_ANY_TX_MAILBOX, &txmsg, MS2ST(100)); + canTransmit(&CAND1, CAN_ANY_MAILBOX, &txmsg, MS2ST(100)); chThdSleepMilliseconds(500); } return 0; diff --git a/testhal/STM32F4xx/CAN/.project b/testhal/STM32F4xx/CAN/.project index 91c2aa2ca..3c1df9502 100644 --- a/testhal/STM32F4xx/CAN/.project +++ b/testhal/STM32F4xx/CAN/.project @@ -9,6 +9,58 @@ org.eclipse.cdt.managedbuilder.core.genmakebuilder clean,full,incremental, + + ?name? + + + + org.eclipse.cdt.make.core.append_environment + true + + + org.eclipse.cdt.make.core.autoBuildTarget + all + + + org.eclipse.cdt.make.core.buildArguments + -j1 + + + org.eclipse.cdt.make.core.buildCommand + make + + + org.eclipse.cdt.make.core.cleanBuildTarget + clean + + + org.eclipse.cdt.make.core.contents + org.eclipse.cdt.make.core.activeConfigSettings + + + org.eclipse.cdt.make.core.enableAutoBuild + false + + + org.eclipse.cdt.make.core.enableCleanBuild + true + + + org.eclipse.cdt.make.core.enableFullBuild + true + + + org.eclipse.cdt.make.core.fullBuildTarget + all + + + org.eclipse.cdt.make.core.stopOnError + true + + + org.eclipse.cdt.make.core.useDefaultBuildCmd + true + diff --git a/testhal/STM32F4xx/CAN/main.c b/testhal/STM32F4xx/CAN/main.c index e095da4d5..2ff2025e0 100644 --- a/testhal/STM32F4xx/CAN/main.c +++ b/testhal/STM32F4xx/CAN/main.c @@ -56,7 +56,8 @@ static msg_t can_rx(void *p) { while(!chThdShouldTerminate()) { if (chEvtWaitAnyTimeout(ALL_EVENTS, MS2ST(100)) == 0) continue; - while (canReceive(cip->canp, 1, &rxmsg, TIME_IMMEDIATE) == RDY_OK) { + while (canReceive(cip->canp, CAN_ANY_MAILBOX, + &rxmsg, TIME_IMMEDIATE) == RDY_OK) { /* Process message.*/ palTogglePad(GPIOD, cip->led); } @@ -82,8 +83,8 @@ static msg_t can_tx(void * p) { txmsg.data32[1] = 0x00FF00FF; while (!chThdShouldTerminate()) { - canTransmit(&CAND1, CAN_ANY_TX_MAILBOX, &txmsg, MS2ST(100)); - canTransmit(&CAND2, CAN_ANY_TX_MAILBOX, &txmsg, MS2ST(100)); + canTransmit(&CAND1, CAN_ANY_MAILBOX, &txmsg, MS2ST(100)); + canTransmit(&CAND2, CAN_ANY_MAILBOX, &txmsg, MS2ST(100)); chThdSleepMilliseconds(500); } return 0;