Tiva I2C: Driver is code complete but untested
This commit is contained in:
parent
03e1ecd6aa
commit
58d0e169c7
@ -543,7 +543,7 @@
|
|||||||
|
|
||||||
/* I2C Master Interrupt Mask (I2CM_IMR) */
|
/* I2C Master Interrupt Mask (I2CM_IMR) */
|
||||||
|
|
||||||
#define I2CM_IMR_IM (1 << 0) /* Bit 0: Interrupt Mask */
|
#define I2CM_IMR_MIM (1 << 0) /* Bit 0: Master Interrupt Mask */
|
||||||
|
|
||||||
#if defined(CONFIG_ARCH_CHIP_TM4C123GH6ZRB) || \
|
#if defined(CONFIG_ARCH_CHIP_TM4C123GH6ZRB) || \
|
||||||
defined(CONFIG_ARCH_CHIP_TM4C1294NCPDT)
|
defined(CONFIG_ARCH_CHIP_TM4C1294NCPDT)
|
||||||
@ -565,68 +565,68 @@
|
|||||||
|
|
||||||
/* I2C Master Raw Interrupt Status (I2CM_RIS) */
|
/* I2C Master Raw Interrupt Status (I2CM_RIS) */
|
||||||
|
|
||||||
#define I2CM_RIS_RIS (1 << 0) /* Bit 0: Raw Interrupt Status */
|
#define I2CM_RIS_MRIS (1 << 0) /* Bit 0: Master Raw Interrupt Status */
|
||||||
|
|
||||||
#if defined(CONFIG_ARCH_CHIP_TM4C123GH6ZRB) || \
|
#if defined(CONFIG_ARCH_CHIP_TM4C123GH6ZRB) || \
|
||||||
defined(CONFIG_ARCH_CHIP_TM4C1294NCPDT)
|
defined(CONFIG_ARCH_CHIP_TM4C1294NCPDT)
|
||||||
# define I2CM_RIS_CLKRIS (1 << 1) /* Bit 1: Clock Timeout Raw Interrupt Status */
|
# define I2CM_RIS_CLKRIS (1 << 1) /* Bit 1: Clock Timeout Raw Interrupt Status */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_ARCH_CHIP_TM4C1294NCPDT)
|
#if defined(CONFIG_ARCH_CHIP_TM4C1294NCPDT)
|
||||||
# define I2CM_RIS_DMARXRIS (1 << 2) /* Bit 2: Receive DMA Interrupt Mask */
|
# define I2CM_RIS_DMARXRIS (1 << 2) /* Bit 2: Receive DMA Interrupt Status */
|
||||||
# define I2CM_RIS_DMATXRIS (1 << 3) /* Bit 3: Transmit DMA Interrupt Mask */
|
# define I2CM_RIS_DMATXRIS (1 << 3) /* Bit 3: Transmit DMA Interrupt Status */
|
||||||
# define I2CM_RIS_NACKRIS (1 << 4) /* Bit 4: Address/Data NACK Interrupt Mask */
|
# define I2CM_RIS_NACKRIS (1 << 4) /* Bit 4: Address/Data NACK Interrupt Status */
|
||||||
# define I2CM_RIS_STARTRIS (1 << 5) /* Bit 5: START Detection Interrupt Mask */
|
# define I2CM_RIS_STARTRIS (1 << 5) /* Bit 5: START Detection Interrupt Status */
|
||||||
# define I2CM_RIS_STOPRIS (1 << 6) /* Bit 6: STOP Detection Interrupt Mask */
|
# define I2CM_RIS_STOPRIS (1 << 6) /* Bit 6: STOP Detection Interrupt Status */
|
||||||
# define I2CM_RIS_ARBLOSTRIS (1 << 7) /* Bit 7: Arbitration Lost Interrupt Mask */
|
# define I2CM_RIS_ARBLOSTRIS (1 << 7) /* Bit 7: Arbitration Lost Interrupt Status */
|
||||||
# define I2CM_RIS_TXRIS (1 << 8) /* Bit 8: Transmit FIFO Request Interrupt Mask */
|
# define I2CM_RIS_TXRIS (1 << 8) /* Bit 8: Transmit FIFO Request Interrupt Status */
|
||||||
# define I2CM_RIS_RXRIS (1 << 9) /* Bit 9: Receive FIFO Request Interrupt Mask */
|
# define I2CM_RIS_RXRIS (1 << 9) /* Bit 9: Receive FIFO Request Interrupt Status */
|
||||||
# define I2CM_RIS_TXFERIS (1 << 10) /* Bit 10: Transmit FIFO Empty Interrupt Mask */
|
# define I2CM_RIS_TXFERIS (1 << 10) /* Bit 10: Transmit FIFO Empty Interrupt Status */
|
||||||
# define I2CM_RIS_RXFFRIS (1 << 11) /* Bit 11: Receive FIFO Full Interrupt Mask */
|
# define I2CM_RIS_RXFFRIS (1 << 11) /* Bit 11: Receive FIFO Full Interrupt Status */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* I2C Master Masked Interrupt Status (I2CM_MIS) */
|
/* I2C Master Masked Interrupt Status (I2CM_MIS) */
|
||||||
|
|
||||||
#define I2CM_MIS_MIS (1 << 0) /* Bit 0: Masked Interrupt Status */
|
#define I2CM_MIS_MMIS (1 << 0) /* Bit 0: Maseter Masked Interrupt Status */
|
||||||
|
|
||||||
#if defined(CONFIG_ARCH_CHIP_TM4C123GH6ZRB) || \
|
#if defined(CONFIG_ARCH_CHIP_TM4C123GH6ZRB) || \
|
||||||
defined(CONFIG_ARCH_CHIP_TM4C1294NCPDT)
|
defined(CONFIG_ARCH_CHIP_TM4C1294NCPDT)
|
||||||
# define I2CM_MIS_CLKMIS (1 << 1) /* Bit 1: Clock Timeout Masked Interrupt Status */
|
# define I2CM_MIS_CLKMIS (1 << 1) /* Bit 1: Clock Timeout Masked Interrupt Status */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_ARCH_CHIP_TM4C1294NCPDT)
|
#if defined(CONFIG_ARCH_CHIP_TM4C1294NCPDT)
|
||||||
# define I2CM_MIS_DMARXMIS (1 << 2) /* Bit 2: Receive DMA Interrupt Mask */
|
# define I2CM_MIS_DMARXMIS (1 << 2) /* Bit 2: Receive DMA Interrupt Status */
|
||||||
# define I2CM_MIS_DMATXMIS (1 << 3) /* Bit 3: Transmit DMA Interrupt Mask */
|
# define I2CM_MIS_DMATXMIS (1 << 3) /* Bit 3: Transmit DMA Interrupt Status */
|
||||||
# define I2CM_MIS_NACKMIS (1 << 4) /* Bit 4: Address/Data NACK Interrupt Mask */
|
# define I2CM_MIS_NACKMIS (1 << 4) /* Bit 4: Address/Data NACK Interrupt Status */
|
||||||
# define I2CM_MIS_STARTMIS (1 << 5) /* Bit 5: START Detection Interrupt Mask */
|
# define I2CM_MIS_STARTMIS (1 << 5) /* Bit 5: START Detection Interrupt Status */
|
||||||
# define I2CM_MIS_STOPMIS (1 << 6) /* Bit 6: STOP Detection Interrupt Mask */
|
# define I2CM_MIS_STOPMIS (1 << 6) /* Bit 6: STOP Detection Interrupt Status */
|
||||||
# define I2CM_MIS_ARBLOSTMIS (1 << 7) /* Bit 7: Arbitration Lost Interrupt Mask */
|
# define I2CM_MIS_ARBLOSTMIS (1 << 7) /* Bit 7: Arbitration Lost Interrupt Status */
|
||||||
# define I2CM_MIS_TXMIS (1 << 8) /* Bit 8: Transmit FIFO Request Interrupt Mask */
|
# define I2CM_MIS_TXMIS (1 << 8) /* Bit 8: Transmit FIFO Request Interrupt Status */
|
||||||
# define I2CM_MIS_RXMIS (1 << 9) /* Bit 9: Receive FIFO Request Interrupt Mask */
|
# define I2CM_MIS_RXMIS (1 << 9) /* Bit 9: Receive FIFO Request Interrupt Status */
|
||||||
# define I2CM_MIS_TXFEMIS (1 << 10) /* Bit 10: Transmit FIFO Empty Interrupt Mask */
|
# define I2CM_MIS_TXFEMIS (1 << 10) /* Bit 10: Transmit FIFO Empty Interrupt Status */
|
||||||
# define I2CM_MIS_RXFFMIS (1 << 11) /* Bit 11: Receive FIFO Full Interrupt Mask */
|
# define I2CM_MIS_RXFFMIS (1 << 11) /* Bit 11: Receive FIFO Full Interrupt Status */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* I2C Master Masked Interrupt Status (I2CM_ICR) */
|
/* I2C Master Masked Interrupt Status (I2CM_ICR) */
|
||||||
|
|
||||||
#define I2CM_ICR_IC (1 << 0) /* Bit 0: Masked Interrupt Status */
|
#define I2CM_ICR_MIC (1 << 0) /* Bit 0: Master Masked Interrupt Clear */
|
||||||
|
|
||||||
#if defined(CONFIG_ARCH_CHIP_TM4C123GH6ZRB) || \
|
#if defined(CONFIG_ARCH_CHIP_TM4C123GH6ZRB) || \
|
||||||
defined(CONFIG_ARCH_CHIP_TM4C1294NCPDT)
|
defined(CONFIG_ARCH_CHIP_TM4C1294NCPDT)
|
||||||
# define I2CM_ICR_CLKIC (1 << 1) /* Bit 1: Clock Timeout Interrupt Clear */
|
# define I2CM_ICR_CLKC (1 << 1) /* Bit 1: Clock Timeout Interrupt Clear */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_ARCH_CHIP_TM4C1294NCPDT)
|
#if defined(CONFIG_ARCH_CHIP_TM4C1294NCPDT)
|
||||||
# define I2CM_ICR_DMARXIC (1 << 2) /* Bit 2: Receive DMA Interrupt Mask */
|
# define I2CM_ICR_DMARXIC (1 << 2) /* Bit 2: Receive DMA Interrupt Clear */
|
||||||
# define I2CM_ICR_DMATXIC (1 << 3) /* Bit 3: Transmit DMA Interrupt Mask */
|
# define I2CM_ICR_DMATXIC (1 << 3) /* Bit 3: Transmit DMA Interrupt Clear */
|
||||||
# define I2CM_ICR_NACKIC (1 << 4) /* Bit 4: Address/Data NACK Interrupt Mask */
|
# define I2CM_ICR_NACKIC (1 << 4) /* Bit 4: Address/Data NACK Interrupt Clear */
|
||||||
# define I2CM_ICR_STARTIC (1 << 5) /* Bit 5: START Detection Interrupt Mask */
|
# define I2CM_ICR_STARTIC (1 << 5) /* Bit 5: START Detection Interrupt Clear */
|
||||||
# define I2CM_ICR_STOPIC (1 << 6) /* Bit 6: STOP Detection Interrupt Mask */
|
# define I2CM_ICR_STOPIC (1 << 6) /* Bit 6: STOP Detection Interrupt Clear */
|
||||||
# define I2CM_ICR_ARBLOSTIC (1 << 7) /* Bit 7: Arbitration Lost Interrupt Mask */
|
# define I2CM_ICR_ARBLOSTIC (1 << 7) /* Bit 7: Arbitration Lost Interrupt Clear */
|
||||||
# define I2CM_ICR_TXIC (1 << 8) /* Bit 8: Transmit FIFO Request Interrupt Mask */
|
# define I2CM_ICR_TXIC (1 << 8) /* Bit 8: Transmit FIFO Request Interrupt Clear */
|
||||||
# define I2CM_ICR_RXIC (1 << 9) /* Bit 9: Receive FIFO Request Interrupt Mask */
|
# define I2CM_ICR_RXIC (1 << 9) /* Bit 9: Receive FIFO Request Interrupt Clear */
|
||||||
# define I2CM_ICR_TXFEIC (1 << 10) /* Bit 10: Transmit FIFO Empty Interrupt Mask */
|
# define I2CM_ICR_TXFEIC (1 << 10) /* Bit 10: Transmit FIFO Empty Interrupt Mask */
|
||||||
# define I2CM_ICR_RXFFIC (1 << 11) /* Bit 11: Receive FIFO Full Interrupt Mask */
|
# define I2CM_ICR_RXFFIC (1 << 11) /* Bit 11: Receive FIFO Full Interrupt Clear */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* I2C Master Configuration (I2CM_CR) */
|
/* I2C Master Configuration (I2CM_CR) */
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Derives in spirit if nothing more from the NuttX STM32 I2C driver which has:
|
* The basic structure of this driver derives in spirit (if nothing more) from the
|
||||||
|
* NuttX STM32 I2C driver which has:
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011 Uros Platise. All rights reserved.
|
* Copyright (C) 2011 Uros Platise. All rights reserved.
|
||||||
* Author: Uros Platise <uros.platise@isotel.eu>
|
* Author: Uros Platise <uros.platise@isotel.eu>
|
||||||
@ -147,8 +148,9 @@
|
|||||||
enum tiva_intstate_e
|
enum tiva_intstate_e
|
||||||
{
|
{
|
||||||
INTSTATE_IDLE = 0, /* No I2C activity */
|
INTSTATE_IDLE = 0, /* No I2C activity */
|
||||||
INTSTATE_WAITING, /* Waiting for completion of interrupt activity */
|
INTSTATE_ADDRESS, /* Address sent, waiting for completion */
|
||||||
INTSTATE_DONE, /* Interrupt activity complete */
|
INTSTATE_XFRWAIT, /* Waiting for data transfer to complete */
|
||||||
|
INTSTATE_DONE /* Interrupt activity complete */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Trace events */
|
/* Trace events */
|
||||||
@ -156,16 +158,15 @@ enum tiva_intstate_e
|
|||||||
enum tiva_trace_e
|
enum tiva_trace_e
|
||||||
{
|
{
|
||||||
I2CEVENT_NONE = 0, /* No events have occurred with this status */
|
I2CEVENT_NONE = 0, /* No events have occurred with this status */
|
||||||
I2CEVENT_SENDADDR, /* Start/Master bit set and address sent, param = msgc */
|
I2CEVENT_SENDADDRESS, /* Address sent, param = address */
|
||||||
|
I2CEVENT_ERROR, /* Error occurred, param = MCS */
|
||||||
|
I2CEVENT_BUSY, /* Still busy, param = MCS */
|
||||||
|
I2CEVENT_XFRDONE, /* Transfer completed without error, param = dcnt */
|
||||||
|
I2CEVENT_RECVSETUP, /* Setup to receive the next byte, param = dcnt */
|
||||||
I2CEVENT_SENDBYTE, /* Send byte, param = dcnt */
|
I2CEVENT_SENDBYTE, /* Send byte, param = dcnt */
|
||||||
I2CEVENT_ITBUFEN, /* Enable buffer interrupts, param = 0 */
|
I2CEVENT_SPURIOUS, /* Spurious interrupt received, param = msgc */
|
||||||
I2CEVENT_RCVBYTE, /* Read more dta, param = dcnt */
|
I2CEVENT_NEXTMSG, /* Starting next message, param = msgc */
|
||||||
I2CEVENT_REITBUFEN, /* Re-enable buffer interrupts, param = 0 */
|
I2CEVENT_DONE /* All messages transferred, param = intstate */
|
||||||
I2CEVENT_DISITBUFEN, /* Disable buffer interrupts, param = 0 */
|
|
||||||
I2CEVENT_BTFNOSTART, /* BTF on last byte with no restart, param = msgc */
|
|
||||||
I2CEVENT_BTFRESTART, /* Last byte sent, re-starting, param = msgc */
|
|
||||||
I2CEVENT_BTFSTOP, /* Last byte sten, send stop, param = 0 */
|
|
||||||
I2CEVENT_ERROR /* Error occurred, param = 0 */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Trace data */
|
/* Trace data */
|
||||||
@ -213,6 +214,7 @@ struct tiva_i2c_priv_s
|
|||||||
uint8_t *ptr; /* Current message buffer */
|
uint8_t *ptr; /* Current message buffer */
|
||||||
int dcnt; /* Current message length */
|
int dcnt; /* Current message length */
|
||||||
uint16_t flags; /* Current message flags */
|
uint16_t flags; /* Current message flags */
|
||||||
|
uint32_t status; /* MCS register at the end of the transfer */
|
||||||
|
|
||||||
/* I2C trace support */
|
/* I2C trace support */
|
||||||
|
|
||||||
@ -234,7 +236,7 @@ struct tiva_i2c_inst_s
|
|||||||
struct tiva_i2c_priv_s *priv; /* Common driver private data structure */
|
struct tiva_i2c_priv_s *priv; /* Common driver private data structure */
|
||||||
|
|
||||||
uint32_t frequency; /* Frequency used in this instantiation */
|
uint32_t frequency; /* Frequency used in this instantiation */
|
||||||
int address; /* Address used in this instantiation */
|
uint16_t address; /* Address used in this instantiation */
|
||||||
uint16_t flags; /* Flags used in this instantiation */
|
uint16_t flags; /* Flags used in this instantiation */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -256,7 +258,6 @@ static useconds_t tiva_i2c_tousecs(int msgc, struct i2c_msg_s *msgs);
|
|||||||
#endif /* CONFIG_TIVA_I2C_DYNTIMEO */
|
#endif /* CONFIG_TIVA_I2C_DYNTIMEO */
|
||||||
|
|
||||||
static inline int tiva_i2c_sem_waitdone(struct tiva_i2c_priv_s *priv);
|
static inline int tiva_i2c_sem_waitdone(struct tiva_i2c_priv_s *priv);
|
||||||
static inline void tiva_i2c_sem_waitstop(struct tiva_i2c_priv_s *priv);
|
|
||||||
static inline void tiva_i2c_sem_post(struct i2c_dev_s *dev);
|
static inline void tiva_i2c_sem_post(struct i2c_dev_s *dev);
|
||||||
static inline void tiva_i2c_sem_init(struct i2c_dev_s *dev);
|
static inline void tiva_i2c_sem_init(struct i2c_dev_s *dev);
|
||||||
static inline void tiva_i2c_sem_destroy(struct i2c_dev_s *dev);
|
static inline void tiva_i2c_sem_destroy(struct i2c_dev_s *dev);
|
||||||
@ -269,10 +270,8 @@ static void tiva_i2c_traceevent(struct tiva_i2c_priv_s *priv,
|
|||||||
static void tiva_i2c_tracedump(struct tiva_i2c_priv_s *priv);
|
static void tiva_i2c_tracedump(struct tiva_i2c_priv_s *priv);
|
||||||
#endif /* CONFIG_I2C_TRACE */
|
#endif /* CONFIG_I2C_TRACE */
|
||||||
|
|
||||||
static inline void tiva_i2c_sendstart(struct tiva_i2c_priv_s *priv);
|
static void tiva_i2c_sendaddress(struct tiva_i2c_priv_s *priv);
|
||||||
static inline void tiva_i2c_clrstart(struct tiva_i2c_priv_s *priv);
|
static void tiva_i2c_nextxfr(struct tiva_i2c_priv_s *priv);
|
||||||
static inline void tiva_i2c_sendstop(struct tiva_i2c_priv_s *priv);
|
|
||||||
|
|
||||||
static int tiva_i2c_interrupt(struct tiva_i2c_priv_s * priv, uint32_t status);
|
static int tiva_i2c_interrupt(struct tiva_i2c_priv_s * priv, uint32_t status);
|
||||||
|
|
||||||
#ifndef CONFIG_I2C_POLLED
|
#ifndef CONFIG_I2C_POLLED
|
||||||
@ -565,24 +564,22 @@ static inline int tiva_i2c_sem_waitdone(struct tiva_i2c_priv_s *priv)
|
|||||||
{
|
{
|
||||||
struct timespec abstime;
|
struct timespec abstime;
|
||||||
irqstate_t flags;
|
irqstate_t flags;
|
||||||
uint32_t regval;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
flags = irqsave();
|
flags = irqsave();
|
||||||
|
|
||||||
/* Enable the master interrupt. The I2C master module generates an interrupt when
|
/* Enable the master interrupt. The I2C master module generates an interrupt when
|
||||||
* a transaction completes (either transmit or receive), when arbitration is lost,
|
* a transaction completes (either transmit or receive), when arbitration is lost,
|
||||||
* or when an error occurs during a transaction.
|
* or when an error occurs during a transaction.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
tiva_i2c_putreg(priv, TIVA_I2CM_IMR_OFFSET, I2CM_IMR_IM);
|
tiva_i2c_putreg(priv, TIVA_I2CM_IMR_OFFSET, I2CM_IMR_MIM);
|
||||||
|
|
||||||
/* Signal the interrupt handler that we are waiting. NOTE: Interrupts
|
/* Signal the interrupt handler that we are waiting. NOTE: Interrupts
|
||||||
* are currently disabled but will be temporarily re-enabled below when
|
* are currently disabled but will be temporarily re-enabled below when
|
||||||
* sem_timedwait() sleeps.
|
* sem_timedwait() sleeps.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
priv->intstate = INTSTATE_WAITING;
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
/* Get the current time */
|
/* Get the current time */
|
||||||
@ -665,7 +662,6 @@ static inline int tiva_i2c_sem_waitdone(struct tiva_i2c_priv_s *priv)
|
|||||||
* sem_timedwait() sleeps.
|
* sem_timedwait() sleeps.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
priv->intstate = INTSTATE_WAITING;
|
|
||||||
start = clock_systimer();
|
start = clock_systimer();
|
||||||
|
|
||||||
do
|
do
|
||||||
@ -700,60 +696,6 @@ static inline int tiva_i2c_sem_waitdone(struct tiva_i2c_priv_s *priv)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/************************************************************************************
|
|
||||||
* Name: tiva_i2c_sem_waitstop
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Wait for a STOP to complete
|
|
||||||
*
|
|
||||||
************************************************************************************/
|
|
||||||
|
|
||||||
static inline void tiva_i2c_sem_waitstop(struct tiva_i2c_priv_s *priv)
|
|
||||||
{
|
|
||||||
uint32_t start;
|
|
||||||
uint32_t elapsed;
|
|
||||||
uint32_t timeout;
|
|
||||||
|
|
||||||
/* Select a timeout */
|
|
||||||
|
|
||||||
#ifdef CONFIG_TIVA_I2C_DYNTIMEO
|
|
||||||
timeout = USEC2TICK(CONFIG_TIVA_I2C_DYNTIMEO_STARTSTOP);
|
|
||||||
#else
|
|
||||||
timeout = CONFIG_TIVA_I2CTIMEOTICKS;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Wait as stop might still be in progress; but stop might also
|
|
||||||
* be set because of a timeout error: "The [STOP] bit is set and
|
|
||||||
* cleared by software, cleared by hardware when a Stop condition is
|
|
||||||
* detected, set by hardware when a timeout error is detected."
|
|
||||||
*/
|
|
||||||
|
|
||||||
start = clock_systimer();
|
|
||||||
do
|
|
||||||
{
|
|
||||||
/* Check for STOP condition */
|
|
||||||
#warning Missing logic
|
|
||||||
|
|
||||||
/* Check for timeout error */
|
|
||||||
#warning Missing logic
|
|
||||||
|
|
||||||
|
|
||||||
/* Calculate the elapsed time */
|
|
||||||
|
|
||||||
elapsed = clock_systimer() - start;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Loop until the stop is complete or a timeout occurs. */
|
|
||||||
|
|
||||||
while (elapsed < timeout);
|
|
||||||
|
|
||||||
/* If we get here then a timeout occurred with the STOP condition
|
|
||||||
* still pending.
|
|
||||||
*/
|
|
||||||
|
|
||||||
i2cvdbg("Timeout with CR1: %04x SR1: %04x\n", cr1, sr1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: tiva_i2c_sem_post
|
* Name: tiva_i2c_sem_post
|
||||||
*
|
*
|
||||||
@ -920,43 +862,115 @@ static void tiva_i2c_tracedump(struct tiva_i2c_priv_s *priv)
|
|||||||
#endif /* CONFIG_I2C_TRACE */
|
#endif /* CONFIG_I2C_TRACE */
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: tiva_i2c_sendstart
|
* Name: tiva_i2c_sendaddress
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Send the START conditions/force Master mode
|
* Send the START conditions/force Master mode
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
static inline void tiva_i2c_sendstart(struct tiva_i2c_priv_s *priv)
|
static void tiva_i2c_sendaddress(struct tiva_i2c_priv_s *priv)
|
||||||
{
|
{
|
||||||
/* Disable ACK on receive by default and generate START */
|
struct i2c_msg_s *msg;
|
||||||
#warning Missing logic
|
uint32_t regval;
|
||||||
|
|
||||||
|
DEBUGASSERT(priv && priv->msgc > 0);
|
||||||
|
|
||||||
|
/* Check for new trace setup, post the SENADDRESS event */
|
||||||
|
|
||||||
|
tiva_i2c_tracenew(priv, 0);
|
||||||
|
|
||||||
|
/* Get run-time data for the next message */
|
||||||
|
|
||||||
|
msg = priv->msgv;
|
||||||
|
priv->ptr = msg->buffer;
|
||||||
|
priv->dcnt = msg->length;
|
||||||
|
priv->flags = msg->flags;
|
||||||
|
|
||||||
|
/* Set the Master Slave Address */
|
||||||
|
|
||||||
|
regval = (uint32_t)msg->addr << I2CM_SA_SA_SHIFT;
|
||||||
|
if ((msg->flags & I2C_M_READ) != 0)
|
||||||
|
{
|
||||||
|
regval |= I2CM_SA_RS;
|
||||||
|
}
|
||||||
|
|
||||||
|
tiva_i2c_putreg(priv, TIVA_I2CM_SA_OFFSET, regval);
|
||||||
|
|
||||||
|
/* Write the command to the control register */
|
||||||
|
|
||||||
|
regval = I2CM_CS_RUN;
|
||||||
|
if ((msg->flags & I2C_M_NORESTART) == 0)
|
||||||
|
{
|
||||||
|
regval |= I2CM_CS_START;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->dcnt < 1)
|
||||||
|
{
|
||||||
|
regval |= I2CM_CS_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
tiva_i2c_putreg(priv, TIVA_I2CM_CS_OFFSET, regval);
|
||||||
|
|
||||||
|
tiva_i2c_traceevent(priv, I2CEVENT_SENDADDRESS, msg->addr);
|
||||||
|
priv->intstate = INTSTATE_ADDRESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: tiva_i2c_clrstart
|
* Name: tiva_i2c_nextxfr
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Clear the STOP, START or PEC condition on certain error recovery steps.
|
* Common Interrupt Service Routine
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
static inline void tiva_i2c_clrstart(struct tiva_i2c_priv_s *priv)
|
static void tiva_i2c_nextxfr(struct tiva_i2c_priv_s *priv)
|
||||||
{
|
{
|
||||||
#warning Missing logic
|
uint32_t cmd;
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************************
|
/* Set up the basic command. The STOP bit should be set on the last transfer
|
||||||
* Name: tiva_i2c_sendstop
|
* UNLESS this there is a repeated start.
|
||||||
*
|
*/
|
||||||
* Description:
|
|
||||||
* Send the STOP conditions
|
|
||||||
*
|
|
||||||
************************************************************************************/
|
|
||||||
|
|
||||||
static inline void tiva_i2c_sendstop(struct tiva_i2c_priv_s *priv)
|
cmd = I2CM_CS_RUN;
|
||||||
{
|
if (priv->msgc < 2 && priv->dcnt < 2)
|
||||||
#warning Missing logic
|
{
|
||||||
|
/* This is the last byte of the last message... add the STOP bit */
|
||||||
|
|
||||||
|
cmd |= I2CM_CS_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up to transfer the next byte. Are we sending or receiving? */
|
||||||
|
|
||||||
|
if ((priv->flags & I2C_M_READ) != 0)
|
||||||
|
{
|
||||||
|
/* We are receiving data. Write the command to the control register to
|
||||||
|
* receive the next byte.
|
||||||
|
*/
|
||||||
|
|
||||||
|
cmd |= I2CM_CS_ACK;
|
||||||
|
|
||||||
|
tiva_i2c_putreg(priv, TIVA_I2CM_CS_OFFSET, cmd);
|
||||||
|
tiva_i2c_traceevent(priv, I2CEVENT_RECVSETUP, priv->dcnt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint32_t dr;
|
||||||
|
|
||||||
|
/* We are sending data. Write the data to be sent to the DR register. */
|
||||||
|
|
||||||
|
dr = (uint32_t)*priv->ptr++;
|
||||||
|
tiva_i2c_putreg(priv, TIVA_I2CM_DR_OFFSET, dr << I2CM_DR_SHIFT);
|
||||||
|
|
||||||
|
/* Write the command to the control register to send the byte in the DR
|
||||||
|
* register.
|
||||||
|
*/
|
||||||
|
|
||||||
|
tiva_i2c_putreg(priv, TIVA_I2CM_CS_OFFSET, cmd);
|
||||||
|
tiva_i2c_traceevent(priv, I2CEVENT_SENDBYTE, priv->dcnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->intstate = INTSTATE_XFRWAIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
@ -973,216 +987,199 @@ static int tiva_i2c_interrupt(struct tiva_i2c_priv_s *priv, uint32_t status)
|
|||||||
|
|
||||||
tiva_i2c_tracenew(priv, status);
|
tiva_i2c_tracenew(priv, status);
|
||||||
|
|
||||||
/* Was start bit sent */
|
/* Check for a master interrupt? The I2C master module generates an interrupt when
|
||||||
#warning Missing logic
|
* a transaction completes (either transmit or receive), when arbitration is lost,
|
||||||
|
* or when an error occurs during a transaction.
|
||||||
{
|
|
||||||
tiva_i2c_traceevent(priv, I2CEVENT_SENDADDR, priv->msgc);
|
|
||||||
|
|
||||||
/* We check for msgc > 0 here as an unexpected interrupt with
|
|
||||||
* due to noise on the I2C cable can otherwise cause msgc to
|
|
||||||
* wrap causing memory overwrite
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (priv->msgc > 0 && priv->msgv != NULL)
|
|
||||||
{
|
|
||||||
/* Get run-time data */
|
|
||||||
|
|
||||||
priv->ptr = priv->msgv->buffer;
|
|
||||||
priv->dcnt = priv->msgv->length;
|
|
||||||
priv->flags = priv->msgv->flags;
|
|
||||||
|
|
||||||
/* Send address byte and define addressing mode */
|
|
||||||
|
|
||||||
tiva_i2c_putreg(priv, TIVA_I2CM_SA_OFFSET,
|
|
||||||
(priv->msgv->addr << 1) | (priv->flags & I2C_M_READ));
|
|
||||||
|
|
||||||
/* Set ACK for receive mode */
|
|
||||||
#warning Missing logic
|
|
||||||
|
|
||||||
/* Increment to next pointer and decrement message count */
|
|
||||||
|
|
||||||
priv->msgv++;
|
|
||||||
priv->msgc--;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Clear ISR by writing to DR register */
|
|
||||||
#warning Missing logic
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Was address sent, continue with either sending or reading data */
|
|
||||||
#warning Missing logic
|
|
||||||
|
|
||||||
else if ((priv->flags & I2C_M_READ) == 0 && 0 /* ? */ )
|
|
||||||
{
|
|
||||||
if (priv->dcnt > 0)
|
|
||||||
{
|
|
||||||
/* Send a byte */
|
|
||||||
#warning Missing logic
|
|
||||||
priv->dcnt--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if ((priv->flags & I2C_M_READ) != 0 && 0 /* ? */)
|
|
||||||
{
|
|
||||||
/* Enable in order to receive one or multiple bytes */
|
|
||||||
#warning Missing logic
|
|
||||||
}
|
|
||||||
|
|
||||||
/* More bytes to read */
|
|
||||||
#warning Missing logic
|
|
||||||
|
|
||||||
{
|
|
||||||
/* Read a byte, if dcnt goes < 0, then read dummy bytes to ack ISRs */
|
|
||||||
|
|
||||||
if (priv->dcnt > 0)
|
|
||||||
{
|
|
||||||
tiva_i2c_traceevent(priv, I2CEVENT_RCVBYTE, priv->dcnt);
|
|
||||||
|
|
||||||
/* No interrupts or context switches may occur in the following
|
|
||||||
* sequence. Otherwise, additional bytes may be sent by the
|
|
||||||
* device.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef CONFIG_I2C_POLLED
|
|
||||||
irqstate_t state = irqsave();
|
|
||||||
#endif
|
|
||||||
/* Receive a byte */
|
|
||||||
#warning Missing logic
|
|
||||||
|
|
||||||
/* Disable acknowledge when last byte is to be received */
|
|
||||||
|
|
||||||
priv->dcnt--;
|
|
||||||
if (priv->dcnt == 1)
|
|
||||||
{
|
|
||||||
#warning Missing logic
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_I2C_POLLED
|
|
||||||
irqrestore(state);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Throw away the unexpected byte */
|
|
||||||
#warning Missing logic
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Do we have more bytes to send, enable/disable buffer interrupts
|
|
||||||
* (these ISRs could be replaced by DMAs)
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CONFIG_I2C_POLLED
|
if ((status & I2CM_RIS_MRIS) != 0)
|
||||||
if (priv->dcnt > 0)
|
|
||||||
{
|
{
|
||||||
tiva_i2c_traceevent(priv, I2CEVENT_REITBUFEN, 0);
|
uint32_t mcs;
|
||||||
#warning Missing logic
|
|
||||||
}
|
|
||||||
else if (priv->dcnt == 0)
|
|
||||||
{
|
|
||||||
tiva_i2c_traceevent(priv, I2CEVENT_DISITBUFEN, 0);
|
|
||||||
#warning Missing logic
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Was last byte received or sent? */
|
/* Clear the pending master interrupt */
|
||||||
|
|
||||||
if (priv->dcnt <= 0 && 0 /* ? */)
|
tiva_i2c_putreg(priv, TIVA_I2CM_ICR_OFFSET, I2CM_ICR_MIC);
|
||||||
{
|
status &= ~I2CM_RIS_MRIS;
|
||||||
/* Acknowledge the pending interrupt */
|
|
||||||
#warning Missing logic
|
|
||||||
|
|
||||||
/* Do we need to terminate or restart after this byte?
|
/* We need look at the Master Control/Status register to determine the cause
|
||||||
* If there are more messages to send, then we may:
|
* of the master interrupt.
|
||||||
*
|
|
||||||
* - continue with repeated start
|
|
||||||
* - or just continue sending writeable part
|
|
||||||
* - or we close down by sending the stop bit
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (priv->msgc > 0)
|
mcs = tiva_i2c_getreg(priv, TIVA_I2CM_CS_OFFSET);
|
||||||
{
|
|
||||||
if (priv->msgv->flags & I2C_M_NORESTART)
|
|
||||||
{
|
|
||||||
tiva_i2c_traceevent(priv, I2CEVENT_BTFNOSTART, priv->msgc);
|
|
||||||
priv->ptr = priv->msgv->buffer;
|
|
||||||
priv->dcnt = priv->msgv->length;
|
|
||||||
priv->flags = priv->msgv->flags;
|
|
||||||
priv->msgv++;
|
|
||||||
priv->msgc--;
|
|
||||||
|
|
||||||
/* Restart this ISR! */
|
/* If the busy bit is set, then the other bits are not valid */
|
||||||
|
|
||||||
|
if ((mcs & I2CM_CS_BUSY) != 0)
|
||||||
|
{
|
||||||
|
tiva_i2c_traceevent(priv, I2CEVENT_BUSY, mcs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for errors, in which case, stop the transfer and return. */
|
||||||
|
|
||||||
|
else if ((mcs & I2CM_CS_ERROR) != 0)
|
||||||
|
{
|
||||||
|
tiva_i2c_traceevent(priv, I2CEVENT_ERROR, mcs);
|
||||||
|
|
||||||
|
/* Disable further interrupts */
|
||||||
|
|
||||||
|
tiva_i2c_putreg(priv, TIVA_I2CM_IMR_OFFSET, 0);
|
||||||
|
|
||||||
#ifndef CONFIG_I2C_POLLED
|
#ifndef CONFIG_I2C_POLLED
|
||||||
#warning Missing logic
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tiva_i2c_traceevent(priv, I2CEVENT_BTFRESTART, priv->msgc);
|
|
||||||
tiva_i2c_sendstart(priv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (priv->msgv)
|
|
||||||
{
|
|
||||||
tiva_i2c_traceevent(priv, I2CEVENT_BTFSTOP, 0);
|
|
||||||
tiva_i2c_sendstop(priv);
|
|
||||||
|
|
||||||
/* Is there a thread waiting for this event (there should be) */
|
/* Is there a thread waiting for this event (there should be) */
|
||||||
|
|
||||||
#ifndef CONFIG_I2C_POLLED
|
if (priv->intstate != INTSTATE_IDLE &&
|
||||||
if (priv->intstate == INTSTATE_WAITING)
|
priv->intstate != INTSTATE_DONE)
|
||||||
{
|
{
|
||||||
/* Yes.. inform the thread that the transfer is complete
|
/* Yes.. inform the thread that the transfer is complete
|
||||||
* and wake it up.
|
* and wake it up.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
sem_post(&priv->waitsem);
|
sem_post(&priv->waitsem);
|
||||||
|
priv->status = mcs;
|
||||||
priv->intstate = INTSTATE_DONE;
|
priv->intstate = INTSTATE_DONE;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
priv->status = mcs;
|
||||||
priv->intstate = INTSTATE_DONE;
|
priv->intstate = INTSTATE_DONE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Mark that we have stopped with this transaction */
|
|
||||||
|
|
||||||
priv->msgv = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for errors, in which case, stop the transfer and return
|
/* Otherwise, the last transfer must have completed successfully */
|
||||||
* Note that in master reception mode AF becomes set on last byte
|
|
||||||
* since ACK is not returned. We should ignore this error.
|
|
||||||
*/
|
|
||||||
#warning Missing logic
|
|
||||||
|
|
||||||
{
|
else
|
||||||
tiva_i2c_traceevent(priv, I2CEVENT_ERROR, 0);
|
{
|
||||||
|
int dr;
|
||||||
|
|
||||||
/* Clear interrupt flags */
|
tiva_i2c_traceevent(priv, I2CEVENT_XFRDONE, priv->dcnt);
|
||||||
#warning Missing logic
|
|
||||||
|
|
||||||
|
/* Read from the DR register */
|
||||||
|
|
||||||
/* Is there a thread waiting for this event (there should be) */
|
dr = tiva_i2c_getreg(priv, TIVA_I2CM_DR_OFFSET);
|
||||||
|
|
||||||
|
/* We check for msgc > 0 here as an unexpected interrupt with
|
||||||
|
* due to noise on the I2C cable can otherwise cause msgc to
|
||||||
|
* wrap causing memory overwrite
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (priv->msgc > 0 && priv->msgv != NULL)
|
||||||
|
{
|
||||||
|
/* Was this the completion of an address or of the data portion
|
||||||
|
* of the transfer?
|
||||||
|
*/
|
||||||
|
|
||||||
|
DEBUGASSERT(priv->dcnt > 0);
|
||||||
|
|
||||||
|
if (priv->intstate == INTSTATE_XFRWAIT)
|
||||||
|
{
|
||||||
|
/* Data transfer completed. Are we sending or receiving data? */
|
||||||
|
|
||||||
|
if ((priv->flags & I2C_M_READ) != 0)
|
||||||
|
{
|
||||||
|
/* We are receiving data. Copy the received data to
|
||||||
|
* the user buffer
|
||||||
|
*/
|
||||||
|
|
||||||
|
*priv->ptr++ = (uint8_t)dr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decrement the count of bytes remaining to be sent */
|
||||||
|
|
||||||
|
priv->dcnt--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Was that the last byte of this message? */
|
||||||
|
|
||||||
|
if (priv->dcnt > 0)
|
||||||
|
{
|
||||||
|
/* Send the next byte */
|
||||||
|
|
||||||
|
tiva_i2c_nextxfr(priv);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Increment to next pointer and decrement message count */
|
||||||
|
|
||||||
|
priv->msgv++;
|
||||||
|
priv->msgc--;
|
||||||
|
|
||||||
|
/* Is there another message to be sent? */
|
||||||
|
|
||||||
|
if (priv->msgc > 0)
|
||||||
|
{
|
||||||
|
/* Do we need to terminate or restart after this byte?
|
||||||
|
* If there are more messages to send, then we may
|
||||||
|
* continue with or without the (repeated) start bit.
|
||||||
|
*/
|
||||||
|
|
||||||
|
tiva_i2c_traceevent(priv, I2CEVENT_NEXTMSG, priv->msgc);
|
||||||
|
if (priv->msgv->flags & I2C_M_NORESTART)
|
||||||
|
{
|
||||||
|
/* Just continue transferring data. In this case,
|
||||||
|
* no STOP was sent at the end of the last message
|
||||||
|
* and the there is no new address.
|
||||||
|
*
|
||||||
|
* REVISIT: In this case, the address or the
|
||||||
|
* direction of the transfer cannot be permitted to
|
||||||
|
* change
|
||||||
|
*/
|
||||||
|
|
||||||
|
tiva_i2c_nextxfr(priv);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set the repeated start. No STOP was sent at the
|
||||||
|
* end of the previous message.
|
||||||
|
*/
|
||||||
|
|
||||||
|
tiva_i2c_sendaddress(priv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* No.. then we are finished */
|
||||||
|
|
||||||
|
tiva_i2c_traceevent(priv, I2CEVENT_DONE, priv->intstate);
|
||||||
|
|
||||||
|
/* Disable further interrupts */
|
||||||
|
|
||||||
|
tiva_i2c_putreg(priv, TIVA_I2CM_IMR_OFFSET, 0);
|
||||||
|
|
||||||
#ifndef CONFIG_I2C_POLLED
|
#ifndef CONFIG_I2C_POLLED
|
||||||
if (priv->intstate == INTSTATE_WAITING)
|
/* Is there a thread waiting for this event (there
|
||||||
{
|
* should be)
|
||||||
/* Yes.. inform the thread that the transfer is complete
|
*/
|
||||||
* and wake it up.
|
|
||||||
*/
|
|
||||||
|
|
||||||
sem_post(&priv->waitsem);
|
if (priv->intstate != INTSTATE_IDLE &&
|
||||||
priv->intstate = INTSTATE_DONE;
|
priv->intstate != INTSTATE_DONE)
|
||||||
}
|
{
|
||||||
|
/* Yes.. inform the thread that the transfer is
|
||||||
|
* complete and wake it up.
|
||||||
|
*/
|
||||||
|
|
||||||
|
sem_post(&priv->waitsem);
|
||||||
|
priv->status = mcs;
|
||||||
|
priv->intstate = INTSTATE_DONE;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
priv->intstate = INTSTATE_DONE;
|
priv->status = mcs;
|
||||||
|
priv->intstate = INTSTATE_DONE;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* There is no pending message? Must be a spurious interrupt */
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tiva_i2c_traceevent(priv, I2CEVENT_SPURIOUS, priv->msgc);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Make sure that all pending interrupts were handled */
|
||||||
|
|
||||||
|
DEBUGASSERT(status == 0);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1465,8 +1462,8 @@ static uint32_t tiva_i2c_setclock(struct tiva_i2c_priv_s *priv, uint32_t frequen
|
|||||||
regval = tiva_i2c_putreg(priv, TIVA_I2CSC_PP_OFFSET);
|
regval = tiva_i2c_putreg(priv, TIVA_I2CSC_PP_OFFSET);
|
||||||
if ((regval & I2CSC_PP_HS) != 0)
|
if ((regval & I2CSC_PP_HS) != 0)
|
||||||
{
|
{
|
||||||
regval = ((SYSCLK_FREQUENCY +
|
tmp = (2 * 3 * 3400000)
|
||||||
(2 * 3 * 3400000) - 1) / (2 * 3 * 3400000)) - 1;
|
regval = (((SYSCLK_FREQUENCY + tmp - 1) / tmp) - 1) << I2CM_TPR_SHIFT;
|
||||||
|
|
||||||
tiva_i2c_putreg(priv, TIVA_I2CM_TPR_OFFSET, I2CM_TPR_HS | regval);
|
tiva_i2c_putreg(priv, TIVA_I2CM_TPR_OFFSET, I2CM_TPR_HS | regval);
|
||||||
}
|
}
|
||||||
@ -1535,32 +1532,10 @@ static int tiva_i2c_process(struct i2c_dev_s *dev, struct i2c_msg_s *msgs,
|
|||||||
{
|
{
|
||||||
struct tiva_i2c_inst_s *inst = (struct tiva_i2c_inst_s *)dev;
|
struct tiva_i2c_inst_s *inst = (struct tiva_i2c_inst_s *)dev;
|
||||||
struct tiva_i2c_priv_s *priv = inst->priv;
|
struct tiva_i2c_priv_s *priv = inst->priv;
|
||||||
uint32_t status = 0;
|
|
||||||
int errval = 0;
|
int errval = 0;
|
||||||
|
|
||||||
ASSERT(count);
|
ASSERT(count);
|
||||||
|
|
||||||
/* Wait for any STOP in progress. NOTE: If we have to disable the FSMC
|
|
||||||
* then we cannot do this at the top of the loop, unfortunately. The STOP
|
|
||||||
* will not complete normally if the FSMC is enabled.
|
|
||||||
*/
|
|
||||||
|
|
||||||
tiva_i2c_sem_waitstop(priv);
|
|
||||||
|
|
||||||
/* Clear any pending error interrupts */
|
|
||||||
#warning Missing logic
|
|
||||||
|
|
||||||
/* "Note: When the STOP, START or PEC bit is set, the software must
|
|
||||||
* not perform any write access to I2C_CR1 before this bit is
|
|
||||||
* cleared by hardware. Otherwise there is a risk of setting a
|
|
||||||
* second STOP, START or PEC request." However, if the bits are
|
|
||||||
* not cleared by hardware, then we will have to do that from hardware.
|
|
||||||
*/
|
|
||||||
|
|
||||||
tiva_i2c_clrstart(priv);
|
|
||||||
|
|
||||||
/* Old transfers are done */
|
|
||||||
|
|
||||||
/* Reset ptr and dcnt to ensure an unexpected data interrupt doesn't
|
/* Reset ptr and dcnt to ensure an unexpected data interrupt doesn't
|
||||||
* overwrite stale data.
|
* overwrite stale data.
|
||||||
*/
|
*/
|
||||||
@ -1571,6 +1546,8 @@ static int tiva_i2c_process(struct i2c_dev_s *dev, struct i2c_msg_s *msgs,
|
|||||||
priv->msgv = msgs;
|
priv->msgv = msgs;
|
||||||
priv->msgc = count;
|
priv->msgc = count;
|
||||||
|
|
||||||
|
priv->status = 0;
|
||||||
|
|
||||||
/* Reset I2C trace logic */
|
/* Reset I2C trace logic */
|
||||||
|
|
||||||
tiva_i2c_tracereset(priv);
|
tiva_i2c_tracereset(priv);
|
||||||
@ -1579,11 +1556,11 @@ static int tiva_i2c_process(struct i2c_dev_s *dev, struct i2c_msg_s *msgs,
|
|||||||
|
|
||||||
tiva_i2c_setclock(priv, inst->frequency);
|
tiva_i2c_setclock(priv, inst->frequency);
|
||||||
|
|
||||||
/* Trigger start condition, then the process moves into the ISR. I2C
|
/* Send the address, then the process moves into the ISR. I2C
|
||||||
* interrupts will be enabled within tiva_i2c_waitdone().
|
* interrupts will be enabled within tiva_i2c_waitdone().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
tiva_i2c_sendstart(priv);
|
tiva_i2c_sendaddress(priv);
|
||||||
|
|
||||||
/* Wait for an ISR, if there was a timeout, fetch latest status to get
|
/* Wait for an ISR, if there was a timeout, fetch latest status to get
|
||||||
* the BUSY flag.
|
* the BUSY flag.
|
||||||
@ -1591,64 +1568,36 @@ static int tiva_i2c_process(struct i2c_dev_s *dev, struct i2c_msg_s *msgs,
|
|||||||
|
|
||||||
if (tiva_i2c_sem_waitdone(priv) < 0)
|
if (tiva_i2c_sem_waitdone(priv) < 0)
|
||||||
{
|
{
|
||||||
/* Read the raw interrupt status */
|
i2cdbg("ERROR: Timed out\n");
|
||||||
|
|
||||||
status = tiva_i2c_getreg(priv, TIVA_I2CM_RIS_OFFSET);
|
|
||||||
errval = ETIMEDOUT;
|
errval = ETIMEDOUT;
|
||||||
|
|
||||||
i2cdbg("Timed out: status: 0x%08x\n", status);
|
|
||||||
|
|
||||||
/* "Note: When the STOP, START or PEC bit is set, the software must
|
|
||||||
* not perform any write access to I2C_CR1 before this bit is
|
|
||||||
* cleared by hardware. Otherwise there is a risk of setting a
|
|
||||||
* second STOP, START or PEC request."
|
|
||||||
*/
|
|
||||||
|
|
||||||
tiva_i2c_clrstart(priv);
|
|
||||||
}
|
}
|
||||||
|
else if ((priv->status & I2CM_CS_ERROR) != 0)
|
||||||
/* Check for error status conditions */
|
|
||||||
#warning Missing logic
|
|
||||||
{
|
{
|
||||||
|
if ((priv->status & I2CM_CS_ARBLST) != 0)
|
||||||
{
|
{
|
||||||
/* Bus Error */
|
/* Arbitration Lost */
|
||||||
|
|
||||||
errval = EIO;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
/* Arbitration Lost (master mode) */
|
|
||||||
|
|
||||||
errval = EAGAIN;
|
errval = EAGAIN;
|
||||||
}
|
}
|
||||||
|
else if ((priv->status & (I2CM_CS_ADRACK | I2CM_CS_DATACK)) != 0)
|
||||||
{
|
{
|
||||||
/* Acknowledge Failure */
|
/* Acknowledge Failure */
|
||||||
|
|
||||||
errval = ENXIO;
|
errval = ENXIO;
|
||||||
}
|
}
|
||||||
|
#ifdef I2CM_CS_CLKTO
|
||||||
|
else if ((priv->status & I2CM_CS_CLKTO) != 0)
|
||||||
{
|
{
|
||||||
/* Overrun/Underrun */
|
/* Timeout */
|
||||||
|
|
||||||
errval = EIO;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
/* PEC Error in reception */
|
|
||||||
|
|
||||||
errval = EPROTO;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
/* Timeout or Tlow Error */
|
|
||||||
|
|
||||||
errval = ETIME;
|
errval = ETIME;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
/* This is not an error and should never happen since SMBus is not enabled */
|
else
|
||||||
|
|
||||||
{
|
{
|
||||||
/* SMBus alert is an optional signal with an interrupt line for devices
|
/* Something else? */
|
||||||
* that want to trade their ability to master for a pin.
|
|
||||||
*/
|
|
||||||
|
|
||||||
errval = EINTR;
|
errval = EIO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1657,7 +1606,8 @@ static int tiva_i2c_process(struct i2c_dev_s *dev, struct i2c_msg_s *msgs,
|
|||||||
* NOTE: We will only see this busy indication if tiva_i2c_sem_waitdone()
|
* NOTE: We will only see this busy indication if tiva_i2c_sem_waitdone()
|
||||||
* fails above; Otherwise it is cleared.
|
* fails above; Otherwise it is cleared.
|
||||||
*/
|
*/
|
||||||
#warning Missing logic
|
|
||||||
|
if ((tiva_i2c_getreg(priv, TIVA_I2CM_CS_OFFSET) & (I2CM_CS_BUSY | I2CM_CS_BUSBSY)) != 0)
|
||||||
{
|
{
|
||||||
/* I2C Bus is for some reason busy */
|
/* I2C Bus is for some reason busy */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user