aboutsummaryrefslogtreecommitdiffstats
path: root/os
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2009-12-02 16:24:32 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2009-12-02 16:24:32 +0000
commitc2ad39132395d52a3894c13f978da2349f650201 (patch)
tree84ba493fbde95a6a2fb2057cdd9d60a0498b3ab3 /os
parent3d182788ee7386b0fa53b4aee08fe8146d67d3b0 (diff)
downloadChibiOS-c2ad39132395d52a3894c13f978da2349f650201.tar.gz
ChibiOS-c2ad39132395d52a3894c13f978da2349f650201.tar.bz2
ChibiOS-c2ad39132395d52a3894c13f978da2349f650201.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1370 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os')
-rw-r--r--os/hal/include/can.h5
-rw-r--r--os/hal/platforms/STM32/can_lld.c29
-rw-r--r--os/hal/platforms/STM32/can_lld.h62
-rw-r--r--os/hal/src/can.c21
-rw-r--r--os/hal/templates/meta/driver_lld.h4
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. */
@@ -70,10 +74,6 @@
#endif /* !CAN_SUPPORTS_SLEEP */
/*===========================================================================*/
-/* Driver constants. */
-/*===========================================================================*/
-
-/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
@@ -100,6 +100,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.
*/
typedef struct {
@@ -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 <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.
*/
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. */
/*===========================================================================*/
/*===========================================================================*/