aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2009-12-03 16:26:54 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2009-12-03 16:26:54 +0000
commit980f0b675138676b1e977ca456dc73c3b2502596 (patch)
treebdb8b986847edcd572d080f522a68d03f7480625 /os/hal
parent20bf146ed82de1415d7a2de5dc60442c5405a850 (diff)
downloadChibiOS-980f0b675138676b1e977ca456dc73c3b2502596.tar.gz
ChibiOS-980f0b675138676b1e977ca456dc73c3b2502596.tar.bz2
ChibiOS-980f0b675138676b1e977ca456dc73c3b2502596.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1373 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal')
-rw-r--r--os/hal/include/can.h4
-rw-r--r--os/hal/platforms/STM32/can_lld.c84
-rw-r--r--os/hal/platforms/STM32/can_lld.h40
-rw-r--r--os/hal/src/can.c24
4 files changed, 116 insertions, 36 deletions
diff --git a/os/hal/include/can.h b/os/hal/include/can.h
index 54623945e..c8027af39 100644
--- a/os/hal/include/can.h
+++ b/os/hal/include/can.h
@@ -78,8 +78,8 @@ extern "C" {
void canObjectInit(CANDriver *canp);
void canStart(CANDriver *canp, const CANConfig *config);
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);
+ msg_t canTransmit(CANDriver *canp, const CANTxFrame *ctfp, systime_t timeout);
+ msg_t canReceive(CANDriver *canp, CANRxFrame *crfp, systime_t timeout);
canstatus_t canGetAndClearFlags(CANDriver *canp);
#if CAN_USE_SLEEP_MODE
void canSleep(CANDriver *canp);
diff --git a/os/hal/platforms/STM32/can_lld.c b/os/hal/platforms/STM32/can_lld.c
index 86c8ecbf5..624f9028b 100644
--- a/os/hal/platforms/STM32/can_lld.c
+++ b/os/hal/platforms/STM32/can_lld.c
@@ -179,9 +179,53 @@ void can_lld_start(CANDriver *canp) {
canp->cd_can->MCR = CAN_MCR_INRQ;
while ((canp->cd_can->MSR & CAN_MSR_INAK) == 0)
chThdSleepS(1);
- /* Initialization.*/
+ /* BTR initialization.*/
canp->cd_can->BTR = canp->cd_config->cc_btr;
+ /* MCR initialization.*/
canp->cd_can->MCR = canp->cd_config->cc_mcr;
+ /* Filters initialization.*/
+ canp->cd_can->FMR |= CAN_FMR_FINIT;
+ if (canp->cd_config->cc_num > 0) {
+ uint32_t i, fmask;
+ CAN_FilterRegister_TypeDef *cfp;
+
+ canp->cd_can->FA1R = 0;
+ canp->cd_can->FM1R = 0;
+ canp->cd_can->FS1R = 0;
+ canp->cd_can->FFA1R = 0;
+ cfp = canp->cd_can->sFilterRegister;
+ fmask = 1;
+ for (i = 0; i < CAN_MAX_FILTERS; i++) {
+ if (i < canp->cd_config->cc_num) {
+ if (canp->cd_config->cc_filters[i].cf_mode)
+ canp->cd_can->FM1R |= fmask;
+ if (canp->cd_config->cc_filters[i].cf_scale)
+ canp->cd_can->FS1R |= fmask;
+ if (canp->cd_config->cc_filters[i].cf_assignment)
+ canp->cd_can->FFA1R |= fmask;
+ cfp->FR1 = canp->cd_config->cc_filters[i].cf_register1;
+ cfp->FR2 = canp->cd_config->cc_filters[i].cf_register2;
+ canp->cd_can->FA1R |= fmask;
+ }
+ else {
+ cfp->FR1 = 0;
+ cfp->FR2 = 0;
+ }
+ cfp++;
+ fmask <<= 1;
+ }
+ }
+ else {
+ /* Setup a default filter.*/
+ canp->cd_can->sFilterRegister[0].FR1 = 0;
+ canp->cd_can->sFilterRegister[0].FR2 = 0;
+ canp->cd_can->FM1R = 0;
+ canp->cd_can->FFA1R = 0;
+ canp->cd_can->FS1R = 1;
+ canp->cd_can->FA1R = 1;
+ }
+ canp->cd_can->FMR &= ~CAN_FMR_FINIT;
+ /* Interrupt sources initialization.*/
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 |
@@ -222,7 +266,7 @@ void can_lld_stop(CANDriver *canp) {
*/
bool_t can_lld_can_transmit(CANDriver *canp) {
- return FALSE;
+ return (canp->cd_can->TSR & CAN_TSR_TME) != 0;
}
/**
@@ -230,13 +274,8 @@ bool_t can_lld_can_transmit(CANDriver *canp) {
*
* @param[in] canp pointer to the @p CANDriver object
* @param[in] cfp pointer to the CAN frame to be transmitted
- *
- * @return The operation status.
- * @retval RDY_OK frame transmitted.
*/
-msg_t can_lld_transmit(CANDriver *canp, const CANFrame *cfp) {
-
- return RDY_OK;
+void can_lld_transmit(CANDriver *canp, const CANTxFrame *ctfp) {
}
/**
@@ -250,7 +289,7 @@ msg_t can_lld_transmit(CANDriver *canp, const CANFrame *cfp) {
*/
bool_t can_lld_can_receive(CANDriver *canp) {
- return FALSE;
+ return (canp->cd_can->RF0R & CAN_RF0R_FMP0) > 0;
}
/**
@@ -258,13 +297,26 @@ bool_t can_lld_can_receive(CANDriver *canp) {
*
* @param[in] canp pointer to the @p CANDriver object
* @param[out] cfp pointer to the buffer where the CAN frame is copied
- *
- * @return The operation status.
- * @retval RDY_OK frame received.
*/
-msg_t can_lld_receive(CANDriver *canp, CANFrame *cfp) {
-
- return RDY_OK;
+void can_lld_receive(CANDriver *canp, CANRxFrame *crfp) {
+ uint32_t r;
+
+ /* Fetches the message.*/
+ r = canp->cd_can->sFIFOMailBox[0].RDTR;
+ crfp->cf_DLC = r & CAN_RDT0R_DLC;
+ crfp->cf_FMI = (uint8_t)(r >> 8);
+ crfp->cf_TIME = (uint16_t)(r >> 16);
+ r = canp->cd_can->sFIFOMailBox[0].RIR;
+ crfp->cf_RTR = r & CAN_RI0R_RTR;
+ crfp->cf_IDE = r & CAN_RI0R_IDE;
+ if (crfp->cf_IDE)
+ crfp->cf_ID = r >> 3;
+ else
+ crfp->cf_ID = r >> 24;
+ crfp->cf_data32[0] = canp->cd_can->sFIFOMailBox[0].RDLR;
+ crfp->cf_data32[1] = canp->cd_can->sFIFOMailBox[0].RDHR;
+ /* Releases the mailbox.*/
+ canp->cd_can->RF0R |= CAN_RF0R_RFOM0;
}
#if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__)
@@ -275,6 +327,7 @@ msg_t can_lld_receive(CANDriver *canp, CANFrame *cfp) {
*/
void can_lld_sleep(CANDriver *canp) {
+ (void)canp;
}
/**
@@ -284,6 +337,7 @@ void can_lld_sleep(CANDriver *canp) {
*/
void can_lld_wakeup(CANDriver *canp) {
+ (void)canp;
}
#endif /* CAN_USE_SLEEP_MODE */
diff --git a/os/hal/platforms/STM32/can_lld.h b/os/hal/platforms/STM32/can_lld.h
index 9f54e4cc6..f995ffb16 100644
--- a/os/hal/platforms/STM32/can_lld.h
+++ b/os/hal/platforms/STM32/can_lld.h
@@ -39,6 +39,15 @@
*/
#define CAN_SUPPORTS_SLEEP TRUE
+/**
+ * @brief Manimum number of CAN filters.
+ */
+#if defined(STM32F10X_CL) || defined(__DOXYGEN__)
+#define CAN_MAX_FILTERS 28
+#else
+#define CAN_MAX_FILTERS 14
+#endif
+
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
@@ -83,21 +92,40 @@
typedef uint32_t canstatus_t;
/**
- * @brief CAN frame.
+ * @brief CAN transmission frame.
* @note Accessing the frame data as word16 or word32 is not portable because
- * machine data endianness, it can be still useful for a quick filling.
+ * machine data endianness, it can be still useful for a quick filling.
*/
typedef struct {
uint8_t cf_DLC:4; /**< @brief Data length. */
+ uint8_t cf_RTR:1; /**< @brief Frame type. */
uint8_t cf_IDE:1; /**< @brief Identifier type. */
+ uint32_t cf_ID; /**< @brief Frame identifier. */
+ union {
+ uint8_t cf_data8[8]; /**< @brief Frame data. */
+ uint16_t cf_data16[4]; /**< @brief Frame data. */
+ uint32_t cf_data32[2]; /**< @brief Frame data. */
+ };
+} CANTxFrame;
+
+/**
+ * @brief CAN received frame.
+ * @note Accessing the frame data as word16 or word32 is not portable because
+ * machine data endianness, it can be still useful for a quick filling.
+ */
+typedef struct {
+ uint16_t cf_TIME; /**< @brief Time stamp. */
+ uint8_t cf_FMI; /**< @brief Filter id. */
+ uint8_t cf_DLC:4; /**< @brief Data length. */
uint8_t cf_RTR:1; /**< @brief Frame type. */
- uint32_t cf_id; /**< @brief Frame identifier. */
+ uint8_t cf_IDE:1; /**< @brief Identifier type. */
+ uint32_t cf_ID; /**< @brief Frame identifier. */
union {
uint8_t cf_data8[8]; /**< @brief Frame data. */
uint16_t cf_data16[4]; /**< @brief Frame data. */
uint32_t cf_data32[2]; /**< @brief Frame data. */
};
-} CANFrame;
+} CANRxFrame;
/**
* @brief CAN filter.
@@ -236,9 +264,9 @@ extern "C" {
void can_lld_start(CANDriver *canp);
void can_lld_stop(CANDriver *canp);
bool_t can_lld_can_transmit(CANDriver *canp);
- msg_t can_lld_transmit(CANDriver *canp, const CANFrame *cfp);
+ void can_lld_transmit(CANDriver *canp, const CANTxFrame *crfp);
bool_t can_lld_can_receive(CANDriver *canp);
- msg_t can_lld_receive(CANDriver *canp, CANFrame *cfp);
+ void can_lld_receive(CANDriver *canp, CANRxFrame *ctfp);
#if CAN_USE_SLEEP_MODE
void can_lld_sleep(CANDriver *canp);
void can_lld_wakeup(CANDriver *canp);
diff --git a/os/hal/src/can.c b/os/hal/src/can.c
index e4258050e..3cd10126d 100644
--- a/os/hal/src/can.c
+++ b/os/hal/src/can.c
@@ -110,7 +110,7 @@ void canStop(CANDriver *canp) {
* @note Trying to transmit while in sleep mode simply enqueues the thread.
*
* @param[in] canp pointer to the @p CANDriver object
- * @param[in] cfp pointer to the CAN frame to be transmitted
+ * @param[in] ctfp pointer to the CAN frame to be transmitted
* @param[in] timeout the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
@@ -121,25 +121,24 @@ void canStop(CANDriver *canp) {
* @retval RDY_TIMEOUT operation not finished within the specified time.
* @retval RDY_RESET driver stopped while waiting.
*/
-msg_t canTransmit(CANDriver *canp, const CANFrame *cfp, systime_t timeout) {
- msg_t msg;
+msg_t canTransmit(CANDriver *canp, const CANTxFrame *ctfp, systime_t timeout) {
- chDbgCheck((canp != NULL) && (cfp != NULL), "canTransmit");
+ chDbgCheck((canp != NULL) && (ctfp != NULL), "canTransmit");
chSysLock();
chDbgAssert((canp->cd_state == CAN_READY) || (canp->cd_state == CAN_SLEEP),
"canTransmit(), #1",
"invalid state");
if ((canp->cd_state == CAN_SLEEP) || !can_lld_can_transmit(canp)) {
- msg = chSemWaitTimeoutS(&canp->cd_txsem, timeout);
+ msg_t msg = chSemWaitTimeoutS(&canp->cd_txsem, timeout);
if (msg != RDY_OK) {
chSysUnlock();
return msg;
}
}
- msg = can_lld_transmit(canp, cfp);
+ can_lld_transmit(canp, ctfp);
chSysUnlock();
- return msg;
+ return RDY_OK;
}
/**
@@ -162,25 +161,24 @@ msg_t canTransmit(CANDriver *canp, const CANFrame *cfp, systime_t timeout) {
* 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) {
- msg_t msg;
+msg_t canReceive(CANDriver *canp, CANRxFrame *crfp, systime_t timeout) {
- chDbgCheck((canp != NULL) && (cfp != NULL), "canReceive");
+ chDbgCheck((canp != NULL) && (crfp != NULL), "canReceive");
chSysLock();
chDbgAssert((canp->cd_state == CAN_READY) || (canp->cd_state == CAN_SLEEP),
"canReceive(), #1",
"invalid state");
if ((canp->cd_state == CAN_SLEEP) || !can_lld_can_receive(canp)) {
- msg = chSemWaitTimeoutS(&canp->cd_rxsem, timeout);
+ msg_t msg = chSemWaitTimeoutS(&canp->cd_rxsem, timeout);
if (msg != RDY_OK) {
chSysUnlock();
return msg;
}
}
- msg = can_lld_receive(canp, cfp);
+ can_lld_receive(canp, crfp);
chSysUnlock();
- return msg;
+ return RDY_OK;
}
/**