git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1373 35acf78f-673a-0410-8e92-d51de3d6d3f4

master
gdisirio 2009-12-03 16:26:54 +00:00
parent 20bf146ed8
commit 980f0b6751
4 changed files with 116 additions and 36 deletions

View File

@ -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);

View File

@ -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) {
void can_lld_receive(CANDriver *canp, CANRxFrame *crfp) {
uint32_t r;
return RDY_OK;
/* 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 */

View File

@ -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_IDE:1; /**< @brief Identifier type. */
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;
} 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. */
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. */
};
} 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);

View File

@ -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;
}
/**