From 7dbc25b02ba12a4e005e72ab42f4e60e0da36634 Mon Sep 17 00:00:00 2001 From: Alan Carvalho de Assis Date: Wed, 23 Nov 2016 13:33:51 -0600 Subject: [PATCH] LPC43xx: Add timer driver; configs/bambino-200e: Add support for timer driver --- arch/arm/src/lpc43xx/Kconfig | 10 +- arch/arm/src/lpc43xx/Make.defs | 6 +- arch/arm/src/lpc43xx/chip/lpc43_timer.h | 4 + arch/arm/src/lpc43xx/lpc43_timer.c | 771 +++++++++++++++++++++++ arch/arm/src/lpc43xx/lpc43_timer.h | 100 +++ configs/bambino-200e/nsh/defconfig | 16 +- configs/bambino-200e/src/Makefile | 4 + configs/bambino-200e/src/bambino-200e.h | 14 + configs/bambino-200e/src/lpc43_appinit.c | 10 +- configs/bambino-200e/src/lpc43_timer.c | 125 ++++ 10 files changed, 1054 insertions(+), 6 deletions(-) create mode 100644 arch/arm/src/lpc43xx/lpc43_timer.c create mode 100644 arch/arm/src/lpc43xx/lpc43_timer.h create mode 100644 configs/bambino-200e/src/lpc43_timer.c diff --git a/arch/arm/src/lpc43xx/Kconfig b/arch/arm/src/lpc43xx/Kconfig index c063fd86c7..b597090dca 100644 --- a/arch/arm/src/lpc43xx/Kconfig +++ b/arch/arm/src/lpc43xx/Kconfig @@ -269,8 +269,9 @@ config LPC43_SSP1 default n config LPC43_TMR0 - bool "ADC1" + bool "Timer 0" default n + select LPC43_TIMER config LPC43_TMR1 bool "Timer 1" @@ -279,10 +280,17 @@ config LPC43_TMR1 config LPC43_TMR2 bool "Timer 2" default n + select LPC43_TIMER config LPC43_TMR3 bool "Timer 3" default n + select LPC43_TIMER + +config LPC43_TIMER + bool + default n + select ARCH_HAVE_EXTCLK config LPC43_USART0 bool "USART0" diff --git a/arch/arm/src/lpc43xx/Make.defs b/arch/arm/src/lpc43xx/Make.defs index 79ddaa4a02..c0d95a2799 100644 --- a/arch/arm/src/lpc43xx/Make.defs +++ b/arch/arm/src/lpc43xx/Make.defs @@ -154,6 +154,10 @@ CHIP_CSRCS += lpc43_ssp.c endif endif +ifeq ($(CONFIG_LPC43_TIMER),y) +CHIP_CSRCS += lpc43_timer.c +endif + ifeq ($(CONFIG_LPC43_RIT),y) CHIP_CSRCS += lpc43_rit.c endif @@ -196,4 +200,4 @@ CHIP_CSRCS += lpc43_usb0dev.c endif endif --include chip/spifi/src/Make.defs \ No newline at end of file +-include chip/spifi/src/Make.defs diff --git a/arch/arm/src/lpc43xx/chip/lpc43_timer.h b/arch/arm/src/lpc43xx/chip/lpc43_timer.h index 109b8c8b7f..b62f1352a3 100644 --- a/arch/arm/src/lpc43xx/chip/lpc43_timer.h +++ b/arch/arm/src/lpc43xx/chip/lpc43_timer.h @@ -42,10 +42,14 @@ #include +#include "chip.h" + /************************************************************************************ * Pre-processor Definitions ************************************************************************************/ +#define TMR_RVALUE_MASK (0xffffffff) + /* Register offsets *****************************************************************/ #define LPC43_TMR_IR_OFFSET 0x0000 /* Interrupt Register */ diff --git a/arch/arm/src/lpc43xx/lpc43_timer.c b/arch/arm/src/lpc43xx/lpc43_timer.c new file mode 100644 index 0000000000..0d8b35c911 --- /dev/null +++ b/arch/arm/src/lpc43xx/lpc43_timer.c @@ -0,0 +1,771 @@ +/**************************************************************************** + * arch/arm/src/lpc43/lpc43_timer.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * Alan Carvalho de Assis + * + * 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 +#include + +#include + +#include +#include +#include + +#include +#include +#include + +#include "up_arch.h" +#include "lpc43_timer.h" + +#if defined(CONFIG_TIMER) && (defined(CONFIG_LPC43_TMR0) || \ + defined(CONFIG_LPC43_TMR1) || defined(CONFIG_LPC43_TMR2) || \ + defined(CONFIG_LPC43_TMR3) ) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ + +#ifndef CONFIG_DEBUG_TIMER_INFO +# undef CONFIG_LPC43_TMR_REGDEBUG +#endif + +/* Clocking *****************************************************************/ + +/* TODO: Allow selection of any of the input clocks */ + +#define TMR_FCLK (BOARD_FCLKOUT_FREQUENCY) +#define TMR_MAXTIMEOUT ((1000000ULL * (1ULL + TMR_RVALUE_MASK)) / TMR_FCLK) + +/**************************************************************************** + * Private Types + ****************************************************************************/ +/* This structure provides the private representation of the "lower-half" + * driver state structure. This structure must be cast-compatible with the + * timer_lowerhalf_s structure. + */ + +struct lpc43_lowerhalf_s +{ + FAR const struct timer_ops_s *ops; /* Lower half operations */ + + /* Private data */ + + uint32_t base; /* Base address of the timer */ + tccb_t callback; /* Current user interrupt callback */ + FAR void *arg; /* Argument passed to the callback function */ + uint32_t timeout; /* The current timeout value (us) */ + uint32_t adjustment; /* time lost due to clock resolution truncation (us) */ + uint32_t clkticks; /* actual clock ticks for current interval */ + bool started; /* The timer has been started */ + uint16_t tmrid; /* Timer id */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ +/* Register operations ******************************************************/ + +#ifdef CONFIG_LPC43_TMR_REGDEBUG +static uint32_t lpc43_getreg(uint32_t addr); +static void lpc43_putreg(uint32_t val, uint32_t addr); +#else +# define lpc43_getreg(addr) getreg32(addr) +# define lpc43_putreg(val,addr) putreg32(val,addr) +#endif + +/* Interrupt handling *******************************************************/ + +static int lpc43_interrupt(int irq, FAR void *context); + +/* "Lower half" driver methods **********************************************/ + +static int lpc43_start(FAR struct timer_lowerhalf_s *lower); +static int lpc43_stop(FAR struct timer_lowerhalf_s *lower); +static int lpc43_getstatus(FAR struct timer_lowerhalf_s *lower, + FAR struct timer_status_s *status); +static int lpc43_settimeout(FAR struct timer_lowerhalf_s *lower, + uint32_t timeout); +static void lpc43_setcallback(FAR struct timer_lowerhalf_s *lower, + tccb_t callback, FAR void *arg); +static int lpc43_ioctl(FAR struct timer_lowerhalf_s *lower, int cmd, + unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* "Lower half" driver methods */ + +static const struct timer_ops_s g_tmrops = +{ + .start = lpc43_start, + .stop = lpc43_stop, + .getstatus = lpc43_getstatus, + .settimeout = lpc43_settimeout, + .setcallback = lpc43_setcallback, + .ioctl = lpc43_ioctl, +}; + +/* "Lower half" driver state */ + +/* TODO - allocating all 6 now, even though we might not need them. + * May want to allocate the right number to not be wasteful. + */ + +static struct lpc43_lowerhalf_s g_tmrdevs[4]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lpc43_getreg + * + * Description: + * Get the contents of a register + * + ****************************************************************************/ + +#ifdef CONFIG_LPC43_TMR_REGDEBUG +static uint32_t lpc43_getreg(uint32_t addr) +{ + static uint32_t prevaddr = 0; + static uint32_t count = 0; + static uint32_t preval = 0; + + /* Read the value from the register */ + + uint32_t val = getreg32(addr); + + /* Is this the same value that we read from the same registe last time? + * Are we polling the register? If so, suppress some of the output. + */ + + if (addr == prevaddr && val == preval) + { + if (count == 0xffffffff || ++count > 3) + { + if (count == 4) + { + tmrinfo("...\n"); + } + + return val; + } + } + + /* No this is a new address or value */ + + else + { + /* Did we print "..." for the previous value? */ + + if (count > 3) + { + /* Yes.. then show how many times the value repeated */ + + tmrinfo("[repeats %d more times]\n", count-3); + } + + /* Save the new address, value, and count */ + + prevaddr = addr; + preval = val; + count = 1; + } + + /* Show the register value read */ + + tmrinfo("%08lx->%08lx\n", addr, val); + return val; +} +#endif + +/**************************************************************************** + * Name: lpc43_putreg + * + * Description: + * Set the contents of an LPC43 register to a value + * + ****************************************************************************/ + +#ifdef CONFIG_LPC43_TMR_REGDEBUG +static void lpc43_putreg(uint32_t val, uint32_t addr) +{ + /* Show the register value being written */ + + tmrinfo("%08lx<-%08lx\n", addr, val); + + /* Write the value */ + + putreg32(val, addr); +} +#endif + +void tmr_clk_enable(uint16_t tmrid) +{ + uint32_t regval; + + /* Enable Timer 0 */ + + if (tmrid == 0) + { + regval = getreg32(LPC43_CCU1_M4_TIMER0_CFG); + regval |= CCU_CLK_CFG_RUN; + putreg32(regval, LPC43_CCU1_M4_TIMER0_CFG); + } + + /* Enable Timer 1 */ + + if (tmrid == 1) + { + regval = getreg32(LPC43_CCU1_M4_TIMER1_CFG); + regval |= CCU_CLK_CFG_RUN; + putreg32(regval, LPC43_CCU1_M4_TIMER1_CFG); + } + + /* Enable Timer 2 */ + + if (tmrid == 2) + { + regval = getreg32(LPC43_CCU1_M4_TIMER2_CFG); + regval |= CCU_CLK_CFG_RUN; + putreg32(regval, LPC43_CCU1_M4_TIMER2_CFG); + } + + /* Enable Timer 3 */ + + if (tmrid == 3) + { + regval = getreg32(LPC43_CCU1_M4_TIMER3_CFG); + regval |= CCU_CLK_CFG_RUN; + putreg32(regval, LPC43_CCU1_M4_TIMER3_CFG); + } +} + +void tmr_clk_disable(uint16_t tmrid) +{ + uint32_t regval; + + /* Enable Timer 0 */ + + if (tmrid == 0) + { + regval = getreg32(LPC43_CCU1_M4_TIMER0_CFG); + regval &= ~CCU_CLK_CFG_RUN; + putreg32(regval, LPC43_CCU1_M4_TIMER0_CFG); + } + + /* Enable Timer 1 */ + + if (tmrid == 1) + { + regval = getreg32(LPC43_CCU1_M4_TIMER1_CFG); + regval &= ~CCU_CLK_CFG_RUN; + putreg32(regval, LPC43_CCU1_M4_TIMER1_CFG); + } + + /* Enable Timer 2 */ + + if (tmrid == 2) + { + regval = getreg32(LPC43_CCU1_M4_TIMER2_CFG); + regval &= ~CCU_CLK_CFG_RUN; + putreg32(regval, LPC43_CCU1_M4_TIMER2_CFG); + } + + /* Enable Timer 3 */ + + if (tmrid == 3) + { + regval = getreg32(LPC43_CCU1_M4_TIMER3_CFG); + regval &= ~CCU_CLK_CFG_RUN; + putreg32(regval, LPC43_CCU1_M4_TIMER3_CFG); + } +} + +/**************************************************************************** + * Name: lpc43_interrupt + * + * Description: + * TC interrupt + * + * Input Parameters: + * Usual interrupt callback arguments. + * + * Returned Values: + * Always returns OK. + * + ****************************************************************************/ + +static int lpc43_interrupt(int irq, FAR void *context) +{ + uint8_t chan_int = 0x0f; + FAR struct lpc43_lowerhalf_s *priv = &g_tmrdevs[irq-LPC43M4_IRQ_TIMER0]; + + tmrinfo("Entry\n"); + DEBUGASSERT((irq >= LPC43M4_IRQ_TIMER0) && (irq <= LPC43M4_IRQ_TIMER3)); + + /* Check if the interrupt is really pending */ + + if ((lpc43_getreg(priv->base + LPC43_TMR_IR_OFFSET) & chan_int) != 0) + { + uint32_t timeout; + + /* Is there a registered callback? If the callback has been + * nullified, the timer will be stopped. + */ + + if (priv->callback && priv->callback(&priv->timeout, priv->arg)) + { + /* Calculate new ticks / dither adjustment */ + + priv->clkticks =((uint64_t)(priv->adjustment + priv->timeout)) * + TMR_FCLK / 1000000; + + /* Set next interval interval. TODO: make sure the interval is not + * so soon it will be missed! + */ + + lpc43_putreg(priv->clkticks, priv->base + LPC43_TMR_PR_OFFSET); + + /* Truncated timeout */ + + timeout = (1000000ULL * priv->clkticks) / TMR_FCLK; + + /* Truncated time to be added to next interval (dither) */ + + priv->adjustment = (priv->adjustment + priv->timeout) - timeout; + } + else + { + /* No callback or the callback returned false.. stop the timer */ + + lpc43_stop((FAR struct timer_lowerhalf_s *)priv); + tmrinfo("Stopped\n"); + } + + /* Clear the interrupts */ + + lpc43_putreg(chan_int, priv->base + LPC43_TMR_IR_OFFSET); + } + + return OK; +} + +/**************************************************************************** + * Name: lpc43_start + * + * Description: + * Start the timer, resetting the time to the current timeout, + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower-half" + * driver state structure. + * + * Returned Values: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int lpc43_start(FAR struct timer_lowerhalf_s *lower) +{ + FAR struct lpc43_lowerhalf_s *priv = (FAR struct lpc43_lowerhalf_s *)lower; + uint32_t presc_val; + + tmrinfo("Entry\n"); + DEBUGASSERT(priv); + + if (priv->started) + { + return -EINVAL; + } + + /* Enable timer clock */ + + tmr_clk_enable(priv->tmrid); + + /* Set it to Timer Mode */ + + lpc43_putreg(0, priv->base + LPC43_TMR_CTCR_OFFSET); + + /* Disable the timer */ + + lpc43_putreg(0, priv->base + LPC43_TMR_TCR_OFFSET); + + /* Set prescaler to increase TC each 1 us */ + + presc_val = TMR_FCLK / 1000000; + lpc43_putreg(presc_val - 1, priv->base + LPC43_TMR_PR_OFFSET); + + /* Set MR0 with a large enough initial value */ + + lpc43_putreg(10000000, priv->base + LPC43_TMR_MR0_OFFSET); + + if (priv->callback) + { + /* Enable Match on MR0 generate interrupt and auto-restart */ + + lpc43_putreg(3, priv->base + LPC43_TMR_MCR_OFFSET); + } + + /* Enable the timer */ + + lpc43_putreg(TMR_TCR_EN, priv->base + LPC43_TMR_TCR_OFFSET); + + priv->started = true; + return OK; +} + +/**************************************************************************** + * Name: lpc43_stop + * + * Description: + * Stop the timer + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower-half" + * driver state structure. + * + * Returned Values: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int lpc43_stop(FAR struct timer_lowerhalf_s *lower) +{ + FAR struct lpc43_lowerhalf_s *priv = (FAR struct lpc43_lowerhalf_s *)lower; + tmrinfo("Entry\n"); + DEBUGASSERT(priv); + + if (!priv->started) + { + return -EINVAL; + } + + /* Disable timer */ + + lpc43_putreg(0, priv->base + LPC43_TMR_TCR_OFFSET); + + /* Disable interrupt */ + + lpc43_putreg(0, priv->base + LPC43_TMR_MCR_OFFSET); + + /* Disable timer clock */ + + tmr_clk_disable(priv->tmrid); + + priv->started = false; + + return OK; +} + +/**************************************************************************** + * Name: lpc43_getstatus + * + * Description: + * Get the current timer status + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower- + * half" driver state structure. + * status - The location to return the status information. + * + * Returned Values: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int lpc43_getstatus(FAR struct timer_lowerhalf_s *lower, + FAR struct timer_status_s *status) +{ + FAR struct lpc43_lowerhalf_s *priv = (FAR struct lpc43_lowerhalf_s *)lower; + uint32_t elapsed; + + tmrinfo("Entry\n"); + DEBUGASSERT(priv); + + /* Return the status bit */ + + status->flags = 0; + if (priv->started) + { + status->flags |= TCFLAGS_ACTIVE; + } + + if (priv->callback) + { + status->flags |= TCFLAGS_HANDLER; + } + + /* Return the actual timeout is milliseconds */ + + status->timeout = priv->timeout; + + /* Get the time remaining until the timer expires (in microseconds) */ + /* TODO - check on the +1 in the time left calculation */ + + elapsed = lpc43_getreg(priv->base + LPC43_TMR_TC_OFFSET); + status->timeleft = ((uint64_t)priv->timeout * elapsed) / + (priv->clkticks + 1); + + tmrinfo(" flags : %08x\n", status->flags); + tmrinfo(" timeout : %d\n", status->timeout); + tmrinfo(" timeleft : %d\n", status->timeleft); + return OK; +} + +/**************************************************************************** + * Name: lpc43_settimeout + * + * Description: + * Set a new timeout value (and reset the timer) + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower + * half" driver state structure. + * timeout - The new timeout value in milliseconds. + * + * Returned Values: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int lpc43_settimeout(FAR struct timer_lowerhalf_s *lower, + uint32_t timeout) +{ + FAR struct lpc43_lowerhalf_s *priv = (FAR struct lpc43_lowerhalf_s *)lower; + + DEBUGASSERT(priv); + + if (priv->started) + { + return -EPERM; + } + + tmrinfo("Entry: timeout=%d\n", timeout); + + /* Can this timeout be represented? */ + + if (timeout < 1 || timeout > TMR_MAXTIMEOUT) + { + tmrerr("ERROR: Cannot represent timeout=%lu > %lu\n", + timeout, TMR_MAXTIMEOUT); + return -ERANGE; + } + + /* Intended timeout */ + + priv->timeout = timeout; + + /* Actual clock ticks */ + + priv->clkticks = (((uint64_t)timeout * TMR_FCLK) / 1000000); + + /* Truncated timeout */ + + timeout = (1000000ULL * priv->clkticks) / TMR_FCLK; + + /* Truncated time to be added to next interval (dither) */ + + priv->adjustment = priv->timeout - timeout; + + tmrinfo("fclk=%d clkticks=%d timout=%d, adjustment=%d\n", + TMR_FCLK, priv->clkticks, priv->timeout, priv->adjustment); + + return OK; +} + +/**************************************************************************** + * Name: lpc43_setcallback + * + * Description: + * Call this user provided timeout callback. + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower-half" + * driver state structure. + * newcallback - The new timer expiration function pointer. If this + * function pointer is NULL, then the reset-on-expiration + * behavior is restored, + * + * Returned Values: + * The previous timer expiration function pointer or NULL is there was + * no previous function pointer. + * + ****************************************************************************/ + +static void lpc43_setcallback(FAR struct timer_lowerhalf_s *lower, + tccb_t callback, FAR void *arg) +{ + FAR struct lpc43_lowerhalf_s *priv = (FAR struct lpc43_lowerhalf_s *)lower; + irqstate_t flags; + + flags = enter_critical_section(); + + DEBUGASSERT(priv); + tmrinfo("Entry: callback=%p\n", callback); + + /* Save the new callback and its argument */ + + priv->callback = callback; + priv->arg = arg; + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: lpc43_ioctl + * + * Description: + * Any ioctl commands that are not recognized by the "upper-half" driver + * are forwarded to the lower half driver through this method. + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower-half" + * driver state structure. + * cmd - The ioctl command value + * arg - The optional argument that accompanies the 'cmd'. The + * interpretation of this argument depends on the particular + * command. + * + * Returned Values: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int lpc43_ioctl(FAR struct timer_lowerhalf_s *lower, int cmd, + unsigned long arg) +{ + FAR struct lpc43_lowerhalf_s *priv = (FAR struct lpc43_lowerhalf_s *)lower; + int ret = -ENOTTY; + + DEBUGASSERT(priv); + tmrinfo("Entry: cmd=%d arg=%ld\n", cmd, arg); + UNUSED(priv); + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lpc43_tmrinitialize + * + * Description: + * Initialize the timer. The timer is initialized and + * registers as 'devpath'. + * + * Input Parameters: + * devpath - The full path to the timer. This should be of the form + * /dev/tmr0 + * + * Returned Values: + * None + * + ****************************************************************************/ + +void lpc43_tmrinitialize(FAR const char *devpath, int irq) +{ + FAR struct lpc43_lowerhalf_s *priv = &g_tmrdevs[irq-LPC43M4_IRQ_TIMER0]; + + tmrinfo("Entry: devpath=%s\n", devpath); + DEBUGASSERT((irq >= LPC43M4_IRQ_TIMER0) && (irq <= LPC43M4_IRQ_TIMER3)); + + /* Initialize the driver state structure. Here we assume: (1) the state + * structure lies in .bss and was zeroed at reset time. (2) This function + * is only called once so it is never necessary to re-zero the structure. + */ + + switch (irq) + { +#if defined(CONFIG_LPC43_TMR0) + case LPC43M4_IRQ_TIMER0: + priv->base = LPC43_TIMER0_BASE; + priv->tmrid = 0; + tmrinfo("Using: Timer 0"); + break; +#endif + +#if defined(CONFIG_LPC43_TMR1) + case LPC43M4_IRQ_TIMER1: + priv->base = LPC43_TIMER1_BASE; + priv->tmrid = 1; + tmrinfo("Using: Timer 1"); + break; +#endif + +#if defined(CONFIG_LPC43_TMR2) + case LPC43M4_IRQ_TIMER2: + priv->base = LPC43_TIMER2_BASE; + priv->tmrid = 2; + tmrinfo("Using: Timer 2"); + break; +#endif + +#if defined(CONFIG_LPC43_TMR3) + case LPC43M4_IRQ_TIMER3: + priv->base = LPC43_TIMER3_BASE; + priv->tmrid = 3; + tmrinfo("Using: Timer 3"); + break; +#endif + + default: + ASSERT(0); + } + + priv->ops = &g_tmrops; + + (void)irq_attach(irq, lpc43_interrupt); + + /* Enable NVIC interrupt. */ + + up_enable_irq(irq); + + /* Register the timer driver as /dev/timerX */ + + (void)timer_register(devpath, (FAR struct timer_lowerhalf_s *)priv); +} + +#endif /* CONFIG_TIMER && CONFIG_LPC43_TMRx */ diff --git a/arch/arm/src/lpc43xx/lpc43_timer.h b/arch/arm/src/lpc43xx/lpc43_timer.h new file mode 100644 index 0000000000..194d917c31 --- /dev/null +++ b/arch/arm/src/lpc43xx/lpc43_timer.h @@ -0,0 +1,100 @@ +/**************************************************************************** + * arch/arm/src/sam34/lpc43_tc.h + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * Alan Carvalho de Assis + * + * 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_LPC43_TMR_H +#define __ARCH_ARM_SRC_LPC43_TMR_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "chip.h" +#include "chip/lpc43_timer.h" +#include "chip/lpc43_ccu.h" + +#ifdef CONFIG_TIMER + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lpc43_tmrinitialize + * + * Description: + * Initialize the timer. The timer is initialized and + * registers as 'devpath. The initial state of the timer is + * disabled. + * + * Input Parameters: + * devpath - The full path to the timer. This should be of the form + * /dev/timer0 + * irq - irq associated with the timer + * Returned Values: + * None + * + ****************************************************************************/ + +#if defined(CONFIG_LPC43_TMR0) || defined(CONFIG_LPC43_TMR1) || \ + defined(CONFIG_LPC43_TMR2) || defined(CONFIG_LPC43_TMR3) +void lpc43_tmrinitialize(FAR const char *devpath, int irq); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* CONFIG_TIMER */ +#endif /* __ARCH_ARM_SRC_LPC43_TMR_H */ diff --git a/configs/bambino-200e/nsh/defconfig b/configs/bambino-200e/nsh/defconfig index 1593440d4b..ab5b2edc94 100644 --- a/configs/bambino-200e/nsh/defconfig +++ b/configs/bambino-200e/nsh/defconfig @@ -209,10 +209,11 @@ CONFIG_LPC43_BOOT_SPIFI=y # CONFIG_LPC43_SPIFI is not set # CONFIG_LPC43_SSP0 is not set # CONFIG_LPC43_SSP1 is not set -# CONFIG_LPC43_TMR0 is not set +CONFIG_LPC43_TMR0=y # CONFIG_LPC43_TMR1 is not set # CONFIG_LPC43_TMR2 is not set # CONFIG_LPC43_TMR3 is not set +CONFIG_LPC43_TIMER=y # CONFIG_LPC43_USART0 is not set CONFIG_LPC43_UART1=y # CONFIG_LPC43_USART2 is not set @@ -262,7 +263,7 @@ CONFIG_ARCH_HAVE_VFORK=y # CONFIG_ARCH_HAVE_MMU is not set CONFIG_ARCH_HAVE_MPU=y # CONFIG_ARCH_NAND_HWECC is not set -# CONFIG_ARCH_HAVE_EXTCLK is not set +CONFIG_ARCH_HAVE_EXTCLK=y # CONFIG_ARCH_HAVE_POWEROFF is not set CONFIG_ARCH_HAVE_RESET=y # CONFIG_ARCH_USE_MPU is not set @@ -350,6 +351,7 @@ CONFIG_DISABLE_OS_API=y CONFIG_ARCH_HAVE_TICKLESS=y # CONFIG_SCHED_TICKLESS is not set CONFIG_USEC_PER_TICK=10000 +# CONFIG_SYSTEMTICK_EXTCLK is not set # CONFIG_SYSTEM_TIME64 is not set # CONFIG_CLOCK_MONOTONIC is not set # CONFIG_ARCH_HAVE_TIMEKEEPING is not set @@ -466,7 +468,7 @@ CONFIG_DEV_NULL=y # # Timer Driver Support # -# CONFIG_TIMER is not set +CONFIG_TIMER=y # CONFIG_ONESHOT is not set # CONFIG_RTC is not set # CONFIG_WATCHDOG is not set @@ -809,6 +811,14 @@ CONFIG_EXAMPLES_NSH=y # CONFIG_EXAMPLES_TCPECHO is not set # CONFIG_EXAMPLES_TELNETD is not set # CONFIG_EXAMPLES_TIFF is not set +CONFIG_EXAMPLES_TIMER=y +CONFIG_EXAMPLE_TIMER_DEVNAME="/dev/timer0" +CONFIG_EXAMPLE_TIMER_INTERVAL=1000000 +CONFIG_EXAMPLE_TIMER_DELAY=100000 +CONFIG_EXAMPLE_TIMER_NSAMPLES=20 +CONFIG_EXAMPLES_TIMER_APPNAME="timer" +CONFIG_EXAMPLES_TIMER_STACKSIZE=2048 +CONFIG_EXAMPLES_TIMER_PRIORITY=100 # CONFIG_EXAMPLES_TOUCHSCREEN is not set # CONFIG_EXAMPLES_USBSERIAL is not set # CONFIG_EXAMPLES_USBTERM is not set diff --git a/configs/bambino-200e/src/Makefile b/configs/bambino-200e/src/Makefile index fa49acd104..bb34f2be40 100644 --- a/configs/bambino-200e/src/Makefile +++ b/configs/bambino-200e/src/Makefile @@ -57,6 +57,10 @@ ifeq ($(CONFIG_ARCH_BUTTONS),y) CSRCS += lpc43_buttons.c endif +ifeq ($(CONFIG_TIMER),y) +CSRCS += lpc43_timer.c +endif + ifeq ($(CONFIG_USBMSC),y) CSRCS += lpc43_usbmsc.c endif diff --git a/configs/bambino-200e/src/bambino-200e.h b/configs/bambino-200e/src/bambino-200e.h index 2ec6d17479..9a0b856801 100644 --- a/configs/bambino-200e/src/bambino-200e.h +++ b/configs/bambino-200e/src/bambino-200e.h @@ -123,5 +123,19 @@ void weak_function lpc43_sspdev_initialize(void); +/************************************************************************************ + * Name: lpc43xx_timerinitialize() + * + * Description: + * Perform architecture-specific initialization of the timer hardware. + * + ************************************************************************************/ + +#ifdef CONFIG_TIMER +int lpc43_timerinitialize(void); +#else +# define lpc43_timerinitialize() (0) +#endif + #endif /* __ASSEMBLY__ */ #endif /* _CONFIGS_BAMBINO_200E_SRC_BAMBINO_H */ diff --git a/configs/bambino-200e/src/lpc43_appinit.c b/configs/bambino-200e/src/lpc43_appinit.c index eae609cf2e..13c51dfd81 100644 --- a/configs/bambino-200e/src/lpc43_appinit.c +++ b/configs/bambino-200e/src/lpc43_appinit.c @@ -162,5 +162,13 @@ int board_app_initialize(uintptr_t arg) { /* Initialize the SPIFI block device */ - return nsh_spifi_initialize(); + nsh_spifi_initialize(); + +#ifdef CONFIG_TIMER + /* Registers the timers */ + + lpc43_timerinitialize(); +#endif + + return 0; } diff --git a/configs/bambino-200e/src/lpc43_timer.c b/configs/bambino-200e/src/lpc43_timer.c new file mode 100644 index 0000000000..2efe5b2366 --- /dev/null +++ b/configs/bambino-200e/src/lpc43_timer.c @@ -0,0 +1,125 @@ +/**************************************************************************** + * configs/bambino-200e/src/lpc43_timer.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * Bob Doiron + * + * 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 +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include "lpc43_timer.h" + +#ifdef CONFIG_TIMER + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ + +#if !(defined(CONFIG_LPC43_TMR0) || defined(CONFIG_LPC43_TMR1) || defined(CONFIG_LPC43_TMR2) \ + || defined(CONFIG_LPC43_TMR3) ) +# warning "CONFIG_LPC43_TMRx must be defined" +#endif + +/* Select the path to the registered watchdog timer device */ + +#ifndef CONFIG_TIMER0_DEVPATH +# define CONFIG_TIMER0_DEVPATH "/dev/timer0" +#endif +#ifndef CONFIG_TIMER1_DEVPATH +# define CONFIG_TIMER1_DEVPATH "/dev/timer1" +#endif +#ifndef CONFIG_TIMER2_DEVPATH +# define CONFIG_TIMER2_DEVPATH "/dev/timer2" +#endif +#ifndef CONFIG_TIMER3_DEVPATH +# define CONFIG_TIMER3_DEVPATH "/dev/timer3" +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lpc43_timerinitialize() + * + * Description: + * Perform architecture-specific initialization of the timer hardware. + * + ****************************************************************************/ + +int lpc43_timerinitialize(void) +{ + /* Initialize and register the timer devices */ + +#if defined(CONFIG_LPC43_TMR0) + tmrinfo("Initializing %s...\n", CONFIG_TIMER0_DEVPATH); + lpc43_tmrinitialize(CONFIG_TIMER0_DEVPATH, LPC43M4_IRQ_TIMER0); +#endif + +#if defined(CONFIG_LPC43_TMR1) + tmrinfo("Initializing %s...\n", CONFIG_TIMER1_DEVPATH); + lpc43_tmrinitialize(CONFIG_TIMER1_DEVPATH, LPC43M4_IRQ_TIMER1); +#endif + +#if defined(CONFIG_LPC43_TMR2) + tmrinfo("Initializing %s...\n", CONFIG_TIMER2_DEVPATH); + lpc43_tmrinitialize(CONFIG_TIMER2_DEVPATH, LPC43M4_IRQ_TIMER2); +#endif + +#if defined(CONFIG_LPC43_TMR3) + tmrinfo("Initializing %s...\n", CONFIG_TIMER3_DEVPATH); + lpc43_tmrinitialize(CONFIG_TIMER3_DEVPATH, LPC43M4_IRQ_TIMER3); +#endif + + return OK; +} + +#endif /* CONFIG_TIMER */