altos: get MPU6000 I2C link working reliably
authorKeith Packard <keithp@keithp.com>
Wed, 27 Jun 2012 21:38:35 +0000 (14:38 -0700)
committerKeith Packard <keithp@keithp.com>
Wed, 27 Jun 2012 21:38:35 +0000 (14:38 -0700)
This slows the i2c bus to 100kHz (yuck), sets the rise time to spec
(it was way off) and adds more delays during bus setup. I've run this
for hours now without trouble. Will try to adjust things back to fast
mode and see if I can make that work as 100kHz isn't fast enough to
reliably get data at 100 samples/sec.

Signed-off-by: Keith Packard <keithp@keithp.com>
src/stm/ao_i2c_stm.c

index 4d7d8d87a37fff150c6418f7f328060504bf0305..c4a6c5a38e1078f609fd4b42148d6bfe934c7962 100644 (file)
@@ -167,9 +167,10 @@ ao_i2c_start(uint8_t index, uint16_t addr)
                if (!(stm_i2c->cr1 & (1 << STM_I2C_CR1_START)))
                        break;
        }
-       stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN);
        ao_alarm(AO_MS_TO_TICKS(250));
        cli();
+       stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN);
+       ao_i2c_ev_isr(index);
        while (ao_i2c_state[index] == I2C_IDLE)
                if (ao_sleep(&ao_i2c_state[index]))
                        break;
@@ -192,6 +193,19 @@ ao_i2c_wait_stop(uint8_t index)
        ao_i2c_state[index] = I2C_IDLE;
 }
 
+static void
+ao_i2c_wait_addr(uint8_t index)
+{
+       struct stm_i2c  *stm_i2c = ao_i2c_stm_info[index].stm_i2c;
+       int     t;
+
+       for (t = 0; t < I2C_TIMEOUT; t++)
+               if (!(stm_i2c->sr1 & (1 << STM_I2C_SR1_ADDR)))
+                       break;
+       if (t)
+               printf ("wait_addr %d\n", t);
+}
+
 uint8_t
 ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop)
 {
@@ -199,9 +213,11 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop)
        uint8_t         *b = block;
        uint32_t        sr1;
        uint8_t         tx_dma_index = ao_i2c_stm_info[index].tx_dma_index;
+       int             t;
 
        /* Clear any pending ADDR bit */
        (void) stm_i2c->sr2;
+       ao_i2c_wait_addr(index);
        stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_DMAEN);
        ao_dma_set_transfer(tx_dma_index,
                            &stm_i2c->dr,
@@ -272,6 +288,7 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop)
 
                /* Clear any pending ADDR bit */
                stm_i2c->sr2;
+               ao_i2c_wait_addr(index);
 
                /* Enable interrupts to transfer the byte */
                stm_i2c->cr2 = (AO_STM_I2C_CR2 |
@@ -308,6 +325,7 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop)
                        (1 << STM_I2C_CR2_DMAEN) | (1 << STM_I2C_CR2_LAST);
                /* Clear any pending ADDR bit */
                (void) stm_i2c->sr2;
+               ao_i2c_wait_addr(index);
 
                ao_dma_start(rx_dma_index);
                ao_alarm(len);
@@ -346,10 +364,11 @@ ao_i2c_channel_init(uint8_t index)
        stm_i2c->sr1 = 0;
        stm_i2c->sr2 = 0;
 
-       stm_i2c->ccr = ((1 << STM_I2C_CCR_FS) |
+       stm_i2c->ccr = ((0 << STM_I2C_CCR_FS) |
                        (0 << STM_I2C_CCR_DUTY) |
-                       (20 << STM_I2C_CCR_CCR));
-       
+                       (80 << STM_I2C_CCR_CCR));
+
+       stm_i2c->trise = 17;
 
        stm_i2c->cr1 = AO_STM_I2C_CR1;
 }