Fix read function. Add comment. Use macro for registers devices specific.
authorasterix <asterix@38d2e660-2303-0410-9eaa-f027e97ec537>
Tue, 20 Jul 2010 10:17:00 +0000 (10:17 +0000)
committerasterix <asterix@38d2e660-2303-0410-9eaa-f027e97ec537>
Tue, 20 Jul 2010 10:17:00 +0000 (10:17 +0000)
git-svn-id: https://src.develer.com/svnoss/bertos/branches/i2c@4035 38d2e660-2303-0410-9eaa-f027e97ec537

bertos/cpu/arm/drv/i2c_lpc2.c

index 4619e5376c7ebd2cc70e8efa9179c0aaa545918c..270f4c02bd11076fd1563fa2c7a1b2b46572429b 100644 (file)
 
 #include <io/lpc23xx.h>
 
-
-#define I2C_READBIT                      BV(0)
-
 /*
  *
  */
 #if 1
        /* I2C 0 */
-
        #define I2C_PCONP                    PCONP_PCI2C0
        #define I2C_CONSET                   I20CONSET
        #define I2C_CONCLR                   I20CONCLR
        #define I2C_SCLL                     I20SCLL
        #define I2C_STAT                     I20STAT
        #define I2C_DAT                      I20DAT
-       #define I2C_SDA_PINSEL_MASK          I2C_SDA0_PINSEL_MASK
-       #define I2C_SCL_PINSEL_MASK          I2C_SCL0_PINSEL_MASK
-       #define I2C_SDA_PINSEL               I2C_SDA0_PINSEL
-       #define I2C_SCL_PINSEL               I2C_SCL0_PINSEL
+       #define I2C_PINSEL_PORT              PINSEL1
+       #define I2C_PINSEL                   I2C0_PINSEL
+       #define I2C_PINSEL_MASK              I2C0_PINSEL_MASK
+       #define I2C_PCLKSEL                  PCLKSEL0
+       #define I2C_PCLK_MASK                I2C0_PCLK_MASK
+       #define I2C_PCLK_DIV8                I2C0_PCLK_DIV8
 #else
        /* I2C 1 */
+       #error
 #endif
 
-#define GET_STATUS()   (I2C_STAT)
+#define GET_STATUS()   ((uint8_t)I2C_STAT)
+/*
+ * Wait that SI bit is set.
+ *
+ * Note: this bit is set when the I2C state changes. However, entering
+ * state F8 does not set SI since there is nothing for an interrupt service
+ * routine to do in that case.
+ */
+#define WAIT_SI()           while( !(I2C_CONSET & BV(I2CON_SI)) )
 
 static uint8_t i2c_builtin_start(void)
 {
+       // Clear all pending flags.
+       I2C_CONCLR = BV(I2CON_STAC) | BV(I2CON_SIC) | BV(I2CON_AAC);
+
+       // Set start and ack bit.
        I2C_CONSET = BV(I2CON_STA) | BV(I2CON_AA);
 
-       while( !(I2C_CONSET & BV(I2CON_SI)) );
+       WAIT_SI();
 
        return true;
 }
@@ -102,8 +113,9 @@ bool i2c_builtin_start_w(uint8_t id)
        ticks_t start = timer_clock();
        while (i2c_builtin_start())
        {
-               uint32_t status = GET_STATUS();
+               uint8_t status = GET_STATUS();
 
+               /* Start status ok, set addres and the R/W bit */
                if ((status == I2C_STAT_SEND) || (status == I2C_STAT_RESEND))
                        I2C_DAT = id & ~I2C_READBIT;
 
@@ -113,7 +125,10 @@ bool i2c_builtin_start_w(uint8_t id)
                if (status == I2C_STAT_SLAW_ACK)
                        return true;
                else if (status == I2C_STAT_ARB_LOST)
+               {
+                       LOG_ERR("Arbitration lost\n");
                        break;
+               }
                else if (timer_clock() - start > ms_to_ticks(CONFIG_I2C_START_TIMEOUT))
                {
                        LOG_ERR("Timeout on I2C START\n");
@@ -135,22 +150,30 @@ bool i2c_builtin_start_r(uint8_t id)
 {
        if (i2c_builtin_start())
        {
-               uint32_t status = GET_STATUS();
+               uint8_t status = GET_STATUS();
 
+               /* Start status ok, set addres and the R/W bit */
                if ((status == I2C_STAT_SEND) || (status == I2C_STAT_RESEND))
                        I2C_DAT = id | I2C_READBIT;
 
                /* Clear the start bit and clear the SI bit */
                I2C_CONCLR = BV(I2CON_SIC) | BV(I2CON_STAC);
 
-               while( !(I2C_CONSET & BV(I2CON_SI)) );
+               WAIT_SI();
 
                status = GET_STATUS();
 
                if (status == I2C_STAT_SLAR_ACK)
                        return true;
+
+               else if (status == I2C_STAT_SLAR_ACK)
+               {
+                       LOG_ERR("SLAR NACK:%02x\n", status);
+               }
                else if (status == I2C_STAT_ARB_LOST)
-                       return false;
+               {
+                       LOG_ERR("ARB Lost:%02x\n", status);
+               }
 
        }
        return false;
@@ -159,7 +182,9 @@ bool i2c_builtin_start_r(uint8_t id)
 
 void i2c_builtin_stop(void)
 {
+       /* Set the stop bit */
        I2C_CONSET = BV(I2CON_STO);
+       /* Clear pending flags */
        I2C_CONCLR = BV(I2CON_STAC) | BV(I2CON_SIC) | BV(I2CON_AAC);
 }
 
@@ -183,33 +208,33 @@ int i2c_builtin_get(bool ack)
 bool i2c_send(const void *_buf, size_t count)
 {
        const uint8_t *buf = (const uint8_t *)_buf;
-       uint32_t status = 0;
+       uint8_t status = 0;
 
        while (count)
        {
                I2C_DAT = *buf++;
-               I2C_CONSET = BV(I2CON_AA);
                I2C_CONCLR = BV(I2CON_SIC);
                count--;
 
-               while( !(I2C_CONSET & BV(I2CON_SI)) );
+               WAIT_SI();
 
                status = GET_STATUS();
+
                if (status == I2C_STAT_DATA_ACK)
                        continue;
                else if (status == I2C_STAT_DATA_NACK)
                {
-                       LOG_ERR("send:%02x\n", (uint8_t)status);
+                       LOG_ERR("Data NACK\n");
                        return false;
                }
-               else if (status == 0xf8)
+               else if (status == I2C_STAT_ERROR)
                {
-                       LOG_ERR("send:%02x\n", (uint8_t)status);
+                       LOG_ERR("I2C error.\n");
                        return false;
                }
-               else if (status == 0x10)
+               else if (status == I2C_STAT_UNKNOW)
                {
-                       LOG_ERR("send:%02x\n", (uint8_t)status);
+                       LOG_ERR("I2C unable to read status.\n");
                        return false;
                }
 
@@ -226,11 +251,19 @@ bool i2c_recv(void *_buf, size_t count)
        uint8_t *buf = (uint8_t *)_buf;
        uint8_t status = GET_STATUS();
 
-//     LOG_ERR("recv:%02x\n", (uint8_t)status);
+       /* Ready for read */
+       I2C_CONSET = BV(I2CON_AA);
+       I2C_CONCLR = BV(I2CON_SIC);
+
+       WAIT_SI();
 
        while (count)
        {
                *buf++ = I2C_DAT;
+               /*
+                * Set ack bit if we want read more byte, otherwise
+                * we disable it
+                */
                if (count > 1)
                        I2C_CONSET = BV(I2CON_AA);
                else
@@ -239,25 +272,22 @@ bool i2c_recv(void *_buf, size_t count)
                I2C_CONCLR = BV(I2CON_SIC);
                count--;
 
-               while( !(I2C_CONSET & BV(I2CON_SI)) );
+               WAIT_SI();
 
                status = GET_STATUS();
 
                if (status == I2C_STAT_RDATA_ACK)
                        continue;
                else if (status == I2C_STAT_RDATA_NACK)
-               {
-               //      LOG_ERR("recv:%02x\n", (uint8_t)status);
                        return true;
-               }
-               else if (status == 0xf8)
+               else if (status == I2C_STAT_ERROR)
                {
-                       LOG_ERR("recv:%02x\n", (uint8_t)status);
+                       LOG_ERR("I2C error.\n");
                        return false;
                }
-               else if (status == 0x10)
+               else if (status == I2C_STAT_UNKNOW)
                {
-                       LOG_ERR("recv:%02x\n", (uint8_t)status);
+                       LOG_ERR("I2C unable to read status.\n");
                        return false;
                }
        }
@@ -285,8 +315,8 @@ void i2c_builtin_init(void)
         * Bit Frequency = Fplk / (I2C_I2SCLH + I2C_I2SCLL)
         * value of I2SCLH and I2SCLL must be different
         */
-       PCLKSEL0 &= ~I2C0_PCLK_MASK;
-       PCLKSEL0 |= I2C0_PCLK_DIV8;
+       I2C_PCLKSEL &= ~I2C_PCLK_MASK;
+       I2C_PCLKSEL |= I2C_PCLK_DIV8;
 
        I2C_SCLH = (((CPU_FREQ / 8) / CONFIG_I2C_FREQ) / 2) + 1;
        I2C_SCLL = (((CPU_FREQ / 8) / CONFIG_I2C_FREQ) / 2);
@@ -294,8 +324,8 @@ void i2c_builtin_init(void)
        ASSERT(I2C_SCLH > 4 || I2C_SCLL > 4);
 
        /* Assign pins to SCL and SDA (P0_27, P0_28) */
-       PINSEL1 &= ~I2C_PINSEL_MASK;
-       PINSEL1 |= I2C_PINSEL;
+       I2C_PINSEL_PORT &= ~I2C_PINSEL_MASK;
+       I2C_PINSEL_PORT |= I2C_PINSEL;
 
        // Enable I2C
        I2C_CONSET = BV(I2CON_I2EN);