X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=bertos%2Fcpu%2Fcortex-m3%2Fdrv%2Fi2c_sam3.c;h=8330a7005d1bd439cd41a86074f06cd14b454fe5;hb=666af47976ef74df740dc7df58fc31fa6e3fc65b;hp=9e9ba6f42df3e5a96e61194bb21f93a145895d3b;hpb=432ab15ef87735cce089856d255d5c19c4edd0f4;p=bertos.git diff --git a/bertos/cpu/cortex-m3/drv/i2c_sam3.c b/bertos/cpu/cortex-m3/drv/i2c_sam3.c index 9e9ba6f4..8330a700 100644 --- a/bertos/cpu/cortex-m3/drv/i2c_sam3.c +++ b/bertos/cpu/cortex-m3/drv/i2c_sam3.c @@ -98,13 +98,6 @@ INLINE void waitXferComplete(I2c *i2c) cpu_relax(); } -/* - * Send STOP condition. - */ -INLINE void sendStop(I2c *i2c) -{ - HWREG(i2c->hw->base + TWI_CR_OFF) |= TWI_CR_STOP; -} /* * The start is not performed when we call the start function @@ -121,9 +114,9 @@ static void i2c_sam3_start(struct I2c *i2c, uint16_t slave_addr) i2c->hw->first_xtranf = true; if (I2C_TEST_START(i2c->flags) == I2C_START_R) - HWREG(i2c->hw->base + TWI_MMR_OFF) = TWI_MMR_DADR(slave_addr) | TWI_MMR_MREAD; + HWREG(i2c->hw->base + TWI_MMR_OFF) = TWI_MMR_DADR(slave_addr >> 1) | TWI_MMR_MREAD; else - HWREG(i2c->hw->base + TWI_MMR_OFF) = TWI_MMR_DADR(slave_addr); + HWREG(i2c->hw->base + TWI_MMR_OFF) = TWI_MMR_DADR(slave_addr >> 1); } static void i2c_sam3_putc(I2c *i2c, const uint8_t data) @@ -137,34 +130,38 @@ static void i2c_sam3_putc(I2c *i2c, const uint8_t data) HWREG(i2c->hw->base + TWI_THR_OFF) = data; + if ((i2c->xfer_size == 1) && (I2C_TEST_STOP(i2c->flags) == I2C_STOP)) + HWREG(i2c->hw->base + TWI_CR_OFF) = TWI_CR_STOP; + // On first byte sent wait for start timeout if (i2c->hw->first_xtranf && !waitTxRdy(i2c, CONFIG_I2C_START_TIMEOUT)) { LOG_ERR("i2c: write start timeout\n"); i2c->errors |= I2C_START_TIMEOUT; - sendStop(i2c); + HWREG(i2c->hw->base + TWI_CR_OFF) = TWI_CR_STOP; waitXferComplete(i2c); return; } i2c->hw->first_xtranf = false; if ((i2c->xfer_size == 1) && (I2C_TEST_STOP(i2c->flags) == I2C_STOP)) - { - sendStop(i2c); waitXferComplete(i2c); - } } static uint8_t i2c_sam3_getc(I2c *i2c) { + uint8_t data; + uint32_t cr = 0; + if (i2c->hw->first_xtranf) { - HWREG(i2c->hw->base + TWI_CR_OFF) = TWI_CR_START; + cr |= TWI_CR_START; i2c->hw->first_xtranf = false; } - if ((i2c->xfer_size == 1) && (I2C_TEST_STOP(i2c->flags) == I2C_STOP)) - sendStop(i2c); + cr |= TWI_CR_STOP; + + HWREG(i2c->hw->base + TWI_CR_OFF) = cr; if (!waitRxRdy(i2c, CONFIG_I2C_START_TIMEOUT)) { @@ -173,7 +170,12 @@ static uint8_t i2c_sam3_getc(I2c *i2c) return 0xFF; } - return HWREG(i2c->hw->base + TWI_RHR_OFF); + data = HWREG(i2c->hw->base + TWI_RHR_OFF); + + if ((i2c->xfer_size == 1) && (I2C_TEST_STOP(i2c->flags) == I2C_STOP)) + waitXferComplete(i2c); + + return data; } static void i2c_setClock(I2c *i2c, int clock) @@ -216,14 +218,11 @@ struct I2cHardware i2c_sam3_hw[I2C_CNT]; */ void i2c_hw_init(I2c *i2c, int dev, uint32_t clock) { - uint8_t dummy; - ASSERT(dev < I2C_CNT); i2c->hw = &i2c_sam3_hw[dev]; i2c->vt = &i2c_sam3_vt; - // Configure I/O pins pmc_periphEnable(PIOA_ID); switch (dev) @@ -245,18 +244,10 @@ void i2c_hw_init(I2c *i2c, int dev, uint32_t clock) return; } - /* - * Reset sequence: enable slave mode, reset, read RHR, - * disable slave and master modes. - */ - HWREG(i2c->hw->base + TWI_CR_OFF) = TWI_CR_SVEN; - HWREG(i2c->hw->base + TWI_CR_OFF) = TWI_CR_SWRST; - dummy = HWREG(i2c->hw->base + TWI_RHR_OFF); - HWREG(i2c->hw->base + TWI_CR_OFF) = TWI_CR_SVDIS; - HWREG(i2c->hw->base + TWI_CR_OFF) = TWI_CR_MSDIS; - // Set master mode - HWREG(i2c->hw->base + TWI_CR_OFF) = TWI_CR_MSEN; + // Reset and set master mode + HWREG(i2c->hw->base + TWI_CR_OFF) = TWI_CR_SWRST; + HWREG(i2c->hw->base + TWI_CR_OFF) = TWI_CR_MSEN | TWI_CR_SVDIS; i2c_setClock(i2c, clock); }