git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1373 35acf78f-673a-0410-8e92-d51de3d6d3f4
parent
20bf146ed8
commit
980f0b6751
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue