diff --git a/os/hal/include/icu.h b/os/hal/include/icu.h index 99cfc4e3c..15a9b2380 100644 --- a/os/hal/include/icu.h +++ b/os/hal/include/icu.h @@ -157,6 +157,17 @@ typedef void (*icucallback_t)(ICUDriver *icup); if (previous_state != ICU_WAITING) \ (icup)->config->period_cb(icup); \ } + +/** + * @brief Common ISR code, ICU timer overflow event. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @notapi + */ +#define _icu_isr_invoke_overflow_cb(icup) { \ + (icup)->config->overflow_cb(icup); \ +} /** @} */ /*===========================================================================*/ diff --git a/os/hal/platforms/STM32/icu_lld.c b/os/hal/platforms/STM32/icu_lld.c index 2bfffd3bd..849241c2b 100644 --- a/os/hal/platforms/STM32/icu_lld.c +++ b/os/hal/platforms/STM32/icu_lld.c @@ -17,6 +17,10 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +/* + Concepts and parts of this file have been contributed by Fabio Utzig and + Xo Wang. + */ /** * @file STM32/icu_lld.c @@ -112,6 +116,8 @@ static void icu_lld_serve_interrupt(ICUDriver *icup) { if ((sr & TIM_SR_CC2IF) != 0) _icu_isr_invoke_period_cb(icup); } + if ((sr & TIM_SR_UIF) != 0) + _icu_isr_invoke_overflow_cb(icup); } /*===========================================================================*/ @@ -482,7 +488,7 @@ void icu_lld_stop(ICUDriver *icup) { */ void icu_lld_enable(ICUDriver *icup) { - icup->tim->SR = 0; /* Clear pending IRQs (if any). */ + icup->tim->SR = 0; /* Clear pending IRQs (if any). */ if (icup->config->channel == ICU_CHANNEL_1) { if (icup->config->period_cb != NULL) icup->tim->DIER |= TIM_DIER_CC1IE; @@ -494,6 +500,8 @@ void icu_lld_enable(ICUDriver *icup) { if (icup->config->period_cb != NULL) icup->tim->DIER |= TIM_DIER_CC2IE; } + if (icup->config->overflow_cb != NULL) + icup->tim->DIER |= TIM_DIER_UIE; icup->tim->CR1 = TIM_CR1_URS | TIM_CR1_CEN; } diff --git a/os/hal/platforms/STM32/icu_lld.h b/os/hal/platforms/STM32/icu_lld.h index 642de2a64..691b06a71 100644 --- a/os/hal/platforms/STM32/icu_lld.h +++ b/os/hal/platforms/STM32/icu_lld.h @@ -227,6 +227,10 @@ typedef struct { * @brief Callback for cycle period measurement. */ icucallback_t period_cb; + /** + * @brief Callback for timer overflow. + */ + icucallback_t overflow_cb; /* End of the mandatory fields.*/ /** * @brief Timer input channel to be used. diff --git a/os/hal/templates/icu_lld.h b/os/hal/templates/icu_lld.h index 4b0568102..56ce3af98 100644 --- a/os/hal/templates/icu_lld.h +++ b/os/hal/templates/icu_lld.h @@ -17,6 +17,10 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +/* + Concepts and parts of this file have been contributed by Fabio Utzig and + Xo Wang. + */ /** * @file templates/icu_lld.h @@ -88,6 +92,10 @@ typedef struct { * @brief Callback for cycle period measurement. */ icucallback_t period_cb; + /** + * @brief Callback for timer overflow. + */ + icucallback_t overflow_cb; /* End of the mandatory fields.*/ } ICUConfig; diff --git a/readme.txt b/readme.txt index 5521d3349..639793ae3 100644 --- a/readme.txt +++ b/readme.txt @@ -97,6 +97,7 @@ 3484947)(backported to 2.4.1). - FIX: Fixed various minor documentation errors (bug 3484942)(backported to 2.4.1). +- NEW: Added overflow handling in the ICU driver (contributed by Xo). - NEW: Updated debug plugin 1.0.8 (backported to 2.4.0). - NEW: Added more accurate UBRR calculation in AVR serial driver (backported to 2.4.0). diff --git a/testhal/STM32F1xx/PWM-ICU/main.c b/testhal/STM32F1xx/PWM-ICU/main.c index ab9cd8be2..78bcbf063 100644 --- a/testhal/STM32F1xx/PWM-ICU/main.c +++ b/testhal/STM32F1xx/PWM-ICU/main.c @@ -66,6 +66,7 @@ static ICUConfig icucfg = { 10000, /* 10KHz ICU clock frequency. */ icuwidthcb, icuperiodcb, + NULL, ICU_CHANNEL_1 }; diff --git a/testhal/STM32F4xx/PWM-ICU/main.c b/testhal/STM32F4xx/PWM-ICU/main.c index af3caa109..5221123e2 100644 --- a/testhal/STM32F4xx/PWM-ICU/main.c +++ b/testhal/STM32F4xx/PWM-ICU/main.c @@ -51,20 +51,22 @@ icucnt_t last_width, last_period; static void icuwidthcb(ICUDriver *icup) { palSetPad(GPIOD, GPIOD_LED4); - last_width = icuGetWidthI(icup); + last_width = icuGetWidth(icup); } static void icuperiodcb(ICUDriver *icup) { palClearPad(GPIOD, GPIOD_LED4); - last_period = icuGetPeriodI(icup); + last_period = icuGetPeriod(icup); } static ICUConfig icucfg = { ICU_INPUT_ACTIVE_HIGH, 10000, /* 10KHz ICU clock frequency. */ icuwidthcb, - icuperiodcb + icuperiodcb, + NULL, + ICU_CHANNEL_1 }; /* diff --git a/testhal/STM32L1xx/PWM-ICU/main.c b/testhal/STM32L1xx/PWM-ICU/main.c index 22d31a379..35044663c 100644 --- a/testhal/STM32L1xx/PWM-ICU/main.c +++ b/testhal/STM32L1xx/PWM-ICU/main.c @@ -51,20 +51,22 @@ icucnt_t last_width, last_period; static void icuwidthcb(ICUDriver *icup) { palSetPad(GPIOB, GPIOB_LED3); - last_width = icuGetWidthI(icup); + last_width = icuGetWidth(icup); } static void icuperiodcb(ICUDriver *icup) { palClearPad(GPIOB, GPIOB_LED3); - last_period = icuGetPeriodI(icup); + last_period = icuGetPeriod(icup); } static ICUConfig icucfg = { ICU_INPUT_ACTIVE_HIGH, 10000, /* 10KHz ICU clock frequency. */ icuwidthcb, - icuperiodcb + icuperiodcb, + NULL, + ICU_CHANNEL_1 }; /*