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);