From a84c32523cb971505e03ae73409839637d8706a9 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Sat, 2 Apr 2016 08:31:39 +0000 Subject: STM32 LLD renaming done. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9208 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/ports/STM32/LLD/TIMv1/gpt_lld.c | 891 ----------------------------- os/hal/ports/STM32/LLD/TIMv1/gpt_lld.h | 641 --------------------- os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.c | 891 +++++++++++++++++++++++++++++ os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.h | 641 +++++++++++++++++++++ os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.c | 805 ++++++++++++++++++++++++++ os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.h | 487 ++++++++++++++++ os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.c | 858 +++++++++++++++++++++++++++ os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.h | 550 ++++++++++++++++++ os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.c | 308 ++++++++++ os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.h | 210 +++++++ os/hal/ports/STM32/LLD/TIMv1/icu_lld.c | 805 -------------------------- os/hal/ports/STM32/LLD/TIMv1/icu_lld.h | 487 ---------------- os/hal/ports/STM32/LLD/TIMv1/pwm_lld.c | 858 --------------------------- os/hal/ports/STM32/LLD/TIMv1/pwm_lld.h | 550 ------------------ os/hal/ports/STM32/LLD/TIMv1/st_lld.c | 308 ---------- os/hal/ports/STM32/LLD/TIMv1/st_lld.h | 210 ------- 16 files changed, 4750 insertions(+), 4750 deletions(-) delete mode 100644 os/hal/ports/STM32/LLD/TIMv1/gpt_lld.c delete mode 100644 os/hal/ports/STM32/LLD/TIMv1/gpt_lld.h create mode 100644 os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.c create mode 100644 os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.h create mode 100644 os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.c create mode 100644 os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.h create mode 100644 os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.c create mode 100644 os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.h create mode 100644 os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.c create mode 100644 os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.h delete mode 100644 os/hal/ports/STM32/LLD/TIMv1/icu_lld.c delete mode 100644 os/hal/ports/STM32/LLD/TIMv1/icu_lld.h delete mode 100644 os/hal/ports/STM32/LLD/TIMv1/pwm_lld.c delete mode 100644 os/hal/ports/STM32/LLD/TIMv1/pwm_lld.h delete mode 100644 os/hal/ports/STM32/LLD/TIMv1/st_lld.c delete mode 100644 os/hal/ports/STM32/LLD/TIMv1/st_lld.h (limited to 'os/hal/ports/STM32/LLD/TIMv1') diff --git a/os/hal/ports/STM32/LLD/TIMv1/gpt_lld.c b/os/hal/ports/STM32/LLD/TIMv1/gpt_lld.c deleted file mode 100644 index fd2a804c1..000000000 --- a/os/hal/ports/STM32/LLD/TIMv1/gpt_lld.c +++ /dev/null @@ -1,891 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 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 "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. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_GPT_USE_TIM1 || defined(__DOXYGEN__) -#if !defined(STM32_TIM1_SUPPRESS_ISR) -#if !defined(STM32_TIM1_UP_HANDLER) -#error "STM32_TIM1_UP_HANDLER not defined" -#endif -/** - * @brief TIM2 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD1); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM1_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM1 */ - -#if STM32_GPT_USE_TIM2 || defined(__DOXYGEN__) -#if !defined(STM32_TIM2_SUPPRESS_ISR) -#if !defined(STM32_TIM2_HANDLER) -#error "STM32_TIM2_HANDLER not defined" -#endif -/** - * @brief TIM2 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM2_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD2); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM2_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM2 */ - -#if STM32_GPT_USE_TIM3 || defined(__DOXYGEN__) -#if !defined(STM32_TIM3_SUPPRESS_ISR) -#if !defined(STM32_TIM3_HANDLER) -#error "STM32_TIM3_HANDLER not defined" -#endif -/** - * @brief TIM3 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM3_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD3); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM3_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM3 */ - -#if STM32_GPT_USE_TIM4 || defined(__DOXYGEN__) -#if !defined(STM32_TIM4_SUPPRESS_ISR) -#if !defined(STM32_TIM4_HANDLER) -#error "STM32_TIM4_HANDLER not defined" -#endif -/** - * @brief TIM4 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM4_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD4); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM4_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM4 */ - -#if STM32_GPT_USE_TIM5 || defined(__DOXYGEN__) -#if !defined(STM32_TIM5_SUPPRESS_ISR) -#if !defined(STM32_TIM5_HANDLER) -#error "STM32_TIM5_HANDLER not defined" -#endif -/** - * @brief TIM5 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM5_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD5); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM5_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM5 */ - -#if STM32_GPT_USE_TIM6 || defined(__DOXYGEN__) -#if !defined(STM32_TIM6_SUPPRESS_ISR) -#if !defined(STM32_TIM6_HANDLER) -#error "STM32_TIM6_HANDLER not defined" -#endif -/** - * @brief TIM6 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM6_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD6); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM6_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM6 */ - -#if STM32_GPT_USE_TIM7 || defined(__DOXYGEN__) -#if !defined(STM32_TIM7_SUPPRESS_ISR) -#if !defined(STM32_TIM7_HANDLER) -#error "STM32_TIM7_HANDLER not defined" -#endif -/** - * @brief TIM7 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM7_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD7); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM7_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM7 */ - -#if STM32_GPT_USE_TIM8 || defined(__DOXYGEN__) -#if !defined(STM32_TIM8_SUPPRESS_ISR) -#if !defined(STM32_TIM8_UP_HANDLER) -#error "STM32_TIM8_UP_HANDLER not defined" -#endif -/** - * @brief TIM8 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD8); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM8_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM8 */ - -#if STM32_GPT_USE_TIM9 || defined(__DOXYGEN__) -#if !defined(STM32_TIM9_SUPPRESS_ISR) -#if !defined(STM32_TIM9_HANDLER) -#error "STM32_TIM9_HANDLER not defined" -#endif -/** - * @brief TIM9 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM9_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD9); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM9_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM9 */ - -#if STM32_GPT_USE_TIM11 || defined(__DOXYGEN__) -#if !defined(STM32_TIM11_SUPPRESS_ISR) -#if !defined(STM32_TIM11_HANDLER) -#error "STM32_TIM11_HANDLER not defined" -#endif -/** - * @brief TIM11 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM11_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD11); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM11_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM11 */ - -#if STM32_GPT_USE_TIM12 || defined(__DOXYGEN__) -#if !defined(STM32_TIM12_SUPPRESS_ISR) -#if !defined(STM32_TIM12_HANDLER) -#error "STM32_TIM12_HANDLER not defined" -#endif -/** - * @brief TIM12 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM12_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD12); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM12_SUPPRESS_ISR) */ -#endif /* STM32_GPT_USE_TIM12 */ - -#if STM32_GPT_USE_TIM14 || defined(__DOXYGEN__) -#if !defined(STM32_TIM14_SUPPRESS_ISR) -#if !defined(STM32_TIM14_HANDLER) -#error "STM32_TIM14_HANDLER not defined" -#endif -/** - * @brief TIM14 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM14_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD14); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM14_SUPPRESS_ISR) */ -#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(); -#if !defined(STM32_TIM1_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM1_UP_NUMBER, STM32_GPT_TIM1_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM1CLK) - gptp->clock = STM32_TIM1CLK; -#else - gptp->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_GPT_USE_TIM2 - if (&GPTD2 == gptp) { - rccEnableTIM2(FALSE); - rccResetTIM2(); -#if !defined(STM32_TIM2_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM2_NUMBER, STM32_GPT_TIM2_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM2CLK) - gptp->clock = STM32_TIM2CLK; -#else - gptp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_GPT_USE_TIM3 - if (&GPTD3 == gptp) { - rccEnableTIM3(FALSE); - rccResetTIM3(); -#if !defined(STM32_TIM3_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM3_NUMBER, STM32_GPT_TIM3_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM3CLK) - gptp->clock = STM32_TIM3CLK; -#else - gptp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_GPT_USE_TIM4 - if (&GPTD4 == gptp) { - rccEnableTIM4(FALSE); - rccResetTIM4(); -#if !defined(STM32_TIM4_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM4_NUMBER, STM32_GPT_TIM4_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM4CLK) - gptp->clock = STM32_TIM4CLK; -#else - gptp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_GPT_USE_TIM5 - if (&GPTD5 == gptp) { - rccEnableTIM5(FALSE); - rccResetTIM5(); -#if !defined(STM32_TIM5_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM5_NUMBER, STM32_GPT_TIM5_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM5CLK) - gptp->clock = STM32_TIM5CLK; -#else - gptp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_GPT_USE_TIM6 - if (&GPTD6 == gptp) { - rccEnableTIM6(FALSE); - rccResetTIM6(); -#if !defined(STM32_TIM6_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM6_NUMBER, STM32_GPT_TIM6_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM6CLK) - gptp->clock = STM32_TIM6CLK; -#else - gptp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_GPT_USE_TIM7 - if (&GPTD7 == gptp) { - rccEnableTIM7(FALSE); - rccResetTIM7(); -#if !defined(STM32_TIM7_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM7_NUMBER, STM32_GPT_TIM7_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM7CLK) - gptp->clock = STM32_TIM7CLK; -#else - gptp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_GPT_USE_TIM8 - if (&GPTD8 == gptp) { - rccEnableTIM8(FALSE); - rccResetTIM8(); -#if !defined(STM32_TIM8_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM8_UP_NUMBER, STM32_GPT_TIM8_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM8CLK) - gptp->clock = STM32_TIM8CLK; -#else - gptp->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_GPT_USE_TIM9 - if (&GPTD9 == gptp) { - rccEnableTIM9(FALSE); - rccResetTIM9(); -#if !defined(STM32_TIM9_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM9_NUMBER, STM32_GPT_TIM9_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM9CLK) - gptp->clock = STM32_TIM9CLK; -#else - gptp->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_GPT_USE_TIM11 - if (&GPTD11 == gptp) { - rccEnableTIM11(FALSE); - rccResetTIM11(); -#if !defined(STM32_TIM11_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM11_NUMBER, STM32_GPT_TIM11_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM11CLK) - gptp->clock = STM32_TIM11CLK; -#else - gptp->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_GPT_USE_TIM12 - if (&GPTD12 == gptp) { - rccEnableTIM12(FALSE); - rccResetTIM12(); -#if !defined(STM32_TIM12_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM12_NUMBER, STM32_GPT_TIM12_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM12CLK) - gptp->clock = STM32_TIM12CLK; -#else - gptp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_GPT_USE_TIM14 - if (&GPTD14 == gptp) { - rccEnableTIM14(FALSE); - rccResetTIM14(); -#if !defined(STM32_TIM14_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM14_NUMBER, STM32_GPT_TIM14_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM14CLK) - gptp->clock = STM32_TIM14CLK; -#else - gptp->clock = STM32_TIMCLK1; -#endif - } -#endif - } - - /* Prescaler value calculation.*/ - psc = (uint16_t)((gptp->clock / gptp->config->frequency) - 1); - osalDbgAssert(((uint32_t)(psc + 1) * gptp->config->frequency) == gptp->clock, - "invalid frequency"); - - /* Timer configuration.*/ - gptp->tim->CR1 = 0; /* Initially stopped. */ - gptp->tim->CR2 = gptp->config->cr2; - gptp->tim->PSC = psc; /* Prescaler value. */ - gptp->tim->SR = 0; /* Clear pending IRQs. */ - gptp->tim->DIER = gptp->config->dier & /* DMA-related DIER bits. */ - ~STM32_TIM_DIER_IRQ_MASK; -} - -/** - * @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 pending IRQs. */ - -#if STM32_GPT_USE_TIM1 - if (&GPTD1 == gptp) { -#if !defined(STM32_TIM1_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM1_UP_NUMBER); -#endif - rccDisableTIM1(FALSE); - } -#endif - -#if STM32_GPT_USE_TIM2 - if (&GPTD2 == gptp) { -#if !defined(STM32_TIM2_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM2_NUMBER); -#endif - rccDisableTIM2(FALSE); - } -#endif - -#if STM32_GPT_USE_TIM3 - if (&GPTD3 == gptp) { -#if !defined(STM32_TIM3_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM3_NUMBER); -#endif - rccDisableTIM3(FALSE); - } -#endif - -#if STM32_GPT_USE_TIM4 - if (&GPTD4 == gptp) { -#if !defined(STM32_TIM4_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM4_NUMBER); -#endif - rccDisableTIM4(FALSE); - } -#endif - -#if STM32_GPT_USE_TIM5 - if (&GPTD5 == gptp) { -#if !defined(STM32_TIM5_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM5_NUMBER); -#endif - rccDisableTIM5(FALSE); - } -#endif - -#if STM32_GPT_USE_TIM6 - if (&GPTD6 == gptp) { -#if !defined(STM32_TIM6_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM6_NUMBER); -#endif - rccDisableTIM6(FALSE); - } -#endif - -#if STM32_GPT_USE_TIM7 - if (&GPTD7 == gptp) { -#if !defined(STM32_TIM7_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM7_NUMBER); -#endif - rccDisableTIM7(FALSE); - } -#endif - -#if STM32_GPT_USE_TIM8 - if (&GPTD8 == gptp) { -#if !defined(STM32_TIM8_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM8_UP_NUMBER); -#endif - rccDisableTIM8(FALSE); - } -#endif - -#if STM32_GPT_USE_TIM9 - if (&GPTD9 == gptp) { -#if !defined(STM32_TIM9_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM9_NUMBER); -#endif - rccDisableTIM9(FALSE); - } -#endif - -#if STM32_GPT_USE_TIM11 - if (&GPTD11 == gptp) { -#if !defined(STM32_TIM11_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM11_NUMBER); -#endif - rccDisableTIM11(FALSE); - } -#endif - -#if STM32_GPT_USE_TIM12 - if (&GPTD12 == gptp) { -#if !defined(STM32_TIM12_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM12_NUMBER); -#endif - rccDisableTIM12(FALSE); - } -#endif - -#if STM32_GPT_USE_TIM14 - if (&GPTD14 == gptp) { -#if !defined(STM32_TIM14_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM14_NUMBER); -#endif - 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 = (uint32_t)(interval - 1); /* Time constant. */ - gptp->tim->EGR = STM32_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 (NULL != gptp->config->callback) - gptp->tim->DIER |= STM32_TIM_DIER_UIE; /* Update Event IRQ enabled.*/ - gptp->tim->CR1 = STM32_TIM_CR1_URS | STM32_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. */ - - /* All interrupts disabled.*/ - gptp->tim->DIER &= ~STM32_TIM_DIER_IRQ_MASK; -} - -/** - * @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 = (uint32_t)(interval - 1); /* Time constant. */ - gptp->tim->EGR = STM32_TIM_EGR_UG; /* Update event. */ - gptp->tim->CR1 = STM32_TIM_CR1_OPM | STM32_TIM_CR1_URS | STM32_TIM_CR1_CEN; - while (!(gptp->tim->SR & STM32_TIM_SR_UIF)) - ; - gptp->tim->SR = 0; /* Clear pending IRQs. */ -} - -/** - * @brief Shared IRQ handler. - * - * @param[in] gptp pointer to a @p GPTDriver object - * - * @notapi - */ -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); -} - -#endif /* HAL_USE_GPT */ - -/** @} */ diff --git a/os/hal/ports/STM32/LLD/TIMv1/gpt_lld.h b/os/hal/ports/STM32/LLD/TIMv1/gpt_lld.h deleted file mode 100644 index 526514a10..000000000 --- a/os/hal/ports/STM32/LLD/TIMv1/gpt_lld.h +++ /dev/null @@ -1,641 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 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_ - -#include "stm32_tim.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 - -/* Checks on allocation of TIMx units.*/ -#if STM32_GPT_USE_TIM1 -#if defined(STM32_TIM1_IS_USED) -#error "GPTD1 requires TIM1 but the timer is already used" -#else -#define STM32_TIM1_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM2 -#if defined(STM32_TIM2_IS_USED) -#error "GPTD2 requires TIM2 but the timer is already used" -#else -#define STM32_TIM2_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM3 -#if defined(STM32_TIM3_IS_USED) -#error "GPTD3 requires TIM3 but the timer is already used" -#else -#define STM32_TIM3_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM4 -#if defined(STM32_TIM4_IS_USED) -#error "GPTD4 requires TIM4 but the timer is already used" -#else -#define STM32_TIM4_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM5 -#if defined(STM32_TIM5_IS_USED) -#error "GPTD5 requires TIM5 but the timer is already used" -#else -#define STM32_TIM5_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM6 -#if defined(STM32_TIM6_IS_USED) -#error "GPTD6 requires TIM6 but the timer is already used" -#else -#define STM32_TIM6_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM7 -#if defined(STM32_TIM7_IS_USED) -#error "GPTD7 requires TIM7 but the timer is already used" -#else -#define STM32_TIM7_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM8 -#if defined(STM32_TIM8_IS_USED) -#error "GPTD8 requires TIM8 but the timer is already used" -#else -#define STM32_TIM8_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM9 -#if defined(STM32_TIM9_IS_USED) -#error "GPTD9 requires TIM9 but the timer is already used" -#else -#define STM32_TIM9_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM11 -#if defined(STM32_TIM11_IS_USED) -#error "GPTD11 requires TIM11 but the timer is already used" -#else -#define STM32_TIM11_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM12 -#if defined(STM32_TIM12_IS_USED) -#error "GPTD12 requires TIM12 but the timer is already used" -#else -#define STM32_TIM12_IS_USED -#endif -#endif - -#if STM32_GPT_USE_TIM14 -#if defined(STM32_TIM14_IS_USED) -#error "GPTD14 requires TIM14 but the timer is already used" -#else -#define STM32_TIM14_IS_USED -#endif -#endif - -/* IRQ priority checks.*/ -#if STM32_GPT_USE_TIM1 && !defined(STM32_TIM1_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM1" -#endif - -#if STM32_GPT_USE_TIM2 && !defined(STM32_TIM2_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM2" -#endif - -#if STM32_GPT_USE_TIM3 && !defined(STM32_TIM3_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM3" -#endif - -#if STM32_GPT_USE_TIM4 && !defined(STM32_TIM_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM4_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM4" -#endif - -#if STM32_GPT_USE_TIM5 && !defined(STM32_TIM5_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM5_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM5" -#endif - -#if STM32_GPT_USE_TIM6 && !defined(STM32_TIM6_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM6_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM6" -#endif - -#if STM32_GPT_USE_TIM7 && !defined(STM32_TIM7_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM7_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM7" -#endif - -#if STM32_GPT_USE_TIM8 && !defined(STM32_TIM8_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM8_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM8" -#endif - -#if STM32_GPT_USE_TIM9 && !defined(STM32_TIM9_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM9_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM9" -#endif - -#if STM32_GPT_USE_TIM11 && !defined(STM32_TIM11_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM11_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM11" -#endif - -#if STM32_GPT_USE_TIM12 && !defined(STM32_TIM12_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM12_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM12" -#endif - -#if STM32_GPT_USE_TIM14 && !defined(STM32_TIM14_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_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 uint32_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. - * @note This callback can be set to @p NULL but in that case the - * one-shot mode cannot be used. - */ - gptcallback_t callback; - /* End of the mandatory fields.*/ - /** - * @brief TIM CR2 register initialization data. - * @note The value of this field should normally be equal to zero. - */ - uint32_t cr2; - /** - * @brief TIM DIER register initialization data. - * @note The value of this field should normally be equal to zero. - * @note Only the DMA-related bits can be specified in this field. - */ - uint32_t dier; -} 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 be running in continuous mode. - * @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 = (uint32_t)((interval) - 1)) - -/** - * @brief Returns the interval of GPT peripheral. - * @pre The GPT unit must be running in continuous mode. - * - * @param[in] gptp pointer to a @p GPTDriver object - * @return The current interval. - * - * @notapi - */ -#define gpt_lld_get_interval(gptp) ((gptcnt_t)(gptp)->tim->ARR + 1) - -/** - * @brief Returns the counter value of GPT peripheral. - * @pre The GPT unit must be running in continuous mode. - * @note The nature of the counter is not defined, it may count upward - * or downward, it could be continuously running or not. - * - * @param[in] gptp pointer to a @p GPTDriver object - * @return The current counter value. - * - * @notapi - */ -#define gpt_lld_get_counter(gptp) ((gptcnt_t)(gptp)->tim->CNT) - -/*===========================================================================*/ -/* 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); - void gpt_lld_serve_interrupt(GPTDriver *gptp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_GPT */ - -#endif /* _GPT_LLD_H_ */ - -/** @} */ diff --git a/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.c b/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.c new file mode 100644 index 000000000..fd2a804c1 --- /dev/null +++ b/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.c @@ -0,0 +1,891 @@ +/* + ChibiOS - Copyright (C) 2006..2016 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 "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. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_GPT_USE_TIM1 || defined(__DOXYGEN__) +#if !defined(STM32_TIM1_SUPPRESS_ISR) +#if !defined(STM32_TIM1_UP_HANDLER) +#error "STM32_TIM1_UP_HANDLER not defined" +#endif +/** + * @brief TIM2 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD1); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM1_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM1 */ + +#if STM32_GPT_USE_TIM2 || defined(__DOXYGEN__) +#if !defined(STM32_TIM2_SUPPRESS_ISR) +#if !defined(STM32_TIM2_HANDLER) +#error "STM32_TIM2_HANDLER not defined" +#endif +/** + * @brief TIM2 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD2); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM2_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM2 */ + +#if STM32_GPT_USE_TIM3 || defined(__DOXYGEN__) +#if !defined(STM32_TIM3_SUPPRESS_ISR) +#if !defined(STM32_TIM3_HANDLER) +#error "STM32_TIM3_HANDLER not defined" +#endif +/** + * @brief TIM3 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM3_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD3); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM3_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM3 */ + +#if STM32_GPT_USE_TIM4 || defined(__DOXYGEN__) +#if !defined(STM32_TIM4_SUPPRESS_ISR) +#if !defined(STM32_TIM4_HANDLER) +#error "STM32_TIM4_HANDLER not defined" +#endif +/** + * @brief TIM4 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM4_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD4); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM4_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM4 */ + +#if STM32_GPT_USE_TIM5 || defined(__DOXYGEN__) +#if !defined(STM32_TIM5_SUPPRESS_ISR) +#if !defined(STM32_TIM5_HANDLER) +#error "STM32_TIM5_HANDLER not defined" +#endif +/** + * @brief TIM5 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM5_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD5); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM5_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM5 */ + +#if STM32_GPT_USE_TIM6 || defined(__DOXYGEN__) +#if !defined(STM32_TIM6_SUPPRESS_ISR) +#if !defined(STM32_TIM6_HANDLER) +#error "STM32_TIM6_HANDLER not defined" +#endif +/** + * @brief TIM6 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM6_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD6); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM6_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM6 */ + +#if STM32_GPT_USE_TIM7 || defined(__DOXYGEN__) +#if !defined(STM32_TIM7_SUPPRESS_ISR) +#if !defined(STM32_TIM7_HANDLER) +#error "STM32_TIM7_HANDLER not defined" +#endif +/** + * @brief TIM7 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM7_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD7); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM7_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM7 */ + +#if STM32_GPT_USE_TIM8 || defined(__DOXYGEN__) +#if !defined(STM32_TIM8_SUPPRESS_ISR) +#if !defined(STM32_TIM8_UP_HANDLER) +#error "STM32_TIM8_UP_HANDLER not defined" +#endif +/** + * @brief TIM8 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD8); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM8_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM8 */ + +#if STM32_GPT_USE_TIM9 || defined(__DOXYGEN__) +#if !defined(STM32_TIM9_SUPPRESS_ISR) +#if !defined(STM32_TIM9_HANDLER) +#error "STM32_TIM9_HANDLER not defined" +#endif +/** + * @brief TIM9 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM9_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD9); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM9_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM9 */ + +#if STM32_GPT_USE_TIM11 || defined(__DOXYGEN__) +#if !defined(STM32_TIM11_SUPPRESS_ISR) +#if !defined(STM32_TIM11_HANDLER) +#error "STM32_TIM11_HANDLER not defined" +#endif +/** + * @brief TIM11 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM11_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD11); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM11_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM11 */ + +#if STM32_GPT_USE_TIM12 || defined(__DOXYGEN__) +#if !defined(STM32_TIM12_SUPPRESS_ISR) +#if !defined(STM32_TIM12_HANDLER) +#error "STM32_TIM12_HANDLER not defined" +#endif +/** + * @brief TIM12 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM12_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD12); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM12_SUPPRESS_ISR) */ +#endif /* STM32_GPT_USE_TIM12 */ + +#if STM32_GPT_USE_TIM14 || defined(__DOXYGEN__) +#if !defined(STM32_TIM14_SUPPRESS_ISR) +#if !defined(STM32_TIM14_HANDLER) +#error "STM32_TIM14_HANDLER not defined" +#endif +/** + * @brief TIM14 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM14_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD14); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM14_SUPPRESS_ISR) */ +#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(); +#if !defined(STM32_TIM1_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM1_UP_NUMBER, STM32_GPT_TIM1_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM1CLK) + gptp->clock = STM32_TIM1CLK; +#else + gptp->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_GPT_USE_TIM2 + if (&GPTD2 == gptp) { + rccEnableTIM2(FALSE); + rccResetTIM2(); +#if !defined(STM32_TIM2_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM2_NUMBER, STM32_GPT_TIM2_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM2CLK) + gptp->clock = STM32_TIM2CLK; +#else + gptp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_GPT_USE_TIM3 + if (&GPTD3 == gptp) { + rccEnableTIM3(FALSE); + rccResetTIM3(); +#if !defined(STM32_TIM3_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM3_NUMBER, STM32_GPT_TIM3_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM3CLK) + gptp->clock = STM32_TIM3CLK; +#else + gptp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_GPT_USE_TIM4 + if (&GPTD4 == gptp) { + rccEnableTIM4(FALSE); + rccResetTIM4(); +#if !defined(STM32_TIM4_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM4_NUMBER, STM32_GPT_TIM4_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM4CLK) + gptp->clock = STM32_TIM4CLK; +#else + gptp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_GPT_USE_TIM5 + if (&GPTD5 == gptp) { + rccEnableTIM5(FALSE); + rccResetTIM5(); +#if !defined(STM32_TIM5_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM5_NUMBER, STM32_GPT_TIM5_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM5CLK) + gptp->clock = STM32_TIM5CLK; +#else + gptp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_GPT_USE_TIM6 + if (&GPTD6 == gptp) { + rccEnableTIM6(FALSE); + rccResetTIM6(); +#if !defined(STM32_TIM6_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM6_NUMBER, STM32_GPT_TIM6_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM6CLK) + gptp->clock = STM32_TIM6CLK; +#else + gptp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_GPT_USE_TIM7 + if (&GPTD7 == gptp) { + rccEnableTIM7(FALSE); + rccResetTIM7(); +#if !defined(STM32_TIM7_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM7_NUMBER, STM32_GPT_TIM7_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM7CLK) + gptp->clock = STM32_TIM7CLK; +#else + gptp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_GPT_USE_TIM8 + if (&GPTD8 == gptp) { + rccEnableTIM8(FALSE); + rccResetTIM8(); +#if !defined(STM32_TIM8_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM8_UP_NUMBER, STM32_GPT_TIM8_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM8CLK) + gptp->clock = STM32_TIM8CLK; +#else + gptp->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_GPT_USE_TIM9 + if (&GPTD9 == gptp) { + rccEnableTIM9(FALSE); + rccResetTIM9(); +#if !defined(STM32_TIM9_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM9_NUMBER, STM32_GPT_TIM9_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM9CLK) + gptp->clock = STM32_TIM9CLK; +#else + gptp->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_GPT_USE_TIM11 + if (&GPTD11 == gptp) { + rccEnableTIM11(FALSE); + rccResetTIM11(); +#if !defined(STM32_TIM11_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM11_NUMBER, STM32_GPT_TIM11_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM11CLK) + gptp->clock = STM32_TIM11CLK; +#else + gptp->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_GPT_USE_TIM12 + if (&GPTD12 == gptp) { + rccEnableTIM12(FALSE); + rccResetTIM12(); +#if !defined(STM32_TIM12_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM12_NUMBER, STM32_GPT_TIM12_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM12CLK) + gptp->clock = STM32_TIM12CLK; +#else + gptp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_GPT_USE_TIM14 + if (&GPTD14 == gptp) { + rccEnableTIM14(FALSE); + rccResetTIM14(); +#if !defined(STM32_TIM14_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM14_NUMBER, STM32_GPT_TIM14_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM14CLK) + gptp->clock = STM32_TIM14CLK; +#else + gptp->clock = STM32_TIMCLK1; +#endif + } +#endif + } + + /* Prescaler value calculation.*/ + psc = (uint16_t)((gptp->clock / gptp->config->frequency) - 1); + osalDbgAssert(((uint32_t)(psc + 1) * gptp->config->frequency) == gptp->clock, + "invalid frequency"); + + /* Timer configuration.*/ + gptp->tim->CR1 = 0; /* Initially stopped. */ + gptp->tim->CR2 = gptp->config->cr2; + gptp->tim->PSC = psc; /* Prescaler value. */ + gptp->tim->SR = 0; /* Clear pending IRQs. */ + gptp->tim->DIER = gptp->config->dier & /* DMA-related DIER bits. */ + ~STM32_TIM_DIER_IRQ_MASK; +} + +/** + * @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 pending IRQs. */ + +#if STM32_GPT_USE_TIM1 + if (&GPTD1 == gptp) { +#if !defined(STM32_TIM1_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM1_UP_NUMBER); +#endif + rccDisableTIM1(FALSE); + } +#endif + +#if STM32_GPT_USE_TIM2 + if (&GPTD2 == gptp) { +#if !defined(STM32_TIM2_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM2_NUMBER); +#endif + rccDisableTIM2(FALSE); + } +#endif + +#if STM32_GPT_USE_TIM3 + if (&GPTD3 == gptp) { +#if !defined(STM32_TIM3_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM3_NUMBER); +#endif + rccDisableTIM3(FALSE); + } +#endif + +#if STM32_GPT_USE_TIM4 + if (&GPTD4 == gptp) { +#if !defined(STM32_TIM4_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM4_NUMBER); +#endif + rccDisableTIM4(FALSE); + } +#endif + +#if STM32_GPT_USE_TIM5 + if (&GPTD5 == gptp) { +#if !defined(STM32_TIM5_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM5_NUMBER); +#endif + rccDisableTIM5(FALSE); + } +#endif + +#if STM32_GPT_USE_TIM6 + if (&GPTD6 == gptp) { +#if !defined(STM32_TIM6_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM6_NUMBER); +#endif + rccDisableTIM6(FALSE); + } +#endif + +#if STM32_GPT_USE_TIM7 + if (&GPTD7 == gptp) { +#if !defined(STM32_TIM7_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM7_NUMBER); +#endif + rccDisableTIM7(FALSE); + } +#endif + +#if STM32_GPT_USE_TIM8 + if (&GPTD8 == gptp) { +#if !defined(STM32_TIM8_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM8_UP_NUMBER); +#endif + rccDisableTIM8(FALSE); + } +#endif + +#if STM32_GPT_USE_TIM9 + if (&GPTD9 == gptp) { +#if !defined(STM32_TIM9_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM9_NUMBER); +#endif + rccDisableTIM9(FALSE); + } +#endif + +#if STM32_GPT_USE_TIM11 + if (&GPTD11 == gptp) { +#if !defined(STM32_TIM11_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM11_NUMBER); +#endif + rccDisableTIM11(FALSE); + } +#endif + +#if STM32_GPT_USE_TIM12 + if (&GPTD12 == gptp) { +#if !defined(STM32_TIM12_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM12_NUMBER); +#endif + rccDisableTIM12(FALSE); + } +#endif + +#if STM32_GPT_USE_TIM14 + if (&GPTD14 == gptp) { +#if !defined(STM32_TIM14_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM14_NUMBER); +#endif + 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 = (uint32_t)(interval - 1); /* Time constant. */ + gptp->tim->EGR = STM32_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 (NULL != gptp->config->callback) + gptp->tim->DIER |= STM32_TIM_DIER_UIE; /* Update Event IRQ enabled.*/ + gptp->tim->CR1 = STM32_TIM_CR1_URS | STM32_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. */ + + /* All interrupts disabled.*/ + gptp->tim->DIER &= ~STM32_TIM_DIER_IRQ_MASK; +} + +/** + * @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 = (uint32_t)(interval - 1); /* Time constant. */ + gptp->tim->EGR = STM32_TIM_EGR_UG; /* Update event. */ + gptp->tim->CR1 = STM32_TIM_CR1_OPM | STM32_TIM_CR1_URS | STM32_TIM_CR1_CEN; + while (!(gptp->tim->SR & STM32_TIM_SR_UIF)) + ; + gptp->tim->SR = 0; /* Clear pending IRQs. */ +} + +/** + * @brief Shared IRQ handler. + * + * @param[in] gptp pointer to a @p GPTDriver object + * + * @notapi + */ +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); +} + +#endif /* HAL_USE_GPT */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.h b/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.h new file mode 100644 index 000000000..526514a10 --- /dev/null +++ b/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.h @@ -0,0 +1,641 @@ +/* + ChibiOS - Copyright (C) 2006..2016 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_ + +#include "stm32_tim.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 + +/* Checks on allocation of TIMx units.*/ +#if STM32_GPT_USE_TIM1 +#if defined(STM32_TIM1_IS_USED) +#error "GPTD1 requires TIM1 but the timer is already used" +#else +#define STM32_TIM1_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM2 +#if defined(STM32_TIM2_IS_USED) +#error "GPTD2 requires TIM2 but the timer is already used" +#else +#define STM32_TIM2_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM3 +#if defined(STM32_TIM3_IS_USED) +#error "GPTD3 requires TIM3 but the timer is already used" +#else +#define STM32_TIM3_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM4 +#if defined(STM32_TIM4_IS_USED) +#error "GPTD4 requires TIM4 but the timer is already used" +#else +#define STM32_TIM4_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM5 +#if defined(STM32_TIM5_IS_USED) +#error "GPTD5 requires TIM5 but the timer is already used" +#else +#define STM32_TIM5_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM6 +#if defined(STM32_TIM6_IS_USED) +#error "GPTD6 requires TIM6 but the timer is already used" +#else +#define STM32_TIM6_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM7 +#if defined(STM32_TIM7_IS_USED) +#error "GPTD7 requires TIM7 but the timer is already used" +#else +#define STM32_TIM7_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM8 +#if defined(STM32_TIM8_IS_USED) +#error "GPTD8 requires TIM8 but the timer is already used" +#else +#define STM32_TIM8_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM9 +#if defined(STM32_TIM9_IS_USED) +#error "GPTD9 requires TIM9 but the timer is already used" +#else +#define STM32_TIM9_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM11 +#if defined(STM32_TIM11_IS_USED) +#error "GPTD11 requires TIM11 but the timer is already used" +#else +#define STM32_TIM11_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM12 +#if defined(STM32_TIM12_IS_USED) +#error "GPTD12 requires TIM12 but the timer is already used" +#else +#define STM32_TIM12_IS_USED +#endif +#endif + +#if STM32_GPT_USE_TIM14 +#if defined(STM32_TIM14_IS_USED) +#error "GPTD14 requires TIM14 but the timer is already used" +#else +#define STM32_TIM14_IS_USED +#endif +#endif + +/* IRQ priority checks.*/ +#if STM32_GPT_USE_TIM1 && !defined(STM32_TIM1_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM1" +#endif + +#if STM32_GPT_USE_TIM2 && !defined(STM32_TIM2_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM2" +#endif + +#if STM32_GPT_USE_TIM3 && !defined(STM32_TIM3_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM3" +#endif + +#if STM32_GPT_USE_TIM4 && !defined(STM32_TIM_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM4_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM4" +#endif + +#if STM32_GPT_USE_TIM5 && !defined(STM32_TIM5_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM5_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM5" +#endif + +#if STM32_GPT_USE_TIM6 && !defined(STM32_TIM6_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM6_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM6" +#endif + +#if STM32_GPT_USE_TIM7 && !defined(STM32_TIM7_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM7_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM7" +#endif + +#if STM32_GPT_USE_TIM8 && !defined(STM32_TIM8_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM8_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM8" +#endif + +#if STM32_GPT_USE_TIM9 && !defined(STM32_TIM9_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM9_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM9" +#endif + +#if STM32_GPT_USE_TIM11 && !defined(STM32_TIM11_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM11_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM11" +#endif + +#if STM32_GPT_USE_TIM12 && !defined(STM32_TIM12_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM12_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM12" +#endif + +#if STM32_GPT_USE_TIM14 && !defined(STM32_TIM14_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_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 uint32_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. + * @note This callback can be set to @p NULL but in that case the + * one-shot mode cannot be used. + */ + gptcallback_t callback; + /* End of the mandatory fields.*/ + /** + * @brief TIM CR2 register initialization data. + * @note The value of this field should normally be equal to zero. + */ + uint32_t cr2; + /** + * @brief TIM DIER register initialization data. + * @note The value of this field should normally be equal to zero. + * @note Only the DMA-related bits can be specified in this field. + */ + uint32_t dier; +} 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 be running in continuous mode. + * @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 = (uint32_t)((interval) - 1)) + +/** + * @brief Returns the interval of GPT peripheral. + * @pre The GPT unit must be running in continuous mode. + * + * @param[in] gptp pointer to a @p GPTDriver object + * @return The current interval. + * + * @notapi + */ +#define gpt_lld_get_interval(gptp) ((gptcnt_t)(gptp)->tim->ARR + 1) + +/** + * @brief Returns the counter value of GPT peripheral. + * @pre The GPT unit must be running in continuous mode. + * @note The nature of the counter is not defined, it may count upward + * or downward, it could be continuously running or not. + * + * @param[in] gptp pointer to a @p GPTDriver object + * @return The current counter value. + * + * @notapi + */ +#define gpt_lld_get_counter(gptp) ((gptcnt_t)(gptp)->tim->CNT) + +/*===========================================================================*/ +/* 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); + void gpt_lld_serve_interrupt(GPTDriver *gptp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_GPT */ + +#endif /* _GPT_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.c b/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.c new file mode 100644 index 000000000..f7554241b --- /dev/null +++ b/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.c @@ -0,0 +1,805 @@ +/* + ChibiOS - Copyright (C) 2006..2016 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 "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. */ +/*===========================================================================*/ + +static bool icu_lld_wait_edge(ICUDriver *icup) { + uint32_t sr; + bool result; + + /* Polled mode so re-enabling the interrupts while the operation is + performed.*/ + osalSysUnlock(); + + /* Polling the right bit depending on the input channel.*/ + if (icup->config->channel == ICU_CHANNEL_1) { + /* Waiting for an edge.*/ + while (((sr = icup->tim->SR) & + (STM32_TIM_SR_CC1IF | STM32_TIM_SR_UIF)) == 0) + ; + } + else { + /* Waiting for an edge.*/ + while (((sr = icup->tim->SR) & + (STM32_TIM_SR_CC2IF | STM32_TIM_SR_UIF)) == 0) + ; + } + + /* Edge or overflow?*/ + result = (sr & STM32_TIM_SR_UIF) != 0 ? true : false; + + /* Done, disabling interrupts again.*/ + osalSysLock(); + + /* Resetting all flags.*/ + icup->tim->SR &= ~(STM32_TIM_SR_CC1IF | + STM32_TIM_SR_CC2IF | + STM32_TIM_SR_UIF); + + return result; +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_ICU_USE_TIM1 || defined(__DOXYGEN__) +#if !defined(STM32_TIM1_SUPPRESS_ISR) +#if !defined(STM32_TIM1_UP_HANDLER) +#error "STM32_TIM1_UP_HANDLER not defined" +#endif +/** + * @brief TIM1 compare interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD1); + + OSAL_IRQ_EPILOGUE(); +} + +#if !defined(STM32_TIM1_CC_HANDLER) +#error "STM32_TIM1_CC_HANDLER not defined" +#endif +/** + * @brief TIM1 compare interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM1_CC_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD1); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM1_SUPPRESS_ISR) */ +#endif /* STM32_ICU_USE_TIM1 */ + +#if STM32_ICU_USE_TIM2 || defined(__DOXYGEN__) +#if !defined(STM32_TIM2_SUPPRESS_ISR) +#if !defined(STM32_TIM2_HANDLER) +#error "STM32_TIM2_HANDLER not defined" +#endif +/** + * @brief TIM2 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD2); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM2_SUPPRESS_ISR) */ +#endif /* STM32_ICU_USE_TIM2 */ + +#if STM32_ICU_USE_TIM3 || defined(__DOXYGEN__) +#if !defined(STM32_TIM3_SUPPRESS_ISR) +#if !defined(STM32_TIM3_HANDLER) +#error "STM32_TIM3_HANDLER not defined" +#endif +/** + * @brief TIM3 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM3_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD3); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM3_SUPPRESS_ISR) */ +#endif /* STM32_ICU_USE_TIM3 */ + +#if STM32_ICU_USE_TIM4 || defined(__DOXYGEN__) +#if !defined(STM32_TIM4_SUPPRESS_ISR) +#if !defined(STM32_TIM4_HANDLER) +#error "STM32_TIM4_HANDLER not defined" +#endif +/** + * @brief TIM4 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM4_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD4); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM4_SUPPRESS_ISR) */ +#endif /* STM32_ICU_USE_TIM4 */ + +#if STM32_ICU_USE_TIM5 || defined(__DOXYGEN__) +#if !defined(STM32_TIM5_SUPPRESS_ISR) +#if !defined(STM32_TIM5_HANDLER) +#error "STM32_TIM5_HANDLER not defined" +#endif +/** + * @brief TIM5 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM5_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD5); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM5_SUPPRESS_ISR) */ +#endif /* STM32_ICU_USE_TIM5 */ + +#if STM32_ICU_USE_TIM8 || defined(__DOXYGEN__) +#if !defined(STM32_TIM8_SUPPRESS_ISR) +#if !defined(STM32_TIM8_UP_HANDLER) +#error "STM32_TIM8_UP_HANDLER not defined" +#endif +/** + * @brief TIM8 compare interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD8); + + OSAL_IRQ_EPILOGUE(); +} + +#if !defined(STM32_TIM8_CC_HANDLER) +#error "STM32_TIM8_CC_HANDLER not defined" +#endif +/** + * @brief TIM8 compare interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM8_CC_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD8); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM8_SUPPRESS_ISR) */ +#endif /* STM32_ICU_USE_TIM8 */ + +#if STM32_ICU_USE_TIM9 || defined(__DOXYGEN__) +#if !defined(STM32_TIM9_SUPPRESS_ISR) +#if !defined(STM32_TIM9_HANDLER) +#error "STM32_TIM9_HANDLER not defined" +#endif +/** + * @brief TIM9 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM9_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + icu_lld_serve_interrupt(&ICUD9); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM9_SUPPRESS_ISR) */ +#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; + + osalDbgAssert((icup->config->channel == ICU_CHANNEL_1) || + (icup->config->channel == ICU_CHANNEL_2), + "invalid input"); + + if (icup->state == ICU_STOP) { + /* Clock activation and timer reset.*/ +#if STM32_ICU_USE_TIM1 + if (&ICUD1 == icup) { + rccEnableTIM1(FALSE); + rccResetTIM1(); +#if !defined(STM32_TIM1_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM1_UP_NUMBER, STM32_ICU_TIM1_IRQ_PRIORITY); + nvicEnableVector(STM32_TIM1_CC_NUMBER, STM32_ICU_TIM1_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM1CLK) + icup->clock = STM32_TIM1CLK; +#else + icup->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_ICU_USE_TIM2 + if (&ICUD2 == icup) { + rccEnableTIM2(FALSE); + rccResetTIM2(); +#if !defined(STM32_TIM2_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM2_NUMBER, STM32_ICU_TIM2_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM2CLK) + icup->clock = STM32_TIM2CLK; +#else + icup->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_ICU_USE_TIM3 + if (&ICUD3 == icup) { + rccEnableTIM3(FALSE); + rccResetTIM3(); +#if !defined(STM32_TIM3_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM3_NUMBER, STM32_ICU_TIM3_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM3CLK) + icup->clock = STM32_TIM3CLK; +#else + icup->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_ICU_USE_TIM4 + if (&ICUD4 == icup) { + rccEnableTIM4(FALSE); + rccResetTIM4(); +#if !defined(STM32_TIM4_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM4_NUMBER, STM32_ICU_TIM4_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM4CLK) + icup->clock = STM32_TIM4CLK; +#else + icup->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_ICU_USE_TIM5 + if (&ICUD5 == icup) { + rccEnableTIM5(FALSE); + rccResetTIM5(); +#if !defined(STM32_TIM5_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM5_NUMBER, STM32_ICU_TIM5_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM5CLK) + icup->clock = STM32_TIM5CLK; +#else + icup->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_ICU_USE_TIM8 + if (&ICUD8 == icup) { + rccEnableTIM8(FALSE); + rccResetTIM8(); +#if !defined(STM32_TIM8_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM8_UP_NUMBER, STM32_ICU_TIM8_IRQ_PRIORITY); + nvicEnableVector(STM32_TIM8_CC_NUMBER, STM32_ICU_TIM8_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM8CLK) + icup->clock = STM32_TIM8CLK; +#else + icup->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_ICU_USE_TIM9 + if (&ICUD9 == icup) { + rccEnableTIM9(FALSE); + rccResetTIM9(); +#if !defined(STM32_TIM9_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM9_NUMBER, STM32_ICU_TIM9_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM9CLK) + icup->clock = STM32_TIM9CLK; +#else + icup->clock = STM32_TIMCLK2; +#endif + } +#endif + } + else { + /* Driver re-configuration scenario, it must be stopped first.*/ + icup->tim->CR1 = 0; /* Timer disabled. */ + 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.*/ + icup->tim->SR = 0; /* Clear eventual pending IRQs. */ + icup->tim->DIER = icup->config->dier & /* DMA-related DIER settings. */ + ~STM32_TIM_DIER_IRQ_MASK; + psc = (icup->clock / icup->config->frequency) - 1; + osalDbgAssert((psc <= 0xFFFF) && + ((psc + 1) * icup->config->frequency) == icup->clock, + "invalid frequency"); + icup->tim->PSC = 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) { +#if !defined(STM32_TIM1_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM1_UP_NUMBER); + nvicDisableVector(STM32_TIM1_CC_NUMBER); +#endif + rccDisableTIM1(FALSE); + } +#endif + +#if STM32_ICU_USE_TIM2 + if (&ICUD2 == icup) { +#if !defined(STM32_TIM2_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM2_NUMBER); +#endif + rccDisableTIM2(FALSE); + } +#endif + +#if STM32_ICU_USE_TIM3 + if (&ICUD3 == icup) { +#if !defined(STM32_TIM3_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM3_NUMBER); +#endif + rccDisableTIM3(FALSE); + } +#endif + +#if STM32_ICU_USE_TIM4 + if (&ICUD4 == icup) { +#if !defined(STM32_TIM4_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM4_NUMBER); +#endif + rccDisableTIM4(FALSE); + } +#endif + +#if STM32_ICU_USE_TIM5 + if (&ICUD5 == icup) { +#if !defined(STM32_TIM5_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM5_NUMBER); +#endif + rccDisableTIM5(FALSE); + } +#endif + +#if STM32_ICU_USE_TIM8 + if (&ICUD8 == icup) { +#if !defined(STM32_TIM8_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM8_UP_NUMBER); + nvicDisableVector(STM32_TIM8_CC_NUMBER); +#endif + rccDisableTIM8(FALSE); + } +#endif + +#if STM32_ICU_USE_TIM9 + if (&ICUD9 == icup) { +#if !defined(STM32_TIM9_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM9_NUMBER); +#endif + rccDisableTIM9(FALSE); + } +#endif + } +} + +/** + * @brief Starts the input capture. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @notapi + */ +void icu_lld_start_capture(ICUDriver *icup) { + + /* Triggering an UG and clearing the IRQ status.*/ + icup->tim->EGR |= STM32_TIM_EGR_UG; + icup->tim->SR = 0; + + /* Timer is started.*/ + icup->tim->CR1 = STM32_TIM_CR1_URS | STM32_TIM_CR1_CEN; +} + +/** + * @brief Waits for a completed capture. + * @note The operation is performed in polled mode. + * @note In order to use this function notifications must be disabled. + * + * @param[in] icup pointer to the @p ICUDriver object + * @return The capture status. + * @retval false if the capture is successful. + * @retval true if a timer overflow occurred. + * + * @notapi + */ +bool icu_lld_wait_capture(ICUDriver *icup) { + + /* If the driver is still in the ICU_WAITING state then we need to wait + for the first activation edge.*/ + if (icup->state == ICU_WAITING) + if (icu_lld_wait_edge(icup)) + return true; + + /* This edge marks the availability of a capture result.*/ + return icu_lld_wait_edge(icup); +} + +/** + * @brief Stops the input capture. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @notapi + */ +void icu_lld_stop_capture(ICUDriver *icup) { + + /* Timer stopped.*/ + icup->tim->CR1 = 0; + + /* All interrupts disabled.*/ + icup->tim->DIER &= ~STM32_TIM_DIER_IRQ_MASK; +} + +/** + * @brief Enables notifications. + * @pre The ICU unit must have been activated using @p icuStart(). + * @note If the notification is already enabled then the call has no effect. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @notapi + */ +void icu_lld_enable_notifications(ICUDriver *icup) { + uint32_t dier = icup->tim->DIER; + + /* If interrupts were already enabled then the operation is skipped. + This is done in order to avoid clearing the SR and risk losing + pending interrupts.*/ + if ((dier & STM32_TIM_DIER_IRQ_MASK) == 0) { + /* Previously triggered IRQs are ignored, status cleared.*/ + icup->tim->SR = 0; + + if (icup->config->channel == ICU_CHANNEL_1) { + /* Enabling periodic callback on CC1.*/ + dier |= STM32_TIM_DIER_CC1IE; + + /* Optionally enabling width callback on CC2.*/ + if (icup->config->width_cb != NULL) + dier |= STM32_TIM_DIER_CC2IE; + } + else { + /* Enabling periodic callback on CC2.*/ + dier |= STM32_TIM_DIER_CC2IE; + + /* Optionally enabling width callback on CC1.*/ + if (icup->config->width_cb != NULL) + dier |= STM32_TIM_DIER_CC1IE; + } + + /* If an overflow callback is defined then also the overflow callback + is enabled.*/ + if (icup->config->overflow_cb != NULL) + dier |= STM32_TIM_DIER_UIE; + + /* One single atomic write.*/ + icup->tim->DIER = dier; + } +} + +/** + * @brief Disables notifications. + * @pre The ICU unit must have been activated using @p icuStart(). + * @note If the notification is already disabled then the call has no effect. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @notapi + */ +void icu_lld_disable_notifications(ICUDriver *icup) { + + /* All interrupts disabled.*/ + icup->tim->DIER &= ~STM32_TIM_DIER_IRQ_MASK; +} + +/** + * @brief Shared IRQ handler. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @notapi + */ +void icu_lld_serve_interrupt(ICUDriver *icup) { + uint32_t sr; + + sr = icup->tim->SR; + sr &= icup->tim->DIER & STM32_TIM_DIER_IRQ_MASK; + icup->tim->SR = ~sr; + if (icup->config->channel == ICU_CHANNEL_1) { + if ((sr & STM32_TIM_SR_CC2IF) != 0) + _icu_isr_invoke_width_cb(icup); + if ((sr & STM32_TIM_SR_CC1IF) != 0) + _icu_isr_invoke_period_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); +} + +#endif /* HAL_USE_ICU */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.h b/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.h new file mode 100644 index 000000000..25a4f627a --- /dev/null +++ b/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.h @@ -0,0 +1,487 @@ +/* + ChibiOS - Copyright (C) 2006..2016 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_ + +#if HAL_USE_ICU || defined(__DOXYGEN__) + +#include "stm32_tim.h" + +/*===========================================================================*/ +/* 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 + +/* Checks on allocation of TIMx units.*/ +#if STM32_ICU_USE_TIM1 +#if defined(STM32_TIM1_IS_USED) +#error "ICUD1 requires TIM1 but the timer is already used" +#else +#define STM32_TIM1_IS_USED +#endif +#endif + +#if STM32_ICU_USE_TIM2 +#if defined(STM32_TIM2_IS_USED) +#error "ICUD2 requires TIM2 but the timer is already used" +#else +#define STM32_TIM2_IS_USED +#endif +#endif + +#if STM32_ICU_USE_TIM3 +#if defined(STM32_TIM3_IS_USED) +#error "ICUD3 requires TIM3 but the timer is already used" +#else +#define STM32_TIM3_IS_USED +#endif +#endif + +#if STM32_ICU_USE_TIM4 +#if defined(STM32_TIM4_IS_USED) +#error "ICUD4 requires TIM4 but the timer is already used" +#else +#define STM32_TIM4_IS_USED +#endif +#endif + +#if STM32_ICU_USE_TIM5 +#if defined(STM32_TIM5_IS_USED) +#error "ICUD5 requires TIM5 but the timer is already used" +#else +#define STM32_TIM5_IS_USED +#endif +#endif + +#if STM32_ICU_USE_TIM8 +#if defined(STM32_TIM8_IS_USED) +#error "ICUD8 requires TIM8 but the timer is already used" +#else +#define STM32_TIM8_IS_USED +#endif +#endif + +#if STM32_ICU_USE_TIM9 +#if defined(STM32_TIM9_IS_USED) +#error "ICUD9 requires TIM9 but the timer is already used" +#else +#define STM32_TIM9_IS_USED +#endif +#endif + +/* IRQ priority checks.*/ +#if STM32_ICU_USE_TIM1 && !defined(STM32_TIM1_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM1" +#endif + +#if STM32_ICU_USE_TIM2 && !defined(STM32_TIM2_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM2" +#endif + +#if STM32_ICU_USE_TIM3 && !defined(STM32_TIM3_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM3" +#endif + +#if STM32_ICU_USE_TIM4 && !defined(STM32_TIM4_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM4_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM4" +#endif + +#if STM32_ICU_USE_TIM5 && !defined(STM32_TIM5_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM5_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM5" +#endif + +#if STM32_ICU_USE_TIM8 && !defined(STM32_TIM8_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM8_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM8" +#endif + +#if STM32_ICU_USE_TIM9 && !defined(STM32_TIM9_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_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 uint32_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; + /** + * @brief TIM DIER register initialization data. + * @note The value of this field should normally be equal to zero. + * @note Only the DMA-related bits can be specified in this field. + */ + uint32_t dier; +} 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) + +/** + * @brief Check on notifications status. + * + * @param[in] icup pointer to the @p ICUDriver object + * @return The notifications status. + * @retval false if notifications are not enabled. + * @retval true if notifications are enabled. + * + * @notapi + */ +#define icu_lld_are_notifications_enabled(icup) \ + (bool)(((icup)->tim->DIER & STM32_TIM_DIER_IRQ_MASK) != 0) + +/*===========================================================================*/ +/* 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_start_capture(ICUDriver *icup); + bool icu_lld_wait_capture(ICUDriver *icup); + void icu_lld_stop_capture(ICUDriver *icup); + void icu_lld_enable_notifications(ICUDriver *icup); + void icu_lld_disable_notifications(ICUDriver *icup); + void icu_lld_serve_interrupt(ICUDriver *icup); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_ICU */ + +#endif /* _ICU_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.c b/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.c new file mode 100644 index 000000000..7837b4d02 --- /dev/null +++ b/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.c @@ -0,0 +1,858 @@ +/* + ChibiOS - Copyright (C) 2006..2016 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 "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. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_PWM_USE_TIM1 || defined(__DOXYGEN__) +#if !defined(STM32_TIM1_SUPPRESS_ISR) +#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 + */ +OSAL_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + pwm_lld_serve_interrupt(&PWMD1); + + OSAL_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 + */ +OSAL_IRQ_HANDLER(STM32_TIM1_CC_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + pwm_lld_serve_interrupt(&PWMD1); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM1_SUPPRESS_ISR) */ +#endif /* STM32_PWM_USE_TIM1 */ + +#if STM32_PWM_USE_TIM2 || defined(__DOXYGEN__) +#if !defined(STM32_TIM2_SUPPRESS_ISR) +#if !defined(STM32_TIM2_HANDLER) +#error "STM32_TIM2_HANDLER not defined" +#endif +/** + * @brief TIM2 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + pwm_lld_serve_interrupt(&PWMD2); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM2_SUPPRESS_ISR) */ +#endif /* STM32_PWM_USE_TIM2 */ + +#if STM32_PWM_USE_TIM3 || defined(__DOXYGEN__) +#if !defined(STM32_TIM3_SUPPRESS_ISR) +#if !defined(STM32_TIM3_HANDLER) +#error "STM32_TIM3_HANDLER not defined" +#endif +/** + * @brief TIM3 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM3_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + pwm_lld_serve_interrupt(&PWMD3); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM3_SUPPRESS_ISR) */ +#endif /* STM32_PWM_USE_TIM3 */ + +#if STM32_PWM_USE_TIM4 || defined(__DOXYGEN__) +#if !defined(STM32_TIM4_SUPPRESS_ISR) +#if !defined(STM32_TIM4_HANDLER) +#error "STM32_TIM4_HANDLER not defined" +#endif +/** + * @brief TIM4 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM4_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + pwm_lld_serve_interrupt(&PWMD4); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM4_SUPPRESS_ISR) */ +#endif /* STM32_PWM_USE_TIM4 */ + +#if STM32_PWM_USE_TIM5 || defined(__DOXYGEN__) +#if !defined(STM32_TIM5_SUPPRESS_ISR) +#if !defined(STM32_TIM5_HANDLER) +#error "STM32_TIM5_HANDLER not defined" +#endif +/** + * @brief TIM5 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM5_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + pwm_lld_serve_interrupt(&PWMD5); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM5_SUPPRESS_ISR) */ +#endif /* STM32_PWM_USE_TIM5 */ + +#if STM32_PWM_USE_TIM8 || defined(__DOXYGEN__) +#if !defined(STM32_TIM8_SUPPRESS_ISR) +#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 + */ +OSAL_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + pwm_lld_serve_interrupt(&PWMD8); + + OSAL_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 + */ +OSAL_IRQ_HANDLER(STM32_TIM8_CC_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + pwm_lld_serve_interrupt(&PWMD8); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM8_SUPPRESS_ISR) */ +#endif /* STM32_PWM_USE_TIM8 */ + +#if STM32_PWM_USE_TIM9 || defined(__DOXYGEN__) +#if !defined(STM32_TIM9_SUPPRESS_ISR) +#if !defined(STM32_TIM9_HANDLER) +#error "STM32_TIM9_HANDLER not defined" +#endif +/** + * @brief TIM9 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_TIM9_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + pwm_lld_serve_interrupt(&PWMD9); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* !defined(STM32_TIM9_SUPPRESS_ISR) */ +#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.channels = STM32_TIM1_CHANNELS; + PWMD1.tim = STM32_TIM1; +#endif + +#if STM32_PWM_USE_TIM2 + /* Driver initialization.*/ + pwmObjectInit(&PWMD2); + PWMD2.channels = STM32_TIM2_CHANNELS; + PWMD2.tim = STM32_TIM2; +#endif + +#if STM32_PWM_USE_TIM3 + /* Driver initialization.*/ + pwmObjectInit(&PWMD3); + PWMD3.channels = STM32_TIM3_CHANNELS; + PWMD3.tim = STM32_TIM3; +#endif + +#if STM32_PWM_USE_TIM4 + /* Driver initialization.*/ + pwmObjectInit(&PWMD4); + PWMD4.channels = STM32_TIM4_CHANNELS; + PWMD4.tim = STM32_TIM4; +#endif + +#if STM32_PWM_USE_TIM5 + /* Driver initialization.*/ + pwmObjectInit(&PWMD5); + PWMD5.channels = STM32_TIM5_CHANNELS; + PWMD5.tim = STM32_TIM5; +#endif + +#if STM32_PWM_USE_TIM8 + /* Driver initialization.*/ + pwmObjectInit(&PWMD8); + PWMD8.channels = STM32_TIM8_CHANNELS; + PWMD8.tim = STM32_TIM8; +#endif + +#if STM32_PWM_USE_TIM9 + /* Driver initialization.*/ + pwmObjectInit(&PWMD9); + PWMD9.channels = STM32_TIM9_CHANNELS; + 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; + uint32_t ccer; + + if (pwmp->state == PWM_STOP) { + /* Clock activation and timer reset.*/ +#if STM32_PWM_USE_TIM1 + if (&PWMD1 == pwmp) { + rccEnableTIM1(FALSE); + rccResetTIM1(); +#if !defined(STM32_TIM1_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM1_UP_NUMBER, STM32_PWM_TIM1_IRQ_PRIORITY); + nvicEnableVector(STM32_TIM1_CC_NUMBER, STM32_PWM_TIM1_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM1CLK) + pwmp->clock = STM32_TIM1CLK; +#else + pwmp->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_PWM_USE_TIM2 + if (&PWMD2 == pwmp) { + rccEnableTIM2(FALSE); + rccResetTIM2(); +#if !defined(STM32_TIM2_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM2_NUMBER, STM32_PWM_TIM2_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM2CLK) + pwmp->clock = STM32_TIM2CLK; +#else + pwmp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_PWM_USE_TIM3 + if (&PWMD3 == pwmp) { + rccEnableTIM3(FALSE); + rccResetTIM3(); +#if !defined(STM32_TIM3_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM3_NUMBER, STM32_PWM_TIM3_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM3CLK) + pwmp->clock = STM32_TIM3CLK; +#else + pwmp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_PWM_USE_TIM4 + if (&PWMD4 == pwmp) { + rccEnableTIM4(FALSE); + rccResetTIM4(); +#if !defined(STM32_TIM4_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM4_NUMBER, STM32_PWM_TIM4_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM4CLK) + pwmp->clock = STM32_TIM4CLK; +#else + pwmp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_PWM_USE_TIM5 + if (&PWMD5 == pwmp) { + rccEnableTIM5(FALSE); + rccResetTIM5(); +#if !defined(STM32_TIM5_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM5_NUMBER, STM32_PWM_TIM5_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM5CLK) + pwmp->clock = STM32_TIM5CLK; +#else + pwmp->clock = STM32_TIMCLK1; +#endif + } +#endif + +#if STM32_PWM_USE_TIM8 + if (&PWMD8 == pwmp) { + rccEnableTIM8(FALSE); + rccResetTIM8(); +#if !defined(STM32_TIM8_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM8_UP_NUMBER, STM32_PWM_TIM8_IRQ_PRIORITY); + nvicEnableVector(STM32_TIM8_CC_NUMBER, STM32_PWM_TIM8_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM8CLK) + pwmp->clock = STM32_TIM8CLK; +#else + pwmp->clock = STM32_TIMCLK2; +#endif + } +#endif + +#if STM32_PWM_USE_TIM9 + if (&PWMD9 == pwmp) { + rccEnableTIM9(FALSE); + rccResetTIM9(); +#if !defined(STM32_TIM9_SUPPRESS_ISR) + nvicEnableVector(STM32_TIM9_NUMBER, STM32_PWM_TIM9_IRQ_PRIORITY); +#endif +#if defined(STM32_TIM9CLK) + pwmp->clock = STM32_TIM9CLK; +#else + pwmp->clock = STM32_TIMCLK2; +#endif + } +#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; +#if STM32_TIM_MAX_CHANNELS > 4 + pwmp->tim->CCMR3 = STM32_TIM_CCMR3_OC5M(6) | STM32_TIM_CCMR3_OC5PE | + STM32_TIM_CCMR3_OC6M(6) | STM32_TIM_CCMR3_OC6PE; +#endif + } + else { + /* Driver re-configuration scenario, it must be stopped first.*/ + pwmp->tim->CR1 = 0; /* Timer disabled. */ + 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. */ +#if STM32_TIM_MAX_CHANNELS > 4 + if (pwmp->channels > 4) { + pwmp->tim->CCXR[0] = 0; /* Comparator 5 disabled. */ + pwmp->tim->CCXR[1] = 0; /* Comparator 6 disabled. */ + } +#endif + pwmp->tim->CNT = 0; /* Counter reset to zero. */ + } + + /* Timer configuration.*/ + psc = (pwmp->clock / pwmp->config->frequency) - 1; + osalDbgAssert((psc <= 0xFFFF) && + ((psc + 1) * pwmp->config->frequency) == pwmp->clock, + "invalid frequency"); + pwmp->tim->PSC = psc; + pwmp->tim->ARR = 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->SR = 0; /* Clear pending IRQs. */ + pwmp->tim->DIER = pwmp->config->dier & /* DMA-related DIER settings. */ + ~STM32_TIM_DIER_IRQ_MASK; +#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) { +#if !defined(STM32_TIM1_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM1_UP_NUMBER); + nvicDisableVector(STM32_TIM1_CC_NUMBER); +#endif + rccDisableTIM1(FALSE); + } +#endif + +#if STM32_PWM_USE_TIM2 + if (&PWMD2 == pwmp) { +#if !defined(STM32_TIM2_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM2_NUMBER); +#endif + rccDisableTIM2(FALSE); + } +#endif + +#if STM32_PWM_USE_TIM3 + if (&PWMD3 == pwmp) { +#if !defined(STM32_TIM3_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM3_NUMBER); +#endif + rccDisableTIM3(FALSE); + } +#endif + +#if STM32_PWM_USE_TIM4 + if (&PWMD4 == pwmp) { +#if !defined(STM32_TIM4_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM4_NUMBER); +#endif + rccDisableTIM4(FALSE); + } +#endif + +#if STM32_PWM_USE_TIM5 + if (&PWMD5 == pwmp) { +#if !defined(STM32_TIM5_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM5_NUMBER); +#endif + rccDisableTIM5(FALSE); + } +#endif + +#if STM32_PWM_USE_TIM8 + if (&PWMD8 == pwmp) { +#if !defined(STM32_TIM8_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM8_UP_NUMBER); + nvicDisableVector(STM32_TIM8_CC_NUMBER); +#endif + rccDisableTIM8(FALSE); + } +#endif + +#if STM32_PWM_USE_TIM9 + if (&PWMD9 == pwmp) { +#if !defined(STM32_TIM9_SUPPRESS_ISR) + nvicDisableVector(STM32_TIM9_NUMBER); +#endif + 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. + * @note Channel notification is not enabled. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...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) { + + /* Changing channel duty cycle on the fly.*/ +#if STM32_TIM_MAX_CHANNELS <= 4 + pwmp->tim->CCR[channel] = width; +#else + if (channel < 4) + pwmp->tim->CCR[channel] = width; + else + pwmp->tim->CCXR[channel - 4] = width; +#endif +} + +/** + * @brief Disables a PWM channel and its notification. + * @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...channels-1) + * + * @notapi + */ +void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel) { + +#if STM32_TIM_MAX_CHANNELS <= 4 + pwmp->tim->CCR[channel] = 0; + pwmp->tim->DIER &= ~(2 << channel); +#else + if (channel < 4) { + pwmp->tim->CCR[channel] = 0; + pwmp->tim->DIER &= ~(2 << channel); + } + else + pwmp->tim->CCXR[channel - 4] = 0; +#endif +} + +/** + * @brief Enables the periodic activation edge notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @note If the notification is already enabled then the call has no effect. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * + * @notapi + */ +void pwm_lld_enable_periodic_notification(PWMDriver *pwmp) { + 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 & STM32_TIM_DIER_UIE) == 0) { + pwmp->tim->DIER = dier | STM32_TIM_DIER_UIE; + pwmp->tim->SR &= STM32_TIM_SR_UIF; + } +} + +/** + * @brief Disables the periodic activation edge notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @note If the notification is already disabled then the call has no effect. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * + * @notapi + */ +void pwm_lld_disable_periodic_notification(PWMDriver *pwmp) { + + pwmp->tim->DIER &= ~STM32_TIM_DIER_UIE; +} + +/** + * @brief Enables a channel de-activation edge notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @pre The channel must have been activated using @p pwmEnableChannel(). + * @note If the notification is already enabled then the call has no effect. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...channels-1) + * + * @notapi + */ +void pwm_lld_enable_channel_notification(PWMDriver *pwmp, + pwmchannel_t channel) { + uint32_t dier = pwmp->tim->DIER; + +#if STM32_TIM_MAX_CHANNELS > 4 + /* Channels 4 and 5 do not support callbacks.*/ + osalDbgAssert(channel < 4, "callback not supported"); +#endif + + /* 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 channel de-activation edge notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @pre The channel must have been activated using @p pwmEnableChannel(). + * @note If the notification is already disabled then the call has no effect. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...channels-1) + * + * @notapi + */ +void pwm_lld_disable_channel_notification(PWMDriver *pwmp, + pwmchannel_t channel) { + + pwmp->tim->DIER &= ~(2 << channel); +} + +/** + * @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 + * + * @notapi + */ +void pwm_lld_serve_interrupt(PWMDriver *pwmp) { + uint32_t sr; + + sr = pwmp->tim->SR; + sr &= pwmp->tim->DIER & STM32_TIM_DIER_IRQ_MASK; + pwmp->tim->SR = ~sr; + if (((sr & STM32_TIM_SR_CC1IF) != 0) && + (pwmp->config->channels[0].callback != NULL)) + pwmp->config->channels[0].callback(pwmp); + if (((sr & STM32_TIM_SR_CC2IF) != 0) && + (pwmp->config->channels[1].callback != NULL)) + pwmp->config->channels[1].callback(pwmp); + if (((sr & STM32_TIM_SR_CC3IF) != 0) && + (pwmp->config->channels[2].callback != NULL)) + pwmp->config->channels[2].callback(pwmp); + if (((sr & STM32_TIM_SR_CC4IF) != 0) && + (pwmp->config->channels[3].callback != NULL)) + pwmp->config->channels[3].callback(pwmp); + if (((sr & STM32_TIM_SR_UIF) != 0) && (pwmp->config->callback != NULL)) + pwmp->config->callback(pwmp); +} + +#endif /* HAL_USE_PWM */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.h b/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.h new file mode 100644 index 000000000..981312f38 --- /dev/null +++ b/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.h @@ -0,0 +1,550 @@ +/* + ChibiOS - Copyright (C) 2006..2016 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_ + +#if HAL_USE_PWM || defined(__DOXYGEN__) + +#include "stm32_tim.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Number of PWM channels per PWM driver. + */ +#define PWM_CHANNELS STM32_TIM_MAX_CHANNELS + +/** + * @name STM32-specific PWM complementary output mode macros + * @{ + */ +/** + * @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 + +/* Checks on allocation of TIMx units.*/ +#if STM32_PWM_USE_TIM1 +#if defined(STM32_TIM1_IS_USED) +#error "PWMD1 requires TIM1 but the timer is already used" +#else +#define STM32_TIM1_IS_USED +#endif +#endif + +#if STM32_PWM_USE_TIM2 +#if defined(STM32_TIM2_IS_USED) +#error "PWMD2 requires TIM2 but the timer is already used" +#else +#define STM32_TIM2_IS_USED +#endif +#endif + +#if STM32_PWM_USE_TIM3 +#if defined(STM32_TIM3_IS_USED) +#error "PWMD3 requires TIM3 but the timer is already used" +#else +#define STM32_TIM3_IS_USED +#endif +#endif + +#if STM32_PWM_USE_TIM4 +#if defined(STM32_TIM4_IS_USED) +#error "PWMD4 requires TIM4 but the timer is already used" +#else +#define STM32_TIM4_IS_USED +#endif +#endif + +#if STM32_PWM_USE_TIM5 +#if defined(STM32_TIM5_IS_USED) +#error "PWMD5 requires TIM5 but the timer is already used" +#else +#define STM32_TIM5_IS_USED +#endif +#endif + +#if STM32_PWM_USE_TIM8 +#if defined(STM32_TIM8_IS_USED) +#error "PWMD8 requires TIM8 but the timer is already used" +#else +#define STM32_TIM8_IS_USED +#endif +#endif + +#if STM32_PWM_USE_TIM9 +#if defined(STM32_TIM9_IS_USED) +#error "PWMD9 requires TIM9 but the timer is already used" +#else +#define STM32_TIM9_IS_USED +#endif +#endif + +/* IRQ priority checks.*/ +#if STM32_PWM_USE_TIM1 && !defined(STM32_TIM1_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM1" +#endif + +#if STM32_PWM_USE_TIM2 && !defined(STM32_TIM2_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM2" +#endif + +#if STM32_PWM_USE_TIM3 && !defined(STM32_TIM3_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM3" +#endif + +#if STM32_PWM_USE_TIM4 && !defined(STM32_TIM4_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM4_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM4" +#endif + +#if STM32_PWM_USE_TIM5 && !defined(STM32_TIM5_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM5_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM5" +#endif + +#if STM32_PWM_USE_TIM8 && !defined(STM32_TIM8_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM8_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM8" +#endif + +#if STM32_PWM_USE_TIM9 && !defined(STM32_TIM9_SUPPRESS_ISR) && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM9_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIM9" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of a PWM mode. + */ +typedef uint32_t pwmmode_t; + +/** + * @brief Type of a PWM channel. + */ +typedef uint8_t pwmchannel_t; + +/** + * @brief Type of a channels mask. + */ +typedef uint32_t pwmchnmsk_t; + +/** + * @brief Type of a PWM counter. + */ +typedef uint32_t pwmcnt_t; + +/** + * @brief Type of a 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 Type of a 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. + */ + uint32_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. + */ \ + uint32_t bdtr; +#endif + /** + * @brief TIM DIER register initialization data. + * @note The value of this field should normally be equal to zero. + * @note Only the DMA-related bits can be specified in this field. + */ + uint32_t dier; +} 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; + /** + * @brief Mask of the enabled channels. + */ + pwmchnmsk_t enabled; + /** + * @brief Number of channels in this instance. + */ + pwmchannel_t channels; +#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 = ((period) - 1)) + +/*===========================================================================*/ +/* 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); + void pwm_lld_enable_periodic_notification(PWMDriver *pwmp); + void pwm_lld_disable_periodic_notification(PWMDriver *pwmp); + void pwm_lld_enable_channel_notification(PWMDriver *pwmp, + pwmchannel_t channel); + void pwm_lld_disable_channel_notification(PWMDriver *pwmp, + pwmchannel_t channel); + void pwm_lld_serve_interrupt(PWMDriver *pwmp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_PWM */ + +#endif /* _PWM_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.c b/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.c new file mode 100644 index 000000000..cea1847ee --- /dev/null +++ b/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.c @@ -0,0 +1,308 @@ +/* + ChibiOS - Copyright (C) 2006..2016 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/st_lld.c + * @brief ST Driver subsystem low level driver code. + * + * @addtogroup ST + * @{ + */ + +#include "hal.h" + +#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING + +#if (OSAL_ST_RESOLUTION == 32) +#define ST_ARR_INIT 0xFFFFFFFF +#else +#define ST_ARR_INIT 0x0000FFFF +#endif + +#if STM32_ST_USE_TIMER == 2 +#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM2_IS_32BITS +#error "TIM2 is not a 32bits timer" +#endif + +#if defined(STM32_TIM2_IS_USED) +#error "ST requires TIM2 but the timer is already used" +#else +#define STM32_TIM2_IS_USED +#endif + +#define ST_HANDLER STM32_TIM2_HANDLER +#define ST_NUMBER STM32_TIM2_NUMBER +#define ST_CLOCK_SRC STM32_TIMCLK1 +#define ST_ENABLE_CLOCK() rccEnableTIM2(FALSE) +#if defined(STM32F1XX) +#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM2_STOP +#elif defined(STM32L4XX) +#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM2_STOP +#else +#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM2_STOP +#endif + +#elif STM32_ST_USE_TIMER == 3 +#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM3_IS_32BITS +#error "TIM3 is not a 32bits timer" +#endif + +#if defined(STM32_TIM3_IS_USED) +#error "ST requires TIM3 but the timer is already used" +#else +#define STM32_TIM3_IS_USED +#endif + +#define ST_HANDLER STM32_TIM3_HANDLER +#define ST_NUMBER STM32_TIM3_NUMBER +#define ST_CLOCK_SRC STM32_TIMCLK1 +#define ST_ENABLE_CLOCK() rccEnableTIM3(FALSE) +#if defined(STM32F1XX) +#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM3_STOP +#elif defined(STM32L4XX) +#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM3_STOP +#else +#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM3_STOP +#endif + +#elif STM32_ST_USE_TIMER == 4 +#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM4_IS_32BITS +#error "TIM4 is not a 32bits timer" +#endif + +#if defined(STM32_TIM4_IS_USED) +#error "ST requires TIM4 but the timer is already used" +#else +#define STM32_TIM4_IS_USED +#endif + +#define ST_HANDLER STM32_TIM4_HANDLER +#define ST_NUMBER STM32_TIM4_NUMBER +#define ST_CLOCK_SRC STM32_TIMCLK1 +#define ST_ENABLE_CLOCK() rccEnableTIM4(FALSE) +#if defined(STM32F1XX) +#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM4_STOP +#elif defined(STM32L4XX) +#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM4_STOP +#else +#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM4_STOP +#endif + +#elif STM32_ST_USE_TIMER == 5 +#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM5_IS_32BITS +#error "TIM5 is not a 32bits timer" +#endif + +#if defined(STM32_TIM5_IS_USED) +#error "ST requires TIM5 but the timer is already used" +#else +#define STM32_TIM5_IS_USED +#endif + +#define ST_HANDLER STM32_TIM5_HANDLER +#define ST_NUMBER STM32_TIM5_NUMBER +#define ST_CLOCK_SRC STM32_TIMCLK1 +#define ST_ENABLE_CLOCK() rccEnableTIM5(FALSE) +#if defined(STM32F1XX) +#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM5_STOP +#elif defined(STM32L4XX) +#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM5_STOP +#else +#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM5_STOP +#endif + +#elif STM32_ST_USE_TIMER == 21 +#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM21_IS_32BITS +#error "TIM21 is not a 32bits timer" +#endif + +#if defined(STM32_TIM21_IS_USED) +#error "ST requires TIM21 but the timer is already used" +#else +#define STM32_TIM21_IS_USED +#endif + +#define ST_HANDLER STM32_TIM21_HANDLER +#define ST_NUMBER STM32_TIM21_NUMBER +#define ST_CLOCK_SRC STM32_TIMCLK2 +#define ST_ENABLE_CLOCK() rccEnableTIM21(FALSE) +#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB2_FZ_DBG_TIM21_STOP + +#elif STM32_ST_USE_TIMER == 22 +#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM22_IS_32BITS +#error "TIM21 is not a 32bits timer" +#endif + +#if defined(STM32_TIM22_IS_USED) +#error "ST requires TIM22 but the timer is already used" +#else +#define STM32_TIM22_IS_USED +#endif + +#define ST_HANDLER STM32_TIM22_HANDLER +#define ST_NUMBER STM32_TIM22_NUMBER +#define ST_CLOCK_SRC STM32_TIMCLK2 +#define ST_ENABLE_CLOCK() rccEnableTIM22(FALSE) +#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB2_FZ_DBG_TIM21_STOP + +#else +#error "STM32_ST_USE_TIMER specifies an unsupported timer" +#endif + +#if ST_CLOCK_SRC % OSAL_ST_FREQUENCY != 0 +#error "the selected ST frequency is not obtainable because integer rounding" +#endif + +#if (ST_CLOCK_SRC / OSAL_ST_FREQUENCY) - 1 > 0xFFFF +#error "the selected ST frequency is not obtainable because TIM timer prescaler limits" +#endif + +#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */ + +#if OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC + +#if STM32_HCLK % OSAL_ST_FREQUENCY != 0 +#error "the selected ST frequency is not obtainable because integer rounding" +#endif + +#if (STM32_HCLK / OSAL_ST_FREQUENCY) - 1 > 0xFFFFFF +#error "the selected ST frequency is not obtainable because SysTick timer counter limits" +#endif + +#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if (OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC) || defined(__DOXYGEN__) +/** + * @brief System Timer vector. + * @details This interrupt is used for system tick in periodic mode. + * + * @isr + */ +OSAL_IRQ_HANDLER(SysTick_Handler) { + + OSAL_IRQ_PROLOGUE(); + + osalSysLockFromISR(); + osalOsTimerHandlerI(); + osalSysUnlockFromISR(); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */ + +#if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) || defined(__DOXYGEN__) +/** + * @brief TIM2 interrupt handler. + * @details This interrupt is used for system tick in free running mode. + * + * @isr + */ +OSAL_IRQ_HANDLER(ST_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + /* Note, under rare circumstances an interrupt can remain latched even if + the timer SR register has been cleared, in those cases the interrupt + is simply ignored.*/ + if ((STM32_ST_TIM->SR & TIM_SR_CC1IF) != 0U) { + STM32_ST_TIM->SR = 0U; + + osalSysLockFromISR(); + osalOsTimerHandlerI(); + osalSysUnlockFromISR(); + } + + OSAL_IRQ_EPILOGUE(); +} +#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level ST driver initialization. + * + * @notapi + */ +void st_lld_init(void) { + +#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING + /* Free running counter mode.*/ + + /* Enabling timer clock.*/ + ST_ENABLE_CLOCK(); + + /* Enabling the stop mode during debug for this timer.*/ + ST_ENABLE_STOP(); + + /* Initializing the counter in free running mode.*/ + STM32_ST_TIM->PSC = (ST_CLOCK_SRC / OSAL_ST_FREQUENCY) - 1; + STM32_ST_TIM->ARR = ST_ARR_INIT; + STM32_ST_TIM->CCMR1 = 0; + STM32_ST_TIM->CCR[0] = 0; + STM32_ST_TIM->DIER = 0; + STM32_ST_TIM->CR2 = 0; + STM32_ST_TIM->EGR = TIM_EGR_UG; + STM32_ST_TIM->CR1 = TIM_CR1_CEN; + + /* IRQ enabled.*/ + nvicEnableVector(ST_NUMBER, STM32_ST_IRQ_PRIORITY); +#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */ + +#if OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC + /* Periodic systick mode, the Cortex-Mx internal systick timer is used + in this mode.*/ + SysTick->LOAD = (STM32_HCLK / OSAL_ST_FREQUENCY) - 1; + SysTick->VAL = 0; + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_ENABLE_Msk | + SysTick_CTRL_TICKINT_Msk; + + /* IRQ enabled.*/ + nvicSetSystemHandlerPriority(HANDLER_SYSTICK, STM32_ST_IRQ_PRIORITY); +#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */ +} + +#endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.h b/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.h new file mode 100644 index 000000000..beefd16e2 --- /dev/null +++ b/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.h @@ -0,0 +1,210 @@ +/* + ChibiOS - Copyright (C) 2006..2016 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/st_lld.h + * @brief ST Driver subsystem low level driver header. + * @details This header is designed to be include-able without having to + * include other files from the HAL. + * + * @addtogroup ST + * @{ + */ + +#ifndef _ST_LLD_H_ +#define _ST_LLD_H_ + +#include "mcuconf.h" +#include "stm32_registry.h" +#include "stm32_tim.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief SysTick timer IRQ priority. + */ +#if !defined(STM32_ST_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_ST_IRQ_PRIORITY 8 +#endif + +/** + * @brief TIMx unit (by number) to be used for free running operations. + * @note You must select a 32 bits timer if a 32 bits @p systick_t type + * is required. + * @note Timers 2, 3, 4 and 5 are supported. + */ +#if !defined(STM32_ST_USE_TIMER) || defined(__DOXYGEN__) +#define STM32_ST_USE_TIMER 2 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_ST_USE_TIMER == 2 +#if !STM32_HAS_TIM2 +#error "TIM2 not present" +#endif +#define STM32_ST_TIM STM32_TIM2 + +#elif STM32_ST_USE_TIMER == 3 +#if !STM32_HAS_TIM3 +#error "TIM3 not present" +#endif +#define STM32_ST_TIM STM32_TIM3 + +#elif STM32_ST_USE_TIMER == 4 +#if !STM32_HAS_TIM4 +#error "TIM4 not present" +#endif +#define STM32_ST_TIM STM32_TIM4 + +#elif STM32_ST_USE_TIMER == 5 +#if !STM32_HAS_TIM5 +#error "TIM5 not present" +#endif +#define STM32_ST_TIM STM32_TIM5 + +#elif STM32_ST_USE_TIMER == 21 +#if !STM32_HAS_TIM21 +#error "TIM21 not present" +#endif +#define STM32_ST_TIM STM32_TIM21 + +#elif STM32_ST_USE_TIMER == 22 +#if !STM32_HAS_TIM22 +#error "TIM22 not present" +#endif +#define STM32_ST_TIM STM32_TIM22 + +#else +#error "STM32_ST_USE_TIMER specifies an unsupported timer" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void st_lld_init(void); +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Driver inline functions. */ +/*===========================================================================*/ + +/** + * @brief Returns the time counter value. + * + * @return The counter value. + * + * @notapi + */ +static inline systime_t st_lld_get_counter(void) { + + return (systime_t)STM32_ST_TIM->CNT; +} + +/** + * @brief Starts the alarm. + * @note Makes sure that no spurious alarms are triggered after + * this call. + * + * @param[in] time the time to be set for the first alarm + * + * @notapi + */ +static inline void st_lld_start_alarm(systime_t time) { + + STM32_ST_TIM->CCR[0] = (uint32_t)time; + STM32_ST_TIM->SR = 0; + STM32_ST_TIM->DIER = STM32_TIM_DIER_CC1IE; +} + +/** + * @brief Stops the alarm interrupt. + * + * @notapi + */ +static inline void st_lld_stop_alarm(void) { + + STM32_ST_TIM->DIER = 0; +} + +/** + * @brief Sets the alarm time. + * + * @param[in] time the time to be set for the next alarm + * + * @notapi + */ +static inline void st_lld_set_alarm(systime_t time) { + + STM32_ST_TIM->CCR[0] = (uint32_t)time; +} + +/** + * @brief Returns the current alarm time. + * + * @return The currently set alarm time. + * + * @notapi + */ +static inline systime_t st_lld_get_alarm(void) { + + return (systime_t)STM32_ST_TIM->CCR[0]; +} + +/** + * @brief Determines if the alarm is active. + * + * @return The alarm status. + * @retval false if the alarm is not active. + * @retval true is the alarm is active + * + * @notapi + */ +static inline bool st_lld_is_alarm_active(void) { + + return (bool)((STM32_ST_TIM->DIER & STM32_TIM_DIER_CC1IE) != 0); +} + +#endif /* _ST_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/TIMv1/icu_lld.c b/os/hal/ports/STM32/LLD/TIMv1/icu_lld.c deleted file mode 100644 index f7554241b..000000000 --- a/os/hal/ports/STM32/LLD/TIMv1/icu_lld.c +++ /dev/null @@ -1,805 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 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 "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. */ -/*===========================================================================*/ - -static bool icu_lld_wait_edge(ICUDriver *icup) { - uint32_t sr; - bool result; - - /* Polled mode so re-enabling the interrupts while the operation is - performed.*/ - osalSysUnlock(); - - /* Polling the right bit depending on the input channel.*/ - if (icup->config->channel == ICU_CHANNEL_1) { - /* Waiting for an edge.*/ - while (((sr = icup->tim->SR) & - (STM32_TIM_SR_CC1IF | STM32_TIM_SR_UIF)) == 0) - ; - } - else { - /* Waiting for an edge.*/ - while (((sr = icup->tim->SR) & - (STM32_TIM_SR_CC2IF | STM32_TIM_SR_UIF)) == 0) - ; - } - - /* Edge or overflow?*/ - result = (sr & STM32_TIM_SR_UIF) != 0 ? true : false; - - /* Done, disabling interrupts again.*/ - osalSysLock(); - - /* Resetting all flags.*/ - icup->tim->SR &= ~(STM32_TIM_SR_CC1IF | - STM32_TIM_SR_CC2IF | - STM32_TIM_SR_UIF); - - return result; -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_ICU_USE_TIM1 || defined(__DOXYGEN__) -#if !defined(STM32_TIM1_SUPPRESS_ISR) -#if !defined(STM32_TIM1_UP_HANDLER) -#error "STM32_TIM1_UP_HANDLER not defined" -#endif -/** - * @brief TIM1 compare interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD1); - - OSAL_IRQ_EPILOGUE(); -} - -#if !defined(STM32_TIM1_CC_HANDLER) -#error "STM32_TIM1_CC_HANDLER not defined" -#endif -/** - * @brief TIM1 compare interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM1_CC_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD1); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM1_SUPPRESS_ISR) */ -#endif /* STM32_ICU_USE_TIM1 */ - -#if STM32_ICU_USE_TIM2 || defined(__DOXYGEN__) -#if !defined(STM32_TIM2_SUPPRESS_ISR) -#if !defined(STM32_TIM2_HANDLER) -#error "STM32_TIM2_HANDLER not defined" -#endif -/** - * @brief TIM2 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM2_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD2); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM2_SUPPRESS_ISR) */ -#endif /* STM32_ICU_USE_TIM2 */ - -#if STM32_ICU_USE_TIM3 || defined(__DOXYGEN__) -#if !defined(STM32_TIM3_SUPPRESS_ISR) -#if !defined(STM32_TIM3_HANDLER) -#error "STM32_TIM3_HANDLER not defined" -#endif -/** - * @brief TIM3 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM3_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD3); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM3_SUPPRESS_ISR) */ -#endif /* STM32_ICU_USE_TIM3 */ - -#if STM32_ICU_USE_TIM4 || defined(__DOXYGEN__) -#if !defined(STM32_TIM4_SUPPRESS_ISR) -#if !defined(STM32_TIM4_HANDLER) -#error "STM32_TIM4_HANDLER not defined" -#endif -/** - * @brief TIM4 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM4_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD4); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM4_SUPPRESS_ISR) */ -#endif /* STM32_ICU_USE_TIM4 */ - -#if STM32_ICU_USE_TIM5 || defined(__DOXYGEN__) -#if !defined(STM32_TIM5_SUPPRESS_ISR) -#if !defined(STM32_TIM5_HANDLER) -#error "STM32_TIM5_HANDLER not defined" -#endif -/** - * @brief TIM5 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM5_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD5); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM5_SUPPRESS_ISR) */ -#endif /* STM32_ICU_USE_TIM5 */ - -#if STM32_ICU_USE_TIM8 || defined(__DOXYGEN__) -#if !defined(STM32_TIM8_SUPPRESS_ISR) -#if !defined(STM32_TIM8_UP_HANDLER) -#error "STM32_TIM8_UP_HANDLER not defined" -#endif -/** - * @brief TIM8 compare interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD8); - - OSAL_IRQ_EPILOGUE(); -} - -#if !defined(STM32_TIM8_CC_HANDLER) -#error "STM32_TIM8_CC_HANDLER not defined" -#endif -/** - * @brief TIM8 compare interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM8_CC_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD8); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM8_SUPPRESS_ISR) */ -#endif /* STM32_ICU_USE_TIM8 */ - -#if STM32_ICU_USE_TIM9 || defined(__DOXYGEN__) -#if !defined(STM32_TIM9_SUPPRESS_ISR) -#if !defined(STM32_TIM9_HANDLER) -#error "STM32_TIM9_HANDLER not defined" -#endif -/** - * @brief TIM9 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM9_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - icu_lld_serve_interrupt(&ICUD9); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM9_SUPPRESS_ISR) */ -#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; - - osalDbgAssert((icup->config->channel == ICU_CHANNEL_1) || - (icup->config->channel == ICU_CHANNEL_2), - "invalid input"); - - if (icup->state == ICU_STOP) { - /* Clock activation and timer reset.*/ -#if STM32_ICU_USE_TIM1 - if (&ICUD1 == icup) { - rccEnableTIM1(FALSE); - rccResetTIM1(); -#if !defined(STM32_TIM1_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM1_UP_NUMBER, STM32_ICU_TIM1_IRQ_PRIORITY); - nvicEnableVector(STM32_TIM1_CC_NUMBER, STM32_ICU_TIM1_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM1CLK) - icup->clock = STM32_TIM1CLK; -#else - icup->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_ICU_USE_TIM2 - if (&ICUD2 == icup) { - rccEnableTIM2(FALSE); - rccResetTIM2(); -#if !defined(STM32_TIM2_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM2_NUMBER, STM32_ICU_TIM2_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM2CLK) - icup->clock = STM32_TIM2CLK; -#else - icup->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_ICU_USE_TIM3 - if (&ICUD3 == icup) { - rccEnableTIM3(FALSE); - rccResetTIM3(); -#if !defined(STM32_TIM3_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM3_NUMBER, STM32_ICU_TIM3_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM3CLK) - icup->clock = STM32_TIM3CLK; -#else - icup->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_ICU_USE_TIM4 - if (&ICUD4 == icup) { - rccEnableTIM4(FALSE); - rccResetTIM4(); -#if !defined(STM32_TIM4_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM4_NUMBER, STM32_ICU_TIM4_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM4CLK) - icup->clock = STM32_TIM4CLK; -#else - icup->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_ICU_USE_TIM5 - if (&ICUD5 == icup) { - rccEnableTIM5(FALSE); - rccResetTIM5(); -#if !defined(STM32_TIM5_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM5_NUMBER, STM32_ICU_TIM5_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM5CLK) - icup->clock = STM32_TIM5CLK; -#else - icup->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_ICU_USE_TIM8 - if (&ICUD8 == icup) { - rccEnableTIM8(FALSE); - rccResetTIM8(); -#if !defined(STM32_TIM8_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM8_UP_NUMBER, STM32_ICU_TIM8_IRQ_PRIORITY); - nvicEnableVector(STM32_TIM8_CC_NUMBER, STM32_ICU_TIM8_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM8CLK) - icup->clock = STM32_TIM8CLK; -#else - icup->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_ICU_USE_TIM9 - if (&ICUD9 == icup) { - rccEnableTIM9(FALSE); - rccResetTIM9(); -#if !defined(STM32_TIM9_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM9_NUMBER, STM32_ICU_TIM9_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM9CLK) - icup->clock = STM32_TIM9CLK; -#else - icup->clock = STM32_TIMCLK2; -#endif - } -#endif - } - else { - /* Driver re-configuration scenario, it must be stopped first.*/ - icup->tim->CR1 = 0; /* Timer disabled. */ - 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.*/ - icup->tim->SR = 0; /* Clear eventual pending IRQs. */ - icup->tim->DIER = icup->config->dier & /* DMA-related DIER settings. */ - ~STM32_TIM_DIER_IRQ_MASK; - psc = (icup->clock / icup->config->frequency) - 1; - osalDbgAssert((psc <= 0xFFFF) && - ((psc + 1) * icup->config->frequency) == icup->clock, - "invalid frequency"); - icup->tim->PSC = 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) { -#if !defined(STM32_TIM1_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM1_UP_NUMBER); - nvicDisableVector(STM32_TIM1_CC_NUMBER); -#endif - rccDisableTIM1(FALSE); - } -#endif - -#if STM32_ICU_USE_TIM2 - if (&ICUD2 == icup) { -#if !defined(STM32_TIM2_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM2_NUMBER); -#endif - rccDisableTIM2(FALSE); - } -#endif - -#if STM32_ICU_USE_TIM3 - if (&ICUD3 == icup) { -#if !defined(STM32_TIM3_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM3_NUMBER); -#endif - rccDisableTIM3(FALSE); - } -#endif - -#if STM32_ICU_USE_TIM4 - if (&ICUD4 == icup) { -#if !defined(STM32_TIM4_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM4_NUMBER); -#endif - rccDisableTIM4(FALSE); - } -#endif - -#if STM32_ICU_USE_TIM5 - if (&ICUD5 == icup) { -#if !defined(STM32_TIM5_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM5_NUMBER); -#endif - rccDisableTIM5(FALSE); - } -#endif - -#if STM32_ICU_USE_TIM8 - if (&ICUD8 == icup) { -#if !defined(STM32_TIM8_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM8_UP_NUMBER); - nvicDisableVector(STM32_TIM8_CC_NUMBER); -#endif - rccDisableTIM8(FALSE); - } -#endif - -#if STM32_ICU_USE_TIM9 - if (&ICUD9 == icup) { -#if !defined(STM32_TIM9_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM9_NUMBER); -#endif - rccDisableTIM9(FALSE); - } -#endif - } -} - -/** - * @brief Starts the input capture. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @notapi - */ -void icu_lld_start_capture(ICUDriver *icup) { - - /* Triggering an UG and clearing the IRQ status.*/ - icup->tim->EGR |= STM32_TIM_EGR_UG; - icup->tim->SR = 0; - - /* Timer is started.*/ - icup->tim->CR1 = STM32_TIM_CR1_URS | STM32_TIM_CR1_CEN; -} - -/** - * @brief Waits for a completed capture. - * @note The operation is performed in polled mode. - * @note In order to use this function notifications must be disabled. - * - * @param[in] icup pointer to the @p ICUDriver object - * @return The capture status. - * @retval false if the capture is successful. - * @retval true if a timer overflow occurred. - * - * @notapi - */ -bool icu_lld_wait_capture(ICUDriver *icup) { - - /* If the driver is still in the ICU_WAITING state then we need to wait - for the first activation edge.*/ - if (icup->state == ICU_WAITING) - if (icu_lld_wait_edge(icup)) - return true; - - /* This edge marks the availability of a capture result.*/ - return icu_lld_wait_edge(icup); -} - -/** - * @brief Stops the input capture. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @notapi - */ -void icu_lld_stop_capture(ICUDriver *icup) { - - /* Timer stopped.*/ - icup->tim->CR1 = 0; - - /* All interrupts disabled.*/ - icup->tim->DIER &= ~STM32_TIM_DIER_IRQ_MASK; -} - -/** - * @brief Enables notifications. - * @pre The ICU unit must have been activated using @p icuStart(). - * @note If the notification is already enabled then the call has no effect. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @notapi - */ -void icu_lld_enable_notifications(ICUDriver *icup) { - uint32_t dier = icup->tim->DIER; - - /* If interrupts were already enabled then the operation is skipped. - This is done in order to avoid clearing the SR and risk losing - pending interrupts.*/ - if ((dier & STM32_TIM_DIER_IRQ_MASK) == 0) { - /* Previously triggered IRQs are ignored, status cleared.*/ - icup->tim->SR = 0; - - if (icup->config->channel == ICU_CHANNEL_1) { - /* Enabling periodic callback on CC1.*/ - dier |= STM32_TIM_DIER_CC1IE; - - /* Optionally enabling width callback on CC2.*/ - if (icup->config->width_cb != NULL) - dier |= STM32_TIM_DIER_CC2IE; - } - else { - /* Enabling periodic callback on CC2.*/ - dier |= STM32_TIM_DIER_CC2IE; - - /* Optionally enabling width callback on CC1.*/ - if (icup->config->width_cb != NULL) - dier |= STM32_TIM_DIER_CC1IE; - } - - /* If an overflow callback is defined then also the overflow callback - is enabled.*/ - if (icup->config->overflow_cb != NULL) - dier |= STM32_TIM_DIER_UIE; - - /* One single atomic write.*/ - icup->tim->DIER = dier; - } -} - -/** - * @brief Disables notifications. - * @pre The ICU unit must have been activated using @p icuStart(). - * @note If the notification is already disabled then the call has no effect. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @notapi - */ -void icu_lld_disable_notifications(ICUDriver *icup) { - - /* All interrupts disabled.*/ - icup->tim->DIER &= ~STM32_TIM_DIER_IRQ_MASK; -} - -/** - * @brief Shared IRQ handler. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @notapi - */ -void icu_lld_serve_interrupt(ICUDriver *icup) { - uint32_t sr; - - sr = icup->tim->SR; - sr &= icup->tim->DIER & STM32_TIM_DIER_IRQ_MASK; - icup->tim->SR = ~sr; - if (icup->config->channel == ICU_CHANNEL_1) { - if ((sr & STM32_TIM_SR_CC2IF) != 0) - _icu_isr_invoke_width_cb(icup); - if ((sr & STM32_TIM_SR_CC1IF) != 0) - _icu_isr_invoke_period_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); -} - -#endif /* HAL_USE_ICU */ - -/** @} */ diff --git a/os/hal/ports/STM32/LLD/TIMv1/icu_lld.h b/os/hal/ports/STM32/LLD/TIMv1/icu_lld.h deleted file mode 100644 index 25a4f627a..000000000 --- a/os/hal/ports/STM32/LLD/TIMv1/icu_lld.h +++ /dev/null @@ -1,487 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 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_ - -#if HAL_USE_ICU || defined(__DOXYGEN__) - -#include "stm32_tim.h" - -/*===========================================================================*/ -/* 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 - -/* Checks on allocation of TIMx units.*/ -#if STM32_ICU_USE_TIM1 -#if defined(STM32_TIM1_IS_USED) -#error "ICUD1 requires TIM1 but the timer is already used" -#else -#define STM32_TIM1_IS_USED -#endif -#endif - -#if STM32_ICU_USE_TIM2 -#if defined(STM32_TIM2_IS_USED) -#error "ICUD2 requires TIM2 but the timer is already used" -#else -#define STM32_TIM2_IS_USED -#endif -#endif - -#if STM32_ICU_USE_TIM3 -#if defined(STM32_TIM3_IS_USED) -#error "ICUD3 requires TIM3 but the timer is already used" -#else -#define STM32_TIM3_IS_USED -#endif -#endif - -#if STM32_ICU_USE_TIM4 -#if defined(STM32_TIM4_IS_USED) -#error "ICUD4 requires TIM4 but the timer is already used" -#else -#define STM32_TIM4_IS_USED -#endif -#endif - -#if STM32_ICU_USE_TIM5 -#if defined(STM32_TIM5_IS_USED) -#error "ICUD5 requires TIM5 but the timer is already used" -#else -#define STM32_TIM5_IS_USED -#endif -#endif - -#if STM32_ICU_USE_TIM8 -#if defined(STM32_TIM8_IS_USED) -#error "ICUD8 requires TIM8 but the timer is already used" -#else -#define STM32_TIM8_IS_USED -#endif -#endif - -#if STM32_ICU_USE_TIM9 -#if defined(STM32_TIM9_IS_USED) -#error "ICUD9 requires TIM9 but the timer is already used" -#else -#define STM32_TIM9_IS_USED -#endif -#endif - -/* IRQ priority checks.*/ -#if STM32_ICU_USE_TIM1 && !defined(STM32_TIM1_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM1" -#endif - -#if STM32_ICU_USE_TIM2 && !defined(STM32_TIM2_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM2" -#endif - -#if STM32_ICU_USE_TIM3 && !defined(STM32_TIM3_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM3" -#endif - -#if STM32_ICU_USE_TIM4 && !defined(STM32_TIM4_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM4_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM4" -#endif - -#if STM32_ICU_USE_TIM5 && !defined(STM32_TIM5_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM5_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM5" -#endif - -#if STM32_ICU_USE_TIM8 && !defined(STM32_TIM8_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM8_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM8" -#endif - -#if STM32_ICU_USE_TIM9 && !defined(STM32_TIM9_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_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 uint32_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; - /** - * @brief TIM DIER register initialization data. - * @note The value of this field should normally be equal to zero. - * @note Only the DMA-related bits can be specified in this field. - */ - uint32_t dier; -} 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) - -/** - * @brief Check on notifications status. - * - * @param[in] icup pointer to the @p ICUDriver object - * @return The notifications status. - * @retval false if notifications are not enabled. - * @retval true if notifications are enabled. - * - * @notapi - */ -#define icu_lld_are_notifications_enabled(icup) \ - (bool)(((icup)->tim->DIER & STM32_TIM_DIER_IRQ_MASK) != 0) - -/*===========================================================================*/ -/* 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_start_capture(ICUDriver *icup); - bool icu_lld_wait_capture(ICUDriver *icup); - void icu_lld_stop_capture(ICUDriver *icup); - void icu_lld_enable_notifications(ICUDriver *icup); - void icu_lld_disable_notifications(ICUDriver *icup); - void icu_lld_serve_interrupt(ICUDriver *icup); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_ICU */ - -#endif /* _ICU_LLD_H_ */ - -/** @} */ diff --git a/os/hal/ports/STM32/LLD/TIMv1/pwm_lld.c b/os/hal/ports/STM32/LLD/TIMv1/pwm_lld.c deleted file mode 100644 index 7837b4d02..000000000 --- a/os/hal/ports/STM32/LLD/TIMv1/pwm_lld.c +++ /dev/null @@ -1,858 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 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 "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. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_PWM_USE_TIM1 || defined(__DOXYGEN__) -#if !defined(STM32_TIM1_SUPPRESS_ISR) -#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 - */ -OSAL_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - pwm_lld_serve_interrupt(&PWMD1); - - OSAL_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 - */ -OSAL_IRQ_HANDLER(STM32_TIM1_CC_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - pwm_lld_serve_interrupt(&PWMD1); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM1_SUPPRESS_ISR) */ -#endif /* STM32_PWM_USE_TIM1 */ - -#if STM32_PWM_USE_TIM2 || defined(__DOXYGEN__) -#if !defined(STM32_TIM2_SUPPRESS_ISR) -#if !defined(STM32_TIM2_HANDLER) -#error "STM32_TIM2_HANDLER not defined" -#endif -/** - * @brief TIM2 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM2_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - pwm_lld_serve_interrupt(&PWMD2); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM2_SUPPRESS_ISR) */ -#endif /* STM32_PWM_USE_TIM2 */ - -#if STM32_PWM_USE_TIM3 || defined(__DOXYGEN__) -#if !defined(STM32_TIM3_SUPPRESS_ISR) -#if !defined(STM32_TIM3_HANDLER) -#error "STM32_TIM3_HANDLER not defined" -#endif -/** - * @brief TIM3 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM3_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - pwm_lld_serve_interrupt(&PWMD3); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM3_SUPPRESS_ISR) */ -#endif /* STM32_PWM_USE_TIM3 */ - -#if STM32_PWM_USE_TIM4 || defined(__DOXYGEN__) -#if !defined(STM32_TIM4_SUPPRESS_ISR) -#if !defined(STM32_TIM4_HANDLER) -#error "STM32_TIM4_HANDLER not defined" -#endif -/** - * @brief TIM4 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM4_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - pwm_lld_serve_interrupt(&PWMD4); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM4_SUPPRESS_ISR) */ -#endif /* STM32_PWM_USE_TIM4 */ - -#if STM32_PWM_USE_TIM5 || defined(__DOXYGEN__) -#if !defined(STM32_TIM5_SUPPRESS_ISR) -#if !defined(STM32_TIM5_HANDLER) -#error "STM32_TIM5_HANDLER not defined" -#endif -/** - * @brief TIM5 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM5_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - pwm_lld_serve_interrupt(&PWMD5); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM5_SUPPRESS_ISR) */ -#endif /* STM32_PWM_USE_TIM5 */ - -#if STM32_PWM_USE_TIM8 || defined(__DOXYGEN__) -#if !defined(STM32_TIM8_SUPPRESS_ISR) -#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 - */ -OSAL_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - pwm_lld_serve_interrupt(&PWMD8); - - OSAL_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 - */ -OSAL_IRQ_HANDLER(STM32_TIM8_CC_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - pwm_lld_serve_interrupt(&PWMD8); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM8_SUPPRESS_ISR) */ -#endif /* STM32_PWM_USE_TIM8 */ - -#if STM32_PWM_USE_TIM9 || defined(__DOXYGEN__) -#if !defined(STM32_TIM9_SUPPRESS_ISR) -#if !defined(STM32_TIM9_HANDLER) -#error "STM32_TIM9_HANDLER not defined" -#endif -/** - * @brief TIM9 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(STM32_TIM9_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - pwm_lld_serve_interrupt(&PWMD9); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* !defined(STM32_TIM9_SUPPRESS_ISR) */ -#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.channels = STM32_TIM1_CHANNELS; - PWMD1.tim = STM32_TIM1; -#endif - -#if STM32_PWM_USE_TIM2 - /* Driver initialization.*/ - pwmObjectInit(&PWMD2); - PWMD2.channels = STM32_TIM2_CHANNELS; - PWMD2.tim = STM32_TIM2; -#endif - -#if STM32_PWM_USE_TIM3 - /* Driver initialization.*/ - pwmObjectInit(&PWMD3); - PWMD3.channels = STM32_TIM3_CHANNELS; - PWMD3.tim = STM32_TIM3; -#endif - -#if STM32_PWM_USE_TIM4 - /* Driver initialization.*/ - pwmObjectInit(&PWMD4); - PWMD4.channels = STM32_TIM4_CHANNELS; - PWMD4.tim = STM32_TIM4; -#endif - -#if STM32_PWM_USE_TIM5 - /* Driver initialization.*/ - pwmObjectInit(&PWMD5); - PWMD5.channels = STM32_TIM5_CHANNELS; - PWMD5.tim = STM32_TIM5; -#endif - -#if STM32_PWM_USE_TIM8 - /* Driver initialization.*/ - pwmObjectInit(&PWMD8); - PWMD8.channels = STM32_TIM8_CHANNELS; - PWMD8.tim = STM32_TIM8; -#endif - -#if STM32_PWM_USE_TIM9 - /* Driver initialization.*/ - pwmObjectInit(&PWMD9); - PWMD9.channels = STM32_TIM9_CHANNELS; - 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; - uint32_t ccer; - - if (pwmp->state == PWM_STOP) { - /* Clock activation and timer reset.*/ -#if STM32_PWM_USE_TIM1 - if (&PWMD1 == pwmp) { - rccEnableTIM1(FALSE); - rccResetTIM1(); -#if !defined(STM32_TIM1_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM1_UP_NUMBER, STM32_PWM_TIM1_IRQ_PRIORITY); - nvicEnableVector(STM32_TIM1_CC_NUMBER, STM32_PWM_TIM1_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM1CLK) - pwmp->clock = STM32_TIM1CLK; -#else - pwmp->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_PWM_USE_TIM2 - if (&PWMD2 == pwmp) { - rccEnableTIM2(FALSE); - rccResetTIM2(); -#if !defined(STM32_TIM2_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM2_NUMBER, STM32_PWM_TIM2_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM2CLK) - pwmp->clock = STM32_TIM2CLK; -#else - pwmp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_PWM_USE_TIM3 - if (&PWMD3 == pwmp) { - rccEnableTIM3(FALSE); - rccResetTIM3(); -#if !defined(STM32_TIM3_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM3_NUMBER, STM32_PWM_TIM3_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM3CLK) - pwmp->clock = STM32_TIM3CLK; -#else - pwmp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_PWM_USE_TIM4 - if (&PWMD4 == pwmp) { - rccEnableTIM4(FALSE); - rccResetTIM4(); -#if !defined(STM32_TIM4_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM4_NUMBER, STM32_PWM_TIM4_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM4CLK) - pwmp->clock = STM32_TIM4CLK; -#else - pwmp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_PWM_USE_TIM5 - if (&PWMD5 == pwmp) { - rccEnableTIM5(FALSE); - rccResetTIM5(); -#if !defined(STM32_TIM5_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM5_NUMBER, STM32_PWM_TIM5_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM5CLK) - pwmp->clock = STM32_TIM5CLK; -#else - pwmp->clock = STM32_TIMCLK1; -#endif - } -#endif - -#if STM32_PWM_USE_TIM8 - if (&PWMD8 == pwmp) { - rccEnableTIM8(FALSE); - rccResetTIM8(); -#if !defined(STM32_TIM8_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM8_UP_NUMBER, STM32_PWM_TIM8_IRQ_PRIORITY); - nvicEnableVector(STM32_TIM8_CC_NUMBER, STM32_PWM_TIM8_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM8CLK) - pwmp->clock = STM32_TIM8CLK; -#else - pwmp->clock = STM32_TIMCLK2; -#endif - } -#endif - -#if STM32_PWM_USE_TIM9 - if (&PWMD9 == pwmp) { - rccEnableTIM9(FALSE); - rccResetTIM9(); -#if !defined(STM32_TIM9_SUPPRESS_ISR) - nvicEnableVector(STM32_TIM9_NUMBER, STM32_PWM_TIM9_IRQ_PRIORITY); -#endif -#if defined(STM32_TIM9CLK) - pwmp->clock = STM32_TIM9CLK; -#else - pwmp->clock = STM32_TIMCLK2; -#endif - } -#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; -#if STM32_TIM_MAX_CHANNELS > 4 - pwmp->tim->CCMR3 = STM32_TIM_CCMR3_OC5M(6) | STM32_TIM_CCMR3_OC5PE | - STM32_TIM_CCMR3_OC6M(6) | STM32_TIM_CCMR3_OC6PE; -#endif - } - else { - /* Driver re-configuration scenario, it must be stopped first.*/ - pwmp->tim->CR1 = 0; /* Timer disabled. */ - 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. */ -#if STM32_TIM_MAX_CHANNELS > 4 - if (pwmp->channels > 4) { - pwmp->tim->CCXR[0] = 0; /* Comparator 5 disabled. */ - pwmp->tim->CCXR[1] = 0; /* Comparator 6 disabled. */ - } -#endif - pwmp->tim->CNT = 0; /* Counter reset to zero. */ - } - - /* Timer configuration.*/ - psc = (pwmp->clock / pwmp->config->frequency) - 1; - osalDbgAssert((psc <= 0xFFFF) && - ((psc + 1) * pwmp->config->frequency) == pwmp->clock, - "invalid frequency"); - pwmp->tim->PSC = psc; - pwmp->tim->ARR = 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->SR = 0; /* Clear pending IRQs. */ - pwmp->tim->DIER = pwmp->config->dier & /* DMA-related DIER settings. */ - ~STM32_TIM_DIER_IRQ_MASK; -#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) { -#if !defined(STM32_TIM1_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM1_UP_NUMBER); - nvicDisableVector(STM32_TIM1_CC_NUMBER); -#endif - rccDisableTIM1(FALSE); - } -#endif - -#if STM32_PWM_USE_TIM2 - if (&PWMD2 == pwmp) { -#if !defined(STM32_TIM2_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM2_NUMBER); -#endif - rccDisableTIM2(FALSE); - } -#endif - -#if STM32_PWM_USE_TIM3 - if (&PWMD3 == pwmp) { -#if !defined(STM32_TIM3_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM3_NUMBER); -#endif - rccDisableTIM3(FALSE); - } -#endif - -#if STM32_PWM_USE_TIM4 - if (&PWMD4 == pwmp) { -#if !defined(STM32_TIM4_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM4_NUMBER); -#endif - rccDisableTIM4(FALSE); - } -#endif - -#if STM32_PWM_USE_TIM5 - if (&PWMD5 == pwmp) { -#if !defined(STM32_TIM5_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM5_NUMBER); -#endif - rccDisableTIM5(FALSE); - } -#endif - -#if STM32_PWM_USE_TIM8 - if (&PWMD8 == pwmp) { -#if !defined(STM32_TIM8_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM8_UP_NUMBER); - nvicDisableVector(STM32_TIM8_CC_NUMBER); -#endif - rccDisableTIM8(FALSE); - } -#endif - -#if STM32_PWM_USE_TIM9 - if (&PWMD9 == pwmp) { -#if !defined(STM32_TIM9_SUPPRESS_ISR) - nvicDisableVector(STM32_TIM9_NUMBER); -#endif - 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. - * @note Channel notification is not enabled. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] channel PWM channel identifier (0...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) { - - /* Changing channel duty cycle on the fly.*/ -#if STM32_TIM_MAX_CHANNELS <= 4 - pwmp->tim->CCR[channel] = width; -#else - if (channel < 4) - pwmp->tim->CCR[channel] = width; - else - pwmp->tim->CCXR[channel - 4] = width; -#endif -} - -/** - * @brief Disables a PWM channel and its notification. - * @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...channels-1) - * - * @notapi - */ -void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel) { - -#if STM32_TIM_MAX_CHANNELS <= 4 - pwmp->tim->CCR[channel] = 0; - pwmp->tim->DIER &= ~(2 << channel); -#else - if (channel < 4) { - pwmp->tim->CCR[channel] = 0; - pwmp->tim->DIER &= ~(2 << channel); - } - else - pwmp->tim->CCXR[channel - 4] = 0; -#endif -} - -/** - * @brief Enables the periodic activation edge notification. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @note If the notification is already enabled then the call has no effect. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * - * @notapi - */ -void pwm_lld_enable_periodic_notification(PWMDriver *pwmp) { - 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 & STM32_TIM_DIER_UIE) == 0) { - pwmp->tim->DIER = dier | STM32_TIM_DIER_UIE; - pwmp->tim->SR &= STM32_TIM_SR_UIF; - } -} - -/** - * @brief Disables the periodic activation edge notification. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @note If the notification is already disabled then the call has no effect. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * - * @notapi - */ -void pwm_lld_disable_periodic_notification(PWMDriver *pwmp) { - - pwmp->tim->DIER &= ~STM32_TIM_DIER_UIE; -} - -/** - * @brief Enables a channel de-activation edge notification. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @pre The channel must have been activated using @p pwmEnableChannel(). - * @note If the notification is already enabled then the call has no effect. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] channel PWM channel identifier (0...channels-1) - * - * @notapi - */ -void pwm_lld_enable_channel_notification(PWMDriver *pwmp, - pwmchannel_t channel) { - uint32_t dier = pwmp->tim->DIER; - -#if STM32_TIM_MAX_CHANNELS > 4 - /* Channels 4 and 5 do not support callbacks.*/ - osalDbgAssert(channel < 4, "callback not supported"); -#endif - - /* 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 channel de-activation edge notification. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @pre The channel must have been activated using @p pwmEnableChannel(). - * @note If the notification is already disabled then the call has no effect. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] channel PWM channel identifier (0...channels-1) - * - * @notapi - */ -void pwm_lld_disable_channel_notification(PWMDriver *pwmp, - pwmchannel_t channel) { - - pwmp->tim->DIER &= ~(2 << channel); -} - -/** - * @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 - * - * @notapi - */ -void pwm_lld_serve_interrupt(PWMDriver *pwmp) { - uint32_t sr; - - sr = pwmp->tim->SR; - sr &= pwmp->tim->DIER & STM32_TIM_DIER_IRQ_MASK; - pwmp->tim->SR = ~sr; - if (((sr & STM32_TIM_SR_CC1IF) != 0) && - (pwmp->config->channels[0].callback != NULL)) - pwmp->config->channels[0].callback(pwmp); - if (((sr & STM32_TIM_SR_CC2IF) != 0) && - (pwmp->config->channels[1].callback != NULL)) - pwmp->config->channels[1].callback(pwmp); - if (((sr & STM32_TIM_SR_CC3IF) != 0) && - (pwmp->config->channels[2].callback != NULL)) - pwmp->config->channels[2].callback(pwmp); - if (((sr & STM32_TIM_SR_CC4IF) != 0) && - (pwmp->config->channels[3].callback != NULL)) - pwmp->config->channels[3].callback(pwmp); - if (((sr & STM32_TIM_SR_UIF) != 0) && (pwmp->config->callback != NULL)) - pwmp->config->callback(pwmp); -} - -#endif /* HAL_USE_PWM */ - -/** @} */ diff --git a/os/hal/ports/STM32/LLD/TIMv1/pwm_lld.h b/os/hal/ports/STM32/LLD/TIMv1/pwm_lld.h deleted file mode 100644 index 981312f38..000000000 --- a/os/hal/ports/STM32/LLD/TIMv1/pwm_lld.h +++ /dev/null @@ -1,550 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 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_ - -#if HAL_USE_PWM || defined(__DOXYGEN__) - -#include "stm32_tim.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Number of PWM channels per PWM driver. - */ -#define PWM_CHANNELS STM32_TIM_MAX_CHANNELS - -/** - * @name STM32-specific PWM complementary output mode macros - * @{ - */ -/** - * @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 - -/* Checks on allocation of TIMx units.*/ -#if STM32_PWM_USE_TIM1 -#if defined(STM32_TIM1_IS_USED) -#error "PWMD1 requires TIM1 but the timer is already used" -#else -#define STM32_TIM1_IS_USED -#endif -#endif - -#if STM32_PWM_USE_TIM2 -#if defined(STM32_TIM2_IS_USED) -#error "PWMD2 requires TIM2 but the timer is already used" -#else -#define STM32_TIM2_IS_USED -#endif -#endif - -#if STM32_PWM_USE_TIM3 -#if defined(STM32_TIM3_IS_USED) -#error "PWMD3 requires TIM3 but the timer is already used" -#else -#define STM32_TIM3_IS_USED -#endif -#endif - -#if STM32_PWM_USE_TIM4 -#if defined(STM32_TIM4_IS_USED) -#error "PWMD4 requires TIM4 but the timer is already used" -#else -#define STM32_TIM4_IS_USED -#endif -#endif - -#if STM32_PWM_USE_TIM5 -#if defined(STM32_TIM5_IS_USED) -#error "PWMD5 requires TIM5 but the timer is already used" -#else -#define STM32_TIM5_IS_USED -#endif -#endif - -#if STM32_PWM_USE_TIM8 -#if defined(STM32_TIM8_IS_USED) -#error "PWMD8 requires TIM8 but the timer is already used" -#else -#define STM32_TIM8_IS_USED -#endif -#endif - -#if STM32_PWM_USE_TIM9 -#if defined(STM32_TIM9_IS_USED) -#error "PWMD9 requires TIM9 but the timer is already used" -#else -#define STM32_TIM9_IS_USED -#endif -#endif - -/* IRQ priority checks.*/ -#if STM32_PWM_USE_TIM1 && !defined(STM32_TIM1_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM1" -#endif - -#if STM32_PWM_USE_TIM2 && !defined(STM32_TIM2_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM2" -#endif - -#if STM32_PWM_USE_TIM3 && !defined(STM32_TIM3_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM3" -#endif - -#if STM32_PWM_USE_TIM4 && !defined(STM32_TIM4_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM4_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM4" -#endif - -#if STM32_PWM_USE_TIM5 && !defined(STM32_TIM5_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM5_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM5" -#endif - -#if STM32_PWM_USE_TIM8 && !defined(STM32_TIM8_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM8_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM8" -#endif - -#if STM32_PWM_USE_TIM9 && !defined(STM32_TIM9_SUPPRESS_ISR) && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM9_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIM9" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of a PWM mode. - */ -typedef uint32_t pwmmode_t; - -/** - * @brief Type of a PWM channel. - */ -typedef uint8_t pwmchannel_t; - -/** - * @brief Type of a channels mask. - */ -typedef uint32_t pwmchnmsk_t; - -/** - * @brief Type of a PWM counter. - */ -typedef uint32_t pwmcnt_t; - -/** - * @brief Type of a 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 Type of a 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. - */ - uint32_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. - */ \ - uint32_t bdtr; -#endif - /** - * @brief TIM DIER register initialization data. - * @note The value of this field should normally be equal to zero. - * @note Only the DMA-related bits can be specified in this field. - */ - uint32_t dier; -} 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; - /** - * @brief Mask of the enabled channels. - */ - pwmchnmsk_t enabled; - /** - * @brief Number of channels in this instance. - */ - pwmchannel_t channels; -#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 = ((period) - 1)) - -/*===========================================================================*/ -/* 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); - void pwm_lld_enable_periodic_notification(PWMDriver *pwmp); - void pwm_lld_disable_periodic_notification(PWMDriver *pwmp); - void pwm_lld_enable_channel_notification(PWMDriver *pwmp, - pwmchannel_t channel); - void pwm_lld_disable_channel_notification(PWMDriver *pwmp, - pwmchannel_t channel); - void pwm_lld_serve_interrupt(PWMDriver *pwmp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_PWM */ - -#endif /* _PWM_LLD_H_ */ - -/** @} */ diff --git a/os/hal/ports/STM32/LLD/TIMv1/st_lld.c b/os/hal/ports/STM32/LLD/TIMv1/st_lld.c deleted file mode 100644 index cea1847ee..000000000 --- a/os/hal/ports/STM32/LLD/TIMv1/st_lld.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 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/st_lld.c - * @brief ST Driver subsystem low level driver code. - * - * @addtogroup ST - * @{ - */ - -#include "hal.h" - -#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING - -#if (OSAL_ST_RESOLUTION == 32) -#define ST_ARR_INIT 0xFFFFFFFF -#else -#define ST_ARR_INIT 0x0000FFFF -#endif - -#if STM32_ST_USE_TIMER == 2 -#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM2_IS_32BITS -#error "TIM2 is not a 32bits timer" -#endif - -#if defined(STM32_TIM2_IS_USED) -#error "ST requires TIM2 but the timer is already used" -#else -#define STM32_TIM2_IS_USED -#endif - -#define ST_HANDLER STM32_TIM2_HANDLER -#define ST_NUMBER STM32_TIM2_NUMBER -#define ST_CLOCK_SRC STM32_TIMCLK1 -#define ST_ENABLE_CLOCK() rccEnableTIM2(FALSE) -#if defined(STM32F1XX) -#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM2_STOP -#elif defined(STM32L4XX) -#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM2_STOP -#else -#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM2_STOP -#endif - -#elif STM32_ST_USE_TIMER == 3 -#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM3_IS_32BITS -#error "TIM3 is not a 32bits timer" -#endif - -#if defined(STM32_TIM3_IS_USED) -#error "ST requires TIM3 but the timer is already used" -#else -#define STM32_TIM3_IS_USED -#endif - -#define ST_HANDLER STM32_TIM3_HANDLER -#define ST_NUMBER STM32_TIM3_NUMBER -#define ST_CLOCK_SRC STM32_TIMCLK1 -#define ST_ENABLE_CLOCK() rccEnableTIM3(FALSE) -#if defined(STM32F1XX) -#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM3_STOP -#elif defined(STM32L4XX) -#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM3_STOP -#else -#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM3_STOP -#endif - -#elif STM32_ST_USE_TIMER == 4 -#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM4_IS_32BITS -#error "TIM4 is not a 32bits timer" -#endif - -#if defined(STM32_TIM4_IS_USED) -#error "ST requires TIM4 but the timer is already used" -#else -#define STM32_TIM4_IS_USED -#endif - -#define ST_HANDLER STM32_TIM4_HANDLER -#define ST_NUMBER STM32_TIM4_NUMBER -#define ST_CLOCK_SRC STM32_TIMCLK1 -#define ST_ENABLE_CLOCK() rccEnableTIM4(FALSE) -#if defined(STM32F1XX) -#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM4_STOP -#elif defined(STM32L4XX) -#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM4_STOP -#else -#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM4_STOP -#endif - -#elif STM32_ST_USE_TIMER == 5 -#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM5_IS_32BITS -#error "TIM5 is not a 32bits timer" -#endif - -#if defined(STM32_TIM5_IS_USED) -#error "ST requires TIM5 but the timer is already used" -#else -#define STM32_TIM5_IS_USED -#endif - -#define ST_HANDLER STM32_TIM5_HANDLER -#define ST_NUMBER STM32_TIM5_NUMBER -#define ST_CLOCK_SRC STM32_TIMCLK1 -#define ST_ENABLE_CLOCK() rccEnableTIM5(FALSE) -#if defined(STM32F1XX) -#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM5_STOP -#elif defined(STM32L4XX) -#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM5_STOP -#else -#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM5_STOP -#endif - -#elif STM32_ST_USE_TIMER == 21 -#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM21_IS_32BITS -#error "TIM21 is not a 32bits timer" -#endif - -#if defined(STM32_TIM21_IS_USED) -#error "ST requires TIM21 but the timer is already used" -#else -#define STM32_TIM21_IS_USED -#endif - -#define ST_HANDLER STM32_TIM21_HANDLER -#define ST_NUMBER STM32_TIM21_NUMBER -#define ST_CLOCK_SRC STM32_TIMCLK2 -#define ST_ENABLE_CLOCK() rccEnableTIM21(FALSE) -#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB2_FZ_DBG_TIM21_STOP - -#elif STM32_ST_USE_TIMER == 22 -#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM22_IS_32BITS -#error "TIM21 is not a 32bits timer" -#endif - -#if defined(STM32_TIM22_IS_USED) -#error "ST requires TIM22 but the timer is already used" -#else -#define STM32_TIM22_IS_USED -#endif - -#define ST_HANDLER STM32_TIM22_HANDLER -#define ST_NUMBER STM32_TIM22_NUMBER -#define ST_CLOCK_SRC STM32_TIMCLK2 -#define ST_ENABLE_CLOCK() rccEnableTIM22(FALSE) -#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB2_FZ_DBG_TIM21_STOP - -#else -#error "STM32_ST_USE_TIMER specifies an unsupported timer" -#endif - -#if ST_CLOCK_SRC % OSAL_ST_FREQUENCY != 0 -#error "the selected ST frequency is not obtainable because integer rounding" -#endif - -#if (ST_CLOCK_SRC / OSAL_ST_FREQUENCY) - 1 > 0xFFFF -#error "the selected ST frequency is not obtainable because TIM timer prescaler limits" -#endif - -#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */ - -#if OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC - -#if STM32_HCLK % OSAL_ST_FREQUENCY != 0 -#error "the selected ST frequency is not obtainable because integer rounding" -#endif - -#if (STM32_HCLK / OSAL_ST_FREQUENCY) - 1 > 0xFFFFFF -#error "the selected ST frequency is not obtainable because SysTick timer counter limits" -#endif - -#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if (OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC) || defined(__DOXYGEN__) -/** - * @brief System Timer vector. - * @details This interrupt is used for system tick in periodic mode. - * - * @isr - */ -OSAL_IRQ_HANDLER(SysTick_Handler) { - - OSAL_IRQ_PROLOGUE(); - - osalSysLockFromISR(); - osalOsTimerHandlerI(); - osalSysUnlockFromISR(); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */ - -#if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) || defined(__DOXYGEN__) -/** - * @brief TIM2 interrupt handler. - * @details This interrupt is used for system tick in free running mode. - * - * @isr - */ -OSAL_IRQ_HANDLER(ST_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - /* Note, under rare circumstances an interrupt can remain latched even if - the timer SR register has been cleared, in those cases the interrupt - is simply ignored.*/ - if ((STM32_ST_TIM->SR & TIM_SR_CC1IF) != 0U) { - STM32_ST_TIM->SR = 0U; - - osalSysLockFromISR(); - osalOsTimerHandlerI(); - osalSysUnlockFromISR(); - } - - OSAL_IRQ_EPILOGUE(); -} -#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level ST driver initialization. - * - * @notapi - */ -void st_lld_init(void) { - -#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING - /* Free running counter mode.*/ - - /* Enabling timer clock.*/ - ST_ENABLE_CLOCK(); - - /* Enabling the stop mode during debug for this timer.*/ - ST_ENABLE_STOP(); - - /* Initializing the counter in free running mode.*/ - STM32_ST_TIM->PSC = (ST_CLOCK_SRC / OSAL_ST_FREQUENCY) - 1; - STM32_ST_TIM->ARR = ST_ARR_INIT; - STM32_ST_TIM->CCMR1 = 0; - STM32_ST_TIM->CCR[0] = 0; - STM32_ST_TIM->DIER = 0; - STM32_ST_TIM->CR2 = 0; - STM32_ST_TIM->EGR = TIM_EGR_UG; - STM32_ST_TIM->CR1 = TIM_CR1_CEN; - - /* IRQ enabled.*/ - nvicEnableVector(ST_NUMBER, STM32_ST_IRQ_PRIORITY); -#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */ - -#if OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC - /* Periodic systick mode, the Cortex-Mx internal systick timer is used - in this mode.*/ - SysTick->LOAD = (STM32_HCLK / OSAL_ST_FREQUENCY) - 1; - SysTick->VAL = 0; - SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | - SysTick_CTRL_ENABLE_Msk | - SysTick_CTRL_TICKINT_Msk; - - /* IRQ enabled.*/ - nvicSetSystemHandlerPriority(HANDLER_SYSTICK, STM32_ST_IRQ_PRIORITY); -#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */ -} - -#endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */ - -/** @} */ diff --git a/os/hal/ports/STM32/LLD/TIMv1/st_lld.h b/os/hal/ports/STM32/LLD/TIMv1/st_lld.h deleted file mode 100644 index beefd16e2..000000000 --- a/os/hal/ports/STM32/LLD/TIMv1/st_lld.h +++ /dev/null @@ -1,210 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 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/st_lld.h - * @brief ST Driver subsystem low level driver header. - * @details This header is designed to be include-able without having to - * include other files from the HAL. - * - * @addtogroup ST - * @{ - */ - -#ifndef _ST_LLD_H_ -#define _ST_LLD_H_ - -#include "mcuconf.h" -#include "stm32_registry.h" -#include "stm32_tim.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief SysTick timer IRQ priority. - */ -#if !defined(STM32_ST_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_ST_IRQ_PRIORITY 8 -#endif - -/** - * @brief TIMx unit (by number) to be used for free running operations. - * @note You must select a 32 bits timer if a 32 bits @p systick_t type - * is required. - * @note Timers 2, 3, 4 and 5 are supported. - */ -#if !defined(STM32_ST_USE_TIMER) || defined(__DOXYGEN__) -#define STM32_ST_USE_TIMER 2 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if STM32_ST_USE_TIMER == 2 -#if !STM32_HAS_TIM2 -#error "TIM2 not present" -#endif -#define STM32_ST_TIM STM32_TIM2 - -#elif STM32_ST_USE_TIMER == 3 -#if !STM32_HAS_TIM3 -#error "TIM3 not present" -#endif -#define STM32_ST_TIM STM32_TIM3 - -#elif STM32_ST_USE_TIMER == 4 -#if !STM32_HAS_TIM4 -#error "TIM4 not present" -#endif -#define STM32_ST_TIM STM32_TIM4 - -#elif STM32_ST_USE_TIMER == 5 -#if !STM32_HAS_TIM5 -#error "TIM5 not present" -#endif -#define STM32_ST_TIM STM32_TIM5 - -#elif STM32_ST_USE_TIMER == 21 -#if !STM32_HAS_TIM21 -#error "TIM21 not present" -#endif -#define STM32_ST_TIM STM32_TIM21 - -#elif STM32_ST_USE_TIMER == 22 -#if !STM32_HAS_TIM22 -#error "TIM22 not present" -#endif -#define STM32_ST_TIM STM32_TIM22 - -#else -#error "STM32_ST_USE_TIMER specifies an unsupported timer" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void st_lld_init(void); -#ifdef __cplusplus -} -#endif - -/*===========================================================================*/ -/* Driver inline functions. */ -/*===========================================================================*/ - -/** - * @brief Returns the time counter value. - * - * @return The counter value. - * - * @notapi - */ -static inline systime_t st_lld_get_counter(void) { - - return (systime_t)STM32_ST_TIM->CNT; -} - -/** - * @brief Starts the alarm. - * @note Makes sure that no spurious alarms are triggered after - * this call. - * - * @param[in] time the time to be set for the first alarm - * - * @notapi - */ -static inline void st_lld_start_alarm(systime_t time) { - - STM32_ST_TIM->CCR[0] = (uint32_t)time; - STM32_ST_TIM->SR = 0; - STM32_ST_TIM->DIER = STM32_TIM_DIER_CC1IE; -} - -/** - * @brief Stops the alarm interrupt. - * - * @notapi - */ -static inline void st_lld_stop_alarm(void) { - - STM32_ST_TIM->DIER = 0; -} - -/** - * @brief Sets the alarm time. - * - * @param[in] time the time to be set for the next alarm - * - * @notapi - */ -static inline void st_lld_set_alarm(systime_t time) { - - STM32_ST_TIM->CCR[0] = (uint32_t)time; -} - -/** - * @brief Returns the current alarm time. - * - * @return The currently set alarm time. - * - * @notapi - */ -static inline systime_t st_lld_get_alarm(void) { - - return (systime_t)STM32_ST_TIM->CCR[0]; -} - -/** - * @brief Determines if the alarm is active. - * - * @return The alarm status. - * @retval false if the alarm is not active. - * @retval true is the alarm is active - * - * @notapi - */ -static inline bool st_lld_is_alarm_active(void) { - - return (bool)((STM32_ST_TIM->DIER & STM32_TIM_DIER_CC1IE) != 0); -} - -#endif /* _ST_LLD_H_ */ - -/** @} */ -- cgit v1.2.3