commit
657b4f7d71
@ -46,7 +46,7 @@
|
||||
* Pre-processor Definitions
|
||||
************************************************************************************/
|
||||
|
||||
/* Per the data sheet: LPC4350/30/20/10 Rev. 3.2 — 4 June 2012 */
|
||||
/* Per the data sheet: LPC4350/30/20/10 Rev. 3.2 — 4 June 2012 */
|
||||
/* Get customizations for each supported chip.
|
||||
*
|
||||
* SRAM Resources
|
||||
@ -74,7 +74,7 @@
|
||||
* manager. This gives some symmetry to all of the members of the family.
|
||||
*/
|
||||
|
||||
/* Per the user manual: UM10503, Rev. 1.2 — 8 June 2012 */
|
||||
/* Per the user manual: UM10503, Rev. 1.2 — 8 June 2012 */
|
||||
/* Get customizations for each supported chip.
|
||||
*
|
||||
* SRAM Resources
|
||||
|
@ -96,6 +96,8 @@ CHIP_CSRCS += lpc43_start.c lpc43_uart.c
|
||||
|
||||
ifneq ($(CONFIG_SCHED_TICKLESS),y)
|
||||
CHIP_CSRCS += lpc43_timerisr.c
|
||||
else
|
||||
CHIP_CSRCS += lpc43_tickless_rit.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BUILD_PROTECTED),y)
|
||||
@ -131,10 +133,10 @@ CHIP_CSRCS += lpc43_spifi.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_LPC43_SSP0),y)
|
||||
CHIP_CSRCS += lpc43_ssp.c
|
||||
CHIP_CSRCS += lpc43_ssp.c lpc43_spi.c
|
||||
else
|
||||
ifeq ($(CONFIG_LPC43_SSP1),y)
|
||||
CHIP_CSRCS += lpc43_ssp.c
|
||||
CHIP_CSRCS += lpc43_ssp.c lpc43_spi.c
|
||||
endif
|
||||
endif
|
||||
|
||||
|
@ -42,7 +42,6 @@
|
||||
************************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include "chip/lpc4310203050_memorymap.h"
|
||||
|
||||
/************************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
@ -68,77 +68,77 @@
|
||||
|
||||
/* Register addresses ***************************************************************/
|
||||
|
||||
#define LPC43_TMR0_IR (LPC43_TMR0_BASE+LPC43_TMR_IR_OFFSET)
|
||||
#define LPC43_TMR0_TCR (LPC43_TMR0_BASE+LPC43_TMR_TCR_OFFSET)
|
||||
#define LPC43_TMR0_TC (LPC43_TMR0_BASE+LPC43_TMR_TC_OFFSET)
|
||||
#define LPC43_TMR0_PR (LPC43_TMR0_BASE+LPC43_TMR_PR_OFFSET)
|
||||
#define LPC43_TMR0_PC (LPC43_TMR0_BASE+LPC43_TMR_PC_OFFSET)
|
||||
#define LPC43_TMR0_MCR (LPC43_TMR0_BASE+LPC43_TMR_MCR_OFFSET)
|
||||
#define LPC43_TMR0_MR0 (LPC43_TMR0_BASE+LPC43_TMR_MR0_OFFSET)
|
||||
#define LPC43_TMR0_MR1 (LPC43_TMR0_BASE+LPC43_TMR_MR1_OFFSET)
|
||||
#define LPC43_TMR0_MR2 (LPC43_TMR0_BASE+LPC43_TMR_MR2_OFFSET)
|
||||
#define LPC43_TMR0_MR3 (LPC43_TMR0_BASE+LPC43_TMR_MR3_OFFSET)
|
||||
#define LPC43_TMR0_CCR (LPC43_TMR0_BASE+LPC43_TMR_CCR_OFFSET)
|
||||
#define LPC43_TMR0_CR0 (LPC43_TMR0_BASE+LPC43_TMR_CR0_OFFSET)
|
||||
#define LPC43_TMR0_CR1 (LPC43_TMR0_BASE+LPC43_TMR_CR1_OFFSET)
|
||||
#define LPC43_TMR0_CR2 (LPC43_TMR0_BASE+LPC43_TMR_CR2_OFFSET)
|
||||
#define LPC43_TMR0_CR3 (LPC43_TMR0_BASE+LPC43_TMR_CR3_OFFSET)
|
||||
#define LPC43_TMR0_EMR (LPC43_TMR0_BASE+LPC43_TMR_EMR_OFFSET)
|
||||
#define LPC43_TMR0_CTCR (LPC43_TMR0_BASE+LPC43_TMR_CTCR_OFFSET)
|
||||
#define LPC43_TMR0_IR (LPC43_TIMER0_BASE+LPC43_TMR_IR_OFFSET)
|
||||
#define LPC43_TMR0_TCR (LPC43_TIMER0_BASE+LPC43_TMR_TCR_OFFSET)
|
||||
#define LPC43_TMR0_TC (LPC43_TIMER0_BASE+LPC43_TMR_TC_OFFSET)
|
||||
#define LPC43_TMR0_PR (LPC43_TIMER0_BASE+LPC43_TMR_PR_OFFSET)
|
||||
#define LPC43_TMR0_PC (LPC43_TIMER0_BASE+LPC43_TMR_PC_OFFSET)
|
||||
#define LPC43_TMR0_MCR (LPC43_TIMER0_BASE+LPC43_TMR_MCR_OFFSET)
|
||||
#define LPC43_TMR0_MR0 (LPC43_TIMER0_BASE+LPC43_TMR_MR0_OFFSET)
|
||||
#define LPC43_TMR0_MR1 (LPC43_TIMER0_BASE+LPC43_TMR_MR1_OFFSET)
|
||||
#define LPC43_TMR0_MR2 (LPC43_TIMER0_BASE+LPC43_TMR_MR2_OFFSET)
|
||||
#define LPC43_TMR0_MR3 (LPC43_TIMER0_BASE+LPC43_TMR_MR3_OFFSET)
|
||||
#define LPC43_TMR0_CCR (LPC43_TIMER0_BASE+LPC43_TMR_CCR_OFFSET)
|
||||
#define LPC43_TMR0_CR0 (LPC43_TIMER0_BASE+LPC43_TMR_CR0_OFFSET)
|
||||
#define LPC43_TMR0_CR1 (LPC43_TIMER0_BASE+LPC43_TMR_CR1_OFFSET)
|
||||
#define LPC43_TMR0_CR2 (LPC43_TIMER0_BASE+LPC43_TMR_CR2_OFFSET)
|
||||
#define LPC43_TMR0_CR3 (LPC43_TIMER0_BASE+LPC43_TMR_CR3_OFFSET)
|
||||
#define LPC43_TMR0_EMR (LPC43_TIMER0_BASE+LPC43_TMR_EMR_OFFSET)
|
||||
#define LPC43_TMR0_CTCR (LPC43_TIMER0_BASE+LPC43_TMR_CTCR_OFFSET)
|
||||
|
||||
#define LPC43_TMR1_IR (LPC43_TMR1_BASE+LPC43_TMR_IR_OFFSET)
|
||||
#define LPC43_TMR1_TCR (LPC43_TMR1_BASE+LPC43_TMR_TCR_OFFSET)
|
||||
#define LPC43_TMR1_TC (LPC43_TMR1_BASE+LPC43_TMR_TC_OFFSET)
|
||||
#define LPC43_TMR1_PR (LPC43_TMR1_BASE+LPC43_TMR_PR_OFFSET)
|
||||
#define LPC43_TMR1_PC (LPC43_TMR1_BASE+LPC43_TMR_PC_OFFSET)
|
||||
#define LPC43_TMR1_MCR (LPC43_TMR1_BASE+LPC43_TMR_MCR_OFFSET)
|
||||
#define LPC43_TMR1_MR0 (LPC43_TMR1_BASE+LPC43_TMR_MR0_OFFSET)
|
||||
#define LPC43_TMR1_MR1 (LPC43_TMR1_BASE+LPC43_TMR_MR1_OFFSET)
|
||||
#define LPC43_TMR1_MR2 (LPC43_TMR1_BASE+LPC43_TMR_MR2_OFFSET)
|
||||
#define LPC43_TMR1_MR3 (LPC43_TMR1_BASE+LPC43_TMR_MR3_OFFSET)
|
||||
#define LPC43_TMR1_CCR (LPC43_TMR1_BASE+LPC43_TMR_CCR_OFFSET)
|
||||
#define LPC43_TMR1_CR0 (LPC43_TMR1_BASE+LPC43_TMR_CR0_OFFSET)
|
||||
#define LPC43_TMR1_CR1 (LPC43_TMR1_BASE+LPC43_TMR_CR1_OFFSET)
|
||||
#define LPC43_TMR1_CR2 (LPC43_TMR1_BASE+LPC43_TMR_CR2_OFFSET)
|
||||
#define LPC43_TMR1_CR3 (LPC43_TMR1_BASE+LPC43_TMR_CR3_OFFSET)
|
||||
#define LPC43_TMR1_EMR (LPC43_TMR1_BASE+LPC43_TMR_EMR_OFFSET)
|
||||
#define LPC43_TMR1_CTCR (LPC43_TMR1_BASE+LPC43_TMR_CTCR_OFFSET)
|
||||
#define LPC43_TMR1_IR (LPC43_TIMER1_BASE+LPC43_TMR_IR_OFFSET)
|
||||
#define LPC43_TMR1_TCR (LPC43_TIMER1_BASE+LPC43_TMR_TCR_OFFSET)
|
||||
#define LPC43_TMR1_TC (LPC43_TIMER1_BASE+LPC43_TMR_TC_OFFSET)
|
||||
#define LPC43_TMR1_PR (LPC43_TIMER1_BASE+LPC43_TMR_PR_OFFSET)
|
||||
#define LPC43_TMR1_PC (LPC43_TIMER1_BASE+LPC43_TMR_PC_OFFSET)
|
||||
#define LPC43_TMR1_MCR (LPC43_TIMER1_BASE+LPC43_TMR_MCR_OFFSET)
|
||||
#define LPC43_TMR1_MR0 (LPC43_TIMER1_BASE+LPC43_TMR_MR0_OFFSET)
|
||||
#define LPC43_TMR1_MR1 (LPC43_TIMER1_BASE+LPC43_TMR_MR1_OFFSET)
|
||||
#define LPC43_TMR1_MR2 (LPC43_TIMER1_BASE+LPC43_TMR_MR2_OFFSET)
|
||||
#define LPC43_TMR1_MR3 (LPC43_TIMER1_BASE+LPC43_TMR_MR3_OFFSET)
|
||||
#define LPC43_TMR1_CCR (LPC43_TIMER1_BASE+LPC43_TMR_CCR_OFFSET)
|
||||
#define LPC43_TMR1_CR0 (LPC43_TIMER1_BASE+LPC43_TMR_CR0_OFFSET)
|
||||
#define LPC43_TMR1_CR1 (LPC43_TIMER1_BASE+LPC43_TMR_CR1_OFFSET)
|
||||
#define LPC43_TMR1_CR2 (LPC43_TIMER1_BASE+LPC43_TMR_CR2_OFFSET)
|
||||
#define LPC43_TMR1_CR3 (LPC43_TIMER1_BASE+LPC43_TMR_CR3_OFFSET)
|
||||
#define LPC43_TMR1_EMR (LPC43_TIMER1_BASE+LPC43_TMR_EMR_OFFSET)
|
||||
#define LPC43_TMR1_CTCR (LPC43_TIMER1_BASE+LPC43_TMR_CTCR_OFFSET)
|
||||
|
||||
#define LPC43_TMR2_IR (LPC43_TMR2_BASE+LPC43_TMR_IR_OFFSET)
|
||||
#define LPC43_TMR2_TCR (LPC43_TMR2_BASE+LPC43_TMR_TCR_OFFSET)
|
||||
#define LPC43_TMR2_TC (LPC43_TMR2_BASE+LPC43_TMR_TC_OFFSET)
|
||||
#define LPC43_TMR2_PR (LPC43_TMR2_BASE+LPC43_TMR_PR_OFFSET)
|
||||
#define LPC43_TMR2_PC (LPC43_TMR2_BASE+LPC43_TMR_PC_OFFSET)
|
||||
#define LPC43_TMR2_MCR (LPC43_TMR2_BASE+LPC43_TMR_MCR_OFFSET)
|
||||
#define LPC43_TMR2_MR0 (LPC43_TMR2_BASE+LPC43_TMR_MR0_OFFSET)
|
||||
#define LPC43_TMR2_MR1 (LPC43_TMR2_BASE+LPC43_TMR_MR1_OFFSET)
|
||||
#define LPC43_TMR2_MR2 (LPC43_TMR2_BASE+LPC43_TMR_MR2_OFFSET)
|
||||
#define LPC43_TMR2_MR3 (LPC43_TMR2_BASE+LPC43_TMR_MR3_OFFSET)
|
||||
#define LPC43_TMR2_CCR (LPC43_TMR2_BASE+LPC43_TMR_CCR_OFFSET)
|
||||
#define LPC43_TMR2_CR0 (LPC43_TMR2_BASE+LPC43_TMR_CR0_OFFSET)
|
||||
#define LPC43_TMR2_CR1 (LPC43_TMR2_BASE+LPC43_TMR_CR1_OFFSET)
|
||||
#define LPC43_TMR2_CR2 (LPC43_TMR2_BASE+LPC43_TMR_CR2_OFFSET)
|
||||
#define LPC43_TMR2_CR3 (LPC43_TMR2_BASE+LPC43_TMR_CR3_OFFSET)
|
||||
#define LPC43_TMR2_EMR (LPC43_TMR2_BASE+LPC43_TMR_EMR_OFFSET)
|
||||
#define LPC43_TMR2_CTCR (LPC43_TMR2_BASE+LPC43_TMR_CTCR_OFFSET)
|
||||
#define LPC43_TMR2_IR (LPC43_TIMER2_BASE+LPC43_TMR_IR_OFFSET)
|
||||
#define LPC43_TMR2_TCR (LPC43_TIMER2_BASE+LPC43_TMR_TCR_OFFSET)
|
||||
#define LPC43_TMR2_TC (LPC43_TIMER2_BASE+LPC43_TMR_TC_OFFSET)
|
||||
#define LPC43_TMR2_PR (LPC43_TIMER2_BASE+LPC43_TMR_PR_OFFSET)
|
||||
#define LPC43_TMR2_PC (LPC43_TIMER2_BASE+LPC43_TMR_PC_OFFSET)
|
||||
#define LPC43_TMR2_MCR (LPC43_TIMER2_BASE+LPC43_TMR_MCR_OFFSET)
|
||||
#define LPC43_TMR2_MR0 (LPC43_TIMER2_BASE+LPC43_TMR_MR0_OFFSET)
|
||||
#define LPC43_TMR2_MR1 (LPC43_TIMER2_BASE+LPC43_TMR_MR1_OFFSET)
|
||||
#define LPC43_TMR2_MR2 (LPC43_TIMER2_BASE+LPC43_TMR_MR2_OFFSET)
|
||||
#define LPC43_TMR2_MR3 (LPC43_TIMER2_BASE+LPC43_TMR_MR3_OFFSET)
|
||||
#define LPC43_TMR2_CCR (LPC43_TIMER2_BASE+LPC43_TMR_CCR_OFFSET)
|
||||
#define LPC43_TMR2_CR0 (LPC43_TIMER2_BASE+LPC43_TMR_CR0_OFFSET)
|
||||
#define LPC43_TMR2_CR1 (LPC43_TIMER2_BASE+LPC43_TMR_CR1_OFFSET)
|
||||
#define LPC43_TMR2_CR2 (LPC43_TIMER2_BASE+LPC43_TMR_CR2_OFFSET)
|
||||
#define LPC43_TMR2_CR3 (LPC43_TIMER2_BASE+LPC43_TMR_CR3_OFFSET)
|
||||
#define LPC43_TMR2_EMR (LPC43_TIMER2_BASE+LPC43_TMR_EMR_OFFSET)
|
||||
#define LPC43_TMR2_CTCR (LPC43_TIMER2_BASE+LPC43_TMR_CTCR_OFFSET)
|
||||
|
||||
#define LPC43_TMR3_IR (LPC43_TMR3_BASE+LPC43_TMR_IR_OFFSET)
|
||||
#define LPC43_TMR3_TCR (LPC43_TMR3_BASE+LPC43_TMR_TCR_OFFSET)
|
||||
#define LPC43_TMR3_TC (LPC43_TMR3_BASE+LPC43_TMR_TC_OFFSET)
|
||||
#define LPC43_TMR3_PR (LPC43_TMR3_BASE+LPC43_TMR_PR_OFFSET)
|
||||
#define LPC43_TMR3_PC (LPC43_TMR3_BASE+LPC43_TMR_PC_OFFSET)
|
||||
#define LPC43_TMR3_MCR (LPC43_TMR3_BASE+LPC43_TMR_MCR_OFFSET)
|
||||
#define LPC43_TMR3_MR0 (LPC43_TMR3_BASE+LPC43_TMR_MR0_OFFSET)
|
||||
#define LPC43_TMR3_MR1 (LPC43_TMR3_BASE+LPC43_TMR_MR1_OFFSET)
|
||||
#define LPC43_TMR3_MR2 (LPC43_TMR3_BASE+LPC43_TMR_MR2_OFFSET)
|
||||
#define LPC43_TMR3_MR3 (LPC43_TMR3_BASE+LPC43_TMR_MR3_OFFSET)
|
||||
#define LPC43_TMR3_CCR (LPC43_TMR3_BASE+LPC43_TMR_CCR_OFFSET)
|
||||
#define LPC43_TMR3_CR0 (LPC43_TMR3_BASE+LPC43_TMR_CR0_OFFSET)
|
||||
#define LPC43_TMR3_CR1 (LPC43_TMR3_BASE+LPC43_TMR_CR1_OFFSET)
|
||||
#define LPC43_TMR3_CR2 (LPC43_TMR3_BASE+LPC43_TMR_CR2_OFFSET)
|
||||
#define LPC43_TMR3_CR3 (LPC43_TMR3_BASE+LPC43_TMR_CR3_OFFSET)
|
||||
#define LPC43_TMR3_EMR (LPC43_TMR3_BASE+LPC43_TMR_EMR_OFFSET)
|
||||
#define LPC43_TMR3_CTCR (LPC43_TMR3_BASE+LPC43_TMR_CTCR_OFFSET)
|
||||
#define LPC43_TMR3_IR (LPC43_TIMER3_BASE+LPC43_TMR_IR_OFFSET)
|
||||
#define LPC43_TMR3_TCR (LPC43_TIMER3_BASE+LPC43_TMR_TCR_OFFSET)
|
||||
#define LPC43_TMR3_TC (LPC43_TIMER3_BASE+LPC43_TMR_TC_OFFSET)
|
||||
#define LPC43_TMR3_PR (LPC43_TIMER3_BASE+LPC43_TMR_PR_OFFSET)
|
||||
#define LPC43_TMR3_PC (LPC43_TIMER3_BASE+LPC43_TMR_PC_OFFSET)
|
||||
#define LPC43_TMR3_MCR (LPC43_TIMER3_BASE+LPC43_TMR_MCR_OFFSET)
|
||||
#define LPC43_TMR3_MR0 (LPC43_TIMER3_BASE+LPC43_TMR_MR0_OFFSET)
|
||||
#define LPC43_TMR3_MR1 (LPC43_TIMER3_BASE+LPC43_TMR_MR1_OFFSET)
|
||||
#define LPC43_TMR3_MR2 (LPC43_TIMER3_BASE+LPC43_TMR_MR2_OFFSET)
|
||||
#define LPC43_TMR3_MR3 (LPC43_TIMER3_BASE+LPC43_TMR_MR3_OFFSET)
|
||||
#define LPC43_TMR3_CCR (LPC43_TIMER3_BASE+LPC43_TMR_CCR_OFFSET)
|
||||
#define LPC43_TMR3_CR0 (LPC43_TIMER3_BASE+LPC43_TMR_CR0_OFFSET)
|
||||
#define LPC43_TMR3_CR1 (LPC43_TIMER3_BASE+LPC43_TMR_CR1_OFFSET)
|
||||
#define LPC43_TMR3_CR2 (LPC43_TIMER3_BASE+LPC43_TMR_CR2_OFFSET)
|
||||
#define LPC43_TMR3_CR3 (LPC43_TIMER3_BASE+LPC43_TMR_CR3_OFFSET)
|
||||
#define LPC43_TMR3_EMR (LPC43_TIMER3_BASE+LPC43_TMR_EMR_OFFSET)
|
||||
#define LPC43_TMR3_CTCR (LPC43_TIMER3_BASE+LPC43_TMR_CTCR_OFFSET)
|
||||
|
||||
/* Register bit definitions *********************************************************/
|
||||
/* Registers holding 32-bit numeric values (no bit field definitions):
|
||||
|
@ -461,7 +461,7 @@ void lpc43_pll0usbenable(void)
|
||||
* operation and will make the lock signal high once it has regained
|
||||
* lock on the input clock
|
||||
*
|
||||
* Wait for PLL1 to report that it is locked.
|
||||
* Wait for PLL0 to report that it is locked.
|
||||
*/
|
||||
|
||||
while ((getreg32(LPC43_PLL0USB_STAT) & PLL0USB_STAT_LOCK) == 0);
|
||||
|
@ -206,8 +206,7 @@ static int i2c_setaddress(FAR struct i2c_dev_s *dev, int addr, int nbits)
|
||||
DEBUGASSERT(dev != NULL);
|
||||
DEBUGASSERT(nbits == 7);
|
||||
|
||||
priv->msg.addr = addr << 1;
|
||||
priv->msg.flags = 0 ;
|
||||
priv->msg.addr = addr;
|
||||
|
||||
return OK;
|
||||
}
|
||||
@ -231,7 +230,7 @@ static int i2c_write(FAR struct i2c_dev_s *dev, const uint8_t *buffer,
|
||||
|
||||
priv->wrcnt = 0;
|
||||
priv->rdcnt = 0;
|
||||
priv->msg.addr &= ~0x01;
|
||||
priv->msg.flags = 0;
|
||||
priv->msg.buffer = (uint8_t *)buffer;
|
||||
priv->msg.length = buflen;
|
||||
|
||||
@ -264,7 +263,7 @@ static int i2c_read(FAR struct i2c_dev_s *dev, uint8_t *buffer, int buflen)
|
||||
|
||||
priv->wrcnt = 0;
|
||||
priv->rdcnt = 0;
|
||||
priv->msg.addr |= 0x01;
|
||||
priv->msg.flags = I2C_M_READ;
|
||||
priv->msg.buffer = buffer;
|
||||
priv->msg.length = buflen;
|
||||
|
||||
@ -364,7 +363,7 @@ static int i2c_transfer(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs, i
|
||||
priv->msgs = msgs;
|
||||
priv->nmsg = count;
|
||||
|
||||
ret = count - i2c_start(priv);
|
||||
ret = i2c_start(priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -428,7 +427,7 @@ static int i2c_interrupt(int irq, FAR void *context)
|
||||
|
||||
case 0x08: /* A START condition has been transmitted. */
|
||||
case 0x10: /* A Repeated START condition has been transmitted. */
|
||||
putreg32(msg->addr, priv->base + LPC43_I2C_DAT_OFFSET); /* set address */
|
||||
putreg32(((I2C_M_READ & msg->flags) == I2C_M_READ)?I2C_READADDR8(msg->addr):I2C_WRITEADDR8(msg->addr), priv->base + LPC43_I2C_DAT_OFFSET); /* set address */
|
||||
putreg32(I2C_CONCLR_STAC, priv->base + LPC43_I2C_CONCLR_OFFSET); /* clear start bit */
|
||||
break;
|
||||
|
||||
|
@ -56,6 +56,7 @@
|
||||
#include "chip.h"
|
||||
#include "lpc43_pinconfig.h"
|
||||
#include "lpc43_spi.h"
|
||||
#include "lpc43_ssp.h"
|
||||
|
||||
#ifdef CONFIG_LPC43_SPI
|
||||
|
||||
@ -583,3 +584,39 @@ FAR struct spi_dev_s *lpc43_spiinitialize(int port)
|
||||
|
||||
#endif /* CONFIG_LPC43_SPI */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_spiinitialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize the selected SPI port
|
||||
* 0 - SPI
|
||||
* 1 - SSP0
|
||||
* 2 - SSP1
|
||||
*
|
||||
* Input Parameter:
|
||||
* Port number (for hardware that has multiple SPI interfaces)
|
||||
*
|
||||
* Returned Value:
|
||||
* Valid SPI device structure reference on success; a NULL on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct spi_dev_s *up_spiinitialize(int port)
|
||||
{
|
||||
if (port) {
|
||||
#if ( defined(CONFIG_LPC43_SSP0) || defined(CONFIG_LPC43_SSP1) )
|
||||
return lpc43_sspinitialize(port-1);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
} else {
|
||||
#if defined(CONFIG_LPC43_SPI)
|
||||
return lpc43_spiinitialize(port);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -162,8 +162,12 @@ static const struct spi_ops_s g_spi0ops =
|
||||
.cmddata = lpc43_ssp0cmddata, /* Provided externally */
|
||||
#endif
|
||||
.send = ssp_send,
|
||||
#ifdef CONFIG_SPI_EXCHANGE
|
||||
.exchange = ssp_exchange,
|
||||
#else
|
||||
.sndblock = ssp_sndblock,
|
||||
.recvblock = ssp_recvblock,
|
||||
#endif
|
||||
#ifdef CONFIG_SPI_CALLBACK
|
||||
.registercallback = lpc43_ssp0register, /* Provided externally */
|
||||
#else
|
||||
@ -197,8 +201,12 @@ static const struct spi_ops_s g_spi1ops =
|
||||
.cmddata = lpc43_ssp1cmddata, /* Provided externally */
|
||||
#endif
|
||||
.send = ssp_send,
|
||||
#ifdef CONFIG_SPI_EXCHANGE
|
||||
.exchange = ssp_exchange,
|
||||
#else
|
||||
.sndblock = ssp_sndblock,
|
||||
.recvblock = ssp_recvblock,
|
||||
#endif
|
||||
#ifdef CONFIG_SPI_CALLBACK
|
||||
.registercallback = lpc43_ssp1register, /* Provided externally */
|
||||
#else
|
||||
@ -526,6 +534,76 @@ static uint16_t ssp_send(FAR struct spi_dev_s *dev, uint16_t wd)
|
||||
return (uint16_t)regval;
|
||||
}
|
||||
|
||||
static void ssp_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
|
||||
FAR void *rxbuffer, size_t nwords) {
|
||||
FAR struct lpc43_sspdev_s *priv = (FAR struct lpc43_sspdev_s *)dev;
|
||||
union
|
||||
{
|
||||
FAR uint8_t *p8;
|
||||
FAR uint16_t *p16;
|
||||
FAR const void *pv;
|
||||
} tx;
|
||||
union
|
||||
{
|
||||
FAR uint8_t *p8;
|
||||
FAR uint16_t *p16;
|
||||
FAR const void *pv;
|
||||
} rx;
|
||||
uint32_t data;
|
||||
uint32_t datadummy = (priv->nbits > 8)?0xffff:0xff;
|
||||
uint32_t rxpending = 0;
|
||||
|
||||
/* While there is remaining to be sent (and no synchronization error has occurred) */
|
||||
|
||||
sspdbg("nwords: %d\n", nwords);
|
||||
|
||||
tx.pv = txbuffer;
|
||||
rx.pv = rxbuffer;
|
||||
|
||||
while (nwords || rxpending)
|
||||
{
|
||||
/* Write data to the data register while (1) the TX FIFO is
|
||||
* not full, (2) we have not exceeded the depth of the TX FIFO,
|
||||
* and (3) there are more bytes to be sent.
|
||||
*/
|
||||
|
||||
spivdbg("TX: rxpending: %d nwords: %d\n", rxpending, nwords);
|
||||
while ((ssp_getreg(priv, LPC43_SSP_SR_OFFSET) & SSP_SR_TNF) &&
|
||||
(rxpending < LPC43_SSP_FIFOSZ) && nwords)
|
||||
{
|
||||
if (txbuffer && priv->nbits > 8)
|
||||
{
|
||||
data = (uint32_t)*tx.p16++;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = (uint32_t)*tx.p8++;
|
||||
}
|
||||
|
||||
ssp_putreg(priv, LPC43_SSP_DR_OFFSET, txbuffer?data:datadummy);
|
||||
nwords--;
|
||||
rxpending++;
|
||||
}
|
||||
|
||||
/* Now, read the RX data from the RX FIFO while the RX FIFO is not empty */
|
||||
|
||||
spivdbg("RX: rxpending: %d\n", rxpending);
|
||||
while (ssp_getreg(priv, LPC43_SSP_SR_OFFSET) & SSP_SR_RNE)
|
||||
{
|
||||
data = ssp_getreg(priv, LPC43_SSP_DR_OFFSET);
|
||||
if (rxbuffer && priv->nbits > 8)
|
||||
{
|
||||
*rx.p16++ = (uint16_t)data;
|
||||
}
|
||||
else
|
||||
{
|
||||
*rx.p8++ = (uint8_t)data;
|
||||
}
|
||||
rxpending--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ssp_sndblock
|
||||
*
|
||||
@ -547,72 +625,7 @@ static uint16_t ssp_send(FAR struct spi_dev_s *dev, uint16_t wd)
|
||||
|
||||
static void ssp_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t nwords)
|
||||
{
|
||||
FAR struct lpc43_sspdev_s *priv = (FAR struct lpc43_sspdev_s *)dev;
|
||||
union
|
||||
{
|
||||
FAR const uint8_t *p8;
|
||||
FAR const uint16_t *p16;
|
||||
FAR const void *pv;
|
||||
} u;
|
||||
uint32_t data;
|
||||
uint32_t sr;
|
||||
|
||||
/* Loop while thre are bytes remaining to be sent */
|
||||
|
||||
sspdbg("nwords: %d\n", nwords);
|
||||
u.pv = buffer;
|
||||
while (nwords > 0)
|
||||
{
|
||||
/* While the TX FIFO is not full and there are bytes left to send */
|
||||
|
||||
while ((ssp_getreg(priv, LPC43_SSP_SR_OFFSET) & SSP_SR_TNF) && nwords)
|
||||
{
|
||||
/* Fetch the data to send */
|
||||
|
||||
if (priv->nbits > 8)
|
||||
{
|
||||
data = (uint32_t)*u.p16++;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = (uint32_t)*u.p8++;
|
||||
}
|
||||
|
||||
/* Send the data */
|
||||
|
||||
ssp_putreg(priv, LPC43_SSP_DR_OFFSET, data);
|
||||
nwords--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Then discard all card responses until the RX & TX FIFOs are emptied. */
|
||||
|
||||
sspdbg("discarding\n");
|
||||
do
|
||||
{
|
||||
/* Is there anything in the RX fifo? */
|
||||
|
||||
sr = ssp_getreg(priv, LPC43_SSP_SR_OFFSET);
|
||||
if ((sr & SSP_SR_RNE) != 0)
|
||||
{
|
||||
/* Yes.. Read and discard */
|
||||
|
||||
(void)ssp_getreg(priv, LPC43_SSP_DR_OFFSET);
|
||||
}
|
||||
|
||||
/* There is a race condition where TFE may go true just before
|
||||
* RNE goes true and this loop terminates prematurely. The nasty little
|
||||
* delay in the following solves that (it could probably be tuned
|
||||
* to improve performance).
|
||||
*/
|
||||
|
||||
else if ((sr & SSP_SR_TFE) != 0)
|
||||
{
|
||||
up_udelay(100);
|
||||
sr = ssp_getreg(priv, LPC43_SSP_SR_OFFSET);
|
||||
}
|
||||
}
|
||||
while ((sr & SSP_SR_RNE) != 0 || (sr & SSP_SR_TFE) == 0);
|
||||
return ssp_exchange(dev, buffer, NULL, nwords);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -636,54 +649,7 @@ static void ssp_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size
|
||||
|
||||
static void ssp_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nwords)
|
||||
{
|
||||
FAR struct lpc43_sspdev_s *priv = (FAR struct lpc43_sspdev_s *)dev;
|
||||
union
|
||||
{
|
||||
FAR uint8_t *p8;
|
||||
FAR uint16_t *p16;
|
||||
FAR void *pv;
|
||||
} u;
|
||||
uint32_t data;
|
||||
uint32_t rxpending = 0;
|
||||
|
||||
/* While there is remaining to be sent (and no synchronization error has occurred) */
|
||||
|
||||
sspdbg("nwords: %d\n", nwords);
|
||||
u.pv = buffer;
|
||||
while (nwords || rxpending)
|
||||
{
|
||||
/* Fill the transmit FIFO with 0xffff...
|
||||
* Write 0xff to the data register while (1) the TX FIFO is
|
||||
* not full, (2) we have not exceeded the depth of the TX FIFO,
|
||||
* and (3) there are more bytes to be sent.
|
||||
*/
|
||||
|
||||
spivdbg("TX: rxpending: %d nwords: %d\n", rxpending, nwords);
|
||||
while ((ssp_getreg(priv, LPC43_SSP_SR_OFFSET) & SSP_SR_TNF) &&
|
||||
(rxpending < LPC43_SSP_FIFOSZ) && nwords)
|
||||
{
|
||||
ssp_putreg(priv, LPC43_SSP_DR_OFFSET, 0xffff);
|
||||
nwords--;
|
||||
rxpending++;
|
||||
}
|
||||
|
||||
/* Now, read the RX data from the RX FIFO while the RX FIFO is not empty */
|
||||
|
||||
spivdbg("RX: rxpending: %d\n", rxpending);
|
||||
while (ssp_getreg(priv, LPC43_SSP_SR_OFFSET) & SSP_SR_RNE)
|
||||
{
|
||||
data = (uint8_t)ssp_getreg(priv, LPC43_SSP_DR_OFFSET);
|
||||
if (priv->nbits > 8)
|
||||
{
|
||||
*u.p16++ = (uint16_t)data;
|
||||
}
|
||||
else
|
||||
{
|
||||
*u.p8++ = (uint8_t)data;
|
||||
}
|
||||
rxpending--;
|
||||
}
|
||||
}
|
||||
return ssp_exchange(dev, NULL, buffer, nwords);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
773
arch/arm/src/lpc43xx/lpc43_tickless_rit.c
Normal file
773
arch/arm/src/lpc43xx/lpc43_tickless_rit.c
Normal file
@ -0,0 +1,773 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/lpc43/lpc43_rit.c
|
||||
*
|
||||
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* only controlled resets to 0 are performed, no direct set to counter
|
||||
* working counter region is from 0 to TO_END
|
||||
* all public functions are synchronized with disabled irqs
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <arch/board/board.h>
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/clock.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "up_arch.h"
|
||||
#include "chip.h"
|
||||
#include "chip/lpc43_rit.h"
|
||||
|
||||
#ifdef CONFIG_SCHED_TICKLESS
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef min
|
||||
# define min(a,b) (a < b ? a : b)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t TO_RESET = UINT32_MAX / 2;
|
||||
static uint32_t TO_RESET_NEXT = UINT32_MAX / 2 + UINT32_MAX / 4;
|
||||
static uint32_t TO_END = UINT32_MAX / 2 + UINT32_MAX / 4 + UINT32_MAX / 8; /* any alarm should no last more than UINT32_MAX/8 */
|
||||
static struct timespec MAX_TS;
|
||||
|
||||
static uint32_t COMMON_DEV;
|
||||
static uint32_t MIN_TICKS;
|
||||
static uint32_t MIN_NSEC;
|
||||
|
||||
static uint32_t RESET_TICKS = 1000; /* ticks to add to force a reset */
|
||||
|
||||
static struct timespec base_ts; /* time base */
|
||||
static uint32_t base_rest; /* rest of ticks that is < MIN_TICKS*/
|
||||
|
||||
static struct timespec alarm_time_ts; /* alarmTime to set on next interrupt, used if not already armed */
|
||||
|
||||
static bool alarm_time_set = false; /* true if alarm_time set and need to be processed */
|
||||
static bool call = false; /* true if callback should be called on next interrupt */
|
||||
static bool forced_int = false; /* true if interrupt was forced with mask, no reset */
|
||||
static bool armed = false; /* true if alarm is armed for next match */
|
||||
static uint32_t synch = 0; /* synch all calls, recursion is possible */
|
||||
static irqstate_t g_flags;
|
||||
|
||||
static uint32_t ctrl_cache;
|
||||
static uint32_t mask_cache;
|
||||
static uint32_t compare_cache;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/* some timer HW functions */
|
||||
|
||||
static inline void lpc43_tl_set_counter (uint32_t value)
|
||||
{
|
||||
putreg32(value, LPC43_RIT_COUNTER);
|
||||
}
|
||||
|
||||
static inline uint32_t lpc43_tl_get_counter (void)
|
||||
{
|
||||
return getreg32(LPC43_RIT_COUNTER);
|
||||
}
|
||||
|
||||
static inline void lpc43_tl_set_compare (uint32_t value)
|
||||
{
|
||||
if ( value != compare_cache)
|
||||
{
|
||||
compare_cache = value;
|
||||
putreg32(value, LPC43_RIT_COMPVAL);
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t lpc43_tl_get_compare (void)
|
||||
{
|
||||
return compare_cache;
|
||||
}
|
||||
|
||||
static inline void lpc43_tl_set_mask (uint32_t value)
|
||||
{
|
||||
if ( value != mask_cache)
|
||||
{
|
||||
mask_cache = value;
|
||||
putreg32(value, LPC43_RIT_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t lpc43_tl_get_mask (void)
|
||||
{
|
||||
return mask_cache;
|
||||
}
|
||||
|
||||
static inline bool lpc43_tl_get_ctrl_bit (uint32_t bit)
|
||||
{
|
||||
return ((ctrl_cache & bit)?true:false);
|
||||
}
|
||||
|
||||
static inline void lpc43_tl_set_ctrl_bit (uint32_t bit, bool value)
|
||||
{
|
||||
|
||||
if ( lpc43_tl_get_ctrl_bit(bit) != value ) {
|
||||
|
||||
if (value)
|
||||
{
|
||||
ctrl_cache |= bit;
|
||||
}
|
||||
else
|
||||
{
|
||||
ctrl_cache &= ~bit;
|
||||
}
|
||||
|
||||
putreg32(ctrl_cache, LPC43_RIT_CTRL);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void lpc43_tl_set_reset_on_match (bool value)
|
||||
{
|
||||
lpc43_tl_set_ctrl_bit (RIT_CTRL_ENCLR, value);
|
||||
}
|
||||
|
||||
static inline bool lpc43_tl_get_reset_on_match (void)
|
||||
{
|
||||
return lpc43_tl_get_ctrl_bit (RIT_CTRL_ENCLR);
|
||||
}
|
||||
|
||||
static inline void lpc43_tl_set_enable (bool value)
|
||||
{
|
||||
lpc43_tl_set_ctrl_bit (RIT_CTRL_EN, value);
|
||||
}
|
||||
|
||||
static inline bool lpc43_tl_get_enable (void)
|
||||
{
|
||||
return lpc43_tl_get_ctrl_bit (RIT_CTRL_EN);
|
||||
}
|
||||
|
||||
static inline void lpc43_tl_clear_interrupt (void)
|
||||
{
|
||||
putreg32(ctrl_cache | RIT_CTRL_INT, LPC43_RIT_CTRL);
|
||||
}
|
||||
|
||||
static inline bool lpc43_tl_get_interrupt (void)
|
||||
{
|
||||
return (( getreg32(LPC43_RIT_CTRL) & RIT_CTRL_INT )?true:false);
|
||||
}
|
||||
|
||||
/* converters */
|
||||
static uint32_t commonDev(uint32_t a, uint32_t b)
|
||||
{
|
||||
while(b !=0)
|
||||
{
|
||||
int h = a%b;
|
||||
a = b;
|
||||
b = h;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
static void lpc43_tl_add(FAR const struct timespec *ts1,
|
||||
FAR const struct timespec *ts2,
|
||||
FAR struct timespec *ts3)
|
||||
{
|
||||
time_t sec = ts1->tv_sec + ts2->tv_sec;
|
||||
long nsec = ts1->tv_nsec + ts2->tv_nsec;
|
||||
|
||||
if (nsec >= NSEC_PER_SEC)
|
||||
{
|
||||
nsec -= NSEC_PER_SEC;
|
||||
sec++;
|
||||
}
|
||||
|
||||
ts3->tv_sec = sec;
|
||||
ts3->tv_nsec = nsec;
|
||||
}
|
||||
|
||||
static void lpc43_tl_sub(FAR const struct timespec *ts1,
|
||||
FAR const struct timespec *ts2,
|
||||
FAR struct timespec *ts3)
|
||||
{
|
||||
time_t sec;
|
||||
long nsec;
|
||||
|
||||
if (ts1->tv_sec < ts2->tv_sec)
|
||||
{
|
||||
sec = 0;
|
||||
nsec = 0;
|
||||
}
|
||||
else if (ts1->tv_sec == ts2->tv_sec && ts1->tv_nsec <= ts2->tv_nsec)
|
||||
{
|
||||
sec = 0;
|
||||
nsec = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sec = ts1->tv_sec - ts2->tv_sec;
|
||||
if (ts1->tv_nsec < ts2->tv_nsec)
|
||||
{
|
||||
nsec = (ts1->tv_nsec + NSEC_PER_SEC) - ts2->tv_nsec;
|
||||
sec--;
|
||||
}
|
||||
else
|
||||
{
|
||||
nsec = ts1->tv_nsec - ts2->tv_nsec;
|
||||
}
|
||||
}
|
||||
|
||||
ts3->tv_sec = sec;
|
||||
ts3->tv_nsec = nsec;
|
||||
}
|
||||
|
||||
static inline uint32_t lpc43_tl_ts2tick ( FAR const struct timespec *ts)
|
||||
{
|
||||
return ( ts->tv_sec*LPC43_CCLK + ( ts->tv_nsec/MIN_NSEC*MIN_TICKS ) );
|
||||
}
|
||||
|
||||
static uint32_t lpc43_tl_tick2ts (uint32_t ticks, FAR struct timespec *ts, bool with_rest)
|
||||
{
|
||||
|
||||
uint32_t ticks_whole;
|
||||
uint32_t ticks_rest = 0;
|
||||
|
||||
if (with_rest)
|
||||
{
|
||||
uint32_t ticks_mult = ticks/MIN_TICKS;
|
||||
ticks_whole = ticks_mult*MIN_TICKS;
|
||||
ticks_rest = ticks - ticks_whole;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ticks_whole = ticks;
|
||||
}
|
||||
|
||||
ts->tv_sec = ticks_whole/LPC43_CCLK;
|
||||
ts->tv_nsec = ((ticks_whole%LPC43_CCLK)/MIN_TICKS)*MIN_NSEC;
|
||||
|
||||
return ticks_rest;
|
||||
}
|
||||
|
||||
/* logic functions */
|
||||
|
||||
static inline void lpc43_tl_sync_up (void) {
|
||||
irqstate_t flags;
|
||||
flags = irqsave ();
|
||||
|
||||
if ( synch == 0 )
|
||||
{
|
||||
g_flags = flags;
|
||||
|
||||
}
|
||||
synch++;
|
||||
}
|
||||
|
||||
static inline void lpc43_tl_sync_down (void) {
|
||||
synch--;
|
||||
if ( synch == 0 )
|
||||
{
|
||||
irqrestore (g_flags);
|
||||
}
|
||||
}
|
||||
|
||||
/* assuming safe timer state, force interrupt, no reset possible */
|
||||
|
||||
static inline void lpc43_tl_force_int (void)
|
||||
{
|
||||
forced_int = true;
|
||||
lpc43_tl_set_reset_on_match (false);
|
||||
lpc43_tl_set_mask (UINT32_MAX);
|
||||
lpc43_tl_set_compare(UINT32_MAX);
|
||||
}
|
||||
|
||||
/* init all vars, forced_int should not be cleared */
|
||||
|
||||
static inline void lpc43_tl_init_timer_vars (void)
|
||||
{
|
||||
alarm_time_set = false;
|
||||
call = false;
|
||||
armed = false;
|
||||
|
||||
}
|
||||
|
||||
/* calc RESET_TICKS and set compare to TO_RESET */
|
||||
|
||||
static void lpc43_tl_calibrate_init (void)
|
||||
{
|
||||
uint32_t counter = lpc43_tl_get_counter ();
|
||||
|
||||
uint32_t counter_after = lpc43_tl_get_counter ();
|
||||
counter_after = TO_RESET + counter;
|
||||
counter_after = counter_after - counter;
|
||||
|
||||
/*shift to toReset*/
|
||||
|
||||
lpc43_tl_set_compare (counter_after);
|
||||
|
||||
counter_after = lpc43_tl_get_counter ();
|
||||
|
||||
RESET_TICKS = (counter_after - counter) * 2;
|
||||
|
||||
}
|
||||
|
||||
/* process current and set timer in default safe state */
|
||||
|
||||
static void lpc43_tl_save_timer (bool from_isr)
|
||||
{
|
||||
if (forced_int) /* special case of forced interrupt by mask*/
|
||||
{
|
||||
forced_int = false;
|
||||
lpc43_tl_set_compare (UINT32_MAX);
|
||||
lpc43_tl_set_mask (0);
|
||||
lpc43_tl_clear_interrupt ();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/*process reset if any*/
|
||||
|
||||
uint32_t match = lpc43_tl_get_compare ();
|
||||
|
||||
/*move to end, no resets during processing*/
|
||||
|
||||
lpc43_tl_set_compare (UINT32_MAX);
|
||||
lpc43_tl_set_mask (0);
|
||||
|
||||
if (from_isr || lpc43_tl_get_interrupt ())
|
||||
{
|
||||
if (lpc43_tl_get_reset_on_match ()) /*was reset ?*/
|
||||
{
|
||||
struct timespec match_ts;
|
||||
base_rest = lpc43_tl_tick2ts(match + base_rest, &match_ts,true);
|
||||
lpc43_tl_add(&base_ts, &match_ts,&base_ts);
|
||||
}
|
||||
lpc43_tl_clear_interrupt ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* assuming safe timer state, true if set, false - time is in the past */
|
||||
|
||||
static bool lpc43_tl_set_safe_compare (uint32_t compare_to_set)
|
||||
{
|
||||
if (compare_to_set < TO_RESET)
|
||||
{
|
||||
lpc43_tl_set_reset_on_match (false);
|
||||
}
|
||||
else
|
||||
{
|
||||
lpc43_tl_set_reset_on_match (true);
|
||||
}
|
||||
|
||||
lpc43_tl_set_compare (compare_to_set);
|
||||
|
||||
//check if ok
|
||||
bool reset = lpc43_tl_get_interrupt ();
|
||||
uint32_t counter = lpc43_tl_get_counter ();
|
||||
bool reset_after = lpc43_tl_get_interrupt ();
|
||||
|
||||
if (reset != reset_after)
|
||||
{
|
||||
//was a reset get new counter
|
||||
counter = lpc43_tl_get_counter ();
|
||||
}
|
||||
|
||||
if (reset_after || (!reset_after && compare_to_set > counter))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
lpc43_tl_set_compare (UINT32_MAX);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* assuming safe timer state, set_safe_compare in loop */
|
||||
|
||||
static void lpc43_tl_looped_forced_set_compare (void)
|
||||
{
|
||||
uint32_t i = 1;
|
||||
bool result = lpc43_tl_set_safe_compare (
|
||||
lpc43_tl_get_counter () + RESET_TICKS); /* like in calibrateInit */
|
||||
while (!result)
|
||||
{
|
||||
i++;
|
||||
result = lpc43_tl_set_safe_compare (
|
||||
lpc43_tl_get_counter () + RESET_TICKS * i);
|
||||
};
|
||||
}
|
||||
|
||||
/* assuming safe timer state, true if set, false - time is in the past */
|
||||
|
||||
static bool lpc43_tl_set_calc_arm (uint32_t curr, uint32_t to_set, bool arm)
|
||||
{
|
||||
|
||||
uint32_t calcTime;
|
||||
|
||||
if (curr < TO_RESET_NEXT)
|
||||
{
|
||||
calcTime = min(TO_RESET_NEXT, to_set);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (curr < TO_END)
|
||||
{
|
||||
calcTime = min(curr + RESET_TICKS, to_set);
|
||||
}
|
||||
else
|
||||
{
|
||||
lpc43_tl_looped_forced_set_compare ();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool set = lpc43_tl_set_safe_compare (calcTime);
|
||||
|
||||
if (arm && set && (calcTime == to_set))
|
||||
{
|
||||
armed = true;
|
||||
}
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
/* assuming safe timer state, try to set compare for normal operation */
|
||||
|
||||
static void lpc43_tl_set_default_compare (uint32_t curr)
|
||||
{
|
||||
bool result = lpc43_tl_set_calc_arm (curr, UINT32_MAX,
|
||||
false);
|
||||
if (!result)
|
||||
{
|
||||
result = lpc43_tl_set_calc_arm (lpc43_tl_get_counter (), UINT32_MAX,
|
||||
false);
|
||||
if (!result)
|
||||
{
|
||||
lpc43_tl_looped_forced_set_compare ();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* calculates ticks to set from alarm_time_ts and base_ts/base_rest, UINT32_MAX if overflow */
|
||||
static inline uint32_t lpc43_tl_calc_to_set (void)
|
||||
{
|
||||
struct timespec diff_ts;
|
||||
struct timespec ovf_ts;
|
||||
|
||||
lpc43_tl_sub(&alarm_time_ts,&base_ts,&diff_ts);
|
||||
|
||||
lpc43_tl_sub(&diff_ts,&MAX_TS,&ovf_ts);
|
||||
if ( ovf_ts.tv_sec == 0 && ovf_ts.tv_nsec == 0 ) /* check overflow */
|
||||
{
|
||||
return ( lpc43_tl_ts2tick(&diff_ts) - base_rest );
|
||||
}
|
||||
else
|
||||
{
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* assuming safe timer state, used by isr: sets default compare , calls alarm */
|
||||
static inline void lpc43_tl_alarm (uint32_t curr)
|
||||
{
|
||||
lpc43_tl_init_timer_vars ();
|
||||
lpc43_tl_set_default_compare (curr);
|
||||
|
||||
|
||||
#ifdef CONFIG_SCHED_TICKLESS_ALARM
|
||||
struct timespec ts;
|
||||
up_timer_gettime(&ts);
|
||||
sched_alarm_expiration (&ts);
|
||||
#else
|
||||
sched_timer_expiration();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* interrupt handler */
|
||||
|
||||
static int lpc43_tl_isr (int irq, FAR void *context)
|
||||
{
|
||||
lpc43_tl_sync_up();
|
||||
|
||||
lpc43_tl_save_timer(true);
|
||||
|
||||
uint32_t curr = lpc43_tl_get_counter ();
|
||||
if (call)
|
||||
{
|
||||
lpc43_tl_alarm(curr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (armed)
|
||||
{
|
||||
lpc43_tl_alarm(curr); /* armed - call alarm */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (alarm_time_set) /* need to set alarm time */
|
||||
{
|
||||
uint32_t toSet = lpc43_tl_calc_to_set();
|
||||
|
||||
if (toSet > curr)
|
||||
{
|
||||
if (toSet > TO_END)
|
||||
{
|
||||
lpc43_tl_set_default_compare (curr);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool set = lpc43_tl_set_calc_arm (curr, toSet, true);
|
||||
if (!set)
|
||||
{
|
||||
lpc43_tl_alarm(curr);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lpc43_tl_alarm(curr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lpc43_tl_set_default_compare (curr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lpc43_tl_sync_down();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
void up_timer_initialize (void)
|
||||
{
|
||||
irqstate_t flags;
|
||||
flags = irqsave ();
|
||||
|
||||
ctrl_cache = getreg32(LPC43_RIT_CTRL);
|
||||
ctrl_cache &= ~RIT_CTRL_INT; /* set interrupt to 0*/
|
||||
mask_cache = getreg32(LPC43_RIT_MASK);
|
||||
compare_cache = getreg32(LPC43_RIT_COMPVAL);
|
||||
|
||||
COMMON_DEV = commonDev(NSEC_PER_SEC,LPC43_CCLK);
|
||||
MIN_TICKS = LPC43_CCLK/COMMON_DEV;
|
||||
MIN_NSEC = NSEC_PER_SEC/COMMON_DEV;
|
||||
|
||||
base_ts.tv_sec = 0;
|
||||
base_ts.tv_nsec = 0;
|
||||
base_rest = 0;
|
||||
|
||||
lpc43_tl_tick2ts(TO_END,&MAX_TS,false);
|
||||
|
||||
lpc43_tl_set_enable (false);
|
||||
|
||||
lpc43_tl_set_compare (UINT32_MAX);
|
||||
lpc43_tl_set_counter (0);
|
||||
lpc43_tl_set_mask (0);
|
||||
|
||||
lpc43_tl_set_reset_on_match (false);
|
||||
lpc43_tl_clear_interrupt ();
|
||||
|
||||
irq_attach (LPC43M4_IRQ_RITIMER, lpc43_tl_isr);
|
||||
up_enable_irq (LPC43M4_IRQ_RITIMER);
|
||||
|
||||
lpc43_tl_init_timer_vars ();
|
||||
|
||||
lpc43_tl_set_enable (true);
|
||||
|
||||
lpc43_tl_calibrate_init ();
|
||||
|
||||
irqrestore (flags);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* no reg changes, only processing */
|
||||
int up_timer_gettime (FAR struct timespec *ts)
|
||||
{
|
||||
lpc43_tl_sync_up();
|
||||
|
||||
/* order of calls is important, reset can come during processing */
|
||||
|
||||
bool reset = lpc43_tl_get_interrupt ();
|
||||
uint32_t count = lpc43_tl_get_counter ();
|
||||
|
||||
/* not processed reset can exist */
|
||||
if (lpc43_tl_get_reset_on_match ())
|
||||
{
|
||||
bool resetAfter = lpc43_tl_get_interrupt ();
|
||||
|
||||
if (reset != resetAfter) /* was a reset during processing? get new counter */
|
||||
{
|
||||
count = lpc43_tl_get_counter ();
|
||||
}
|
||||
|
||||
if (resetAfter)
|
||||
{
|
||||
count += lpc43_tl_get_compare (); /* count should be smaller then UINT32_MAX-TO_END -> no overflow */
|
||||
}
|
||||
}
|
||||
|
||||
struct timespec count_ts;
|
||||
|
||||
|
||||
lpc43_tl_tick2ts(count + base_rest,&count_ts,false );
|
||||
|
||||
lpc43_tl_add(&base_ts,&count_ts,ts);
|
||||
|
||||
lpc43_tl_sync_down();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
int up_alarm_cancel (FAR struct timespec *ts)
|
||||
{
|
||||
lpc43_tl_sync_up();
|
||||
|
||||
/*no reg changes, only variables logic*/
|
||||
|
||||
if ( ts != NULL ) {
|
||||
up_timer_gettime (ts);
|
||||
}
|
||||
|
||||
/* let default setup will be done in interrupt handler or up_alarm_start */
|
||||
lpc43_tl_init_timer_vars ();
|
||||
|
||||
lpc43_tl_sync_down();
|
||||
return OK;
|
||||
}
|
||||
|
||||
int up_alarm_start (FAR const struct timespec *ts)
|
||||
{
|
||||
lpc43_tl_sync_up();
|
||||
|
||||
lpc43_tl_save_timer (false);
|
||||
|
||||
lpc43_tl_init_timer_vars ();
|
||||
|
||||
alarm_time_set = true;
|
||||
alarm_time_ts.tv_sec = ts->tv_sec;
|
||||
alarm_time_ts.tv_nsec = ts->tv_nsec;
|
||||
|
||||
uint32_t toSet = lpc43_tl_calc_to_set();
|
||||
|
||||
uint32_t curr = lpc43_tl_get_counter ();
|
||||
|
||||
if (toSet > curr)
|
||||
{
|
||||
if (toSet > TO_END) /* future set */
|
||||
{
|
||||
lpc43_tl_set_default_compare (curr);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool set = lpc43_tl_set_calc_arm (curr, toSet, true);
|
||||
if (!set) /* signal call, force interrupt handler */
|
||||
{
|
||||
call = true;
|
||||
lpc43_tl_force_int ();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else /* signal call, force interrupt handler */
|
||||
{
|
||||
call = true;
|
||||
lpc43_tl_force_int ();
|
||||
}
|
||||
|
||||
lpc43_tl_sync_down();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SCHED_TICKLESS_ALARM
|
||||
|
||||
int up_timer_cancel(FAR struct timespec *ts)
|
||||
{
|
||||
lpc43_tl_sync_up();
|
||||
|
||||
if (ts != NULL)
|
||||
{
|
||||
struct timespec abs_ts;
|
||||
up_timer_gettime(&abs_ts);
|
||||
lpc43_tl_sub( &alarm_time_ts,&abs_ts,ts );
|
||||
}
|
||||
|
||||
lpc43_tl_init_timer_vars ();
|
||||
|
||||
lpc43_tl_sync_down();
|
||||
return OK;
|
||||
}
|
||||
|
||||
int up_timer_start(FAR const struct timespec *ts)
|
||||
{
|
||||
|
||||
lpc43_tl_sync_up();
|
||||
|
||||
struct timespec abs_ts;
|
||||
up_timer_gettime(&abs_ts);
|
||||
lpc43_tl_add(&abs_ts,ts,&abs_ts);
|
||||
|
||||
up_alarm_start(&abs_ts);
|
||||
|
||||
lpc43_tl_sync_down();
|
||||
return OK;
|
||||
}
|
||||
|
||||
# endif /* CONFIG_SCHED_TICKLESS_ALARM */
|
||||
|
||||
#endif /* CONFIG_SCHED_TICKLESS */
|
@ -1079,9 +1079,8 @@ static void lpc43_usbreset(struct lpc43_usbdev_s *priv)
|
||||
{
|
||||
int epphy;
|
||||
|
||||
/* Disable all endpoints */
|
||||
/* Disable all endpoints. Control endpoint 0 is always enabled */
|
||||
|
||||
lpc43_clrbits (USBDEV_ENDPTCTRL_RXE | USBDEV_ENDPTCTRL_TXE, LPC43_USBDEV_ENDPTCTRL0);
|
||||
lpc43_clrbits (USBDEV_ENDPTCTRL_RXE | USBDEV_ENDPTCTRL_TXE, LPC43_USBDEV_ENDPTCTRL1);
|
||||
lpc43_clrbits (USBDEV_ENDPTCTRL_RXE | USBDEV_ENDPTCTRL_TXE, LPC43_USBDEV_ENDPTCTRL2);
|
||||
lpc43_clrbits (USBDEV_ENDPTCTRL_RXE | USBDEV_ENDPTCTRL_TXE, LPC43_USBDEV_ENDPTCTRL3);
|
||||
@ -2584,12 +2583,9 @@ void up_usbinitialize(void)
|
||||
struct lpc43_usbdev_s *priv = &g_usbdev;
|
||||
int i;
|
||||
uint32_t regval;
|
||||
irqstate_t flags;
|
||||
|
||||
usbtrace(TRACE_DEVINIT, 0);
|
||||
|
||||
/* Disable USB interrupts */
|
||||
|
||||
lpc43_putreg(0, LPC43_USBDEV_USBINTR);
|
||||
flags = irqsave();
|
||||
|
||||
/* Initialize the device state structure */
|
||||
|
||||
@ -2647,10 +2643,15 @@ void up_usbinitialize(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable PLL0 clock */
|
||||
|
||||
lpc43_pll0usbconfig();
|
||||
lpc43_pll0usbenable();
|
||||
|
||||
/* Clock */
|
||||
|
||||
regval = getreg32(LPC43_BASE_USB0_CLK);
|
||||
regval &= ~BASE_USB0_CLK_CLKSEL_MASK;
|
||||
regval &= ~(BASE_USB0_CLK_CLKSEL_MASK | BASE_USB0_CLK_PD) ;
|
||||
regval |= (BASE_USB0_CLKSEL_PLL0USB | BASE_USB0_CLK_AUTOBLOCK);
|
||||
putreg32(regval, LPC43_BASE_USB0_CLK);
|
||||
|
||||
@ -2660,20 +2661,11 @@ void up_usbinitialize(void)
|
||||
regval |= CCU_CLK_CFG_RUN;
|
||||
putreg32(regval, LPC43_CCU1_M4_USB0_CFG);
|
||||
|
||||
/* Enable PLL0 clock */
|
||||
//lpc43_putreg(RGU_CTRL0_USB0_RST, LPC43_RGU_CTRL0); /* Reset USB block */
|
||||
|
||||
lpc43_pll0usbconfig();
|
||||
lpc43_pll0usbenable();
|
||||
lpc43_pullup(&priv->usbdev, false); /* disconnect device */
|
||||
|
||||
/* Reset USB block */
|
||||
|
||||
regval = lpc43_getreg(LPC43_RGU_CTRL0);
|
||||
regval |= RGU_CTRL0_USB0_RST;
|
||||
lpc43_putreg(regval, LPC43_RGU_CTRL0);
|
||||
|
||||
/* Reset the controller */
|
||||
|
||||
lpc43_putreg (USBDEV_USBCMD_RST, LPC43_USBDEV_USBCMD);
|
||||
lpc43_setbits (USBDEV_USBCMD_RST, LPC43_USBDEV_USBCMD); /* Reset the controller */
|
||||
while (lpc43_getreg (LPC43_USBDEV_USBCMD) & USBDEV_USBCMD_RST)
|
||||
;
|
||||
|
||||
@ -2683,33 +2675,25 @@ void up_usbinitialize(void)
|
||||
regval &= ~CREG0_USB0PHY;
|
||||
putreg32(regval, LPC43_CREG0);
|
||||
|
||||
/* Attach USB controller interrupt handler */
|
||||
|
||||
if (irq_attach(LPC43M4_IRQ_USB0, lpc43_usbinterrupt) != 0)
|
||||
{
|
||||
usbtrace(TRACE_DEVERROR(LPC43_TRACEERR_IRQREGISTRATION),
|
||||
(uint16_t)LPC43M4_IRQ_USB0);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
lpc43_putreg(0, LPC43_USBDEV_USBINTR); /* Disable USB interrupts */
|
||||
|
||||
/* Program the controller to be the USB device controller */
|
||||
|
||||
lpc43_putreg (USBDEV_USBMODE_SDIS | USBDEV_USBMODE_SLOM | USBDEV_USBMODE_CM_DEVICE,
|
||||
LPC43_USBDEV_USBMODE);
|
||||
|
||||
/* Disconnect device */
|
||||
/* Attach USB controller interrupt handler */
|
||||
|
||||
lpc43_pullup(&priv->usbdev, false);
|
||||
irq_attach(LPC43M4_IRQ_USB0, lpc43_usbinterrupt);
|
||||
up_enable_irq(LPC43M4_IRQ_USB0);
|
||||
|
||||
irqrestore(flags);
|
||||
|
||||
/* Reset/Re-initialize the USB hardware */
|
||||
|
||||
lpc43_usbreset(priv);
|
||||
|
||||
return;
|
||||
|
||||
errout:
|
||||
up_usbuninitialize();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -2742,7 +2726,7 @@ void up_usbuninitialize(void)
|
||||
|
||||
/* Reset the controller */
|
||||
|
||||
lpc43_putreg (USBDEV_USBCMD_RST, LPC43_USBDEV_USBCMD);
|
||||
lpc43_setbits (USBDEV_USBCMD_RST, LPC43_USBDEV_USBCMD);
|
||||
while (lpc43_getreg (LPC43_USBDEV_USBCMD) & USBDEV_USBCMD_RST)
|
||||
;
|
||||
|
||||
@ -2850,3 +2834,4 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver)
|
||||
g_usbdev.driver = NULL;
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user