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
Revision 13:530968937ccb, committed 2013-05-10
- Comitter:
- humlet
- Date:
- Fri May 10 20:38:35 2013 +0000
- Parent:
- 12:6ddadcbbdca2
- Child:
- 14:352609d395c1
- Commit message:
- happyhappyjoyjoy
Changed in this revision
--- a/I2CDriver.cpp Fri May 10 07:34:24 2013 +0000 +++ b/I2CDriver.cpp Fri May 10 20:38:35 2013 +0000 @@ -5,7 +5,10 @@ using namespace mbed; using namespace rtos; -#define DRV_USR_SIG (1<<6) +#define PREFIX i2c +#define PASTER(x,y) x ## _ ## y +#define EVALUATOR(x,y) PASTER(x,y) +#define FUNCTION(fun) EVALUATOR(PREFIX, fun) const PinName I2CDriver::c_sdas[] = {p9,p28}; const PinName I2CDriver::c_scls[] = {p10,p27}; @@ -14,6 +17,8 @@ I2CDriver::I2CDriver(PinName sda, PinName scl, int hz, int slaveAdr):m_freq(hz),m_slaveAdr(slaveAdr) { + static Mutex mutex; + mutex.lock(); // check pins and determine i2c channel int channel=0; #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) @@ -24,89 +29,15 @@ else error("I2CDriver: Invalid I2C pins selected\n"); if(s_channels[channel]==0) { - new Thread(threadFun,(void *)channel,osPriorityRealtime,1024); // evillive + s_channels[channel] = new I2CDriver::Channel; + m_channel = s_channels[channel]; + m_channel->freq = 0; + m_channel->slaveAdr = 0; + m_channel->modeSlave = 0; + FUNCTION(init)(&m_channel->i2c, c_sdas[channel], c_scls[channel]); } m_channel = s_channels[channel]; -} - - -void I2CDriver::threadFun(void const *args) -{ - int channelIdx = (int)args; - Channel channel; - s_channels[channelIdx] = &channel; - channel.driver = Thread::gettid(); - - int freq = 0; - int adrSlave = 0; - int modeSlave = 0; - i2c_t i2c; - i2cRtos_init(&i2c, c_sdas[channelIdx], c_scls[channelIdx]); - - volatile Transfer& tr = channel.transfer; - while(1) { - // wait for requests - osSignalWait(DRV_USR_SIG,osWaitForever); - - // check and adapt frequency - if(freq != tr.freq) { - freq = tr.freq; - i2c_frequency(&i2c, tr.freq); - } - - // check and adapt slave/master mode - if(modeSlave != tr.slv) { - modeSlave = tr.slv; - i2c_slave_mode(&i2c, tr.slv); - } - - // check and adapt slave address - int adr = (tr.adr & 0xFF) | 1; - if(tr.slv && adrSlave != adr) { - adrSlave = adr; - i2c_slave_address(&i2c, 0, adr, 0); - } - - // just doit - switch(tr.cmd) { - case START: - i2c_start(&i2c); - break; - case STOP: - i2c_stop(&i2c); - break; - case READ_MST: - tr.ret = i2cRtos_read(&i2c, tr.adr, tr.dta, tr.len, (tr.rep?0:1)); - break; - case READ_MST_REG: - tr.ret = i2cRtos_write(&i2c, tr.adr,(const char*)&(tr.reg), 1, 0); - if(tr.ret)break; // error => bail out - tr.ret = i2cRtos_read(&i2c, tr.adr, tr.dta, tr.len, (tr.rep?0:1)); - break; - case READ_SLV: - tr.ret = i2cRtos_slave_read(&i2c, tr.dta, tr.len); - break; - case READ_BYTE: - tr.ret = i2cRtos_byte_read(&i2c, (tr.ack?0:1)); - break; - case WRITE_MST: - tr.ret = i2cRtos_write(&i2c, tr.adr, tr.wdta, tr.len, (tr.rep?0:1)); - break; - case WRITE_SLV: - tr.ret = i2cRtos_slave_write(&i2c, tr.wdta, tr.len); - break; - case WRITE_BYTE: - tr.ret = i2cRtos_byte_write(&i2c, tr.ack); - break; - case RECEIVE: - tr.ret = i2cRtos_slave_receive(&i2c, tr.tmout); - break; - default: - error("call 911\n"); - } - // inform the caller - osSignalSet( channel.transfer.caller, DRV_USR_SIG); - } + mutex.unlock(); } void I2CDriver::lock() @@ -116,157 +47,140 @@ m_callerID = osThreadGetId(); m_callerPrio = osThreadGetPriority(m_callerID); m_channel->mutex.lock(osWaitForever); - osThreadSetPriority(m_callerID, c_drvPrio); // evillive hopefully not interrupted since the lock + // maximize thread prio + osThreadSetPriority(m_callerID, c_drvPrio); // hopefully not interrupted since the lock in the line above + // mutex code looks like that waiting threads are priority ordered + // also priority inheritance seems to be provided } void I2CDriver::unlock() { - // free the mtex and restore original prio + // free the mutex and restore original prio m_channel->mutex.unlock(); osThreadSetPriority(m_callerID, m_callerPrio); } -int I2CDriver::sendNwait() +void I2CDriver::config() { - m_channel->transfer.freq = m_freq; - m_channel->transfer.caller = Thread::gettid(); - osSignalSet( m_channel->driver, DRV_USR_SIG); - osSignalWait(DRV_USR_SIG,osWaitForever); - int ret = m_channel->transfer.ret; - unlock(); - return ret; + // check and update frequency + if(m_freq != m_channel->freq) { + m_channel->freq = m_freq; + i2c_frequency(&m_channel->i2c, m_freq); + } + // check and update slave/master mode + if(m_modeSlave != m_channel->modeSlave) { + m_channel->modeSlave = m_modeSlave; + i2c_slave_mode(&m_channel->i2c, m_modeSlave); + } + // check and update slave address + if(m_modeSlave && m_slaveAdr != m_channel->slaveAdr) { + m_channel->slaveAdr = m_slaveAdr; + i2c_slave_address(&m_channel->i2c, 0, m_slaveAdr, 0); + } } int I2CDriver::readMaster(int address, char *data, int length, bool repeated) { - lock(); - m_channel->transfer.cmd = READ_MST; - m_channel->transfer.slv = false; - m_channel->transfer.adr = address; - m_channel->transfer.dta = data; - m_channel->transfer.len = length; - m_channel->transfer.rep = repeated; - return sendNwait(); + m_modeSlave = false; + lockNconfig(); + int ret = FUNCTION(read)(&m_channel->i2c, address, data, length, (repeated?0:1)); + unlock(); + return ret; } - int I2CDriver::readMaster(int address, uint8_t _register, char *data, int length, bool repeated) { - lock(); - m_channel->transfer.cmd = READ_MST_REG; - m_channel->transfer.slv = false; - m_channel->transfer.adr = address; - m_channel->transfer.reg = _register; - m_channel->transfer.dta = data; - m_channel->transfer.len = length; - m_channel->transfer.rep = repeated; - return sendNwait(); + m_modeSlave = false; + lockNconfig(); + int ret = FUNCTION(write)(&m_channel->i2c, address,(const char*)&_register, 1, 0); + if(!ret) ret = FUNCTION(read)(&m_channel->i2c, address, data, length, (repeated?0:1)); + unlock(); + return ret; } - int I2CDriver::readMaster(int ack) { - lock(); - m_channel->transfer.cmd = READ_BYTE; - m_channel->transfer.slv = false; - m_channel->transfer.ack = ack; - return sendNwait(); + m_modeSlave = false; + lockNconfig(); + int ret = i2cRtos_byte_read(&m_channel->i2c, (ack?0:1)); + unlock(); + return ret; } - int I2CDriver::writeMaster(int address, const char *data, int length, bool repeated) { - lock(); - m_channel->transfer.cmd = WRITE_MST; - m_channel->transfer.slv = false; - m_channel->transfer.adr = address; - m_channel->transfer.wdta = data; - m_channel->transfer.len = length; - m_channel->transfer.rep = repeated; - return sendNwait(); + m_modeSlave = false; + lockNconfig(); + int ret = FUNCTION(write)(&m_channel->i2c, address, data, length, (repeated?0:1)); + unlock(); + return ret; } - int I2CDriver::writeMaster(int data) { - lock(); - m_channel->transfer.cmd = WRITE_BYTE; - m_channel->transfer.slv = false; - m_channel->transfer.ack = data; - return sendNwait(); + m_modeSlave = false; + lockNconfig(); + int ret = i2cRtos_byte_write(&m_channel->i2c, data); + unlock(); + return ret; } - void I2CDriver::startMaster(void) { - lock(); - m_channel->transfer.cmd = START; - m_channel->transfer.slv = false; - sendNwait(); + m_modeSlave = false; + lockNconfig(); + i2c_start(&m_channel->i2c); + unlock(); } - -void I2CDriver::stopMaster(void) +bool I2CDriver::stopMaster(void) { - lock(); - m_channel->transfer.cmd = STOP; - m_channel->transfer.slv = false; - sendNwait(); + m_modeSlave = false; + lockNconfig(); + bool ret=i2cRtos_stop(&m_channel->i2c); + unlock(); + return ret; } - void I2CDriver::stopSlave(void) { - lock(); - m_channel->transfer.cmd = STOP; - m_channel->transfer.slv = true; - m_channel->transfer.adr = m_slaveAdr; - sendNwait(); + m_modeSlave = true; + lockNconfig(); + i2c_stop(&m_channel->i2c); + unlock(); } - int I2CDriver::receiveSlave(uint32_t timeout_ms) { - lock(); - m_channel->transfer.cmd = RECEIVE; - m_channel->transfer.slv = true; - m_channel->transfer.adr = m_slaveAdr; - m_channel->transfer.tmout = timeout_ms; - return sendNwait(); + m_modeSlave = true; + lockNconfig(); + int ret = i2cRtos_slave_receive(&m_channel->i2c, timeout_ms); + unlock(); + return ret; } - int I2CDriver::readSlave(char* data, int length) { - lock(); - m_channel->transfer.cmd = READ_SLV; - m_channel->transfer.slv = true; - m_channel->transfer.adr = m_slaveAdr; - m_channel->transfer.dta = data; - m_channel->transfer.len = length; - return sendNwait(); + m_modeSlave = true; + lockNconfig(); + int ret = i2cRtos_slave_read(&m_channel->i2c, data, length); + unlock(); + return ret; } - int I2CDriver::readSlave(void) { - lock(); - m_channel->transfer.cmd = READ_BYTE; - m_channel->transfer.slv = true; - m_channel->transfer.adr = m_slaveAdr; - m_channel->transfer.ack = 1; - return sendNwait(); + m_modeSlave = true; + lockNconfig(); + int ret = i2cRtos_byte_read(&m_channel->i2c, 0); + unlock(); + return ret; } - int I2CDriver::writeSlave(const char *data, int length) { - lock(); - m_channel->transfer.cmd = WRITE_SLV; - m_channel->transfer.slv = true; - m_channel->transfer.adr = m_slaveAdr; - m_channel->transfer.wdta = data; - m_channel->transfer.len = length; - return sendNwait(); + m_modeSlave = true; + lockNconfig(); + int ret = i2cRtos_slave_write(&m_channel->i2c, data, length); + unlock(); + return ret; } - int I2CDriver::writeSlave(int data) { - lock(); - m_channel->transfer.cmd = WRITE_BYTE; - m_channel->transfer.slv = true; - m_channel->transfer.adr = m_slaveAdr; - m_channel->transfer.ack = data; - return sendNwait(); + m_modeSlave = true; + lockNconfig(); + int ret = i2cRtos_byte_write(&m_channel->i2c, data); + unlock(); + return ret; }
--- a/I2CDriver.h Fri May 10 07:34:24 2013 +0000 +++ b/I2CDriver.h Fri May 10 20:38:35 2013 +0000 @@ -5,7 +5,6 @@ #include "I2C.h" -#include "Thread.h" #include "Mutex.h" namespace mbed @@ -115,7 +114,7 @@ * general call address. */ void addressSlave(int address) { - m_slaveAdr=address; + m_slaveAdr=(address & 0xff) | 1; } /** Checks to see if this I2C Slave has been addressed. @@ -137,6 +136,7 @@ * @returns * 0 on success, * non-0 otherwise + * ... no! instead it returns number of bytes read minus one ... weird, guess its a bug in the official lib */ int readSlave(char *data, int length); @@ -154,7 +154,7 @@ * * @returns * 0 on success, - * non-0 otherwise + * non-0 otherwise */ int writeSlave(const char *data, int length); @@ -175,8 +175,10 @@ ///Creates a stop condition on the I2C bus void stopSlave(void); - ///Creates a stop condition on the I2C bus - void stopMaster(void); + /// Creates a stop condition on the I2C bus + /// If unsccessful because someone on the bus holds the scl line down it returns "false" after 23µs + /// In normal operation the stop shouldn't take longer than 12µs @ 100kHz and 3-4µs @ 400kHz. + bool stopMaster(void); /// Wait until the i2c driver becomes available. /// @@ -189,52 +191,30 @@ void unlock(); protected: - // commands sent from user to drive thread - enum Command { - START, - STOP, - READ_MST, - READ_MST_REG, - READ_SLV, - READ_BYTE, - WRITE_MST, - WRITE_SLV, - WRITE_BYTE, - RECEIVE + void config(); + void lockNconfig() { + lock(); + config(); + } + + // structure that holds I2C channels status + struct Channel { + rtos::Mutex mutex; + i2c_t i2c; + int freq; + int slaveAdr; + bool modeSlave; }; - // data transfer struct for communication between user and driver thread - struct Transfer { - Command cmd; - int ret; - int freq; - int adr; - char* dta; - const char* wdta; - int len; - int ack; - bool rep; - uint8_t reg; - bool slv; - uint32_t tmout; - osThreadId caller; - }; + // curren i2c configuration of this driver interface + int m_freq; + int m_slaveAdr; + bool m_modeSlave; - // structure that holds handles/locks for accessing the I2C channels - struct Channel { - osThreadId driver; - rtos::Mutex mutex; - volatile Transfer transfer; - }; - - // current frequency setting - int m_freq; - // current slave address setting - int m_slaveAdr; - // prio of current caller thread + // id and prio of current caller thread + osThreadId m_callerID; osPriority m_callerPrio; - // ID of current caller thread - osThreadId m_callerID; + // i2c driver prio static const osPriority c_drvPrio = osPriorityRealtime; @@ -245,14 +225,9 @@ // static storage for the I2C channel access objects static Channel* s_channels[2]; - // i2c channel object of this driver interface, in fact just pointer + // i2c channel object of this driver interface, in fact just a pointer /// to one of the entries in s_channels Channel* m_channel; - - // the driver thread function - static void threadFun(void const *args); - - int sendNwait(); }; } #endif
--- a/I2CDriverTest03.h Fri May 10 07:34:24 2013 +0000 +++ b/I2CDriverTest03.h Fri May 10 20:38:35 2013 +0000 @@ -1,173 +1,97 @@ #include "mbed.h" #include "rtos.h" #include "I2CMasterRtos.h" -#include "stdint.h" +#include "I2CSlaveRtos.h" -const int dataReadySig = 1<<5; -osThreadId mainThreadID = 0; -char data[64]; -int16_t fifo[16]; -const int i2cAdr = 0x68<<1; -int fifoAdr = 0x72; +const int freq = 400000; +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 "; -//Serial pc(USBTX, USBRX); - -void configMPU6050(I2CMasterRtos& i2c); -void config(I2CMasterRtos& i2c); +static void slvRxMsg(I2CSlaveRtos& slv) +{ + char rxMsg[len]; + memset(rxMsg,0,len); + if ( slv.receive() == I2CSlave::WriteAddressed ) { + int cnt=0; + while(cnt<len) rxMsg[cnt++]=slv.read(); + slv.stop(); // stop sretching low level of scl + printf("thread %x received message (sz=%d) as i2c slave: '%s'\n",Thread::gettid(),cnt,rxMsg); + } else + printf("Ouch slv rx failure\n"); +} +static void slvTxMsg(I2CSlaveRtos& slv) +{ + if ( slv.receive()==I2CSlave::ReadAddressed) { + int cnt=0; + while(cnt<len && slv.write(slvMsg[cnt++])); + slv.stop(); // stop sretching low level of scl + } else + printf("Ouch slv tx failure\n"); +} -void dataReadyIsr() +static void mstTxMsg(I2CMasterRtos& mst) { - osSignalSet(mainThreadID, dataReadySig); + mst.start(); + if(!mst.write(adr & 0xfe))printf("adr+W not acked\n"); + int cnt=0; + while(cnt<len && mst.write(mstMsg[cnt++])); + // give the slave a chance to stop stretching scl to low, otherwise we will busy wait for the stop forever + while(!mst.stop())Thread::wait(1); } -void readModWrite(I2CMasterRtos& i2c, uint8_t reg, uint8_t dta) +static void mstRxMsg(I2CMasterRtos& mst) { + char rxMsg[len]; + memset(rxMsg,0,len); - char rd1; - int rStat1 = i2c.read(i2cAdr, reg, &rd1, 1); - char data[2]; - data[0]=(char)reg; - data[1]=(char)dta; - char rd2; - int wStat = i2c.write(i2cAdr, data, 2); - osDelay(500); - int rStat2 = i2c.read(i2cAdr, reg, &rd2, 1); - printf("%2d%2d%2d %2x <- %2x => %2x -> %2x \n", rStat1, wStat, rStat2, reg, dta, rd1, rd2); + mst.lock(); // no special reason, just a test + mst.start(); + if(!mst.write(adr | 0x01))printf("adr+R not acked\n"); + int cnt=0; + while(cnt<len-1) rxMsg[cnt++]=mst.read(1); + mst.unlock(); + rxMsg[cnt++]=mst.read(0); + // give the slave a chance to stop stretching scl to low, otherwise we will busy wait for the stop forever + while(!mst.stop())Thread::wait(1); + printf("thread %x received message (sz=%d) as i2c master: '%s'\n",Thread::gettid(),cnt,rxMsg); } +static void channel1(void const *args) +{ + I2CMasterRtos mst(p9,p10,freq); + I2CSlaveRtos slv(p9,p10,freq,adr); + while(1) { + slvRxMsg(slv); + slvTxMsg(slv); + Thread::wait(100); + mstTxMsg(mst); + Thread::wait(100); + mstRxMsg(mst); + } +} + +void channel2(void const *args) +{ + I2CMasterRtos mst(p28,p27,freq); + I2CSlaveRtos slv(p28,p27,freq,adr); + while(1) { + Thread::wait(100); + mstTxMsg(mst); + Thread::wait(100); + mstRxMsg(mst); + slvRxMsg(slv); + slvTxMsg(slv); + } +} int doit() { - //pc.baud(115200); - mainThreadID = osThreadGetId(); - - I2CMasterRtos i2c(p28, p27,400000); - osDelay(500); - - printf("Initialize ... \n"); - config(i2c); - - printf("Action!\n"); - - InterruptIn dataReadyIrq(p8); - dataReadyIrq.mode(PullNone); - dataReadyIrq.rise(&dataReadyIsr); - - /* - data[0]=0x6a; // pwr 1 reg - data[1]=(1<<6)|(1<<2); // fifo on - i2c.write(i2cAdr,data,2,1); - - data[0]=0x38; // irq conf reg - data[1]=1; // irq on data ready - i2c.write(i2cAdr,data,2,1); - */ - //fifoAdr = 0x3b; - char devNull; - while(1) { - osSignalWait(dataReadySig, 1000); // osWaitForever - i2c.read(i2cAdr,fifoAdr,data,2); - i2c.read(i2cAdr,fifoAdr+2,data+2,12); - i2c.read(i2cAdr,0x3a,&devNull,1); - for(int i=0; i<7; i++) { - fifo[i] = (data[2*i]<<8) | data[2*i+1]; - printf("%8d",fifo[i]); - } - printf(" %x\n",devNull); - - } + Thread selftalk01(channel1,0); + Thread selftalk02(channel2,0); + Thread::wait(5000); return 0; } -static void config(I2CMasterRtos& i2c) -{ - uint8_t ncfg=32; - uint8_t regs[ncfg]; - uint8_t vals[ncfg]; - int cnt=0; - regs[cnt]=0x6b; - vals[cnt++]=(1<<7); // pwr 1 reg //: device reset - regs[cnt]=0x6b; - vals[cnt++]=1; // pwr 1 reg // clock from x gyro all pwr sav modes off - regs[cnt]=0x19; - vals[cnt++]=199; // sample rate divider reg // sapmle rate = gyro rate / (1+x) - regs[cnt]=0x1a; - vals[cnt++]=1;// conf reg // no ext frame sync / dig low pass set to 1 => 1kHz Sampling with ~200Hz bandwidth DLPF - regs[cnt]=0x1b; - vals[cnt++]=0;// gyro conf reg // no test mode and gyro range 250°/s - regs[cnt]=0x1c; - vals[cnt++]=0;// accl conf reg // no test mode and accl range 2g - regs[cnt]=0x23; - vals[cnt++]=0xf<<3;// fifo conf reg // accl + all gyro -> fifo - regs[cnt]=0x37; - vals[cnt++]=(0<<7)|(0<<6)|(0<<5)|(0<<4); // irq conf reg // act high | 0:pupu 1:opnDrn| pulse | clear on any read - regs[cnt]=0x38; - vals[cnt++]=1|(1<<4); // irq conf reg // irq on data ready - regs[cnt]=0x6a; - vals[cnt++]=(1<<2); // pwr 1 reg // fifo reset - regs[cnt]=0x6a; - vals[cnt++]=(1<<6); // pwr 1 reg // fifo on - - /* - readModWrite(i2c, regs[0], vals[0]); - char reset=0xff; - while(reset&(1<<7)) { - osDelay(100); - i2c.read(i2cAdr,0x6b,&reset,1,1); - } - */ - for(int i=0; i<cnt; i++) - readModWrite(i2c, regs[i], vals[i]); -} - -static void configMPU6050(I2CMasterRtos& i2c) -{ - - data[0]=0x6b; // pwr 1 reg - data[1]=1<<7; // device reset - i2c.write(i2cAdr,data,2,1); - char reset=0xff; - while(reset&(1<<7)) { - osDelay(100); - i2c.read(i2cAdr,0x6b,&reset,1,1); - } - - data[0]=0x19; // sample rate divider reg - data[1]=99; // sapmle rate = gyro rate / (1+x) - i2c.write(i2cAdr,data,2,1); - - data[0]=0x1a; // conf reg - data[1]=1; // no ext frame sync / dig low pass set to 1 => 1kHz Sampling with ~200Hz bandwidth DLPF - i2c.write(i2cAdr,data,2,1); - - data[0]=0x1b; // gyro conf reg - data[1]=0; // no test mode and gyro range 250°/s - i2c.write(i2cAdr,data,2,1); - - data[0]=0x1c; // accl conf reg - data[1]=0; // no test mode and accl range 2g - i2c.write(i2cAdr,data,2,1); - - data[0]=0x23; // fifo conf reg - data[1]=0xf<<3; // accl + all gyro -> fifo - i2c.write(i2cAdr,data,2,1); - - data[0]=0x37; // irq conf reg - data[1]=(1<<7)|(0<<6)|(0<<5)|(1<<4); // act high | pupu | pulse | clear on any read - i2c.write(i2cAdr,data,2,1); - - /* - data[0]=0x38; // irq conf reg - data[1]=1; // irq on data ready - i2c.write(i2cAdr,data,2,1); - - data[0]=0x6a; // pwr 1 reg - data[1]=(1<<6); // fifo on - i2c.write(i2cAdr,data,2,1); - */ - data[0]=0x6b; // pwr 1 reg - data[1]=1; // clock from x gyro all pwr sav modes off - i2c.write(i2cAdr,data,2,1); -} -
--- a/I2CDriverTest04.h Fri May 10 07:34:24 2013 +0000 +++ b/I2CDriverTest04.h Fri May 10 20:38:35 2013 +0000 @@ -63,7 +63,7 @@ #elif defined(TARGET_LPC11U24) const int nTest=5; const int freq[nTest]= {1e5, 1e5, 4e5, 4e5, 4e5 }; - const int len[nTest]= {1, 4, 1, 6, 16}; + const int len[nTest]= {1, 6, 1, 6, 32}; #endif for(int i=0; i<nTest; ++i) { g_freq = freq[i];
--- a/I2CMasterRtos.h Fri May 10 07:34:24 2013 +0000 +++ b/I2CMasterRtos.h Fri May 10 20:38:35 2013 +0000 @@ -112,14 +112,29 @@ /** Creates a start condition on the I2C bus */ - void startMaster(void) { + void start(void) { m_drv.startMaster(); } - /** Creates a stop condition on the I2C bus - */ - void stop(void) { - m_drv.stopMaster(); + /// Creates a stop condition on the I2C bus + /// If unsccessful because someone on the bus holds the scl line down it returns "false" after 23µs + /// In normal operation the stop shouldn't take longer than 12µs @ 100kHz and 3-4µs @ 400kHz. + bool stop(void) { + return m_drv.stopMaster(); + } + + /// Wait until the interface becomes available. + /// + /// Useful if you want to run a sequence of command without interrution by another thread. + /// There's no need to call this function for running single request, because all driver functions + /// will lock the device for exclusive access automatically. + void lock() { + m_drv.lock(); + } + + /// Unlock the interface that has previously been locked by the same thread. + void unlock() { + m_drv.unlock(); } };
--- a/I2CSlaveRtos.h Fri May 10 07:34:24 2013 +0000 +++ b/I2CSlaveRtos.h Fri May 10 20:38:35 2013 +0000 @@ -60,6 +60,7 @@ * @returns * 0 on success, * non-0 otherwise + * ... no! instead it returns number of bytes read minus one ... weird, guess its a bug in the official lib */ int read(char *data, int length) { return m_drv.readSlave(data, length); @@ -112,9 +113,25 @@ /** Reset the I2C slave back into the known ready receiving state. */ - void stop(void){ + void stop(void) { m_drv.stopSlave(); } + + + /// Wait until the interface becomes available. + /// + /// Useful if you want to run a sequence of command without interrution by another thread. + /// There's no need to call this function for running single request, because all driver functions + /// will lock the device for exclusive access automatically. + void lock() { + m_drv.lock(); + } + + /// Unlock the interface that has previously been locked by the same thread. + void unlock() { + m_drv.unlock(); + } + }; }
--- a/i2cRtos_api.c Fri May 10 07:34:24 2013 +0000 +++ b/i2cRtos_api.c Fri May 10 20:38:35 2013 +0000 @@ -2,16 +2,24 @@ #if DEVICE_I2C +#include "us_ticker_api.h" #include "cmsis_os.h" #include "error.h" +#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) #define I2C_CONSET(x) (x->i2c->I2CONSET) #define I2C_CONCLR(x) (x->i2c->I2CONCLR) #define I2C_STAT(x) (x->i2c->I2STAT) #define I2C_DAT(x) (x->i2c->I2DAT) +#elif defined(TARGET_LPC11U24) +#define I2C_CONSET(x) (x->i2c->CONSET) +#define I2C_CONCLR(x) (x->i2c->CONCLR) +#define I2C_STAT(x) (x->i2c->STAT) +#define I2C_DAT(x) (x->i2c->DAT) +#endif -//#include "gpio_api.h" -//static gpio_t gpio[2]; // evillive +#include "gpio_api.h" +static gpio_t gpio[2]; // evillive enum I2cIsrCmd { readMst, @@ -126,12 +134,14 @@ NVIC_DisableIRQ(isrIrqSem[ch].irq); } } +#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) static void i2cRtos_isr_ch0() { //gpio_write(&gpio[0], 1); i2cRtos_isr(0); //gpio_write(&gpio[0], 0); } +#endif static void i2cRtos_isr_ch1() { //gpio_write(&gpio[1], 1); @@ -249,6 +259,19 @@ } +inline int i2cRtos_stop(i2c_t *obj) { + i2c_conset(obj, 0, 1, 0, 0); + i2c_clear_SI(obj); + + uint32_t t0=us_ticker_read(); + uint32_t dt=0; + while((I2C_CONSET(obj) & (1 << 4)) && dt<23){ + dt = us_ticker_read() - t0; + } + return dt<23; +} + + #if DEVICE_I2CSLAVE @@ -306,7 +329,7 @@ // 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); @@ -315,7 +338,7 @@ 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)
--- a/i2cRtos_api.h Fri May 10 07:34:24 2013 +0000 +++ b/i2cRtos_api.h Fri May 10 20:38:35 2013 +0000 @@ -29,6 +29,7 @@ int i2cRtos_write(i2c_t *obj, int address, const char *data, int length, int stop); int i2cRtos_byte_read(i2c_t *obj, int last); int i2cRtos_byte_write(i2c_t *obj, int data); + int i2cRtos_stop(i2c_t *obj); #if DEVICE_I2CSLAVE int i2cRtos_slave_receive(i2c_t *obj, uint32_t tmOut);