arch/arm/src/lpc54xx: Complete coding of the I2C driver. It is not yet functional and has not yet been seriously tested. config/lpcxpresso-lpc54628: Add support for I2C2 and for the I2C tool to the nsh configuration.
This commit is contained in:
parent
9638f3f065
commit
c8a8eb028f
@ -313,6 +313,8 @@
|
||||
#define I2C_SLAVE_STATE_RXAVAIL (1) /* Received data is available (Slave Receiver mode) */
|
||||
#define I2C_SLAVE_STATE_TXOK (2) /* Data can be transmitted (Slave Transmitter mode) */
|
||||
|
||||
/* Interrupt status, set and read, and clear registers */
|
||||
|
||||
#define I2C_INT_MSTPENDING (1 << 0) /* Bit 0 Master Pending interrupt */
|
||||
#define I2C_STAT_MSTSTATE_SHIFT (1) /* Bits 1-3: Master State code (status only) */
|
||||
#define I2C_STAT_MSTSTATE_MASK (7 << I2C_STAT_MSTSTATE_SHIFT)
|
||||
@ -345,7 +347,7 @@
|
||||
#define I2C_INT_EVENTTIMEOUT (1 << 24) /* Bit 24: Event time-out interrupt */
|
||||
#define I2C_INT_SCLTIMEOUT (1 << 25) /* Bit 25: SCL time-out interrupt */
|
||||
|
||||
#define I2C_INT_MSTPENDING (1 << 0) /* Bit 0 Master Pending interrupt */
|
||||
#define I2C_INT_MSTPENDING (1 << 0) /* Bit 0 Master Pending interrupt */
|
||||
#define I2C_INT_MSTARBLOSS (1 << 4) /* Bit 4: Master Arbitration Loss interrupt */
|
||||
#define I2C_INT_MSTSTSTPERR (1 << 6) /* Bit 6: Master Start/Stop Error interrupt */
|
||||
#define I2C_INT_SLVPENDING (1 << 8) /* Bit 8: Slave Pending interrupt */
|
||||
@ -360,7 +362,11 @@
|
||||
#define I2C_INT_ALL 0x030b8951
|
||||
|
||||
/* Time-out value */
|
||||
#define I2C_TIMEOUT_
|
||||
|
||||
#define I2C_TIMEOUT_SHIFT (0) /* Bits 0-15: Time out value
|
||||
* Bits 0-3 hardwired to 0xff */
|
||||
#define I2C_TIMEOUT_MASK (0xffff << I2C_TIMEOUT_SHIFT)
|
||||
# define I2C_TIMEOUT(n) ((uint32_t)((n)-1) << I2C_TIMEOUT_SHIFT)
|
||||
|
||||
/* Clock pre-divider for the entire I2C interface */
|
||||
|
||||
@ -368,9 +374,6 @@
|
||||
#define I2C_CLKDIV_MASK (0xffff << I2C_CLKDIV_SHIFT)
|
||||
# define I2C_CLKDIV(n) ((uint32_t)((n)-1) << I2C_CLKDIV_SHIFT)
|
||||
|
||||
/* Interrupt status register for shared functions */
|
||||
#define I2C_INTSTAT_
|
||||
|
||||
/* Master control */
|
||||
|
||||
#define I2C_MSTCTL_MSTCONTINUE (1 << 0) /* Bit 0: Master Continue */
|
||||
@ -388,7 +391,11 @@
|
||||
# define I2C_MSTTIME_SCLHIGH(n) ((uint32_t)((n)-2) << I2C_MSTTIME_SCLHIGH_SHIFT)
|
||||
|
||||
/* Combined Master receiver and transmitter data */
|
||||
#define I2C_MSTDAT_
|
||||
|
||||
#define I2C_MSTDAT_SHIFT (0) /* Bits 0-7: Master function data */
|
||||
#define I2C_MSTDAT_MASK (0xff << I2C_MSTDAT_SHIFT)
|
||||
# define I2C_MSTDAT(n) ((uint32_t)(n) << I2C_MSTDAT_SHIFT)
|
||||
|
||||
/* Slave control */
|
||||
#define I2C_SLVCTL_
|
||||
/* Combined Slave receiver and transmitter data */
|
||||
|
@ -184,11 +184,11 @@
|
||||
#undef HAVE_I2C_MASTER_DEVICE
|
||||
|
||||
#if defined(CONFIG_LPC54_I2C0_MASTER) || defined(CONFIG_LPC54_I2C1_MASTER) || \
|
||||
defined(CONFIG_LPC54_I2C1_MASTER) || defined(CONFIG_LPC54_I2C3_MASTER) || \
|
||||
defined(CONFIG_LPC54_I2C_MASTER4) || defined(CONFIG_LPC54_I2C5_MASTER) || \
|
||||
defined(CONFIG_LPC54_I2C2_MASTER) || defined(CONFIG_LPC54_I2C3_MASTER) || \
|
||||
defined(CONFIG_LPC54_I2C4_MASTER) || defined(CONFIG_LPC54_I2C5_MASTER) || \
|
||||
defined(CONFIG_LPC54_I2C6_MASTER) || defined(CONFIG_LPC54_I2C7_MASTER) || \
|
||||
defined(CONFIG_LPC54_I2C8_MASTER) || defined(CONFIG_LPC54_I2C9_MASTER)
|
||||
# define HAVE_MASTER_I2C_MASTER_DEVICE 1
|
||||
# define HAVE_I2C_MASTER_DEVICE 1
|
||||
#endif
|
||||
|
||||
/* Check if we have an SPI device */
|
||||
|
@ -4,6 +4,12 @@
|
||||
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Parts of this file were adapted from sample code provided for the LPC54xx
|
||||
* family from NXP which has a compatible BSD license.
|
||||
*
|
||||
* Copyright (c) 2016, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
@ -49,6 +55,7 @@
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/wdog.h>
|
||||
#include <nuttx/clock.h>
|
||||
#include <nuttx/semaphore.h>
|
||||
#include <nuttx/i2c/i2c_master.h>
|
||||
|
||||
@ -64,21 +71,54 @@
|
||||
#include "chip/lpc54_flexcomm.h"
|
||||
#include "chip/lpc54_i2c.h"
|
||||
#include "lpc54_config.h"
|
||||
#include "lpc54_clockconfig.h"
|
||||
#include "lpc54_enableclk.h"
|
||||
#include "lpc54_gpio.h"
|
||||
#include "lpc54_i2c_master.h"
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#ifdef HAVE_SPI_MASTER_DEVICE
|
||||
#ifdef HAVE_I2C_MASTER_DEVICE
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* 20 Millisecond timeout in system clock ticks. */
|
||||
|
||||
#define I2C_WDOG_TIMEOUT MSEC2TICK(20)
|
||||
|
||||
/* Default I2C frequency */
|
||||
|
||||
#if defined(CONFIG_LPC54_I2C_FAST) || defined(CONFIG_LPC54_I2C_HIGH)
|
||||
# define I2C_DEFAULT_FREQUENCY 1000000
|
||||
#else
|
||||
# define I2C_DEFAULT_FREQUENCY 400000
|
||||
#endif
|
||||
|
||||
/* I2C Master Interrupts */
|
||||
|
||||
#define I2C_MASTER_INTS \
|
||||
(I2C_INT_MSTPENDING | I2C_INT_MSTARBLOSS | I2C_INT_MSTSTSTPERR)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/* I2C state */
|
||||
|
||||
enum lpc54_i2cstate_e
|
||||
{
|
||||
I2CSTATE_IDLE = 0,
|
||||
I2CSTATE_TRANSMIT,
|
||||
I2CSTATE_RECEIVE,
|
||||
I2CSTATE_START,
|
||||
I2CSTATE_STOP,
|
||||
I2CSTATE_WAITDONE
|
||||
};
|
||||
|
||||
/* This structure provides the overall state of the I2C driver */
|
||||
|
||||
struct lpc54_i2cdev_s
|
||||
{
|
||||
struct i2c_master_s dev; /* Generic I2C device */
|
||||
@ -89,13 +129,15 @@ struct lpc54_i2cdev_s
|
||||
uint32_t fclock; /* Flexcomm function clock frequency */
|
||||
|
||||
struct i2c_msg_s *msgs; /* Remaining transfers (first is in progress) */
|
||||
unsigned int nmsg; /* Number of transfer remaining */
|
||||
int16_t nmsgs; /* Number of transfer remaining */
|
||||
int16_t result; /* The result of the transfer */
|
||||
|
||||
sem_t exclsem; /* Only one thread can access at a time */
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
sem_t waitsem; /* Supports wait for state machine completion */
|
||||
uint16_t irq; /* Flexcomm IRQ number */
|
||||
uint16_t wrcnt; /* Number of bytes sent to tx fifo */
|
||||
uint16_t rdcnt; /* Number of bytes read from rx fifo */
|
||||
#endif
|
||||
uint16_t xfrd; /* Number of bytes transferred */
|
||||
volatile uint8_t state; /* State of state machine */
|
||||
};
|
||||
|
||||
@ -103,16 +145,26 @@ struct lpc54_i2cdev_s
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static int lpc54_i2c_start(struct lpc54_i2cdev_s *priv);
|
||||
static void lpc54_i2c_stop(struct lpc54_i2cdev_s *priv);
|
||||
static int lpc54_i2c_interrupt(int irq, FAR void *context, FAR void *arg);
|
||||
static void lpc54_i2c_timeout(int argc, uint32_t arg, ...);
|
||||
static inline void lpc54_i2c_putreg(struct lpc54_i2cdev_s *priv,
|
||||
unsigned int regoffset, uint32_t regval);
|
||||
static inline uint32_t lpc54_i2c_getreg(struct lpc54_i2cdev_s *priv,
|
||||
unsigned int regoffset);
|
||||
|
||||
static void lpc54_i2c_setfrequency(struct lpc54_i2cdev_s *priv,
|
||||
uint32_t frequency);
|
||||
static void lpc54_i2c_timeout(int argc, uint32_t arg, ...);
|
||||
static void lpc54_i2c_xfrsetup(struct lpc54_i2cdev_s *priv);
|
||||
static bool lpc54_i2c_nextmsg(struct lpc54_i2cdev_s *priv);
|
||||
static bool lpc54_i2c_statemachine(struct lpc54_i2cdev_s *priv);
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
static int lpc54_i2c_interrupt(int irq, FAR void *context, FAR void *arg);
|
||||
#else
|
||||
static int lpc54_i2c_poll(struct lpc54_i2cdev_s *priv);
|
||||
#endif
|
||||
static int lpc54_i2c_transfer(FAR struct i2c_master_s *dev,
|
||||
FAR struct i2c_msg_s *msgs, int count);
|
||||
#ifdef CONFIG_I2C_RESET
|
||||
static int lpc54_i2c_reset(FAR struct i2c_master_s * dev);
|
||||
static int lpc54_i2c_reset(FAR struct i2c_master_s * dev);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
@ -173,7 +225,7 @@ static struct lpc54_i2cdev_s g_i2c9_dev;
|
||||
static inline void lpc54_i2c_putreg(struct lpc54_i2cdev_s *priv,
|
||||
unsigned int regoffset, uint32_t regval)
|
||||
{
|
||||
putreg32(value, priv->base + regoffset);
|
||||
putreg32(regval, priv->base + regoffset);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -184,39 +236,12 @@ static inline void lpc54_i2c_putreg(struct lpc54_i2cdev_s *priv,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline void lpc54_i2c_getreg(struct lpc54_i2cdev_s *priv,
|
||||
unsigned int regoffset)
|
||||
static inline uint32_t lpc54_i2c_getreg(struct lpc54_i2cdev_s *priv,
|
||||
unsigned int regoffset)
|
||||
{
|
||||
return getreg32(priv->base + regoffset);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lpc54_wait_pendingstatus
|
||||
*
|
||||
* Description:
|
||||
* Wait for status update to complete and clear the I2C state.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t lpc54_wait_pendingstatus(struct lpc54_i2cdev_s *priv)
|
||||
{
|
||||
uint32_t regval;
|
||||
|
||||
/* Wait until status is no longer pending */
|
||||
|
||||
do
|
||||
{
|
||||
regval = lpc54_i2c_getreg(priv, LPC54_I2C_STAT_OFFSET);
|
||||
}
|
||||
while ((regval & I2C_INT_MSTPENDING) == 0);
|
||||
|
||||
/* Clear controller state and return the last status */
|
||||
|
||||
lpc43_i2c_putreg(priv, LPC54_I2C_STAT_OFFSET,
|
||||
(I2C_STAT_MSTARBLOSS_MASK | I2C_STAT_MSTSTSTPERR_MASK));
|
||||
return regval;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lpc54_i2c_setfrequency
|
||||
*
|
||||
@ -291,59 +316,12 @@ static void lpc54_i2c_setfrequency(struct lpc54_i2cdev_s *priv,
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_CLKDIV_OFFSET, regval);
|
||||
|
||||
regval = I2C_MSTTIME_SCLLOW(best_scl) | I2C_MSTTIME_SCLHIGH(best_scl);
|
||||
lpc54_i2c_putreg(LPC54_I2C_MSTTIME_OFFSET, regval);
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_MSTTIME_OFFSET, regval);
|
||||
|
||||
priv->frequency = frequency;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lpc54_i2c_start
|
||||
*
|
||||
* Description:
|
||||
* Perform a I2C transfer start
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int lpc54_i2c_start(struct lpc54_i2cdev_s *priv)
|
||||
{
|
||||
struct i2c_msg_s *msg = priv->msgs;
|
||||
uint32_t regval;
|
||||
|
||||
/* Write the address with the R/W bit */
|
||||
|
||||
if ((I2C_M_READ & msg->flags) == I2C_M_READ)
|
||||
{
|
||||
regval = I2C_READADDR8(msg->addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
regval = I2C_WRITEADDR8(msg->addr);
|
||||
}
|
||||
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_MSTDAT_OFFSET, regval);
|
||||
|
||||
/* Initiate the Start */
|
||||
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_MSTCTL_OFFSET, I2C_MSTCTL_MSTSTART);
|
||||
return priv->nmsg;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lpc54_i2c_stop
|
||||
*
|
||||
* Description:
|
||||
* Perform a I2C transfer stop
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void lpc54_i2c_stop(struct lpc54_i2cdev_s *priv)
|
||||
{
|
||||
(void)lpc54_wait_pendingstatus(priv);
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_MSTCTL_OFFSET, I2C_MSTCTL_MSTSTOP);
|
||||
nxsem_post(&priv->waitsem);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lpc54_i2c_timeout
|
||||
*
|
||||
@ -356,32 +334,141 @@ static void lpc54_i2c_timeout(int argc, uint32_t arg, ...)
|
||||
{
|
||||
struct lpc54_i2cdev_s *priv = (struct lpc54_i2cdev_s *)arg;
|
||||
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
irqstate_t flags = enter_critical_section();
|
||||
priv->state = 0xff;
|
||||
#endif
|
||||
|
||||
/* Disable further I2C interrupts and return to the IDLE state with the
|
||||
* timeout result.
|
||||
*/
|
||||
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_INTENCLR_OFFSET, I2C_MASTER_INTS);
|
||||
priv->state = I2CSTATE_IDLE;
|
||||
priv->result = -ETIMEDOUT;
|
||||
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
/* Wake up any waiters */
|
||||
|
||||
nxsem_post(&priv->waitsem);
|
||||
leave_critical_section(flags);
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lpc32_i2c_nextmsg
|
||||
* Name: lpc54_i2c_xfrsetup
|
||||
*
|
||||
* Description:
|
||||
* Setup for the next message.
|
||||
* Setup to initiate a transfer.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void lpc32_i2c_nextmsg(struct lpc54_i2cdev_s *priv)
|
||||
static void lpc54_i2c_xfrsetup(struct lpc54_i2cdev_s *priv)
|
||||
{
|
||||
priv->nmsg--;
|
||||
struct i2c_msg_s *msg;
|
||||
|
||||
if (priv->nmsg > 0)
|
||||
DEBUGASSERT(priv != NULL && priv->msgs != NULL);
|
||||
msg = priv->msgs;
|
||||
|
||||
/* Disable I2C interrupts while configuring for the transfer */
|
||||
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_INTENCLR_OFFSET, I2C_MASTER_INTS);
|
||||
|
||||
/* Set up for the transfer */
|
||||
|
||||
priv->xfrd = 0;
|
||||
|
||||
/* Select the initial state */
|
||||
|
||||
if ((msg->flags & I2C_M_NORESTART) != 0)
|
||||
{
|
||||
priv->msgs++;
|
||||
#warning Missing logic
|
||||
/* Start condition will be ommited. Begin the tranfer in the data
|
||||
* phase.
|
||||
*/
|
||||
|
||||
if (msg->length == 0)
|
||||
{
|
||||
priv->state = I2CSTATE_STOP;
|
||||
}
|
||||
else if ((I2C_M_READ & msg->flags) == I2C_M_READ)
|
||||
{
|
||||
priv->state = I2CSTATE_RECEIVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->state = I2CSTATE_TRANSMIT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lpc54_i2c_stop(priv);
|
||||
priv->state = I2CSTATE_START;
|
||||
}
|
||||
|
||||
/* Set the I2C frequency if provided in this message. Otherwise, use the
|
||||
* current I2C frequency setting.
|
||||
*/
|
||||
|
||||
if (msg->frequency > 0)
|
||||
{
|
||||
(void)lpc54_i2c_setfrequency(priv, msg->frequency);
|
||||
}
|
||||
|
||||
/* Clear error status bits */
|
||||
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_STAT_OFFSET, I2C_INT_MSTARBLOSS |
|
||||
I2C_INT_MSTSTSTPERR);
|
||||
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
/* Enable I2C master interrupts */
|
||||
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_INTENSET_OFFSET, I2C_MASTER_INTS);
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lpc54_i2c_nextmsg
|
||||
*
|
||||
* Description:
|
||||
* Called at the completion of each message. If there are more messages,
|
||||
* this function will perform the setup for the next message.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static bool lpc54_i2c_nextmsg(struct lpc54_i2cdev_s *priv)
|
||||
{
|
||||
irqstate_t flags;
|
||||
|
||||
/* Disable interrupts to prevent the timeout while we make the decision
|
||||
* here.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Decrement the number of messages remaining. */
|
||||
|
||||
if (--priv->nmsgs > 0)
|
||||
{
|
||||
/* There are more messages, set up for the next message */
|
||||
|
||||
priv->msgs++;
|
||||
lpc54_i2c_xfrsetup(priv);
|
||||
|
||||
leave_critical_section(flags);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* That was the last message... we are done. */
|
||||
/* Cancel any timeout */
|
||||
|
||||
wd_cancel(priv->timeout);
|
||||
|
||||
/* Disable further I2C interrupts and return to the IDLE state */
|
||||
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_INTENCLR_OFFSET, I2C_MASTER_INTS);
|
||||
priv->state = I2CSTATE_IDLE;
|
||||
|
||||
leave_critical_section(flags);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -395,9 +482,190 @@ void lpc32_i2c_nextmsg(struct lpc54_i2cdev_s *priv)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void lpc54_i2c_statemachine(struct lpc54_i2cdev_s *priv)
|
||||
static bool lpc54_i2c_statemachine(struct lpc54_i2cdev_s *priv)
|
||||
{
|
||||
#warning Missing logic
|
||||
struct i2c_msg_s *msg;
|
||||
uint32_t status;
|
||||
uint32_t mstate;
|
||||
|
||||
DEBUGASSERT(priv != NULL && priv->msgs != NULL);
|
||||
msg = priv->msgs;
|
||||
|
||||
status = lpc54_i2c_getreg(priv, LPC54_I2C_STAT_OFFSET);
|
||||
|
||||
if (status & I2C_INT_MSTARBLOSS)
|
||||
{
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_STAT_OFFSET, I2C_INT_MSTARBLOSS);
|
||||
priv->result = -EIO;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (status & I2C_INT_MSTSTSTPERR)
|
||||
{
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_STAT_OFFSET, I2C_INT_MSTSTSTPERR);
|
||||
priv->result = -EIO;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((status & I2C_INT_MSTPENDING) == 0)
|
||||
{
|
||||
priv->result = -EBUSY;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Get the state of the I2C module */
|
||||
|
||||
mstate = (status & I2C_STAT_MSTSTATE_MASK) >> I2C_STAT_MSTSTATE_SHIFT;
|
||||
|
||||
if ((mstate == I2C_MASTER_STATE_ADDRNAK) ||
|
||||
(mstate == I2C_MASTER_STATE_DATANAK))
|
||||
{
|
||||
/* Slave NACKed last byte, issue stop and return error */
|
||||
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_MSTCTL_OFFSET, I2C_MSTCTL_MSTSTOP);
|
||||
priv->result = -EPERM;
|
||||
priv->state = I2CSTATE_WAITDONE;
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (priv->state)
|
||||
{
|
||||
case I2CSTATE_START:
|
||||
{
|
||||
enum lpc54_i2cstate_e newstate;
|
||||
|
||||
if ((msg->flags & I2C_M_READ) == I2C_M_READ)
|
||||
{
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_MSTDAT_OFFSET,
|
||||
I2C_READADDR8(msg->addr));
|
||||
newstate = I2CSTATE_TRANSMIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_MSTDAT_OFFSET,
|
||||
I2C_WRITEADDR8(msg->addr));
|
||||
newstate = I2CSTATE_RECEIVE;
|
||||
}
|
||||
|
||||
if (priv->xfrd >= msg->length)
|
||||
{
|
||||
/* No more data, setup for STOP */
|
||||
|
||||
newstate = I2CSTATE_STOP;
|
||||
}
|
||||
|
||||
priv->state = newstate;
|
||||
|
||||
/* Send START condition */
|
||||
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_MSTCTL_OFFSET,
|
||||
I2C_MSTCTL_MSTSTART);
|
||||
}
|
||||
break;
|
||||
|
||||
case I2CSTATE_TRANSMIT:
|
||||
{
|
||||
if (mstate != I2C_MASTER_STATE_TXOK)
|
||||
{
|
||||
priv->result = -EINVAL;
|
||||
return true;
|
||||
}
|
||||
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_MSTDAT_OFFSET,
|
||||
msg->buffer[priv->xfrd]);
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_MSTCTL_OFFSET,
|
||||
I2C_MSTCTL_MSTCONTINUE);
|
||||
priv->xfrd++;
|
||||
|
||||
if (priv->xfrd >= msg->length)
|
||||
{
|
||||
/* No more data, schedule stop condition */
|
||||
|
||||
priv->state = I2CSTATE_STOP;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case I2CSTATE_RECEIVE:
|
||||
{
|
||||
if (mstate != I2C_MASTER_STATE_RXAVAIL)
|
||||
{
|
||||
priv->result = -EINVAL;
|
||||
return true;
|
||||
}
|
||||
|
||||
msg->buffer[priv->xfrd] =
|
||||
lpc54_i2c_getreg(priv, LPC54_I2C_MSTDAT_OFFSET);
|
||||
|
||||
priv->xfrd++;
|
||||
if (priv->xfrd < msg->length)
|
||||
{
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_MSTCTL_OFFSET,
|
||||
I2C_MSTCTL_MSTCONTINUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No more data expected, issue NACK and STOP right away */
|
||||
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_MSTCTL_OFFSET,
|
||||
I2C_MSTCTL_MSTSTOP);
|
||||
priv->state = I2CSTATE_WAITDONE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case I2CSTATE_STOP:
|
||||
{
|
||||
bool dostop = true;
|
||||
|
||||
/* Is this the last message? */
|
||||
|
||||
if (priv->nmsgs > 1)
|
||||
{
|
||||
struct i2c_msg_s *nextmsg;
|
||||
|
||||
/* No.. Is there a start on the next message? If so, it
|
||||
* should be preceded by a STOP.
|
||||
*/
|
||||
|
||||
nextmsg = msg + 1;
|
||||
dostop = ((nextmsg->flags & I2C_M_NORESTART) != 0);
|
||||
}
|
||||
|
||||
if (dostop)
|
||||
{
|
||||
/* Stop condition is omitted, we are done. Start the next
|
||||
* message (or return to the IDLE state if none).
|
||||
*/
|
||||
|
||||
return lpc54_i2c_nextmsg(priv);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Send stop condition */
|
||||
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_MSTCTL_OFFSET,
|
||||
I2C_MSTCTL_MSTSTOP);
|
||||
priv->state = I2CSTATE_WAITDONE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case I2CSTATE_WAITDONE:
|
||||
{
|
||||
/* Start the next message (or return to the IDLE state if none). */
|
||||
|
||||
return lpc54_i2c_nextmsg(priv);
|
||||
}
|
||||
break;
|
||||
|
||||
case I2CSTATE_IDLE:
|
||||
default:
|
||||
priv->result = -EINVAL;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -408,30 +676,31 @@ static void lpc54_i2c_statemachine(struct lpc54_i2cdev_s *priv)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
static int lpc54_i2c_interrupt(int irq, FAR void *context, FAR void *arg)
|
||||
{
|
||||
struct lpc54_i2cdev_s *priv = (struct lpc54_i2cdev_s *)arg;
|
||||
struct i2c_msg_s *msg;
|
||||
uint32_t state;
|
||||
bool done;
|
||||
|
||||
DEBUGASSERT(priv != NULL);
|
||||
|
||||
state = lpc54_i2c_getreg(priv, LPC54_I2C_STAT_OFFSET);
|
||||
msg = priv->msgs;
|
||||
#warning Missing logic
|
||||
/* Run the I2C state machine */
|
||||
|
||||
priv->state = state;
|
||||
switch (state)
|
||||
done = lpc54_i2c_statemachine(priv);
|
||||
if (done)
|
||||
{
|
||||
#warning Missing logic
|
||||
default:
|
||||
lpc54_i2c_stop(priv);
|
||||
break;
|
||||
/* Disable further I2C interrupts. */
|
||||
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_INTENCLR_OFFSET, I2C_MASTER_INTS);
|
||||
|
||||
/* Wake up wake up any waiters */
|
||||
|
||||
nxsem_post(&priv->waitsem);
|
||||
}
|
||||
|
||||
#warning Missing logic
|
||||
return OK;
|
||||
}
|
||||
#endif /* CONFIG_I2C_POLLED */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lpc54_i2c_transfer
|
||||
@ -455,23 +724,33 @@ static int lpc54_i2c_transfer(FAR struct i2c_master_s *dev,
|
||||
|
||||
/* Set up for the transfer */
|
||||
|
||||
priv->wrcnt = 0;
|
||||
priv->rdcnt = 0;
|
||||
priv->xfrd = 0;
|
||||
priv->msgs = msgs;
|
||||
priv->nmsg = count;
|
||||
priv->nmsgs = count;
|
||||
|
||||
/* Configure the I2C frequency.
|
||||
* REVISIT: Note that the frequency is set only on the first message.
|
||||
* This could be extended to support different transfer frequencies for
|
||||
* each message segment.
|
||||
*/
|
||||
/* Set up the transfer timeout */
|
||||
/* wd_start(priv->timeout ...); */
|
||||
|
||||
lpc54_i2c_setfrequency(priv, msgs->frequency);
|
||||
wd_start(priv->timeout, I2C_WDOG_TIMEOUT, lpc54_i2c_timeout, 1,
|
||||
(uint32_t)priv);
|
||||
|
||||
/* Perform the transfer */
|
||||
/* Initiate the transfer */
|
||||
|
||||
ret = lpc54_i2c_start(priv);
|
||||
lpc54_i2c_xfrsetup(priv);
|
||||
|
||||
/* Loop until the transfer is complete or until a timeout occurs */
|
||||
|
||||
do
|
||||
{
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
nxsem_wait(&priv->waitsem);
|
||||
#else
|
||||
(void)lpc54_i2c_statemachine(priv);
|
||||
#endif
|
||||
}
|
||||
while (priv->state != I2CSTATE_IDLE);
|
||||
|
||||
ret = priv->result;
|
||||
nxsem_post(&priv->exclsem);
|
||||
return ret;
|
||||
}
|
||||
@ -515,7 +794,6 @@ struct i2c_master_s *lpc54_i2cbus_initialize(int port)
|
||||
struct lpc54_i2cdev_s *priv;
|
||||
irqstate_t flags;
|
||||
uint32_t regval;
|
||||
uint32_t deffreq;
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
@ -542,8 +820,10 @@ struct i2c_master_s *lpc54_i2cbus_initialize(int port)
|
||||
|
||||
priv = &g_i2c0_dev;
|
||||
priv->base = LPC54_FLEXCOMM0_BASE;
|
||||
priv->irq = LPC54_IRQ_FLEXCOMM0;
|
||||
priv->fclock = BOARD_FLEXCOMM0_FCLK;
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
priv->irq = LPC54_IRQ_FLEXCOMM0;
|
||||
#endif
|
||||
|
||||
/* Configure I2C pins (defined in board.h) */
|
||||
|
||||
@ -553,10 +833,6 @@ struct i2c_master_s *lpc54_i2cbus_initialize(int port)
|
||||
/* Set up the FLEXCOMM0 function clock */
|
||||
|
||||
putreg32(BOARD_FLEXCOMM0_CLKSEL, LPC54_SYSCON_FCLKSEL0);
|
||||
|
||||
/* Set the default I2C frequency */
|
||||
|
||||
deffreq = I2C0_DEFAULT_FREQUENCY;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@ -578,8 +854,10 @@ struct i2c_master_s *lpc54_i2cbus_initialize(int port)
|
||||
|
||||
priv = &g_i2c1_dev;
|
||||
priv->base = LPC54_FLEXCOMM1_BASE;
|
||||
priv->irq = LPC54_IRQ_FLEXCOMM1;
|
||||
priv->fclock = BOARD_FLEXCOMM1_FCLK;
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
priv->irq = LPC54_IRQ_FLEXCOMM1;
|
||||
#endif
|
||||
|
||||
/* Configure I2C pins (defined in board.h) */
|
||||
|
||||
@ -589,10 +867,6 @@ struct i2c_master_s *lpc54_i2cbus_initialize(int port)
|
||||
/* Set up the FLEXCOMM1 function clock */
|
||||
|
||||
putreg32(BOARD_FLEXCOMM1_CLKSEL, LPC54_SYSCON_FCLKSEL1);
|
||||
|
||||
/* Set the default I2C frequency */
|
||||
|
||||
deffreq = I2C1_DEFAULT_FREQUENCY;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@ -614,8 +888,10 @@ struct i2c_master_s *lpc54_i2cbus_initialize(int port)
|
||||
|
||||
priv = &g_i2c2_dev;
|
||||
priv->base = LPC54_FLEXCOMM2_BASE;
|
||||
priv->irq = LPC54_IRQ_FLEXCOMM2;
|
||||
priv->fclock = BOARD_FLEXCOMM2_FCLK;
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
priv->irq = LPC54_IRQ_FLEXCOMM2;
|
||||
#endif
|
||||
|
||||
/* Configure I2C pins (defined in board.h) */
|
||||
|
||||
@ -625,10 +901,6 @@ struct i2c_master_s *lpc54_i2cbus_initialize(int port)
|
||||
/* Set up the FLEXCOMM2 function clock */
|
||||
|
||||
putreg32(BOARD_FLEXCOMM2_CLKSEL, LPC54_SYSCON_FCLKSEL2);
|
||||
|
||||
/* Set the default I2C frequency */
|
||||
|
||||
deffreq = I2C2_DEFAULT_FREQUENCY;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@ -650,8 +922,10 @@ struct i2c_master_s *lpc54_i2cbus_initialize(int port)
|
||||
|
||||
priv = &g_i2c3_dev;
|
||||
priv->base = LPC54_FLEXCOMM3_BASE;
|
||||
priv->irq = LPC54_IRQ_FLEXCOMM3;
|
||||
priv->fclock = BOARD_FLEXCOMM3_FCLK;
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
priv->irq = LPC54_IRQ_FLEXCOMM3;
|
||||
#endif
|
||||
|
||||
/* Configure I2C pins (defined in board.h) */
|
||||
|
||||
@ -661,10 +935,6 @@ struct i2c_master_s *lpc54_i2cbus_initialize(int port)
|
||||
/* Set up the FLEXCOMM3 function clock */
|
||||
|
||||
putreg32(BOARD_FLEXCOMM3_CLKSEL, LPC54_SYSCON_FCLKSEL3);
|
||||
|
||||
/* Set the default I2C frequency */
|
||||
|
||||
deffreq = I2C3_DEFAULT_FREQUENCY;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@ -686,8 +956,10 @@ struct i2c_master_s *lpc54_i2cbus_initialize(int port)
|
||||
|
||||
priv = &g_i2c4_dev;
|
||||
priv->base = LPC54_FLEXCOMM4_BASE;
|
||||
priv->irq = LPC54_IRQ_FLEXCOMM4;
|
||||
priv->fclock = BOARD_FLEXCOMM4_FCLK;
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
priv->irq = LPC54_IRQ_FLEXCOMM4;
|
||||
#endif
|
||||
|
||||
/* Configure I2C pins (defined in board.h) */
|
||||
|
||||
@ -697,10 +969,6 @@ struct i2c_master_s *lpc54_i2cbus_initialize(int port)
|
||||
/* Set up the FLEXCOMM4 function clock */
|
||||
|
||||
putreg32(BOARD_FLEXCOMM4_CLKSEL, LPC54_SYSCON_FCLKSEL4);
|
||||
|
||||
/* Set the default I2C frequency */
|
||||
|
||||
deffreq = I2C4_DEFAULT_FREQUENCY;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@ -722,8 +990,10 @@ struct i2c_master_s *lpc54_i2cbus_initialize(int port)
|
||||
|
||||
priv = &g_i2c5_dev;
|
||||
priv->base = LPC54_FLEXCOMM5_BASE;
|
||||
priv->irq = LPC54_IRQ_FLEXCOMM5;
|
||||
priv->fclock = BOARD_FLEXCOMM5_FCLK;
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
priv->irq = LPC54_IRQ_FLEXCOMM5;
|
||||
#endif
|
||||
|
||||
/* Configure I2C pins (defined in board.h) */
|
||||
|
||||
@ -733,10 +1003,6 @@ struct i2c_master_s *lpc54_i2cbus_initialize(int port)
|
||||
/* Set up the FLEXCOMM5 function clock */
|
||||
|
||||
putreg32(BOARD_FLEXCOMM5_CLKSEL, LPC54_SYSCON_FCLKSEL5);
|
||||
|
||||
/* Set the default I2C frequency */
|
||||
|
||||
deffreq = I2C5_DEFAULT_FREQUENCY;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@ -758,8 +1024,10 @@ struct i2c_master_s *lpc54_i2cbus_initialize(int port)
|
||||
|
||||
priv = &g_i2c6_dev;
|
||||
priv->base = LPC54_FLEXCOMM6_BASE;
|
||||
priv->irq = LPC54_IRQ_FLEXCOMM6;
|
||||
priv->fclock = BOARD_FLEXCOMM6_FCLK;
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
priv->irq = LPC54_IRQ_FLEXCOMM6;
|
||||
#endif
|
||||
|
||||
/* Configure I2C pins (defined in board.h) */
|
||||
|
||||
@ -769,10 +1037,6 @@ struct i2c_master_s *lpc54_i2cbus_initialize(int port)
|
||||
/* Set up the FLEXCOMM6 function clock */
|
||||
|
||||
putreg32(BOARD_FLEXCOMM6_CLKSEL, LPC54_SYSCON_FCLKSEL6);
|
||||
|
||||
/* Set the default I2C frequency */
|
||||
|
||||
deffreq = I2C6_DEFAULT_FREQUENCY;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@ -794,8 +1058,10 @@ struct i2c_master_s *lpc54_i2cbus_initialize(int port)
|
||||
|
||||
priv = &g_i2c7_dev;
|
||||
priv->base = LPC54_FLEXCOMM7_BASE;
|
||||
priv->irq = LPC54_IRQ_FLEXCOMM7;
|
||||
priv->fclock = BOARD_FLEXCOMM7_FCLK;
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
priv->irq = LPC54_IRQ_FLEXCOMM7;
|
||||
#endif
|
||||
|
||||
/* Configure I2C pins (defined in board.h) */
|
||||
|
||||
@ -805,10 +1071,6 @@ struct i2c_master_s *lpc54_i2cbus_initialize(int port)
|
||||
/* Set up the FLEXCOMM7 function clock */
|
||||
|
||||
putreg32(BOARD_FLEXCOMM7_CLKSEL, LPC54_SYSCON_FCLKSEL7);
|
||||
|
||||
/* Set the default I2C frequency */
|
||||
|
||||
deffreq = I2C7_DEFAULT_FREQUENCY;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@ -830,8 +1092,10 @@ struct i2c_master_s *lpc54_i2cbus_initialize(int port)
|
||||
|
||||
priv = &g_i2c8_dev;
|
||||
priv->base = LPC54_FLEXCOMM8_BASE;
|
||||
priv->irq = LPC54_IRQ_FLEXCOMM8;
|
||||
priv->fclock = BOARD_FLEXCOMM8_FCLK;
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
priv->irq = LPC54_IRQ_FLEXCOMM8;
|
||||
#endif
|
||||
|
||||
/* Configure I2C pins (defined in board.h) */
|
||||
|
||||
@ -841,10 +1105,6 @@ struct i2c_master_s *lpc54_i2cbus_initialize(int port)
|
||||
/* Set up the FLEXCOMM8 function clock */
|
||||
|
||||
putreg32(BOARD_FLEXCOMM8_CLKSEL, LPC54_SYSCON_FCLKSEL8);
|
||||
|
||||
/* Set the default I2C frequency */
|
||||
|
||||
deffreq = I2C8_DEFAULT_FREQUENCY;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@ -866,8 +1126,10 @@ struct i2c_master_s *lpc54_i2cbus_initialize(int port)
|
||||
|
||||
priv = &g_i2c9_dev;
|
||||
priv->base = LPC54_FLEXCOMM9_BASE;
|
||||
priv->irq = LPC54_IRQ_FLEXCOMM9;
|
||||
priv->fclock = BOARD_FLEXCOMM9_FCLK;
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
priv->irq = LPC54_IRQ_FLEXCOMM9;
|
||||
#endif
|
||||
|
||||
/* Configure I2C pins (defined in board.h) */
|
||||
|
||||
@ -877,10 +1139,6 @@ struct i2c_master_s *lpc54_i2cbus_initialize(int port)
|
||||
/* Set up the FLEXCOMM9 function clock */
|
||||
|
||||
putreg32(BOARD_FLEXCOMM9_CLKSEL, LPC54_SYSCON_FCLKSEL9);
|
||||
|
||||
/* Set the default I2C frequency */
|
||||
|
||||
deffreq = I2C9_DEFAULT_FREQUENCY;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@ -899,15 +1157,16 @@ struct i2c_master_s *lpc54_i2cbus_initialize(int port)
|
||||
regval = lpc54_i2c_getreg(priv, LPC54_I2C_CFG_OFFSET);
|
||||
regval &= I2C_CFG_ALLENABLES;
|
||||
regval |= I2C_CFG_MSTEN;
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_CFG_OFFSET, regval)
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_CFG_OFFSET, regval);
|
||||
|
||||
/* Set the default I2C frequency */
|
||||
|
||||
lpc54_i2c_setfrequency(priv, deffreq);
|
||||
lpc54_i2c_setfrequency(priv, I2C_DEFAULT_FREQUENCY);
|
||||
|
||||
/* Initialize semaphores */
|
||||
|
||||
nxsem_init(&priv->exclsem, 0, 1);
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
nxsem_init(&priv->waitsem, 0, 0);
|
||||
|
||||
/* The waitsem semaphore is used for signaling and, hence, should not have
|
||||
@ -915,23 +1174,28 @@ struct i2c_master_s *lpc54_i2cbus_initialize(int port)
|
||||
*/
|
||||
|
||||
nxsem_setprotocol(&priv->waitsem, SEM_PRIO_NONE);
|
||||
#endif
|
||||
|
||||
/* Allocate a watchdog timer */
|
||||
|
||||
priv->timeout = wd_create();
|
||||
DEBUGASSERT(priv->timeout != 0);
|
||||
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
/* Attach Interrupt Handler */
|
||||
|
||||
irq_attach(priv->irq, lpc54_i2c_interrupt, priv);
|
||||
#endif
|
||||
|
||||
/* Disable interrupts at the I2C peripheral */
|
||||
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_INTENCLR_OFFSET, I2C_INT_ALL);
|
||||
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
/* Enable interrupts at the NVIC */
|
||||
|
||||
up_enable_irq(priv->irq);
|
||||
#endif
|
||||
return &priv->dev;
|
||||
}
|
||||
|
||||
@ -949,22 +1213,24 @@ int lpc54_i2cbus_uninitialize(FAR struct i2c_master_s * dev)
|
||||
uint32_t regval;
|
||||
|
||||
/* Disable I2C interrupts */
|
||||
#warning Missing logic
|
||||
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_INTENCLR_OFFSET, I2C_MASTER_INTS);
|
||||
|
||||
/* Disable the I2C peripheral */
|
||||
|
||||
regval = lpc54_i2c_getreg(priv, LPC54_I2C_CFG_OFFSET);
|
||||
regval &= I2C_CFG_ALLENABLES;
|
||||
regval &= ~I2C_CFG_MSTEN;
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_CFG_OFFSET, regval)
|
||||
|
||||
#warning Missing logic
|
||||
lpc54_i2c_putreg(priv, LPC54_I2C_CFG_OFFSET, regval);
|
||||
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
/* Disable the Flexcomm interface at the NVIC and detach the interrupt. */
|
||||
|
||||
up_disable_irq(priv->irq);
|
||||
irq_detach(priv->irq);
|
||||
#endif
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
#endif /* HAVE_SPI_MASTER_DEVICE */
|
||||
#endif /* HAVE_I2C_MASTER_DEVICE */
|
||||
|
@ -46,6 +46,23 @@ STATUS
|
||||
horizontal elongation.
|
||||
2017-12-14: Corrected a misconception about how the video data lines
|
||||
were configured. Now the LCD appears to be fully functional.
|
||||
2017-12-15: Added an I2C driver. This is the first step on the road
|
||||
to getting support for the capacitive touchscreen on the TFT panel.
|
||||
Not yet functional:
|
||||
|
||||
nsh> i2c dev -b 2 3 77
|
||||
0 1 2 3 4 5 6 7 8 9 a b c d e f
|
||||
00: -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
70: -- -- -- -- -- -- -- --
|
||||
|
||||
I believe that the on-board Accelerometer, Audio Codec, and touch panel controller should have been detected (but perhaps that are not properly
|
||||
powered in this configuration?)
|
||||
|
||||
Configurations
|
||||
==============
|
||||
@ -118,7 +135,7 @@ Configurations
|
||||
as NSH built-in applications.
|
||||
|
||||
NOTES:
|
||||
1, This configuration enables SDRAM to hold the LCD framebuffer and
|
||||
1. This configuration enables SDRAM to hold the LCD framebuffer and
|
||||
enables the LPC54xx LCD driver in order to support the LPCXpresso's
|
||||
TFT panel. In this configuration, the framebuffer resides in the
|
||||
the lower half megabyte of SDRAM beginning at address 0xa0000000
|
||||
@ -179,3 +196,20 @@ Configurations
|
||||
RAMTest: Pattern test: a0000000 16777216 33333333 cccccccc
|
||||
RAMTest: Address-in-address test: a0000000 16777216
|
||||
nsh>
|
||||
|
||||
3. I2C2 is enabled (will be used with the capacitive touchscreen). In
|
||||
order to verify I2C functionality, the I2C tool at apps/system/i2ctool
|
||||
is enabled in this configuration.
|
||||
|
||||
nsh> i2c bus
|
||||
BUS EXISTS?
|
||||
Bus 0: NO
|
||||
Bus 1: NO
|
||||
Bus 2: YES
|
||||
Bus 3: NO
|
||||
Bus 4: NO
|
||||
Bus 5: NO
|
||||
Bus 6: NO
|
||||
Bus 7: NO
|
||||
Bus 8: NO
|
||||
Bus 9: NO
|
||||
|
@ -173,11 +173,16 @@
|
||||
# define BOARD_SYSTICK_CLOCK (BOARD_AHB_FREQUENCY / BOARD_SYSTICKCLKDIV)
|
||||
#endif
|
||||
|
||||
/* Flexcomm0: REVIST */
|
||||
/* Flexcomm0: USART0 (REVIST) */
|
||||
|
||||
#define BOARD_FLEXCOMM0_CLKSEL SYSCON_FCLKSEL_FRO12M
|
||||
#define BOARD_FLEXCOMM0_FCLK LPC54_FRO_12MHZ
|
||||
|
||||
/* Flexcomm2: I2C2 (REVIST) */
|
||||
|
||||
#define BOARD_FLEXCOMM2_CLKSEL SYSCON_FCLKSEL_FRO12M
|
||||
#define BOARD_FLEXCOMM2_FCLK LPC54_FRO_12MHZ
|
||||
|
||||
/* EMC */
|
||||
|
||||
#ifdef BOARD_220MHz
|
||||
@ -273,6 +278,41 @@
|
||||
#define GPIO_USART0_RXD (GPIO_FC0_RXD_SDA_MOSI_2 | GPIO_FILTER_OFF)
|
||||
#define GPIO_USART0_TXD (GPIO_FC0_TXD_SCL_MISO_2 | GPIO_FILTER_OFF)
|
||||
|
||||
/* Flexomm2/I2C
|
||||
*
|
||||
* For I2C:
|
||||
* Type A & D pins need:
|
||||
* GPIO_OPENDRAIN + GPIO_FILTER_OFF
|
||||
* Type I pins need for Standard mode I2C need:
|
||||
* GPIO_FILTER_OFF + GPIO_I2C_FILTER_ON + GPIO_I2CDRIVE_LOW
|
||||
* Type I pins need for fast speed I2C need:
|
||||
* GPIO_FILTER_OFF + GPIO_I2C_FILTER_ON or OFF +
|
||||
* GPIO_I2CDRIVE_LOW or HIGH
|
||||
* Type I pins need for high speed I2C need:
|
||||
* GPIO_FILTER_OFF + GPIO_I2C_FILTER_OFF + GPIO_I2CDRIVE_HIGH
|
||||
*
|
||||
* The touchscreen controller is on I2C2: SCL P3.24, SDA P3.23. These are
|
||||
* both Type D/I pins.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_LPC54_I2C_FAST)
|
||||
# define _I2CFILTER GPIO_I2C_FILTER_OFF
|
||||
# define _I2CDRIVE GPIO_I2CDRIVE_HIGH
|
||||
#elif defined(CONFIG_LPC54_I2C_HIGH)
|
||||
# define _I2CFILTER GPIO_I2C_FILTER_OFF
|
||||
# define _I2CDRIVE GPIO_I2CDRIVE_HIGH
|
||||
#else
|
||||
# define _I2CFILTER GPIO_I2C_FILTER_ON
|
||||
# define _I2CDRIVE GPIO_I2CDRIVE_LOW
|
||||
#endif
|
||||
|
||||
#define GPIO_I2C2_SCL (GPIO_FC2_RTS_SCL_SSEL1_2 | \
|
||||
GPIO_FILTER_OFF | _I2CFILTER | \
|
||||
_I2CDRIVE)
|
||||
#define GPIO_I2C2_SDA (GPIO_FC2_CTS_SDA_SSEL0_2 | \
|
||||
GPIO_FILTER_OFF | _I2CFILTER | \
|
||||
_I2CDRIVE)
|
||||
|
||||
/* LCD
|
||||
*
|
||||
* There are no alternatives for LCD pins except for the VD0-VD3 pins.
|
||||
|
@ -13,8 +13,11 @@ CONFIG_FAT_LCNAMES=y
|
||||
CONFIG_FAT_LFN=y
|
||||
CONFIG_FS_FAT=y
|
||||
CONFIG_FS_PROCFS=y
|
||||
CONFIG_I2C=y
|
||||
CONFIG_I2CTOOL_MAXBUS=9
|
||||
CONFIG_LPC54_EMC_DYNAMIC_CS0=y
|
||||
CONFIG_LPC54_EMC=y
|
||||
CONFIG_LPC54_I2C2_MASTER=y
|
||||
CONFIG_LPC54_USART0=y
|
||||
CONFIG_MAX_TASKS=16
|
||||
CONFIG_MAX_WDOGPARMS=2
|
||||
@ -38,6 +41,7 @@ CONFIG_SDCLONE_DISABLE=y
|
||||
CONFIG_START_DAY=2
|
||||
CONFIG_START_MONTH=12
|
||||
CONFIG_SYMTAB_ORDEREDBYNAME=y
|
||||
CONFIG_SYSTEM_I2CTOOL=y
|
||||
CONFIG_SYSTEM_RAMTEST=y
|
||||
CONFIG_TASK_NAME_SIZE=0
|
||||
CONFIG_USART0_SERIAL_CONSOLE=y
|
||||
|
@ -44,9 +44,94 @@
|
||||
#include <syslog.h>
|
||||
|
||||
#include <nuttx/video/fb.h>
|
||||
#include <nuttx/i2c/i2c_master.h>
|
||||
|
||||
#include "lpc54_config.h"
|
||||
#include "lpc54_i2c_master.h"
|
||||
#include "lpcxpresso-lpc54628.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lpc54_i2c_register
|
||||
*
|
||||
* Description:
|
||||
* Register one I2C drivers for the I2C tool.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_I2CTOOL
|
||||
static void lpc54_i2c_register(int bus)
|
||||
{
|
||||
FAR struct i2c_master_s *i2c;
|
||||
int ret;
|
||||
|
||||
i2c = lpc54_i2cbus_initialize(bus);
|
||||
if (i2c == NULL)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: Failed to get I2C%d interface\n", bus);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = i2c_register(i2c, bus);
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: Failed to register I2C%d driver: %d\n",
|
||||
bus, ret);
|
||||
lpc54_i2cbus_uninitialize(i2c);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lpc54_i2ctool
|
||||
*
|
||||
* Description:
|
||||
* Register I2C drivers for the I2C tool.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_I2CTOOL
|
||||
static void lpc54_i2ctool(void)
|
||||
{
|
||||
#ifdef CONFIG_LPC54_I2C0_MASTER
|
||||
lpc54_i2c_register(0);
|
||||
#endif
|
||||
#ifdef CONFIG_LPC54_I2C1_MASTER
|
||||
lpc54_i2c_register(1);
|
||||
#endif
|
||||
#ifdef CONFIG_LPC54_I2C2_MASTER
|
||||
lpc54_i2c_register(2);
|
||||
#endif
|
||||
#ifdef CONFIG_LPC54_I2C3_MASTER
|
||||
lpc54_i2c_register(3);
|
||||
#endif
|
||||
#ifdef CONFIG_LPC54_I2C4_MASTER
|
||||
lpc54_i2c_register(4);
|
||||
#endif
|
||||
#ifdef CONFIG_LPC54_I2C5_MASTER
|
||||
lpc54_i2c_register(5);
|
||||
#endif
|
||||
#ifdef CONFIG_LPC54_I2C6_MASTER
|
||||
lpc54_i2c_register(6);
|
||||
#endif
|
||||
#ifdef CONFIG_LPC54_I2C7_MASTER
|
||||
lpc54_i2c_register(7);
|
||||
#endif
|
||||
#ifdef CONFIG_LPC54_I2C8_MASTER
|
||||
lpc54_i2c_register(8);
|
||||
#endif
|
||||
#ifdef CONFIG_LPC54_I2C9_MASTER
|
||||
lpc54_i2c_register(9);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
# define lpc54_i2ctool()
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@ -79,6 +164,10 @@ int lpc54_bringup(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Register I2C drivers on behalf of the I2C tool */
|
||||
|
||||
lpc54_i2ctool();
|
||||
|
||||
#ifdef CONFIG_VIDEO_FB
|
||||
/* Initialize and register the framebuffer driver */
|
||||
|
||||
|
@ -43,10 +43,21 @@
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/compiler.h>
|
||||
|
||||
#include "lpc54_config.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define HAVE_I2CTOOL 1
|
||||
|
||||
/* Do we need to register I2C drivers on behalf of the I2C tool? */
|
||||
|
||||
#if !defined(CONFIG_SYSTEM_I2CTOOL) || !defined(CONFIG_I2C_DRIVER) || \
|
||||
!defined(HAVE_I2C_MASTER_DEVICE)
|
||||
# undef HAVE_I2CTOOL
|
||||
#endif
|
||||
|
||||
/* LED definitions **********************************************************/
|
||||
/* The LPCXpress-LPC54628 has three user LEDs: D9, D11, and D12. These
|
||||
* LEDs are for application use. They are illuminated when the driving
|
||||
|
Loading…
Reference in New Issue
Block a user