diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2014-10-23 06:54:24 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2014-10-23 06:54:24 -0600 |
commit | cdeb35bd1c35391541c44457f80b22b6b71c3a3b (patch) | |
tree | bbd7f8244cb11b0640d43ae34df0e5209fc14a87 /nuttx/arch/arm/src/lpc43xx | |
parent | 8b015cffbb4892d8c662daa5f0293517b5ef0bb1 (diff) | |
download | nuttx-cdeb35bd1c35391541c44457f80b22b6b71c3a3b.tar.gz nuttx-cdeb35bd1c35391541c44457f80b22b6b71c3a3b.tar.bz2 nuttx-cdeb35bd1c35391541c44457f80b22b6b71c3a3b.zip |
Add support for tickless operation using the NXP LPC43xx
Diffstat (limited to 'nuttx/arch/arm/src/lpc43xx')
-rw-r--r-- | nuttx/arch/arm/src/lpc43xx/Kconfig | 6 | ||||
-rw-r--r-- | nuttx/arch/arm/src/lpc43xx/Make.defs | 4 | ||||
-rw-r--r-- | nuttx/arch/arm/src/lpc43xx/chip/lpc43_rit.h | 1 | ||||
-rw-r--r-- | nuttx/arch/arm/src/lpc43xx/lpc43_rit.c | 248 | ||||
-rw-r--r-- | nuttx/arch/arm/src/lpc43xx/lpc43_rit.h | 68 |
5 files changed, 327 insertions, 0 deletions
diff --git a/nuttx/arch/arm/src/lpc43xx/Kconfig b/nuttx/arch/arm/src/lpc43xx/Kconfig index 87c3cd920..80bb19606 100644 --- a/nuttx/arch/arm/src/lpc43xx/Kconfig +++ b/nuttx/arch/arm/src/lpc43xx/Kconfig @@ -66,26 +66,32 @@ endchoice config ARCH_FAMILY_LPC4310 bool default y if ARCH_CHIP_LPC4310FBD144 || ARCH_CHIP_LPC4310FET100 + select ARCH_HAVE_TICKLESS config ARCH_FAMILY_LPC4320 bool default y if ARCH_CHIP_LPC4320FBD144 || ARCH_CHIP_LPC4320FET100 + select ARCH_HAVE_TICKLESS config ARCH_FAMILY_LPC4330 bool default y if ARCH_CHIP_LPC4330FBD144 || ARCH_CHIP_LPC4330FET100 || ARCH_CHIP_LPC4330FET180 || ARCH_CHIP_LPC4330FET256 + select ARCH_HAVE_TICKLESS config ARCH_FAMILY_LPC4350 bool default y if ARCH_CHIP_LPC4350FBD208 || ARCH_CHIP_LPC4350FET180 || ARCH_CHIP_LPC4350FET256 + select ARCH_HAVE_TICKLESS config ARCH_FAMILY_LPC4353 bool default y if ARCH_CHIP_LPC4353FBD208 || ARCH_CHIP_LPC4353FET180 || ARCH_CHIP_LPC4353FET256 + select ARCH_HAVE_TICKLESS config ARCH_FAMILY_LPC4357 bool default y if ARCH_CHIP_LPC4357FET180 || ARCH_CHIP_LPC4357FBD208 || ARCH_CHIP_LPC4357FET256 + select ARCH_HAVE_TICKLESS choice prompt "LPC43XX Boot Configuration" diff --git a/nuttx/arch/arm/src/lpc43xx/Make.defs b/nuttx/arch/arm/src/lpc43xx/Make.defs index 9e28dffc9..2a302a36e 100644 --- a/nuttx/arch/arm/src/lpc43xx/Make.defs +++ b/nuttx/arch/arm/src/lpc43xx/Make.defs @@ -128,6 +128,10 @@ CHIP_CSRCS += lpc43_ssp.c endif endif +ifeq ($(CONFIG_LPC43_RIT),y) +CHIP_CSRCS += lpc43_rit.c +endif + ifeq ($(CONFIG_LPC43_I2C0),y) CHIP_CSRCS += lpc43_i2c.c else diff --git a/nuttx/arch/arm/src/lpc43xx/chip/lpc43_rit.h b/nuttx/arch/arm/src/lpc43xx/chip/lpc43_rit.h index 915836e80..85aba157c 100644 --- a/nuttx/arch/arm/src/lpc43xx/chip/lpc43_rit.h +++ b/nuttx/arch/arm/src/lpc43xx/chip/lpc43_rit.h @@ -41,6 +41,7 @@ ************************************************************************************/ #include <nuttx/config.h> +#include "chip/lpc4310203050_memorymap.h" /************************************************************************************ * Pre-processor Definitions diff --git a/nuttx/arch/arm/src/lpc43xx/lpc43_rit.c b/nuttx/arch/arm/src/lpc43xx/lpc43_rit.c new file mode 100644 index 000000000..2ee8c70be --- /dev/null +++ b/nuttx/arch/arm/src/lpc43xx/lpc43_rit.c @@ -0,0 +1,248 @@ +/**************************************************************************** + * arch/arm/src/lpc43/lpc43_rit.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Brandon Warhurst <warhurst_002@yahoo.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <arch/board/board.h> +#include <nuttx/config.h> + +#include <nuttx/arch.h> +#include <errno.h> + +#include "up_arch.h" +#include "chip/lpc43_rit.h" +#include "lpc43_rit.h" + +#ifdef CONFIG_LPC43_RIT + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* set the timer resolution at 1uS + * + * This is a battery waster, but I need this kind of resolution for 1-wire + * protocols... Until I can find a better way to implement them. + */ + +#define RIT_TIMER_RESOLUTION 250 + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static double sec_per_tick; +static uint64_t internal_timer, alarm; +struct timespec g_ts; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int lpc43_RIT_isr(int irq, FAR void *context) +{ + irqstate_t flags; + + flags = irqsave(); + + putreg32(RIT_CTRL_INT,LPC43_RIT_CTRL); + + internal_timer += (uint64_t)RIT_TIMER_RESOLUTION; + if (alarm > 0 && internal_timer >= alarm) + { + /* handle expired alarm */ + + g_ts.tv_sec = (uint32_t)(internal_timer / 1000000000); + g_ts.tv_nsec = (uint32_t)(internal_timer % 1000000000); + sched_alarm_expiration(&g_ts); + } + + irqrestore(flags); + return OK; +} + +static inline void lpc43_load_RIT_timer(uint32_t value) +{ + putreg32(value, LPC43_RIT_COUNTER); +} + +static inline void lpc43_load_RIT_compare(uint32_t value) +{ + putreg32(value, LPC43_RIT_COMPVAL); +} + +static inline void lpc43_set_RIT_timer_mask(uint32_t value) +{ + putreg32(value, LPC43_RIT_MASK); +} + +static inline uint32_t lpc43_read_RIT_timer(void) +{ + return getreg32(LPC43_RIT_COUNTER); +} + +static inline void lpc43_RIT_timer_start(void) +{ + uint32_t regval; + regval = getreg32(LPC43_RIT_CTRL); + + /* Since a cycle timer is in use here, the timer clear is enabled. If + * using the timer directly, this likely should not be used. Also, clear + * the interrupt flag. + */ + + regval |= RIT_CTRL_INT | RIT_CTRL_EN | RIT_CTRL_ENCLR; + putreg32(regval, LPC43_RIT_CTRL); +} + +static inline void lpc43_RIT_timer_stop(void) +{ + uint32_t regval; + regval = getreg32(LPC43_RIT_CTRL); + regval &= ~RIT_CTRL_EN; + putreg32(regval, LPC43_RIT_CTRL); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void up_timer_initialize(void) +{ + uint32_t ticks_per_int; + uint32_t mask_bits = 0; + uint32_t mask_test = 0x80000000; + + lpc43_RIT_timer_stop(); + lpc43_load_RIT_timer(0); + internal_timer = 0; + + /* Set up the IRQ here */ + + irq_attach(LPC43M4_IRQ_RITIMER, lpc43_RIT_isr); + + /* Compute how many seconds per tick we have on the main clock. If it is + * 204MHz for example, then there should be about 4.90ns per tick + */ + + sec_per_tick = (double)1.0/(double)LPC43_CCLK; + + /* Given an RIT_TIMER_RESOLUTION, compute how many ticks it will take to + * reach that resolution. For example, if we wanted a 1/4uS timer + * resolution, that would be 250ns resolution. The timer is an integer + * value, although maybe this should change, but that means + * 250/1000000000*0.00000000490 = 51.02 ticks or 51 ticks, roughly. + */ + + ticks_per_int = RIT_TIMER_RESOLUTION/(1000000000*sec_per_tick)+1; + + /* Now we need to compute the mask that will let us set up to generate an + * interrupt every 1/4uS. This isn't "tickless" per-se, and probably + * should be implemented differently, however it allows me to create a + * 64 bit nanosecond timer than can "free-run" by being updated every + * RIT_TIMER_RESOLUTION cycles. I would have implemented the better + * approach, but I didn't have a good way to determine how to manage a + * 32 bit ns timer. Every 21 seconds the thing rolls over, so you'd have + * to set up the compare interrupt to handle the roll over. It WOULD be + * fewer interrupts, but it seemed to make things more complicated. When + * I have a better idea, I'll change this. + */ + + while(!((mask_test >> mask_bits) & ticks_per_int)) mask_bits++; + + lldbg("mask_bits = %d, mask = %X, ticks_per_int = %d\r\n", + mask_bits, (0xFFFFFFFF<<(32 - mask_bits)), ticks_per_int); + + /* Set the mask and compare value so we get interrupts every + * RIT_TIMER_RESOLUTION cycles. + */ + + lpc43_set_RIT_timer_mask((0xFFFFFFFF << (32 - mask_bits))); + lpc43_load_RIT_compare(ticks_per_int); + + /* Turn on the IRQ */ + + up_enable_irq(LPC43M4_IRQ_RITIMER); + + /* Start the timer */ + + lpc43_RIT_timer_start(); +} + +int up_timer_gettime(FAR struct timespec *ts) +{ + ts->tv_sec = (uint32_t)(internal_timer / 1000000000); + ts->tv_nsec = (uint32_t)(internal_timer % 1000000000); + + return OK; +} + +int up_alarm_cancel(FAR struct timespec *ts) +{ + ts->tv_sec = (uint32_t)(internal_timer / 1000000000); + ts->tv_nsec = (uint32_t)(internal_timer % 1000000000); + alarm = 0; + return OK; +} + +int up_alarm_start(FAR const struct timespec *ts) +{ + alarm = (uint64_t)ts->tv_sec * (uint64_t)1000000000 + (uint64_t)ts->tv_nsec; + return OK; +} + +int up_timer_cancel(FAR struct timespec *ts) +{ + /* Currently this is just an alarm and both are implemented. This is *NOT* + * how it is supposed to be and will be corrected, but for now, this is a + * simple way to implement both. + */ + + return up_alarm_cancel(ts); +} + +int up_timer_start(FAR const struct timespec *ts) +{ + /* Currently this is just an alarm and both are implemented. This is *NOT* + * how it is supposed to be and will be corrected, but for now, this is a + * simple way to implement both. + */ + + return up_alarm_start(ts); +} + +#endif /* CONFIG_LPC43_RIT */ diff --git a/nuttx/arch/arm/src/lpc43xx/lpc43_rit.h b/nuttx/arch/arm/src/lpc43xx/lpc43_rit.h new file mode 100644 index 000000000..8ef367bc4 --- /dev/null +++ b/nuttx/arch/arm/src/lpc43xx/lpc43_rit.h @@ -0,0 +1,68 @@ +/***************************************************************************** + * arch/arm/src/lpc43xx/lpc43_rit.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_LPC43XX_LPC43_RIT_H +#define __ARCH_ARM_SRC_LPC43XX_LPC43_RIT_H + +/***************************************************************************** + * Included Files + *****************************************************************************/ + +#include <nuttx/config.h> + +/***************************************************************************** + * Pre-processor Definitions + *****************************************************************************/ + +/***************************************************************************** + * Public Types + *****************************************************************************/ + +/***************************************************************************** + * Public Data + *****************************************************************************/ + +/************************************************************************************ + * Public Functions + *****************************************************************************/ + +void up_timer_initialize(void); +int up_timer_gettime(FAR struct timespec *ts); +int up_alarm_cancel(FAR struct timespec *ts); +int up_alarm_start(FAR const struct timespec *ts); +int up_timer_cancel(FAR struct timespec *ts); +int up_timer_start(FAR const struct timespec *ts); + +#endif /* __ARCH_ARM_SRC_LPC43XX_LPC43_RIT_H */ |