Helmut Schmücker / mbed-RtosI2cDriver

Dependencies:   mbed-rtos mbed-src

Files at this revision

API Documentation at this revision

Comitter:
humlet
Date:
Sun Apr 14 06:39:04 2013 +0000
Parent:
0:13c962fecb13
Child:
2:514105beb343
Commit message:
no more smoke

Changed in this revision

I2CDriver.cpp Show annotated file Show diff for this revision Revisions of this file
I2CDriver.h Show annotated file Show diff for this revision Revisions of this file
mbed-NXP.lib Show annotated file Show diff for this revision Revisions of this file
--- a/I2CDriver.cpp	Sat Apr 13 13:37:29 2013 +0000
+++ b/I2CDriver.cpp	Sun Apr 14 06:39:04 2013 +0000
@@ -1,102 +1,197 @@
 #include "I2CDriver.h"
 #include "error.h"
 
-#define ISR2DRV_SIG (1<<0);
-#define DRV_USR_SIG (1<<1);
+using namespace mbed;
+using namespace rtos;
 
-Channel I2CDriver::channels[2]= {0,0};
+#define ISR2DRV_SIG (1<<7)
+#define DRV_USR_SIG (1<<6)
+
+const PinName I2CDriver::c_sdas[] = {p9,p28};
+const PinName I2CDriver::c_scls[] = {p10,p27};
+
+I2CDriver::Channel* I2CDriver::s_channels[2] = {0,0};
 
 
 void I2CDriver::channel_0_ISR()
 {
-    osSignalSet( channels[0].driver, ISR2DRV_SIG);
-    NVIC_DisableIRQ(I2C1_IRQn); //I2C_IRQn
+    osSignalSet( s_channels[0]->driver, ISR2DRV_SIG);
+    NVIC_DisableIRQ(I2C1_IRQn);
 }
 
 
 void I2CDriver::channel_1_ISR()
 {
-    osSignalSet( channels[1].driver, ISR2DRV_SIG);
-    NVIC_DisableIRQ(I2C2_IRQn); //I2C_IRQn
+    osSignalSet( s_channels[1]->driver, ISR2DRV_SIG);
+#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
+    NVIC_DisableIRQ(I2C2_IRQn);
+#elif defined(TARGET_LPC11U24)
+    NVIC_DisableIRQ(I2C_IRQn);
+#endif
 }
 
 
-void I2CDriver::threadFun(void* const args)
+void I2CDriver::threadFun(void const *args)
 {
     int channelIdx = (int)args;
     Channel channel;
     s_channels[channelIdx] = &channel;
 
     channel.driver = Thread::gettid();
-
+#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
     if(channelIdx==0)NVIC_SetVector(I2C1_IRQn, (uint32_t)I2CDriver::channel_0_ISR);
     if(channelIdx==1)NVIC_SetVector(I2C2_IRQn, (uint32_t)I2CDriver::channel_1_ISR);
-
-    I2C i2c(c_sda[channelIdx], c_scl[channelIdx]);
-
+#elif defined(TARGET_LPC11U24)
+    NVIC_SetVector(I2C_IRQn, (uint32_t)I2CDriver::channel_1_ISR);
+#endif
+    I2C i2c(c_sdas[channelIdx], c_scls[channelIdx]);
+    volatile Transfer& tr = channel.transfer;
     while(1) {
-        osSignalWait(DRV_USR_SIG,0);
-        switch(channels[channel].transfer.cmd) {
+        // wait for requests
+        osSignalWait(DRV_USR_SIG,osWaitForever);
+        // check and adapt frequency
+        if(channel.freq != tr.freq) {
+            channel.freq = tr.freq;
+            i2c.frequency(tr.freq);
+        }
+        // just doit
+        switch(tr.cmd) {
             case START:
-                if(channel.freq!=channel.transfer.freq) i2c.frequency
                 i2c.start();
                 break;
             case STOP:
                 i2c.stop();
                 break;
+            case READ:
+                tr.ret = i2c.read(tr.adr, tr.dta, tr.len, tr.rep);
+                break;
+            case READ_FROM_REGISTER:
+                tr.ret = i2c.write(tr.adr,(const char*)&(tr.reg), 1, true);
+                if(tr.ret)break; // error => bail out
+                tr.ret = i2c.read(tr.adr, tr.dta, tr.len, tr.rep);
+                break;
+            case READ_BYTE:
+                tr.ret = i2c.read(tr.ack);
+                break;
+            case WRITE:
+                tr.ret = i2c.write(tr.adr, tr.wdta, tr.len, tr.rep);
+                break;
+            case WRITE_BYTE:
+                tr.ret = i2c.write(tr.ack);
+                break;
+            default:
+                error("call 911");
         }
-        s_threads[2]
+        // inform the caller
+        osSignalSet( channel.transfer.caller, DRV_USR_SIG);
     }
 }
 
 
-I2CDriver::I2CDriver(PinName sda, PinName scl)
+I2CDriver::I2CDriver(PinName sda, PinName scl):I2C(sda,scl)
 {
     // check pins and determine i2c channel
     int channel=0;
-    if(sda==sdas[0] && scl==scls[0]) channel=0; // I2C_1
-    else if (sda==sdas[1] && scl==scls[1]) channel=1; //I2C_2
-    else error("I2CDriver: Invalid I2C pinns selected");
-
+#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
+    if(sda==c_sdas[0] && scl==c_scls[0]) channel=0; // I2C_1
+    else
+#endif
+        if (sda==c_sdas[1] && scl==c_scls[1]) channel=1; //I2C_2 or I2C
+        else error("I2CDriver: Invalid I2C pinns selected");
     if(s_channels[channel]==0)
         new Thread(threadFun,(void *)channel,osPriorityRealtime);
-        
-    m_channel = *(s_channel[channel]);
+    m_channel = s_channels[channel];
 }
 
-void I2CDriver::sendNwait(){
-    osSignalSet( m_channel.driver, DRV_USR_SIG);
+
+void I2CDriver::sendNwait()
+{
+    m_channel->transfer.freq = _hz;
+    m_channel->transfer.caller = Thread::gettid();
+    osSignalSet( m_channel->driver, DRV_USR_SIG);
     osSignalWait(DRV_USR_SIG,osWaitForever);
 }
 
-void I2CDriver::frequency(int hz);
 
-
-int I2CDriver::read(int address, char *data, int length, bool repeated = false);
-
-
-int I2CDriver::read(int ack);
-
-
-int I2CDriver::write(int address, const char *data, int length, bool repeated = false);
-
-
-int I2CDriver::write(int data);
-
-
-void I2CDriver::start(void){
+int I2CDriver::read(int address, char *data, int length, bool repeated)
+{
     lock();
-    m_channel.transfer.freq = _hz;
-    m_channel.transfer.cmd = START;
+    m_channel->transfer.cmd = READ;
+    m_channel->transfer.adr = address;
+    m_channel->transfer.dta = data;
+    m_channel->transfer.len = length;
+    m_channel->transfer.rep = repeated;
     sendNwait();
-    unlock();   
+    int ret = m_channel->transfer.ret;
+    unlock();
+    return ret;
 }
 
 
-void I2CDriver::stop(void){
+int I2CDriver::read(int address, uint8_t regist, char *data, int length, bool repeated)
+{
+    lock();
+    m_channel->transfer.cmd = READ_FROM_REGISTER;
+    m_channel->transfer.adr = address;
+    m_channel->transfer.reg = regist;
+    m_channel->transfer.dta = data;
+    m_channel->transfer.len = length;
+    m_channel->transfer.rep = repeated;
+    sendNwait();
+    int ret = m_channel->transfer.ret;
+    unlock();
+    return ret;
+}
+
+int I2CDriver::read(int ack)
+{
+    lock();
+    m_channel->transfer.cmd = READ_BYTE;
+    m_channel->transfer.ack = ack;
+    sendNwait();
+    int ret = m_channel->transfer.ret;
+    unlock();
+    return ret;
+}
+
+int I2CDriver::write(int address, const char *data, int length, bool repeated)
+{
     lock();
-    m_channel.transfer.freq = _hz;
-    m_channel.transfer.cmd = STOP;
+    m_channel->transfer.cmd = WRITE;
+    m_channel->transfer.adr = address;
+    m_channel->transfer.wdta = data;
+    m_channel->transfer.len = length;
+    m_channel->transfer.rep = repeated;
+    sendNwait();
+    int ret = m_channel->transfer.ret;
+    unlock();
+    return ret;
+}
+
+int I2CDriver::write(int data)
+{
+    lock();
+    m_channel->transfer.cmd = WRITE_BYTE;
+    m_channel->transfer.ack = data;
     sendNwait();
-    unlock();   
+    int ret = m_channel->transfer.ret;
+    unlock();
+    return ret;
 }
+
+void I2CDriver::start(void)
+{
+    lock();
+    m_channel->transfer.cmd = START;
+    sendNwait();
+    unlock();
+}
+
+
+void I2CDriver::stop(void)
+{
+    lock();
+    m_channel->transfer.cmd = STOP;
+    sendNwait();
+    unlock();
+}
--- a/I2CDriver.h	Sat Apr 13 13:37:29 2013 +0000
+++ b/I2CDriver.h	Sun Apr 14 06:39:04 2013 +0000
@@ -26,12 +26,6 @@
      */
     I2CDriver(PinName sda, PinName scl);
 
-    /** Set the frequency of the I2C interface
-     *
-     *  @param hz The bus frequency in hertz
-     */
-    void frequency(int hz);
-
     /** Read from an I2C slave
      *
      * Performs a complete read transaction. The bottom bit of
@@ -48,6 +42,8 @@
      */
     int read(int address, char *data, int length, bool repeated = false);
 
+    int read(int address, uint8_t regist, char *data, int length, bool repeated = false);
+
     /** Read a single byte from the I2C bus
      *
      *  @param ack indicates if the byte is to be acknowledged (1 = acknowledge)
@@ -90,15 +86,15 @@
     void stop(void);
 
     /// Wait until the i2c driver becomes available.
-    void lock() {
+     void lock()  {
         // if one and the same thread can lock twice, but then it needs also to unlock twice.
         // exactly what we need here
-        m_channel.mutex.lock(osWaitForever);
+        m_channel->mutex.lock(osWaitForever);
     }
 
     /// Unlock the driver that has previously been locked by the same thread
-    void osStatus unlock() {
-        m_channel.mutex.unlock(osWaitForever);
+     void unlock() {
+        m_channel->mutex.unlock();
     }
 
 
@@ -112,41 +108,43 @@
         READ_BYTE,
         READ,
         READ_FROM_REGISTER
-    }
+    };
 
     struct Transfer {
+        osThreadId caller;
         Command cmd;
         int freq;
         int adr;
-        int reg;
+        uint8_t reg;
         char* dta;
+        const char* wdta;
         int len;
+        int ack;
         bool rep;
-        int res;
-    }
+        int ret;
+    };
 
     struct Channel {
-        osThreadId caller;
-        osThreadId driver;
-        Mutex  mutex;
-        Transfer transfer;
-        int freq;
-    }
+        volatile osThreadId driver;
+        rtos::Mutex  mutex;
+        volatile Transfer transfer;
+        volatile int freq;
+    };
 
-    static const PinName c_sda[]= {p9,p28};
-    static const PinName c_scl[]= {p10,p27};
+    static const PinName c_sdas[2];
+    static const PinName c_scls[2];
 
-    static Channel* s_channels[2];
+     static Channel* s_channels[2];
 
-    Channel& m_channel;
+     Channel* m_channel;
 
     static void channel_0_ISR();
     static void channel_1_ISR();
 
-    static void threadFun(void* const args);
+    static void threadFun(void const *args);
 
     void sendNwait();
 
-}
+};
 }
 #endif
--- a/mbed-NXP.lib	Sat Apr 13 13:37:29 2013 +0000
+++ b/mbed-NXP.lib	Sun Apr 14 06:39:04 2013 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/mbed-NXP/#c9f4bde8b624
+http://mbed.org/users/mbed_official/code/mbed-NXP/#102159096554