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. */
|
/* Driver exported variables. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
/** @brief ADC1 driver identifier.*/
|
/** @brief CAN1 driver identifier.*/
|
||||||
#if STM32_CAN_USE_CAN1 || defined(__DOXYGEN__)
|
#if STM32_CAN_USE_CAN1 || defined(__DOXYGEN__)
|
||||||
CANDriver CAND1;
|
CANDriver CAND1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/** @brief CAN2 driver identifier.*/
|
||||||
|
#if STM32_CAN_USE_CAN2 || defined(__DOXYGEN__)
|
||||||
|
CANDriver CAND2;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* Driver local variables. */
|
/* Driver local variables. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -52,10 +57,176 @@ CANDriver CAND1;
|
||||||
/* Driver local functions. */
|
/* 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. */
|
/* Driver interrupt handlers. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
#if STM32_CAN_USE_CAN1 || defined(__DOXYGEN__)
|
||||||
/**
|
/**
|
||||||
* @brief CAN1 TX interrupt handler.
|
* @brief CAN1 TX interrupt handler.
|
||||||
*
|
*
|
||||||
|
@ -65,13 +236,7 @@ CH_IRQ_HANDLER(STM32_CAN1_TX_HANDLER) {
|
||||||
|
|
||||||
CH_IRQ_PROLOGUE();
|
CH_IRQ_PROLOGUE();
|
||||||
|
|
||||||
/* No more events until a message is transmitted.*/
|
can_lld_tx_handler(&CAND1);
|
||||||
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();
|
|
||||||
|
|
||||||
CH_IRQ_EPILOGUE();
|
CH_IRQ_EPILOGUE();
|
||||||
}
|
}
|
||||||
|
@ -82,27 +247,10 @@ CH_IRQ_HANDLER(STM32_CAN1_TX_HANDLER) {
|
||||||
* @isr
|
* @isr
|
||||||
*/
|
*/
|
||||||
CH_IRQ_HANDLER(STM32_CAN1_RX0_HANDLER) {
|
CH_IRQ_HANDLER(STM32_CAN1_RX0_HANDLER) {
|
||||||
uint32_t rf0r;
|
|
||||||
|
|
||||||
CH_IRQ_PROLOGUE();
|
CH_IRQ_PROLOGUE();
|
||||||
|
|
||||||
rf0r = CAN1->RF0R;
|
can_lld_rx0_handler(&CAND1);
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
CH_IRQ_EPILOGUE();
|
CH_IRQ_EPILOGUE();
|
||||||
}
|
}
|
||||||
|
@ -116,7 +264,7 @@ CH_IRQ_HANDLER(STM32_CAN1_RX1_HANDLER) {
|
||||||
|
|
||||||
CH_IRQ_PROLOGUE();
|
CH_IRQ_PROLOGUE();
|
||||||
|
|
||||||
chSysHalt(); /* Not supported (yet).*/
|
can_lld_rx1_handler(&CAND1);
|
||||||
|
|
||||||
CH_IRQ_EPILOGUE();
|
CH_IRQ_EPILOGUE();
|
||||||
}
|
}
|
||||||
|
@ -127,39 +275,72 @@ CH_IRQ_HANDLER(STM32_CAN1_RX1_HANDLER) {
|
||||||
* @isr
|
* @isr
|
||||||
*/
|
*/
|
||||||
CH_IRQ_HANDLER(STM32_CAN1_SCE_HANDLER) {
|
CH_IRQ_HANDLER(STM32_CAN1_SCE_HANDLER) {
|
||||||
uint32_t msr;
|
|
||||||
|
|
||||||
CH_IRQ_PROLOGUE();
|
CH_IRQ_PROLOGUE();
|
||||||
|
|
||||||
msr = CAN1->MSR;
|
can_lld_sce_handler(&CAND1);
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
CH_IRQ_EPILOGUE();
|
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. */
|
/* Driver exported functions. */
|
||||||
|
@ -177,6 +358,19 @@ void can_lld_init(void) {
|
||||||
canObjectInit(&CAND1);
|
canObjectInit(&CAND1);
|
||||||
CAND1.can = CAN1;
|
CAND1.can = CAN1;
|
||||||
#endif
|
#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);
|
rccEnableCAN1(FALSE);
|
||||||
}
|
}
|
||||||
#endif
|
#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. */
|
/* Entering initialization mode. */
|
||||||
canp->state = CAN_STARTING;
|
canp->state = CAN_STARTING;
|
||||||
|
@ -212,51 +419,7 @@ void can_lld_start(CANDriver *canp) {
|
||||||
canp->can->BTR = canp->config->btr;
|
canp->can->BTR = canp->config->btr;
|
||||||
/* MCR initialization.*/
|
/* MCR initialization.*/
|
||||||
canp->can->MCR = canp->config->mcr;
|
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.*/
|
/* Interrupt sources initialization.*/
|
||||||
canp->can->IER = CAN_IER_TMEIE | CAN_IER_FMPIE0 | CAN_IER_FMPIE1 |
|
canp->can->IER = CAN_IER_TMEIE | CAN_IER_FMPIE0 | CAN_IER_FMPIE1 |
|
||||||
CAN_IER_WKUIE | CAN_IER_ERRIE | CAN_IER_LECIE |
|
CAN_IER_WKUIE | CAN_IER_ERRIE | CAN_IER_LECIE |
|
||||||
|
@ -285,6 +448,17 @@ void can_lld_stop(CANDriver *canp) {
|
||||||
nvicDisableVector(STM32_CAN1_SCE_NUMBER);
|
nvicDisableVector(STM32_CAN1_SCE_NUMBER);
|
||||||
rccDisableCAN1(FALSE);
|
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
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -409,6 +583,36 @@ void can_lld_wakeup(CANDriver *canp) {
|
||||||
}
|
}
|
||||||
#endif /* CAN_USE_SLEEP_MODE */
|
#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 */
|
#endif /* HAL_USE_CAN */
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
|
@ -76,13 +76,20 @@
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* @brief CAN1 driver enable switch.
|
* @brief CAN1 driver enable switch.
|
||||||
* @details If set to @p TRUE the support for ADC1 is included.
|
* @details If set to @p TRUE the support for CAN1 is included.
|
||||||
* @note The default is @p TRUE.
|
|
||||||
*/
|
*/
|
||||||
#if !defined(STM32_CAN_USE_CAN1) || defined(__DOXYGEN__)
|
#if !defined(STM32_CAN_USE_CAN1) || defined(__DOXYGEN__)
|
||||||
#define STM32_CAN_USE_CAN1 FALSE
|
#define STM32_CAN_USE_CAN1 FALSE
|
||||||
#endif
|
#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.
|
* @brief CAN1 interrupt priority level setting.
|
||||||
*/
|
*/
|
||||||
|
@ -91,6 +98,14 @@
|
||||||
#endif
|
#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. */
|
/* Derived constants and error checks. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -99,7 +114,11 @@
|
||||||
#error "CAN1 not present in the selected device"
|
#error "CAN1 not present in the selected device"
|
||||||
#endif
|
#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"
|
#error "CAN driver activated but no CAN peripheral assigned"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -172,6 +191,10 @@ typedef struct {
|
||||||
* @note Refer to the STM32 reference manual for info about filters.
|
* @note Refer to the STM32 reference manual for info about filters.
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
/**
|
||||||
|
* @brief Number of the filter to be programmed.
|
||||||
|
*/
|
||||||
|
uint32_t filter;
|
||||||
/**
|
/**
|
||||||
* @brief Filter mode.
|
* @brief Filter mode.
|
||||||
* @note This bit represent the CAN_FM1R register bit associated to this
|
* @note This bit represent the CAN_FM1R register bit associated to this
|
||||||
|
@ -216,18 +239,6 @@ typedef struct {
|
||||||
* their status in this field.
|
* their status in this field.
|
||||||
*/
|
*/
|
||||||
uint32_t btr;
|
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;
|
} CANConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -255,9 +266,10 @@ typedef struct {
|
||||||
* @note After broadcasting this event it will not be broadcasted again
|
* @note After broadcasting this event it will not be broadcasted again
|
||||||
* until the received frames queue has been completely emptied. It
|
* until the received frames queue has been completely emptied. It
|
||||||
* is <b>not</b> broadcasted for each received frame. It is
|
* is <b>not</b> broadcasted for each received frame. It is
|
||||||
* responsibility of the application to empty the queue by repeatedly
|
* responsibility of the application to empty the queue by
|
||||||
* invoking @p chReceive() when listening to this event. This behavior
|
* repeatedly invoking @p chReceive() when listening to this event.
|
||||||
* minimizes the interrupt served by the system because CAN traffic.
|
* This behavior minimizes the interrupt served by the system
|
||||||
|
* because CAN traffic.
|
||||||
*/
|
*/
|
||||||
EventSource rxfull_event;
|
EventSource rxfull_event;
|
||||||
/**
|
/**
|
||||||
|
@ -297,6 +309,10 @@ typedef struct {
|
||||||
extern CANDriver CAND1;
|
extern CANDriver CAND1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if STM32_CAN_USE_CAN2 && !defined(__DOXYGEN__)
|
||||||
|
extern CANDriver CAND2;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -112,6 +112,7 @@
|
||||||
TODO: Create a FatFS wrapper implementing the interface and using a server
|
TODO: Create a FatFS wrapper implementing the interface and using a server
|
||||||
thread for synchronization.
|
thread for synchronization.
|
||||||
TODO: Create an implementation over a read-only file system in code space.
|
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: Updated STM32L1xx header to the latest version.
|
||||||
- NEW: Added an option to lwipthread to change the link status poll interval.
|
- NEW: Added an option to lwipthread to change the link status poll interval.
|
||||||
- NEW: Added new C++ demo for the STM32F4-Discovery.
|
- 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 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
|
* 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 = {
|
static const CANConfig cancfg = {
|
||||||
CAN_MCR_ABOM | CAN_MCR_AWUM | CAN_MCR_TXFP,
|
CAN_MCR_ABOM | CAN_MCR_AWUM | CAN_MCR_TXFP,
|
||||||
CAN_BTR_LBKM | CAN_BTR_SJW(0) | CAN_BTR_TS2(1) |
|
CAN_BTR_LBKM | CAN_BTR_SJW(0) | CAN_BTR_TS2(1) |
|
||||||
CAN_BTR_TS1(8) | CAN_BTR_BRP(6),
|
CAN_BTR_TS1(8) | CAN_BTR_BRP(6)
|
||||||
0,
|
|
||||||
NULL
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Receiver thread.
|
* Receiver thread.
|
||||||
*/
|
*/
|
||||||
static WORKING_AREA(can_rx1_wa, 256);
|
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) {
|
static msg_t can_rx(void *p) {
|
||||||
struct can_instance *cip = p;
|
struct can_instance *cip = p;
|
||||||
EventListener el;
|
EventListener el;
|
||||||
|
@ -85,6 +83,7 @@ static msg_t can_tx(void * p) {
|
||||||
|
|
||||||
while (!chThdShouldTerminate()) {
|
while (!chThdShouldTerminate()) {
|
||||||
canTransmit(&CAND1, &txmsg, MS2ST(100));
|
canTransmit(&CAND1, &txmsg, MS2ST(100));
|
||||||
|
canTransmit(&CAND2, &txmsg, MS2ST(100));
|
||||||
chThdSleepMilliseconds(500);
|
chThdSleepMilliseconds(500);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -106,17 +105,18 @@ int main(void) {
|
||||||
chSysInit();
|
chSysInit();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Activates the CAN driver 1.
|
* Activates the CAN drivers 1 and 2.
|
||||||
*/
|
*/
|
||||||
canStart(&CAND1, &cancfg);
|
canStart(&CAND1, &cancfg);
|
||||||
|
canStart(&CAND2, &cancfg);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Starting the transmitter and receiver threads.
|
* Starting the transmitter and receiver threads.
|
||||||
*/
|
*/
|
||||||
chThdCreateStatic(can_rx1_wa, sizeof(can_rx1_wa), NORMALPRIO + 7,
|
chThdCreateStatic(can_rx1_wa, sizeof(can_rx1_wa), NORMALPRIO + 7,
|
||||||
can_rx, (void *)&can1);
|
can_rx, (void *)&can1);
|
||||||
// chThdCreateStatic(can_rx2_wa, sizeof(can_rx2_wa), NORMALPRIO + 7,
|
chThdCreateStatic(can_rx2_wa, sizeof(can_rx2_wa), NORMALPRIO + 7,
|
||||||
// can_rx, (void *)&can2);
|
can_rx, (void *)&can2);
|
||||||
chThdCreateStatic(can_tx_wa, sizeof(can_tx_wa), NORMALPRIO + 7,
|
chThdCreateStatic(can_tx_wa, sizeof(can_tx_wa), NORMALPRIO + 7,
|
||||||
can_tx, NULL);
|
can_tx, NULL);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue