diff options
author | gdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2009-12-04 20:56:51 +0000 |
---|---|---|
committer | gdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2009-12-04 20:56:51 +0000 |
commit | 03a0255b043e9a418e96cf3b3e0564ed2f6efe8e (patch) | |
tree | 299c695051e588fb6e7e4f25fc0ad830bc1d7477 /os/hal | |
parent | 980f0b675138676b1e977ca456dc73c3b2502596 (diff) | |
download | ChibiOS-03a0255b043e9a418e96cf3b3e0564ed2f6efe8e.tar.gz ChibiOS-03a0255b043e9a418e96cf3b3e0564ed2f6efe8e.tar.bz2 ChibiOS-03a0255b043e9a418e96cf3b3e0564ed2f6efe8e.zip |
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1374 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal')
-rw-r--r-- | os/hal/platforms/STM32/can_lld.c | 46 | ||||
-rw-r--r-- | os/hal/platforms/STM32/can_lld.h | 43 | ||||
-rw-r--r-- | os/hal/templates/can_lld.c | 29 | ||||
-rw-r--r-- | os/hal/templates/can_lld.h | 74 |
4 files changed, 143 insertions, 49 deletions
diff --git a/os/hal/platforms/STM32/can_lld.c b/os/hal/platforms/STM32/can_lld.c index 624f9028b..26cbadc43 100644 --- a/os/hal/platforms/STM32/can_lld.c +++ b/os/hal/platforms/STM32/can_lld.c @@ -213,6 +213,10 @@ void can_lld_start(CANDriver *canp) { }
cfp++;
fmask <<= 1;
+ /* Gives a chance for preemption since this is a rather long loop.*/
+ chSysUnlock();
+ chThdYield();
+ chSysLock();
}
}
else {
@@ -239,7 +243,7 @@ void can_lld_start(CANDriver *canp) { */
void can_lld_stop(CANDriver *canp) {
- /* If in ready state then disables the CAN clock.*/
+ /* If in ready state then disables the CAN peripheral.*/
if (canp->cd_state == CAN_READY) {
#if USE_STM32_CAN1
if (&CAND1 == canp) {
@@ -273,9 +277,31 @@ bool_t can_lld_can_transmit(CANDriver *canp) { * @brief Inserts a frame into the transmit queue.
* * @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
*/
void can_lld_transmit(CANDriver *canp, const CANTxFrame *ctfp) {
+ uint32_t tir;
+ CAN_TxMailBox_TypeDef *tmbp;
+
+ /* Pointer to a free transmission mailbox.*/
+ tmbp = &canp->cd_can->sTxMailBox[(canp->cd_can->TSR & CAN_TSR_CODE) >> 24];
+
+ /* Preparing the message.*/
+ if (ctfp->cf_IDE)
+ tir = ((uint32_t)ctfp->cf_EID << 3) |
+ ((uint32_t)ctfp->cf_IDE << 2) |
+ ((uint32_t)ctfp->cf_RTR << 1);
+ else
+ tir = ((uint32_t)ctfp->cf_SID << 24) |
+ ((uint32_t)ctfp->cf_IDE << 2) |
+ ((uint32_t)ctfp->cf_RTR << 1);
+ tmbp->TDTR = ctfp->cf_DLC;
+ tmbp->TDLR = ctfp->cf_data32[0];
+ tmbp->TDHR = ctfp->cf_data32[1];
+ tmbp->TIR = tir | CAN_TI0R_TXRQ;
+
+ /* Re-enables the interrupt in order to generate events again.*/
+ canp->cd_can->IER |= CAN_IER_TMEIE;
}
/**
@@ -296,7 +322,7 @@ bool_t can_lld_can_receive(CANDriver *canp) { * @brief Receives a frame from the input queue.
* * @param[in] canp pointer to the @p CANDriver object
- * @param[out] cfp pointer to the buffer where the CAN frame is copied
+ * @param[out] crfp pointer to the buffer where the CAN frame is copied
*/
void can_lld_receive(CANDriver *canp, CANRxFrame *crfp) {
uint32_t r;
@@ -310,13 +336,19 @@ void can_lld_receive(CANDriver *canp, CANRxFrame *crfp) { crfp->cf_RTR = r & CAN_RI0R_RTR;
crfp->cf_IDE = r & CAN_RI0R_IDE;
if (crfp->cf_IDE)
- crfp->cf_ID = r >> 3;
+ crfp->cf_EID = r >> 3;
else
- crfp->cf_ID = r >> 24;
+ crfp->cf_SID = 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 the queue is empty re-enables the interrupt in order to generate
+ events again.*/
+ if ((canp->cd_can->RF0R & CAN_RF0R_FMP0) == 0)
+ canp->cd_can->IER |= CAN_IER_FMPIE0;
}
#if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__)
@@ -327,7 +359,7 @@ void can_lld_receive(CANDriver *canp, CANRxFrame *crfp) { */
void can_lld_sleep(CANDriver *canp) {
- (void)canp;
+ canp->cd_can->MCR |= CAN_MCR_SLEEP;
}
/**
@@ -337,7 +369,7 @@ void can_lld_sleep(CANDriver *canp) { */
void can_lld_wakeup(CANDriver *canp) {
- (void)canp;
+ canp->cd_can->MCR &= ~CAN_MCR_SLEEP;
}
#endif /* CAN_USE_SLEEP_MODE */
diff --git a/os/hal/platforms/STM32/can_lld.h b/os/hal/platforms/STM32/can_lld.h index f995ffb16..b7dff8ced 100644 --- a/os/hal/platforms/STM32/can_lld.h +++ b/os/hal/platforms/STM32/can_lld.h @@ -97,10 +97,19 @@ typedef uint32_t canstatus_t; * 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. */
+ 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. */
+ };
+ union {
+ struct {
+ uint32_t cf_SID:11; /**< @brief Standard identifier.*/
+ };
+ struct {
+ uint32_t cf_EID:29; /**< @brief Extended identifier.*/
+ };
+ };
union {
uint8_t cf_data8[8]; /**< @brief Frame data. */
uint16_t cf_data16[4]; /**< @brief Frame data. */
@@ -114,12 +123,23 @@ typedef struct { * 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. */
- uint8_t cf_IDE:1; /**< @brief Identifier type. */
- uint32_t cf_ID; /**< @brief Frame identifier. */
+ struct {
+ uint8_t cf_FMI; /**< @brief Filter id. */
+ uint16_t cf_TIME; /**< @brief Time stamp. */
+ };
+ 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. */
+ };
+ union {
+ struct {
+ uint32_t cf_SID:11; /**< @brief Standard identifier.*/
+ };
+ struct {
+ uint32_t cf_EID:29; /**< @brief Extended identifier.*/
+ };
+ };
union {
uint8_t cf_data8[8]; /**< @brief Frame data. */
uint16_t cf_data16[4]; /**< @brief Frame data. */
@@ -216,7 +236,8 @@ typedef struct { * 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. + * invoking @p chReceive() when listening to this event. This behavior
+ * minimizes the interrupt served by the system because CAN traffic. */
EventSource cd_rxfull_event;
/**
diff --git a/os/hal/templates/can_lld.c b/os/hal/templates/can_lld.c index f2f54e66d..792c4f888 100644 --- a/os/hal/templates/can_lld.c +++ b/os/hal/templates/can_lld.c @@ -63,10 +63,6 @@ void can_lld_init(void) { */
void can_lld_start(CANDriver *canp) {
- if (canp->can_state == CAN_STOP) {
- /* Clock activation.*/
- }
- /* Configuration.*/
}
/**
@@ -76,8 +72,13 @@ void can_lld_start(CANDriver *canp) { */
void can_lld_stop(CANDriver *canp) {
+ /* If in ready state then disables the CAN peripheral.*/
+ if (canp->cd_state == CAN_READY) {
+
+ }
}
+
/**
* @brief Determines whether a frame can be transmitted.
* @@ -94,16 +95,12 @@ bool_t can_lld_can_transmit(CANDriver *canp) { /**
* @brief Inserts a frame into the transmit queue.
- * - * @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. + * @param[in] canp pointer to the @p CANDriver object
+ * @param[in] ctfp pointer to the CAN frame to be transmitted
*/
-msg_t can_lld_transmit(CANDriver *canp, const CANFrame *cfp) {
+void can_lld_transmit(CANDriver *canp, const CANTxFrame *ctfp) {
- return RDY_OK;
}
/**
@@ -122,16 +119,12 @@ bool_t can_lld_can_receive(CANDriver *canp) { /**
* @brief Receives a frame from the input queue.
- * - * @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.
+ * @param[in] canp pointer to the @p CANDriver object
+ * @param[out] crfp pointer to the buffer where the CAN frame is copied
*/
-msg_t can_lld_receive(CANDriver *canp, CANFrame *cfp) {
+void can_lld_receive(CANDriver *canp, CANRxFrame *crfp) {
- return RDY_OK;
}
#if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__)
diff --git a/os/hal/templates/can_lld.h b/os/hal/templates/can_lld.h index 14588c0d5..9b1124a18 100644 --- a/os/hal/templates/can_lld.h +++ b/os/hal/templates/can_lld.h @@ -29,6 +29,10 @@ #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. @@ -53,10 +57,6 @@ #endif /* !CAN_SUPPORTS_SLEEP */
/*===========================================================================*/
-/* Driver constants. */
-/*===========================================================================*/
-
-/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
@@ -66,21 +66,63 @@ 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.
+ */
+typedef struct {
+ 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. */
+ };
+ union {
+ struct {
+ uint32_t cf_SID:11; /**< @brief Standard identifier.*/
+ };
+ struct {
+ uint32_t cf_EID:29; /**< @brief Extended 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. + * 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_IDE:1; /**< @brief Identifier type. */
- uint8_t cf_RTR:1; /**< @brief Frame type. */
- uint32_t cf_id; /**< @brief Frame identifier. */
+ 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. */
+ };
+ union {
+ struct {
+ uint32_t cf_SID:11; /**< @brief Standard identifier.*/
+ };
+ struct {
+ uint32_t cf_EID:29; /**< @brief Extended 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.
+ * @note It could not be present on some architectures.
+ */
+typedef struct {
+} CANFilter;
/**
* @brief Driver configuration structure.
@@ -111,6 +153,12 @@ typedef struct { Semaphore cd_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 <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. This behavior
+ * minimizes the interrupt served by the system because CAN traffic.
*/
EventSource cd_rxfull_event;
/**
@@ -149,9 +197,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);
|