mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

This library was superseded by mbed-dev - https://os.mbed.com/users/mbed_official/code/mbed-dev/.

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Revision:
409:a95c696104d3
Parent:
390:35c2c1cf29cd
Child:
422:a032ac66f24e
--- a/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/i2c_api.c	Wed Nov 19 08:45:06 2014 +0000
+++ b/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/i2c_api.c	Wed Nov 19 09:00:07 2014 +0000
@@ -61,17 +61,51 @@
     while (!(i2c_status(obj) & (1 << 5))) ;
 }
 
+static void i2c_reg_reset(i2c_t *obj) {
+    // full reset
+    REG(CR1.UINT8[0]) &= ~(1 << 7); // CR1.ICE off
+    REG(CR1.UINT8[0]) |=  (1 << 6); // CR1.IICRST on
+    REG(CR1.UINT8[0]) |=  (1 << 7); // CR1.ICE on
+
+    REG(MR1.UINT8[0])  =  0x08;  // P_phi /8  9bit (including Ack)
+    REG(SER.UINT8[0])  =  0x00;  // no slave addr enabled
+
+    // set default frequency at 100k
+    i2c_frequency(obj, 100000);
+
+    REG(MR2.UINT8[0])  =  0x07;
+    REG(MR3.UINT8[0])  =  0x00;
+
+    REG(FER.UINT8[0])  =  0x72;  // SCLE, NFE enabled, TMOT
+    REG(IER.UINT8[0])  =  0x00;  // no interrupt
+
+    REG(CR1.UINT32) &= ~(1 << 6); // CR1.IICRST negate reset
+}
+
 // Wait until the Trans Data Empty (TDRE) is set
 static int i2c_wait_TDRE(i2c_t *obj) {
     int timeout = 0;
 
     while (!(i2c_status(obj) & (1 << 7))) {
+        timeout ++;
         if (timeout > 100000) return -1;
     }
 
     return 0;
 }
 
+static inline int i2c_wait_TEND(i2c_t *obj) {
+    int timeout = 0;
+
+    while (!(i2c_status(obj) & (1 << 6))) {
+        timeout ++;
+        if (timeout > 100000) return -1;
+    }
+
+    return 0;
+}
+
+
 static inline void i2c_power_enable(i2c_t *obj) {
     volatile uint8_t dummy;
     switch ((int)obj->i2c) {
@@ -90,29 +124,13 @@
     obj->i2c = pinmap_merge(i2c_sda, i2c_scl);
     obj->dummy = 1;
     MBED_ASSERT((int)obj->i2c != NC);
-    
+
     // enable power
     i2c_power_enable(obj);
-    
-    // full reset
-    REG(CR1.UINT8[0]) &= ~(1 << 7); // CR1.ICE off
-    REG(CR1.UINT8[0]) |=  (1 << 6); // CR1.IICRST on
-    REG(CR1.UINT8[0]) |=  (1 << 7); // CR1.ICE on
-
-    REG(MR1.UINT8[0])  =  0x08;  // P_phi /8  9bit (including Ack)
-    REG(SER.UINT8[0])  =  0x00;  // no slave addr enabled
 
-    // set default frequency at 100k
-    i2c_frequency(obj, 100000);
-
-    REG(MR2.UINT8[0])  =  0x07; 
-    REG(MR3.UINT8[0])  =  0x00;
+    // full reset
+    i2c_reg_reset(obj);
 
-    REG(FER.UINT8[0])  =  0x72;  // SCLE, NFE enabled, TMOT
-    REG(IER.UINT8[0])  =  0x00;  // no interrupt
-
-    REG(CR1.UINT32) &= ~(1 << 6); // CR1.IICRST negate reset
-    
     pinmap_pinout(sda, PinMap_I2C_SDA);
     pinmap_pinout(scl, PinMap_I2C_SCL);
 }
@@ -127,11 +145,11 @@
 }
 
 inline int i2c_stop(i2c_t *obj) {
-    int timeout = 0;
+    volatile int timeout = 0;
 
     // write the stop bit
     REG(CR2.UINT32) |= (1 << 3);
-    
+
     // wait for SP bit to reset
     while(REG(CR2.UINT32) & (1 << 3)) {
         timeout ++;
@@ -159,91 +177,140 @@
         volatile int dummy = REG(DRR.UINT32);
         obj->dummy = 0;
     }
-    if (last) {
+
+    // wait for it to arrive
+    i2c_wait_RDRF(obj);
+
+    if (last == 2) {
+        /* this time is befor last byte read */
+        /* Set MR3 WATI bit is 1 */;
+        REG(MR3.UINT32) |= (1 << 6);
+    } else if (last == 1) {
         // send a NOT ACK
-        REG(MR2.UINT32) |=  (1 <<6);
+        REG(MR3.UINT32) |=  (1 <<3);
     } else {
         // send a ACK
-        REG(MR2.UINT32) &= ~(1 <<6);
+        REG(MR3.UINT32) &= ~(1 <<3);
     }
-    // wait for it to arrive
-    i2c_wait_RDRF(obj);
-    
+
     // return the data
     return (REG(DRR.UINT32) & 0xFF);
 }
 
 void i2c_frequency(i2c_t *obj, int hz) {
     uint32_t PCLK = 6666666;
-    
+
     uint32_t pulse = PCLK / (hz * 2);
-    
+
     // I2C Rate
     REG(BRL.UINT32) = pulse;
     REG(BRH.UINT32) = pulse;
 }
 
 int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
-    int count, status;
-    
+    int count = 0;
+    int status;
+    int value;
+    volatile uint32_t work_reg = 0;
+
+
+    // full reset
+    i2c_reg_reset(obj);
+
     status = i2c_start(obj);
-    
+
     if (status == 0xff) {
         i2c_stop(obj);
         return I2C_ERROR_BUS_BUSY;
     }
-    
+
     status = i2c_do_write(obj, (address | 0x01));
     if (status & 0x01) {
         i2c_stop(obj);
         return I2C_ERROR_NO_SLAVE;
     }
-
-    // Read in all except last byte
-    for (count = 0; count < (length - 1); count++) {
-        int value = i2c_do_read(obj, 0);
-        status = i2c_status(obj);
-        if (status & 0x10) {
-            i2c_stop(obj);
-            return count;
-        }
-        data[count] = (char) value;
+    
+    /* wati RDRF */
+    i2c_wait_RDRF(obj);
+    /* check ACK/NACK */
+    if ((REG(SR2.UINT32) & (1 << 4) == 1)) {
+        /* Slave sends NACK */
+        i2c_stop(obj);
+        return I2C_ERROR_NO_SLAVE;
     }
     
+    // Read in all except last byte
+    if (length > 1) {
+        for (count = 0; count < (length - 1); count++) {
+            if (count == (length - 2)) {
+                value = i2c_do_read(obj, 1);
+            } else if ((length >= 3) && (count == (length - 3))) {
+                value = i2c_do_read(obj, 2);
+            } else {
+                value = i2c_do_read(obj, 0);
+            }
+            status = i2c_status(obj);
+            if (status & 0x10) {
+                i2c_stop(obj);
+                return count;
+            }
+            data[count] = (char) value;
+        }
+    }
+
     // read in last byte
-    int value = i2c_do_read(obj, 1);
+    i2c_wait_RDRF(obj);
+    /* RIICnSR2.STOP = 0 */
+    REG(SR2.UINT32) &= ~(1 << 3);
+    /* RIICnCR2.SP   = 1 */
+    REG(CR2.UINT32) |= (1 << 3);
+    /* RIICnDRR read */
+    value = REG(DRR.UINT32) & 0xFF;
+    /* RIICnMR3.WAIT = 0 */
+    REG(MR3.UINT32) &= ~(1 << 6);
+    /* wait SR2.STOP = 1 */
+    while ((work_reg & (1 << 3)) == (1 << 3)) {
+        work_reg = REG(SR2.UINT32);
+    }
+    /* SR2.NACKF = 0 */
+    REG(SR2.UINT32) &= ~(1 << 4);
+    /* SR2.STOP  = 0 */
+    REG(SR2.UINT32) &= ~(1 << 3);
     status = i2c_status(obj);
     if (status & 0x10) {
         i2c_stop(obj);
         return length - 1;
     }
-    
+
     data[count] = (char) value;
-    
+
     // If not repeated start, send stop.
     if (stop) {
         i2c_stop(obj);
     }
-    
+
     return length;
 }
 
 int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
     int i, status;
-    
+
+    // full reset
+    i2c_reg_reset(obj);
+
     status = i2c_start(obj);
-    
+
     if ((status == 0xff)) {
         i2c_stop(obj);
         return I2C_ERROR_BUS_BUSY;
     }
-    
+
     status = i2c_do_write(obj, address);
     if (status & 0x10) {
         i2c_stop(obj);
         return I2C_ERROR_NO_SLAVE;
     }
-    
+
     for (i=0; i<length; i++) {
         status = i2c_do_write(obj, data[i]);
         if(status & 0x10) {
@@ -251,12 +318,14 @@
             return i;
         }
     }
-    
+
+    i2c_wait_TEND(obj);
+
     // If not repeated start, send stop.
     if (stop) {
         i2c_stop(obj);
     }
-    
+
     return length;
 }
 
@@ -276,7 +345,7 @@
     } else {
         ack = 1;
     }
-    
+
     return ack;
 }
 
@@ -291,7 +360,7 @@
 int i2c_slave_receive(i2c_t *obj) {
     int status;
     int retval;
-    
+
     status = i2c_addressed(obj);
     switch(status) {
         case 0x3: retval = 1; break;
@@ -299,7 +368,7 @@
         case 0x1: retval = 3; break;
         default : retval = 1; break;
     }
-    
+
     return(retval);
 }
 
@@ -311,7 +380,7 @@
         volatile int dummy = REG(DRR.UINT32) ;
         obj->dummy = 0;
     }
-    
+
     do {
         i2c_wait_RDRF(obj);
         status = i2c_status(obj);
@@ -320,35 +389,35 @@
         }
         count++;
     } while ( !(status & 0x10)  && (count < length) );
-    
+
     if(status & 0x10) {
         i2c_stop(obj);
     }
-    
+
     //i2c_clear_TDRE(obj);
-    
+
     return count;
 }
 
 int i2c_slave_write(i2c_t *obj, const char *data, int length) {
     int count = 0;
     int status;
-    
+
     if(length <= 0) {
         return(0);
     }
-    
+
     do {
         status = i2c_do_write(obj, data[count]);
         count++;
     } while ((count < length) && !(status & 0x10));
-    
+
     if (!(status & 0x10)) {
         i2c_stop(obj);
     }
-    
+
     i2c_clear_TDRE(obj);
-    
+
     return(count);
 }