configs/z8f64200100kit/ostest at same level as ez80 configurations; nuttx/arch/arm/src/lpc17xx/lpc17_i2c.cuninitialization fix

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5392 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2012-11-27 15:09:12 +00:00
parent 5b81a279ca
commit bf4bee0b1e

View File

@ -67,7 +67,6 @@
#include "up_internal.h" #include "up_internal.h"
#include "os_internal.h" #include "os_internal.h"
#include "lpc17_internal.h" #include "lpc17_internal.h"
#include "lpc17_syscon.h" #include "lpc17_syscon.h"
#include "lpc17_pinconn.h" #include "lpc17_pinconn.h"
@ -79,12 +78,15 @@
#define GPIO_I2C1_SCL GPIO_I2C1_SCL_1 #define GPIO_I2C1_SCL GPIO_I2C1_SCL_1
#define GPIO_I2C1_SDA GPIO_I2C1_SDA_1 #define GPIO_I2C1_SDA GPIO_I2C1_SDA_1
#endif #endif
#ifndef CONFIG_I2C0_FREQ #ifndef CONFIG_I2C0_FREQ
#define CONFIG_I2C0_FREQ 100000 #define CONFIG_I2C0_FREQ 100000
#endif #endif
#ifndef CONFIG_I2C1_FREQ #ifndef CONFIG_I2C1_FREQ
#define CONFIG_I2C1_FREQ 100000 #define CONFIG_I2C1_FREQ 100000
#endif #endif
#ifndef CONFIG_I2C2_FREQ #ifndef CONFIG_I2C2_FREQ
#define CONFIG_I2C2_FREQ 100000 #define CONFIG_I2C2_FREQ 100000
#endif #endif
@ -93,15 +95,16 @@
* Definitions * Definitions
*******************************************************************************/ *******************************************************************************/
/**************************************************************************** /*******************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
****************************************************************************/ *******************************************************************************/
#define I2C_TIMEOUT ((20 * CLK_TCK) / 1000) /* 20 mS */ #define I2C_TIMEOUT ((20 * CLK_TCK) / 1000) /* 20 mS */
/**************************************************************************** /*******************************************************************************
* Private Data * Private Data
****************************************************************************/ *******************************************************************************/
struct lpc17_i2cdev_s struct lpc17_i2cdev_s
{ {
struct i2c_dev_s dev; /* Generic I2C device */ struct i2c_dev_s dev; /* Generic I2C device */
@ -120,17 +123,18 @@ struct lpc17_i2cdev_s
static struct lpc17_i2cdev_s i2cdevices[3]; static struct lpc17_i2cdev_s i2cdevices[3];
/**************************************************************************** /*******************************************************************************
* Private Functions * Private Functions
****************************************************************************/ *******************************************************************************/
static int i2c_start(struct lpc17_i2cdev_s *priv); static int i2c_start(struct lpc17_i2cdev_s *priv);
static void i2c_stop(struct lpc17_i2cdev_s *priv); static void i2c_stop(struct lpc17_i2cdev_s *priv);
static int i2c_interrupt(int irq, FAR void *context); static int i2c_interrupt(int irq, FAR void *context);
static void i2c_timeout(int argc, uint32_t arg, ...); static void i2c_timeout(int argc, uint32_t arg, ...);
/**************************************************************************** /*******************************************************************************
* I2C device operations * I2C device operations
****************************************************************************/ *******************************************************************************/
static uint32_t i2c_setfrequency(FAR struct i2c_dev_s *dev, uint32_t frequency); static uint32_t i2c_setfrequency(FAR struct i2c_dev_s *dev, uint32_t frequency);
static int i2c_setaddress(FAR struct i2c_dev_s *dev, int addr, int nbits); static int i2c_setaddress(FAR struct i2c_dev_s *dev, int addr, int nbits);
@ -164,17 +168,20 @@ static uint32_t i2c_setfrequency(FAR struct i2c_dev_s *dev, uint32_t frequency)
if (frequency > 100000) if (frequency > 100000)
{ {
/* asymetric per 400Khz I2C spec */ /* asymetric per 400Khz I2C spec */
putreg32(LPC17_CCLK / (83 + 47) * 47 / frequency, priv->base + LPC17_I2C_SCLH_OFFSET); putreg32(LPC17_CCLK / (83 + 47) * 47 / frequency, priv->base + LPC17_I2C_SCLH_OFFSET);
putreg32(LPC17_CCLK / (83 + 47) * 83 / frequency, priv->base + LPC17_I2C_SCLL_OFFSET); putreg32(LPC17_CCLK / (83 + 47) * 83 / frequency, priv->base + LPC17_I2C_SCLL_OFFSET);
} }
else else
{ {
/* 50/50 mark space ratio */ /* 50/50 mark space ratio */
putreg32(LPC17_CCLK / 100 * 50 / frequency, priv->base + LPC17_I2C_SCLH_OFFSET); putreg32(LPC17_CCLK / 100 * 50 / frequency, priv->base + LPC17_I2C_SCLH_OFFSET);
putreg32(LPC17_CCLK / 100 * 50 / frequency, priv->base + LPC17_I2C_SCLL_OFFSET); putreg32(LPC17_CCLK / 100 * 50 / frequency, priv->base + LPC17_I2C_SCLL_OFFSET);
} }
/* FIXME: This function should return the actual selected frequency */ /* FIXME: This function should return the actual selected frequency */
return frequency; return frequency;
} }
@ -185,6 +192,7 @@ static uint32_t i2c_setfrequency(FAR struct i2c_dev_s *dev, uint32_t frequency)
* Set the I2C slave address for a subsequent read/write * Set the I2C slave address for a subsequent read/write
* *
*******************************************************************************/ *******************************************************************************/
static int i2c_setaddress(FAR struct i2c_dev_s *dev, int addr, int nbits) static int i2c_setaddress(FAR struct i2c_dev_s *dev, int addr, int nbits)
{ {
struct lpc17_i2cdev_s *priv = (struct lpc17_i2cdev_s *) dev; struct lpc17_i2cdev_s *priv = (struct lpc17_i2cdev_s *) dev;
@ -206,6 +214,7 @@ static int i2c_setaddress(FAR struct i2c_dev_s *dev, int addr, int nbits)
* frequency and slave address. * frequency and slave address.
* *
*******************************************************************************/ *******************************************************************************/
static int i2c_write(FAR struct i2c_dev_s *dev, const uint8_t *buffer, int buflen) static int i2c_write(FAR struct i2c_dev_s *dev, const uint8_t *buffer, int buflen)
{ {
struct lpc17_i2cdev_s *priv = (struct lpc17_i2cdev_s *) dev; struct lpc17_i2cdev_s *priv = (struct lpc17_i2cdev_s *) dev;
@ -232,6 +241,7 @@ static int i2c_write(FAR struct i2c_dev_s *dev, const uint8_t *buffer, int bufle
* frequency and slave address. * frequency and slave address.
* *
*******************************************************************************/ *******************************************************************************/
static int i2c_read(FAR struct i2c_dev_s *dev, uint8_t *buffer, int buflen) static int i2c_read(FAR struct i2c_dev_s *dev, uint8_t *buffer, int buflen)
{ {
struct lpc17_i2cdev_s *priv = (struct lpc17_i2cdev_s *) dev; struct lpc17_i2cdev_s *priv = (struct lpc17_i2cdev_s *) dev;
@ -257,9 +267,11 @@ static int i2c_read(FAR struct i2c_dev_s *dev, uint8_t *buffer, int buflen)
* Perform a I2C transfer start * Perform a I2C transfer start
* *
*******************************************************************************/ *******************************************************************************/
static int i2c_start(struct lpc17_i2cdev_s *priv) static int i2c_start(struct lpc17_i2cdev_s *priv)
{ {
int ret = -1; int ret = -1;
sem_wait(&priv->mutex); sem_wait(&priv->mutex);
putreg32(I2C_CONCLR_STAC|I2C_CONCLR_SIC, priv->base+LPC17_I2C_CONCLR_OFFSET); putreg32(I2C_CONCLR_STAC|I2C_CONCLR_SIC, priv->base+LPC17_I2C_CONCLR_OFFSET);
@ -271,9 +283,14 @@ static int i2c_start (struct lpc17_i2cdev_s *priv)
sem_post(&priv->mutex); sem_post(&priv->mutex);
if (priv-> state == 0x18 || priv->state == 0x28) if (priv-> state == 0x18 || priv->state == 0x28)
{
ret = priv->wrcnt; ret = priv->wrcnt;
}
else if (priv-> state == 0x50 || priv->state == 0x58) else if (priv-> state == 0x50 || priv->state == 0x58)
{
ret = priv->rdcnt; ret = priv->rdcnt;
}
return ret; return ret;
} }
@ -284,10 +301,14 @@ static int i2c_start (struct lpc17_i2cdev_s *priv)
* Perform a I2C transfer stop * Perform a I2C transfer stop
* *
*******************************************************************************/ *******************************************************************************/
static void i2c_stop(struct lpc17_i2cdev_s *priv) static void i2c_stop(struct lpc17_i2cdev_s *priv)
{ {
if (priv->state != 0x38) if (priv->state != 0x38)
{
putreg32(I2C_CONSET_STO|I2C_CONSET_AA,priv->base+LPC17_I2C_CONSET_OFFSET); putreg32(I2C_CONSET_STO|I2C_CONSET_AA,priv->base+LPC17_I2C_CONSET_OFFSET);
}
sem_post(&priv->wait); sem_post(&priv->wait);
} }
@ -320,6 +341,8 @@ static void i2c_timeout (int argc, uint32_t arg, ...)
static int i2c_interrupt(int irq, FAR void *context) static int i2c_interrupt(int irq, FAR void *context)
{ {
struct lpc17_i2cdev_s *priv; struct lpc17_i2cdev_s *priv;
uint32_t state;
#ifdef CONFIG_LPC17_I2C0 #ifdef CONFIG_LPC17_I2C0
if (irq == LPC17_IRQ_I2C0) if (irq == LPC17_IRQ_I2C0)
{ {
@ -344,13 +367,14 @@ static int i2c_interrupt (int irq, FAR void *context)
{ {
PANIC(OSERR_INTERNAL); PANIC(OSERR_INTERNAL);
} }
/*
* refrence UM10360 19.10.5 /* Reference UM10360 19.10.5 */
*/
uint32_t state = getreg32(priv->base+LPC17_I2C_STAT_OFFSET); state = getreg32(priv->base+LPC17_I2C_STAT_OFFSET);
putreg32(I2C_CONCLR_SIC, priv->base+LPC17_I2C_CONCLR_OFFSET); putreg32(I2C_CONCLR_SIC, priv->base+LPC17_I2C_CONCLR_OFFSET);
priv->state = state; priv->state = state;
state &= 0xf8; state &= 0xf8;
switch (state) switch (state)
{ {
case 0x00: // Bus Error case 0x00: // Bus Error
@ -360,47 +384,63 @@ static int i2c_interrupt (int irq, FAR void *context)
case 0x48: case 0x48:
i2c_stop(priv); i2c_stop(priv);
break; break;
case 0x08: // START case 0x08: // START
case 0x10: // Repeat START case 0x10: // Repeat START
putreg32(priv->msg.addr, priv->base+LPC17_I2C_DAT_OFFSET); putreg32(priv->msg.addr, priv->base+LPC17_I2C_DAT_OFFSET);
putreg32(I2C_CONCLR_STAC, priv->base+LPC17_I2C_CONCLR_OFFSET); putreg32(I2C_CONCLR_STAC, priv->base+LPC17_I2C_CONCLR_OFFSET);
break; break;
case 0x18: case 0x18:
priv->wrcnt = 0; priv->wrcnt = 0;
putreg32(priv->msg.buffer[0], priv->base+LPC17_I2C_DAT_OFFSET); putreg32(priv->msg.buffer[0], priv->base+LPC17_I2C_DAT_OFFSET);
break; break;
case 0x28: case 0x28:
priv->wrcnt++; priv->wrcnt++;
if (priv->wrcnt<priv->msg.length) if (priv->wrcnt<priv->msg.length)
{
putreg32(priv->msg.buffer[priv->wrcnt],priv->base+LPC17_I2C_DAT_OFFSET); putreg32(priv->msg.buffer[priv->wrcnt],priv->base+LPC17_I2C_DAT_OFFSET);
}
else else
{
i2c_stop(priv); i2c_stop(priv);
}
break; break;
case 0x40: case 0x40:
priv->rdcnt = -1; priv->rdcnt = -1;
putreg32(I2C_CONSET_AA, priv->base+LPC17_I2C_CONSET_OFFSET); putreg32(I2C_CONSET_AA, priv->base+LPC17_I2C_CONSET_OFFSET);
break; break;
case 0x50: case 0x50:
priv->rdcnt++; priv->rdcnt++;
if (priv->rdcnt < priv->msg.length) if (priv->rdcnt < priv->msg.length)
{
priv->msg.buffer[priv->rdcnt] = getreg32(priv->base+LPC17_I2C_BUFR_OFFSET); priv->msg.buffer[priv->rdcnt] = getreg32(priv->base+LPC17_I2C_BUFR_OFFSET);
}
if (priv->rdcnt>=priv->msg.length-1) if (priv->rdcnt>=priv->msg.length-1)
{
putreg32(I2C_CONCLR_AAC|I2C_CONCLR_SIC, priv->base+LPC17_I2C_CONCLR_OFFSET); putreg32(I2C_CONCLR_AAC|I2C_CONCLR_SIC, priv->base+LPC17_I2C_CONCLR_OFFSET);
}
break; break;
case 0x58: case 0x58:
i2c_stop(priv); i2c_stop(priv);
break; break;
default: default:
i2c_stop(priv); i2c_stop(priv);
break; break;
} }
return OK; return OK;
} }
/**************************************************************************** /*******************************************************************************
* Public Functions * Public Functions
****************************************************************************/ *******************************************************************************/
/******************************************************************************* /*******************************************************************************
* Name: up_i2cinitialize * Name: up_i2cinitialize
@ -413,6 +453,8 @@ static int i2c_interrupt (int irq, FAR void *context)
struct i2c_dev_s *up_i2cinitialize(int port) struct i2c_dev_s *up_i2cinitialize(int port)
{ {
struct lpc17_i2cdev_s *priv; struct lpc17_i2cdev_s *priv;
irqstate_t flags;
uint32_t regval;
if (port > 2) if (port > 2)
{ {
@ -420,9 +462,6 @@ struct i2c_dev_s *up_i2cinitialize(int port)
return NULL; return NULL;
} }
irqstate_t flags;
uint32_t regval;
flags = irqsave(); flags = irqsave();
priv= &i2cdevices[port]; priv= &i2cdevices[port];
@ -447,7 +486,6 @@ struct i2c_dev_s *up_i2cinitialize(int port)
putreg32(LPC17_CCLK/CONFIG_I2C0_FREQ/2, priv->base + LPC17_I2C_SCLH_OFFSET); putreg32(LPC17_CCLK/CONFIG_I2C0_FREQ/2, priv->base + LPC17_I2C_SCLH_OFFSET);
putreg32(LPC17_CCLK/CONFIG_I2C0_FREQ/2, priv->base + LPC17_I2C_SCLL_OFFSET); putreg32(LPC17_CCLK/CONFIG_I2C0_FREQ/2, priv->base + LPC17_I2C_SCLL_OFFSET);
} }
else else
#endif #endif
@ -502,25 +540,28 @@ struct i2c_dev_s *up_i2cinitialize(int port)
{ {
return NULL; return NULL;
} }
putreg32(I2C_CONSET_I2EN, priv->base+LPC17_I2C_CONSET_OFFSET); putreg32(I2C_CONSET_I2EN, priv->base+LPC17_I2C_CONSET_OFFSET);
sem_init(&priv->mutex, 0, 1); sem_init(&priv->mutex, 0, 1);
sem_init(&priv->wait, 0, 0); sem_init(&priv->wait, 0, 0);
/* Allocate a watchdog timer */ /* Allocate a watchdog timer */
priv->timeout = wd_create();
priv->timeout = wd_create();
DEBUGASSERT(priv->timeout != 0); DEBUGASSERT(priv->timeout != 0);
/* Attach Interrupt Handler */ /* Attach Interrupt Handler */
irq_attach(priv->irqid, i2c_interrupt); irq_attach(priv->irqid, i2c_interrupt);
/* Enable Interrupt Handler */ /* Enable Interrupt Handler */
up_enable_irq(priv->irqid); up_enable_irq(priv->irqid);
/* Install our operations */ /* Install our operations */
priv->dev.ops = &lpc17_i2c_ops;
priv->dev.ops = &lpc17_i2c_ops;
return &priv->dev; return &priv->dev;
} }
@ -536,8 +577,26 @@ int up_i2cuninitialize(FAR struct i2c_dev_s * dev)
{ {
struct lpc17_i2cdev_s *priv = (struct lpc17_i2cdev_s *) dev; struct lpc17_i2cdev_s *priv = (struct lpc17_i2cdev_s *) dev;
/* Disable I2C */
putreg32(I2C_CONCLRT_I2ENC, priv->base+LPC17_I2C_CONCLR_OFFSET); putreg32(I2C_CONCLRT_I2ENC, priv->base+LPC17_I2C_CONCLR_OFFSET);
/* Reset data structures */
sem_destroy(&priv->mutex);
sem_destroy(&priv->wait);
/* Free the watchdog timer */
wd_delete(priv->timeout);
priv->timeout = NULL;
/* Disable interrupts */
up_disable_irq(priv->irqid); up_disable_irq(priv->irqid);
/* Detach Interrupt Handler */
irq_detach(priv->irqid); irq_detach(priv->irqid);
return OK; return OK;
} }