diff options
Diffstat (limited to 'os/hal')
-rw-r--r-- | os/hal/include/can.h | 9 | ||||
-rw-r--r-- | os/hal/platforms/STM32/adc_lld.c | 2 | ||||
-rw-r--r-- | os/hal/platforms/STM32/adc_lld.h | 2 | ||||
-rw-r--r-- | os/hal/platforms/STM32/can_lld.c | 63 | ||||
-rw-r--r-- | os/hal/platforms/STM32/can_lld.h | 63 | ||||
-rw-r--r-- | os/hal/src/can.c | 71 | ||||
-rw-r--r-- | os/hal/templates/can_lld.h | 39 |
7 files changed, 196 insertions, 53 deletions
diff --git a/os/hal/include/can.h b/os/hal/include/can.h index 3d43e1c51..3637c64b0 100644 --- a/os/hal/include/can.h +++ b/os/hal/include/can.h @@ -41,6 +41,14 @@ typedef enum { #include "can_lld.h"
+/**
+ * @brief Adds some flags to the CAN status mask.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ * @param[in] mask flags to be added to the status mask
+ */
+#define canAddFlagsI(canp, mask) ((canp)->cd_status |= (mask))
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -50,6 +58,7 @@ extern "C" { 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);
+ canstatus_t canGetAndClearFlags(CANDriver *canp);
#if CAN_USE_SLEEP_MODE
void canSleep(CANDriver *canp);
void canWakeup(CANDriver *canp);
diff --git a/os/hal/platforms/STM32/adc_lld.c b/os/hal/platforms/STM32/adc_lld.c index e90448fa3..1213484e2 100644 --- a/os/hal/platforms/STM32/adc_lld.c +++ b/os/hal/platforms/STM32/adc_lld.c @@ -33,8 +33,8 @@ /* Low Level Driver exported variables. */
/*===========================================================================*/
-#if USE_STM32_ADC1 || defined(__DOXYGEN__)
/** @brief ADC1 driver identifier.*/
+#if USE_STM32_ADC1 || defined(__DOXYGEN__)
ADCDriver ADCD1;
#endif
diff --git a/os/hal/platforms/STM32/adc_lld.h b/os/hal/platforms/STM32/adc_lld.h index 2b254d7af..f9950afd5 100644 --- a/os/hal/platforms/STM32/adc_lld.h +++ b/os/hal/platforms/STM32/adc_lld.h @@ -251,7 +251,7 @@ typedef struct { /** @cond never*/
#if USE_STM32_ADC1
-ADCDriver ADCD1;
+extern ADCDriver ADCD1;
#endif
#ifdef __cplusplus
diff --git a/os/hal/platforms/STM32/can_lld.c b/os/hal/platforms/STM32/can_lld.c index 91831cff1..30d270a37 100644 --- a/os/hal/platforms/STM32/can_lld.c +++ b/os/hal/platforms/STM32/can_lld.c @@ -33,6 +33,11 @@ /* Low Level Driver exported variables. */
/*===========================================================================*/
+/** @brief ADC1 driver identifier.*/
+#if USE_STM32_CAN1 || defined(__DOXYGEN__)
+CANDriver CAND1;
+#endif
+
/*===========================================================================*/
/* Low Level Driver local variables. */
/*===========================================================================*/
@@ -45,6 +50,62 @@ /* Low Level Driver interrupt handlers. */
/*===========================================================================*/
+/*
+ * CAN1 TX interrupt handler.
+ */
+CH_IRQ_HANDLER(Vector8C) {
+
+ CH_IRQ_PROLOGUE();
+
+ /* No more events until a message is transmitted.*/
+ CAN1->IER &= ~CAN_IER_TMEIE;
+ chEvtBroadcastI(&CAND1.cd_txempty_event);
+
+ CH_IRQ_EPILOGUE();
+}
+
+/*
+ * CAN1 RX0 interrupt handler.
+ */
+CH_IRQ_HANDLER(Vector90) {
+
+ CH_IRQ_PROLOGUE();
+
+ /* No more events until the incoming messages queues are emptied.*/
+ CAN1->IER &= ~(CAN_IER_FMPIE0 | CAN_IER_FMPIE1);
+ chEvtBroadcastI(&CAND1.cd_rxfull_event);
+
+ CH_IRQ_EPILOGUE();
+}
+
+/*
+ * CAN1 RX1 interrupt handler.
+ */
+CH_IRQ_HANDLER(Vector94) {
+
+ CH_IRQ_PROLOGUE();
+
+ /* No more events until the incoming messages queues are emptied.*/
+ CAN1->IER &= ~(CAN_IER_FMPIE0 | CAN_IER_FMPIE1);
+ chEvtBroadcastI(&CAND1.cd_rxfull_event);
+
+ CH_IRQ_EPILOGUE();
+}
+
+/*
+ * CAN1 SCE interrupt handler.
+ */
+CH_IRQ_HANDLER(Vector98) {
+
+ CH_IRQ_PROLOGUE();
+
+ canAddFlagsI(&CAND1, 1);
+ chEvtBroadcastI(&CAND1.cd_error_event);
+ CAN1->MSR = CAN_MSR_ERRI;
+
+ CH_IRQ_EPILOGUE();
+}
+
/*===========================================================================*/
/* Low Level Driver exported functions. */
/*===========================================================================*/
@@ -63,7 +124,7 @@ void can_lld_init(void) { */
void can_lld_start(CANDriver *canp) {
- if (canp->can_state == CAN_STOP) {
+ if (canp->cd_state == CAN_STOP) {
/* Clock activation.*/
}
/* Configuration.*/
diff --git a/os/hal/platforms/STM32/can_lld.h b/os/hal/platforms/STM32/can_lld.h index 6b7cf3b6c..a02ce15fc 100644 --- a/os/hal/platforms/STM32/can_lld.h +++ b/os/hal/platforms/STM32/can_lld.h @@ -40,6 +40,15 @@ /*===========================================================================*/
/**
+ * @brief ADC1 driver enable switch.
+ * @details If set to @p TRUE the support for ADC1 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(USE_STM32_CAN1) || defined(__DOXYGEN__)
+#define USE_STM32_CAN1 TRUE
+#endif
+
+/**
* @brief Sleep mode related APIs inclusion switch.
* @note This switch is enforced to @p FALSE if the driver implementation
* does not support the sleep mode. @@ -61,6 +70,11 @@ /*===========================================================================*/
/**
+ * @brief CAN status flags. + */
+typedef uint32_t canstatus_t;
+
+/**
* @brief CAN 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. @@ -79,9 +93,20 @@ typedef struct { /**
* @brief Driver configuration structure.
- * @note It could be empty on some architectures.
*/
typedef struct {
+ /**
+ * @brief CAN MCR register initialization data.
+ * @note Some bits in this register are enforced by the driver regardless
+ * their status in this field.
+ */
+ uint32_t cc_mcr;
+ /**
+ * @brief CAN BTR register initialization data.
+ * @note Some bits in this register are enforced by the driver regardless
+ * their status in this field.
+ */
+ uint32_t cc_btr;
} CANConfig;
/**
@@ -91,44 +116,61 @@ typedef struct { /**
* @brief Driver state.
*/
- canstate_t can_state;
+ canstate_t cd_state;
/**
* @brief Current configuration data.
*/
- const CANConfig *can_config;
+ const CANConfig *cd_config;
/**
* @brief Transmission queue semaphore. */
- Semaphore can_txsem;
+ Semaphore cd_txsem;
/**
* @brief Receive queue semaphore.
*/
- Semaphore can_rxsem;
+ Semaphore cd_rxsem;
/**
* @brief One or more frames become available. */
- EventSource can_rxfull_event;
+ EventSource cd_rxfull_event;
+ /**
+ * @brief One or more transmission slots become available.
+ */
+ EventSource cd_txempty_event;
+ /**
+ * @brief A CAN bus error happened.
+ */
+ EventSource cd_error_event;
/**
- * @brief One or more transmission slots become available. + * @brief Error flags set when an error event is broadcasted. */
- EventSource can_txempty_event;
+ canstatus_t cd_status;
#if CAN_USE_SLEEP_MODE || defined (__DOXYGEN__)
/**
* @brief Entering sleep state event. */
- EventSource can_sleep_event;
+ EventSource cd_sleep_event;
/**
* @brief Exiting sleep state event. */
- EventSource can_wakeup_event;
+ EventSource cd_wakeup_event;
#endif /* CAN_USE_SLEEP_MODE */
/* End of the mandatory fields.*/
+ /**
+ * @brief Pointer to the CAN registers. + */
+ CAN_TypeDef *cd_canp;
} CANDriver;
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
+/** @cond never*/
+#if USE_STM32_CAN1
+extern CANDriver CAND1;
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -146,6 +188,7 @@ extern "C" { #ifdef __cplusplus
}
#endif
+/** @endcond*/
#endif /* CH_HAL_USE_CAN */
diff --git a/os/hal/src/can.c b/os/hal/src/can.c index 387581d8c..698bcfbc4 100644 --- a/os/hal/src/can.c +++ b/os/hal/src/can.c @@ -44,15 +44,15 @@ void canInit(void) { */
void canObjectInit(CANDriver *canp) {
- canp->can_state = CAN_STOP;
- canp->can_config = NULL;
- chSemInit(&canp->can_txsem, 0);
- chSemInit(&canp->can_rxsem, 0);
- chEvtInit(&canp->can_rxfull_event);
- chEvtInit(&canp->can_txempty_event);
+ canp->cd_state = CAN_STOP;
+ canp->cd_config = NULL;
+ chSemInit(&canp->cd_txsem, 0);
+ chSemInit(&canp->cd_rxsem, 0);
+ chEvtInit(&canp->cd_rxfull_event);
+ chEvtInit(&canp->cd_txempty_event);
#if CAN_USE_SLEEP_MODE
- chEvtInit(&canp->can_sleep_event);
- chEvtInit(&canp->can_wakeup_event);
+ chEvtInit(&canp->cd_sleep_event);
+ chEvtInit(&canp->cd_wakeup_event);
#endif /* CAN_USE_SLEEP_MODE */
}
@@ -67,12 +67,12 @@ void canStart(CANDriver *canp, const CANConfig *config) { chDbgCheck((canp != NULL) && (config != NULL), "canStart");
chSysLock();
- chDbgAssert((canp->can_state == CAN_STOP) || (canp->can_state == CAN_READY),
+ chDbgAssert((canp->cd_state == CAN_STOP) || (canp->cd_state == CAN_READY),
"canStart(), #1",
"invalid state");
- canp->can_config = config;
+ canp->cd_config = config;
can_lld_start(canp);
- canp->can_state = CAN_READY;
+ canp->cd_state = CAN_READY;
chSysUnlock();
}
@@ -86,11 +86,11 @@ void canStop(CANDriver *canp) { chDbgCheck(canp != NULL, "canStop");
chSysLock();
- chDbgAssert((canp->can_state == CAN_STOP) || (canp->can_state == CAN_READY),
+ chDbgAssert((canp->cd_state == CAN_STOP) || (canp->cd_state == CAN_READY),
"canStop(), #1",
"invalid state");
can_lld_stop(canp);
- canp->can_state = CAN_STOP;
+ canp->cd_state = CAN_STOP;
chSysUnlock();
}
@@ -118,11 +118,11 @@ msg_t canTransmit(CANDriver *canp, const CANFrame *cfp, systime_t timeout) { chDbgCheck((canp != NULL) && (cfp != NULL), "canTransmit");
chSysLock();
- chDbgAssert((canp->can_state == CAN_READY) || (canp->can_state == CAN_SLEEP),
+ chDbgAssert((canp->cd_state == CAN_READY) || (canp->cd_state == CAN_SLEEP),
"canTransmit(), #1",
"invalid state");
- if ((canp->can_state == CAN_SLEEP) || !can_lld_can_transmit(canp)) {
- msg = chSemWaitTimeoutS(&canp->can_txsem, timeout);
+ if ((canp->cd_state == CAN_SLEEP) || !can_lld_can_transmit(canp)) {
+ msg = chSemWaitTimeoutS(&canp->cd_txsem, timeout);
if (msg != RDY_OK) {
chSysUnlock();
return msg;
@@ -156,11 +156,11 @@ msg_t canReceive(CANDriver *canp, CANFrame *cfp, systime_t timeout) { chDbgCheck((canp != NULL) && (cfp != NULL), "canReceive");
chSysLock();
- chDbgAssert((canp->can_state == CAN_READY) || (canp->can_state == CAN_SLEEP),
+ chDbgAssert((canp->cd_state == CAN_READY) || (canp->cd_state == CAN_SLEEP),
"canReceive(), #1",
"invalid state");
- if ((canp->can_state == CAN_SLEEP) || !can_lld_can_receive(canp)) {
- msg = chSemWaitTimeoutS(&canp->can_rxsem, timeout);
+ if ((canp->cd_state == CAN_SLEEP) || !can_lld_can_receive(canp)) {
+ msg = chSemWaitTimeoutS(&canp->cd_rxsem, timeout);
if (msg != RDY_OK) {
chSysUnlock();
return msg;
@@ -171,6 +171,23 @@ msg_t canReceive(CANDriver *canp, CANFrame *cfp, systime_t timeout) { return msg;
}
+/**
+ * @brief Returns the current status mask and clears it. + *
+ * @param[in] canp pointer to the @p CANDriver object
+ *
+ * @return The status flags mask.
+ */
+canstatus_t canGetAndClearFlags(CANDriver *canp) {
+ canstatus_t status;
+
+ chSysLock();
+ status = canp->cd_status;
+ canp->cd_status = 0;
+ chSysUnlock();
+ return status;
+}
+
#if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__)
/**
* @brief Enters the sleep mode. @@ -182,13 +199,13 @@ void canSleep(CANDriver *canp) { chDbgCheck(canp != NULL, "canSleep");
chSysLock();
- chDbgAssert((canp->can_state == CAN_READY) || (canp->can_state == CAN_SLEEP),
+ chDbgAssert((canp->cd_state == CAN_READY) || (canp->cd_state == CAN_SLEEP),
"canSleep(), #1",
"invalid state");
- if (canp->can_state == CAN_READY) {
+ if (canp->cd_state == CAN_READY) {
can_lld_sleep(canp);
- canp->can_state = CAN_SLEEP;
- chEvtBroadcastI(&canp->can_sleep_event);
+ canp->cd_state = CAN_SLEEP;
+ chEvtBroadcastI(&canp->cd_sleep_event);
chSchRescheduleS();
}
chSysUnlock();
@@ -206,13 +223,13 @@ void canWakeup(CANDriver *canp) { chDbgCheck(canp != NULL, "canWakeup");
chSysLock();
- chDbgAssert((canp->can_state == CAN_READY) || (canp->can_state == CAN_SLEEP),
+ chDbgAssert((canp->cd_state == CAN_READY) || (canp->cd_state == CAN_SLEEP),
"canWakeup(), #1",
"invalid state");
- if (canp->can_state == CAN_SLEEP) {
+ if (canp->cd_state == CAN_SLEEP) {
can_lld_wakeup(canp);
- canp->can_state = CAN_READY;
- chEvtBroadcastI(&canp->can_wakeup_event);
+ canp->cd_state = CAN_READY;
+ chEvtBroadcastI(&canp->cd_wakeup_event);
chSchRescheduleS();
}
chSysUnlock();
diff --git a/os/hal/templates/can_lld.h b/os/hal/templates/can_lld.h index 202f7e044..14588c0d5 100644 --- a/os/hal/templates/can_lld.h +++ b/os/hal/templates/can_lld.h @@ -61,6 +61,11 @@ /*===========================================================================*/
/**
+ * @brief CAN status flags.
+ */
+typedef uint32_t canstatus_t;
+
+/**
* @brief CAN 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. @@ -91,36 +96,44 @@ typedef struct { /**
* @brief Driver state.
*/
- canstate_t can_state;
+ canstate_t cd_state;
/**
* @brief Current configuration data.
*/
- const CANConfig *can_config;
+ const CANConfig *cd_config;
/**
- * @brief Transmission queue semaphore. + * @brief Transmission queue semaphore.
*/
- Semaphore can_txsem;
+ Semaphore cd_txsem;
/**
* @brief Receive queue semaphore.
*/
- Semaphore can_rxsem;
+ Semaphore cd_rxsem;
+ /**
+ * @brief One or more frames become available.
+ */
+ EventSource cd_rxfull_event;
+ /**
+ * @brief One or more transmission slots become available.
+ */
+ EventSource cd_txempty_event;
/**
- * @brief One or more frames become available. + * @brief A CAN bus error happened.
*/
- EventSource can_rxfull_event;
+ EventSource cd_error_event;
/**
- * @brief One or more transmission slots become available. + * @brief Error flags set when an error event is broadcasted.
*/
- EventSource can_txempty_event;
+ canstatus_t cd_status;
#if CAN_USE_SLEEP_MODE || defined (__DOXYGEN__)
/**
- * @brief Entering sleep state event. + * @brief Entering sleep state event.
*/
- EventSource can_sleep_event;
+ EventSource cd_sleep_event;
/**
- * @brief Exiting sleep state event. + * @brief Exiting sleep state event.
*/
- EventSource can_wakeup_event;
+ EventSource cd_wakeup_event;
#endif /* CAN_USE_SLEEP_MODE */
/* End of the mandatory fields.*/
} CANDriver;
|