From 321ec844af3b1e7a23c94bce65bc8aa13ef1e09e Mon Sep 17 00:00:00 2001 From: Stephane D'Alu Date: Sun, 10 Jul 2016 19:15:46 +0200 Subject: moved GPT to LLD --- os/hal/ports/NRF5/LLD/hal_gpt_lld.c | 359 +++++++++++++++++++++++++++++++ os/hal/ports/NRF5/LLD/hal_gpt_lld.h | 264 +++++++++++++++++++++++ os/hal/ports/NRF5/LLD/hal_st_lld.h | 1 + os/hal/ports/NRF5/NRF51822/hal_gpt_lld.c | 358 ------------------------------ os/hal/ports/NRF5/NRF51822/hal_gpt_lld.h | 264 ----------------------- os/hal/ports/NRF5/NRF51822/platform.mk | 4 +- os/hal/ports/NRF5/NRF52832/platform.mk | 4 + 7 files changed, 630 insertions(+), 624 deletions(-) create mode 100644 os/hal/ports/NRF5/LLD/hal_gpt_lld.c create mode 100644 os/hal/ports/NRF5/LLD/hal_gpt_lld.h delete mode 100644 os/hal/ports/NRF5/NRF51822/hal_gpt_lld.c delete mode 100644 os/hal/ports/NRF5/NRF51822/hal_gpt_lld.h (limited to 'os/hal') diff --git a/os/hal/ports/NRF5/LLD/hal_gpt_lld.c b/os/hal/ports/NRF5/LLD/hal_gpt_lld.c new file mode 100644 index 0000000..e850e31 --- /dev/null +++ b/os/hal/ports/NRF5/LLD/hal_gpt_lld.c @@ -0,0 +1,359 @@ +/* + ChibiOS - 2015 Stephen Caudle + + 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 NRF5/LLD/hal_gpt_lld.c + * @brief NRF5 GPT subsystem low level driver source. + * + * @addtogroup GPT + * @{ + */ + +#include "hal.h" + +#if HAL_USE_GPT || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define NRF5_TIMER_PRESCALER_NUM 10 +#define NRF5_TIMER_COMPARE_NUM 4 + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief GPTD1 driver identifier. + * @note The driver GPTD1 allocates the complex timer TIM1 when enabled. + */ +#if NRF5_GPT_USE_TIMER0 || defined(__DOXYGEN__) +GPTDriver GPTD1; +#endif + +/** + * @brief GPTD2 driver identifier. + * @note The driver GPTD2 allocates the timer TIM2 when enabled. + */ +#if NRF5_GPT_USE_TIMER1 || defined(__DOXYGEN__) +GPTDriver GPTD2; +#endif + +/** + * @brief GPTD3 driver identifier. + * @note The driver GPTD3 allocates the timer TIM3 when enabled. + */ +#if NRF5_GPT_USE_TIMER2 || defined(__DOXYGEN__) +GPTDriver GPTD3; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static uint8_t prescaler(uint16_t freq) +{ + uint8_t i; + static const gptfreq_t frequencies[] = { + NRF5_GPT_FREQ_16MHZ, + NRF5_GPT_FREQ_8MHZ, + NRF5_GPT_FREQ_4MHZ, + NRF5_GPT_FREQ_2MHZ, + NRF5_GPT_FREQ_1MHZ, + NRF5_GPT_FREQ_500KHZ, + NRF5_GPT_FREQ_250KHZ, + NRF5_GPT_FREQ_125KHZ, + NRF5_GPT_FREQ_62500HZ, + NRF5_GPT_FREQ_31250HZ, + }; + + for (i = 0; i < NRF5_TIMER_PRESCALER_NUM; i++) + if (freq == frequencies[i]) + return i; + + osalDbgAssert(FALSE, "invalid timer frequency"); + + return 0; +} + +/** + * @brief Shared IRQ handler. + * + * @param[in] gptp pointer to a @p GPTDriver object + */ +static void gpt_lld_serve_interrupt(GPTDriver *gptp) { + + gptp->tim->EVENTS_COMPARE[gptp->cc_int] = 0; + (void)gptp->tim->EVENTS_COMPARE[gptp->cc_int]; + if (gptp->state == GPT_ONESHOT) + gptp->state = GPT_READY; /* Back in GPT_READY state. */ + gptp->config->callback(gptp); +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if NRF5_GPT_USE_TIMER0 +/** + * @brief TIMER0 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector60) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD1); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* NRF5_GPT_USE_TIMER0 */ + +#if NRF5_GPT_USE_TIMER1 +/** + * @brief TIMER1 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector64) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD2); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* NRF5_GPT_USE_TIMER1 */ + +#if NRF5_GPT_USE_TIMER2 +/** + * @brief TIMER2 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector68) { + + OSAL_IRQ_PROLOGUE(); + + gpt_lld_serve_interrupt(&GPTD3); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* NRF5_GPT_USE_TIMER2 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level GPT driver initialization. + * + * @notapi + */ +void gpt_lld_init(void) { + +#if NRF5_GPT_USE_TIMER0 + /* Driver initialization.*/ + GPTD1.tim = NRF_TIMER0; + gptObjectInit(&GPTD1); +#endif + +#if NRF5_GPT_USE_TIMER1 + /* Driver initialization.*/ + GPTD2.tim = NRF_TIMER1; + gptObjectInit(&GPTD2); +#endif + +#if NRF5_GPT_USE_TIMER2 + /* Driver initialization.*/ + GPTD3.tim = NRF_TIMER2; + gptObjectInit(&GPTD3); +#endif +} + +/** + * @brief Configures and activates the GPT peripheral. + * + * @param[in] gptp pointer to the @p GPTDriver object + * + * @notapi + */ +void gpt_lld_start(GPTDriver *gptp) { + + NRF_TIMER_Type *tim = gptp->tim; + + if (gptp->state == GPT_STOP) { + osalDbgAssert(gptp->cc_int < NRF5_TIMER_COMPARE_NUM, + "invalid capture/compare index"); + + tim->INTENSET = TIMER_INTENSET_COMPARE0_Msk << gptp->cc_int; +#if NRF5_GPT_USE_TIMER0 + if (&GPTD1 == gptp) + nvicEnableVector(TIMER0_IRQn, NRF5_GPT_TIMER0_IRQ_PRIORITY); +#endif +#if NRF5_GPT_USE_TIMER1 + if (&GPTD2 == gptp) + nvicEnableVector(TIMER1_IRQn, NRF5_GPT_TIMER1_IRQ_PRIORITY); +#endif +#if NRF5_GPT_USE_TIMER2 + if (&GPTD3 == gptp) + nvicEnableVector(TIMER2_IRQn, NRF5_GPT_TIMER2_IRQ_PRIORITY); +#endif + } + + /* Prescaler value calculation.*/ + tim->PRESCALER = prescaler(gptp->config->frequency); + + /* Timer configuration.*/ + tim->MODE = TIMER_MODE_MODE_Timer << TIMER_MODE_MODE_Pos; + + switch (gptp->config->resolution) { + + case 8: + tim->BITMODE = TIMER_BITMODE_BITMODE_08Bit << TIMER_BITMODE_BITMODE_Pos; + break; + + case 16: + tim->BITMODE = TIMER_BITMODE_BITMODE_16Bit << TIMER_BITMODE_BITMODE_Pos; + break; + +#if NRF5_GPT_USE_TIMER0 + case 24: + tim->BITMODE = TIMER_BITMODE_BITMODE_24Bit << TIMER_BITMODE_BITMODE_Pos; + break; + + case 32: + tim->BITMODE = TIMER_BITMODE_BITMODE_32Bit << TIMER_BITMODE_BITMODE_Pos; + break; +#endif + + default: + osalDbgAssert(FALSE, "invalid timer resolution"); + break; + }; +} + +/** + * @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->TASKS_SHUTDOWN = 1; + +#if NRF5_GPT_USE_TIMER0 + if (&GPTD1 == gptp) + nvicDisableVector(TIMER0_IRQn); +#endif +#if NRF5_GPT_USE_TIMER1 + if (&GPTD2 == gptp) + nvicDisableVector(TIMER1_IRQn); +#endif +#if NRF5_GPT_USE_TIMER2 + if (&GPTD3 == gptp) + nvicDisableVector(TIMER2_IRQn); +#endif + gptp->tim->INTENCLR = TIMER_INTENSET_COMPARE0_Msk << gptp->cc_int; + } +} + +/** + * @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) { + + NRF_TIMER_Type *tim = gptp->tim; + + tim->TASKS_CLEAR = 1; + tim->CC[gptp->cc_int] = (uint32_t)(interval - 1); /* Time constant. */ + if (gptp->state == GPT_ONESHOT) + gptp->tim->SHORTS = TIMER_SHORTS_COMPARE0_STOP_Msk << gptp->cc_int; + else if (gptp->state == GPT_CONTINUOUS) + gptp->tim->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Msk << gptp->cc_int; + tim->TASKS_START = 1; +} + +/** + * @brief Stops the timer. + * + * @param[in] gptp pointer to the @p GPTDriver object + * + * @notapi + */ +void gpt_lld_stop_timer(GPTDriver *gptp) { + + gptp->tim->TASKS_STOP = 1; +} + +/** + * @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) { + + NRF_TIMER_Type *tim = gptp->tim; + + tim->INTENCLR = (1UL << gptp->cc_int) << TIMER_INTENSET_COMPARE0_Pos; + tim->TASKS_CLEAR = 1; + tim->CC[gptp->cc_int] = (uint32_t)(interval - 1); /* Time constant. */ + tim->TASKS_START = 1; + while (!(tim->INTENSET & (TIMER_INTENSET_COMPARE0_Msk << gptp->cc_int))) + ; + tim->INTENSET = TIMER_INTENSET_COMPARE0_Msk << gptp->cc_int; +} + +/** + * @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 + */ +gptcnt_t gpt_lld_get_counter(GPTDriver *gptp) { + + gptp->tim->TASKS_CAPTURE[gptp->cc_get] = 1; + return gptp->tim->CC[gptp->cc_get]; +} + +#endif /* HAL_USE_GPT */ + +/** @} */ diff --git a/os/hal/ports/NRF5/LLD/hal_gpt_lld.h b/os/hal/ports/NRF5/LLD/hal_gpt_lld.h new file mode 100644 index 0000000..4173a3a --- /dev/null +++ b/os/hal/ports/NRF5/LLD/hal_gpt_lld.h @@ -0,0 +1,264 @@ +/* + Copyright (C) 2015 Stephen Caudle + + 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 NRF5/LLD/gpt_lld.h + * @brief NRF5 GPT subsystem low level driver header. + * + * @addtogroup GPT + * @{ + */ + +#ifndef HAL_GPT_LLD_H +#define HAL_GPT_LLD_H + +#if HAL_USE_GPT || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief GPTD1 driver enable switch. + * @details If set to @p TRUE the support for GPTD1 is included. + * @note The default is @p TRUE. + */ +#if !defined(NRF5_GPT_USE_TIMER0) || defined(__DOXYGEN__) +#define NRF5_GPT_USE_TIMER0 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(NRF5_GPT_USE_TIMER1) || defined(__DOXYGEN__) +#define NRF5_GPT_USE_TIMER1 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(NRF5_GPT_USE_TIMER2) || defined(__DOXYGEN__) +#define NRF5_GPT_USE_TIMER2 FALSE +#endif + +/** + * @brief GPTD1 interrupt priority level setting. + */ +#if !defined(NRF5_GPT_TIMER0_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define NRF5_GPT_TIMER0_IRQ_PRIORITY 3 +#endif + +/** + * @brief GPTD2 interrupt priority level setting. + */ +#if !defined(NRF5_GPT_TIMER1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define NRF5_GPT_TIMER1_IRQ_PRIORITY 3 +#endif + +/** + * @brief GPTD3 interrupt priority level setting. + */ +#if !defined(NRF5_GPT_TIMER2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define NRF5_GPT_TIMER2_IRQ_PRIORITY 3 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !NRF5_GPT_USE_TIMER0 && !NRF5_GPT_USE_TIMER1 && \ + !NRF5_GPT_USE_TIMER2 +#error "GPT driver activated but no TIMER peripheral assigned" +#endif + +#if NRF5_GPT_USE_TIMER0 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(NRF5_GPT_TIMER0_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIMER0" +#endif + +#if NRF5_GPT_USE_TIMER1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(NRF5_GPT_TIMER1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIMER1" +#endif + +#if NRF5_GPT_USE_TIMER2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(NRF5_GPT_TIMER2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to TIMER2" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief GPT frequency type. + */ +typedef enum { + NRF5_GPT_FREQ_31250HZ = 31250, + NRF5_GPT_FREQ_62500HZ = 62500, + NRF5_GPT_FREQ_125KHZ = 125000, + NRF5_GPT_FREQ_250KHZ = 250000, + NRF5_GPT_FREQ_500KHZ = 500000, + NRF5_GPT_FREQ_1MHZ = 1000000, + NRF5_GPT_FREQ_2MHZ = 2000000, + NRF5_GPT_FREQ_4MHZ = 4000000, + NRF5_GPT_FREQ_8MHZ = 8000000, + NRF5_GPT_FREQ_16MHZ = 16000000, +} 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 The timer resolution in bits (8/16/24/32) + * @note The default value of this field is 16 bits + * @note The 24 and 32 bit modes are only valid for TIMER0 + */ + uint8_t resolution; +} 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 Pointer to the TIMERx registers block. + */ + NRF_TIMER_Type *tim; + /** + * @brief Index of the TIMERx capture/compare register used for setting the + * interval between compare events. + */ + uint8_t cc_int; + /** + * @brief Index of the TIMERx capture/compare register used for getting the + * current timer counter value. + */ + uint8_t cc_get; +}; + +/*===========================================================================*/ +/* 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->CC[(gptp)->cc_int] = (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->CC[(gptp)->cc_int]) + 1) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if NRF5_GPT_USE_TIMER0 && !defined(__DOXYGEN__) +extern GPTDriver GPTD1; +#endif + +#if NRF5_GPT_USE_TIMER1 && !defined(__DOXYGEN__) +extern GPTDriver GPTD2; +#endif + +#if NRF5_GPT_USE_TIMER2 && !defined(__DOXYGEN__) +extern GPTDriver GPTD3; +#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); + gptcnt_t gpt_lld_get_counter(GPTDriver *gptp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_GPT */ + +#endif /* HAL_GPT_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/NRF5/LLD/hal_st_lld.h b/os/hal/ports/NRF5/LLD/hal_st_lld.h index 9d67ce9..7073e12 100644 --- a/os/hal/ports/NRF5/LLD/hal_st_lld.h +++ b/os/hal/ports/NRF5/LLD/hal_st_lld.h @@ -124,6 +124,7 @@ #error "Invalid IRQ priority assigned to ST driver" #endif + /*===========================================================================*/ /* Driver data structures and types. */ /*===========================================================================*/ diff --git a/os/hal/ports/NRF5/NRF51822/hal_gpt_lld.c b/os/hal/ports/NRF5/NRF51822/hal_gpt_lld.c deleted file mode 100644 index 3fb14dd..0000000 --- a/os/hal/ports/NRF5/NRF51822/hal_gpt_lld.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - ChibiOS - 2015 Stephen Caudle - - 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 NRF51x22/gpt_lld.c - * @brief NRF51x22 GPT subsystem low level driver source. - * - * @addtogroup GPT - * @{ - */ - -#include "hal.h" - -#if HAL_USE_GPT || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define NRF5_TIMER_PRESCALER_NUM 10 -#define NRF5_TIMER_COMPARE_NUM 4 - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** - * @brief GPTD1 driver identifier. - * @note The driver GPTD1 allocates the complex timer TIM1 when enabled. - */ -#if NRF5_GPT_USE_TIMER0 || defined(__DOXYGEN__) -GPTDriver GPTD1; -#endif - -/** - * @brief GPTD2 driver identifier. - * @note The driver GPTD2 allocates the timer TIM2 when enabled. - */ -#if NRF5_GPT_USE_TIMER1 || defined(__DOXYGEN__) -GPTDriver GPTD2; -#endif - -/** - * @brief GPTD3 driver identifier. - * @note The driver GPTD3 allocates the timer TIM3 when enabled. - */ -#if NRF5_GPT_USE_TIMER2 || defined(__DOXYGEN__) -GPTDriver GPTD3; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -static uint8_t prescaler(uint16_t freq) -{ - uint8_t i; - static const gptfreq_t frequencies[] = { - NRF5_GPT_FREQ_16MHZ, - NRF5_GPT_FREQ_8MHZ, - NRF5_GPT_FREQ_4MHZ, - NRF5_GPT_FREQ_2MHZ, - NRF5_GPT_FREQ_1MHZ, - NRF5_GPT_FREQ_500KHZ, - NRF5_GPT_FREQ_250KHZ, - NRF5_GPT_FREQ_125KHZ, - NRF5_GPT_FREQ_62500HZ, - NRF5_GPT_FREQ_31250HZ, - }; - - for (i = 0; i < NRF5_TIMER_PRESCALER_NUM; i++) - if (freq == frequencies[i]) - return i; - - osalDbgAssert(FALSE, "invalid timer frequency"); - - return 0; -} - -/** - * @brief Shared IRQ handler. - * - * @param[in] gptp pointer to a @p GPTDriver object - */ -static void gpt_lld_serve_interrupt(GPTDriver *gptp) { - - gptp->tim->EVENTS_COMPARE[gptp->cc_int] = 0; - if (gptp->state == GPT_ONESHOT) - gptp->state = GPT_READY; /* Back in GPT_READY state. */ - gptp->config->callback(gptp); -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if NRF5_GPT_USE_TIMER0 -/** - * @brief TIMER0 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector60) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD1); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* NRF5_GPT_USE_TIMER0 */ - -#if NRF5_GPT_USE_TIMER1 -/** - * @brief TIMER1 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector64) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD2); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* NRF5_GPT_USE_TIMER1 */ - -#if NRF5_GPT_USE_TIMER2 -/** - * @brief TIMER2 interrupt handler. - * - * @isr - */ -OSAL_IRQ_HANDLER(Vector68) { - - OSAL_IRQ_PROLOGUE(); - - gpt_lld_serve_interrupt(&GPTD3); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* NRF5_GPT_USE_TIMER2 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level GPT driver initialization. - * - * @notapi - */ -void gpt_lld_init(void) { - -#if NRF5_GPT_USE_TIMER0 - /* Driver initialization.*/ - GPTD1.tim = NRF_TIMER0; - gptObjectInit(&GPTD1); -#endif - -#if NRF5_GPT_USE_TIMER1 - /* Driver initialization.*/ - GPTD2.tim = NRF_TIMER1; - gptObjectInit(&GPTD2); -#endif - -#if NRF5_GPT_USE_TIMER2 - /* Driver initialization.*/ - GPTD3.tim = NRF_TIMER2; - gptObjectInit(&GPTD3); -#endif -} - -/** - * @brief Configures and activates the GPT peripheral. - * - * @param[in] gptp pointer to the @p GPTDriver object - * - * @notapi - */ -void gpt_lld_start(GPTDriver *gptp) { - - NRF_TIMER_Type *tim = gptp->tim; - - if (gptp->state == GPT_STOP) { - osalDbgAssert(gptp->cc_int < NRF5_TIMER_COMPARE_NUM, - "invalid capture/compare index"); - - tim->INTENSET = TIMER_INTENSET_COMPARE0_Msk << gptp->cc_int; -#if NRF5_GPT_USE_TIMER0 - if (&GPTD1 == gptp) - nvicEnableVector(TIMER0_IRQn, NRF5_GPT_TIMER0_IRQ_PRIORITY); -#endif -#if NRF5_GPT_USE_TIMER1 - if (&GPTD2 == gptp) - nvicEnableVector(TIMER1_IRQn, NRF5_GPT_TIMER1_IRQ_PRIORITY); -#endif -#if NRF5_GPT_USE_TIMER2 - if (&GPTD3 == gptp) - nvicEnableVector(TIMER2_IRQn, NRF5_GPT_TIMER2_IRQ_PRIORITY); -#endif - } - - /* Prescaler value calculation.*/ - tim->PRESCALER = prescaler(gptp->config->frequency); - - /* Timer configuration.*/ - tim->MODE = TIMER_MODE_MODE_Timer << TIMER_MODE_MODE_Pos; - - switch (gptp->config->resolution) { - - case 8: - tim->BITMODE = TIMER_BITMODE_BITMODE_08Bit << TIMER_BITMODE_BITMODE_Pos; - break; - - case 16: - tim->BITMODE = TIMER_BITMODE_BITMODE_16Bit << TIMER_BITMODE_BITMODE_Pos; - break; - -#if NRF5_GPT_USE_TIMER0 - case 24: - tim->BITMODE = TIMER_BITMODE_BITMODE_24Bit << TIMER_BITMODE_BITMODE_Pos; - break; - - case 32: - tim->BITMODE = TIMER_BITMODE_BITMODE_32Bit << TIMER_BITMODE_BITMODE_Pos; - break; -#endif - - default: - osalDbgAssert(FALSE, "invalid timer resolution"); - break; - }; -} - -/** - * @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->TASKS_SHUTDOWN = 1; - -#if NRF5_GPT_USE_TIMER0 - if (&GPTD1 == gptp) - nvicDisableVector(TIMER0_IRQn); -#endif -#if NRF5_GPT_USE_TIMER1 - if (&GPTD2 == gptp) - nvicDisableVector(TIMER1_IRQn); -#endif -#if NRF5_GPT_USE_TIMER2 - if (&GPTD3 == gptp) - nvicDisableVector(TIMER2_IRQn); -#endif - gptp->tim->INTENCLR = TIMER_INTENSET_COMPARE0_Msk << gptp->cc_int; - } -} - -/** - * @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) { - - NRF_TIMER_Type *tim = gptp->tim; - - tim->TASKS_CLEAR = 1; - tim->CC[gptp->cc_int] = (uint32_t)(interval - 1); /* Time constant. */ - if (gptp->state == GPT_ONESHOT) - gptp->tim->SHORTS = TIMER_SHORTS_COMPARE0_STOP_Msk << gptp->cc_int; - else if (gptp->state == GPT_CONTINUOUS) - gptp->tim->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Msk << gptp->cc_int; - tim->TASKS_START = 1; -} - -/** - * @brief Stops the timer. - * - * @param[in] gptp pointer to the @p GPTDriver object - * - * @notapi - */ -void gpt_lld_stop_timer(GPTDriver *gptp) { - - gptp->tim->TASKS_STOP = 1; -} - -/** - * @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) { - - NRF_TIMER_Type *tim = gptp->tim; - - tim->INTENCLR = (1UL << gptp->cc_int) << TIMER_INTENSET_COMPARE0_Pos; - tim->TASKS_CLEAR = 1; - tim->CC[gptp->cc_int] = (uint32_t)(interval - 1); /* Time constant. */ - tim->TASKS_START = 1; - while (!(tim->INTENSET & (TIMER_INTENSET_COMPARE0_Msk << gptp->cc_int))) - ; - tim->INTENSET = TIMER_INTENSET_COMPARE0_Msk << gptp->cc_int; -} - -/** - * @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 - */ -gptcnt_t gpt_lld_get_counter(GPTDriver *gptp) { - - gptp->tim->TASKS_CAPTURE[gptp->cc_get] = 1; - return gptp->tim->CC[gptp->cc_get]; -} - -#endif /* HAL_USE_GPT */ - -/** @} */ diff --git a/os/hal/ports/NRF5/NRF51822/hal_gpt_lld.h b/os/hal/ports/NRF5/NRF51822/hal_gpt_lld.h deleted file mode 100644 index 5ce7a95..0000000 --- a/os/hal/ports/NRF5/NRF51822/hal_gpt_lld.h +++ /dev/null @@ -1,264 +0,0 @@ -/* - Copyright (C) 2015 Stephen Caudle - - 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 NRF51x22/gpt_lld.h - * @brief NRF51x22 GPT subsystem low level driver header. - * - * @addtogroup GPT - * @{ - */ - -#ifndef HAL_GPT_LLD_H -#define HAL_GPT_LLD_H - -#if HAL_USE_GPT || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief GPTD1 driver enable switch. - * @details If set to @p TRUE the support for GPTD1 is included. - * @note The default is @p TRUE. - */ -#if !defined(NRF5_GPT_USE_TIMER0) || defined(__DOXYGEN__) -#define NRF5_GPT_USE_TIMER0 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(NRF5_GPT_USE_TIMER1) || defined(__DOXYGEN__) -#define NRF5_GPT_USE_TIMER1 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(NRF5_GPT_USE_TIMER2) || defined(__DOXYGEN__) -#define NRF5_GPT_USE_TIMER2 FALSE -#endif - -/** - * @brief GPTD1 interrupt priority level setting. - */ -#if !defined(NRF5_GPT_TIMER0_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define NRF5_GPT_TIMER0_IRQ_PRIORITY 3 -#endif - -/** - * @brief GPTD2 interrupt priority level setting. - */ -#if !defined(NRF5_GPT_TIMER1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define NRF5_GPT_TIMER1_IRQ_PRIORITY 3 -#endif - -/** - * @brief GPTD3 interrupt priority level setting. - */ -#if !defined(NRF5_GPT_TIMER2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define NRF5_GPT_TIMER2_IRQ_PRIORITY 3 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if !NRF5_GPT_USE_TIMER0 && !NRF5_GPT_USE_TIMER1 && \ - !NRF5_GPT_USE_TIMER2 -#error "GPT driver activated but no TIMER peripheral assigned" -#endif - -#if NRF5_GPT_USE_TIMER0 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(NRF5_GPT_TIMER0_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIMER0" -#endif - -#if NRF5_GPT_USE_TIMER1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(NRF5_GPT_TIMER1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIMER1" -#endif - -#if NRF5_GPT_USE_TIMER2 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(NRF5_GPT_TIMER2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to TIMER2" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief GPT frequency type. - */ -typedef enum { - NRF5_GPT_FREQ_31250HZ = 31250, - NRF5_GPT_FREQ_62500HZ = 62500, - NRF5_GPT_FREQ_125KHZ = 125000, - NRF5_GPT_FREQ_250KHZ = 250000, - NRF5_GPT_FREQ_500KHZ = 500000, - NRF5_GPT_FREQ_1MHZ = 1000000, - NRF5_GPT_FREQ_2MHZ = 2000000, - NRF5_GPT_FREQ_4MHZ = 4000000, - NRF5_GPT_FREQ_8MHZ = 8000000, - NRF5_GPT_FREQ_16MHZ = 16000000, -} 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 The timer resolution in bits (8/16/24/32) - * @note The default value of this field is 16 bits - * @note The 24 and 32 bit modes are only valid for TIMER0 - */ - uint8_t resolution; -} 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 Pointer to the TIMERx registers block. - */ - NRF_TIMER_Type *tim; - /** - * @brief Index of the TIMERx capture/compare register used for setting the - * interval between compare events. - */ - uint8_t cc_int; - /** - * @brief Index of the TIMERx capture/compare register used for getting the - * current timer counter value. - */ - uint8_t cc_get; -}; - -/*===========================================================================*/ -/* 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->CC[(gptp)->cc_int] = (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->CC[(gptp)->cc_int]) + 1) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if NRF5_GPT_USE_TIMER0 && !defined(__DOXYGEN__) -extern GPTDriver GPTD1; -#endif - -#if NRF5_GPT_USE_TIMER1 && !defined(__DOXYGEN__) -extern GPTDriver GPTD2; -#endif - -#if NRF5_GPT_USE_TIMER2 && !defined(__DOXYGEN__) -extern GPTDriver GPTD3; -#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); - gptcnt_t gpt_lld_get_counter(GPTDriver *gptp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_GPT */ - -#endif /* HAL_GPT_LLD_H */ - -/** @} */ diff --git a/os/hal/ports/NRF5/NRF51822/platform.mk b/os/hal/ports/NRF5/NRF51822/platform.mk index 9ddbeee..8631487 100644 --- a/os/hal/ports/NRF5/NRF51822/platform.mk +++ b/os/hal/ports/NRF5/NRF51822/platform.mk @@ -26,7 +26,7 @@ ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),) PLATFORMSRC += ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/NRF51822/hal_adc_lld.c endif ifneq ($(findstring HAL_USE_GPT TRUE,$(HALCONF)),) -PLATFORMSRC += ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/NRF51822/hal_gpt_lld.c +PLATFORMSRC += ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/hal_gpt_lld.c endif ifneq ($(findstring HAL_USE_WDG TRUE,$(HALCONF)),) PLATFORMSRC += ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/hal_wdg_lld.c @@ -51,7 +51,7 @@ PLATFORMSRC = ${CHIBIOS}/os/hal/ports/common/ARMCMx/nvic.c \ ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/NRF51822/hal_ext_lld.c \ ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/NRF51822/hal_i2c_lld.c \ ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/NRF51822/hal_adc_lld.c \ - ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/NRF51822/hal_gpt_lld.c \ + ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/hal_gpt_lld.c \ ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/hal_wdg_lld.c \ ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/hal_rng_lld.c \ ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/NRF51822/hal_pwm_lld.c \ diff --git a/os/hal/ports/NRF5/NRF52832/platform.mk b/os/hal/ports/NRF5/NRF52832/platform.mk index fd3912c..57ae88d 100644 --- a/os/hal/ports/NRF5/NRF52832/platform.mk +++ b/os/hal/ports/NRF5/NRF52832/platform.mk @@ -12,6 +12,9 @@ endif ifneq ($(findstring HAL_USE_SERIAL TRUE,$(HALCONF)),) PLATFORMSRC += ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/hal_serial_lld.c endif +ifneq ($(findstring HAL_USE_GPT TRUE,$(HALCONF)),) +PLATFORMSRC += ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/hal_gpt_lld.c +endif ifneq ($(findstring HAL_USE_WDG TRUE,$(HALCONF)),) PLATFORMSRC += ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/hal_wdg_lld.c endif @@ -24,6 +27,7 @@ PLATFORMSRC = ${CHIBIOS}/os/hal/ports/common/ARMCMx/nvic.c \ ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/hal_pal_lld.c \ ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/hal_serial_lld.c \ ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/hal_st_lld.c \ + ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/hal_gpt_lld.c \ ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/hal_wdg_lld.c \ ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/hal_rng_lld.c endif -- cgit v1.2.3