diff options
author | gdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2014-10-17 12:28:10 +0000 |
---|---|---|
committer | gdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2014-10-17 12:28:10 +0000 |
commit | b2c261eeeefcd94c9c164fa1e8671b7b42997e4d (patch) | |
tree | cc5413af9fef7661c7e8d55db1d14a88d67e729a /os | |
parent | a708e083e1cf6f6181bcd02baf9cc580f38b5397 (diff) | |
download | ChibiOS-b2c261eeeefcd94c9c164fa1e8671b7b42997e4d.tar.gz ChibiOS-b2c261eeeefcd94c9c164fa1e8671b7b42997e4d.tar.bz2 ChibiOS-b2c261eeeefcd94c9c164fa1e8671b7b42997e4d.zip |
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@7411 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os')
-rw-r--r-- | os/hal/include/icu.h | 6 | ||||
-rw-r--r-- | os/hal/ports/STM32/LLD/TIMv1/icu_lld.c | 36 | ||||
-rw-r--r-- | os/hal/ports/STM32/LLD/TIMv1/icu_lld.h | 2 | ||||
-rw-r--r-- | os/hal/src/icu.c | 17 |
4 files changed, 42 insertions, 19 deletions
diff --git a/os/hal/include/icu.h b/os/hal/include/icu.h index 9d7a06220..f9df3cd6a 100644 --- a/os/hal/include/icu.h +++ b/os/hal/include/icu.h @@ -187,6 +187,7 @@ typedef void (*icucallback_t)(ICUDriver *icup); /**
* @brief Common ISR code, ICU period event.
+ * @note A period event brings the driver into the @p ICU_ACTIVE state.
*
* @param[in] icup pointer to the @p ICUDriver object
*
@@ -201,6 +202,8 @@ typedef void (*icucallback_t)(ICUDriver *icup); /**
* @brief Common ISR code, ICU timer overflow event.
+ * @note An overflow always brings the driver back to the @p ICU_WAITING
+ * state.
*
* @param[in] icup pointer to the @p ICUDriver object
*
@@ -208,6 +211,7 @@ typedef void (*icucallback_t)(ICUDriver *icup); */
#define _icu_isr_invoke_overflow_cb(icup) do { \
(icup)->config->overflow_cb(icup); \
+ (icup)->state = ICU_WAITING; \
} while (0)
/** @} */
@@ -223,7 +227,7 @@ extern "C" { void icuStart(ICUDriver *icup, const ICUConfig *config);
void icuStop(ICUDriver *icup);
void icuStartCapture(ICUDriver *icup);
- void icuWaitCapture(ICUDriver *icup);
+ bool icuWaitCapture(ICUDriver *icup);
void icuStopCapture(ICUDriver *icup);
void icuEnableNotifications(ICUDriver *icup);
void icuDisableNotifications(ICUDriver *icup);
diff --git a/os/hal/ports/STM32/LLD/TIMv1/icu_lld.c b/os/hal/ports/STM32/LLD/TIMv1/icu_lld.c index d5604515e..04fec43cd 100644 --- a/os/hal/ports/STM32/LLD/TIMv1/icu_lld.c +++ b/os/hal/ports/STM32/LLD/TIMv1/icu_lld.c @@ -102,7 +102,9 @@ ICUDriver ICUD9; /* Driver local functions. */
/*===========================================================================*/
-static void icu_lld_wait_edge(ICUDriver *icup) {
+static bool icu_lld_wait_edge(ICUDriver *icup) {
+ uint32_t sr;
+ bool result;
/* Polled mode so re-enabling the interrupts while the operation is
performed.*/
@@ -111,23 +113,29 @@ static void icu_lld_wait_edge(ICUDriver *icup) { /* Polling the right bit depending on the input channel.*/
if (icup->config->channel == ICU_CHANNEL_1) {
/* Waiting for an edge.*/
- while ((icup->tim->SR & STM32_TIM_SR_CC1IF) == 0)
+ while (((sr = icup->tim->SR) &
+ (STM32_TIM_SR_CC1IF | STM32_TIM_SR_UIF)) == 0)
;
-
- /* Resetting capture flag.*/
- icup->tim->SR &= ~STM32_TIM_SR_CC1IF;
}
else {
/* Waiting for an edge.*/
- while ((icup->tim->SR & STM32_TIM_SR_CC2IF) == 0)
+ while (((sr = icup->tim->SR) &
+ (STM32_TIM_SR_CC2IF | STM32_TIM_SR_UIF)) == 0)
;
-
- /* Resetting capture flag.*/
- icup->tim->SR &= ~STM32_TIM_SR_CC2IF;
}
+ /* Edge or overflow?*/
+ result = (sr & STM32_TIM_SR_UIF) != 0 ? true : false;
+
/* Done, disabling interrupts again.*/
chSysLock();
+
+ /* Resetting all flags.*/
+ icup->tim->SR &= ~(STM32_TIM_SR_CC1IF |
+ STM32_TIM_SR_CC2IF |
+ STM32_TIM_SR_UIF);
+
+ return result;
}
/**
@@ -648,18 +656,22 @@ void icu_lld_start_capture(ICUDriver *icup) { * @note In order to use this function notifications must be disabled.
*
* @param[in] icup pointer to the @p ICUDriver object
+ * @return The capture status.
+ * @retval false if the capture is successful.
+ * @retval true if a timer overflow occurred.
*
* @notapi
*/
-void icu_lld_wait_capture(ICUDriver *icup) {
+bool icu_lld_wait_capture(ICUDriver *icup) {
/* If the driver is still in the ICU_WAITING state then we need to wait
for the first activation edge.*/
if (icup->state == ICU_WAITING)
- icu_lld_wait_edge(icup);
+ if (icu_lld_wait_edge(icup))
+ return true;
/* This edge marks the availability of a capture result.*/
- icu_lld_wait_edge(icup);
+ return icu_lld_wait_edge(icup);
}
/**
diff --git a/os/hal/ports/STM32/LLD/TIMv1/icu_lld.h b/os/hal/ports/STM32/LLD/TIMv1/icu_lld.h index 5b8b71d9f..c20d1bc7c 100644 --- a/os/hal/ports/STM32/LLD/TIMv1/icu_lld.h +++ b/os/hal/ports/STM32/LLD/TIMv1/icu_lld.h @@ -413,7 +413,7 @@ extern "C" { void icu_lld_start(ICUDriver *icup);
void icu_lld_stop(ICUDriver *icup);
void icu_lld_start_capture(ICUDriver *icup);
- void icu_lld_wait_capture(ICUDriver *icup);
+ bool icu_lld_wait_capture(ICUDriver *icup);
void icu_lld_stop_capture(ICUDriver *icup);
void icu_lld_enable_notifications(ICUDriver *icup);
void icu_lld_disable_notifications(ICUDriver *icup);
diff --git a/os/hal/src/icu.c b/os/hal/src/icu.c index 9f7a6b6c6..481b8a6c6 100644 --- a/os/hal/src/icu.c +++ b/os/hal/src/icu.c @@ -136,15 +136,20 @@ void icuStartCapture(ICUDriver *icup) { * @brief Waits for a completed capture.
* @note The operation could be performed in polled mode depending on.
* @note In order to use this function notifications must be disabled.
- * @pre The driver must be in @p ICU_WAITING or @p ICU_ACTIVE modes.
+ * @pre The driver must be in @p ICU_WAITING or @p ICU_ACTIVE states.
* @post After the capture is available the driver is in @p ICU_ACTIVE
- * mode.
+ * state. If a capture fails then the driver is in @p ICU_WAITING
+ * state.
*
* @param[in] icup pointer to the @p ICUDriver object
+ * @return The capture status.
+ * @retval false if the capture is successful.
+ * @retval true if a timer overflow occurred.
*
* @api
*/
-void icuWaitCapture(ICUDriver *icup) {
+bool icuWaitCapture(ICUDriver *icup) {
+ bool result;
osalDbgCheck(icup != NULL);
@@ -153,9 +158,11 @@ void icuWaitCapture(ICUDriver *icup) { "invalid state");
osalDbgAssert(icuAreNotificationsEnabledX(icup) == false,
"notifications enabled");
- icu_lld_wait_capture(icup);
- icup->state = ICU_ACTIVE;
+ result = icu_lld_wait_capture(icup);
+ icup->state = result ? ICU_WAITING : ICU_ACTIVE;
osalSysUnlock();
+
+ return result;
}
/**
|