From 5ab1f418c84cb003a2bf65bd66758bd0abacb08b Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 6 Mar 2011 08:46:51 +0000 Subject: [PATCH] LPC13xx GPT driver added (not tested yet). git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2799 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- demos/ARMCM3-LPC1343-LPCXPRESSO/mcuconf.h | 12 + os/hal/platforms/LPC11xx/platform.dox | 2 +- os/hal/platforms/LPC13xx/gpt_lld.c | 341 ++++++++++++++++++++++ os/hal/platforms/LPC13xx/gpt_lld.h | 223 ++++++++++++++ os/hal/platforms/LPC13xx/platform.dox | 18 ++ os/hal/platforms/LPC13xx/platform.mk | 1 + 6 files changed, 596 insertions(+), 1 deletion(-) create mode 100644 os/hal/platforms/LPC13xx/gpt_lld.c create mode 100644 os/hal/platforms/LPC13xx/gpt_lld.h diff --git a/demos/ARMCM3-LPC1343-LPCXPRESSO/mcuconf.h b/demos/ARMCM3-LPC1343-LPCXPRESSO/mcuconf.h index f5d119449..195eb6c6a 100644 --- a/demos/ARMCM3-LPC1343-LPCXPRESSO/mcuconf.h +++ b/demos/ARMCM3-LPC1343-LPCXPRESSO/mcuconf.h @@ -45,6 +45,18 @@ * CAN driver system settings. */ +/* + * GPT driver system settings. + */ +#define LPC13xx_GPT_USE_CT16B0 TRUE +#define LPC13xx_GPT_USE_CT16B1 TRUE +#define LPC13xx_GPT_USE_CT32B0 TRUE +#define LPC13xx_GPT_USE_CT32B1 TRUE +#define LPC13xx_GPT_CT16B0_IRQ_PRIORITY 2 +#define LPC13xx_GPT_CT16B1_IRQ_PRIORITY 2 +#define LPC13xx_GPT_CT32B0_IRQ_PRIORITY 2 +#define LPC13xx_GPT_CT32B1_IRQ_PRIORITY 2 + /* * PWM driver system settings. */ diff --git a/os/hal/platforms/LPC11xx/platform.dox b/os/hal/platforms/LPC11xx/platform.dox index 47b9273e9..405ed8ee3 100644 --- a/os/hal/platforms/LPC11xx/platform.dox +++ b/os/hal/platforms/LPC11xx/platform.dox @@ -55,7 +55,7 @@ * @section lpc11xx_gpt_2 LPC11xx GPT driver implementation features * - Each timer can be independently enabled and programmed. Unused * peripherals are left in low power mode. - * - Programmable TIMx interrupts priority level. + * - Programmable CTxxBy interrupts priority level. * . * @ingroup LPC11xx */ diff --git a/os/hal/platforms/LPC13xx/gpt_lld.c b/os/hal/platforms/LPC13xx/gpt_lld.c new file mode 100644 index 000000000..e6a112d61 --- /dev/null +++ b/os/hal/platforms/LPC13xx/gpt_lld.c @@ -0,0 +1,341 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file LPC13xx/gpt_lld.c + * @brief LPC13xx GPT subsystem low level driver source. + * + * @addtogroup GPT + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#if HAL_USE_GPT || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief GPT1 driver identifier. + * @note The driver GPT1 allocates the complex timer CT16B0 when enabled. + */ +#if LPC13xx_GPT_USE_CT16B0 || defined(__DOXYGEN__) +GPTDriver GPTD1; +#endif + +/** + * @brief GPT2 driver identifier. + * @note The driver GPT2 allocates the timer CT16B1 when enabled. + */ +#if LPC13xx_GPT_USE_CT16B1 || defined(__DOXYGEN__) +GPTDriver GPTD2; +#endif + +/** + * @brief GPT3 driver identifier. + * @note The driver GPT3 allocates the timer CT32B0 when enabled. + */ +#if LPC13xx_GPT_USE_CT32B0 || defined(__DOXYGEN__) +GPTDriver GPTD3; +#endif + +/** + * @brief GPT4 driver identifier. + * @note The driver GPT4 allocates the timer CT32B1 when enabled. + */ +#if LPC13xx_GPT_USE_CT32B1 || defined(__DOXYGEN__) +GPTDriver GPTD4; +#endif + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Shared IRQ handler. + * + * @param[in] gptp pointer to a @p GPTDriver object + */ +static void gpt_lld_serve_interrupt(GPTDriver *gptp) { + + gptp->tmr->IR = 1; /* Clear interrupt on match MR0.*/ + if (gptp->state == GPT_ONESHOT) { + gptp->state = GPT_READY; /* Back in GPT_READY state. */ + gpt_lld_stop_timer(gptp); /* Timer automatically stopped. */ + } + gptp->config->callback(gptp); +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if LPC13xx_GPT_USE_CT16B0 +/** + * @brief CT16B0 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(VectorE4) { + + CH_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD1); + + CH_IRQ_EPILOGUE(); +} +#endif /* LPC13xx_GPT_USE_CT16B0 */ + +#if LPC13xx_GPT_USE_CT16B1 +/** + * @brief CT16B1 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(VectorE8) { + + CH_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD2); + + CH_IRQ_EPILOGUE(); +} +#endif /* LPC13xx_GPT_USE_CT16B0 */ + +#if LPC13xx_GPT_USE_CT32B0 +/** + * @brief CT32B0 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(VectorEC) { + + CH_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD3); + + CH_IRQ_EPILOGUE(); +} +#endif /* LPC13xx_GPT_USE_CT32B0 */ + +#if LPC13xx_GPT_USE_CT32B1 +/** + * @brief CT32B1 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(VectorF0) { + + CH_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD4); + + CH_IRQ_EPILOGUE(); +} +#endif /* LPC13xx_GPT_USE_CT32B1 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level GPT driver initialization. + * + * @notapi + */ +void gpt_lld_init(void) { + +#if LPC13xx_GPT_USE_CT16B0 + /* Driver initialization.*/ + GPTD1.tmr = LPC_TMR16B0; + gptObjectInit(&GPTD1); +#endif + +#if LPC13xx_GPT_USE_CT16B1 + /* Driver initialization.*/ + GPTD2.tmr = LPC_TMR16B1; + gptObjectInit(&GPTD2); +#endif + +#if LPC13xx_GPT_USE_CT32B0 + /* Driver initialization.*/ + GPTD3.tmr = LPC_TMR32B0; + gptObjectInit(&GPTD3); +#endif + +#if LPC13xx_GPT_USE_CT32B1 + /* Driver initialization.*/ + GPTD4.tmr = LPC_TMR32B1; + gptObjectInit(&GPTD4); +#endif +} + +/** + * @brief Configures and activates the GPT peripheral. + * + * @param[in] gptp pointer to the @p GPTDriver object + * + * @notapi + */ +void gpt_lld_start(GPTDriver *gptp) { + uint32_t pr; + + if (gptp->state == GPT_STOP) { + /* Clock activation.*/ +#if LPC13xx_GPT_USE_CT16B0 + if (&GPTD1 == gptp) { + LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 7); + NVICEnableVector(TIMER_16_0_IRQn, CORTEX_PRIORITY_MASK(2)); + } +#endif +#if LPC13xx_GPT_USE_CT16B1 + if (&GPTD2 == gptp) { + LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 8); + NVICEnableVector(TIMER_16_1_IRQn, CORTEX_PRIORITY_MASK(3)); + } +#endif +#if LPC13xx_GPT_USE_CT32B0 + if (&GPTD3 == gptp) { + LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 9); + NVICEnableVector(TIMER_32_0_IRQn, CORTEX_PRIORITY_MASK(2)); + } +#endif +#if LPC13xx_GPT_USE_CT32B1 + if (&GPTD4 == gptp) { + LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 10); + NVICEnableVector(TIMER_32_1_IRQn, CORTEX_PRIORITY_MASK(2)); + } +#endif + } + + /* Prescaler value calculation.*/ + pr = (uint16_t)((LPC13xx_SYSCLK / gptp->config->frequency) - 1); + chDbgAssert(((uint32_t)(pr + 1) * gptp->config->frequency) == LPC13xx_SYSCLK, + "gpt_lld_start(), #1", "invalid frequency"); + + /* Timer configuration.*/ + gptp->tmr->PR = pr; + gptp->tmr->IR = 1; + gptp->tmr->MCR = 0; + gptp->tmr->TCR = 0; +} + +/** + * @brief Deactivates the GPT peripheral. + * + * @param[in] gptp pointer to the @p GPTDriver object + * + * @notapi + */ +void gpt_lld_stop(GPTDriver *gptp) { + + if (gptp->state == GPT_READY) { + gptp->tmr->MCR = 0; + gptp->tmr->TCR = 0; + +#if LPC13xx_GPT_USE_CT16B0 + if (&GPTD1 == gptp) { + NVICDisableVector(TIMER_16_0_IRQn); + LPC_SYSCON->SYSAHBCLKCTRL &= ~(1 << 7); + } +#endif +#if LPC13xx_GPT_USE_CT16B1 + if (&GPTD2 == gptp) { + NVICDisableVector(TIMER_16_1_IRQn); + LPC_SYSCON->SYSAHBCLKCTRL &= ~(1 << 8); + } +#endif +#if LPC13xx_GPT_USE_CT32B0 + if (&GPTD3 == gptp) { + NVICDisableVector(TIMER_32_0_IRQn); + LPC_SYSCON->SYSAHBCLKCTRL &= ~(1 << 9); + } +#endif +#if LPC13xx_GPT_USE_CT32B1 + if (&GPTD4 == gptp) { + NVICDisableVector(TIMER_32_1_IRQn); + LPC_SYSCON->SYSAHBCLKCTRL &= ~(1 << 10); + } +#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->tmr->MR0 = interval - 1; + gptp->tmr->IR = 1; + gptp->tmr->MCR = 3; /* IRQ and clr TC on match MR0. */ + gptp->tmr->TCR = 2; /* Reset counter and prescaler. */ + gptp->tmr->TCR = 1; /* Timer enabled. */ +} + +/** + * @brief Stops the timer. + * + * @param[in] gptp pointer to the @p GPTDriver object + * + * @notapi + */ +void gpt_lld_stop_timer(GPTDriver *gptp) { + + gptp->tmr->IR = 1; + gptp->tmr->MCR = 0; + gptp->tmr->TCR = 0; +} + +/** + * @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->tmr->MR0 = interval - 1; + gptp->tmr->IR = 1; + gptp->tmr->MCR = 4; /* Stop TC on match MR0. */ + gptp->tmr->TCR = 2; /* Reset counter and prescaler. */ + gptp->tmr->TCR = 1; /* Timer enabled. */ + while (gptp->tmr->TCR & 1) + ; +} + +#endif /* HAL_USE_GPT */ + +/** @} */ diff --git a/os/hal/platforms/LPC13xx/gpt_lld.h b/os/hal/platforms/LPC13xx/gpt_lld.h new file mode 100644 index 000000000..9be8179c3 --- /dev/null +++ b/os/hal/platforms/LPC13xx/gpt_lld.h @@ -0,0 +1,223 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file LPC13xx/gpt_lld.h + * @brief LPC13xx GPT subsystem low level driver header. + * + * @addtogroup GPT + * @{ + */ + +#ifndef _GPT_LLD_H_ +#define _GPT_LLD_H_ + +#if HAL_USE_GPT || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief GPT1 driver enable switch. + * @details If set to @p TRUE the support for GPT1 is included. + * @note The default is @p TRUE. + */ +#if !defined(LPC13xx_GPT_USE_CT16B0) || defined(__DOXYGEN__) +#define LPC13xx_GPT_USE_CT16B0 TRUE +#endif + +/** + * @brief GPT2 driver enable switch. + * @details If set to @p TRUE the support for GPT2 is included. + * @note The default is @p TRUE. + */ +#if !defined(LPC13xx_GPT_USE_CT16B1) || defined(__DOXYGEN__) +#define LPC13xx_GPT_USE_CT16B1 TRUE +#endif + +/** + * @brief GPT3 driver enable switch. + * @details If set to @p TRUE the support for GPT3 is included. + * @note The default is @p TRUE. + */ +#if !defined(LPC13xx_GPT_USE_CT32B0) || defined(__DOXYGEN__) +#define LPC13xx_GPT_USE_CT32B0 TRUE +#endif + +/** + * @brief GPT4 driver enable switch. + * @details If set to @p TRUE the support for GPT4 is included. + * @note The default is @p TRUE. + */ +#if !defined(LPC13xx_GPT_USE_CT32B1) || defined(__DOXYGEN__) +#define LPC13xx_GPT_USE_CT32B1 TRUE +#endif + +/** + * @brief GPT1 interrupt priority level setting. + */ +#if !defined(LPC13xx_GPT_CT16B0_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define LPC13xx_GPT_CT16B0_IRQ_PRIORITY 2 +#endif + +/** + * @brief GPT2 interrupt priority level setting. + */ +#if !defined(LPC13xx_GPT_CT16B1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define LPC13xx_GPT_CT16B1_IRQ_PRIORITY 2 +#endif + +/** + * @brief GPT3 interrupt priority level setting. + */ +#if !defined(LPC13xx_GPT_CT32B0_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define LPC13xx_GPT_CT32B0_IRQ_PRIORITY 2 +#endif + +/** + * @brief GPT4 interrupt priority level setting. + */ +#if !defined(LPC13xx_GPT_CT32B1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define LPC13xx_GPT_CT32B1_IRQ_PRIORITY 2 +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !LPC13xx_GPT_USE_CT16B0 && !LPC13xx_GPT_USE_CT16B1 && \ + !LPC13xx_GPT_USE_CT32B0 && !LPC13xx_GPT_USE_CT32B1 +#error "GPT driver activated but no CT peripheral assigned" +#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 Type of a structure representing a GPT driver. + */ +typedef struct GPTDriver GPTDriver; + +/** + * @brief GPT notification callback type. + * + * @param[in] gptp pointer to a @p GPTDriver object + */ +typedef void (*gptcallback_t)(GPTDriver *gptp); + +/** + * @brief Driver configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct { + /** + * @brief Timer clock in Hz. + * @note The low level can use assertions in order to catch invalid + * frequency specifications. + */ + gptfreq_t frequency; + /** + * @brief Timer callback pointer. + * @note This callback is invoked on GPT counter events. + */ + gptcallback_t callback; + /* End of the mandatory fields.*/ +} GPTConfig; + +/** + * @brief Structure representing a GPT driver. + */ +struct GPTDriver { + /** + * @brief Driver state. + */ + gptstate_t state; + /** + * @brief Current configuration data. + */ + const GPTConfig *config; + /* End of the mandatory fields.*/ + /** + * @brief Timer base clock. + */ + uint32_t clock; + /** + * @brief Pointer to the CTxxBy registers block. + */ + LPC_TMR_TypeDef *tmr; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if LPC13xx_GPT_USE_CT16B0 && !defined(__DOXYGEN__) +extern GPTDriver GPTD1; +#endif + +#if LPC13xx_GPT_USE_CT16B1 && !defined(__DOXYGEN__) +extern GPTDriver GPTD2; +#endif + +#if LPC13xx_GPT_USE_CT32B0 && !defined(__DOXYGEN__) +extern GPTDriver GPTD3; +#endif + +#if LPC13xx_GPT_USE_CT32B1 && !defined(__DOXYGEN__) +extern GPTDriver GPTD4; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void gpt_lld_init(void); + void gpt_lld_start(GPTDriver *gptp); + void gpt_lld_stop(GPTDriver *gptp); + void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t period); + void gpt_lld_stop_timer(GPTDriver *gptp); + void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_GPT */ + +#endif /* _GPT_LLD_H_ */ + +/** @} */ diff --git a/os/hal/platforms/LPC13xx/platform.dox b/os/hal/platforms/LPC13xx/platform.dox index 54b90b6dd..00715dd9f 100644 --- a/os/hal/platforms/LPC13xx/platform.dox +++ b/os/hal/platforms/LPC13xx/platform.dox @@ -42,6 +42,24 @@ * @ingroup LPC13xx */ +/** + * @defgroup LPC13xx_GPT LPC13xx GPT Support + * @details The LPC13xx GPT driver uses the CTxxBy peripherals. + * + * @section lpc13xx_gpt_1 Supported HW resources + * - CT16B0. + * - CT16B1. + * - CT32B0. + * - CT32B1. + * . + * @section lpc13xx_gpt_2 LPC13xx GPT driver implementation features + * - Each timer can be independently enabled and programmed. Unused + * peripherals are left in low power mode. + * - Programmable CTxxBy interrupts priority level. + * . + * @ingroup LPC13xx + */ + /** * @defgroup LPC13xx_PAL LPC13xx PAL Support * @details The LPC13xx PAL driver uses the GPIO peripherals. diff --git a/os/hal/platforms/LPC13xx/platform.mk b/os/hal/platforms/LPC13xx/platform.mk index 66c39058e..1171af7d7 100644 --- a/os/hal/platforms/LPC13xx/platform.mk +++ b/os/hal/platforms/LPC13xx/platform.mk @@ -1,5 +1,6 @@ # List of all the LPC13xx platform files. PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/LPC13xx/hal_lld.c \ + ${CHIBIOS}/os/hal/platforms/LPC13xx/gpt_lld.c \ ${CHIBIOS}/os/hal/platforms/LPC13xx/pal_lld.c \ ${CHIBIOS}/os/hal/platforms/LPC13xx/serial_lld.c \ ${CHIBIOS}/os/hal/platforms/LPC13xx/spi_lld.c