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

master
gdisirio 2014-10-17 12:28:10 +00:00
parent a708e083e1
commit b2c261eeee
4 changed files with 42 additions and 19 deletions

View File

@ -187,6 +187,7 @@ typedef void (*icucallback_t)(ICUDriver *icup);
/** /**
* @brief Common ISR code, ICU period event. * @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 * @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. * @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 * @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 { \ #define _icu_isr_invoke_overflow_cb(icup) do { \
(icup)->config->overflow_cb(icup); \ (icup)->config->overflow_cb(icup); \
(icup)->state = ICU_WAITING; \
} while (0) } while (0)
/** @} */ /** @} */
@ -223,7 +227,7 @@ extern "C" {
void icuStart(ICUDriver *icup, const ICUConfig *config); void icuStart(ICUDriver *icup, const ICUConfig *config);
void icuStop(ICUDriver *icup); void icuStop(ICUDriver *icup);
void icuStartCapture(ICUDriver *icup); void icuStartCapture(ICUDriver *icup);
void icuWaitCapture(ICUDriver *icup); bool icuWaitCapture(ICUDriver *icup);
void icuStopCapture(ICUDriver *icup); void icuStopCapture(ICUDriver *icup);
void icuEnableNotifications(ICUDriver *icup); void icuEnableNotifications(ICUDriver *icup);
void icuDisableNotifications(ICUDriver *icup); void icuDisableNotifications(ICUDriver *icup);

View File

@ -102,7 +102,9 @@ ICUDriver ICUD9;
/* Driver local functions. */ /* 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 /* Polled mode so re-enabling the interrupts while the operation is
performed.*/ performed.*/
@ -111,23 +113,29 @@ static void icu_lld_wait_edge(ICUDriver *icup) {
/* Polling the right bit depending on the input channel.*/ /* Polling the right bit depending on the input channel.*/
if (icup->config->channel == ICU_CHANNEL_1) { if (icup->config->channel == ICU_CHANNEL_1) {
/* Waiting for an edge.*/ /* 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 { else {
/* Waiting for an edge.*/ /* 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.*/ /* Done, disabling interrupts again.*/
chSysLock(); 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. * @note In order to use this function notifications must be disabled.
* *
* @param[in] icup pointer to the @p ICUDriver object * @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 * @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 /* If the driver is still in the ICU_WAITING state then we need to wait
for the first activation edge.*/ for the first activation edge.*/
if (icup->state == ICU_WAITING) 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.*/ /* This edge marks the availability of a capture result.*/
icu_lld_wait_edge(icup); return icu_lld_wait_edge(icup);
} }
/** /**

View File

@ -413,7 +413,7 @@ extern "C" {
void icu_lld_start(ICUDriver *icup); void icu_lld_start(ICUDriver *icup);
void icu_lld_stop(ICUDriver *icup); void icu_lld_stop(ICUDriver *icup);
void icu_lld_start_capture(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_stop_capture(ICUDriver *icup);
void icu_lld_enable_notifications(ICUDriver *icup); void icu_lld_enable_notifications(ICUDriver *icup);
void icu_lld_disable_notifications(ICUDriver *icup); void icu_lld_disable_notifications(ICUDriver *icup);

View File

@ -136,15 +136,20 @@ void icuStartCapture(ICUDriver *icup) {
* @brief Waits for a completed capture. * @brief Waits for a completed capture.
* @note The operation could be performed in polled mode depending on. * @note The operation could be performed in polled mode depending on.
* @note In order to use this function notifications must be disabled. * @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 * @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 * @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 * @api
*/ */
void icuWaitCapture(ICUDriver *icup) { bool icuWaitCapture(ICUDriver *icup) {
bool result;
osalDbgCheck(icup != NULL); osalDbgCheck(icup != NULL);
@ -153,9 +158,11 @@ void icuWaitCapture(ICUDriver *icup) {
"invalid state"); "invalid state");
osalDbgAssert(icuAreNotificationsEnabledX(icup) == false, osalDbgAssert(icuAreNotificationsEnabledX(icup) == false,
"notifications enabled"); "notifications enabled");
icu_lld_wait_capture(icup); result = icu_lld_wait_capture(icup);
icup->state = ICU_ACTIVE; icup->state = result ? ICU_WAITING : ICU_ACTIVE;
osalSysUnlock(); osalSysUnlock();
return result;
} }
/** /**