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
I2CDriver.cpp
- Committer:
- humlet
- Date:
- 2013-04-14
- Revision:
- 1:90455d5bdd8c
- Parent:
- 0:13c962fecb13
- Child:
- 2:514105beb343
File content as of revision 1:90455d5bdd8c:
#include "I2CDriver.h" #include "error.h" using namespace mbed; using namespace rtos; #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( s_channels[0]->driver, ISR2DRV_SIG); NVIC_DisableIRQ(I2C1_IRQn); } void I2CDriver::channel_1_ISR() { 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) { 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); #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) { // 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: 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"); } // inform the caller osSignalSet( channel.transfer.caller, DRV_USR_SIG); } } I2CDriver::I2CDriver(PinName sda, PinName scl):I2C(sda,scl) { // check pins and determine i2c channel int channel=0; #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_channels[channel]; } 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); } int I2CDriver::read(int address, char *data, int length, bool repeated) { lock(); 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(); int ret = m_channel->transfer.ret; unlock(); return ret; } 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.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(); 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(); }