From c2ad39132395d52a3894c13f978da2349f650201 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Wed, 2 Dec 2009 16:24:32 +0000 Subject: [PATCH] git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1370 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/can.h | 5 ++- os/hal/platforms/STM32/can_lld.c | 29 +++++++------- os/hal/platforms/STM32/can_lld.h | 62 +++++++++++++++++++++++++++--- os/hal/src/can.c | 21 +++++++--- os/hal/templates/meta/driver_lld.h | 4 +- 5 files changed, 92 insertions(+), 29 deletions(-) diff --git a/os/hal/include/can.h b/os/hal/include/can.h index 2a385b224..54623945e 100644 --- a/os/hal/include/can.h +++ b/os/hal/include/can.h @@ -56,8 +56,9 @@ typedef enum { CAN_UNINIT = 0, /**< @brief Not initialized. */ CAN_STOP = 1, /**< @brief Stopped. */ - CAN_READY = 2, /**< @brief Ready. */ - CAN_SLEEP = 3 /**< @brief Sleep state. */ + CAN_STARTING = 2, /**< @brief Starting. */ + CAN_READY = 3, /**< @brief Ready. */ + CAN_SLEEP = 4 /**< @brief Sleep state. */ } canstate_t; #include "can_lld.h" diff --git a/os/hal/platforms/STM32/can_lld.c b/os/hal/platforms/STM32/can_lld.c index 2e3ed43df..86c8ecbf5 100644 --- a/os/hal/platforms/STM32/can_lld.c +++ b/os/hal/platforms/STM32/can_lld.c @@ -163,21 +163,25 @@ void can_lld_init(void) { */ void can_lld_start(CANDriver *canp) { - if (canp->cd_state == CAN_STOP) { - /* Clock activation.*/ + /* Clock activation.*/ #if USE_STM32_CAN1 - if (&CAND1 == canp) { - NVICEnableVector(USB_HP_CAN1_TX_IRQn, STM32_CAN1_IRQ_PRIORITY); - NVICEnableVector(USB_LP_CAN1_RX0_IRQn, STM32_CAN1_IRQ_PRIORITY); - NVICEnableVector(CAN1_RX1_IRQn, STM32_CAN1_IRQ_PRIORITY); - NVICEnableVector(CAN1_SCE_IRQn, STM32_CAN1_IRQ_PRIORITY); - RCC->APB1ENR |= RCC_APB1ENR_CAN1EN; - } -#endif + if (&CAND1 == canp) { + NVICEnableVector(USB_HP_CAN1_TX_IRQn, STM32_CAN1_IRQ_PRIORITY); + NVICEnableVector(USB_LP_CAN1_RX0_IRQn, STM32_CAN1_IRQ_PRIORITY); + NVICEnableVector(CAN1_RX1_IRQn, STM32_CAN1_IRQ_PRIORITY); + NVICEnableVector(CAN1_SCE_IRQn, STM32_CAN1_IRQ_PRIORITY); + RCC->APB1ENR |= RCC_APB1ENR_CAN1EN; } - /* Configuration.*/ - canp->cd_can->MCR = canp->cd_config->cc_mcr; +#endif + + /* Entering initialization mode. */ + canp->cd_state = CAN_STARTING; + canp->cd_can->MCR = CAN_MCR_INRQ; + while ((canp->cd_can->MSR & CAN_MSR_INAK) == 0) + chThdSleepS(1); + /* Initialization.*/ canp->cd_can->BTR = canp->cd_config->cc_btr; + canp->cd_can->MCR = canp->cd_config->cc_mcr; canp->cd_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 | @@ -196,7 +200,6 @@ void can_lld_stop(CANDriver *canp) { #if USE_STM32_CAN1 if (&CAND1 == canp) { CAN1->MCR = 0x00010002; /* Register reset value. */ - CAN1->BTR = 0x01230000; /* Register reset value. */ CAN1->IER = 0x00000000; /* All sources disabled. */ NVICDisableVector(USB_HP_CAN1_TX_IRQn); NVICDisableVector(USB_LP_CAN1_RX0_IRQn); diff --git a/os/hal/platforms/STM32/can_lld.h b/os/hal/platforms/STM32/can_lld.h index 422249cef..9f54e4cc6 100644 --- a/os/hal/platforms/STM32/can_lld.h +++ b/os/hal/platforms/STM32/can_lld.h @@ -29,11 +29,15 @@ #if CH_HAL_USE_CAN || defined(__DOXYGEN__) +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + /** * @brief This switch defines whether the driver implementation supports * a low power switch mode with automatic an wakeup feature. */ -#define CAN_SUPPORTS_SLEEP TRUE +#define CAN_SUPPORTS_SLEEP TRUE /*===========================================================================*/ /* Driver pre-compile time settings. */ @@ -69,10 +73,6 @@ #define CAN_USE_SLEEP_MODE FALSE #endif /* !CAN_SUPPORTS_SLEEP */ -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - /*===========================================================================*/ /* Driver data structures and types. */ /*===========================================================================*/ @@ -99,6 +99,39 @@ typedef struct { }; } CANFrame; +/** + * @brief CAN filter. + * @note Refer to the STM32 reference manual for info about filters. + */ +typedef struct { + /** + * @brief Filter mode. + * @note This bit represent the CAN_FM1R register bit associated to this + * filter (0=mask mode, 1=list mode). + */ + uint32_t cf_mode:1; + /** + * @brief Filter sclae. + * @note This bit represent the CAN_FS1R register bit associated to this + * filter (0=16 bits mode, 1=32 bits mode). + */ + uint32_t cf_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. + */ + uint32_t cf_assignment:1; + /** + * @brief Filter register 1 (identifier). + */ + uint32_t cf_register1; + /** + * @brief Filter register 2 (mask/identifier depending on cf_mode=0/1). + */ + uint32_t cf_register2; +} CANFilter; + /** * @brief Driver configuration structure. */ @@ -115,6 +148,18 @@ typedef struct { * their status in this field. */ uint32_t cc_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 cc_num; + /** + * @brief Pointer to an array of @p CANFilter structures. + * @note This field can be set to @p NULL if the field @p cc_num is set to + * zero. + */ + const CANFilter *cc_filters; } CANConfig; /** @@ -138,7 +183,12 @@ typedef struct { */ Semaphore cd_rxsem; /** - * @brief One or more frames become available. + * @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. */ EventSource cd_rxfull_event; /** diff --git a/os/hal/src/can.c b/os/hal/src/can.c index 7c6cdd656..e4258050e 100644 --- a/os/hal/src/can.c +++ b/os/hal/src/can.c @@ -69,12 +69,18 @@ void canStart(CANDriver *canp, const CANConfig *config) { chDbgCheck((canp != NULL) && (config != NULL), "canStart"); chSysLock(); - chDbgAssert((canp->cd_state == CAN_STOP) || (canp->cd_state == CAN_READY), + chDbgAssert((canp->cd_state == CAN_STOP) || + (canp->cd_state == CAN_STARTING) || + (canp->cd_state == CAN_READY), "canStart(), #1", "invalid state"); - canp->cd_config = config; - can_lld_start(canp); - canp->cd_state = CAN_READY; + while (canp->cd_state == CAN_STARTING) + chThdSleepS(1); + if (canp->cd_state == CAN_STOP) { + canp->cd_config = config; + can_lld_start(canp); + canp->cd_state = CAN_READY; + } chSysUnlock(); } @@ -145,12 +151,15 @@ msg_t canTransmit(CANDriver *canp, const CANFrame *cfp, systime_t timeout) { * @param[out] cfp pointer to the buffer where the CAN frame is copied * @param[in] timeout the number of ticks before the operation timeouts, * the following special values are allowed: - * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_IMMEDIATE immediate timeout (useful in an + * event driven scenario where a thread never blocks + * for I/O). * - @a TIME_INFINITE no timeout. * . * @return The operation result. * @retval RDY_OK a frame has been received and placed in the buffer. - * @retval RDY_TIMEOUT operation not finished within the specified time. + * @retval RDY_TIMEOUT operation not finished within the specified time or + * frame not immediately available if invoked using @p TIME_IMMEDIATE. * @retval RDY_RESET driver stopped while waiting. */ msg_t canReceive(CANDriver *canp, CANFrame *cfp, systime_t timeout) { diff --git a/os/hal/templates/meta/driver_lld.h b/os/hal/templates/meta/driver_lld.h index 92194664e..fe3786244 100644 --- a/os/hal/templates/meta/driver_lld.h +++ b/os/hal/templates/meta/driver_lld.h @@ -28,11 +28,11 @@ #define _XXX_LLD_H_ /*===========================================================================*/ -/* Driver pre-compile time settings. */ +/* Driver constants. */ /*===========================================================================*/ /*===========================================================================*/ -/* Driver constants. */ +/* Driver pre-compile time settings. */ /*===========================================================================*/ /*===========================================================================*/