Add support for tickless operation using the NXP LPC43xx
This commit is contained in:
parent
a7a5c8cff3
commit
b5fc30f1e8
@ -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"
|
||||
|
@ -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
|
||||
|
@ -41,6 +41,7 @@
|
||||
************************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include "chip/lpc4310203050_memorymap.h"
|
||||
|
||||
/************************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
248
arch/arm/src/lpc43xx/lpc43_rit.c
Normal file
248
arch/arm/src/lpc43xx/lpc43_rit.c
Normal file
@ -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 */
|
68
arch/arm/src/lpc43xx/lpc43_rit.h
Normal file
68
arch/arm/src/lpc43xx/lpc43_rit.h
Normal file
@ -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 */
|
Loading…
Reference in New Issue
Block a user