From b587681a145382f21e827c3a33740ddf313a9e4a Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 11 Aug 2013 09:26:01 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@6130 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/TIMv1/gpt_lld.c | 762 +++++++++++++++++++++++++++++++++ os/hal/platforms/STM32/TIMv1/gpt_lld.h | 504 ++++++++++++++++++++++ os/hal/platforms/STM32/TIMv1/icu_lld.c | 641 +++++++++++++++++++++++++++ os/hal/platforms/STM32/TIMv1/icu_lld.h | 406 ++++++++++++++++++ os/hal/platforms/STM32/TIMv1/pwm_lld.c | 705 ++++++++++++++++++++++++++++++ os/hal/platforms/STM32/TIMv1/pwm_lld.h | 474 ++++++++++++++++++++ os/hal/platforms/STM32/gpt_lld.c | 762 --------------------------------- os/hal/platforms/STM32/gpt_lld.h | 504 ---------------------- os/hal/platforms/STM32/icu_lld.c | 641 --------------------------- os/hal/platforms/STM32/icu_lld.h | 406 ------------------ os/hal/platforms/STM32/pwm_lld.c | 705 ------------------------------ os/hal/platforms/STM32/pwm_lld.h | 474 -------------------- 12 files changed, 3492 insertions(+), 3492 deletions(-) create mode 100644 os/hal/platforms/STM32/TIMv1/gpt_lld.c create mode 100644 os/hal/platforms/STM32/TIMv1/gpt_lld.h create mode 100644 os/hal/platforms/STM32/TIMv1/icu_lld.c create mode 100644 os/hal/platforms/STM32/TIMv1/icu_lld.h create mode 100644 os/hal/platforms/STM32/TIMv1/pwm_lld.c create mode 100644 os/hal/platforms/STM32/TIMv1/pwm_lld.h delete mode 100644 os/hal/platforms/STM32/gpt_lld.c delete mode 100644 os/hal/platforms/STM32/gpt_lld.h delete mode 100644 os/hal/platforms/STM32/icu_lld.c delete mode 100644 os/hal/platforms/STM32/icu_lld.h delete mode 100644 os/hal/platforms/STM32/pwm_lld.c delete mode 100644 os/hal/platforms/STM32/pwm_lld.h (limited to 'os') diff --git a/os/hal/platforms/STM32/TIMv1/gpt_lld.c b/os/hal/platforms/STM32/TIMv1/gpt_lld.c new file mode 100644 index 000000000..35268fbe5 --- /dev/null +++ b/os/hal/platforms/STM32/TIMv1/gpt_lld.c @@ -0,0 +1,762 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/gpt_lld.c + * @brief STM32 GPT subsystem low level driver source. + * + * @addtogroup GPT + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#if HAL_USE_GPT || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief GPTD1 driver identifier. + * @note The driver GPTD1 allocates the complex timer TIM1 when enabled. + */ +#if STM32_GPT_USE_TIM1 || defined(__DOXYGEN__) +GPTDriver GPTD1; +#endif + +/** + * @brief GPTD2 driver identifier. + * @note The driver GPTD2 allocates the timer TIM2 when enabled. + */ +#if STM32_GPT_USE_TIM2 || defined(__DOXYGEN__) +GPTDriver GPTD2; +#endif + +/** + * @brief GPTD3 driver identifier. + * @note The driver GPTD3 allocates the timer TIM3 when enabled. + */ +#if STM32_GPT_USE_TIM3 || defined(__DOXYGEN__) +GPTDriver GPTD3; +#endif + +/** + * @brief GPTD4 driver identifier. + * @note The driver GPTD4 allocates the timer TIM4 when enabled. + */ +#if STM32_GPT_USE_TIM4 || defined(__DOXYGEN__) +GPTDriver GPTD4; +#endif + +/** + * @brief GPTD5 driver identifier. + * @note The driver GPTD5 allocates the timer TIM5 when enabled. + */ +#if STM32_GPT_USE_TIM5 || defined(__DOXYGEN__) +GPTDriver GPTD5; +#endif + +/** + * @brief GPTD6 driver identifier. + * @note The driver GPTD6 allocates the timer TIM6 when enabled. + */ +#if STM32_GPT_USE_TIM6 || defined(__DOXYGEN__) +GPTDriver GPTD6; +#endif + +/** + * @brief GPTD7 driver identifier. + * @note The driver GPTD7 allocates the timer TIM7 when enabled. + */ +#if STM32_GPT_USE_TIM7 || defined(__DOXYGEN__) +GPTDriver GPTD7; +#endif + +/** + * @brief GPTD8 driver identifier. + * @note The driver GPTD8 allocates the timer TIM8 when enabled. + */ +#if STM32_GPT_USE_TIM8 || defined(__DOXYGEN__) +GPTDriver GPTD8; +#endif + +/** + * @brief GPTD9 driver identifier. + * @note The driver GPTD9 allocates the timer TIM9 when enabled. + */ +#if STM32_GPT_USE_TIM9 || defined(__DOXYGEN__) +GPTDriver GPTD9; +#endif + +/** + * @brief GPTD11 driver identifier. + * @note The driver GPTD11 allocates the timer TIM11 when enabled. + */ +#if STM32_GPT_USE_TIM11 || defined(__DOXYGEN__) +GPTDriver GPTD11; +#endif + +/** + * @brief GPTD12 driver identifier. + * @note The driver GPTD12 allocates the timer TIM12 when enabled. + */ +#if STM32_GPT_USE_TIM12 || defined(__DOXYGEN__) +GPTDriver GPTD12; +#endif + +/** + * @brief GPTD14 driver identifier. + * @note The driver GPTD14 allocates the timer TIM14 when enabled. + */ +#if STM32_GPT_USE_TIM14 || defined(__DOXYGEN__) +GPTDriver GPTD14; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Shared IRQ handler. + * + * @param[in] gptp pointer to a @p GPTDriver object + */ +static void gpt_lld_serve_interrupt(GPTDriver *gptp) { + + gptp->tim->SR = 0; + if (gptp->state == GPT_ONESHOT) { + gptp->state = GPT_READY; /* Back in GPT_READY state. */ + gpt_lld_stop_timer(gptp); /* Timer automatically stopped. */ + } + gptp->config->callback(gptp); +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_GPT_USE_TIM1 +#if !defined(STM32_TIM1_UP_HANDLER) +#error "STM32_TIM1_UP_HANDLER not defined" +#endif +/** + * @brief TIM2 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) { + + CH_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD1); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_GPT_USE_TIM1 */ + +#if STM32_GPT_USE_TIM2 +#if !defined(STM32_TIM2_HANDLER) +#error "STM32_TIM2_HANDLER not defined" +#endif +/** + * @brief TIM2 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM2_HANDLER) { + + CH_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD2); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_GPT_USE_TIM2 */ + +#if STM32_GPT_USE_TIM3 +#if !defined(STM32_TIM3_HANDLER) +#error "STM32_TIM3_HANDLER not defined" +#endif +/** + * @brief TIM3 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM3_HANDLER) { + + CH_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD3); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_GPT_USE_TIM3 */ + +#if STM32_GPT_USE_TIM4 +#if !defined(STM32_TIM4_HANDLER) +#error "STM32_TIM4_HANDLER not defined" +#endif +/** + * @brief TIM4 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM4_HANDLER) { + + CH_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD4); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_GPT_USE_TIM4 */ + +#if STM32_GPT_USE_TIM5 +#if !defined(STM32_TIM5_HANDLER) +#error "STM32_TIM5_HANDLER not defined" +#endif +/** + * @brief TIM5 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM5_HANDLER) { + + CH_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD5); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_GPT_USE_TIM5 */ + +#if STM32_GPT_USE_TIM6 +#if !defined(STM32_TIM6_HANDLER) +#error "STM32_TIM6_HANDLER not defined" +#endif +/** + * @brief TIM6 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM6_HANDLER) { + + CH_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD6); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_GPT_USE_TIM6 */ + +#if STM32_GPT_USE_TIM7 +#if !defined(STM32_TIM7_HANDLER) +#error "STM32_TIM7_HANDLER not defined" +#endif +/** + * @brief TIM7 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM7_HANDLER) { + + CH_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD7); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_GPT_USE_TIM7 */ + +#if STM32_GPT_USE_TIM8 +#if !defined(STM32_TIM8_UP_HANDLER) +#error "STM32_TIM8_UP_HANDLER not defined" +#endif +/** + * @brief TIM8 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) { + + CH_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD8); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_GPT_USE_TIM8 */ + +#if STM32_GPT_USE_TIM9 +#if !defined(STM32_TIM9_HANDLER) +#error "STM32_TIM9_HANDLER not defined" +#endif +/** + * @brief TIM9 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM9_HANDLER) { + + CH_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD9); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_GPT_USE_TIM9 */ + +#if STM32_GPT_USE_TIM11 +#if !defined(STM32_TIM11_HANDLER) +#error "STM32_TIM11_HANDLER not defined" +#endif +/** + * @brief TIM11 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM11_HANDLER) { + + CH_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD11); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_GPT_USE_TIM11 */ + +#if STM32_GPT_USE_TIM12 +#if !defined(STM32_TIM12_HANDLER) +#error "STM32_TIM12_HANDLER not defined" +#endif +/** + * @brief TIM12 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM12_HANDLER) { + + CH_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD12); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_GPT_USE_TIM12 */ + +#if STM32_GPT_USE_TIM14 +#if !defined(STM32_TIM14_HANDLER) +#error "STM32_TIM14_HANDLER not defined" +#endif +/** + * @brief TIM14 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM14_HANDLER) { + + CH_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD14); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_GPT_USE_TIM14 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level GPT driver initialization. + * + * @notapi + */ +void gpt_lld_init(void) { + +#if STM32_GPT_USE_TIM1 + /* Driver initialization.*/ + GPTD1.tim = STM32_TIM1; + gptObjectInit(&GPTD1); +#endif + +#if STM32_GPT_USE_TIM2 + /* Driver initialization.*/ + GPTD2.tim = STM32_TIM2; + gptObjectInit(&GPTD2); +#endif + +#if STM32_GPT_USE_TIM3 + /* Driver initialization.*/ + GPTD3.tim = STM32_TIM3; + gptObjectInit(&GPTD3); +#endif + +#if STM32_GPT_USE_TIM4 + /* Driver initialization.*/ + GPTD4.tim = STM32_TIM4; + gptObjectInit(&GPTD4); +#endif + +#if STM32_GPT_USE_TIM5 + /* Driver initialization.*/ + GPTD5.tim = STM32_TIM5; + gptObjectInit(&GPTD5); +#endif + +#if STM32_GPT_USE_TIM6 + /* Driver initialization.*/ + GPTD6.tim = STM32_TIM6; + gptObjectInit(&GPTD6); +#endif + +#if STM32_GPT_USE_TIM7 + /* Driver initialization.*/ + GPTD7.tim = STM32_TIM7; + gptObjectInit(&GPTD7); +#endif + +#if STM32_GPT_USE_TIM8 + /* Driver initialization.*/ + GPTD8.tim = STM32_TIM8; + gptObjectInit(&GPTD8); +#endif + +#if STM32_GPT_USE_TIM9 + /* Driver initialization.*/ + GPTD9.tim = STM32_TIM9; + gptObjectInit(&GPTD9); +#endif + +#if STM32_GPT_USE_TIM11 + /* Driver initialization.*/ + GPTD11.tim = STM32_TIM11; + gptObjectInit(&GPTD11); +#endif + +#if STM32_GPT_USE_TIM12 + /* Driver initialization.*/ + GPTD12.tim = STM32_TIM12; + gptObjectInit(&GPTD12); +#endif + +#if STM32_GPT_USE_TIM14 + /* Driver initialization.*/ + GPTD14.tim = STM32_TIM14; + gptObjectInit(&GPTD14); +#endif +} + +/** + * @brief Configures and activates the GPT peripheral. + * + * @param[in] gptp pointer to the @p GPTDriver object + * + * @notapi + */ +void gpt_lld_start(GPTDriver *gptp) { + uint16_t psc; + + if (gptp->state == GPT_STOP) { + /* Clock activation.*/ +#if STM32_GPT_USE_TIM1 + if (&GPTD1 == gptp) { + rccEnableTIM1(FALSE); + rccResetTIM1(); + nvicEnableVector(STM32_TIM1_UP_NUMBER, + CORTEX_PRIORITY_MASK(STM32_GPT_TIM1_IRQ_PRIORITY)); + gptp->clock = STM32_TIMCLK2; + } +#endif +#if STM32_GPT_USE_TIM2 + if (&GPTD2 == gptp) { + rccEnableTIM2(FALSE); + rccResetTIM2(); + nvicEnableVector(STM32_TIM2_NUMBER, + CORTEX_PRIORITY_MASK(STM32_GPT_TIM2_IRQ_PRIORITY)); + gptp->clock = STM32_TIMCLK1; + } +#endif +#if STM32_GPT_USE_TIM3 + if (&GPTD3 == gptp) { + rccEnableTIM3(FALSE); + rccResetTIM3(); + nvicEnableVector(STM32_TIM3_NUMBER, + CORTEX_PRIORITY_MASK(STM32_GPT_TIM3_IRQ_PRIORITY)); + gptp->clock = STM32_TIMCLK1; + } +#endif +#if STM32_GPT_USE_TIM4 + if (&GPTD4 == gptp) { + rccEnableTIM4(FALSE); + rccResetTIM4(); + nvicEnableVector(STM32_TIM4_NUMBER, + CORTEX_PRIORITY_MASK(STM32_GPT_TIM4_IRQ_PRIORITY)); + gptp->clock = STM32_TIMCLK1; + } +#endif + +#if STM32_GPT_USE_TIM5 + if (&GPTD5 == gptp) { + rccEnableTIM5(FALSE); + rccResetTIM5(); + nvicEnableVector(STM32_TIM5_NUMBER, + CORTEX_PRIORITY_MASK(STM32_GPT_TIM5_IRQ_PRIORITY)); + gptp->clock = STM32_TIMCLK1; + } +#endif + +#if STM32_GPT_USE_TIM6 + if (&GPTD6 == gptp) { + rccEnableTIM6(FALSE); + rccResetTIM6(); + nvicEnableVector(STM32_TIM6_NUMBER, + CORTEX_PRIORITY_MASK(STM32_GPT_TIM6_IRQ_PRIORITY)); + gptp->clock = STM32_TIMCLK1; + } +#endif + +#if STM32_GPT_USE_TIM7 + if (&GPTD7 == gptp) { + rccEnableTIM7(FALSE); + rccResetTIM7(); + nvicEnableVector(STM32_TIM7_NUMBER, + CORTEX_PRIORITY_MASK(STM32_GPT_TIM7_IRQ_PRIORITY)); + gptp->clock = STM32_TIMCLK1; + } +#endif + +#if STM32_GPT_USE_TIM8 + if (&GPTD8 == gptp) { + rccEnableTIM8(FALSE); + rccResetTIM8(); + nvicEnableVector(STM32_TIM8_UP_NUMBER, + CORTEX_PRIORITY_MASK(STM32_GPT_TIM8_IRQ_PRIORITY)); + gptp->clock = STM32_TIMCLK2; + } +#endif + +#if STM32_GPT_USE_TIM9 + if (&GPTD9 == gptp) { + rccEnableTIM9(FALSE); + rccResetTIM9(); + nvicEnableVector(STM32_TIM9_NUMBER, + CORTEX_PRIORITY_MASK(STM32_GPT_TIM9_IRQ_PRIORITY)); + gptp->clock = STM32_TIMCLK2; + } +#endif + +#if STM32_GPT_USE_TIM11 + if (&GPTD11 == gptp) { + rccEnableTIM11(FALSE); + rccResetTIM11(); + nvicEnableVector(STM32_TIM11_NUMBER, + CORTEX_PRIORITY_MASK(STM32_GPT_TIM11_IRQ_PRIORITY)); + gptp->clock = STM32_TIMCLK2; + } +#endif + +#if STM32_GPT_USE_TIM12 + if (&GPTD12 == gptp) { + rccEnableTIM12(FALSE); + rccResetTIM12(); + nvicEnableVector(STM32_TIM12_NUMBER, + CORTEX_PRIORITY_MASK(STM32_GPT_TIM12_IRQ_PRIORITY)); + gptp->clock = STM32_TIMCLK1; + } +#endif + +#if STM32_GPT_USE_TIM14 + if (&GPTD14 == gptp) { + rccEnableTIM14(FALSE); + rccResetTIM14(); + nvicEnableVector(STM32_TIM14_NUMBER, + CORTEX_PRIORITY_MASK(STM32_GPT_TIM14_IRQ_PRIORITY)); + gptp->clock = STM32_TIMCLK1; + } +#endif + } + + /* Prescaler value calculation.*/ + psc = (uint16_t)((gptp->clock / gptp->config->frequency) - 1); + chDbgAssert(((uint32_t)(psc + 1) * gptp->config->frequency) == gptp->clock, + "gpt_lld_start(), #1", "invalid frequency"); + + /* Timer configuration.*/ + gptp->tim->CR1 = 0; /* Initially stopped. */ + gptp->tim->CR2 = TIM_CR2_CCDS; /* DMA on UE (if any). */ + gptp->tim->PSC = psc; /* Prescaler value. */ + gptp->tim->DIER = 0; +} + +/** + * @brief Deactivates the GPT peripheral. + * + * @param[in] gptp pointer to the @p GPTDriver object + * + * @notapi + */ +void gpt_lld_stop(GPTDriver *gptp) { + + if (gptp->state == GPT_READY) { + gptp->tim->CR1 = 0; /* Timer disabled. */ + gptp->tim->DIER = 0; /* All IRQs disabled. */ + gptp->tim->SR = 0; /* Clear eventual pending IRQs. */ + +#if STM32_GPT_USE_TIM1 + if (&GPTD1 == gptp) { + nvicDisableVector(STM32_TIM1_UP_NUMBER); + rccDisableTIM1(FALSE); + } +#endif +#if STM32_GPT_USE_TIM2 + if (&GPTD2 == gptp) { + nvicDisableVector(STM32_TIM2_NUMBER); + rccDisableTIM2(FALSE); + } +#endif +#if STM32_GPT_USE_TIM3 + if (&GPTD3 == gptp) { + nvicDisableVector(STM32_TIM3_NUMBER); + rccDisableTIM3(FALSE); + } +#endif +#if STM32_GPT_USE_TIM4 + if (&GPTD4 == gptp) { + nvicDisableVector(STM32_TIM4_NUMBER); + rccDisableTIM4(FALSE); + } +#endif +#if STM32_GPT_USE_TIM5 + if (&GPTD5 == gptp) { + nvicDisableVector(STM32_TIM5_NUMBER); + rccDisableTIM5(FALSE); + } +#endif +#if STM32_GPT_USE_TIM6 + if (&GPTD6 == gptp) { + nvicDisableVector(STM32_TIM6_NUMBER); + rccDisableTIM6(FALSE); + } +#endif +#if STM32_GPT_USE_TIM7 + if (&GPTD7 == gptp) { + nvicDisableVector(STM32_TIM7_NUMBER); + rccDisableTIM7(FALSE); + } +#endif +#if STM32_GPT_USE_TIM8 + if (&GPTD8 == gptp) { + nvicDisableVector(STM32_TIM8_UP_NUMBER); + rccDisableTIM8(FALSE); + } +#endif +#if STM32_GPT_USE_TIM9 + if (&GPTD9 == gptp) { + nvicDisableVector(STM32_TIM9_NUMBER); + rccDisableTIM9(FALSE); + } +#endif +#if STM32_GPT_USE_TIM11 + if (&GPTD11 == gptp) { + nvicDisableVector(STM32_TIM11_NUMBER); + rccDisableTIM11(FALSE); + } +#endif +#if STM32_GPT_USE_TIM12 + if (&GPTD12 == gptp) { + nvicDisableVector(STM32_TIM12_NUMBER); + rccDisableTIM12(FALSE); + } +#endif +#if STM32_GPT_USE_TIM14 + if (&GPTD14 == gptp) { + nvicDisableVector(STM32_TIM14_NUMBER); + rccDisableTIM14(FALSE); + } +#endif + } +} + +/** + * @brief Starts the timer in continuous mode. + * + * @param[in] gptp pointer to the @p GPTDriver object + * @param[in] interval period in ticks + * + * @notapi + */ +void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t interval) { + + gptp->tim->ARR = interval - 1; /* Time constant. */ + gptp->tim->EGR = TIM_EGR_UG; /* Update event. */ + gptp->tim->CNT = 0; /* Reset counter. */ + /* NOTE: After generating the UG event it takes several clock cycles before + SR bit 0 goes to 1. This is because the clearing of CNT has been inserted + before the clearing of SR, to give it some time.*/ + gptp->tim->SR = 0; /* Clear pending IRQs (if any). */ + gptp->tim->DIER = TIM_DIER_UIE; /* Update Event IRQ enabled. */ + gptp->tim->CR1 = TIM_CR1_URS | TIM_CR1_CEN; +} + +/** + * @brief Stops the timer. + * + * @param[in] gptp pointer to the @p GPTDriver object + * + * @notapi + */ +void gpt_lld_stop_timer(GPTDriver *gptp) { + + gptp->tim->CR1 = 0; /* Initially stopped. */ + gptp->tim->SR = 0; /* Clear pending IRQs (if any). */ + gptp->tim->DIER = 0; /* Interrupts disabled. */ +} + +/** + * @brief Starts the timer in one shot mode and waits for completion. + * @details This function specifically polls the timer waiting for completion + * in order to not have extra delays caused by interrupt servicing, + * this function is only recommended for short delays. + * + * @param[in] gptp pointer to the @p GPTDriver object + * @param[in] interval time interval in ticks + * + * @notapi + */ +void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval) { + + gptp->tim->ARR = interval - 1; /* Time constant. */ + gptp->tim->EGR = TIM_EGR_UG; /* Update event. */ + gptp->tim->SR = 0; /* Clear pending IRQs (if any). */ + gptp->tim->CR1 = TIM_CR1_OPM | TIM_CR1_URS | TIM_CR1_CEN; + while (!(gptp->tim->SR & TIM_SR_UIF)) + ; +} + +#endif /* HAL_USE_GPT */ + +/** @} */ diff --git a/os/hal/platforms/STM32/TIMv1/gpt_lld.h b/os/hal/platforms/STM32/TIMv1/gpt_lld.h new file mode 100644 index 000000000..ecb1dcb35 --- /dev/null +++ b/os/hal/platforms/STM32/TIMv1/gpt_lld.h @@ -0,0 +1,504 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/gpt_lld.h + * @brief STM32 GPT subsystem low level driver header. + * + * @addtogroup GPT + * @{ + */ + +#ifndef _GPT_LLD_H_ +#define _GPT_LLD_H_ + +#if HAL_USE_GPT || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief GPTD1 driver enable switch. + * @details If set to @p TRUE the support for GPTD1 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_GPT_USE_TIM1) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM1 FALSE +#endif + +/** + * @brief GPTD2 driver enable switch. + * @details If set to @p TRUE the support for GPTD2 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_GPT_USE_TIM2) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM2 FALSE +#endif + +/** + * @brief GPTD3 driver enable switch. + * @details If set to @p TRUE the support for GPTD3 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_GPT_USE_TIM3) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM3 FALSE +#endif + +/** + * @brief GPTD4 driver enable switch. + * @details If set to @p TRUE the support for GPTD4 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_GPT_USE_TIM4) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM4 FALSE +#endif + +/** + * @brief GPTD5 driver enable switch. + * @details If set to @p TRUE the support for GPTD5 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_GPT_USE_TIM5) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM5 FALSE +#endif + +/** + * @brief GPTD6 driver enable switch. + * @details If set to @p TRUE the support for GPTD6 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_GPT_USE_TIM6) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM6 FALSE +#endif + +/** + * @brief GPTD7 driver enable switch. + * @details If set to @p TRUE the support for GPTD7 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_GPT_USE_TIM7) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM7 FALSE +#endif + +/** + * @brief GPTD8 driver enable switch. + * @details If set to @p TRUE the support for GPTD8 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_GPT_USE_TIM8) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM8 FALSE +#endif + +/** + * @brief GPTD9 driver enable switch. + * @details If set to @p TRUE the support for GPTD9 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_GPT_USE_TIM9) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM9 FALSE +#endif + +/** + * @brief GPTD11 driver enable switch. + * @details If set to @p TRUE the support for GPTD11 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_GPT_USE_TIM11) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM11 FALSE +#endif + +/** + * @brief GPTD12 driver enable switch. + * @details If set to @p TRUE the support for GPTD12 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_GPT_USE_TIM12) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM12 FALSE +#endif + +/** + * @brief GPTD14 driver enable switch. + * @details If set to @p TRUE the support for GPTD14 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_GPT_USE_TIM14) || defined(__DOXYGEN__) +#define STM32_GPT_USE_TIM14 FALSE +#endif + +/** + * @brief GPTD1 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD2 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD3 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD4 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD5 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM5_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD6 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM6_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD7 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM7_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD8 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM8_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD9 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM9_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD11 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM11_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD12 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM12_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD14 interrupt priority level setting. + */ +#if !defined(STM32_GPT_TIM14_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_GPT_USE_TIM1 && !STM32_HAS_TIM1 +#error "TIM1 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM2 && !STM32_HAS_TIM2 +#error "TIM2 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM3 && !STM32_HAS_TIM3 +#error "TIM3 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM4 && !STM32_HAS_TIM4 +#error "TIM4 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM5 && !STM32_HAS_TIM5 +#error "TIM5 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM6 && !STM32_HAS_TIM6 +#error "TIM6 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM7 && !STM32_HAS_TIM7 +#error "TIM7 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM8 && !STM32_HAS_TIM8 +#error "TIM8 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM9 && !STM32_HAS_TIM9 +#error "TIM9 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM11 && !STM32_HAS_TIM11 +#error "TIM11 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM12 && !STM32_HAS_TIM12 +#error "TIM12 not present in the selected device" +#endif + +#if STM32_GPT_USE_TIM14 && !STM32_HAS_TIM14 +#error "TIM14 not present in the selected device" +#endif + +#if !STM32_GPT_USE_TIM1 && !STM32_GPT_USE_TIM2 && \ + !STM32_GPT_USE_TIM3 && !STM32_GPT_USE_TIM4 && \ + !STM32_GPT_USE_TIM5 && !STM32_GPT_USE_TIM6 && \ + !STM32_GPT_USE_TIM7 && !STM32_GPT_USE_TIM8 && \ + !STM32_GPT_USE_TIM9 && !STM32_GPT_USE_TIM11 && \ + !STM32_GPT_USE_TIM12 && !STM32_GPT_USE_TIM14 +#error "GPT driver activated but no TIM peripheral assigned" +#endif + +#if STM32_GPT_USE_TIM1 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM1" +#endif + +#if STM32_GPT_USE_TIM2 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM2" +#endif + +#if STM32_GPT_USE_TIM3 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM3" +#endif + +#if STM32_GPT_USE_TIM4 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM4_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM4" +#endif + +#if STM32_GPT_USE_TIM5 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM5_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM5" +#endif + +#if STM32_GPT_USE_TIM6 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM6_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM6" +#endif + +#if STM32_GPT_USE_TIM7 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM7_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM7" +#endif + +#if STM32_GPT_USE_TIM8 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM8_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM8" +#endif + +#if STM32_GPT_USE_TIM9 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM9_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM9" +#endif + +#if STM32_GPT_USE_TIM11 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM11_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM11" +#endif + +#if STM32_GPT_USE_TIM12 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM12_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM12" +#endif + +#if STM32_GPT_USE_TIM14 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM14_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM14" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief GPT frequency type. + */ +typedef uint32_t gptfreq_t; + +/** + * @brief GPT counter type. + */ +typedef uint16_t gptcnt_t; + +/** + * @brief Driver configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct { + /** + * @brief Timer clock in Hz. + * @note The low level can use assertions in order to catch invalid + * frequency specifications. + */ + gptfreq_t frequency; + /** + * @brief Timer callback pointer. + * @note This callback is invoked on GPT counter events. + */ + gptcallback_t callback; + /* End of the mandatory fields.*/ +} GPTConfig; + +/** + * @brief Structure representing a GPT driver. + */ +struct GPTDriver { + /** + * @brief Driver state. + */ + gptstate_t state; + /** + * @brief Current configuration data. + */ + const GPTConfig *config; +#if defined(GPT_DRIVER_EXT_FIELDS) + GPT_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Timer base clock. + */ + uint32_t clock; + /** + * @brief Pointer to the TIMx registers block. + */ + stm32_tim_t *tim; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Changes the interval of GPT peripheral. + * @details This function changes the interval of a running GPT unit. + * @pre The GPT unit must have been activated using @p gptStart(). + * @pre The GPT unit must have been running in continuous mode using + * @p gptStartContinuous(). + * @post The GPT unit interval is changed to the new value. + * @note The function has effect at the next cycle start. + * + * @param[in] gptp pointer to a @p GPTDriver object + * @param[in] interval new cycle time in timer ticks + * @notapi + */ +#define gpt_lld_change_interval(gptp, interval) \ + ((gptp)->tim->ARR = (uint16_t)((interval) - 1)) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_GPT_USE_TIM1 && !defined(__DOXYGEN__) +extern GPTDriver GPTD1; +#endif + +#if STM32_GPT_USE_TIM2 && !defined(__DOXYGEN__) +extern GPTDriver GPTD2; +#endif + +#if STM32_GPT_USE_TIM3 && !defined(__DOXYGEN__) +extern GPTDriver GPTD3; +#endif + +#if STM32_GPT_USE_TIM4 && !defined(__DOXYGEN__) +extern GPTDriver GPTD4; +#endif + +#if STM32_GPT_USE_TIM5 && !defined(__DOXYGEN__) +extern GPTDriver GPTD5; +#endif + +#if STM32_GPT_USE_TIM6 && !defined(__DOXYGEN__) +extern GPTDriver GPTD6; +#endif + +#if STM32_GPT_USE_TIM7 && !defined(__DOXYGEN__) +extern GPTDriver GPTD7; +#endif + +#if STM32_GPT_USE_TIM8 && !defined(__DOXYGEN__) +extern GPTDriver GPTD8; +#endif + +#if STM32_GPT_USE_TIM9 && !defined(__DOXYGEN__) +extern GPTDriver GPTD9; +#endif + +#if STM32_GPT_USE_TIM11 && !defined(__DOXYGEN__) +extern GPTDriver GPTD11; +#endif + +#if STM32_GPT_USE_TIM12 && !defined(__DOXYGEN__) +extern GPTDriver GPTD12; +#endif + +#if STM32_GPT_USE_TIM14 && !defined(__DOXYGEN__) +extern GPTDriver GPTD14; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void gpt_lld_init(void); + void gpt_lld_start(GPTDriver *gptp); + void gpt_lld_stop(GPTDriver *gptp); + void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t period); + void gpt_lld_stop_timer(GPTDriver *gptp); + void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_GPT */ + +#endif /* _GPT_LLD_H_ */ + +/** @} */ diff --git a/os/hal/platforms/STM32/TIMv1/icu_lld.c b/os/hal/platforms/STM32/TIMv1/icu_lld.c new file mode 100644 index 000000000..ad838d903 --- /dev/null +++ b/os/hal/platforms/STM32/TIMv1/icu_lld.c @@ -0,0 +1,641 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Fabio Utzig and + Xo Wang. + */ + +/** + * @file STM32/icu_lld.c + * @brief STM32 ICU subsystem low level driver header. + * + * @addtogroup ICU + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#if HAL_USE_ICU || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief ICUD1 driver identifier. + * @note The driver ICUD1 allocates the complex timer TIM1 when enabled. + */ +#if STM32_ICU_USE_TIM1 || defined(__DOXYGEN__) +ICUDriver ICUD1; +#endif + +/** + * @brief ICUD2 driver identifier. + * @note The driver ICUD1 allocates the timer TIM2 when enabled. + */ +#if STM32_ICU_USE_TIM2 || defined(__DOXYGEN__) +ICUDriver ICUD2; +#endif + +/** + * @brief ICUD3 driver identifier. + * @note The driver ICUD1 allocates the timer TIM3 when enabled. + */ +#if STM32_ICU_USE_TIM3 || defined(__DOXYGEN__) +ICUDriver ICUD3; +#endif + +/** + * @brief ICUD4 driver identifier. + * @note The driver ICUD4 allocates the timer TIM4 when enabled. + */ +#if STM32_ICU_USE_TIM4 || defined(__DOXYGEN__) +ICUDriver ICUD4; +#endif + +/** + * @brief ICUD5 driver identifier. + * @note The driver ICUD5 allocates the timer TIM5 when enabled. + */ +#if STM32_ICU_USE_TIM5 || defined(__DOXYGEN__) +ICUDriver ICUD5; +#endif + +/** + * @brief ICUD8 driver identifier. + * @note The driver ICUD8 allocates the timer TIM8 when enabled. + */ +#if STM32_ICU_USE_TIM8 || defined(__DOXYGEN__) +ICUDriver ICUD8; +#endif + +/** + * @brief ICUD9 driver identifier. + * @note The driver ICUD9 allocates the timer TIM9 when enabled. + */ +#if STM32_ICU_USE_TIM9 || defined(__DOXYGEN__) +ICUDriver ICUD9; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Shared IRQ handler. + * + * @param[in] icup pointer to the @p ICUDriver object + */ +static void icu_lld_serve_interrupt(ICUDriver *icup) { + uint16_t sr; + + sr = icup->tim->SR; + sr &= icup->tim->DIER; + icup->tim->SR = ~sr; + if (icup->config->channel == ICU_CHANNEL_1) { + if ((sr & STM32_TIM_SR_CC1IF) != 0) + _icu_isr_invoke_period_cb(icup); + if ((sr & STM32_TIM_SR_CC2IF) != 0) + _icu_isr_invoke_width_cb(icup); + } else { + if ((sr & STM32_TIM_SR_CC1IF) != 0) + _icu_isr_invoke_width_cb(icup); + if ((sr & STM32_TIM_SR_CC2IF) != 0) + _icu_isr_invoke_period_cb(icup); + } + if ((sr & STM32_TIM_SR_UIF) != 0) + _icu_isr_invoke_overflow_cb(icup); +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_ICU_USE_TIM1 +#if !defined(STM32_TIM1_UP_HANDLER) +#error "STM32_TIM1_UP_HANDLER not defined" +#endif +/** + * @brief TIM1 compare interrupt handler. + * @note It is assumed that the various sources are only activated if the + * associated callback pointer is not equal to @p NULL in order to not + * perform an extra check in a potentially critical interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) { + + CH_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD1); + + CH_IRQ_EPILOGUE(); +} + +#if !defined(STM32_TIM1_CC_HANDLER) +#error "STM32_TIM1_CC_HANDLER not defined" +#endif +/** + * @brief TIM1 compare interrupt handler. + * @note It is assumed that the various sources are only activated if the + * associated callback pointer is not equal to @p NULL in order to not + * perform an extra check in a potentially critical interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM1_CC_HANDLER) { + + CH_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD1); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_ICU_USE_TIM1 */ + +#if STM32_ICU_USE_TIM2 +#if !defined(STM32_TIM2_HANDLER) +#error "STM32_TIM2_HANDLER not defined" +#endif +/** + * @brief TIM2 interrupt handler. + * @note It is assumed that the various sources are only activated if the + * associated callback pointer is not equal to @p NULL in order to not + * perform an extra check in a potentially critical interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM2_HANDLER) { + + CH_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD2); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_ICU_USE_TIM2 */ + +#if STM32_ICU_USE_TIM3 +#if !defined(STM32_TIM3_HANDLER) +#error "STM32_TIM3_HANDLER not defined" +#endif +/** + * @brief TIM3 interrupt handler. + * @note It is assumed that the various sources are only activated if the + * associated callback pointer is not equal to @p NULL in order to not + * perform an extra check in a potentially critical interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM3_HANDLER) { + + CH_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD3); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_ICU_USE_TIM3 */ + +#if STM32_ICU_USE_TIM4 +#if !defined(STM32_TIM4_HANDLER) +#error "STM32_TIM4_HANDLER not defined" +#endif +/** + * @brief TIM4 interrupt handler. + * @note It is assumed that the various sources are only activated if the + * associated callback pointer is not equal to @p NULL in order to not + * perform an extra check in a potentially critical interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM4_HANDLER) { + + CH_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD4); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_ICU_USE_TIM4 */ + +#if STM32_ICU_USE_TIM5 +#if !defined(STM32_TIM5_HANDLER) +#error "STM32_TIM5_HANDLER not defined" +#endif +/** + * @brief TIM5 interrupt handler. + * @note It is assumed that the various sources are only activated if the + * associated callback pointer is not equal to @p NULL in order to not + * perform an extra check in a potentially critical interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM5_HANDLER) { + + CH_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD5); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_ICU_USE_TIM5 */ + +#if STM32_ICU_USE_TIM8 +#if !defined(STM32_TIM8_UP_HANDLER) +#error "STM32_TIM8_UP_HANDLER not defined" +#endif +/** + * @brief TIM8 compare interrupt handler. + * @note It is assumed that the various sources are only activated if the + * associated callback pointer is not equal to @p NULL in order to not + * perform an extra check in a potentially critical interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) { + + CH_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD8); + + CH_IRQ_EPILOGUE(); +} + +#if !defined(STM32_TIM8_CC_HANDLER) +#error "STM32_TIM8_CC_HANDLER not defined" +#endif +/** + * @brief TIM8 compare interrupt handler. + * @note It is assumed that the various sources are only activated if the + * associated callback pointer is not equal to @p NULL in order to not + * perform an extra check in a potentially critical interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM8_CC_HANDLER) { + + CH_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD8); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_ICU_USE_TIM8 */ + +#if STM32_ICU_USE_TIM9 +#if !defined(STM32_TIM9_HANDLER) +#error "STM32_TIM9_HANDLER not defined" +#endif +/** + * @brief TIM9 interrupt handler. + * @note It is assumed that the various sources are only activated if the + * associated callback pointer is not equal to @p NULL in order to not + * perform an extra check in a potentially critical interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM9_HANDLER) { + + CH_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD9); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_ICU_USE_TIM9 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level ICU driver initialization. + * + * @notapi + */ +void icu_lld_init(void) { + +#if STM32_ICU_USE_TIM1 + /* Driver initialization.*/ + icuObjectInit(&ICUD1); + ICUD1.tim = STM32_TIM1; +#endif + +#if STM32_ICU_USE_TIM2 + /* Driver initialization.*/ + icuObjectInit(&ICUD2); + ICUD2.tim = STM32_TIM2; +#endif + +#if STM32_ICU_USE_TIM3 + /* Driver initialization.*/ + icuObjectInit(&ICUD3); + ICUD3.tim = STM32_TIM3; +#endif + +#if STM32_ICU_USE_TIM4 + /* Driver initialization.*/ + icuObjectInit(&ICUD4); + ICUD4.tim = STM32_TIM4; +#endif + +#if STM32_ICU_USE_TIM5 + /* Driver initialization.*/ + icuObjectInit(&ICUD5); + ICUD5.tim = STM32_TIM5; +#endif + +#if STM32_ICU_USE_TIM8 + /* Driver initialization.*/ + icuObjectInit(&ICUD8); + ICUD8.tim = STM32_TIM8; +#endif + +#if STM32_ICU_USE_TIM9 + /* Driver initialization.*/ + icuObjectInit(&ICUD9); + ICUD9.tim = STM32_TIM9; +#endif +} + +/** + * @brief Configures and activates the ICU peripheral. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @notapi + */ +void icu_lld_start(ICUDriver *icup) { + uint32_t psc; + + chDbgAssert((icup->config->channel == ICU_CHANNEL_1) || + (icup->config->channel == ICU_CHANNEL_2), + "icu_lld_start(), #1", "invalid input"); + + if (icup->state == ICU_STOP) { + /* Clock activation and timer reset.*/ +#if STM32_ICU_USE_TIM1 + if (&ICUD1 == icup) { + rccEnableTIM1(FALSE); + rccResetTIM1(); + nvicEnableVector(STM32_TIM1_UP_NUMBER, + CORTEX_PRIORITY_MASK(STM32_ICU_TIM1_IRQ_PRIORITY)); + nvicEnableVector(STM32_TIM1_CC_NUMBER, + CORTEX_PRIORITY_MASK(STM32_ICU_TIM1_IRQ_PRIORITY)); + icup->clock = STM32_TIMCLK2; + } +#endif +#if STM32_ICU_USE_TIM2 + if (&ICUD2 == icup) { + rccEnableTIM2(FALSE); + rccResetTIM2(); + nvicEnableVector(STM32_TIM2_NUMBER, + CORTEX_PRIORITY_MASK(STM32_ICU_TIM2_IRQ_PRIORITY)); + icup->clock = STM32_TIMCLK1; + } +#endif +#if STM32_ICU_USE_TIM3 + if (&ICUD3 == icup) { + rccEnableTIM3(FALSE); + rccResetTIM3(); + nvicEnableVector(STM32_TIM3_NUMBER, + CORTEX_PRIORITY_MASK(STM32_ICU_TIM3_IRQ_PRIORITY)); + icup->clock = STM32_TIMCLK1; + } +#endif +#if STM32_ICU_USE_TIM4 + if (&ICUD4 == icup) { + rccEnableTIM4(FALSE); + rccResetTIM4(); + nvicEnableVector(STM32_TIM4_NUMBER, + CORTEX_PRIORITY_MASK(STM32_ICU_TIM4_IRQ_PRIORITY)); + icup->clock = STM32_TIMCLK1; + } +#endif +#if STM32_ICU_USE_TIM5 + if (&ICUD5 == icup) { + rccEnableTIM5(FALSE); + rccResetTIM5(); + nvicEnableVector(STM32_TIM5_NUMBER, + CORTEX_PRIORITY_MASK(STM32_ICU_TIM5_IRQ_PRIORITY)); + icup->clock = STM32_TIMCLK1; + } +#endif +#if STM32_ICU_USE_TIM8 + if (&ICUD8 == icup) { + rccEnableTIM8(FALSE); + rccResetTIM8(); + nvicEnableVector(STM32_TIM8_UP_NUMBER, + CORTEX_PRIORITY_MASK(STM32_ICU_TIM8_IRQ_PRIORITY)); + nvicEnableVector(STM32_TIM8_CC_NUMBER, + CORTEX_PRIORITY_MASK(STM32_ICU_TIM8_IRQ_PRIORITY)); + icup->clock = STM32_TIMCLK2; + } +#endif +#if STM32_ICU_USE_TIM9 + if (&ICUD9 == icup) { + rccEnableTIM9(FALSE); + rccResetTIM9(); + nvicEnableVector(STM32_TIM9_NUMBER, + CORTEX_PRIORITY_MASK(STM32_ICU_TIM9_IRQ_PRIORITY)); + icup->clock = STM32_TIMCLK1; + } +#endif + } + else { + /* Driver re-configuration scenario, it must be stopped first.*/ + icup->tim->CR1 = 0; /* Timer disabled. */ + icup->tim->DIER = 0; /* All IRQs disabled. */ + icup->tim->SR = 0; /* Clear eventual pending IRQs. */ + icup->tim->CCR[0] = 0; /* Comparator 1 disabled. */ + icup->tim->CCR[1] = 0; /* Comparator 2 disabled. */ + icup->tim->CNT = 0; /* Counter reset to zero. */ + } + + /* Timer configuration.*/ + psc = (icup->clock / icup->config->frequency) - 1; + chDbgAssert((psc <= 0xFFFF) && + ((psc + 1) * icup->config->frequency) == icup->clock, + "icu_lld_start(), #1", "invalid frequency"); + icup->tim->PSC = (uint16_t)psc; + icup->tim->ARR = 0xFFFF; + + if (icup->config->channel == ICU_CHANNEL_1) { + /* Selected input 1. + CCMR1_CC1S = 01 = CH1 Input on TI1. + CCMR1_CC2S = 10 = CH2 Input on TI1.*/ + icup->tim->CCMR1 = STM32_TIM_CCMR1_CC1S(1) | STM32_TIM_CCMR1_CC2S(2); + + /* SMCR_TS = 101, input is TI1FP1. + SMCR_SMS = 100, reset on rising edge.*/ + icup->tim->SMCR = STM32_TIM_SMCR_TS(5) | STM32_TIM_SMCR_SMS(4); + + /* The CCER settings depend on the selected trigger mode. + ICU_INPUT_ACTIVE_HIGH: Active on rising edge, idle on falling edge. + ICU_INPUT_ACTIVE_LOW: Active on falling edge, idle on rising edge.*/ + if (icup->config->mode == ICU_INPUT_ACTIVE_HIGH) + icup->tim->CCER = STM32_TIM_CCER_CC1E | + STM32_TIM_CCER_CC2E | STM32_TIM_CCER_CC2P; + else + icup->tim->CCER = STM32_TIM_CCER_CC1E | STM32_TIM_CCER_CC1P | + STM32_TIM_CCER_CC2E; + + /* Direct pointers to the capture registers in order to make reading + data faster from within callbacks.*/ + icup->wccrp = &icup->tim->CCR[1]; + icup->pccrp = &icup->tim->CCR[0]; + } else { + /* Selected input 2. + CCMR1_CC1S = 10 = CH1 Input on TI2. + CCMR1_CC2S = 01 = CH2 Input on TI2.*/ + icup->tim->CCMR1 = STM32_TIM_CCMR1_CC1S(2) | STM32_TIM_CCMR1_CC2S(1); + + /* SMCR_TS = 110, input is TI2FP2. + SMCR_SMS = 100, reset on rising edge.*/ + icup->tim->SMCR = STM32_TIM_SMCR_TS(6) | STM32_TIM_SMCR_SMS(4); + + /* The CCER settings depend on the selected trigger mode. + ICU_INPUT_ACTIVE_HIGH: Active on rising edge, idle on falling edge. + ICU_INPUT_ACTIVE_LOW: Active on falling edge, idle on rising edge.*/ + if (icup->config->mode == ICU_INPUT_ACTIVE_HIGH) + icup->tim->CCER = STM32_TIM_CCER_CC1E | STM32_TIM_CCER_CC1P | + STM32_TIM_CCER_CC2E; + else + icup->tim->CCER = STM32_TIM_CCER_CC1E | + STM32_TIM_CCER_CC2E | STM32_TIM_CCER_CC2P; + + /* Direct pointers to the capture registers in order to make reading + data faster from within callbacks.*/ + icup->wccrp = &icup->tim->CCR[0]; + icup->pccrp = &icup->tim->CCR[1]; + } +} + +/** + * @brief Deactivates the ICU peripheral. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @notapi + */ +void icu_lld_stop(ICUDriver *icup) { + + if (icup->state == ICU_READY) { + /* Clock deactivation.*/ + icup->tim->CR1 = 0; /* Timer disabled. */ + icup->tim->DIER = 0; /* All IRQs disabled. */ + icup->tim->SR = 0; /* Clear eventual pending IRQs. */ + +#if STM32_ICU_USE_TIM1 + if (&ICUD1 == icup) { + nvicDisableVector(STM32_TIM1_UP_NUMBER); + nvicDisableVector(STM32_TIM1_CC_NUMBER); + rccDisableTIM1(FALSE); + } +#endif +#if STM32_ICU_USE_TIM2 + if (&ICUD2 == icup) { + nvicDisableVector(STM32_TIM2_NUMBER); + rccDisableTIM2(FALSE); + } +#endif +#if STM32_ICU_USE_TIM3 + if (&ICUD3 == icup) { + nvicDisableVector(STM32_TIM3_NUMBER); + rccDisableTIM3(FALSE); + } +#endif +#if STM32_ICU_USE_TIM4 + if (&ICUD4 == icup) { + nvicDisableVector(STM32_TIM4_NUMBER); + rccDisableTIM4(FALSE); + } +#endif +#if STM32_ICU_USE_TIM5 + if (&ICUD5 == icup) { + nvicDisableVector(STM32_TIM5_NUMBER); + rccDisableTIM5(FALSE); + } +#endif +#if STM32_ICU_USE_TIM8 + if (&ICUD8 == icup) { + nvicDisableVector(STM32_TIM8_UP_NUMBER); + nvicDisableVector(STM32_TIM8_CC_NUMBER); + rccDisableTIM8(FALSE); + } +#endif +#if STM32_ICU_USE_TIM9 + if (&ICUD9 == icup) { + nvicDisableVector(STM32_TIM9_NUMBER); + rccDisableTIM9(FALSE); + } +#endif + } +} + +/** + * @brief Enables the input capture. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @notapi + */ +void icu_lld_enable(ICUDriver *icup) { + + 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 |= STM32_TIM_DIER_CC1IE; + if (icup->config->width_cb != NULL) + icup->tim->DIER |= STM32_TIM_DIER_CC2IE; + } else { + if (icup->config->width_cb != NULL) + icup->tim->DIER |= STM32_TIM_DIER_CC1IE; + if (icup->config->period_cb != NULL) + icup->tim->DIER |= STM32_TIM_DIER_CC2IE; + } + if (icup->config->overflow_cb != NULL) + icup->tim->DIER |= STM32_TIM_DIER_UIE; + icup->tim->CR1 = STM32_TIM_CR1_URS | STM32_TIM_CR1_CEN; +} + +/** + * @brief Disables the input capture. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @notapi + */ +void icu_lld_disable(ICUDriver *icup) { + + icup->tim->CR1 = 0; /* Initially stopped. */ + icup->tim->SR = 0; /* Clear pending IRQs (if any). */ + icup->tim->DIER = 0; /* Interrupts disabled. */ +} + +#endif /* HAL_USE_ICU */ + +/** @} */ diff --git a/os/hal/platforms/STM32/TIMv1/icu_lld.h b/os/hal/platforms/STM32/TIMv1/icu_lld.h new file mode 100644 index 000000000..ad6ddffe5 --- /dev/null +++ b/os/hal/platforms/STM32/TIMv1/icu_lld.h @@ -0,0 +1,406 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/icu_lld.h + * @brief STM32 ICU subsystem low level driver header. + * + * @addtogroup ICU + * @{ + */ + +#ifndef _ICU_LLD_H_ +#define _ICU_LLD_H_ + +#include "stm32_tim.h" + +#if HAL_USE_ICU || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief ICUD1 driver enable switch. + * @details If set to @p TRUE the support for ICUD1 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_ICU_USE_TIM1) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM1 FALSE +#endif + +/** + * @brief ICUD2 driver enable switch. + * @details If set to @p TRUE the support for ICUD2 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_ICU_USE_TIM2) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM2 FALSE +#endif + +/** + * @brief ICUD3 driver enable switch. + * @details If set to @p TRUE the support for ICUD3 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_ICU_USE_TIM3) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM3 FALSE +#endif + +/** + * @brief ICUD4 driver enable switch. + * @details If set to @p TRUE the support for ICUD4 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_ICU_USE_TIM4) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM4 FALSE +#endif + +/** + * @brief ICUD5 driver enable switch. + * @details If set to @p TRUE the support for ICUD5 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_ICU_USE_TIM5) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM5 FALSE +#endif + +/** + * @brief ICUD8 driver enable switch. + * @details If set to @p TRUE the support for ICUD8 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_ICU_USE_TIM8) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM8 FALSE +#endif + +/** + * @brief ICUD9 driver enable switch. + * @details If set to @p TRUE the support for ICUD9 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_ICU_USE_TIM9) || defined(__DOXYGEN__) +#define STM32_ICU_USE_TIM9 FALSE +#endif + +/** + * @brief ICUD1 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#endif + +/** + * @brief ICUD2 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#endif + +/** + * @brief ICUD3 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#endif + +/** + * @brief ICUD4 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#endif + +/** + * @brief ICUD5 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM5_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#endif + +/** + * @brief ICUD8 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM8_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#endif + +/** + * @brief ICUD9 interrupt priority level setting. + */ +#if !defined(STM32_ICU_TIM9_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_ICU_USE_TIM1 && !STM32_HAS_TIM1 +#error "TIM1 not present in the selected device" +#endif + +#if STM32_ICU_USE_TIM2 && !STM32_HAS_TIM2 +#error "TIM2 not present in the selected device" +#endif + +#if STM32_ICU_USE_TIM3 && !STM32_HAS_TIM3 +#error "TIM3 not present in the selected device" +#endif + +#if STM32_ICU_USE_TIM4 && !STM32_HAS_TIM4 +#error "TIM4 not present in the selected device" +#endif + +#if STM32_ICU_USE_TIM5 && !STM32_HAS_TIM5 +#error "TIM5 not present in the selected device" +#endif + +#if STM32_ICU_USE_TIM8 && !STM32_HAS_TIM8 +#error "TIM8 not present in the selected device" +#endif + +#if STM32_ICU_USE_TIM9 && !STM32_HAS_TIM9 +#error "TIM9 not present in the selected device" +#endif + +#if !STM32_ICU_USE_TIM1 && !STM32_ICU_USE_TIM2 && \ + !STM32_ICU_USE_TIM3 && !STM32_ICU_USE_TIM4 && \ + !STM32_ICU_USE_TIM5 && !STM32_ICU_USE_TIM8 && \ + !STM32_ICU_USE_TIM9 +#error "ICU driver activated but no TIM peripheral assigned" +#endif + +#if STM32_ICU_USE_TIM1 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM1" +#endif + +#if STM32_ICU_USE_TIM2 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM2" +#endif + +#if STM32_ICU_USE_TIM3 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM3" +#endif + +#if STM32_ICU_USE_TIM4 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM4_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM4" +#endif + +#if STM32_ICU_USE_TIM5 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM5_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM5" +#endif + +#if STM32_ICU_USE_TIM8 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM8_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM8" +#endif + +#if STM32_ICU_USE_TIM9 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM9_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM9" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief ICU driver mode. + */ +typedef enum { + ICU_INPUT_ACTIVE_HIGH = 0, /**< Trigger on rising edge. */ + ICU_INPUT_ACTIVE_LOW = 1, /**< Trigger on falling edge. */ +} icumode_t; + +/** + * @brief ICU frequency type. + */ +typedef uint32_t icufreq_t; + +/** + * @brief ICU channel type. + */ +typedef enum { + ICU_CHANNEL_1 = 0, /**< Use TIMxCH1. */ + ICU_CHANNEL_2 = 1, /**< Use TIMxCH2. */ +} icuchannel_t; + +/** + * @brief ICU counter type. + */ +typedef uint16_t icucnt_t; + +/** + * @brief Driver configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct { + /** + * @brief Driver mode. + */ + icumode_t mode; + /** + * @brief Timer clock in Hz. + * @note The low level can use assertions in order to catch invalid + * frequency specifications. + */ + icufreq_t frequency; + /** + * @brief Callback for pulse width measurement. + */ + icucallback_t width_cb; + /** + * @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. + * @note Only inputs TIMx 1 and 2 are supported. + */ + icuchannel_t channel; +} ICUConfig; + +/** + * @brief Structure representing an ICU driver. + */ +struct ICUDriver { + /** + * @brief Driver state. + */ + icustate_t state; + /** + * @brief Current configuration data. + */ + const ICUConfig *config; +#if defined(ICU_DRIVER_EXT_FIELDS) + ICU_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Timer base clock. + */ + uint32_t clock; + /** + * @brief Pointer to the TIMx registers block. + */ + stm32_tim_t *tim; + /** + * @brief CCR register used for width capture. + */ + volatile uint32_t *wccrp; + /** + * @brief CCR register used for period capture. + */ + volatile uint32_t *pccrp; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Returns the width of the latest pulse. + * @details The pulse width is defined as number of ticks between the start + * edge and the stop edge. + * + * @param[in] icup pointer to the @p ICUDriver object + * @return The number of ticks. + * + * @notapi + */ +#define icu_lld_get_width(icup) (*((icup)->wccrp) + 1) + +/** + * @brief Returns the width of the latest cycle. + * @details The cycle width is defined as number of ticks between a start + * edge and the next start edge. + * + * @param[in] icup pointer to the @p ICUDriver object + * @return The number of ticks. + * + * @notapi + */ +#define icu_lld_get_period(icup) (*((icup)->pccrp) + 1) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_ICU_USE_TIM1 && !defined(__DOXYGEN__) +extern ICUDriver ICUD1; +#endif + +#if STM32_ICU_USE_TIM2 && !defined(__DOXYGEN__) +extern ICUDriver ICUD2; +#endif + +#if STM32_ICU_USE_TIM3 && !defined(__DOXYGEN__) +extern ICUDriver ICUD3; +#endif + +#if STM32_ICU_USE_TIM4 && !defined(__DOXYGEN__) +extern ICUDriver ICUD4; +#endif + +#if STM32_ICU_USE_TIM5 && !defined(__DOXYGEN__) +extern ICUDriver ICUD5; +#endif + +#if STM32_ICU_USE_TIM8 && !defined(__DOXYGEN__) +extern ICUDriver ICUD8; +#endif + +#if STM32_ICU_USE_TIM9 && !defined(__DOXYGEN__) +extern ICUDriver ICUD9; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void icu_lld_init(void); + void icu_lld_start(ICUDriver *icup); + void icu_lld_stop(ICUDriver *icup); + void icu_lld_enable(ICUDriver *icup); + void icu_lld_disable(ICUDriver *icup); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_ICU */ + +#endif /* _ICU_LLD_H_ */ + +/** @} */ diff --git a/os/hal/platforms/STM32/TIMv1/pwm_lld.c b/os/hal/platforms/STM32/TIMv1/pwm_lld.c new file mode 100644 index 000000000..97114ac79 --- /dev/null +++ b/os/hal/platforms/STM32/TIMv1/pwm_lld.c @@ -0,0 +1,705 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/pwm_lld.c + * @brief STM32 PWM subsystem low level driver header. + * + * @addtogroup PWM + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#if HAL_USE_PWM || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief PWMD1 driver identifier. + * @note The driver PWMD1 allocates the complex timer TIM1 when enabled. + */ +#if STM32_PWM_USE_TIM1 || defined(__DOXYGEN__) +PWMDriver PWMD1; +#endif + +/** + * @brief PWMD2 driver identifier. + * @note The driver PWMD2 allocates the timer TIM2 when enabled. + */ +#if STM32_PWM_USE_TIM2 || defined(__DOXYGEN__) +PWMDriver PWMD2; +#endif + +/** + * @brief PWMD3 driver identifier. + * @note The driver PWMD3 allocates the timer TIM3 when enabled. + */ +#if STM32_PWM_USE_TIM3 || defined(__DOXYGEN__) +PWMDriver PWMD3; +#endif + +/** + * @brief PWMD4 driver identifier. + * @note The driver PWMD4 allocates the timer TIM4 when enabled. + */ +#if STM32_PWM_USE_TIM4 || defined(__DOXYGEN__) +PWMDriver PWMD4; +#endif + +/** + * @brief PWMD5 driver identifier. + * @note The driver PWMD5 allocates the timer TIM5 when enabled. + */ +#if STM32_PWM_USE_TIM5 || defined(__DOXYGEN__) +PWMDriver PWMD5; +#endif + +/** + * @brief PWMD8 driver identifier. + * @note The driver PWMD8 allocates the timer TIM8 when enabled. + */ +#if STM32_PWM_USE_TIM8 || defined(__DOXYGEN__) +PWMDriver PWMD8; +#endif + +/** + * @brief PWMD9 driver identifier. + * @note The driver PWMD9 allocates the timer TIM9 when enabled. + */ +#if STM32_PWM_USE_TIM9 || defined(__DOXYGEN__) +PWMDriver PWMD9; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +#if STM32_PWM_USE_TIM2 || STM32_PWM_USE_TIM3 || STM32_PWM_USE_TIM4 || \ + STM32_PWM_USE_TIM5 || STM32_PWM_USE_TIM9 || defined(__DOXYGEN__) +/** + * @brief Common TIM2...TIM5,TIM9 IRQ handler. + * @note It is assumed that the various sources are only activated if the + * associated callback pointer is not equal to @p NULL in order to not + * perform an extra check in a potentially critical interrupt handler. + * + * @param[in] pwmp pointer to a @p PWMDriver object + */ +static void pwm_lld_serve_interrupt(PWMDriver *pwmp) { + uint16_t sr; + + sr = pwmp->tim->SR; + sr &= pwmp->tim->DIER; + pwmp->tim->SR = ~sr; + if ((sr & STM32_TIM_SR_CC1IF) != 0) + pwmp->config->channels[0].callback(pwmp); + if ((sr & STM32_TIM_SR_CC2IF) != 0) + pwmp->config->channels[1].callback(pwmp); + if ((sr & STM32_TIM_SR_CC3IF) != 0) + pwmp->config->channels[2].callback(pwmp); + if ((sr & STM32_TIM_SR_CC4IF) != 0) + pwmp->config->channels[3].callback(pwmp); + if ((sr & STM32_TIM_SR_UIF) != 0) + pwmp->config->callback(pwmp); +} +#endif /* STM32_PWM_USE_TIM2 || ... || STM32_PWM_USE_TIM5 */ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_PWM_USE_TIM1 +#if !defined(STM32_TIM1_UP_HANDLER) +#error "STM32_TIM1_UP_HANDLER not defined" +#endif +/** + * @brief TIM1 update interrupt handler. + * @note It is assumed that this interrupt is only activated if the callback + * pointer is not equal to @p NULL in order to not perform an extra + * check in a potentially critical interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) { + + CH_IRQ_PROLOGUE(); + + STM32_TIM1->SR = ~STM32_TIM_SR_UIF; + PWMD1.config->callback(&PWMD1); + + CH_IRQ_EPILOGUE(); +} + +#if !defined(STM32_TIM1_CC_HANDLER) +#error "STM32_TIM1_CC_HANDLER not defined" +#endif +/** + * @brief TIM1 compare interrupt handler. + * @note It is assumed that the various sources are only activated if the + * associated callback pointer is not equal to @p NULL in order to not + * perform an extra check in a potentially critical interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM1_CC_HANDLER) { + uint16_t sr; + + CH_IRQ_PROLOGUE(); + + sr = STM32_TIM1->SR & STM32_TIM1->DIER; + STM32_TIM1->SR = ~(STM32_TIM_SR_CC1IF | STM32_TIM_SR_CC2IF | + STM32_TIM_SR_CC3IF | STM32_TIM_SR_CC4IF); + if ((sr & STM32_TIM_SR_CC1IF) != 0) + PWMD1.config->channels[0].callback(&PWMD1); + if ((sr & STM32_TIM_SR_CC2IF) != 0) + PWMD1.config->channels[1].callback(&PWMD1); + if ((sr & STM32_TIM_SR_CC3IF) != 0) + PWMD1.config->channels[2].callback(&PWMD1); + if ((sr & STM32_TIM_SR_CC4IF) != 0) + PWMD1.config->channels[3].callback(&PWMD1); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_PWM_USE_TIM1 */ + +#if STM32_PWM_USE_TIM2 +#if !defined(STM32_TIM2_HANDLER) +#error "STM32_TIM2_HANDLER not defined" +#endif +/** + * @brief TIM2 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM2_HANDLER) { + + CH_IRQ_PROLOGUE(); + + pwm_lld_serve_interrupt(&PWMD2); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_PWM_USE_TIM2 */ + +#if STM32_PWM_USE_TIM3 +#if !defined(STM32_TIM3_HANDLER) +#error "STM32_TIM3_HANDLER not defined" +#endif +/** + * @brief TIM3 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM3_HANDLER) { + + CH_IRQ_PROLOGUE(); + + pwm_lld_serve_interrupt(&PWMD3); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_PWM_USE_TIM3 */ + +#if STM32_PWM_USE_TIM4 +#if !defined(STM32_TIM4_HANDLER) +#error "STM32_TIM4_HANDLER not defined" +#endif +/** + * @brief TIM4 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM4_HANDLER) { + + CH_IRQ_PROLOGUE(); + + pwm_lld_serve_interrupt(&PWMD4); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_PWM_USE_TIM4 */ + +#if STM32_PWM_USE_TIM5 +#if !defined(STM32_TIM5_HANDLER) +#error "STM32_TIM5_HANDLER not defined" +#endif +/** + * @brief TIM5 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM5_HANDLER) { + + CH_IRQ_PROLOGUE(); + + pwm_lld_serve_interrupt(&PWMD5); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_PWM_USE_TIM5 */ + +#if STM32_PWM_USE_TIM8 +#if !defined(STM32_TIM8_UP_HANDLER) +#error "STM32_TIM8_UP_HANDLER not defined" +#endif +/** + * @brief TIM8 update interrupt handler. + * @note It is assumed that this interrupt is only activated if the callback + * pointer is not equal to @p NULL in order to not perform an extra + * check in a potentially critical interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) { + + CH_IRQ_PROLOGUE(); + + STM32_TIM8->SR = ~TIM_SR_UIF; + PWMD8.config->callback(&PWMD8); + + CH_IRQ_EPILOGUE(); +} + +#if !defined(STM32_TIM8_CC_HANDLER) +#error "STM32_TIM8_CC_HANDLER not defined" +#endif +/** + * @brief TIM8 compare interrupt handler. + * @note It is assumed that the various sources are only activated if the + * associated callback pointer is not equal to @p NULL in order to not + * perform an extra check in a potentially critical interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM8_CC_HANDLER) { + uint16_t sr; + + CH_IRQ_PROLOGUE(); + + sr = STM32_TIM8->SR & STM32_TIM8->DIER; + STM32_TIM8->SR = ~(STM32_TIM_SR_CC1IF | STM32_TIM_SR_CC2IF | + STM32_TIM_SR_CC3IF | STM32_TIM_SR_CC4IF); + if ((sr & STM32_TIM_SR_CC1IF) != 0) + PWMD8.config->channels[0].callback(&PWMD8); + if ((sr & STM32_TIM_SR_CC2IF) != 0) + PWMD8.config->channels[1].callback(&PWMD8); + if ((sr & STM32_TIM_SR_CC3IF) != 0) + PWMD8.config->channels[2].callback(&PWMD8); + if ((sr & STM32_TIM_SR_CC4IF) != 0) + PWMD8.config->channels[3].callback(&PWMD8); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_PWM_USE_TIM8 */ + +#if STM32_PWM_USE_TIM9 +#if !defined(STM32_TIM9_HANDLER) +#error "STM32_TIM9_HANDLER not defined" +#endif +/** + * @brief TIM9 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(STM32_TIM9_HANDLER) { + + CH_IRQ_PROLOGUE(); + + pwm_lld_serve_interrupt(&PWMD9); + + CH_IRQ_EPILOGUE(); +} +#endif /* STM32_PWM_USE_TIM9 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level PWM driver initialization. + * + * @notapi + */ +void pwm_lld_init(void) { + +#if STM32_PWM_USE_TIM1 + /* Driver initialization.*/ + pwmObjectInit(&PWMD1); + PWMD1.tim = STM32_TIM1; +#endif + +#if STM32_PWM_USE_TIM2 + /* Driver initialization.*/ + pwmObjectInit(&PWMD2); + PWMD2.tim = STM32_TIM2; +#endif + +#if STM32_PWM_USE_TIM3 + /* Driver initialization.*/ + pwmObjectInit(&PWMD3); + PWMD3.tim = STM32_TIM3; +#endif + +#if STM32_PWM_USE_TIM4 + /* Driver initialization.*/ + pwmObjectInit(&PWMD4); + PWMD4.tim = STM32_TIM4; +#endif + +#if STM32_PWM_USE_TIM5 + /* Driver initialization.*/ + pwmObjectInit(&PWMD5); + PWMD5.tim = STM32_TIM5; +#endif + +#if STM32_PWM_USE_TIM8 + /* Driver initialization.*/ + pwmObjectInit(&PWMD8); + PWMD8.tim = STM32_TIM8; +#endif + +#if STM32_PWM_USE_TIM9 + /* Driver initialization.*/ + pwmObjectInit(&PWMD9); + PWMD9.tim = STM32_TIM9; +#endif +} + +/** + * @brief Configures and activates the PWM peripheral. + * @note Starting a driver that is already in the @p PWM_READY state + * disables all the active channels. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * + * @notapi + */ +void pwm_lld_start(PWMDriver *pwmp) { + uint32_t psc; + uint16_t ccer; + + if (pwmp->state == PWM_STOP) { + /* Clock activation and timer reset.*/ +#if STM32_PWM_USE_TIM1 + if (&PWMD1 == pwmp) { + rccEnableTIM1(FALSE); + rccResetTIM1(); + nvicEnableVector(STM32_TIM1_UP_NUMBER, + CORTEX_PRIORITY_MASK(STM32_PWM_TIM1_IRQ_PRIORITY)); + nvicEnableVector(STM32_TIM1_CC_NUMBER, + CORTEX_PRIORITY_MASK(STM32_PWM_TIM1_IRQ_PRIORITY)); + pwmp->clock = STM32_TIMCLK2; + } +#endif +#if STM32_PWM_USE_TIM2 + if (&PWMD2 == pwmp) { + rccEnableTIM2(FALSE); + rccResetTIM2(); + nvicEnableVector(STM32_TIM2_NUMBER, + CORTEX_PRIORITY_MASK(STM32_PWM_TIM2_IRQ_PRIORITY)); + pwmp->clock = STM32_TIMCLK1; + } +#endif +#if STM32_PWM_USE_TIM3 + if (&PWMD3 == pwmp) { + rccEnableTIM3(FALSE); + rccResetTIM3(); + nvicEnableVector(STM32_TIM3_NUMBER, + CORTEX_PRIORITY_MASK(STM32_PWM_TIM3_IRQ_PRIORITY)); + pwmp->clock = STM32_TIMCLK1; + } +#endif +#if STM32_PWM_USE_TIM4 + if (&PWMD4 == pwmp) { + rccEnableTIM4(FALSE); + rccResetTIM4(); + nvicEnableVector(STM32_TIM4_NUMBER, + CORTEX_PRIORITY_MASK(STM32_PWM_TIM4_IRQ_PRIORITY)); + pwmp->clock = STM32_TIMCLK1; + } +#endif + +#if STM32_PWM_USE_TIM5 + if (&PWMD5 == pwmp) { + rccEnableTIM5(FALSE); + rccResetTIM5(); + nvicEnableVector(STM32_TIM5_NUMBER, + CORTEX_PRIORITY_MASK(STM32_PWM_TIM5_IRQ_PRIORITY)); + pwmp->clock = STM32_TIMCLK1; + } +#endif +#if STM32_PWM_USE_TIM8 + if (&PWMD8 == pwmp) { + rccEnableTIM8(FALSE); + rccResetTIM8(); + nvicEnableVector(STM32_TIM8_UP_NUMBER, + CORTEX_PRIORITY_MASK(STM32_PWM_TIM8_IRQ_PRIORITY)); + nvicEnableVector(STM32_TIM8_CC_NUMBER, + CORTEX_PRIORITY_MASK(STM32_PWM_TIM8_IRQ_PRIORITY)); + pwmp->clock = STM32_TIMCLK2; + } +#endif +#if STM32_PWM_USE_TIM9 + if (&PWMD9 == pwmp) { + rccEnableTIM9(FALSE); + rccResetTIM9(); + nvicEnableVector(STM32_TIM9_NUMBER, + CORTEX_PRIORITY_MASK(STM32_PWM_TIM9_IRQ_PRIORITY)); + pwmp->clock = STM32_TIMCLK1; + } +#endif + + /* All channels configured in PWM1 mode with preload enabled and will + stay that way until the driver is stopped.*/ + pwmp->tim->CCMR1 = STM32_TIM_CCMR1_OC1M(6) | STM32_TIM_CCMR1_OC1PE | + STM32_TIM_CCMR1_OC2M(6) | STM32_TIM_CCMR1_OC2PE; + pwmp->tim->CCMR2 = STM32_TIM_CCMR2_OC3M(6) | STM32_TIM_CCMR2_OC3PE | + STM32_TIM_CCMR2_OC4M(6) | STM32_TIM_CCMR2_OC4PE; + } + else { + /* Driver re-configuration scenario, it must be stopped first.*/ + pwmp->tim->CR1 = 0; /* Timer disabled. */ + pwmp->tim->DIER = 0; /* All IRQs disabled. */ + pwmp->tim->SR = 0; /* Clear eventual pending IRQs. */ + pwmp->tim->CCR[0] = 0; /* Comparator 1 disabled. */ + pwmp->tim->CCR[1] = 0; /* Comparator 2 disabled. */ + pwmp->tim->CCR[2] = 0; /* Comparator 3 disabled. */ + pwmp->tim->CCR[3] = 0; /* Comparator 4 disabled. */ + pwmp->tim->CNT = 0; /* Counter reset to zero. */ + } + + /* Timer configuration.*/ + psc = (pwmp->clock / pwmp->config->frequency) - 1; + chDbgAssert((psc <= 0xFFFF) && + ((psc + 1) * pwmp->config->frequency) == pwmp->clock, + "pwm_lld_start(), #1", "invalid frequency"); + pwmp->tim->PSC = (uint16_t)psc; + pwmp->tim->ARR = (uint16_t)(pwmp->period - 1); + pwmp->tim->CR2 = pwmp->config->cr2; + + /* Output enables and polarities setup.*/ + ccer = 0; + switch (pwmp->config->channels[0].mode & PWM_OUTPUT_MASK) { + case PWM_OUTPUT_ACTIVE_LOW: + ccer |= STM32_TIM_CCER_CC1P; + case PWM_OUTPUT_ACTIVE_HIGH: + ccer |= STM32_TIM_CCER_CC1E; + default: + ; + } + switch (pwmp->config->channels[1].mode & PWM_OUTPUT_MASK) { + case PWM_OUTPUT_ACTIVE_LOW: + ccer |= STM32_TIM_CCER_CC2P; + case PWM_OUTPUT_ACTIVE_HIGH: + ccer |= STM32_TIM_CCER_CC2E; + default: + ; + } + switch (pwmp->config->channels[2].mode & PWM_OUTPUT_MASK) { + case PWM_OUTPUT_ACTIVE_LOW: + ccer |= STM32_TIM_CCER_CC3P; + case PWM_OUTPUT_ACTIVE_HIGH: + ccer |= STM32_TIM_CCER_CC3E; + default: + ; + } + switch (pwmp->config->channels[3].mode & PWM_OUTPUT_MASK) { + case PWM_OUTPUT_ACTIVE_LOW: + ccer |= STM32_TIM_CCER_CC4P; + case PWM_OUTPUT_ACTIVE_HIGH: + ccer |= STM32_TIM_CCER_CC4E; + default: + ; + } +#if STM32_PWM_USE_ADVANCED +#if STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM8 + if (&PWMD1 == pwmp) { +#endif +#if !STM32_PWM_USE_TIM1 && STM32_PWM_USE_TIM8 + if (&PWMD8 == pwmp) { +#endif +#if STM32_PWM_USE_TIM1 && STM32_PWM_USE_TIM8 + if ((&PWMD1 == pwmp) || (&PWMD8 == pwmp)) { +#endif + switch (pwmp->config->channels[0].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) { + case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW: + ccer |= STM32_TIM_CCER_CC1NP; + case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH: + ccer |= STM32_TIM_CCER_CC1NE; + default: + ; + } + switch (pwmp->config->channels[1].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) { + case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW: + ccer |= STM32_TIM_CCER_CC2NP; + case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH: + ccer |= STM32_TIM_CCER_CC2NE; + default: + ; + } + switch (pwmp->config->channels[2].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) { + case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW: + ccer |= STM32_TIM_CCER_CC3NP; + case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH: + ccer |= STM32_TIM_CCER_CC3NE; + default: + ; + } + } +#endif /* STM32_PWM_USE_ADVANCED*/ + + pwmp->tim->CCER = ccer; + pwmp->tim->EGR = STM32_TIM_EGR_UG; /* Update event. */ + pwmp->tim->DIER = pwmp->config->callback == NULL ? 0 : STM32_TIM_DIER_UIE; + pwmp->tim->SR = 0; /* Clear pending IRQs. */ +#if STM32_PWM_USE_TIM1 || STM32_PWM_USE_TIM8 +#if STM32_PWM_USE_ADVANCED + pwmp->tim->BDTR = pwmp->config->bdtr | STM32_TIM_BDTR_MOE; +#else + pwmp->tim->BDTR = STM32_TIM_BDTR_MOE; +#endif +#endif + /* Timer configured and started.*/ + pwmp->tim->CR1 = STM32_TIM_CR1_ARPE | STM32_TIM_CR1_URS | STM32_TIM_CR1_CEN; +} + +/** + * @brief Deactivates the PWM peripheral. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * + * @notapi + */ +void pwm_lld_stop(PWMDriver *pwmp) { + + /* If in ready state then disables the PWM clock.*/ + if (pwmp->state == PWM_READY) { + pwmp->tim->CR1 = 0; /* Timer disabled. */ + pwmp->tim->DIER = 0; /* All IRQs disabled. */ + pwmp->tim->SR = 0; /* Clear eventual pending IRQs. */ +#if STM32_PWM_USE_TIM1 || STM32_PWM_USE_TIM8 + pwmp->tim->BDTR = 0; +#endif + +#if STM32_PWM_USE_TIM1 + if (&PWMD1 == pwmp) { + nvicDisableVector(STM32_TIM1_UP_NUMBER); + nvicDisableVector(STM32_TIM1_CC_NUMBER); + rccDisableTIM1(FALSE); + } +#endif +#if STM32_PWM_USE_TIM2 + if (&PWMD2 == pwmp) { + nvicDisableVector(STM32_TIM2_NUMBER); + rccDisableTIM2(FALSE); + } +#endif +#if STM32_PWM_USE_TIM3 + if (&PWMD3 == pwmp) { + nvicDisableVector(STM32_TIM3_NUMBER); + rccDisableTIM3(FALSE); + } +#endif +#if STM32_PWM_USE_TIM4 + if (&PWMD4 == pwmp) { + nvicDisableVector(STM32_TIM4_NUMBER); + rccDisableTIM4(FALSE); + } +#endif +#if STM32_PWM_USE_TIM5 + if (&PWMD5 == pwmp) { + nvicDisableVector(STM32_TIM5_NUMBER); + rccDisableTIM5(FALSE); + } +#endif +#if STM32_PWM_USE_TIM8 + if (&PWMD8 == pwmp) { + nvicDisableVector(STM32_TIM8_UP_NUMBER); + nvicDisableVector(STM32_TIM8_CC_NUMBER); + rccDisableTIM8(FALSE); + } +#endif +#if STM32_PWM_USE_TIM9 + if (&PWMD9 == pwmp) { + nvicDisableVector(STM32_TIM9_NUMBER); + rccDisableTIM9(FALSE); + } +#endif + } +} + +/** + * @brief Enables a PWM channel. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @post The channel is active using the specified configuration. + * @note The function has effect at the next cycle start. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1) + * @param[in] width PWM pulse width as clock pulses number + * + * @notapi + */ +void pwm_lld_enable_channel(PWMDriver *pwmp, + pwmchannel_t channel, + pwmcnt_t width) { + + pwmp->tim->CCR[channel] = width; /* New duty cycle. */ + /* If there is a callback defined for the channel then the associated + interrupt must be enabled.*/ + if (pwmp->config->channels[channel].callback != NULL) { + uint32_t dier = pwmp->tim->DIER; + /* If the IRQ is not already enabled care must be taken to clear it, + it is probably already pending because the timer is running.*/ + if ((dier & (2 << channel)) == 0) { + pwmp->tim->DIER = dier | (2 << channel); + pwmp->tim->SR = ~(2 << channel); + } + } +} + +/** + * @brief Disables a PWM channel. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @post The channel is disabled and its output line returned to the + * idle state. + * @note The function has effect at the next cycle start. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1) + * + * @notapi + */ +void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel) { + + pwmp->tim->CCR[channel] = 0; + pwmp->tim->DIER &= ~(2 << channel); +} + +#endif /* HAL_USE_PWM */ + +/** @} */ diff --git a/os/hal/platforms/STM32/TIMv1/pwm_lld.h b/os/hal/platforms/STM32/TIMv1/pwm_lld.h new file mode 100644 index 000000000..0ef6abbca --- /dev/null +++ b/os/hal/platforms/STM32/TIMv1/pwm_lld.h @@ -0,0 +1,474 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file STM32/pwm_lld.h + * @brief STM32 PWM subsystem low level driver header. + * + * @addtogroup PWM + * @{ + */ + +#ifndef _PWM_LLD_H_ +#define _PWM_LLD_H_ + +#include "stm32_tim.h" + +#if HAL_USE_PWM || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Number of PWM channels per PWM driver. + */ +#define PWM_CHANNELS 4 + +/** + * @brief Complementary output modes mask. + * @note This is an STM32-specific setting. + */ +#define PWM_COMPLEMENTARY_OUTPUT_MASK 0xF0 + +/** + * @brief Complementary output not driven. + * @note This is an STM32-specific setting. + */ +#define PWM_COMPLEMENTARY_OUTPUT_DISABLED 0x00 + +/** + * @brief Complementary output, active is logic level one. + * @note This is an STM32-specific setting. + * @note This setting is only available if the configuration option + * @p STM32_PWM_USE_ADVANCED is set to TRUE and only for advanced + * timers TIM1 and TIM8. + */ +#define PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH 0x10 + +/** + * @brief Complementary output, active is logic level zero. + * @note This is an STM32-specific setting. + * @note This setting is only available if the configuration option + * @p STM32_PWM_USE_ADVANCED is set to TRUE and only for advanced + * timers TIM1 and TIM8. + */ +#define PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW 0x20 + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief If advanced timer features switch. + * @details If set to @p TRUE the advanced features for TIM1 and TIM8 are + * enabled. + * @note The default is @p TRUE. + */ +#if !defined(STM32_PWM_USE_ADVANCED) || defined(__DOXYGEN__) +#define STM32_PWM_USE_ADVANCED FALSE +#endif + +/** + * @brief PWMD1 driver enable switch. + * @details If set to @p TRUE the support for PWMD1 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_PWM_USE_TIM1) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM1 FALSE +#endif + +/** + * @brief PWMD2 driver enable switch. + * @details If set to @p TRUE the support for PWMD2 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_PWM_USE_TIM2) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM2 FALSE +#endif + +/** + * @brief PWMD3 driver enable switch. + * @details If set to @p TRUE the support for PWMD3 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_PWM_USE_TIM3) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM3 FALSE +#endif + +/** + * @brief PWMD4 driver enable switch. + * @details If set to @p TRUE the support for PWMD4 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_PWM_USE_TIM4) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM4 FALSE +#endif + +/** + * @brief PWMD5 driver enable switch. + * @details If set to @p TRUE the support for PWMD5 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_PWM_USE_TIM5) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM5 FALSE +#endif + +/** + * @brief PWMD8 driver enable switch. + * @details If set to @p TRUE the support for PWMD8 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_PWM_USE_TIM8) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM8 FALSE +#endif + +/** + * @brief PWMD9 driver enable switch. + * @details If set to @p TRUE the support for PWMD9 is included. + * @note The default is @p TRUE. + */ +#if !defined(STM32_PWM_USE_TIM9) || defined(__DOXYGEN__) +#define STM32_PWM_USE_TIM9 FALSE +#endif + +/** + * @brief PWMD1 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#endif + +/** + * @brief PWMD2 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#endif + +/** + * @brief PWMD3 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#endif + +/** + * @brief PWMD4 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#endif + +/** + * @brief PWMD5 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM5_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#endif + +/** + * @brief PWMD8 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM8_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#endif +/** @} */ + +/** + * @brief PWMD9 interrupt priority level setting. + */ +#if !defined(STM32_PWM_TIM9_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 +#endif +/** @} */ + +/*===========================================================================*/ +/* Configuration checks. */ +/*===========================================================================*/ + +#if STM32_PWM_USE_TIM1 && !STM32_HAS_TIM1 +#error "TIM1 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM2 && !STM32_HAS_TIM2 +#error "TIM2 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM3 && !STM32_HAS_TIM3 +#error "TIM3 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM4 && !STM32_HAS_TIM4 +#error "TIM4 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM5 && !STM32_HAS_TIM5 +#error "TIM5 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM8 && !STM32_HAS_TIM8 +#error "TIM8 not present in the selected device" +#endif + +#if STM32_PWM_USE_TIM9 && !STM32_HAS_TIM9 +#error "TIM9 not present in the selected device" +#endif + +#if !STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM2 && \ + !STM32_PWM_USE_TIM3 && !STM32_PWM_USE_TIM4 && \ + !STM32_PWM_USE_TIM5 && !STM32_PWM_USE_TIM8 && \ + !STM32_PWM_USE_TIM9 +#error "PWM driver activated but no TIM peripheral assigned" +#endif + +#if STM32_PWM_USE_ADVANCED && !STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM8 +#error "advanced mode selected but no advanced timer assigned" +#endif + +#if STM32_PWM_USE_TIM1 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM1" +#endif + +#if STM32_PWM_USE_TIM2 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM2" +#endif + +#if STM32_PWM_USE_TIM3 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM3" +#endif + +#if STM32_PWM_USE_TIM4 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM4_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM4" +#endif + +#if STM32_PWM_USE_TIM5 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM5_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM5" +#endif + +#if STM32_PWM_USE_TIM8 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM8_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM8" +#endif + +#if STM32_PWM_USE_TIM9 && \ + !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM9_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM9" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief PWM mode type. + */ +typedef uint32_t pwmmode_t; + +/** + * @brief PWM channel type. + */ +typedef uint8_t pwmchannel_t; + +/** + * @brief PWM counter type. + */ +typedef uint16_t pwmcnt_t; + +/** + * @brief PWM driver channel configuration structure. + */ +typedef struct { + /** + * @brief Channel active logic level. + */ + pwmmode_t mode; + /** + * @brief Channel callback pointer. + * @note This callback is invoked on the channel compare event. If set to + * @p NULL then the callback is disabled. + */ + pwmcallback_t callback; + /* End of the mandatory fields.*/ +} PWMChannelConfig; + +/** + * @brief PWM driver configuration structure. + */ +typedef struct { + /** + * @brief Timer clock in Hz. + * @note The low level can use assertions in order to catch invalid + * frequency specifications. + */ + uint32_t frequency; + /** + * @brief PWM period in ticks. + * @note The low level can use assertions in order to catch invalid + * period specifications. + */ + pwmcnt_t period; + /** + * @brief Periodic callback pointer. + * @note This callback is invoked on PWM counter reset. If set to + * @p NULL then the callback is disabled. + */ + pwmcallback_t callback; + /** + * @brief Channels configurations. + */ + PWMChannelConfig channels[PWM_CHANNELS]; + /* End of the mandatory fields.*/ + /** + * @brief TIM CR2 register initialization data. + * @note The value of this field should normally be equal to zero. + */ + uint16_t cr2; +#if STM32_PWM_USE_ADVANCED || defined(__DOXYGEN__) + /** + * @brief TIM BDTR (break & dead-time) register initialization data. + * @note The value of this field should normally be equal to zero. + */ \ + uint16_t bdtr; +#endif +} PWMConfig; + +/** + * @brief Structure representing a PWM driver. + */ +struct PWMDriver { + /** + * @brief Driver state. + */ + pwmstate_t state; + /** + * @brief Current driver configuration data. + */ + const PWMConfig *config; + /** + * @brief Current PWM period in ticks. + */ + pwmcnt_t period; +#if defined(PWM_DRIVER_EXT_FIELDS) + PWM_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Timer base clock. + */ + uint32_t clock; + /** + * @brief Pointer to the TIMx registers block. + */ + stm32_tim_t *tim; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Changes the period the PWM peripheral. + * @details This function changes the period of a PWM unit that has already + * been activated using @p pwmStart(). + * @pre The PWM unit must have been activated using @p pwmStart(). + * @post The PWM unit period is changed to the new value. + * @note The function has effect at the next cycle start. + * @note If a period is specified that is shorter than the pulse width + * programmed in one of the channels then the behavior is not + * guaranteed. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] period new cycle time in ticks + * + * @notapi + */ +#define pwm_lld_change_period(pwmp, period) \ + ((pwmp)->tim->ARR = (uint16_t)((period) - 1)) + +/** + * @brief Returns a PWM channel status. + * @pre The PWM unit must have been activated using @p pwmStart(). + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1) + * + * @notapi + */ +#define pwm_lld_is_channel_enabled(pwmp, channel) \ + (((pwmp)->tim->CCR[channel] != 0) || \ + (((pwmp)->tim->DIER & (2 << channel)) != 0)) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_PWM_USE_TIM1 && !defined(__DOXYGEN__) +extern PWMDriver PWMD1; +#endif + +#if STM32_PWM_USE_TIM2 && !defined(__DOXYGEN__) +extern PWMDriver PWMD2; +#endif + +#if STM32_PWM_USE_TIM3 && !defined(__DOXYGEN__) +extern PWMDriver PWMD3; +#endif + +#if STM32_PWM_USE_TIM4 && !defined(__DOXYGEN__) +extern PWMDriver PWMD4; +#endif + +#if STM32_PWM_USE_TIM5 && !defined(__DOXYGEN__) +extern PWMDriver PWMD5; +#endif + +#if STM32_PWM_USE_TIM8 && !defined(__DOXYGEN__) +extern PWMDriver PWMD8; +#endif + +#if STM32_PWM_USE_TIM9 && !defined(__DOXYGEN__) +extern PWMDriver PWMD9; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void pwm_lld_init(void); + void pwm_lld_start(PWMDriver *pwmp); + void pwm_lld_stop(PWMDriver *pwmp); + void pwm_lld_enable_channel(PWMDriver *pwmp, + pwmchannel_t channel, + pwmcnt_t width); + void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_PWM */ + +#endif /* _PWM_LLD_H_ */ + +/** @} */ diff --git a/os/hal/platforms/STM32/gpt_lld.c b/os/hal/platforms/STM32/gpt_lld.c deleted file mode 100644 index 35268fbe5..000000000 --- a/os/hal/platforms/STM32/gpt_lld.c +++ /dev/null @@ -1,762 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/gpt_lld.c - * @brief STM32 GPT subsystem low level driver source. - * - * @addtogroup GPT - * @{ - */ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_GPT || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief GPTD1 driver identifier. - * @note The driver GPTD1 allocates the complex timer TIM1 when enabled. - */ -#if STM32_GPT_USE_TIM1 || defined(__DOXYGEN__) -GPTDriver GPTD1; -#endif - -/** - * @brief GPTD2 driver identifier. - * @note The driver GPTD2 allocates the timer TIM2 when enabled. - */ -#if STM32_GPT_USE_TIM2 || defined(__DOXYGEN__) -GPTDriver GPTD2; -#endif - -/** - * @brief GPTD3 driver identifier. - * @note The driver GPTD3 allocates the timer TIM3 when enabled. - */ -#if STM32_GPT_USE_TIM3 || defined(__DOXYGEN__) -GPTDriver GPTD3; -#endif - -/** - * @brief GPTD4 driver identifier. - * @note The driver GPTD4 allocates the timer TIM4 when enabled. - */ -#if STM32_GPT_USE_TIM4 || defined(__DOXYGEN__) -GPTDriver GPTD4; -#endif - -/** - * @brief GPTD5 driver identifier. - * @note The driver GPTD5 allocates the timer TIM5 when enabled. - */ -#if STM32_GPT_USE_TIM5 || defined(__DOXYGEN__) -GPTDriver GPTD5; -#endif - -/** - * @brief GPTD6 driver identifier. - * @note The driver GPTD6 allocates the timer TIM6 when enabled. - */ -#if STM32_GPT_USE_TIM6 || defined(__DOXYGEN__) -GPTDriver GPTD6; -#endif - -/** - * @brief GPTD7 driver identifier. - * @note The driver GPTD7 allocates the timer TIM7 when enabled. - */ -#if STM32_GPT_USE_TIM7 || defined(__DOXYGEN__) -GPTDriver GPTD7; -#endif - -/** - * @brief GPTD8 driver identifier. - * @note The driver GPTD8 allocates the timer TIM8 when enabled. - */ -#if STM32_GPT_USE_TIM8 || defined(__DOXYGEN__) -GPTDriver GPTD8; -#endif - -/** - * @brief GPTD9 driver identifier. - * @note The driver GPTD9 allocates the timer TIM9 when enabled. - */ -#if STM32_GPT_USE_TIM9 || defined(__DOXYGEN__) -GPTDriver GPTD9; -#endif - -/** - * @brief GPTD11 driver identifier. - * @note The driver GPTD11 allocates the timer TIM11 when enabled. - */ -#if STM32_GPT_USE_TIM11 || defined(__DOXYGEN__) -GPTDriver GPTD11; -#endif - -/** - * @brief GPTD12 driver identifier. - * @note The driver GPTD12 allocates the timer TIM12 when enabled. - */ -#if STM32_GPT_USE_TIM12 || defined(__DOXYGEN__) -GPTDriver GPTD12; -#endif - -/** - * @brief GPTD14 driver identifier. - * @note The driver GPTD14 allocates the timer TIM14 when enabled. - */ -#if STM32_GPT_USE_TIM14 || defined(__DOXYGEN__) -GPTDriver GPTD14; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Shared IRQ handler. - * - * @param[in] gptp pointer to a @p GPTDriver object - */ -static void gpt_lld_serve_interrupt(GPTDriver *gptp) { - - gptp->tim->SR = 0; - if (gptp->state == GPT_ONESHOT) { - gptp->state = GPT_READY; /* Back in GPT_READY state. */ - gpt_lld_stop_timer(gptp); /* Timer automatically stopped. */ - } - gptp->config->callback(gptp); -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_GPT_USE_TIM1 -#if !defined(STM32_TIM1_UP_HANDLER) -#error "STM32_TIM1_UP_HANDLER not defined" -#endif -/** - * @brief TIM2 interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) { - - CH_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD1); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_GPT_USE_TIM1 */ - -#if STM32_GPT_USE_TIM2 -#if !defined(STM32_TIM2_HANDLER) -#error "STM32_TIM2_HANDLER not defined" -#endif -/** - * @brief TIM2 interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM2_HANDLER) { - - CH_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD2); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_GPT_USE_TIM2 */ - -#if STM32_GPT_USE_TIM3 -#if !defined(STM32_TIM3_HANDLER) -#error "STM32_TIM3_HANDLER not defined" -#endif -/** - * @brief TIM3 interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM3_HANDLER) { - - CH_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD3); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_GPT_USE_TIM3 */ - -#if STM32_GPT_USE_TIM4 -#if !defined(STM32_TIM4_HANDLER) -#error "STM32_TIM4_HANDLER not defined" -#endif -/** - * @brief TIM4 interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM4_HANDLER) { - - CH_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD4); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_GPT_USE_TIM4 */ - -#if STM32_GPT_USE_TIM5 -#if !defined(STM32_TIM5_HANDLER) -#error "STM32_TIM5_HANDLER not defined" -#endif -/** - * @brief TIM5 interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM5_HANDLER) { - - CH_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD5); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_GPT_USE_TIM5 */ - -#if STM32_GPT_USE_TIM6 -#if !defined(STM32_TIM6_HANDLER) -#error "STM32_TIM6_HANDLER not defined" -#endif -/** - * @brief TIM6 interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM6_HANDLER) { - - CH_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD6); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_GPT_USE_TIM6 */ - -#if STM32_GPT_USE_TIM7 -#if !defined(STM32_TIM7_HANDLER) -#error "STM32_TIM7_HANDLER not defined" -#endif -/** - * @brief TIM7 interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM7_HANDLER) { - - CH_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD7); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_GPT_USE_TIM7 */ - -#if STM32_GPT_USE_TIM8 -#if !defined(STM32_TIM8_UP_HANDLER) -#error "STM32_TIM8_UP_HANDLER not defined" -#endif -/** - * @brief TIM8 interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) { - - CH_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD8); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_GPT_USE_TIM8 */ - -#if STM32_GPT_USE_TIM9 -#if !defined(STM32_TIM9_HANDLER) -#error "STM32_TIM9_HANDLER not defined" -#endif -/** - * @brief TIM9 interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM9_HANDLER) { - - CH_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD9); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_GPT_USE_TIM9 */ - -#if STM32_GPT_USE_TIM11 -#if !defined(STM32_TIM11_HANDLER) -#error "STM32_TIM11_HANDLER not defined" -#endif -/** - * @brief TIM11 interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM11_HANDLER) { - - CH_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD11); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_GPT_USE_TIM11 */ - -#if STM32_GPT_USE_TIM12 -#if !defined(STM32_TIM12_HANDLER) -#error "STM32_TIM12_HANDLER not defined" -#endif -/** - * @brief TIM12 interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM12_HANDLER) { - - CH_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD12); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_GPT_USE_TIM12 */ - -#if STM32_GPT_USE_TIM14 -#if !defined(STM32_TIM14_HANDLER) -#error "STM32_TIM14_HANDLER not defined" -#endif -/** - * @brief TIM14 interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM14_HANDLER) { - - CH_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD14); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_GPT_USE_TIM14 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level GPT driver initialization. - * - * @notapi - */ -void gpt_lld_init(void) { - -#if STM32_GPT_USE_TIM1 - /* Driver initialization.*/ - GPTD1.tim = STM32_TIM1; - gptObjectInit(&GPTD1); -#endif - -#if STM32_GPT_USE_TIM2 - /* Driver initialization.*/ - GPTD2.tim = STM32_TIM2; - gptObjectInit(&GPTD2); -#endif - -#if STM32_GPT_USE_TIM3 - /* Driver initialization.*/ - GPTD3.tim = STM32_TIM3; - gptObjectInit(&GPTD3); -#endif - -#if STM32_GPT_USE_TIM4 - /* Driver initialization.*/ - GPTD4.tim = STM32_TIM4; - gptObjectInit(&GPTD4); -#endif - -#if STM32_GPT_USE_TIM5 - /* Driver initialization.*/ - GPTD5.tim = STM32_TIM5; - gptObjectInit(&GPTD5); -#endif - -#if STM32_GPT_USE_TIM6 - /* Driver initialization.*/ - GPTD6.tim = STM32_TIM6; - gptObjectInit(&GPTD6); -#endif - -#if STM32_GPT_USE_TIM7 - /* Driver initialization.*/ - GPTD7.tim = STM32_TIM7; - gptObjectInit(&GPTD7); -#endif - -#if STM32_GPT_USE_TIM8 - /* Driver initialization.*/ - GPTD8.tim = STM32_TIM8; - gptObjectInit(&GPTD8); -#endif - -#if STM32_GPT_USE_TIM9 - /* Driver initialization.*/ - GPTD9.tim = STM32_TIM9; - gptObjectInit(&GPTD9); -#endif - -#if STM32_GPT_USE_TIM11 - /* Driver initialization.*/ - GPTD11.tim = STM32_TIM11; - gptObjectInit(&GPTD11); -#endif - -#if STM32_GPT_USE_TIM12 - /* Driver initialization.*/ - GPTD12.tim = STM32_TIM12; - gptObjectInit(&GPTD12); -#endif - -#if STM32_GPT_USE_TIM14 - /* Driver initialization.*/ - GPTD14.tim = STM32_TIM14; - gptObjectInit(&GPTD14); -#endif -} - -/** - * @brief Configures and activates the GPT peripheral. - * - * @param[in] gptp pointer to the @p GPTDriver object - * - * @notapi - */ -void gpt_lld_start(GPTDriver *gptp) { - uint16_t psc; - - if (gptp->state == GPT_STOP) { - /* Clock activation.*/ -#if STM32_GPT_USE_TIM1 - if (&GPTD1 == gptp) { - rccEnableTIM1(FALSE); - rccResetTIM1(); - nvicEnableVector(STM32_TIM1_UP_NUMBER, - CORTEX_PRIORITY_MASK(STM32_GPT_TIM1_IRQ_PRIORITY)); - gptp->clock = STM32_TIMCLK2; - } -#endif -#if STM32_GPT_USE_TIM2 - if (&GPTD2 == gptp) { - rccEnableTIM2(FALSE); - rccResetTIM2(); - nvicEnableVector(STM32_TIM2_NUMBER, - CORTEX_PRIORITY_MASK(STM32_GPT_TIM2_IRQ_PRIORITY)); - gptp->clock = STM32_TIMCLK1; - } -#endif -#if STM32_GPT_USE_TIM3 - if (&GPTD3 == gptp) { - rccEnableTIM3(FALSE); - rccResetTIM3(); - nvicEnableVector(STM32_TIM3_NUMBER, - CORTEX_PRIORITY_MASK(STM32_GPT_TIM3_IRQ_PRIORITY)); - gptp->clock = STM32_TIMCLK1; - } -#endif -#if STM32_GPT_USE_TIM4 - if (&GPTD4 == gptp) { - rccEnableTIM4(FALSE); - rccResetTIM4(); - nvicEnableVector(STM32_TIM4_NUMBER, - CORTEX_PRIORITY_MASK(STM32_GPT_TIM4_IRQ_PRIORITY)); - gptp->clock = STM32_TIMCLK1; - } -#endif - -#if STM32_GPT_USE_TIM5 - if (&GPTD5 == gptp) { - rccEnableTIM5(FALSE); - rccResetTIM5(); - nvicEnableVector(STM32_TIM5_NUMBER, - CORTEX_PRIORITY_MASK(STM32_GPT_TIM5_IRQ_PRIORITY)); - gptp->clock = STM32_TIMCLK1; - } -#endif - -#if STM32_GPT_USE_TIM6 - if (&GPTD6 == gptp) { - rccEnableTIM6(FALSE); - rccResetTIM6(); - nvicEnableVector(STM32_TIM6_NUMBER, - CORTEX_PRIORITY_MASK(STM32_GPT_TIM6_IRQ_PRIORITY)); - gptp->clock = STM32_TIMCLK1; - } -#endif - -#if STM32_GPT_USE_TIM7 - if (&GPTD7 == gptp) { - rccEnableTIM7(FALSE); - rccResetTIM7(); - nvicEnableVector(STM32_TIM7_NUMBER, - CORTEX_PRIORITY_MASK(STM32_GPT_TIM7_IRQ_PRIORITY)); - gptp->clock = STM32_TIMCLK1; - } -#endif - -#if STM32_GPT_USE_TIM8 - if (&GPTD8 == gptp) { - rccEnableTIM8(FALSE); - rccResetTIM8(); - nvicEnableVector(STM32_TIM8_UP_NUMBER, - CORTEX_PRIORITY_MASK(STM32_GPT_TIM8_IRQ_PRIORITY)); - gptp->clock = STM32_TIMCLK2; - } -#endif - -#if STM32_GPT_USE_TIM9 - if (&GPTD9 == gptp) { - rccEnableTIM9(FALSE); - rccResetTIM9(); - nvicEnableVector(STM32_TIM9_NUMBER, - CORTEX_PRIORITY_MASK(STM32_GPT_TIM9_IRQ_PRIORITY)); - gptp->clock = STM32_TIMCLK2; - } -#endif - -#if STM32_GPT_USE_TIM11 - if (&GPTD11 == gptp) { - rccEnableTIM11(FALSE); - rccResetTIM11(); - nvicEnableVector(STM32_TIM11_NUMBER, - CORTEX_PRIORITY_MASK(STM32_GPT_TIM11_IRQ_PRIORITY)); - gptp->clock = STM32_TIMCLK2; - } -#endif - -#if STM32_GPT_USE_TIM12 - if (&GPTD12 == gptp) { - rccEnableTIM12(FALSE); - rccResetTIM12(); - nvicEnableVector(STM32_TIM12_NUMBER, - CORTEX_PRIORITY_MASK(STM32_GPT_TIM12_IRQ_PRIORITY)); - gptp->clock = STM32_TIMCLK1; - } -#endif - -#if STM32_GPT_USE_TIM14 - if (&GPTD14 == gptp) { - rccEnableTIM14(FALSE); - rccResetTIM14(); - nvicEnableVector(STM32_TIM14_NUMBER, - CORTEX_PRIORITY_MASK(STM32_GPT_TIM14_IRQ_PRIORITY)); - gptp->clock = STM32_TIMCLK1; - } -#endif - } - - /* Prescaler value calculation.*/ - psc = (uint16_t)((gptp->clock / gptp->config->frequency) - 1); - chDbgAssert(((uint32_t)(psc + 1) * gptp->config->frequency) == gptp->clock, - "gpt_lld_start(), #1", "invalid frequency"); - - /* Timer configuration.*/ - gptp->tim->CR1 = 0; /* Initially stopped. */ - gptp->tim->CR2 = TIM_CR2_CCDS; /* DMA on UE (if any). */ - gptp->tim->PSC = psc; /* Prescaler value. */ - gptp->tim->DIER = 0; -} - -/** - * @brief Deactivates the GPT peripheral. - * - * @param[in] gptp pointer to the @p GPTDriver object - * - * @notapi - */ -void gpt_lld_stop(GPTDriver *gptp) { - - if (gptp->state == GPT_READY) { - gptp->tim->CR1 = 0; /* Timer disabled. */ - gptp->tim->DIER = 0; /* All IRQs disabled. */ - gptp->tim->SR = 0; /* Clear eventual pending IRQs. */ - -#if STM32_GPT_USE_TIM1 - if (&GPTD1 == gptp) { - nvicDisableVector(STM32_TIM1_UP_NUMBER); - rccDisableTIM1(FALSE); - } -#endif -#if STM32_GPT_USE_TIM2 - if (&GPTD2 == gptp) { - nvicDisableVector(STM32_TIM2_NUMBER); - rccDisableTIM2(FALSE); - } -#endif -#if STM32_GPT_USE_TIM3 - if (&GPTD3 == gptp) { - nvicDisableVector(STM32_TIM3_NUMBER); - rccDisableTIM3(FALSE); - } -#endif -#if STM32_GPT_USE_TIM4 - if (&GPTD4 == gptp) { - nvicDisableVector(STM32_TIM4_NUMBER); - rccDisableTIM4(FALSE); - } -#endif -#if STM32_GPT_USE_TIM5 - if (&GPTD5 == gptp) { - nvicDisableVector(STM32_TIM5_NUMBER); - rccDisableTIM5(FALSE); - } -#endif -#if STM32_GPT_USE_TIM6 - if (&GPTD6 == gptp) { - nvicDisableVector(STM32_TIM6_NUMBER); - rccDisableTIM6(FALSE); - } -#endif -#if STM32_GPT_USE_TIM7 - if (&GPTD7 == gptp) { - nvicDisableVector(STM32_TIM7_NUMBER); - rccDisableTIM7(FALSE); - } -#endif -#if STM32_GPT_USE_TIM8 - if (&GPTD8 == gptp) { - nvicDisableVector(STM32_TIM8_UP_NUMBER); - rccDisableTIM8(FALSE); - } -#endif -#if STM32_GPT_USE_TIM9 - if (&GPTD9 == gptp) { - nvicDisableVector(STM32_TIM9_NUMBER); - rccDisableTIM9(FALSE); - } -#endif -#if STM32_GPT_USE_TIM11 - if (&GPTD11 == gptp) { - nvicDisableVector(STM32_TIM11_NUMBER); - rccDisableTIM11(FALSE); - } -#endif -#if STM32_GPT_USE_TIM12 - if (&GPTD12 == gptp) { - nvicDisableVector(STM32_TIM12_NUMBER); - rccDisableTIM12(FALSE); - } -#endif -#if STM32_GPT_USE_TIM14 - if (&GPTD14 == gptp) { - nvicDisableVector(STM32_TIM14_NUMBER); - rccDisableTIM14(FALSE); - } -#endif - } -} - -/** - * @brief Starts the timer in continuous mode. - * - * @param[in] gptp pointer to the @p GPTDriver object - * @param[in] interval period in ticks - * - * @notapi - */ -void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t interval) { - - gptp->tim->ARR = interval - 1; /* Time constant. */ - gptp->tim->EGR = TIM_EGR_UG; /* Update event. */ - gptp->tim->CNT = 0; /* Reset counter. */ - /* NOTE: After generating the UG event it takes several clock cycles before - SR bit 0 goes to 1. This is because the clearing of CNT has been inserted - before the clearing of SR, to give it some time.*/ - gptp->tim->SR = 0; /* Clear pending IRQs (if any). */ - gptp->tim->DIER = TIM_DIER_UIE; /* Update Event IRQ enabled. */ - gptp->tim->CR1 = TIM_CR1_URS | TIM_CR1_CEN; -} - -/** - * @brief Stops the timer. - * - * @param[in] gptp pointer to the @p GPTDriver object - * - * @notapi - */ -void gpt_lld_stop_timer(GPTDriver *gptp) { - - gptp->tim->CR1 = 0; /* Initially stopped. */ - gptp->tim->SR = 0; /* Clear pending IRQs (if any). */ - gptp->tim->DIER = 0; /* Interrupts disabled. */ -} - -/** - * @brief Starts the timer in one shot mode and waits for completion. - * @details This function specifically polls the timer waiting for completion - * in order to not have extra delays caused by interrupt servicing, - * this function is only recommended for short delays. - * - * @param[in] gptp pointer to the @p GPTDriver object - * @param[in] interval time interval in ticks - * - * @notapi - */ -void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval) { - - gptp->tim->ARR = interval - 1; /* Time constant. */ - gptp->tim->EGR = TIM_EGR_UG; /* Update event. */ - gptp->tim->SR = 0; /* Clear pending IRQs (if any). */ - gptp->tim->CR1 = TIM_CR1_OPM | TIM_CR1_URS | TIM_CR1_CEN; - while (!(gptp->tim->SR & TIM_SR_UIF)) - ; -} - -#endif /* HAL_USE_GPT */ - -/** @} */ diff --git a/os/hal/platforms/STM32/gpt_lld.h b/os/hal/platforms/STM32/gpt_lld.h deleted file mode 100644 index ecb1dcb35..000000000 --- a/os/hal/platforms/STM32/gpt_lld.h +++ /dev/null @@ -1,504 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/gpt_lld.h - * @brief STM32 GPT subsystem low level driver header. - * - * @addtogroup GPT - * @{ - */ - -#ifndef _GPT_LLD_H_ -#define _GPT_LLD_H_ - -#if HAL_USE_GPT || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief GPTD1 driver enable switch. - * @details If set to @p TRUE the support for GPTD1 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_GPT_USE_TIM1) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM1 FALSE -#endif - -/** - * @brief GPTD2 driver enable switch. - * @details If set to @p TRUE the support for GPTD2 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_GPT_USE_TIM2) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM2 FALSE -#endif - -/** - * @brief GPTD3 driver enable switch. - * @details If set to @p TRUE the support for GPTD3 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_GPT_USE_TIM3) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM3 FALSE -#endif - -/** - * @brief GPTD4 driver enable switch. - * @details If set to @p TRUE the support for GPTD4 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_GPT_USE_TIM4) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM4 FALSE -#endif - -/** - * @brief GPTD5 driver enable switch. - * @details If set to @p TRUE the support for GPTD5 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_GPT_USE_TIM5) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM5 FALSE -#endif - -/** - * @brief GPTD6 driver enable switch. - * @details If set to @p TRUE the support for GPTD6 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_GPT_USE_TIM6) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM6 FALSE -#endif - -/** - * @brief GPTD7 driver enable switch. - * @details If set to @p TRUE the support for GPTD7 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_GPT_USE_TIM7) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM7 FALSE -#endif - -/** - * @brief GPTD8 driver enable switch. - * @details If set to @p TRUE the support for GPTD8 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_GPT_USE_TIM8) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM8 FALSE -#endif - -/** - * @brief GPTD9 driver enable switch. - * @details If set to @p TRUE the support for GPTD9 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_GPT_USE_TIM9) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM9 FALSE -#endif - -/** - * @brief GPTD11 driver enable switch. - * @details If set to @p TRUE the support for GPTD11 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_GPT_USE_TIM11) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM11 FALSE -#endif - -/** - * @brief GPTD12 driver enable switch. - * @details If set to @p TRUE the support for GPTD12 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_GPT_USE_TIM12) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM12 FALSE -#endif - -/** - * @brief GPTD14 driver enable switch. - * @details If set to @p TRUE the support for GPTD14 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_GPT_USE_TIM14) || defined(__DOXYGEN__) -#define STM32_GPT_USE_TIM14 FALSE -#endif - -/** - * @brief GPTD1 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM1_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD2 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM2_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD3 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM3_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD4 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM4_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD5 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM5_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM5_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD6 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM6_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM6_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD7 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM7_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM7_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD8 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM8_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM8_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD9 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM9_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM9_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD11 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM11_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM11_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD12 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM12_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM12_IRQ_PRIORITY 7 -#endif - -/** - * @brief GPTD14 interrupt priority level setting. - */ -#if !defined(STM32_GPT_TIM14_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_GPT_TIM14_IRQ_PRIORITY 7 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_GPT_USE_TIM1 && !STM32_HAS_TIM1 -#error "TIM1 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM2 && !STM32_HAS_TIM2 -#error "TIM2 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM3 && !STM32_HAS_TIM3 -#error "TIM3 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM4 && !STM32_HAS_TIM4 -#error "TIM4 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM5 && !STM32_HAS_TIM5 -#error "TIM5 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM6 && !STM32_HAS_TIM6 -#error "TIM6 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM7 && !STM32_HAS_TIM7 -#error "TIM7 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM8 && !STM32_HAS_TIM8 -#error "TIM8 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM9 && !STM32_HAS_TIM9 -#error "TIM9 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM11 && !STM32_HAS_TIM11 -#error "TIM11 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM12 && !STM32_HAS_TIM12 -#error "TIM12 not present in the selected device" -#endif - -#if STM32_GPT_USE_TIM14 && !STM32_HAS_TIM14 -#error "TIM14 not present in the selected device" -#endif - -#if !STM32_GPT_USE_TIM1 && !STM32_GPT_USE_TIM2 && \ - !STM32_GPT_USE_TIM3 && !STM32_GPT_USE_TIM4 && \ - !STM32_GPT_USE_TIM5 && !STM32_GPT_USE_TIM6 && \ - !STM32_GPT_USE_TIM7 && !STM32_GPT_USE_TIM8 && \ - !STM32_GPT_USE_TIM9 && !STM32_GPT_USE_TIM11 && \ - !STM32_GPT_USE_TIM12 && !STM32_GPT_USE_TIM14 -#error "GPT driver activated but no TIM peripheral assigned" -#endif - -#if STM32_GPT_USE_TIM1 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM1" -#endif - -#if STM32_GPT_USE_TIM2 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM2" -#endif - -#if STM32_GPT_USE_TIM3 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM3" -#endif - -#if STM32_GPT_USE_TIM4 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM4_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM4" -#endif - -#if STM32_GPT_USE_TIM5 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM5_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM5" -#endif - -#if STM32_GPT_USE_TIM6 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM6_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM6" -#endif - -#if STM32_GPT_USE_TIM7 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM7_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM7" -#endif - -#if STM32_GPT_USE_TIM8 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM8_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM8" -#endif - -#if STM32_GPT_USE_TIM9 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM9_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM9" -#endif - -#if STM32_GPT_USE_TIM11 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM11_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM11" -#endif - -#if STM32_GPT_USE_TIM12 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM12_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM12" -#endif - -#if STM32_GPT_USE_TIM14 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_GPT_TIM14_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM14" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief GPT frequency type. - */ -typedef uint32_t gptfreq_t; - -/** - * @brief GPT counter type. - */ -typedef uint16_t gptcnt_t; - -/** - * @brief Driver configuration structure. - * @note It could be empty on some architectures. - */ -typedef struct { - /** - * @brief Timer clock in Hz. - * @note The low level can use assertions in order to catch invalid - * frequency specifications. - */ - gptfreq_t frequency; - /** - * @brief Timer callback pointer. - * @note This callback is invoked on GPT counter events. - */ - gptcallback_t callback; - /* End of the mandatory fields.*/ -} GPTConfig; - -/** - * @brief Structure representing a GPT driver. - */ -struct GPTDriver { - /** - * @brief Driver state. - */ - gptstate_t state; - /** - * @brief Current configuration data. - */ - const GPTConfig *config; -#if defined(GPT_DRIVER_EXT_FIELDS) - GPT_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Timer base clock. - */ - uint32_t clock; - /** - * @brief Pointer to the TIMx registers block. - */ - stm32_tim_t *tim; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Changes the interval of GPT peripheral. - * @details This function changes the interval of a running GPT unit. - * @pre The GPT unit must have been activated using @p gptStart(). - * @pre The GPT unit must have been running in continuous mode using - * @p gptStartContinuous(). - * @post The GPT unit interval is changed to the new value. - * @note The function has effect at the next cycle start. - * - * @param[in] gptp pointer to a @p GPTDriver object - * @param[in] interval new cycle time in timer ticks - * @notapi - */ -#define gpt_lld_change_interval(gptp, interval) \ - ((gptp)->tim->ARR = (uint16_t)((interval) - 1)) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_GPT_USE_TIM1 && !defined(__DOXYGEN__) -extern GPTDriver GPTD1; -#endif - -#if STM32_GPT_USE_TIM2 && !defined(__DOXYGEN__) -extern GPTDriver GPTD2; -#endif - -#if STM32_GPT_USE_TIM3 && !defined(__DOXYGEN__) -extern GPTDriver GPTD3; -#endif - -#if STM32_GPT_USE_TIM4 && !defined(__DOXYGEN__) -extern GPTDriver GPTD4; -#endif - -#if STM32_GPT_USE_TIM5 && !defined(__DOXYGEN__) -extern GPTDriver GPTD5; -#endif - -#if STM32_GPT_USE_TIM6 && !defined(__DOXYGEN__) -extern GPTDriver GPTD6; -#endif - -#if STM32_GPT_USE_TIM7 && !defined(__DOXYGEN__) -extern GPTDriver GPTD7; -#endif - -#if STM32_GPT_USE_TIM8 && !defined(__DOXYGEN__) -extern GPTDriver GPTD8; -#endif - -#if STM32_GPT_USE_TIM9 && !defined(__DOXYGEN__) -extern GPTDriver GPTD9; -#endif - -#if STM32_GPT_USE_TIM11 && !defined(__DOXYGEN__) -extern GPTDriver GPTD11; -#endif - -#if STM32_GPT_USE_TIM12 && !defined(__DOXYGEN__) -extern GPTDriver GPTD12; -#endif - -#if STM32_GPT_USE_TIM14 && !defined(__DOXYGEN__) -extern GPTDriver GPTD14; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void gpt_lld_init(void); - void gpt_lld_start(GPTDriver *gptp); - void gpt_lld_stop(GPTDriver *gptp); - void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t period); - void gpt_lld_stop_timer(GPTDriver *gptp); - void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_GPT */ - -#endif /* _GPT_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/icu_lld.c b/os/hal/platforms/STM32/icu_lld.c deleted file mode 100644 index ad838d903..000000000 --- a/os/hal/platforms/STM32/icu_lld.c +++ /dev/null @@ -1,641 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Fabio Utzig and - Xo Wang. - */ - -/** - * @file STM32/icu_lld.c - * @brief STM32 ICU subsystem low level driver header. - * - * @addtogroup ICU - * @{ - */ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_ICU || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief ICUD1 driver identifier. - * @note The driver ICUD1 allocates the complex timer TIM1 when enabled. - */ -#if STM32_ICU_USE_TIM1 || defined(__DOXYGEN__) -ICUDriver ICUD1; -#endif - -/** - * @brief ICUD2 driver identifier. - * @note The driver ICUD1 allocates the timer TIM2 when enabled. - */ -#if STM32_ICU_USE_TIM2 || defined(__DOXYGEN__) -ICUDriver ICUD2; -#endif - -/** - * @brief ICUD3 driver identifier. - * @note The driver ICUD1 allocates the timer TIM3 when enabled. - */ -#if STM32_ICU_USE_TIM3 || defined(__DOXYGEN__) -ICUDriver ICUD3; -#endif - -/** - * @brief ICUD4 driver identifier. - * @note The driver ICUD4 allocates the timer TIM4 when enabled. - */ -#if STM32_ICU_USE_TIM4 || defined(__DOXYGEN__) -ICUDriver ICUD4; -#endif - -/** - * @brief ICUD5 driver identifier. - * @note The driver ICUD5 allocates the timer TIM5 when enabled. - */ -#if STM32_ICU_USE_TIM5 || defined(__DOXYGEN__) -ICUDriver ICUD5; -#endif - -/** - * @brief ICUD8 driver identifier. - * @note The driver ICUD8 allocates the timer TIM8 when enabled. - */ -#if STM32_ICU_USE_TIM8 || defined(__DOXYGEN__) -ICUDriver ICUD8; -#endif - -/** - * @brief ICUD9 driver identifier. - * @note The driver ICUD9 allocates the timer TIM9 when enabled. - */ -#if STM32_ICU_USE_TIM9 || defined(__DOXYGEN__) -ICUDriver ICUD9; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Shared IRQ handler. - * - * @param[in] icup pointer to the @p ICUDriver object - */ -static void icu_lld_serve_interrupt(ICUDriver *icup) { - uint16_t sr; - - sr = icup->tim->SR; - sr &= icup->tim->DIER; - icup->tim->SR = ~sr; - if (icup->config->channel == ICU_CHANNEL_1) { - if ((sr & STM32_TIM_SR_CC1IF) != 0) - _icu_isr_invoke_period_cb(icup); - if ((sr & STM32_TIM_SR_CC2IF) != 0) - _icu_isr_invoke_width_cb(icup); - } else { - if ((sr & STM32_TIM_SR_CC1IF) != 0) - _icu_isr_invoke_width_cb(icup); - if ((sr & STM32_TIM_SR_CC2IF) != 0) - _icu_isr_invoke_period_cb(icup); - } - if ((sr & STM32_TIM_SR_UIF) != 0) - _icu_isr_invoke_overflow_cb(icup); -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_ICU_USE_TIM1 -#if !defined(STM32_TIM1_UP_HANDLER) -#error "STM32_TIM1_UP_HANDLER not defined" -#endif -/** - * @brief TIM1 compare interrupt handler. - * @note It is assumed that the various sources are only activated if the - * associated callback pointer is not equal to @p NULL in order to not - * perform an extra check in a potentially critical interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) { - - CH_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD1); - - CH_IRQ_EPILOGUE(); -} - -#if !defined(STM32_TIM1_CC_HANDLER) -#error "STM32_TIM1_CC_HANDLER not defined" -#endif -/** - * @brief TIM1 compare interrupt handler. - * @note It is assumed that the various sources are only activated if the - * associated callback pointer is not equal to @p NULL in order to not - * perform an extra check in a potentially critical interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM1_CC_HANDLER) { - - CH_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD1); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_ICU_USE_TIM1 */ - -#if STM32_ICU_USE_TIM2 -#if !defined(STM32_TIM2_HANDLER) -#error "STM32_TIM2_HANDLER not defined" -#endif -/** - * @brief TIM2 interrupt handler. - * @note It is assumed that the various sources are only activated if the - * associated callback pointer is not equal to @p NULL in order to not - * perform an extra check in a potentially critical interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM2_HANDLER) { - - CH_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD2); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_ICU_USE_TIM2 */ - -#if STM32_ICU_USE_TIM3 -#if !defined(STM32_TIM3_HANDLER) -#error "STM32_TIM3_HANDLER not defined" -#endif -/** - * @brief TIM3 interrupt handler. - * @note It is assumed that the various sources are only activated if the - * associated callback pointer is not equal to @p NULL in order to not - * perform an extra check in a potentially critical interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM3_HANDLER) { - - CH_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD3); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_ICU_USE_TIM3 */ - -#if STM32_ICU_USE_TIM4 -#if !defined(STM32_TIM4_HANDLER) -#error "STM32_TIM4_HANDLER not defined" -#endif -/** - * @brief TIM4 interrupt handler. - * @note It is assumed that the various sources are only activated if the - * associated callback pointer is not equal to @p NULL in order to not - * perform an extra check in a potentially critical interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM4_HANDLER) { - - CH_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD4); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_ICU_USE_TIM4 */ - -#if STM32_ICU_USE_TIM5 -#if !defined(STM32_TIM5_HANDLER) -#error "STM32_TIM5_HANDLER not defined" -#endif -/** - * @brief TIM5 interrupt handler. - * @note It is assumed that the various sources are only activated if the - * associated callback pointer is not equal to @p NULL in order to not - * perform an extra check in a potentially critical interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM5_HANDLER) { - - CH_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD5); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_ICU_USE_TIM5 */ - -#if STM32_ICU_USE_TIM8 -#if !defined(STM32_TIM8_UP_HANDLER) -#error "STM32_TIM8_UP_HANDLER not defined" -#endif -/** - * @brief TIM8 compare interrupt handler. - * @note It is assumed that the various sources are only activated if the - * associated callback pointer is not equal to @p NULL in order to not - * perform an extra check in a potentially critical interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) { - - CH_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD8); - - CH_IRQ_EPILOGUE(); -} - -#if !defined(STM32_TIM8_CC_HANDLER) -#error "STM32_TIM8_CC_HANDLER not defined" -#endif -/** - * @brief TIM8 compare interrupt handler. - * @note It is assumed that the various sources are only activated if the - * associated callback pointer is not equal to @p NULL in order to not - * perform an extra check in a potentially critical interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM8_CC_HANDLER) { - - CH_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD8); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_ICU_USE_TIM8 */ - -#if STM32_ICU_USE_TIM9 -#if !defined(STM32_TIM9_HANDLER) -#error "STM32_TIM9_HANDLER not defined" -#endif -/** - * @brief TIM9 interrupt handler. - * @note It is assumed that the various sources are only activated if the - * associated callback pointer is not equal to @p NULL in order to not - * perform an extra check in a potentially critical interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM9_HANDLER) { - - CH_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD9); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_ICU_USE_TIM9 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level ICU driver initialization. - * - * @notapi - */ -void icu_lld_init(void) { - -#if STM32_ICU_USE_TIM1 - /* Driver initialization.*/ - icuObjectInit(&ICUD1); - ICUD1.tim = STM32_TIM1; -#endif - -#if STM32_ICU_USE_TIM2 - /* Driver initialization.*/ - icuObjectInit(&ICUD2); - ICUD2.tim = STM32_TIM2; -#endif - -#if STM32_ICU_USE_TIM3 - /* Driver initialization.*/ - icuObjectInit(&ICUD3); - ICUD3.tim = STM32_TIM3; -#endif - -#if STM32_ICU_USE_TIM4 - /* Driver initialization.*/ - icuObjectInit(&ICUD4); - ICUD4.tim = STM32_TIM4; -#endif - -#if STM32_ICU_USE_TIM5 - /* Driver initialization.*/ - icuObjectInit(&ICUD5); - ICUD5.tim = STM32_TIM5; -#endif - -#if STM32_ICU_USE_TIM8 - /* Driver initialization.*/ - icuObjectInit(&ICUD8); - ICUD8.tim = STM32_TIM8; -#endif - -#if STM32_ICU_USE_TIM9 - /* Driver initialization.*/ - icuObjectInit(&ICUD9); - ICUD9.tim = STM32_TIM9; -#endif -} - -/** - * @brief Configures and activates the ICU peripheral. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @notapi - */ -void icu_lld_start(ICUDriver *icup) { - uint32_t psc; - - chDbgAssert((icup->config->channel == ICU_CHANNEL_1) || - (icup->config->channel == ICU_CHANNEL_2), - "icu_lld_start(), #1", "invalid input"); - - if (icup->state == ICU_STOP) { - /* Clock activation and timer reset.*/ -#if STM32_ICU_USE_TIM1 - if (&ICUD1 == icup) { - rccEnableTIM1(FALSE); - rccResetTIM1(); - nvicEnableVector(STM32_TIM1_UP_NUMBER, - CORTEX_PRIORITY_MASK(STM32_ICU_TIM1_IRQ_PRIORITY)); - nvicEnableVector(STM32_TIM1_CC_NUMBER, - CORTEX_PRIORITY_MASK(STM32_ICU_TIM1_IRQ_PRIORITY)); - icup->clock = STM32_TIMCLK2; - } -#endif -#if STM32_ICU_USE_TIM2 - if (&ICUD2 == icup) { - rccEnableTIM2(FALSE); - rccResetTIM2(); - nvicEnableVector(STM32_TIM2_NUMBER, - CORTEX_PRIORITY_MASK(STM32_ICU_TIM2_IRQ_PRIORITY)); - icup->clock = STM32_TIMCLK1; - } -#endif -#if STM32_ICU_USE_TIM3 - if (&ICUD3 == icup) { - rccEnableTIM3(FALSE); - rccResetTIM3(); - nvicEnableVector(STM32_TIM3_NUMBER, - CORTEX_PRIORITY_MASK(STM32_ICU_TIM3_IRQ_PRIORITY)); - icup->clock = STM32_TIMCLK1; - } -#endif -#if STM32_ICU_USE_TIM4 - if (&ICUD4 == icup) { - rccEnableTIM4(FALSE); - rccResetTIM4(); - nvicEnableVector(STM32_TIM4_NUMBER, - CORTEX_PRIORITY_MASK(STM32_ICU_TIM4_IRQ_PRIORITY)); - icup->clock = STM32_TIMCLK1; - } -#endif -#if STM32_ICU_USE_TIM5 - if (&ICUD5 == icup) { - rccEnableTIM5(FALSE); - rccResetTIM5(); - nvicEnableVector(STM32_TIM5_NUMBER, - CORTEX_PRIORITY_MASK(STM32_ICU_TIM5_IRQ_PRIORITY)); - icup->clock = STM32_TIMCLK1; - } -#endif -#if STM32_ICU_USE_TIM8 - if (&ICUD8 == icup) { - rccEnableTIM8(FALSE); - rccResetTIM8(); - nvicEnableVector(STM32_TIM8_UP_NUMBER, - CORTEX_PRIORITY_MASK(STM32_ICU_TIM8_IRQ_PRIORITY)); - nvicEnableVector(STM32_TIM8_CC_NUMBER, - CORTEX_PRIORITY_MASK(STM32_ICU_TIM8_IRQ_PRIORITY)); - icup->clock = STM32_TIMCLK2; - } -#endif -#if STM32_ICU_USE_TIM9 - if (&ICUD9 == icup) { - rccEnableTIM9(FALSE); - rccResetTIM9(); - nvicEnableVector(STM32_TIM9_NUMBER, - CORTEX_PRIORITY_MASK(STM32_ICU_TIM9_IRQ_PRIORITY)); - icup->clock = STM32_TIMCLK1; - } -#endif - } - else { - /* Driver re-configuration scenario, it must be stopped first.*/ - icup->tim->CR1 = 0; /* Timer disabled. */ - icup->tim->DIER = 0; /* All IRQs disabled. */ - icup->tim->SR = 0; /* Clear eventual pending IRQs. */ - icup->tim->CCR[0] = 0; /* Comparator 1 disabled. */ - icup->tim->CCR[1] = 0; /* Comparator 2 disabled. */ - icup->tim->CNT = 0; /* Counter reset to zero. */ - } - - /* Timer configuration.*/ - psc = (icup->clock / icup->config->frequency) - 1; - chDbgAssert((psc <= 0xFFFF) && - ((psc + 1) * icup->config->frequency) == icup->clock, - "icu_lld_start(), #1", "invalid frequency"); - icup->tim->PSC = (uint16_t)psc; - icup->tim->ARR = 0xFFFF; - - if (icup->config->channel == ICU_CHANNEL_1) { - /* Selected input 1. - CCMR1_CC1S = 01 = CH1 Input on TI1. - CCMR1_CC2S = 10 = CH2 Input on TI1.*/ - icup->tim->CCMR1 = STM32_TIM_CCMR1_CC1S(1) | STM32_TIM_CCMR1_CC2S(2); - - /* SMCR_TS = 101, input is TI1FP1. - SMCR_SMS = 100, reset on rising edge.*/ - icup->tim->SMCR = STM32_TIM_SMCR_TS(5) | STM32_TIM_SMCR_SMS(4); - - /* The CCER settings depend on the selected trigger mode. - ICU_INPUT_ACTIVE_HIGH: Active on rising edge, idle on falling edge. - ICU_INPUT_ACTIVE_LOW: Active on falling edge, idle on rising edge.*/ - if (icup->config->mode == ICU_INPUT_ACTIVE_HIGH) - icup->tim->CCER = STM32_TIM_CCER_CC1E | - STM32_TIM_CCER_CC2E | STM32_TIM_CCER_CC2P; - else - icup->tim->CCER = STM32_TIM_CCER_CC1E | STM32_TIM_CCER_CC1P | - STM32_TIM_CCER_CC2E; - - /* Direct pointers to the capture registers in order to make reading - data faster from within callbacks.*/ - icup->wccrp = &icup->tim->CCR[1]; - icup->pccrp = &icup->tim->CCR[0]; - } else { - /* Selected input 2. - CCMR1_CC1S = 10 = CH1 Input on TI2. - CCMR1_CC2S = 01 = CH2 Input on TI2.*/ - icup->tim->CCMR1 = STM32_TIM_CCMR1_CC1S(2) | STM32_TIM_CCMR1_CC2S(1); - - /* SMCR_TS = 110, input is TI2FP2. - SMCR_SMS = 100, reset on rising edge.*/ - icup->tim->SMCR = STM32_TIM_SMCR_TS(6) | STM32_TIM_SMCR_SMS(4); - - /* The CCER settings depend on the selected trigger mode. - ICU_INPUT_ACTIVE_HIGH: Active on rising edge, idle on falling edge. - ICU_INPUT_ACTIVE_LOW: Active on falling edge, idle on rising edge.*/ - if (icup->config->mode == ICU_INPUT_ACTIVE_HIGH) - icup->tim->CCER = STM32_TIM_CCER_CC1E | STM32_TIM_CCER_CC1P | - STM32_TIM_CCER_CC2E; - else - icup->tim->CCER = STM32_TIM_CCER_CC1E | - STM32_TIM_CCER_CC2E | STM32_TIM_CCER_CC2P; - - /* Direct pointers to the capture registers in order to make reading - data faster from within callbacks.*/ - icup->wccrp = &icup->tim->CCR[0]; - icup->pccrp = &icup->tim->CCR[1]; - } -} - -/** - * @brief Deactivates the ICU peripheral. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @notapi - */ -void icu_lld_stop(ICUDriver *icup) { - - if (icup->state == ICU_READY) { - /* Clock deactivation.*/ - icup->tim->CR1 = 0; /* Timer disabled. */ - icup->tim->DIER = 0; /* All IRQs disabled. */ - icup->tim->SR = 0; /* Clear eventual pending IRQs. */ - -#if STM32_ICU_USE_TIM1 - if (&ICUD1 == icup) { - nvicDisableVector(STM32_TIM1_UP_NUMBER); - nvicDisableVector(STM32_TIM1_CC_NUMBER); - rccDisableTIM1(FALSE); - } -#endif -#if STM32_ICU_USE_TIM2 - if (&ICUD2 == icup) { - nvicDisableVector(STM32_TIM2_NUMBER); - rccDisableTIM2(FALSE); - } -#endif -#if STM32_ICU_USE_TIM3 - if (&ICUD3 == icup) { - nvicDisableVector(STM32_TIM3_NUMBER); - rccDisableTIM3(FALSE); - } -#endif -#if STM32_ICU_USE_TIM4 - if (&ICUD4 == icup) { - nvicDisableVector(STM32_TIM4_NUMBER); - rccDisableTIM4(FALSE); - } -#endif -#if STM32_ICU_USE_TIM5 - if (&ICUD5 == icup) { - nvicDisableVector(STM32_TIM5_NUMBER); - rccDisableTIM5(FALSE); - } -#endif -#if STM32_ICU_USE_TIM8 - if (&ICUD8 == icup) { - nvicDisableVector(STM32_TIM8_UP_NUMBER); - nvicDisableVector(STM32_TIM8_CC_NUMBER); - rccDisableTIM8(FALSE); - } -#endif -#if STM32_ICU_USE_TIM9 - if (&ICUD9 == icup) { - nvicDisableVector(STM32_TIM9_NUMBER); - rccDisableTIM9(FALSE); - } -#endif - } -} - -/** - * @brief Enables the input capture. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @notapi - */ -void icu_lld_enable(ICUDriver *icup) { - - 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 |= STM32_TIM_DIER_CC1IE; - if (icup->config->width_cb != NULL) - icup->tim->DIER |= STM32_TIM_DIER_CC2IE; - } else { - if (icup->config->width_cb != NULL) - icup->tim->DIER |= STM32_TIM_DIER_CC1IE; - if (icup->config->period_cb != NULL) - icup->tim->DIER |= STM32_TIM_DIER_CC2IE; - } - if (icup->config->overflow_cb != NULL) - icup->tim->DIER |= STM32_TIM_DIER_UIE; - icup->tim->CR1 = STM32_TIM_CR1_URS | STM32_TIM_CR1_CEN; -} - -/** - * @brief Disables the input capture. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @notapi - */ -void icu_lld_disable(ICUDriver *icup) { - - icup->tim->CR1 = 0; /* Initially stopped. */ - icup->tim->SR = 0; /* Clear pending IRQs (if any). */ - icup->tim->DIER = 0; /* Interrupts disabled. */ -} - -#endif /* HAL_USE_ICU */ - -/** @} */ diff --git a/os/hal/platforms/STM32/icu_lld.h b/os/hal/platforms/STM32/icu_lld.h deleted file mode 100644 index ad6ddffe5..000000000 --- a/os/hal/platforms/STM32/icu_lld.h +++ /dev/null @@ -1,406 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/icu_lld.h - * @brief STM32 ICU subsystem low level driver header. - * - * @addtogroup ICU - * @{ - */ - -#ifndef _ICU_LLD_H_ -#define _ICU_LLD_H_ - -#include "stm32_tim.h" - -#if HAL_USE_ICU || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief ICUD1 driver enable switch. - * @details If set to @p TRUE the support for ICUD1 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_ICU_USE_TIM1) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM1 FALSE -#endif - -/** - * @brief ICUD2 driver enable switch. - * @details If set to @p TRUE the support for ICUD2 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_ICU_USE_TIM2) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM2 FALSE -#endif - -/** - * @brief ICUD3 driver enable switch. - * @details If set to @p TRUE the support for ICUD3 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_ICU_USE_TIM3) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM3 FALSE -#endif - -/** - * @brief ICUD4 driver enable switch. - * @details If set to @p TRUE the support for ICUD4 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_ICU_USE_TIM4) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM4 FALSE -#endif - -/** - * @brief ICUD5 driver enable switch. - * @details If set to @p TRUE the support for ICUD5 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_ICU_USE_TIM5) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM5 FALSE -#endif - -/** - * @brief ICUD8 driver enable switch. - * @details If set to @p TRUE the support for ICUD8 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_ICU_USE_TIM8) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM8 FALSE -#endif - -/** - * @brief ICUD9 driver enable switch. - * @details If set to @p TRUE the support for ICUD9 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_ICU_USE_TIM9) || defined(__DOXYGEN__) -#define STM32_ICU_USE_TIM9 FALSE -#endif - -/** - * @brief ICUD1 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM1_IRQ_PRIORITY 7 -#endif - -/** - * @brief ICUD2 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM2_IRQ_PRIORITY 7 -#endif - -/** - * @brief ICUD3 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM3_IRQ_PRIORITY 7 -#endif - -/** - * @brief ICUD4 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM4_IRQ_PRIORITY 7 -#endif - -/** - * @brief ICUD5 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM5_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM5_IRQ_PRIORITY 7 -#endif - -/** - * @brief ICUD8 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM8_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM8_IRQ_PRIORITY 7 -#endif - -/** - * @brief ICUD9 interrupt priority level setting. - */ -#if !defined(STM32_ICU_TIM9_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ICU_TIM9_IRQ_PRIORITY 7 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_ICU_USE_TIM1 && !STM32_HAS_TIM1 -#error "TIM1 not present in the selected device" -#endif - -#if STM32_ICU_USE_TIM2 && !STM32_HAS_TIM2 -#error "TIM2 not present in the selected device" -#endif - -#if STM32_ICU_USE_TIM3 && !STM32_HAS_TIM3 -#error "TIM3 not present in the selected device" -#endif - -#if STM32_ICU_USE_TIM4 && !STM32_HAS_TIM4 -#error "TIM4 not present in the selected device" -#endif - -#if STM32_ICU_USE_TIM5 && !STM32_HAS_TIM5 -#error "TIM5 not present in the selected device" -#endif - -#if STM32_ICU_USE_TIM8 && !STM32_HAS_TIM8 -#error "TIM8 not present in the selected device" -#endif - -#if STM32_ICU_USE_TIM9 && !STM32_HAS_TIM9 -#error "TIM9 not present in the selected device" -#endif - -#if !STM32_ICU_USE_TIM1 && !STM32_ICU_USE_TIM2 && \ - !STM32_ICU_USE_TIM3 && !STM32_ICU_USE_TIM4 && \ - !STM32_ICU_USE_TIM5 && !STM32_ICU_USE_TIM8 && \ - !STM32_ICU_USE_TIM9 -#error "ICU driver activated but no TIM peripheral assigned" -#endif - -#if STM32_ICU_USE_TIM1 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM1" -#endif - -#if STM32_ICU_USE_TIM2 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM2" -#endif - -#if STM32_ICU_USE_TIM3 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM3" -#endif - -#if STM32_ICU_USE_TIM4 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM4_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM4" -#endif - -#if STM32_ICU_USE_TIM5 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM5_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM5" -#endif - -#if STM32_ICU_USE_TIM8 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM8_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM8" -#endif - -#if STM32_ICU_USE_TIM9 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_ICU_TIM9_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM9" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief ICU driver mode. - */ -typedef enum { - ICU_INPUT_ACTIVE_HIGH = 0, /**< Trigger on rising edge. */ - ICU_INPUT_ACTIVE_LOW = 1, /**< Trigger on falling edge. */ -} icumode_t; - -/** - * @brief ICU frequency type. - */ -typedef uint32_t icufreq_t; - -/** - * @brief ICU channel type. - */ -typedef enum { - ICU_CHANNEL_1 = 0, /**< Use TIMxCH1. */ - ICU_CHANNEL_2 = 1, /**< Use TIMxCH2. */ -} icuchannel_t; - -/** - * @brief ICU counter type. - */ -typedef uint16_t icucnt_t; - -/** - * @brief Driver configuration structure. - * @note It could be empty on some architectures. - */ -typedef struct { - /** - * @brief Driver mode. - */ - icumode_t mode; - /** - * @brief Timer clock in Hz. - * @note The low level can use assertions in order to catch invalid - * frequency specifications. - */ - icufreq_t frequency; - /** - * @brief Callback for pulse width measurement. - */ - icucallback_t width_cb; - /** - * @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. - * @note Only inputs TIMx 1 and 2 are supported. - */ - icuchannel_t channel; -} ICUConfig; - -/** - * @brief Structure representing an ICU driver. - */ -struct ICUDriver { - /** - * @brief Driver state. - */ - icustate_t state; - /** - * @brief Current configuration data. - */ - const ICUConfig *config; -#if defined(ICU_DRIVER_EXT_FIELDS) - ICU_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Timer base clock. - */ - uint32_t clock; - /** - * @brief Pointer to the TIMx registers block. - */ - stm32_tim_t *tim; - /** - * @brief CCR register used for width capture. - */ - volatile uint32_t *wccrp; - /** - * @brief CCR register used for period capture. - */ - volatile uint32_t *pccrp; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Returns the width of the latest pulse. - * @details The pulse width is defined as number of ticks between the start - * edge and the stop edge. - * - * @param[in] icup pointer to the @p ICUDriver object - * @return The number of ticks. - * - * @notapi - */ -#define icu_lld_get_width(icup) (*((icup)->wccrp) + 1) - -/** - * @brief Returns the width of the latest cycle. - * @details The cycle width is defined as number of ticks between a start - * edge and the next start edge. - * - * @param[in] icup pointer to the @p ICUDriver object - * @return The number of ticks. - * - * @notapi - */ -#define icu_lld_get_period(icup) (*((icup)->pccrp) + 1) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_ICU_USE_TIM1 && !defined(__DOXYGEN__) -extern ICUDriver ICUD1; -#endif - -#if STM32_ICU_USE_TIM2 && !defined(__DOXYGEN__) -extern ICUDriver ICUD2; -#endif - -#if STM32_ICU_USE_TIM3 && !defined(__DOXYGEN__) -extern ICUDriver ICUD3; -#endif - -#if STM32_ICU_USE_TIM4 && !defined(__DOXYGEN__) -extern ICUDriver ICUD4; -#endif - -#if STM32_ICU_USE_TIM5 && !defined(__DOXYGEN__) -extern ICUDriver ICUD5; -#endif - -#if STM32_ICU_USE_TIM8 && !defined(__DOXYGEN__) -extern ICUDriver ICUD8; -#endif - -#if STM32_ICU_USE_TIM9 && !defined(__DOXYGEN__) -extern ICUDriver ICUD9; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void icu_lld_init(void); - void icu_lld_start(ICUDriver *icup); - void icu_lld_stop(ICUDriver *icup); - void icu_lld_enable(ICUDriver *icup); - void icu_lld_disable(ICUDriver *icup); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_ICU */ - -#endif /* _ICU_LLD_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/pwm_lld.c b/os/hal/platforms/STM32/pwm_lld.c deleted file mode 100644 index 97114ac79..000000000 --- a/os/hal/platforms/STM32/pwm_lld.c +++ /dev/null @@ -1,705 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/pwm_lld.c - * @brief STM32 PWM subsystem low level driver header. - * - * @addtogroup PWM - * @{ - */ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_PWM || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief PWMD1 driver identifier. - * @note The driver PWMD1 allocates the complex timer TIM1 when enabled. - */ -#if STM32_PWM_USE_TIM1 || defined(__DOXYGEN__) -PWMDriver PWMD1; -#endif - -/** - * @brief PWMD2 driver identifier. - * @note The driver PWMD2 allocates the timer TIM2 when enabled. - */ -#if STM32_PWM_USE_TIM2 || defined(__DOXYGEN__) -PWMDriver PWMD2; -#endif - -/** - * @brief PWMD3 driver identifier. - * @note The driver PWMD3 allocates the timer TIM3 when enabled. - */ -#if STM32_PWM_USE_TIM3 || defined(__DOXYGEN__) -PWMDriver PWMD3; -#endif - -/** - * @brief PWMD4 driver identifier. - * @note The driver PWMD4 allocates the timer TIM4 when enabled. - */ -#if STM32_PWM_USE_TIM4 || defined(__DOXYGEN__) -PWMDriver PWMD4; -#endif - -/** - * @brief PWMD5 driver identifier. - * @note The driver PWMD5 allocates the timer TIM5 when enabled. - */ -#if STM32_PWM_USE_TIM5 || defined(__DOXYGEN__) -PWMDriver PWMD5; -#endif - -/** - * @brief PWMD8 driver identifier. - * @note The driver PWMD8 allocates the timer TIM8 when enabled. - */ -#if STM32_PWM_USE_TIM8 || defined(__DOXYGEN__) -PWMDriver PWMD8; -#endif - -/** - * @brief PWMD9 driver identifier. - * @note The driver PWMD9 allocates the timer TIM9 when enabled. - */ -#if STM32_PWM_USE_TIM9 || defined(__DOXYGEN__) -PWMDriver PWMD9; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -#if STM32_PWM_USE_TIM2 || STM32_PWM_USE_TIM3 || STM32_PWM_USE_TIM4 || \ - STM32_PWM_USE_TIM5 || STM32_PWM_USE_TIM9 || defined(__DOXYGEN__) -/** - * @brief Common TIM2...TIM5,TIM9 IRQ handler. - * @note It is assumed that the various sources are only activated if the - * associated callback pointer is not equal to @p NULL in order to not - * perform an extra check in a potentially critical interrupt handler. - * - * @param[in] pwmp pointer to a @p PWMDriver object - */ -static void pwm_lld_serve_interrupt(PWMDriver *pwmp) { - uint16_t sr; - - sr = pwmp->tim->SR; - sr &= pwmp->tim->DIER; - pwmp->tim->SR = ~sr; - if ((sr & STM32_TIM_SR_CC1IF) != 0) - pwmp->config->channels[0].callback(pwmp); - if ((sr & STM32_TIM_SR_CC2IF) != 0) - pwmp->config->channels[1].callback(pwmp); - if ((sr & STM32_TIM_SR_CC3IF) != 0) - pwmp->config->channels[2].callback(pwmp); - if ((sr & STM32_TIM_SR_CC4IF) != 0) - pwmp->config->channels[3].callback(pwmp); - if ((sr & STM32_TIM_SR_UIF) != 0) - pwmp->config->callback(pwmp); -} -#endif /* STM32_PWM_USE_TIM2 || ... || STM32_PWM_USE_TIM5 */ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_PWM_USE_TIM1 -#if !defined(STM32_TIM1_UP_HANDLER) -#error "STM32_TIM1_UP_HANDLER not defined" -#endif -/** - * @brief TIM1 update interrupt handler. - * @note It is assumed that this interrupt is only activated if the callback - * pointer is not equal to @p NULL in order to not perform an extra - * check in a potentially critical interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) { - - CH_IRQ_PROLOGUE(); - - STM32_TIM1->SR = ~STM32_TIM_SR_UIF; - PWMD1.config->callback(&PWMD1); - - CH_IRQ_EPILOGUE(); -} - -#if !defined(STM32_TIM1_CC_HANDLER) -#error "STM32_TIM1_CC_HANDLER not defined" -#endif -/** - * @brief TIM1 compare interrupt handler. - * @note It is assumed that the various sources are only activated if the - * associated callback pointer is not equal to @p NULL in order to not - * perform an extra check in a potentially critical interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM1_CC_HANDLER) { - uint16_t sr; - - CH_IRQ_PROLOGUE(); - - sr = STM32_TIM1->SR & STM32_TIM1->DIER; - STM32_TIM1->SR = ~(STM32_TIM_SR_CC1IF | STM32_TIM_SR_CC2IF | - STM32_TIM_SR_CC3IF | STM32_TIM_SR_CC4IF); - if ((sr & STM32_TIM_SR_CC1IF) != 0) - PWMD1.config->channels[0].callback(&PWMD1); - if ((sr & STM32_TIM_SR_CC2IF) != 0) - PWMD1.config->channels[1].callback(&PWMD1); - if ((sr & STM32_TIM_SR_CC3IF) != 0) - PWMD1.config->channels[2].callback(&PWMD1); - if ((sr & STM32_TIM_SR_CC4IF) != 0) - PWMD1.config->channels[3].callback(&PWMD1); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_PWM_USE_TIM1 */ - -#if STM32_PWM_USE_TIM2 -#if !defined(STM32_TIM2_HANDLER) -#error "STM32_TIM2_HANDLER not defined" -#endif -/** - * @brief TIM2 interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM2_HANDLER) { - - CH_IRQ_PROLOGUE(); - - pwm_lld_serve_interrupt(&PWMD2); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_PWM_USE_TIM2 */ - -#if STM32_PWM_USE_TIM3 -#if !defined(STM32_TIM3_HANDLER) -#error "STM32_TIM3_HANDLER not defined" -#endif -/** - * @brief TIM3 interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM3_HANDLER) { - - CH_IRQ_PROLOGUE(); - - pwm_lld_serve_interrupt(&PWMD3); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_PWM_USE_TIM3 */ - -#if STM32_PWM_USE_TIM4 -#if !defined(STM32_TIM4_HANDLER) -#error "STM32_TIM4_HANDLER not defined" -#endif -/** - * @brief TIM4 interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM4_HANDLER) { - - CH_IRQ_PROLOGUE(); - - pwm_lld_serve_interrupt(&PWMD4); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_PWM_USE_TIM4 */ - -#if STM32_PWM_USE_TIM5 -#if !defined(STM32_TIM5_HANDLER) -#error "STM32_TIM5_HANDLER not defined" -#endif -/** - * @brief TIM5 interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM5_HANDLER) { - - CH_IRQ_PROLOGUE(); - - pwm_lld_serve_interrupt(&PWMD5); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_PWM_USE_TIM5 */ - -#if STM32_PWM_USE_TIM8 -#if !defined(STM32_TIM8_UP_HANDLER) -#error "STM32_TIM8_UP_HANDLER not defined" -#endif -/** - * @brief TIM8 update interrupt handler. - * @note It is assumed that this interrupt is only activated if the callback - * pointer is not equal to @p NULL in order to not perform an extra - * check in a potentially critical interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) { - - CH_IRQ_PROLOGUE(); - - STM32_TIM8->SR = ~TIM_SR_UIF; - PWMD8.config->callback(&PWMD8); - - CH_IRQ_EPILOGUE(); -} - -#if !defined(STM32_TIM8_CC_HANDLER) -#error "STM32_TIM8_CC_HANDLER not defined" -#endif -/** - * @brief TIM8 compare interrupt handler. - * @note It is assumed that the various sources are only activated if the - * associated callback pointer is not equal to @p NULL in order to not - * perform an extra check in a potentially critical interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM8_CC_HANDLER) { - uint16_t sr; - - CH_IRQ_PROLOGUE(); - - sr = STM32_TIM8->SR & STM32_TIM8->DIER; - STM32_TIM8->SR = ~(STM32_TIM_SR_CC1IF | STM32_TIM_SR_CC2IF | - STM32_TIM_SR_CC3IF | STM32_TIM_SR_CC4IF); - if ((sr & STM32_TIM_SR_CC1IF) != 0) - PWMD8.config->channels[0].callback(&PWMD8); - if ((sr & STM32_TIM_SR_CC2IF) != 0) - PWMD8.config->channels[1].callback(&PWMD8); - if ((sr & STM32_TIM_SR_CC3IF) != 0) - PWMD8.config->channels[2].callback(&PWMD8); - if ((sr & STM32_TIM_SR_CC4IF) != 0) - PWMD8.config->channels[3].callback(&PWMD8); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_PWM_USE_TIM8 */ - -#if STM32_PWM_USE_TIM9 -#if !defined(STM32_TIM9_HANDLER) -#error "STM32_TIM9_HANDLER not defined" -#endif -/** - * @brief TIM9 interrupt handler. - * - * @isr - */ -CH_IRQ_HANDLER(STM32_TIM9_HANDLER) { - - CH_IRQ_PROLOGUE(); - - pwm_lld_serve_interrupt(&PWMD9); - - CH_IRQ_EPILOGUE(); -} -#endif /* STM32_PWM_USE_TIM9 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level PWM driver initialization. - * - * @notapi - */ -void pwm_lld_init(void) { - -#if STM32_PWM_USE_TIM1 - /* Driver initialization.*/ - pwmObjectInit(&PWMD1); - PWMD1.tim = STM32_TIM1; -#endif - -#if STM32_PWM_USE_TIM2 - /* Driver initialization.*/ - pwmObjectInit(&PWMD2); - PWMD2.tim = STM32_TIM2; -#endif - -#if STM32_PWM_USE_TIM3 - /* Driver initialization.*/ - pwmObjectInit(&PWMD3); - PWMD3.tim = STM32_TIM3; -#endif - -#if STM32_PWM_USE_TIM4 - /* Driver initialization.*/ - pwmObjectInit(&PWMD4); - PWMD4.tim = STM32_TIM4; -#endif - -#if STM32_PWM_USE_TIM5 - /* Driver initialization.*/ - pwmObjectInit(&PWMD5); - PWMD5.tim = STM32_TIM5; -#endif - -#if STM32_PWM_USE_TIM8 - /* Driver initialization.*/ - pwmObjectInit(&PWMD8); - PWMD8.tim = STM32_TIM8; -#endif - -#if STM32_PWM_USE_TIM9 - /* Driver initialization.*/ - pwmObjectInit(&PWMD9); - PWMD9.tim = STM32_TIM9; -#endif -} - -/** - * @brief Configures and activates the PWM peripheral. - * @note Starting a driver that is already in the @p PWM_READY state - * disables all the active channels. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * - * @notapi - */ -void pwm_lld_start(PWMDriver *pwmp) { - uint32_t psc; - uint16_t ccer; - - if (pwmp->state == PWM_STOP) { - /* Clock activation and timer reset.*/ -#if STM32_PWM_USE_TIM1 - if (&PWMD1 == pwmp) { - rccEnableTIM1(FALSE); - rccResetTIM1(); - nvicEnableVector(STM32_TIM1_UP_NUMBER, - CORTEX_PRIORITY_MASK(STM32_PWM_TIM1_IRQ_PRIORITY)); - nvicEnableVector(STM32_TIM1_CC_NUMBER, - CORTEX_PRIORITY_MASK(STM32_PWM_TIM1_IRQ_PRIORITY)); - pwmp->clock = STM32_TIMCLK2; - } -#endif -#if STM32_PWM_USE_TIM2 - if (&PWMD2 == pwmp) { - rccEnableTIM2(FALSE); - rccResetTIM2(); - nvicEnableVector(STM32_TIM2_NUMBER, - CORTEX_PRIORITY_MASK(STM32_PWM_TIM2_IRQ_PRIORITY)); - pwmp->clock = STM32_TIMCLK1; - } -#endif -#if STM32_PWM_USE_TIM3 - if (&PWMD3 == pwmp) { - rccEnableTIM3(FALSE); - rccResetTIM3(); - nvicEnableVector(STM32_TIM3_NUMBER, - CORTEX_PRIORITY_MASK(STM32_PWM_TIM3_IRQ_PRIORITY)); - pwmp->clock = STM32_TIMCLK1; - } -#endif -#if STM32_PWM_USE_TIM4 - if (&PWMD4 == pwmp) { - rccEnableTIM4(FALSE); - rccResetTIM4(); - nvicEnableVector(STM32_TIM4_NUMBER, - CORTEX_PRIORITY_MASK(STM32_PWM_TIM4_IRQ_PRIORITY)); - pwmp->clock = STM32_TIMCLK1; - } -#endif - -#if STM32_PWM_USE_TIM5 - if (&PWMD5 == pwmp) { - rccEnableTIM5(FALSE); - rccResetTIM5(); - nvicEnableVector(STM32_TIM5_NUMBER, - CORTEX_PRIORITY_MASK(STM32_PWM_TIM5_IRQ_PRIORITY)); - pwmp->clock = STM32_TIMCLK1; - } -#endif -#if STM32_PWM_USE_TIM8 - if (&PWMD8 == pwmp) { - rccEnableTIM8(FALSE); - rccResetTIM8(); - nvicEnableVector(STM32_TIM8_UP_NUMBER, - CORTEX_PRIORITY_MASK(STM32_PWM_TIM8_IRQ_PRIORITY)); - nvicEnableVector(STM32_TIM8_CC_NUMBER, - CORTEX_PRIORITY_MASK(STM32_PWM_TIM8_IRQ_PRIORITY)); - pwmp->clock = STM32_TIMCLK2; - } -#endif -#if STM32_PWM_USE_TIM9 - if (&PWMD9 == pwmp) { - rccEnableTIM9(FALSE); - rccResetTIM9(); - nvicEnableVector(STM32_TIM9_NUMBER, - CORTEX_PRIORITY_MASK(STM32_PWM_TIM9_IRQ_PRIORITY)); - pwmp->clock = STM32_TIMCLK1; - } -#endif - - /* All channels configured in PWM1 mode with preload enabled and will - stay that way until the driver is stopped.*/ - pwmp->tim->CCMR1 = STM32_TIM_CCMR1_OC1M(6) | STM32_TIM_CCMR1_OC1PE | - STM32_TIM_CCMR1_OC2M(6) | STM32_TIM_CCMR1_OC2PE; - pwmp->tim->CCMR2 = STM32_TIM_CCMR2_OC3M(6) | STM32_TIM_CCMR2_OC3PE | - STM32_TIM_CCMR2_OC4M(6) | STM32_TIM_CCMR2_OC4PE; - } - else { - /* Driver re-configuration scenario, it must be stopped first.*/ - pwmp->tim->CR1 = 0; /* Timer disabled. */ - pwmp->tim->DIER = 0; /* All IRQs disabled. */ - pwmp->tim->SR = 0; /* Clear eventual pending IRQs. */ - pwmp->tim->CCR[0] = 0; /* Comparator 1 disabled. */ - pwmp->tim->CCR[1] = 0; /* Comparator 2 disabled. */ - pwmp->tim->CCR[2] = 0; /* Comparator 3 disabled. */ - pwmp->tim->CCR[3] = 0; /* Comparator 4 disabled. */ - pwmp->tim->CNT = 0; /* Counter reset to zero. */ - } - - /* Timer configuration.*/ - psc = (pwmp->clock / pwmp->config->frequency) - 1; - chDbgAssert((psc <= 0xFFFF) && - ((psc + 1) * pwmp->config->frequency) == pwmp->clock, - "pwm_lld_start(), #1", "invalid frequency"); - pwmp->tim->PSC = (uint16_t)psc; - pwmp->tim->ARR = (uint16_t)(pwmp->period - 1); - pwmp->tim->CR2 = pwmp->config->cr2; - - /* Output enables and polarities setup.*/ - ccer = 0; - switch (pwmp->config->channels[0].mode & PWM_OUTPUT_MASK) { - case PWM_OUTPUT_ACTIVE_LOW: - ccer |= STM32_TIM_CCER_CC1P; - case PWM_OUTPUT_ACTIVE_HIGH: - ccer |= STM32_TIM_CCER_CC1E; - default: - ; - } - switch (pwmp->config->channels[1].mode & PWM_OUTPUT_MASK) { - case PWM_OUTPUT_ACTIVE_LOW: - ccer |= STM32_TIM_CCER_CC2P; - case PWM_OUTPUT_ACTIVE_HIGH: - ccer |= STM32_TIM_CCER_CC2E; - default: - ; - } - switch (pwmp->config->channels[2].mode & PWM_OUTPUT_MASK) { - case PWM_OUTPUT_ACTIVE_LOW: - ccer |= STM32_TIM_CCER_CC3P; - case PWM_OUTPUT_ACTIVE_HIGH: - ccer |= STM32_TIM_CCER_CC3E; - default: - ; - } - switch (pwmp->config->channels[3].mode & PWM_OUTPUT_MASK) { - case PWM_OUTPUT_ACTIVE_LOW: - ccer |= STM32_TIM_CCER_CC4P; - case PWM_OUTPUT_ACTIVE_HIGH: - ccer |= STM32_TIM_CCER_CC4E; - default: - ; - } -#if STM32_PWM_USE_ADVANCED -#if STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM8 - if (&PWMD1 == pwmp) { -#endif -#if !STM32_PWM_USE_TIM1 && STM32_PWM_USE_TIM8 - if (&PWMD8 == pwmp) { -#endif -#if STM32_PWM_USE_TIM1 && STM32_PWM_USE_TIM8 - if ((&PWMD1 == pwmp) || (&PWMD8 == pwmp)) { -#endif - switch (pwmp->config->channels[0].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) { - case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW: - ccer |= STM32_TIM_CCER_CC1NP; - case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH: - ccer |= STM32_TIM_CCER_CC1NE; - default: - ; - } - switch (pwmp->config->channels[1].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) { - case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW: - ccer |= STM32_TIM_CCER_CC2NP; - case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH: - ccer |= STM32_TIM_CCER_CC2NE; - default: - ; - } - switch (pwmp->config->channels[2].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) { - case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW: - ccer |= STM32_TIM_CCER_CC3NP; - case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH: - ccer |= STM32_TIM_CCER_CC3NE; - default: - ; - } - } -#endif /* STM32_PWM_USE_ADVANCED*/ - - pwmp->tim->CCER = ccer; - pwmp->tim->EGR = STM32_TIM_EGR_UG; /* Update event. */ - pwmp->tim->DIER = pwmp->config->callback == NULL ? 0 : STM32_TIM_DIER_UIE; - pwmp->tim->SR = 0; /* Clear pending IRQs. */ -#if STM32_PWM_USE_TIM1 || STM32_PWM_USE_TIM8 -#if STM32_PWM_USE_ADVANCED - pwmp->tim->BDTR = pwmp->config->bdtr | STM32_TIM_BDTR_MOE; -#else - pwmp->tim->BDTR = STM32_TIM_BDTR_MOE; -#endif -#endif - /* Timer configured and started.*/ - pwmp->tim->CR1 = STM32_TIM_CR1_ARPE | STM32_TIM_CR1_URS | STM32_TIM_CR1_CEN; -} - -/** - * @brief Deactivates the PWM peripheral. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * - * @notapi - */ -void pwm_lld_stop(PWMDriver *pwmp) { - - /* If in ready state then disables the PWM clock.*/ - if (pwmp->state == PWM_READY) { - pwmp->tim->CR1 = 0; /* Timer disabled. */ - pwmp->tim->DIER = 0; /* All IRQs disabled. */ - pwmp->tim->SR = 0; /* Clear eventual pending IRQs. */ -#if STM32_PWM_USE_TIM1 || STM32_PWM_USE_TIM8 - pwmp->tim->BDTR = 0; -#endif - -#if STM32_PWM_USE_TIM1 - if (&PWMD1 == pwmp) { - nvicDisableVector(STM32_TIM1_UP_NUMBER); - nvicDisableVector(STM32_TIM1_CC_NUMBER); - rccDisableTIM1(FALSE); - } -#endif -#if STM32_PWM_USE_TIM2 - if (&PWMD2 == pwmp) { - nvicDisableVector(STM32_TIM2_NUMBER); - rccDisableTIM2(FALSE); - } -#endif -#if STM32_PWM_USE_TIM3 - if (&PWMD3 == pwmp) { - nvicDisableVector(STM32_TIM3_NUMBER); - rccDisableTIM3(FALSE); - } -#endif -#if STM32_PWM_USE_TIM4 - if (&PWMD4 == pwmp) { - nvicDisableVector(STM32_TIM4_NUMBER); - rccDisableTIM4(FALSE); - } -#endif -#if STM32_PWM_USE_TIM5 - if (&PWMD5 == pwmp) { - nvicDisableVector(STM32_TIM5_NUMBER); - rccDisableTIM5(FALSE); - } -#endif -#if STM32_PWM_USE_TIM8 - if (&PWMD8 == pwmp) { - nvicDisableVector(STM32_TIM8_UP_NUMBER); - nvicDisableVector(STM32_TIM8_CC_NUMBER); - rccDisableTIM8(FALSE); - } -#endif -#if STM32_PWM_USE_TIM9 - if (&PWMD9 == pwmp) { - nvicDisableVector(STM32_TIM9_NUMBER); - rccDisableTIM9(FALSE); - } -#endif - } -} - -/** - * @brief Enables a PWM channel. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @post The channel is active using the specified configuration. - * @note The function has effect at the next cycle start. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1) - * @param[in] width PWM pulse width as clock pulses number - * - * @notapi - */ -void pwm_lld_enable_channel(PWMDriver *pwmp, - pwmchannel_t channel, - pwmcnt_t width) { - - pwmp->tim->CCR[channel] = width; /* New duty cycle. */ - /* If there is a callback defined for the channel then the associated - interrupt must be enabled.*/ - if (pwmp->config->channels[channel].callback != NULL) { - uint32_t dier = pwmp->tim->DIER; - /* If the IRQ is not already enabled care must be taken to clear it, - it is probably already pending because the timer is running.*/ - if ((dier & (2 << channel)) == 0) { - pwmp->tim->DIER = dier | (2 << channel); - pwmp->tim->SR = ~(2 << channel); - } - } -} - -/** - * @brief Disables a PWM channel. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @post The channel is disabled and its output line returned to the - * idle state. - * @note The function has effect at the next cycle start. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1) - * - * @notapi - */ -void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel) { - - pwmp->tim->CCR[channel] = 0; - pwmp->tim->DIER &= ~(2 << channel); -} - -#endif /* HAL_USE_PWM */ - -/** @} */ diff --git a/os/hal/platforms/STM32/pwm_lld.h b/os/hal/platforms/STM32/pwm_lld.h deleted file mode 100644 index 0ef6abbca..000000000 --- a/os/hal/platforms/STM32/pwm_lld.h +++ /dev/null @@ -1,474 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file STM32/pwm_lld.h - * @brief STM32 PWM subsystem low level driver header. - * - * @addtogroup PWM - * @{ - */ - -#ifndef _PWM_LLD_H_ -#define _PWM_LLD_H_ - -#include "stm32_tim.h" - -#if HAL_USE_PWM || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Number of PWM channels per PWM driver. - */ -#define PWM_CHANNELS 4 - -/** - * @brief Complementary output modes mask. - * @note This is an STM32-specific setting. - */ -#define PWM_COMPLEMENTARY_OUTPUT_MASK 0xF0 - -/** - * @brief Complementary output not driven. - * @note This is an STM32-specific setting. - */ -#define PWM_COMPLEMENTARY_OUTPUT_DISABLED 0x00 - -/** - * @brief Complementary output, active is logic level one. - * @note This is an STM32-specific setting. - * @note This setting is only available if the configuration option - * @p STM32_PWM_USE_ADVANCED is set to TRUE and only for advanced - * timers TIM1 and TIM8. - */ -#define PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH 0x10 - -/** - * @brief Complementary output, active is logic level zero. - * @note This is an STM32-specific setting. - * @note This setting is only available if the configuration option - * @p STM32_PWM_USE_ADVANCED is set to TRUE and only for advanced - * timers TIM1 and TIM8. - */ -#define PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW 0x20 - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief If advanced timer features switch. - * @details If set to @p TRUE the advanced features for TIM1 and TIM8 are - * enabled. - * @note The default is @p TRUE. - */ -#if !defined(STM32_PWM_USE_ADVANCED) || defined(__DOXYGEN__) -#define STM32_PWM_USE_ADVANCED FALSE -#endif - -/** - * @brief PWMD1 driver enable switch. - * @details If set to @p TRUE the support for PWMD1 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_PWM_USE_TIM1) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM1 FALSE -#endif - -/** - * @brief PWMD2 driver enable switch. - * @details If set to @p TRUE the support for PWMD2 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_PWM_USE_TIM2) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM2 FALSE -#endif - -/** - * @brief PWMD3 driver enable switch. - * @details If set to @p TRUE the support for PWMD3 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_PWM_USE_TIM3) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM3 FALSE -#endif - -/** - * @brief PWMD4 driver enable switch. - * @details If set to @p TRUE the support for PWMD4 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_PWM_USE_TIM4) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM4 FALSE -#endif - -/** - * @brief PWMD5 driver enable switch. - * @details If set to @p TRUE the support for PWMD5 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_PWM_USE_TIM5) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM5 FALSE -#endif - -/** - * @brief PWMD8 driver enable switch. - * @details If set to @p TRUE the support for PWMD8 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_PWM_USE_TIM8) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM8 FALSE -#endif - -/** - * @brief PWMD9 driver enable switch. - * @details If set to @p TRUE the support for PWMD9 is included. - * @note The default is @p TRUE. - */ -#if !defined(STM32_PWM_USE_TIM9) || defined(__DOXYGEN__) -#define STM32_PWM_USE_TIM9 FALSE -#endif - -/** - * @brief PWMD1 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM1_IRQ_PRIORITY 7 -#endif - -/** - * @brief PWMD2 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM2_IRQ_PRIORITY 7 -#endif - -/** - * @brief PWMD3 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM3_IRQ_PRIORITY 7 -#endif - -/** - * @brief PWMD4 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM4_IRQ_PRIORITY 7 -#endif - -/** - * @brief PWMD5 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM5_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM5_IRQ_PRIORITY 7 -#endif - -/** - * @brief PWMD8 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM8_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM8_IRQ_PRIORITY 7 -#endif -/** @} */ - -/** - * @brief PWMD9 interrupt priority level setting. - */ -#if !defined(STM32_PWM_TIM9_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_PWM_TIM9_IRQ_PRIORITY 7 -#endif -/** @} */ - -/*===========================================================================*/ -/* Configuration checks. */ -/*===========================================================================*/ - -#if STM32_PWM_USE_TIM1 && !STM32_HAS_TIM1 -#error "TIM1 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM2 && !STM32_HAS_TIM2 -#error "TIM2 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM3 && !STM32_HAS_TIM3 -#error "TIM3 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM4 && !STM32_HAS_TIM4 -#error "TIM4 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM5 && !STM32_HAS_TIM5 -#error "TIM5 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM8 && !STM32_HAS_TIM8 -#error "TIM8 not present in the selected device" -#endif - -#if STM32_PWM_USE_TIM9 && !STM32_HAS_TIM9 -#error "TIM9 not present in the selected device" -#endif - -#if !STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM2 && \ - !STM32_PWM_USE_TIM3 && !STM32_PWM_USE_TIM4 && \ - !STM32_PWM_USE_TIM5 && !STM32_PWM_USE_TIM8 && \ - !STM32_PWM_USE_TIM9 -#error "PWM driver activated but no TIM peripheral assigned" -#endif - -#if STM32_PWM_USE_ADVANCED && !STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM8 -#error "advanced mode selected but no advanced timer assigned" -#endif - -#if STM32_PWM_USE_TIM1 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM1" -#endif - -#if STM32_PWM_USE_TIM2 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM2" -#endif - -#if STM32_PWM_USE_TIM3 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM3" -#endif - -#if STM32_PWM_USE_TIM4 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM4_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM4" -#endif - -#if STM32_PWM_USE_TIM5 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM5_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM5" -#endif - -#if STM32_PWM_USE_TIM8 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM8_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM8" -#endif - -#if STM32_PWM_USE_TIM9 && \ - !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_PWM_TIM9_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM9" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief PWM mode type. - */ -typedef uint32_t pwmmode_t; - -/** - * @brief PWM channel type. - */ -typedef uint8_t pwmchannel_t; - -/** - * @brief PWM counter type. - */ -typedef uint16_t pwmcnt_t; - -/** - * @brief PWM driver channel configuration structure. - */ -typedef struct { - /** - * @brief Channel active logic level. - */ - pwmmode_t mode; - /** - * @brief Channel callback pointer. - * @note This callback is invoked on the channel compare event. If set to - * @p NULL then the callback is disabled. - */ - pwmcallback_t callback; - /* End of the mandatory fields.*/ -} PWMChannelConfig; - -/** - * @brief PWM driver configuration structure. - */ -typedef struct { - /** - * @brief Timer clock in Hz. - * @note The low level can use assertions in order to catch invalid - * frequency specifications. - */ - uint32_t frequency; - /** - * @brief PWM period in ticks. - * @note The low level can use assertions in order to catch invalid - * period specifications. - */ - pwmcnt_t period; - /** - * @brief Periodic callback pointer. - * @note This callback is invoked on PWM counter reset. If set to - * @p NULL then the callback is disabled. - */ - pwmcallback_t callback; - /** - * @brief Channels configurations. - */ - PWMChannelConfig channels[PWM_CHANNELS]; - /* End of the mandatory fields.*/ - /** - * @brief TIM CR2 register initialization data. - * @note The value of this field should normally be equal to zero. - */ - uint16_t cr2; -#if STM32_PWM_USE_ADVANCED || defined(__DOXYGEN__) - /** - * @brief TIM BDTR (break & dead-time) register initialization data. - * @note The value of this field should normally be equal to zero. - */ \ - uint16_t bdtr; -#endif -} PWMConfig; - -/** - * @brief Structure representing a PWM driver. - */ -struct PWMDriver { - /** - * @brief Driver state. - */ - pwmstate_t state; - /** - * @brief Current driver configuration data. - */ - const PWMConfig *config; - /** - * @brief Current PWM period in ticks. - */ - pwmcnt_t period; -#if defined(PWM_DRIVER_EXT_FIELDS) - PWM_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Timer base clock. - */ - uint32_t clock; - /** - * @brief Pointer to the TIMx registers block. - */ - stm32_tim_t *tim; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Changes the period the PWM peripheral. - * @details This function changes the period of a PWM unit that has already - * been activated using @p pwmStart(). - * @pre The PWM unit must have been activated using @p pwmStart(). - * @post The PWM unit period is changed to the new value. - * @note The function has effect at the next cycle start. - * @note If a period is specified that is shorter than the pulse width - * programmed in one of the channels then the behavior is not - * guaranteed. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] period new cycle time in ticks - * - * @notapi - */ -#define pwm_lld_change_period(pwmp, period) \ - ((pwmp)->tim->ARR = (uint16_t)((period) - 1)) - -/** - * @brief Returns a PWM channel status. - * @pre The PWM unit must have been activated using @p pwmStart(). - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1) - * - * @notapi - */ -#define pwm_lld_is_channel_enabled(pwmp, channel) \ - (((pwmp)->tim->CCR[channel] != 0) || \ - (((pwmp)->tim->DIER & (2 << channel)) != 0)) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if STM32_PWM_USE_TIM1 && !defined(__DOXYGEN__) -extern PWMDriver PWMD1; -#endif - -#if STM32_PWM_USE_TIM2 && !defined(__DOXYGEN__) -extern PWMDriver PWMD2; -#endif - -#if STM32_PWM_USE_TIM3 && !defined(__DOXYGEN__) -extern PWMDriver PWMD3; -#endif - -#if STM32_PWM_USE_TIM4 && !defined(__DOXYGEN__) -extern PWMDriver PWMD4; -#endif - -#if STM32_PWM_USE_TIM5 && !defined(__DOXYGEN__) -extern PWMDriver PWMD5; -#endif - -#if STM32_PWM_USE_TIM8 && !defined(__DOXYGEN__) -extern PWMDriver PWMD8; -#endif - -#if STM32_PWM_USE_TIM9 && !defined(__DOXYGEN__) -extern PWMDriver PWMD9; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void pwm_lld_init(void); - void pwm_lld_start(PWMDriver *pwmp); - void pwm_lld_stop(PWMDriver *pwmp); - void pwm_lld_enable_channel(PWMDriver *pwmp, - pwmchannel_t channel, - pwmcnt_t width); - void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_PWM */ - -#endif /* _PWM_LLD_H_ */ - -/** @} */ -- cgit v1.2.3