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-d51de3d6d3f4master
parent
184a71345c
commit
92bf9bdac3
|
@ -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 */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -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 <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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue