I2CRTOS Driver by Helmut Schmücker. Removed included mbed-rtos library to prevent multiple definition. Make sure to include mbed-rtos library in your program!

Fork of I2cRtosDriver by Helmut Schmücker

Files at this revision

API Documentation at this revision

Comitter:
humlet
Date:
Thu May 09 20:52:07 2013 +0000
Parent:
10:e3d6c92ff222
Child:
12:6ddadcbbdca2
Commit message:
seem to work without tweaked mbed lib

Changed in this revision

I2CDriver.cpp Show annotated file Show diff for this revision Revisions of this file
I2CDriverTest02.h Show annotated file Show diff for this revision Revisions of this file
I2CDriverTest04.h Show annotated file Show diff for this revision Revisions of this file
i2cRtos_api.c Show annotated file Show diff for this revision Revisions of this file
mbed-NXP.lib Show diff for this revision Revisions of this file
mbed-src.lib Show diff for this revision Revisions of this file
--- a/I2CDriver.cpp	Wed May 08 19:22:45 2013 +0000
+++ b/I2CDriver.cpp	Thu May 09 20:52:07 2013 +0000
@@ -24,7 +24,7 @@
         else error("I2CDriver: Invalid I2C pins selected\n");
 
     if(s_channels[channel]==0) {
-        new Thread(threadFun,(void *)channel,osPriorityRealtime,512);  // evillive
+        new Thread(threadFun,(void *)channel,osPriorityRealtime,1024);  // evillive
     }
     m_channel = s_channels[channel];
 }
@@ -79,12 +79,9 @@
                 tr.ret = i2cRtos_read(&i2c, tr.adr, tr.dta, tr.len, (tr.rep?0:1));
                 break;
             case READ_MST_REG:
-                //printf("drv00\n");
                 tr.ret = i2cRtos_write(&i2c, tr.adr,(const char*)&(tr.reg), 1, 0);
-                //printf("drv01\n");
                 if(tr.ret)break; // error => bail out
                 tr.ret = i2cRtos_read(&i2c, tr.adr, tr.dta, tr.len, (tr.rep?0:1));
-                //printf("drv02\n");
                 break;
             case READ_SLV:
                 tr.ret = i2cRtos_slave_read(&i2c, tr.dta, tr.len);
@@ -119,7 +116,7 @@
     m_callerID = osThreadGetId();
     m_callerPrio = osThreadGetPriority(m_callerID);
     m_channel->mutex.lock(osWaitForever);
-    osThreadSetPriority(m_callerID, c_drvPrio); // hopefully not interrupted since the lock
+    osThreadSetPriority(m_callerID, c_drvPrio); // evillive hopefully not interrupted since the lock
 }
 
 void I2CDriver::unlock()
--- a/I2CDriverTest02.h	Wed May 08 19:22:45 2013 +0000
+++ b/I2CDriverTest02.h	Thu May 09 20:52:07 2013 +0000
@@ -4,10 +4,10 @@
 #include "I2CSlaveRtos.h"
 
 const int freq = 400000;
-const int adr = 42;
-const int len=42;
-const char* mstMsg="We are mbed, resistance is futile";
-const char* slvMsg="Fine with me, let's get addicted";
+const int adr = 42<<1;
+const int len=34;
+const char mstMsg[len]="We are mbed, resistance is futile";
+const char slvMsg[len]="Fine with me, let's get addicted ";
 
 static void slvRxMsg(I2CSlaveRtos& slv)
 {
--- a/I2CDriverTest04.h	Wed May 08 19:22:45 2013 +0000
+++ b/I2CDriverTest04.h	Thu May 09 20:52:07 2013 +0000
@@ -3,7 +3,7 @@
 #include "I2CMasterRtos.h"
 #include "stdint.h"
 
-DigitalOut osci(p16);
+//DigitalOut osci(p16);
 
 volatile int g_disco=0;
 volatile int g_len=0;
@@ -27,7 +27,7 @@
     config(i2c);
 
     while(true) {
-        osci.write(0);
+        //osci.write(0);
         i2c.frequency(g_freq);
         Thread::signal_wait(1<<5,osWaitForever);
         // read back srf08 echo times (1+16 words)
@@ -38,7 +38,7 @@
 
         uint32_t dt=us_ticker_read()-t1;
         if(stat!=0) {
-            osci.write(1);
+            //osci.write(1);
             printf("\n%x %d %d %d\n",stat,g_freq,g_len,dt);
             exit(0);
         }
--- a/i2cRtos_api.c	Wed May 08 19:22:45 2013 +0000
+++ b/i2cRtos_api.c	Thu May 09 20:52:07 2013 +0000
@@ -11,7 +11,7 @@
 #define I2C_DAT(x)          (x->i2c->I2DAT)
 
 #include "gpio_api.h"
-gpio_t gpio; // evillive
+static gpio_t gpio[2]; // evillive
 
 enum I2cIsrCmd {
     readMst,
@@ -23,7 +23,6 @@
 struct I2cIsrTransfer {
     i2c_t* obj;
     enum I2cIsrCmd cmd;
-    int adr;
     int len;
     int cnt;
     int stat;
@@ -35,7 +34,6 @@
 
 struct IsrIrqSem {
     IRQn_Type irq;
-    //uint32_t isr;
     osSemaphoreId sem;
 };
 static struct IsrIrqSem isrIrqSem[2];
@@ -65,111 +63,85 @@
     return I2C_STAT(obj);
 }
 
-
 // ISR stuff
 static void i2cRtos_isr(uint32_t ch)
 {
-    //printf("isr01\n");
-    volatile struct I2cIsrTransfer* tr=&(i2c_transfer[ch]);
-
-    if(tr->cmd==waitSI) {
+    struct I2cIsrTransfer* tr=&(i2c_transfer[ch]);
+    if(tr->cmd==waitSI){
         osSemaphoreRelease(isrIrqSem[ch].sem);
         NVIC_DisableIRQ(isrIrqSem[ch].irq);
         return;
     }
-
     int stat=i2c_status(tr->obj);
     int stay = 0;
-
     switch(tr->cmd) {
-        case readMst: {
-            int cnt = (tr->cnt)++;
-            if(cnt==-1) {
-                if(stat==0x40) {
-                    if(cnt != tr->len-2) {
+        case readMst:
+            switch(stat) {
+                case 0x50:
+                    (tr->rData)[tr->cnt] = (char)(I2C_DAT(tr->obj) & 0xff);
+                case 0x40:
+                    ++(tr->cnt);
+                    if(tr->cnt != tr->len-1)
                         i2c_conset(tr->obj, 0, 0, 0, 1);
-                    } else {
+                    else
                         i2c_conclr(tr->obj, 0, 0, 0, 1);
-                    }
                     stay = 1;
-                }
-            } else if(cnt < tr->len-1) {
-                if(stat==0x50) {
-                    (tr->rData)[cnt] = (char)(I2C_DAT(tr->obj) & 0xff);
-                    if(cnt != tr->len-2) {
-                        i2c_conset(tr->obj, 0, 0, 0, 1);
-                    } else {
-                        i2c_conclr(tr->obj, 0, 0, 0, 1);
-                    }
-                    stay = 1;
-                }
-            } else {
-                if(stat==0x58) {
-                    (tr->rData)[cnt] = (char)(I2C_DAT(tr->obj) & 0xff);
-                    stat = 0;
-                }
+                    break;
+                case 0x58:
+                    (tr->rData)[tr->cnt] = (char)(I2C_DAT(tr->obj) & 0xff);
+                    stat=0;
+                    break;
             }
             break;
-        }
-        case writeMst: {
-            int cnt = ++(tr->cnt);
-            if(cnt==0) {
-                if(stat==0x18) {
-                    I2C_DAT(tr->obj) = (tr->wData)[cnt];
-                    stay = 1;
-                }
-            } else if(cnt < tr->len) {
-                if(stat==0x28) {
-                    I2C_DAT(tr->obj) = (tr->wData)[cnt];
-                    stay = 1;
-                }
-            } else {
-                if(stat==0x28) {
-                    stat = 0;
-                }
+        case writeMst:
+            switch(stat) {
+                case 0x18:
+                case 0x28:
+                    if(++(tr->cnt)!=tr->len) { // evillive
+                        I2C_DAT(tr->obj) = (tr->wData)[tr->cnt];
+                        stay=1;
+                    } else {
+                        stat=0;
+                    }
             }
             break;
-        }
-        case readSlv: {
-            int cnt = ++(tr->cnt);
+        case readSlv:
+            ++(tr->cnt);
             if(stat==0x80 || stat==0x90)
-                (tr->rData)[cnt] = I2C_DAT(tr->obj) & 0xFF;
-            stay = (stat==0x80 || stat==0x90 || stat==0x060 || stat==0x70) && (cnt < tr->len-1);
+                (tr->rData)[tr->cnt] = I2C_DAT(tr->obj) & 0xFF;
+            stay = (stat==0x80 || stat==0x90 || stat==0x060 || stat==0x70) && (tr->cnt < tr->len-1);
             break;
-        }
-        case writeSlv: {
-            int cnt = ++(tr->cnt);
-            stay = cnt<tr->len && stat==0xb8;
+        case writeSlv:
+            ++(tr->cnt);
+            stay = tr->cnt<tr->len && stat==0xb8;
             if(stay)
-                I2C_DAT(tr->obj) = tr->wData[cnt];
+                I2C_DAT(tr->obj) = tr->wData[tr->cnt];
             break;
-        }
-        default:
-            error("Dial911 i2cRtos_isr\n");
     }
     if(stay) {
         i2c_clear_SI(tr->obj);
     } else {
-        //i2c_clear_SI(tr->obj);
         tr->stat = stat;
         osSemaphoreRelease(isrIrqSem[ch].sem);
         NVIC_DisableIRQ(isrIrqSem[ch].irq);
     }
 }
-void static i2cRtos_isr_ch0() // evillive
+static void i2cRtos_isr_ch0()
 {
+    //gpio_write(&gpio[0], 1);
     i2cRtos_isr(0);
+    //gpio_write(&gpio[0], 0);
 }
-void static i2cRtos_isr_ch1()
+static void i2cRtos_isr_ch1()
 {
-    gpio_write(&gpio, 1);
+    //gpio_write(&gpio[1], 1);
     i2cRtos_isr(1);
-    gpio_write(&gpio, 0);
+    //gpio_write(&gpio[1], 0);
 }
 
 
 // determine channel
-static inline uint32_t i2c_get_channel(i2c_t *obj)
+static inline uint32_t i2c_get_channel(const i2c_t *obj)
 {
 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
     switch((I2CName)(obj->i2c)) {
@@ -180,117 +152,72 @@
         default:
             error("Dial911 i2c_get_channel: Invaid I2CName \n");
     }
-#elif defined(TARGET_LPC11U24)
-    return 1;
-#else
-#error "Dial911 i2c_get_channel: Unsupported HW"
 #endif
     return 1;
 }
 
 
 // wait for ISR finished
-static inline void i2cRtos_wait_and_see(i2c_t *obj, int channel, uint32_t tmOut)
+static void i2cRtos_wait_and_see(i2c_t *obj, int ch, uint32_t tmOut)  //evillive
 {
-    struct IsrIrqSem* iis = &(isrIrqSem[channel]);
-    gpio_write(&gpio, 1);
+    struct IsrIrqSem* iis = &(isrIrqSem[ch]);
     __disable_irq();
     i2c_clear_SI(obj);
-    NVIC_ClearPendingIRQ(iis->irq);  // evillive
+    NVIC_ClearPendingIRQ(iis->irq);
     NVIC_EnableIRQ(iis->irq);
     __enable_irq();
-    gpio_write(&gpio, 0);
-    if(osSemaphoreWait(iis->sem, tmOut)!=1) {
-        NVIC_DisableIRQ(iis->irq);
-        printf("Ouch!\n");
-    }
+    if(osSemaphoreWait(iis->sem, tmOut)!=1) NVIC_DisableIRQ(iis->irq);
+}
+
+static inline void i2cRtos_waitSI(i2c_t *obj, uint32_t tmOut){
+    int ch = i2c_get_channel(obj);
+    i2c_transfer[ch].cmd = waitSI;
+    i2cRtos_wait_and_see(obj, ch, tmOut);
 }
 
 
-// setup semaphores and hook in ISRs
-void i2cRtos_init(i2c_t *obj, PinName sda, PinName scl)
-{
-    gpio_init(&gpio, p15, PIN_OUTPUT);
-
-    i2c_init(obj,sda,scl);
-    uint32_t ch = i2c_get_channel(obj);
-#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
-    static osSemaphoreDef(i2cIsrDrvSem_ch0);
-    static osSemaphoreDef(i2cIsrDrvSem_ch1);
-    switch(ch) {
-        case 0:
-            isrIrqSem[ch].irq = I2C1_IRQn;
-            //isrIrqSem[ch].isr = (uint32_t)i2cRtos_isr_ch0;
-            NVIC_SetVector(I2C1_IRQn, (uint32_t)i2cRtos_isr_ch0);
-            isrIrqSem[ch].sem = osSemaphoreCreate(osSemaphore(i2cIsrDrvSem_ch0), 1);
-            osSemaphoreWait(isrIrqSem[ch].sem, osWaitForever);
-            break;
-        case 1:
-            //printf("apicfg\n");
-            isrIrqSem[ch].irq = I2C2_IRQn;
-            //isrIrqSem[ch].isr = (uint32_t)i2cRtos_isr_ch1;
-            NVIC_SetVector(I2C2_IRQn, (uint32_t)i2cRtos_isr_ch1);
-            //NVIC_DisableIRQ(I2C2_IRQn);
-            isrIrqSem[ch].sem = osSemaphoreCreate(osSemaphore(i2cIsrDrvSem_ch1), 1);
-            osSemaphoreWait(isrIrqSem[ch].sem, osWaitForever);
-            break;
-    }
-#elif defined(TARGET_LPC11U24)
-    static osSemaphoreDef(i2cIsrDrvSem_ch1);
-    isrIrqSem[ch].irq = I2C_IRQn;
-    //isrIrqSem[ch].isr = (uint32_t)i2cRtos_isr_ch1;
-    NVIC_SetVector(I2C_IRQn, (uint32_t)i2cRtos_isr_ch1);
-    isrIrqSem[ch].sem = osSemaphoreCreate(osSemaphore(i2cIsrDrvSem_ch1), 1);
-    osSemaphoreWait(isrIrqSem[ch].sem, osWaitForever);
-#else
-#error "Dial911 i2cRtos_init: Unsupported HW"
-#endif
-}
-
 int i2cRtos_read(i2c_t *obj, int address, char *data, int length, int stop)
 {
-    gpio_write(&gpio, 1);
-    int status = i2c_start(obj);
-    if ((status != 0x10) && (status != 0x08)) {
+    gpio_write(&gpio[1], 1);
+    int stat = i2c_start(obj);
+    if ((stat != 0x10) && (stat != 0x08)) {
         i2c_stop(obj);
-        //printf("start Ouch read\n");
-        return status;
+        return stat;
     }
-    gpio_write(&gpio, 0);
+    gpio_write(&gpio[1], 0);
     int ch = i2c_get_channel(obj);
-    volatile struct I2cIsrTransfer* tr = &(i2c_transfer[ch]); // evilive fill it locally and then copy it in one go to (volatile) mem?
+     struct I2cIsrTransfer* tr = &(i2c_transfer[ch]); // evilive fill it locally and then copy it in one go to (volatile) mem?
     tr->obj=obj;
     tr->cmd=readMst;
     tr->len=length;
     tr->cnt=-1;
     tr->rData=data;
     I2C_DAT(obj) = address | 0x01;
-    i2cRtos_wait_and_see(obj, ch,2);// 1+(length>>2));  // timeout (1+len/4)ms
-    status = tr->stat;
-    if(status || stop) i2c_stop(obj);
-    return status;
+    i2cRtos_wait_and_see(obj, ch,2+(length>>2));  // timeout (2+len/4)ms
+    stat = tr->stat;
+    if(stat || stop) i2c_stop(obj);
+    return stat;
 }
 
 int i2cRtos_write(i2c_t *obj, int address, const char *data, int length, int stop)
 {
+    gpio_write(&gpio[1], 1);
     int status = i2c_start(obj);
     if ((status != 0x10) && (status != 0x08)) {
         i2c_stop(obj);
-        printf("start Ouch write\n");
         return status;
     }
+    gpio_write(&gpio[1], 0);
     int ch = i2c_get_channel(obj);
-    volatile struct I2cIsrTransfer* tr = &(i2c_transfer[ch]); // evilive fill it locally and then copy it in one go to (volatile) mem?
+     struct I2cIsrTransfer* tr = &(i2c_transfer[ch]); // evilive fill it locally and then copy it in one go to (volatile) mem?
     tr->obj=obj;
     tr->cmd=writeMst;
     tr->len=length;
     tr->cnt=-1;
     tr->wData=data;
     I2C_DAT(obj) = address & 0xfe;
-    //printf("api01\n");
-    i2cRtos_wait_and_see(obj, ch,2);// 2+(length>>2));  // timeout (1+len/4)ms
-    //printf("api02\n");
-    //i2c_clear_SI(obj); // ... why? Also in official lib
+    i2cRtos_wait_and_see(obj, ch, 2+(length>>2));  // timeout (2+len/4)ms
+    i2c_clear_SI(obj); // ... why? Also in official lib ... I guess this is the "write instead of start" bug
     status = tr->stat;
     if(status || stop) i2c_stop(obj);
     return status;
@@ -303,19 +230,14 @@
     } else {
         i2c_conset(obj, 0, 0, 0, 1); // send a ACK
     }
-    int ch = i2c_get_channel(obj);
-    i2c_transfer[ch].cmd = waitSI;
-    i2cRtos_wait_and_see(obj, ch, 2);
+    i2cRtos_waitSI(obj, 2);
     return (I2C_DAT(obj) & 0xff);
-
 }
 
 int i2cRtos_byte_write(i2c_t *obj, int data)
 {
     I2C_DAT(obj) = (data & 0xff);
-    int ch = i2c_get_channel(obj);
-    i2c_transfer[ch].cmd = waitSI;
-    i2cRtos_wait_and_see(obj, ch, 2);
+    i2cRtos_waitSI(obj, 2);
     int stat=i2c_status(obj);
     return (stat==0x18 || stat==0x28 || stat==0x40 || stat==0xb8);
 }
@@ -329,11 +251,8 @@
     int retval = i2c_slave_receive(obj);
     //check for pending requests
     if(retval)return retval; // there is one => bail out
-
     // No request? Wait for it!
-    int ch = i2c_get_channel(obj);
-    i2c_transfer[ch].cmd = waitSI;
-    i2cRtos_wait_and_see(obj, ch, tmOut);
+    i2cRtos_waitSI(obj, tmOut);
     // check again for pending requests
     return i2c_slave_receive(obj);
 }
@@ -341,7 +260,7 @@
 int i2cRtos_slave_read(i2c_t *obj, char *data, int length)
 {
     int ch = i2c_get_channel(obj);
-    volatile struct I2cIsrTransfer* tr = &(i2c_transfer[ch]); // evilive fill it locally and then copy it in one go to (volatile) mem?
+     struct I2cIsrTransfer* tr = &(i2c_transfer[ch]); // evilive fill it locally and then copy it in one go to (volatile) mem?
     tr->obj=obj;
     tr->cmd=readSlv;
     tr->len=length;
@@ -351,7 +270,7 @@
     if(tr->stat != 0xa0) {
         i2c_stop(obj);
     }
-    i2c_clear_SI(obj); // ... why? Also in official lib
+    i2c_clear_SI(obj); // ... why? Also in official lib ... stops keeping scl low
     return tr->cnt;    // same weird return as in official lib
 }
 
@@ -361,21 +280,62 @@
         return(0);
     }
     int ch = i2c_get_channel(obj);
-    volatile struct I2cIsrTransfer* tr = &(i2c_transfer[ch]); // evilive fill it locally and then copy it in one go to (volatile) mem?
+     struct I2cIsrTransfer* tr = &(i2c_transfer[ch]); // evilive fill it locally and then copy it in one go to (volatile) mem?
     tr->obj=obj;
     tr->cmd=writeSlv;
     tr->len=length;
     tr->cnt=0;
     tr->wData=data;
     I2C_DAT(obj) = data[0];
-    i2cRtos_wait_and_see(obj, ch, 1+(length>>2));  // timeout (1+len/4)ms
+    i2cRtos_wait_and_see(obj, ch, 2+(length>>2));  // timeout (1+len/4)ms
     int status = tr->stat;
     if(status!=0xC0 && status!=0xC8) {
         i2c_stop(obj);
     }
-    i2c_clear_SI(obj); // ... why? Also in official lib
+    i2c_clear_SI(obj); // ... why? Also in official lib ... stops keeping scl low
     return tr->cnt;
 }
 
+
+// setup semaphores and hook in ISRs
+void i2cRtos_init(i2c_t *obj, PinName sda, PinName scl)
+{
+    static int called=0;
+    if(!called) {
+        gpio_init(&gpio[0], p15, PIN_OUTPUT);
+        gpio_init(&gpio[1], p16, PIN_OUTPUT);
+    }
+    called = 1;
+    gpio_write(&gpio[0], 0);
+    gpio_write(&gpio[1], 0);
+
+    i2c_init(obj,sda,scl);
+    uint32_t ch = i2c_get_channel(obj);
+#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
+    static osSemaphoreDef(i2cIsrDrvSem_ch0);
+    static osSemaphoreDef(i2cIsrDrvSem_ch1);
+    switch(ch) {
+        case 0:
+            isrIrqSem[ch].irq = I2C1_IRQn;
+            NVIC_SetVector(I2C1_IRQn, (uint32_t)i2cRtos_isr_ch0);
+            isrIrqSem[ch].sem = osSemaphoreCreate(osSemaphore(i2cIsrDrvSem_ch0), 1);
+            break;
+        case 1:
+            isrIrqSem[ch].irq = I2C2_IRQn;
+            NVIC_SetVector(I2C2_IRQn, (uint32_t)i2cRtos_isr_ch1);
+            isrIrqSem[ch].sem = osSemaphoreCreate(osSemaphore(i2cIsrDrvSem_ch1), 1);
+            break;
+    }
+    osSemaphoreWait(isrIrqSem[ch].sem, osWaitForever);
+#elif defined(TARGET_LPC11U24)
+    static osSemaphoreDef(i2cIsrDrvSem_ch1);
+    isrIrqSem[ch].irq = I2C_IRQn;
+    NVIC_SetVector(I2C_IRQn, (uint32_t)i2cRtos_isr_ch1);
+    isrIrqSem[ch].sem = osSemaphoreCreate(osSemaphore(i2cIsrDrvSem_ch1), 1);
+    osSemaphoreWait(isrIrqSem[ch].sem, osWaitForever);
+#else
+#error "Dial911 i2cRtos_init: Unsupported HW"
+#endif
+}
 #endif
 #endif
--- a/mbed-NXP.lib	Wed May 08 19:22:45 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://mbed.org/users/humlet/code/mbed-NXP/#692b566d83bf
--- a/mbed-src.lib	Wed May 08 19:22:45 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://mbed.org/users/humlet/code/mbed-src/#49923059ddc8