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:
Wed May 08 19:22:45 2013 +0000
Parent:
9:65aae53a34de
Child:
11:8c1d44595620
Commit message:
less smoke, actually it seems to work

Changed in this revision

I2CDriver.cpp 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
--- a/I2CDriver.cpp	Sat May 04 16:47:56 2013 +0000
+++ b/I2CDriver.cpp	Wed May 08 19:22:45 2013 +0000
@@ -79,10 +79,12 @@
                 tr.ret = i2cRtos_read(&i2c, tr.adr, tr.dta, tr.len, (tr.rep?0:1));
                 break;
             case READ_MST_REG:
-                //printf("Disco\n");
+                //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);
--- a/I2CDriverTest04.h	Sat May 04 16:47:56 2013 +0000
+++ b/I2CDriverTest04.h	Wed May 08 19:22:45 2013 +0000
@@ -3,6 +3,8 @@
 #include "I2CMasterRtos.h"
 #include "stdint.h"
 
+DigitalOut osci(p16);
+
 volatile int g_disco=0;
 volatile int g_len=0;
 volatile int g_freq=100000;
@@ -18,20 +20,28 @@
 
 void highPrioThreadFun(void const *args)
 {
+    //printf("tst01\n");
     i2cDrvThrdID = Thread::gettid();
     I2CMasterRtos i2c(p28, p27);
-    
+    //printf("tst02\n");
     config(i2c);
 
     while(true) {
+        osci.write(0);
         i2c.frequency(g_freq);
         Thread::signal_wait(1<<5,osWaitForever);
         // read back srf08 echo times (1+16 words)
         const char reg= 0x3a;
         char result[64];
         uint32_t t1=us_ticker_read();
-        i2c.read(i2cAdr, reg, result, g_len);
+        int stat = i2c.read(i2cAdr, reg, result, g_len);
+
         uint32_t dt=us_ticker_read()-t1;
+        if(stat!=0) {
+            osci.write(1);
+            printf("\n%x %d %d %d\n",stat,g_freq,g_len,dt);
+            exit(0);
+        }
         uint16_t tm=((static_cast<uint16_t>(result[0])<<8)|static_cast<uint16_t>(result[1]));
 
         if(--g_disco>0) printf("tm=%8d dt=%4dus\n",tm,dt);
@@ -45,11 +55,11 @@
 
     Thread::wait(100);
     highPrioTicker.start(1);
-    
+
 #if defined(TARGET_LPC1768)
     const int nTest=7;
     const int freq[nTest]=  {1e5,   1e5,    1e5,   4e5,    4e5,    4e5,    4e5};
-    const int len[nTest]=   {1,     4,      6,      1,     6,     12,      30};
+    const int len[nTest]=   {1,     4,      6,      1,     6,     12,      36};
 #elif defined(TARGET_LPC11U24)
     const int nTest=5;
     const int freq[nTest]=  {1e5,   1e5,    4e5,   4e5,    4e5    };
@@ -81,9 +91,11 @@
 }
 
 void readModWrite(I2CMasterRtos& i2c, uint8_t reg, uint8_t dta)
-{   
+{
+    //printf("rmw01\n");
     char rd1;
     int rStat1 = i2c.read(i2cAdr, reg, &rd1, 1);
+    //printf("rmw02\n");
     char data[2];
     data[0]=(char)reg;
     data[1]=(char)dta;
@@ -107,7 +119,7 @@
     regs[cnt]=0x19;
     vals[cnt++]=0;  // sample rate divider reg  // sapmle rate = gyro rate / (1+x)
     regs[cnt]=0x1a;
-    vals[cnt++]=0;// conf  reg // no ext frame sync / no dig low pass set to 1 => 8kHz Sampling 
+    vals[cnt++]=0;// conf  reg // no ext frame sync / no dig low pass set to 1 => 8kHz Sampling
     regs[cnt]=0x1b;
     vals[cnt++]=0;// gyro conf  reg // no test mode and gyro range 250°/s
     regs[cnt]=0x1c;
--- a/i2cRtos_api.c	Sat May 04 16:47:56 2013 +0000
+++ b/i2cRtos_api.c	Wed May 08 19:22:45 2013 +0000
@@ -10,6 +10,9 @@
 #define I2C_STAT(x)         (x->i2c->I2STAT)
 #define I2C_DAT(x)          (x->i2c->I2DAT)
 
+#include "gpio_api.h"
+gpio_t gpio; // evillive
+
 enum I2cIsrCmd {
     readMst,
     writeMst,
@@ -27,12 +30,12 @@
     char* rData;
     const char* wData;
 };
-volatile static struct I2cIsrTransfer i2c_transfer[2];  // evillive: dare to get rid of volatile?
+static struct I2cIsrTransfer i2c_transfer[2];  // evillive: dare to get rid of volatile?
 
 
 struct IsrIrqSem {
     IRQn_Type irq;
-    uint32_t isr;
+    //uint32_t isr;
     osSemaphoreId sem;
 };
 static struct IsrIrqSem isrIrqSem[2];
@@ -64,8 +67,9 @@
 
 
 // ISR stuff
-static inline void i2cRtos_isr(uint32_t ch)
+static void i2cRtos_isr(uint32_t ch)
 {
+    //printf("isr01\n");
     volatile struct I2cIsrTransfer* tr=&(i2c_transfer[ch]);
 
     if(tr->cmd==waitSI) {
@@ -82,7 +86,11 @@
             int cnt = (tr->cnt)++;
             if(cnt==-1) {
                 if(stat==0x40) {
-                    i2c_conset(tr->obj, 0, 0, 0, 1);
+                    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(cnt < tr->len-1) {
@@ -142,18 +150,21 @@
     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);
     }
 }
-static inline void i2cRtos_isr_ch0()
+void static i2cRtos_isr_ch0() // evillive
 {
     i2cRtos_isr(0);
 }
-static inline void i2cRtos_isr_ch1()
+void static i2cRtos_isr_ch1()
 {
+    gpio_write(&gpio, 1);
     i2cRtos_isr(1);
+    gpio_write(&gpio, 0);
 }
 
 
@@ -172,9 +183,9 @@
 #elif defined(TARGET_LPC11U24)
     return 1;
 #else
-    #error "Dial911 i2c_get_channel: Unsupported HW"
+#error "Dial911 i2c_get_channel: Unsupported HW"
 #endif
-return 1;
+    return 1;
 }
 
 
@@ -182,16 +193,25 @@
 static inline void i2cRtos_wait_and_see(i2c_t *obj, int channel, uint32_t tmOut)
 {
     struct IsrIrqSem* iis = &(isrIrqSem[channel]);
-    //NVIC_ClearPendingIRQ(iis->irq);  // evillive
+    gpio_write(&gpio, 1);
+    __disable_irq();
     i2c_clear_SI(obj);
+    NVIC_ClearPendingIRQ(iis->irq);  // evillive
     NVIC_EnableIRQ(iis->irq);
-    if(osSemaphoreWait(iis->sem, tmOut)!=1) NVIC_DisableIRQ(iis->irq);
+    __enable_irq();
+    gpio_write(&gpio, 0);
+    if(osSemaphoreWait(iis->sem, tmOut)!=1) {
+        NVIC_DisableIRQ(iis->irq);
+        printf("Ouch!\n");
+    }
 }
 
 
 // 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)
@@ -200,13 +220,17 @@
     switch(ch) {
         case 0:
             isrIrqSem[ch].irq = I2C1_IRQn;
-            isrIrqSem[ch].isr = (uint32_t)i2cRtos_isr_ch0;
+            //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;
+            //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;
@@ -214,21 +238,25 @@
 #elif defined(TARGET_LPC11U24)
     static osSemaphoreDef(i2cIsrDrvSem_ch1);
     isrIrqSem[ch].irq = I2C_IRQn;
-    isrIrqSem[ch].isr = (uint32_t)i2cRtos_isr_ch1;
-    isrIrqSem[1].sem = osSemaphoreCreate(osSemaphore(i2cIsrDrvSem_ch1), 1);
-    osSemaphoreWait(isrIrqSem[0].sem, osWaitForever);
+    //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"
+#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)) {
         i2c_stop(obj);
+        //printf("start Ouch read\n");
         return status;
     }
+    gpio_write(&gpio, 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?
     tr->obj=obj;
@@ -237,7 +265,7 @@
     tr->cnt=-1;
     tr->rData=data;
     I2C_DAT(obj) = address | 0x01;
-    i2cRtos_wait_and_see(obj, ch, 1+(length>>2));  // timeout (1+len/4)ms
+    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;
@@ -248,6 +276,7 @@
     int status = i2c_start(obj);
     if ((status != 0x10) && (status != 0x08)) {
         i2c_stop(obj);
+        printf("start Ouch write\n");
         return status;
     }
     int ch = i2c_get_channel(obj);
@@ -258,8 +287,10 @@
     tr->cnt=-1;
     tr->wData=data;
     I2C_DAT(obj) = address & 0xfe;
-    i2cRtos_wait_and_see(obj, ch, 1+(length>>2));  // timeout (1+len/4)ms
-    i2c_clear_SI(obj); // ... why? Also in official lib
+    //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
     status = tr->stat;
     if(status || stop) i2c_stop(obj);
     return status;
@@ -274,9 +305,9 @@
     }
     int ch = i2c_get_channel(obj);
     i2c_transfer[ch].cmd = waitSI;
-    i2cRtos_wait_and_see(obj, ch, 1);
+    i2cRtos_wait_and_see(obj, ch, 2);
     return (I2C_DAT(obj) & 0xff);
-    
+
 }
 
 int i2cRtos_byte_write(i2c_t *obj, int data)
@@ -284,7 +315,7 @@
     I2C_DAT(obj) = (data & 0xff);
     int ch = i2c_get_channel(obj);
     i2c_transfer[ch].cmd = waitSI;
-    i2cRtos_wait_and_see(obj, ch, 1);
+    i2cRtos_wait_and_see(obj, ch, 2);
     int stat=i2c_status(obj);
     return (stat==0x18 || stat==0x28 || stat==0x40 || stat==0xb8);
 }
@@ -316,7 +347,7 @@
     tr->len=length;
     tr->cnt=-1;
     tr->rData=data;
-    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
     if(tr->stat != 0xa0) {
         i2c_stop(obj);
     }