From 8a433087afe80e92aea1c558965994b53bfcfb48 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Mon, 30 Nov 2009 21:34:05 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1368 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/can.h | 9 +++++ os/hal/platforms/STM32/adc_lld.c | 2 +- os/hal/platforms/STM32/adc_lld.h | 2 +- os/hal/platforms/STM32/can_lld.c | 63 ++++++++++++++++++++++++++++++++++- os/hal/platforms/STM32/can_lld.h | 63 +++++++++++++++++++++++++++++------ os/hal/src/can.c | 71 +++++++++++++++++++++++++--------------- os/hal/templates/can_lld.h | 39 ++++++++++++++-------- 7 files changed, 196 insertions(+), 53 deletions(-) (limited to 'os') diff --git a/os/hal/include/can.h b/os/hal/include/can.h index 3d43e1c51..3637c64b0 100644 --- a/os/hal/include/can.h +++ b/os/hal/include/can.h @@ -41,6 +41,14 @@ typedef enum { #include "can_lld.h" +/** + * @brief Adds some flags to the CAN status mask. + * + * @param[in] canp pointer to the @p CANDriver object + * @param[in] mask flags to be added to the status mask + */ +#define canAddFlagsI(canp, mask) ((canp)->cd_status |= (mask)) + #ifdef __cplusplus extern "C" { #endif @@ -50,6 +58,7 @@ extern "C" { void canStop(CANDriver *canp); msg_t canTransmit(CANDriver *canp, const CANFrame *cfp, systime_t timeout); msg_t canReceive(CANDriver *canp, CANFrame *cfp, systime_t timeout); + canstatus_t canGetAndClearFlags(CANDriver *canp); #if CAN_USE_SLEEP_MODE void canSleep(CANDriver *canp); void canWakeup(CANDriver *canp); diff --git a/os/hal/platforms/STM32/adc_lld.c b/os/hal/platforms/STM32/adc_lld.c index e90448fa3..1213484e2 100644 --- a/os/hal/platforms/STM32/adc_lld.c +++ b/os/hal/platforms/STM32/adc_lld.c @@ -33,8 +33,8 @@ /* Low Level Driver exported variables. */ /*===========================================================================*/ -#if USE_STM32_ADC1 || defined(__DOXYGEN__) /** @brief ADC1 driver identifier.*/ +#if USE_STM32_ADC1 || defined(__DOXYGEN__) ADCDriver ADCD1; #endif diff --git a/os/hal/platforms/STM32/adc_lld.h b/os/hal/platforms/STM32/adc_lld.h index 2b254d7af..f9950afd5 100644 --- a/os/hal/platforms/STM32/adc_lld.h +++ b/os/hal/platforms/STM32/adc_lld.h @@ -251,7 +251,7 @@ typedef struct { /** @cond never*/ #if USE_STM32_ADC1 -ADCDriver ADCD1; +extern ADCDriver ADCD1; #endif #ifdef __cplusplus diff --git a/os/hal/platforms/STM32/can_lld.c b/os/hal/platforms/STM32/can_lld.c index 91831cff1..30d270a37 100644 --- a/os/hal/platforms/STM32/can_lld.c +++ b/os/hal/platforms/STM32/can_lld.c @@ -33,6 +33,11 @@ /* Low Level Driver exported variables. */ /*===========================================================================*/ +/** @brief ADC1 driver identifier.*/ +#if USE_STM32_CAN1 || defined(__DOXYGEN__) +CANDriver CAND1; +#endif + /*===========================================================================*/ /* Low Level Driver local variables. */ /*===========================================================================*/ @@ -45,6 +50,62 @@ /* Low Level Driver interrupt handlers. */ /*===========================================================================*/ +/* + * CAN1 TX interrupt handler. + */ +CH_IRQ_HANDLER(Vector8C) { + + CH_IRQ_PROLOGUE(); + + /* No more events until a message is transmitted.*/ + CAN1->IER &= ~CAN_IER_TMEIE; + chEvtBroadcastI(&CAND1.cd_txempty_event); + + CH_IRQ_EPILOGUE(); +} + +/* + * CAN1 RX0 interrupt handler. + */ +CH_IRQ_HANDLER(Vector90) { + + CH_IRQ_PROLOGUE(); + + /* No more events until the incoming messages queues are emptied.*/ + CAN1->IER &= ~(CAN_IER_FMPIE0 | CAN_IER_FMPIE1); + chEvtBroadcastI(&CAND1.cd_rxfull_event); + + CH_IRQ_EPILOGUE(); +} + +/* + * CAN1 RX1 interrupt handler. + */ +CH_IRQ_HANDLER(Vector94) { + + CH_IRQ_PROLOGUE(); + + /* No more events until the incoming messages queues are emptied.*/ + CAN1->IER &= ~(CAN_IER_FMPIE0 | CAN_IER_FMPIE1); + chEvtBroadcastI(&CAND1.cd_rxfull_event); + + CH_IRQ_EPILOGUE(); +} + +/* + * CAN1 SCE interrupt handler. + */ +CH_IRQ_HANDLER(Vector98) { + + CH_IRQ_PROLOGUE(); + + canAddFlagsI(&CAND1, 1); + chEvtBroadcastI(&CAND1.cd_error_event); + CAN1->MSR = CAN_MSR_ERRI; + + CH_IRQ_EPILOGUE(); +} + /*===========================================================================*/ /* Low Level Driver exported functions. */ /*===========================================================================*/ @@ -63,7 +124,7 @@ void can_lld_init(void) { */ void can_lld_start(CANDriver *canp) { - if (canp->can_state == CAN_STOP) { + if (canp->cd_state == CAN_STOP) { /* Clock activation.*/ } /* Configuration.*/ diff --git a/os/hal/platforms/STM32/can_lld.h b/os/hal/platforms/STM32/can_lld.h index 6b7cf3b6c..a02ce15fc 100644 --- a/os/hal/platforms/STM32/can_lld.h +++ b/os/hal/platforms/STM32/can_lld.h @@ -39,6 +39,15 @@ /* Driver pre-compile time settings. */ /*===========================================================================*/ +/** + * @brief ADC1 driver enable switch. + * @details If set to @p TRUE the support for ADC1 is included. + * @note The default is @p TRUE. + */ +#if !defined(USE_STM32_CAN1) || defined(__DOXYGEN__) +#define USE_STM32_CAN1 TRUE +#endif + /** * @brief Sleep mode related APIs inclusion switch. * @note This switch is enforced to @p FALSE if the driver implementation @@ -60,6 +69,11 @@ /* Driver data structures and types. */ /*===========================================================================*/ +/** + * @brief CAN status flags. + */ +typedef uint32_t canstatus_t; + /** * @brief CAN frame. * @note Accessing the frame data as word16 or word32 is not portable because @@ -79,9 +93,20 @@ typedef struct { /** * @brief Driver configuration structure. - * @note It could be empty on some architectures. */ 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. + */ + uint32_t cc_mcr; + /** + * @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 cc_btr; } CANConfig; /** @@ -91,44 +116,61 @@ typedef struct { /** * @brief Driver state. */ - canstate_t can_state; + canstate_t cd_state; /** * @brief Current configuration data. */ - const CANConfig *can_config; + const CANConfig *cd_config; /** * @brief Transmission queue semaphore. */ - Semaphore can_txsem; + Semaphore cd_txsem; /** * @brief Receive queue semaphore. */ - Semaphore can_rxsem; + Semaphore cd_rxsem; /** * @brief One or more frames become available. */ - EventSource can_rxfull_event; + EventSource cd_rxfull_event; + /** + * @brief One or more transmission slots become available. + */ + EventSource cd_txempty_event; + /** + * @brief A CAN bus error happened. + */ + EventSource cd_error_event; /** - * @brief One or more transmission slots become available. + * @brief Error flags set when an error event is broadcasted. */ - EventSource can_txempty_event; + canstatus_t cd_status; #if CAN_USE_SLEEP_MODE || defined (__DOXYGEN__) /** * @brief Entering sleep state event. */ - EventSource can_sleep_event; + EventSource cd_sleep_event; /** * @brief Exiting sleep state event. */ - EventSource can_wakeup_event; + EventSource cd_wakeup_event; #endif /* CAN_USE_SLEEP_MODE */ /* End of the mandatory fields.*/ + /** + * @brief Pointer to the CAN registers. + */ + CAN_TypeDef *cd_canp; } CANDriver; /*===========================================================================*/ /* External declarations. */ /*===========================================================================*/ +/** @cond never*/ +#if USE_STM32_CAN1 +extern CANDriver CAND1; +#endif + #ifdef __cplusplus extern "C" { #endif @@ -146,6 +188,7 @@ extern "C" { #ifdef __cplusplus } #endif +/** @endcond*/ #endif /* CH_HAL_USE_CAN */ diff --git a/os/hal/src/can.c b/os/hal/src/can.c index 387581d8c..698bcfbc4 100644 --- a/os/hal/src/can.c +++ b/os/hal/src/can.c @@ -44,15 +44,15 @@ void canInit(void) { */ void canObjectInit(CANDriver *canp) { - canp->can_state = CAN_STOP; - canp->can_config = NULL; - chSemInit(&canp->can_txsem, 0); - chSemInit(&canp->can_rxsem, 0); - chEvtInit(&canp->can_rxfull_event); - chEvtInit(&canp->can_txempty_event); + canp->cd_state = CAN_STOP; + canp->cd_config = NULL; + chSemInit(&canp->cd_txsem, 0); + chSemInit(&canp->cd_rxsem, 0); + chEvtInit(&canp->cd_rxfull_event); + chEvtInit(&canp->cd_txempty_event); #if CAN_USE_SLEEP_MODE - chEvtInit(&canp->can_sleep_event); - chEvtInit(&canp->can_wakeup_event); + chEvtInit(&canp->cd_sleep_event); + chEvtInit(&canp->cd_wakeup_event); #endif /* CAN_USE_SLEEP_MODE */ } @@ -67,12 +67,12 @@ void canStart(CANDriver *canp, const CANConfig *config) { chDbgCheck((canp != NULL) && (config != NULL), "canStart"); chSysLock(); - chDbgAssert((canp->can_state == CAN_STOP) || (canp->can_state == CAN_READY), + chDbgAssert((canp->cd_state == CAN_STOP) || (canp->cd_state == CAN_READY), "canStart(), #1", "invalid state"); - canp->can_config = config; + canp->cd_config = config; can_lld_start(canp); - canp->can_state = CAN_READY; + canp->cd_state = CAN_READY; chSysUnlock(); } @@ -86,11 +86,11 @@ void canStop(CANDriver *canp) { chDbgCheck(canp != NULL, "canStop"); chSysLock(); - chDbgAssert((canp->can_state == CAN_STOP) || (canp->can_state == CAN_READY), + chDbgAssert((canp->cd_state == CAN_STOP) || (canp->cd_state == CAN_READY), "canStop(), #1", "invalid state"); can_lld_stop(canp); - canp->can_state = CAN_STOP; + canp->cd_state = CAN_STOP; chSysUnlock(); } @@ -118,11 +118,11 @@ msg_t canTransmit(CANDriver *canp, const CANFrame *cfp, systime_t timeout) { chDbgCheck((canp != NULL) && (cfp != NULL), "canTransmit"); chSysLock(); - chDbgAssert((canp->can_state == CAN_READY) || (canp->can_state == CAN_SLEEP), + chDbgAssert((canp->cd_state == CAN_READY) || (canp->cd_state == CAN_SLEEP), "canTransmit(), #1", "invalid state"); - if ((canp->can_state == CAN_SLEEP) || !can_lld_can_transmit(canp)) { - msg = chSemWaitTimeoutS(&canp->can_txsem, timeout); + if ((canp->cd_state == CAN_SLEEP) || !can_lld_can_transmit(canp)) { + msg = chSemWaitTimeoutS(&canp->cd_txsem, timeout); if (msg != RDY_OK) { chSysUnlock(); return msg; @@ -156,11 +156,11 @@ msg_t canReceive(CANDriver *canp, CANFrame *cfp, systime_t timeout) { chDbgCheck((canp != NULL) && (cfp != NULL), "canReceive"); chSysLock(); - chDbgAssert((canp->can_state == CAN_READY) || (canp->can_state == CAN_SLEEP), + chDbgAssert((canp->cd_state == CAN_READY) || (canp->cd_state == CAN_SLEEP), "canReceive(), #1", "invalid state"); - if ((canp->can_state == CAN_SLEEP) || !can_lld_can_receive(canp)) { - msg = chSemWaitTimeoutS(&canp->can_rxsem, timeout); + if ((canp->cd_state == CAN_SLEEP) || !can_lld_can_receive(canp)) { + msg = chSemWaitTimeoutS(&canp->cd_rxsem, timeout); if (msg != RDY_OK) { chSysUnlock(); return msg; @@ -171,6 +171,23 @@ msg_t canReceive(CANDriver *canp, CANFrame *cfp, systime_t timeout) { return msg; } +/** + * @brief Returns the current status mask and clears it. + * + * @param[in] canp pointer to the @p CANDriver object + * + * @return The status flags mask. + */ +canstatus_t canGetAndClearFlags(CANDriver *canp) { + canstatus_t status; + + chSysLock(); + status = canp->cd_status; + canp->cd_status = 0; + chSysUnlock(); + return status; +} + #if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__) /** * @brief Enters the sleep mode. @@ -182,13 +199,13 @@ void canSleep(CANDriver *canp) { chDbgCheck(canp != NULL, "canSleep"); chSysLock(); - chDbgAssert((canp->can_state == CAN_READY) || (canp->can_state == CAN_SLEEP), + chDbgAssert((canp->cd_state == CAN_READY) || (canp->cd_state == CAN_SLEEP), "canSleep(), #1", "invalid state"); - if (canp->can_state == CAN_READY) { + if (canp->cd_state == CAN_READY) { can_lld_sleep(canp); - canp->can_state = CAN_SLEEP; - chEvtBroadcastI(&canp->can_sleep_event); + canp->cd_state = CAN_SLEEP; + chEvtBroadcastI(&canp->cd_sleep_event); chSchRescheduleS(); } chSysUnlock(); @@ -206,13 +223,13 @@ void canWakeup(CANDriver *canp) { chDbgCheck(canp != NULL, "canWakeup"); chSysLock(); - chDbgAssert((canp->can_state == CAN_READY) || (canp->can_state == CAN_SLEEP), + chDbgAssert((canp->cd_state == CAN_READY) || (canp->cd_state == CAN_SLEEP), "canWakeup(), #1", "invalid state"); - if (canp->can_state == CAN_SLEEP) { + if (canp->cd_state == CAN_SLEEP) { can_lld_wakeup(canp); - canp->can_state = CAN_READY; - chEvtBroadcastI(&canp->can_wakeup_event); + canp->cd_state = CAN_READY; + chEvtBroadcastI(&canp->cd_wakeup_event); chSchRescheduleS(); } chSysUnlock(); diff --git a/os/hal/templates/can_lld.h b/os/hal/templates/can_lld.h index 202f7e044..14588c0d5 100644 --- a/os/hal/templates/can_lld.h +++ b/os/hal/templates/can_lld.h @@ -60,6 +60,11 @@ /* Driver data structures and types. */ /*===========================================================================*/ +/** + * @brief CAN status flags. + */ +typedef uint32_t canstatus_t; + /** * @brief CAN frame. * @note Accessing the frame data as word16 or word32 is not portable because @@ -91,36 +96,44 @@ typedef struct { /** * @brief Driver state. */ - canstate_t can_state; + canstate_t cd_state; /** * @brief Current configuration data. */ - const CANConfig *can_config; + const CANConfig *cd_config; /** - * @brief Transmission queue semaphore. + * @brief Transmission queue semaphore. */ - Semaphore can_txsem; + Semaphore cd_txsem; /** * @brief Receive queue semaphore. */ - Semaphore can_rxsem; + Semaphore cd_rxsem; + /** + * @brief One or more frames become available. + */ + EventSource cd_rxfull_event; + /** + * @brief One or more transmission slots become available. + */ + EventSource cd_txempty_event; /** - * @brief One or more frames become available. + * @brief A CAN bus error happened. */ - EventSource can_rxfull_event; + EventSource cd_error_event; /** - * @brief One or more transmission slots become available. + * @brief Error flags set when an error event is broadcasted. */ - EventSource can_txempty_event; + canstatus_t cd_status; #if CAN_USE_SLEEP_MODE || defined (__DOXYGEN__) /** - * @brief Entering sleep state event. + * @brief Entering sleep state event. */ - EventSource can_sleep_event; + EventSource cd_sleep_event; /** - * @brief Exiting sleep state event. + * @brief Exiting sleep state event. */ - EventSource can_wakeup_event; + EventSource cd_wakeup_event; #endif /* CAN_USE_SLEEP_MODE */ /* End of the mandatory fields.*/ } CANDriver; -- cgit v1.2.3