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

This commit is contained in:
gdisirio 2009-12-01 16:32:16 +00:00
parent 8a433087af
commit 3d182788ee
6 changed files with 115 additions and 14 deletions

View File

@ -45,7 +45,7 @@
* @brief Enables the CAN subsystem. * @brief Enables the CAN subsystem.
*/ */
#if !defined(CH_HAL_USE_CAN) || defined(__DOXYGEN__) #if !defined(CH_HAL_USE_CAN) || defined(__DOXYGEN__)
#define CH_HAL_USE_CAN FALSE #define CH_HAL_USE_CAN TRUE
#endif #endif
/** /**

View File

@ -29,6 +29,27 @@
#if CH_HAL_USE_CAN || defined(__DOXYGEN__) #if CH_HAL_USE_CAN || defined(__DOXYGEN__)
/**
* @brief Errors rate warning.
*/
#define CAN_LIMIT_WARNING 1
/**
* @brief Errors rate error.
*/
#define CAN_LIMIT_ERROR 2
/**
* @brief Bus off condition reached.
*/
#define CAN_BUS_OFF_ERROR 4
/**
* @brief Framing error of some kind on the CAN bus.
*/
#define CAN_FRAMING_ERROR 8
/**
* @brief Overflow in receive queue.
*/
#define CAN_OVERFLOW_ERROR 16
/** /**
* @brief Driver state machine possible states. * @brief Driver state machine possible states.
*/ */

View File

@ -112,7 +112,7 @@ CH_IRQ_HANDLER(Vector6C) {
void adc_lld_init(void) { void adc_lld_init(void) {
#if USE_STM32_ADC1 #if USE_STM32_ADC1
/* ADC reset, ensures reset state in order to avoid truouble with JTAGs.*/ /* ADC reset, ensures reset state in order to avoid trouble with JTAGs.*/
RCC->APB2RSTR = RCC_APB2RSTR_ADC1RST; RCC->APB2RSTR = RCC_APB2RSTR_ADC1RST;
RCC->APB2RSTR = 0; RCC->APB2RSTR = 0;

View File

@ -68,12 +68,24 @@ CH_IRQ_HANDLER(Vector8C) {
* CAN1 RX0 interrupt handler. * CAN1 RX0 interrupt handler.
*/ */
CH_IRQ_HANDLER(Vector90) { CH_IRQ_HANDLER(Vector90) {
uint32_t rf0r;
CH_IRQ_PROLOGUE(); CH_IRQ_PROLOGUE();
/* No more events until the incoming messages queues are emptied.*/ rf0r = CAN1->RF0R;
CAN1->IER &= ~(CAN_IER_FMPIE0 | CAN_IER_FMPIE1); chSysLockFromIsr();
chEvtBroadcastI(&CAND1.cd_rxfull_event); if ((rf0r & CAN_RF0R_FMP0) > 0) {
/* No more receive events until the queue 0 has been emptied.*/
CAN1->IER &= ~CAN_IER_FMPIE0;
chEvtBroadcastI(&CAND1.cd_rxfull_event);
}
if ((rf0r & CAN_RF0R_FOVR0) > 0) {
/* Overflow events handling.*/
CAN1->RF0R = CAN_RF0R_FOVR0;
canAddFlagsI(&CAND1, CAN_OVERFLOW_ERROR);
chEvtBroadcastI(&CAND1.cd_error_event);
}
chSysUnlockFromIsr();
CH_IRQ_EPILOGUE(); CH_IRQ_EPILOGUE();
} }
@ -85,9 +97,7 @@ CH_IRQ_HANDLER(Vector94) {
CH_IRQ_PROLOGUE(); CH_IRQ_PROLOGUE();
/* No more events until the incoming messages queues are emptied.*/ chSysHalt(); /* Not supported (yet).*/
CAN1->IER &= ~(CAN_IER_FMPIE0 | CAN_IER_FMPIE1);
chEvtBroadcastI(&CAND1.cd_rxfull_event);
CH_IRQ_EPILOGUE(); CH_IRQ_EPILOGUE();
} }
@ -96,12 +106,32 @@ CH_IRQ_HANDLER(Vector94) {
* CAN1 SCE interrupt handler. * CAN1 SCE interrupt handler.
*/ */
CH_IRQ_HANDLER(Vector98) { CH_IRQ_HANDLER(Vector98) {
uint32_t msr;
CH_IRQ_PROLOGUE(); CH_IRQ_PROLOGUE();
canAddFlagsI(&CAND1, 1); msr = CAN1->MSR;
chEvtBroadcastI(&CAND1.cd_error_event); CAN1->MSR = CAN_MSR_ERRI | CAN_MSR_WKUI | CAN_MSR_SLAKI;
CAN1->MSR = CAN_MSR_ERRI; /* Wakeup event.*/
if (msr & CAN_MSR_WKUI) {
chSysLockFromIsr();
chEvtBroadcastI(&CAND1.cd_wakeup_event);
chSysUnlockFromIsr();
}
/* Error event.*/
if (msr & CAN_MSR_ERRI) {
canstatus_t flags;
uint32_t esr = CAN1->ESR;
CAN1->ESR &= ~CAN_ESR_LEC;
flags = (canstatus_t)(esr & 7);
if ((esr & CAN_ESR_LEC) > 0)
flags |= CAN_FRAMING_ERROR;
chSysLockFromIsr();
canAddFlagsI(&CAND1, flags);
chEvtBroadcastI(&CAND1.cd_error_event);
chSysUnlockFromIsr();
}
CH_IRQ_EPILOGUE(); CH_IRQ_EPILOGUE();
} }
@ -115,6 +145,15 @@ CH_IRQ_HANDLER(Vector98) {
*/ */
void can_lld_init(void) { void can_lld_init(void) {
#if USE_STM32_CAN1
/* CAN reset, ensures reset state in order to avoid trouble with JTAGs.*/
RCC->APB1RSTR = RCC_APB1RSTR_CAN1RST;
RCC->APB1RSTR = 0;
/* Driver initialization.*/
canObjectInit(&CAND1);
CAND1.cd_can = CAN1;
#endif
} }
/** /**
@ -126,8 +165,23 @@ void can_lld_start(CANDriver *canp) {
if (canp->cd_state == CAN_STOP) { 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
} }
/* Configuration.*/ /* Configuration.*/
canp->cd_can->MCR = canp->cd_config->cc_mcr;
canp->cd_can->BTR = canp->cd_config->cc_btr;
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 |
CAN_IER_FOVIE0 | CAN_IER_FOVIE1;
} }
/** /**
@ -137,6 +191,21 @@ void can_lld_start(CANDriver *canp) {
*/ */
void can_lld_stop(CANDriver *canp) { void can_lld_stop(CANDriver *canp) {
/* If in ready state then disables the CAN clock.*/
if (canp->cd_state == CAN_READY) {
#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);
NVICDisableVector(CAN1_RX1_IRQn);
NVICDisableVector(CAN1_SCE_IRQn);
RCC->APB1ENR &= ~RCC_APB1ENR_CAN1EN;
}
#endif
}
} }
/** /**

View File

@ -40,7 +40,7 @@
/*===========================================================================*/ /*===========================================================================*/
/** /**
* @brief ADC1 driver enable switch. * @brief CAN1 driver enable switch.
* @details If set to @p TRUE the support for ADC1 is included. * @details If set to @p TRUE the support for ADC1 is included.
* @note The default is @p TRUE. * @note The default is @p TRUE.
*/ */
@ -48,6 +48,14 @@
#define USE_STM32_CAN1 TRUE #define USE_STM32_CAN1 TRUE
#endif #endif
/**
* @brief CAN1 interrupt priority level setting.
* @note @p BASEPRI_KERNEL >= @p STM32_SPI1_IRQ_PRIORITY > @p PRIORITY_PENDSV.
*/
#if !defined(STM32_CAN1_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_CAN1_IRQ_PRIORITY 0xB0
#endif
/** /**
* @brief Sleep mode related APIs inclusion switch. * @brief Sleep mode related APIs inclusion switch.
* @note This switch is enforced to @p FALSE if the driver implementation * @note This switch is enforced to @p FALSE if the driver implementation
@ -159,7 +167,7 @@ typedef struct {
/** /**
* @brief Pointer to the CAN registers. * @brief Pointer to the CAN registers.
*/ */
CAN_TypeDef *cd_canp; CAN_TypeDef *cd_can;
} CANDriver; } CANDriver;
/*===========================================================================*/ /*===========================================================================*/

View File

@ -50,6 +50,8 @@ void canObjectInit(CANDriver *canp) {
chSemInit(&canp->cd_rxsem, 0); chSemInit(&canp->cd_rxsem, 0);
chEvtInit(&canp->cd_rxfull_event); chEvtInit(&canp->cd_rxfull_event);
chEvtInit(&canp->cd_txempty_event); chEvtInit(&canp->cd_txempty_event);
chEvtInit(&canp->cd_error_event);
canp->cd_status = 0;
#if CAN_USE_SLEEP_MODE #if CAN_USE_SLEEP_MODE
chEvtInit(&canp->cd_sleep_event); chEvtInit(&canp->cd_sleep_event);
chEvtInit(&canp->cd_wakeup_event); chEvtInit(&canp->cd_wakeup_event);
@ -90,7 +92,8 @@ void canStop(CANDriver *canp) {
"canStop(), #1", "canStop(), #1",
"invalid state"); "invalid state");
can_lld_stop(canp); can_lld_stop(canp);
canp->cd_state = CAN_STOP; canp->cd_state = CAN_STOP;
canp->cd_status = 0;
chSysUnlock(); chSysUnlock();
} }