X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=bertos%2Fcpu%2Fcortex-m3%2Fdrv%2Fi2c_sam3.c;h=333e76a3eb95443ae26c225043043d9e217efcec;hb=4edced13c0db9b868ed2fa501987c45d6890860c;hp=23ebb3d2d7201133bf764c544392b5351c1f271a;hpb=e6aee3618f11f859e2f11814cee8f7a652897775;p=bertos.git diff --git a/bertos/cpu/cortex-m3/drv/i2c_sam3.c b/bertos/cpu/cortex-m3/drv/i2c_sam3.c index 23ebb3d2..333e76a3 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 @@ -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) @@ -192,7 +194,7 @@ static void i2c_setClock(I2c *i2c, int clock) } ASSERT(ck_div < 8); - LOG_INFO("i2c: using CKDIV = %lu and CLDIV/CHDIV = %lu\n\n", ck_div, cl_div); + LOG_INFO("i2c: using CKDIV = %lu and CLDIV/CHDIV = %lu\n", ck_div, cl_div); HWREG(i2c->hw->base + TWI_CWGR_OFF) = 0; HWREG(i2c->hw->base + TWI_CWGR_OFF) = (ck_div << 16) | (cl_div << 8) | cl_div; @@ -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); }