diff --git a/os/hal/platforms/STM32/can_lld.c b/os/hal/platforms/STM32/can_lld.c
index 0b4a918db..75de38353 100644
--- a/os/hal/platforms/STM32/can_lld.c
+++ b/os/hal/platforms/STM32/can_lld.c
@@ -39,11 +39,16 @@
/* Driver exported variables. */
/*===========================================================================*/
-/** @brief ADC1 driver identifier.*/
+/** @brief CAN1 driver identifier.*/
#if STM32_CAN_USE_CAN1 || defined(__DOXYGEN__)
CANDriver CAND1;
#endif
+/** @brief CAN2 driver identifier.*/
+#if STM32_CAN_USE_CAN2 || defined(__DOXYGEN__)
+CANDriver CAND2;
+#endif
+
/*===========================================================================*/
/* Driver local variables. */
/*===========================================================================*/
@@ -52,10 +57,176 @@ CANDriver CAND1;
/* Driver local functions. */
/*===========================================================================*/
+/**
+ * @brief Programs the filters.
+ *
+ * @param[in] can2sb number of the first filter assigned to CAN2
+ * @param[in] num number of entries in the filters array, if zero then
+ * a default filter is programmed
+ * @param[in] cfp pointer to the filters array, can be @p NULL if
+ * (num == 0)
+ *
+ * @notapi
+ */
+static void can_lld_set_filters(uint32_t can2sb,
+ uint32_t num,
+ const CANFilter *cfp) {
+
+ /* Temporarily enabling CAN1 clock.*/
+ rccEnableCAN1(FALSE);
+
+ /* Filters initialization.*/
+ CAN1->FMR = (CAN1->FMR & 0xFFFF0000) | (can2sb << 8) | CAN_FMR_FINIT;
+ if (num > 0) {
+ uint32_t i, fmask;
+
+ /* All filters cleared.*/
+ CAN1->FA1R = 0;
+ CAN1->FM1R = 0;
+ CAN1->FS1R = 0;
+ CAN1->FFA1R = 0;
+ for (i = 0; i < STM32_CAN_MAX_FILTERS; i++) {
+ CAN1->sFilterRegister[i].FR1 = 0;
+ CAN1->sFilterRegister[i].FR2 = 0;
+ }
+
+ /* Scanning the filters array.*/
+ for (i = 0; i < num; i++) {
+ fmask = 1 << cfp->filter;
+ if (cfp->mode)
+ CAN1->FM1R |= fmask;
+ if (cfp->scale)
+ CAN1->FS1R |= fmask;
+ if (cfp->assignment)
+ CAN1->FFA1R |= fmask;
+ CAN1->sFilterRegister[cfp->filter].FR1 = cfp->register1;
+ CAN1->sFilterRegister[cfp->filter].FR2 = cfp->register2;
+ CAN1->FA1R |= fmask;
+ cfp++;
+ }
+ }
+ else {
+ /* Setting up a single default filter that enables everything for both
+ CANs.*/
+ CAN1->sFilterRegister[0].FR1 = 0;
+ CAN1->sFilterRegister[0].FR2 = 0;
+ CAN1->sFilterRegister[can2sb].FR1 = 0;
+ CAN1->sFilterRegister[can2sb].FR2 = 0;
+ CAN1->FM1R = 0;
+ CAN1->FFA1R = 0;
+ CAN1->FS1R = 1 | (1 << can2sb);
+ CAN1->FA1R = 1 | (1 << can2sb);
+ }
+ CAN1->FMR &= ~CAN_FMR_FINIT;
+
+ /* Clock disabled, it will be enabled again in can_lld_start().*/
+ rccDisableCAN1(FALSE);
+}
+
+/**
+ * @brief Common TX ISR handler.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ *
+ * @notapi
+ */
+static void can_lld_tx_handler(CANDriver *canp) {
+
+ /* No more events until a message is transmitted.*/
+ canp->can->TSR = CAN_TSR_RQCP0 | CAN_TSR_RQCP1 | CAN_TSR_RQCP2;
+ chSysLockFromIsr();
+ while (chSemGetCounterI(&canp->txsem) < 0)
+ chSemSignalI(&canp->txsem);
+ chEvtBroadcastI(&canp->txempty_event);
+ chSysUnlockFromIsr();
+}
+
+/**
+ * @brief Common RX0 ISR handler.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ *
+ * @notapi
+ */
+static void can_lld_rx0_handler(CANDriver *canp) {
+ uint32_t rf0r;
+
+ rf0r = canp->can->RF0R;
+ if ((rf0r & CAN_RF0R_FMP0) > 0) {
+ /* No more receive events until the queue 0 has been emptied.*/
+ canp->can->IER &= ~CAN_IER_FMPIE0;
+ chSysLockFromIsr();
+ while (chSemGetCounterI(&canp->rxsem) < 0)
+ chSemSignalI(&canp->rxsem);
+ chEvtBroadcastI(&canp->rxfull_event);
+ chSysUnlockFromIsr();
+ }
+ if ((rf0r & CAN_RF0R_FOVR0) > 0) {
+ /* Overflow events handling.*/
+ canp->can->RF0R = CAN_RF0R_FOVR0;
+ chSysLockFromIsr();
+ chEvtBroadcastFlagsI(&canp->error_event, CAN_OVERFLOW_ERROR);
+ chSysUnlockFromIsr();
+ }
+}
+
+/**
+ * @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) {
+
+ (void)canp;
+ chSysHalt();
+}
+
+/**
+ * @brief Common SCE ISR handler.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ *
+ * @notapi
+ */
+static void can_lld_sce_handler(CANDriver *canp) {
+ uint32_t msr;
+
+ msr = canp->can->MSR;
+ canp->can->MSR = CAN_MSR_ERRI | CAN_MSR_WKUI | CAN_MSR_SLAKI;
+ /* Wakeup event.*/
+ if (msr & CAN_MSR_WKUI) {
+ canp->state = CAN_READY;
+ canp->can->MCR &= ~CAN_MCR_SLEEP;
+ chSysLockFromIsr();
+ chEvtBroadcastI(&canp->wakeup_event);
+ chSysUnlockFromIsr();
+ }
+ /* Error event.*/
+ if (msr & CAN_MSR_ERRI) {
+ flagsmask_t flags;
+ uint32_t esr = canp->can->ESR;
+
+ canp->can->ESR &= ~CAN_ESR_LEC;
+ flags = (flagsmask_t)(esr & 7);
+ if ((esr & CAN_ESR_LEC) > 0)
+ flags |= CAN_FRAMING_ERROR;
+
+ chSysLockFromIsr();
+ /* The content of the ESR register is copied unchanged in the upper
+ half word of the listener flags mask.*/
+ chEvtBroadcastFlagsI(&canp->error_event, flags | (flagsmask_t)(esr < 16));
+ chSysUnlockFromIsr();
+ }
+}
+
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
+#if STM32_CAN_USE_CAN1 || defined(__DOXYGEN__)
/**
* @brief CAN1 TX interrupt handler.
*
@@ -65,13 +236,7 @@ CH_IRQ_HANDLER(STM32_CAN1_TX_HANDLER) {
CH_IRQ_PROLOGUE();
- /* No more events until a message is transmitted.*/
- CAN1->TSR = CAN_TSR_RQCP0 | CAN_TSR_RQCP1 | CAN_TSR_RQCP2;
- chSysLockFromIsr();
- while (chSemGetCounterI(&CAND1.txsem) < 0)
- chSemSignalI(&CAND1.txsem);
- chEvtBroadcastI(&CAND1.txempty_event);
- chSysUnlockFromIsr();
+ can_lld_tx_handler(&CAND1);
CH_IRQ_EPILOGUE();
}
@@ -82,27 +247,10 @@ CH_IRQ_HANDLER(STM32_CAN1_TX_HANDLER) {
* @isr
*/
CH_IRQ_HANDLER(STM32_CAN1_RX0_HANDLER) {
- uint32_t rf0r;
CH_IRQ_PROLOGUE();
- rf0r = CAN1->RF0R;
- if ((rf0r & CAN_RF0R_FMP0) > 0) {
- /* No more receive events until the queue 0 has been emptied.*/
- CAN1->IER &= ~CAN_IER_FMPIE0;
- chSysLockFromIsr();
- while (chSemGetCounterI(&CAND1.rxsem) < 0)
- chSemSignalI(&CAND1.rxsem);
- chEvtBroadcastI(&CAND1.rxfull_event);
- chSysUnlockFromIsr();
- }
- if ((rf0r & CAN_RF0R_FOVR0) > 0) {
- /* Overflow events handling.*/
- CAN1->RF0R = CAN_RF0R_FOVR0;
- chSysLockFromIsr();
- chEvtBroadcastFlagsI(&CAND1.error_event, CAN_OVERFLOW_ERROR);
- chSysUnlockFromIsr();
- }
+ can_lld_rx0_handler(&CAND1);
CH_IRQ_EPILOGUE();
}
@@ -116,7 +264,7 @@ CH_IRQ_HANDLER(STM32_CAN1_RX1_HANDLER) {
CH_IRQ_PROLOGUE();
- chSysHalt(); /* Not supported (yet).*/
+ can_lld_rx1_handler(&CAND1);
CH_IRQ_EPILOGUE();
}
@@ -127,39 +275,72 @@ CH_IRQ_HANDLER(STM32_CAN1_RX1_HANDLER) {
* @isr
*/
CH_IRQ_HANDLER(STM32_CAN1_SCE_HANDLER) {
- uint32_t msr;
CH_IRQ_PROLOGUE();
- msr = CAN1->MSR;
- CAN1->MSR = CAN_MSR_ERRI | CAN_MSR_WKUI | CAN_MSR_SLAKI;
- /* Wakeup event.*/
- if (msr & CAN_MSR_WKUI) {
- CAND1.state = CAN_READY;
- CAND1.can->MCR &= ~CAN_MCR_SLEEP;
- chSysLockFromIsr();
- chEvtBroadcastI(&CAND1.wakeup_event);
- chSysUnlockFromIsr();
- }
- /* Error event.*/
- if (msr & CAN_MSR_ERRI) {
- flagsmask_t flags;
- uint32_t esr = CAN1->ESR;
-
- CAN1->ESR &= ~CAN_ESR_LEC;
- flags = (flagsmask_t)(esr & 7);
- if ((esr & CAN_ESR_LEC) > 0)
- flags |= CAN_FRAMING_ERROR;
-
- chSysLockFromIsr();
- /* The content of the ESR register is copied unchanged in the upper
- half word of the listener flags mask.*/
- chEvtBroadcastFlagsI(&CAND1.error_event, flags | (flagsmask_t)(esr < 16));
- chSysUnlockFromIsr();
- }
+ can_lld_sce_handler(&CAND1);
CH_IRQ_EPILOGUE();
}
+#endif /* STM32_CAN_USE_CAN1 */
+
+#if STM32_CAN_USE_CAN2 || defined(__DOXYGEN__)
+/**
+ * @brief CAN2 TX interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(STM32_CAN2_TX_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ can_lld_tx_handler(&CAND2);
+
+ CH_IRQ_EPILOGUE();
+}
+
+/*
+ * @brief CAN2 RX0 interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(STM32_CAN2_RX0_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ can_lld_rx0_handler(&CAND2);
+
+ CH_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief CAN2 RX1 interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(STM32_CAN2_RX1_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ can_lld_rx1_handler(&CAND2);
+
+ CH_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief CAN2 SCE interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(STM32_CAN2_SCE_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ can_lld_sce_handler(&CAND2);
+
+ CH_IRQ_EPILOGUE();
+}
+#endif /* STM32_CAN_USE_CAN2 */
/*===========================================================================*/
/* Driver exported functions. */
@@ -177,6 +358,19 @@ void can_lld_init(void) {
canObjectInit(&CAND1);
CAND1.can = CAN1;
#endif
+#if STM32_CAN_USE_CAN2
+ /* Driver initialization.*/
+ canObjectInit(&CAND2);
+ CAND2.can = CAN2;
+#endif
+
+ /* Filters initialization.*/
+#if STM32_HAS_CAN2
+ can_lld_set_filters(STM32_CAN_MAX_FILTERS / 2, 0, NULL);
+#else
+ can_lld_set_filters(STM32_CAN_MAX_FILTERS, 0, NULL);
+#endif
+
}
/**
@@ -202,6 +396,19 @@ void can_lld_start(CANDriver *canp) {
rccEnableCAN1(FALSE);
}
#endif
+#if STM32_CAN_USE_CAN2
+ if (&CAND2 == canp) {
+ nvicEnableVector(STM32_CAN2_TX_NUMBER,
+ CORTEX_PRIORITY_MASK(STM32_CAN_CAN2_IRQ_PRIORITY));
+ nvicEnableVector(STM32_CAN2_RX0_NUMBER,
+ CORTEX_PRIORITY_MASK(STM32_CAN_CAN2_IRQ_PRIORITY));
+ nvicEnableVector(STM32_CAN2_RX1_NUMBER,
+ CORTEX_PRIORITY_MASK(STM32_CAN_CAN2_IRQ_PRIORITY));
+ nvicEnableVector(STM32_CAN2_SCE_NUMBER,
+ CORTEX_PRIORITY_MASK(STM32_CAN_CAN2_IRQ_PRIORITY));
+ rccEnableCAN2(FALSE);
+ }
+#endif
/* Entering initialization mode. */
canp->state = CAN_STARTING;
@@ -212,56 +419,12 @@ void can_lld_start(CANDriver *canp) {
canp->can->BTR = canp->config->btr;
/* MCR initialization.*/
canp->can->MCR = canp->config->mcr;
- /* Filters initialization.*/
- canp->can->FMR |= CAN_FMR_FINIT;
- if (canp->config->num > 0) {
- uint32_t i, fmask;
- CAN_FilterRegister_TypeDef *cfp;
- canp->can->FA1R = 0;
- canp->can->FM1R = 0;
- canp->can->FS1R = 0;
- canp->can->FFA1R = 0;
- cfp = canp->can->sFilterRegister;
- fmask = 1;
- for (i = 0; i < STM32_CAN_MAX_FILTERS; i++) {
- if (i < canp->config->num) {
- if (canp->config->filters[i].mode)
- canp->can->FM1R |= fmask;
- if (canp->config->filters[i].scale)
- canp->can->FS1R |= fmask;
- if (canp->config->filters[i].assignment)
- canp->can->FFA1R |= fmask;
- cfp->FR1 = canp->config->filters[i].register1;
- cfp->FR2 = canp->config->filters[i].register2;
- canp->can->FA1R |= fmask;
- }
- else {
- cfp->FR1 = 0;
- cfp->FR2 = 0;
- }
- /* Gives a chance for preemption since this is a rather long loop.*/
- chSysUnlock();
- cfp++;
- fmask <<= 1;
- chSysLock();
- }
- }
- else {
- /* Setup a default filter.*/
- canp->can->sFilterRegister[0].FR1 = 0;
- canp->can->sFilterRegister[0].FR2 = 0;
- canp->can->FM1R = 0;
- canp->can->FFA1R = 0;
- canp->can->FS1R = 1;
- canp->can->FA1R = 1;
- }
- canp->can->FMR &= ~CAN_FMR_FINIT;
/* Interrupt sources initialization.*/
canp->can->IER = CAN_IER_TMEIE | CAN_IER_FMPIE0 | CAN_IER_FMPIE1 |
- CAN_IER_WKUIE | CAN_IER_ERRIE | CAN_IER_LECIE |
- CAN_IER_BOFIE | CAN_IER_EPVIE | CAN_IER_EWGIE |
- CAN_IER_FOVIE0 | CAN_IER_FOVIE1;
+ CAN_IER_WKUIE | CAN_IER_ERRIE | CAN_IER_LECIE |
+ CAN_IER_BOFIE | CAN_IER_EPVIE | CAN_IER_EWGIE |
+ CAN_IER_FOVIE0 | CAN_IER_FOVIE1;
}
/**
@@ -285,6 +448,17 @@ void can_lld_stop(CANDriver *canp) {
nvicDisableVector(STM32_CAN1_SCE_NUMBER);
rccDisableCAN1(FALSE);
}
+#endif
+#if STM32_CAN_USE_CAN2
+ if (&CAND2 == canp) {
+ CAN2->MCR = 0x00010002; /* Register reset value. */
+ CAN2->IER = 0x00000000; /* All sources disabled. */
+ nvicDisableVector(STM32_CAN2_TX_NUMBER);
+ nvicDisableVector(STM32_CAN2_RX0_NUMBER);
+ nvicDisableVector(STM32_CAN2_RX1_NUMBER);
+ nvicDisableVector(STM32_CAN2_SCE_NUMBER);
+ rccDisableCAN2(FALSE);
+ }
#endif
}
}
@@ -409,6 +583,36 @@ void can_lld_wakeup(CANDriver *canp) {
}
#endif /* CAN_USE_SLEEP_MODE */
+/**
+ * @brief Programs the filters.
+ * @note This is an STM32-specific API.
+ *
+ * @param[in] can2sb number of the first filter assigned to CAN2
+ * @param[in] num number of entries in the filters array, if zero then
+ * a default filter is programmed
+ * @param[in] cfp pointer to the filters array, can be @p NULL if
+ * (num == 0)
+ *
+ * @api
+ */
+void canSTM32SetFilters(uint32_t can2sb, uint32_t num, const CANFilter *cfp) {
+
+ chDbgCheck((can2sb > 1) && (can2sb < STM32_CAN_MAX_FILTERS) &&
+ (num < STM32_CAN_MAX_FILTERS),
+ "canSTM32SetFilters");
+
+#if STM32_CAN_USE_CAN1
+ chDbgAssert(CAND1.state == CAN_STOP,
+ "canSTM32SetFilters(), #1", "invalid state");
+#endif
+#if STM32_CAN_USE_CAN2
+ chDbgAssert(CAND2.state == CAN_STOP,
+ "canSTM32SetFilters(), #2", "invalid state");
+#endif
+
+ can_lld_set_filters(can2sb, num, cfp);
+}
+
#endif /* HAL_USE_CAN */
/** @} */
diff --git a/os/hal/platforms/STM32/can_lld.h b/os/hal/platforms/STM32/can_lld.h
index cc0c6e115..132cd207a 100644
--- a/os/hal/platforms/STM32/can_lld.h
+++ b/os/hal/platforms/STM32/can_lld.h
@@ -76,13 +76,20 @@
*/
/**
* @brief CAN1 driver enable switch.
- * @details If set to @p TRUE the support for ADC1 is included.
- * @note The default is @p TRUE.
+ * @details If set to @p TRUE the support for CAN1 is included.
*/
#if !defined(STM32_CAN_USE_CAN1) || defined(__DOXYGEN__)
#define STM32_CAN_USE_CAN1 FALSE
#endif
+/**
+ * @brief CAN2 driver enable switch.
+ * @details If set to @p TRUE the support for CAN2 is included.
+ */
+#if !defined(STM32_CAN_USE_CAN2) || defined(__DOXYGEN__)
+#define STM32_CAN_USE_CAN2 FALSE
+#endif
+
/**
* @brief CAN1 interrupt priority level setting.
*/
@@ -91,6 +98,14 @@
#endif
/** @} */
+/**
+ * @brief CAN2 interrupt priority level setting.
+ */
+#if !defined(STM32_CAN_CAN2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_CAN_CAN2_IRQ_PRIORITY 11
+#endif
+/** @} */
+
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
@@ -99,7 +114,11 @@
#error "CAN1 not present in the selected device"
#endif
-#if !STM32_CAN_USE_CAN1
+#if STM32_CAN_USE_CAN2 && !STM32_HAS_CAN2
+#error "CAN2 not present in the selected device"
+#endif
+
+#if !STM32_CAN_USE_CAN1 && !STM32_CAN_USE_CAN2
#error "CAN driver activated but no CAN peripheral assigned"
#endif
@@ -173,29 +192,33 @@ typedef struct {
*/
typedef struct {
/**
- * @brief Filter mode.
- * @note This bit represent the CAN_FM1R register bit associated to this
- * filter (0=mask mode, 1=list mode).
+ * @brief Number of the filter to be programmed.
+ */
+ uint32_t filter;
+ /**
+ * @brief Filter mode.
+ * @note This bit represent the CAN_FM1R register bit associated to this
+ * filter (0=mask mode, 1=list mode).
*/
uint32_t mode:1;
/**
- * @brief Filter scale.
- * @note This bit represent the CAN_FS1R register bit associated to this
- * filter (0=16 bits mode, 1=32 bits mode).
+ * @brief Filter scale.
+ * @note This bit represent the CAN_FS1R register bit associated to this
+ * filter (0=16 bits mode, 1=32 bits mode).
*/
uint32_t scale:1;
/**
- * @brief Filter mode.
- * @note This bit represent the CAN_FFA1R register bit associated to this
- * filter, must be set to zero in this version of the driver.
+ * @brief Filter mode.
+ * @note This bit represent the CAN_FFA1R register bit associated to this
+ * filter, must be set to zero in this version of the driver.
*/
uint32_t assignment:1;
/**
- * @brief Filter register 1 (identifier).
+ * @brief Filter register 1 (identifier).
*/
uint32_t register1;
/**
- * @brief Filter register 2 (mask/identifier depending on mode=0/1).
+ * @brief Filter register 2 (mask/identifier depending on mode=0/1).
*/
uint32_t register2;
} CANFilter;
@@ -205,29 +228,17 @@ typedef struct {
*/
typedef struct {
/**
- * @brief CAN MCR register initialization data.
- * @note Some bits in this register are enforced by the driver regardless
- * their status in this field.
+ * @brief CAN MCR register initialization data.
+ * @note Some bits in this register are enforced by the driver regardless
+ * their status in this field.
*/
uint32_t mcr;
/**
- * @brief CAN BTR register initialization data.
- * @note Some bits in this register are enforced by the driver regardless
- * their status in this field.
+ * @brief CAN BTR register initialization data.
+ * @note Some bits in this register are enforced by the driver regardless
+ * their status in this field.
*/
uint32_t btr;
- /**
- * @brief Number of elements into the filters array.
- * @note By setting this field to zero a default filter is enabled that
- * allows all frames, this should be adequate for simple applications.
- */
- uint32_t num;
- /**
- * @brief Pointer to an array of @p CANFilter structures.
- * @note This field can be set to @p NULL if the field @p num is set to
- * zero.
- */
- const CANFilter *filters;
} CANConfig;
/**
@@ -235,52 +246,53 @@ typedef struct {
*/
typedef struct {
/**
- * @brief Driver state.
+ * @brief Driver state.
*/
canstate_t state;
/**
- * @brief Current configuration data.
+ * @brief Current configuration data.
*/
const CANConfig *config;
/**
- * @brief Transmission queue semaphore.
+ * @brief Transmission queue semaphore.
*/
Semaphore txsem;
/**
- * @brief Receive queue semaphore.
+ * @brief Receive queue semaphore.
*/
Semaphore rxsem;
/**
- * @brief One or more frames become available.
- * @note After broadcasting this event it will not be broadcasted again
- * until the received frames queue has been completely emptied. It
- * is not broadcasted for each received frame. It is
- * responsibility of the application to empty the queue by repeatedly
- * invoking @p chReceive() when listening to this event. This behavior
- * minimizes the interrupt served by the system because CAN traffic.
+ * @brief One or more frames become available.
+ * @note After broadcasting this event it will not be broadcasted again
+ * until the received frames queue has been completely emptied. It
+ * is not broadcasted for each received frame. It is
+ * responsibility of the application to empty the queue by
+ * repeatedly invoking @p chReceive() when listening to this event.
+ * This behavior minimizes the interrupt served by the system
+ * because CAN traffic.
*/
EventSource rxfull_event;
/**
- * @brief One or more transmission slots become available.
+ * @brief One or more transmission slots become available.
*/
EventSource txempty_event;
/**
- * @brief A CAN bus error happened.
+ * @brief A CAN bus error happened.
*/
EventSource error_event;
#if CAN_USE_SLEEP_MODE || defined (__DOXYGEN__)
/**
- * @brief Entering sleep state event.
+ * @brief Entering sleep state event.
*/
EventSource sleep_event;
/**
- * @brief Exiting sleep state event.
+ * @brief Exiting sleep state event.
*/
EventSource wakeup_event;
#endif /* CAN_USE_SLEEP_MODE */
/* End of the mandatory fields.*/
/**
- * @brief Pointer to the CAN registers.
+ * @brief Pointer to the CAN registers.
*/
CAN_TypeDef *can;
} CANDriver;
@@ -297,6 +309,10 @@ typedef struct {
extern CANDriver CAND1;
#endif
+#if STM32_CAN_USE_CAN2 && !defined(__DOXYGEN__)
+extern CANDriver CAND2;
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/readme.txt b/readme.txt
index a1d689092..28e91268b 100644
--- a/readme.txt
+++ b/readme.txt
@@ -112,6 +112,7 @@
TODO: Create a FatFS wrapper implementing the interface and using a server
thread for synchronization.
TODO: Create an implementation over a read-only file system in code space.
+- NEW: CAN2 support for STM32 added.
- NEW: Updated STM32L1xx header to the latest version.
- NEW: Added an option to lwipthread to change the link status poll interval.
- NEW: Added new C++ demo for the STM32F4-Discovery.
diff --git a/testhal/STM32F4xx/CAN/main.c b/testhal/STM32F4xx/CAN/main.c
index 5f32d868c..e7a10247b 100644
--- a/testhal/STM32F4xx/CAN/main.c
+++ b/testhal/STM32F4xx/CAN/main.c
@@ -27,7 +27,7 @@ struct can_instance {
};
static const struct can_instance can1 = {&CAND1, GPIOD_LED5};
-//static const struct can_instance can2 = {&CAND2, GPIOD_LED3};
+static const struct can_instance can2 = {&CAND2, GPIOD_LED3};
/*
* Internal loopback mode, 500KBaud, automatic wakeup, automatic recover
@@ -37,16 +37,14 @@ static const struct can_instance can1 = {&CAND1, GPIOD_LED5};
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)
};
/*
* Receiver thread.
*/
static WORKING_AREA(can_rx1_wa, 256);
-//static WORKING_AREA(can_rx2_wa, 256);
+static WORKING_AREA(can_rx2_wa, 256);
static msg_t can_rx(void *p) {
struct can_instance *cip = p;
EventListener el;
@@ -85,6 +83,7 @@ static msg_t can_tx(void * p) {
while (!chThdShouldTerminate()) {
canTransmit(&CAND1, &txmsg, MS2ST(100));
+ canTransmit(&CAND2, &txmsg, MS2ST(100));
chThdSleepMilliseconds(500);
}
return 0;
@@ -106,17 +105,18 @@ int main(void) {
chSysInit();
/*
- * Activates the CAN driver 1.
+ * Activates the CAN drivers 1 and 2.
*/
canStart(&CAND1, &cancfg);
+ canStart(&CAND2, &cancfg);
/*
* Starting the transmitter and receiver threads.
*/
chThdCreateStatic(can_rx1_wa, sizeof(can_rx1_wa), NORMALPRIO + 7,
can_rx, (void *)&can1);
-// chThdCreateStatic(can_rx2_wa, sizeof(can_rx2_wa), NORMALPRIO + 7,
-// can_rx, (void *)&can2);
+ chThdCreateStatic(can_rx2_wa, sizeof(can_rx2_wa), NORMALPRIO + 7,
+ can_rx, (void *)&can2);
chThdCreateStatic(can_tx_wa, sizeof(can_tx_wa), NORMALPRIO + 7,
can_tx, NULL);