diff options
author | gdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2013-02-03 10:29:01 +0000 |
---|---|---|
committer | gdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2013-02-03 10:29:01 +0000 |
commit | 92bf9bdac3071fc6586f3bb2f2445e3e7c5cefd0 (patch) | |
tree | 7137b92e04fff3e94c0db7318dd9611d3c22d45d /os | |
parent | 184a71345c6a36a9a8664eda8fbcc3ea728267a8 (diff) | |
download | ChibiOS-92bf9bdac3071fc6586f3bb2f2445e3e7c5cefd0.tar.gz ChibiOS-92bf9bdac3071fc6586f3bb2f2445e3e7c5cefd0.tar.bz2 ChibiOS-92bf9bdac3071fc6586f3bb2f2445e3e7c5cefd0.zip |
Added CAN2 support. Tested on the STM32F4xx only.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@5105 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os')
-rw-r--r-- | os/hal/platforms/STM32/can_lld.c | 402 | ||||
-rw-r--r-- | os/hal/platforms/STM32/can_lld.h | 112 |
2 files changed, 367 insertions, 147 deletions
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,101 +57,159 @@ CANDriver CAND1; /* Driver local functions. */
/*===========================================================================*/
-/*===========================================================================*/
-/* Driver interrupt handlers. */
-/*===========================================================================*/
-
/**
- * @brief CAN1 TX interrupt handler.
+ * @brief Programs the filters.
*
- * @isr
+ * @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
*/
-CH_IRQ_HANDLER(STM32_CAN1_TX_HANDLER) {
+static void can_lld_set_filters(uint32_t can2sb,
+ uint32_t num,
+ const CANFilter *cfp) {
- CH_IRQ_PROLOGUE();
+ /* 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.*/
- CAN1->TSR = CAN_TSR_RQCP0 | CAN_TSR_RQCP1 | CAN_TSR_RQCP2;
+ canp->can->TSR = CAN_TSR_RQCP0 | CAN_TSR_RQCP1 | CAN_TSR_RQCP2;
chSysLockFromIsr();
- while (chSemGetCounterI(&CAND1.txsem) < 0)
- chSemSignalI(&CAND1.txsem);
- chEvtBroadcastI(&CAND1.txempty_event);
+ while (chSemGetCounterI(&canp->txsem) < 0)
+ chSemSignalI(&canp->txsem);
+ chEvtBroadcastI(&canp->txempty_event);
chSysUnlockFromIsr();
-
- CH_IRQ_EPILOGUE();
}
-/*
- * @brief CAN1 RX0 interrupt handler.
+/**
+ * @brief Common RX0 ISR handler.
*
- * @isr
+ * @param[in] canp pointer to the @p CANDriver object
+ *
+ * @notapi
*/
-CH_IRQ_HANDLER(STM32_CAN1_RX0_HANDLER) {
+static void can_lld_rx0_handler(CANDriver *canp) {
uint32_t rf0r;
- CH_IRQ_PROLOGUE();
-
- rf0r = CAN1->RF0R;
+ rf0r = canp->can->RF0R;
if ((rf0r & CAN_RF0R_FMP0) > 0) {
/* No more receive events until the queue 0 has been emptied.*/
- CAN1->IER &= ~CAN_IER_FMPIE0;
+ canp->can->IER &= ~CAN_IER_FMPIE0;
chSysLockFromIsr();
- while (chSemGetCounterI(&CAND1.rxsem) < 0)
- chSemSignalI(&CAND1.rxsem);
- chEvtBroadcastI(&CAND1.rxfull_event);
+ while (chSemGetCounterI(&canp->rxsem) < 0)
+ chSemSignalI(&canp->rxsem);
+ chEvtBroadcastI(&canp->rxfull_event);
chSysUnlockFromIsr();
}
if ((rf0r & CAN_RF0R_FOVR0) > 0) {
/* Overflow events handling.*/
- CAN1->RF0R = CAN_RF0R_FOVR0;
+ canp->can->RF0R = CAN_RF0R_FOVR0;
chSysLockFromIsr();
- chEvtBroadcastFlagsI(&CAND1.error_event, CAN_OVERFLOW_ERROR);
+ chEvtBroadcastFlagsI(&canp->error_event, CAN_OVERFLOW_ERROR);
chSysUnlockFromIsr();
}
-
- CH_IRQ_EPILOGUE();
}
/**
- * @brief CAN1 RX1 interrupt handler.
+ * @brief Common RX1 ISR handler.
+ * @note Not used, must not be invoked, defaulted to an halt.
*
- * @isr
+ * @param[in] canp pointer to the @p CANDriver object
+ *
+ * @notapi
*/
-CH_IRQ_HANDLER(STM32_CAN1_RX1_HANDLER) {
-
- CH_IRQ_PROLOGUE();
-
- chSysHalt(); /* Not supported (yet).*/
+static void can_lld_rx1_handler(CANDriver *canp) {
- CH_IRQ_EPILOGUE();
+ (void)canp;
+ chSysHalt();
}
/**
- * @brief CAN1 SCE interrupt handler.
+ * @brief Common SCE ISR handler.
*
- * @isr
+ * @param[in] canp pointer to the @p CANDriver object
+ *
+ * @notapi
*/
-CH_IRQ_HANDLER(STM32_CAN1_SCE_HANDLER) {
+static void can_lld_sce_handler(CANDriver *canp) {
uint32_t msr;
- CH_IRQ_PROLOGUE();
-
- msr = CAN1->MSR;
- CAN1->MSR = CAN_MSR_ERRI | CAN_MSR_WKUI | CAN_MSR_SLAKI;
+ msr = canp->can->MSR;
+ canp->can->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;
+ canp->state = CAN_READY;
+ canp->can->MCR &= ~CAN_MCR_SLEEP;
chSysLockFromIsr();
- chEvtBroadcastI(&CAND1.wakeup_event);
+ chEvtBroadcastI(&canp->wakeup_event);
chSysUnlockFromIsr();
}
/* Error event.*/
if (msr & CAN_MSR_ERRI) {
flagsmask_t flags;
- uint32_t esr = CAN1->ESR;
+ uint32_t esr = canp->can->ESR;
- CAN1->ESR &= ~CAN_ESR_LEC;
+ canp->can->ESR &= ~CAN_ESR_LEC;
flags = (flagsmask_t)(esr & 7);
if ((esr & CAN_ESR_LEC) > 0)
flags |= CAN_FRAMING_ERROR;
@@ -154,13 +217,131 @@ CH_IRQ_HANDLER(STM32_CAN1_SCE_HANDLER) { 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));
+ 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.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(STM32_CAN1_TX_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ can_lld_tx_handler(&CAND1);
+
+ CH_IRQ_EPILOGUE();
+}
+
+/*
+ * @brief CAN1 RX0 interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(STM32_CAN1_RX0_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ can_lld_rx0_handler(&CAND1);
CH_IRQ_EPILOGUE();
}
+/**
+ * @brief CAN1 RX1 interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(STM32_CAN1_RX1_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ can_lld_rx1_handler(&CAND1);
+
+ CH_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief CAN1 SCE interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(STM32_CAN1_SCE_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ 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;
}
/**
@@ -286,6 +449,17 @@ void can_lld_stop(CANDriver *canp) { 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,14 +76,21 @@ */
/**
* @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.
*/
#if !defined(STM32_CAN_CAN1_IRQ_PRIORITY) || defined(__DOXYGEN__)
@@ -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 <b>not</b> 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 <b>not</b> 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
|