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

Committer:
humlet
Date:
Sun Apr 28 15:08:04 2013 +0000
Revision:
7:04824382eafb
Parent:
6:5b98c902a659
Child:
8:5be85bd4c5ba
stable before perf measurements

Who changed what in which revision?

UserRevisionLine numberNew contents of line
humlet 0:13c962fecb13 1 #include "I2CDriver.h"
humlet 3:967dde37e712 2 #include "i2c_api.h"
humlet 0:13c962fecb13 3 #include "error.h"
humlet 0:13c962fecb13 4
humlet 7:04824382eafb 5 #include "DigitalOut.h"
humlet 7:04824382eafb 6
humlet 1:90455d5bdd8c 7 using namespace mbed;
humlet 1:90455d5bdd8c 8 using namespace rtos;
humlet 0:13c962fecb13 9
humlet 7:04824382eafb 10 DigitalOut osci(p12);
humlet 7:04824382eafb 11
humlet 1:90455d5bdd8c 12 #define DRV_USR_SIG (1<<6)
humlet 1:90455d5bdd8c 13
humlet 1:90455d5bdd8c 14 const PinName I2CDriver::c_sdas[] = {p9,p28};
humlet 1:90455d5bdd8c 15 const PinName I2CDriver::c_scls[] = {p10,p27};
humlet 1:90455d5bdd8c 16
humlet 1:90455d5bdd8c 17 I2CDriver::Channel* I2CDriver::s_channels[2] = {0,0};
humlet 0:13c962fecb13 18
humlet 6:5b98c902a659 19 #if defined(TARGET_LPC1768)
humlet 0:13c962fecb13 20 void I2CDriver::channel_0_ISR()
humlet 0:13c962fecb13 21 {
humlet 7:04824382eafb 22 osci.write(1);
humlet 2:514105beb343 23 osSignalSet( s_channels[0]->driver, I2C_ISR_DRV_SIG);
humlet 1:90455d5bdd8c 24 NVIC_DisableIRQ(I2C1_IRQn);
humlet 7:04824382eafb 25 osci.write(0);
humlet 0:13c962fecb13 26 }
humlet 6:5b98c902a659 27 #endif
humlet 0:13c962fecb13 28
humlet 0:13c962fecb13 29 void I2CDriver::channel_1_ISR()
humlet 0:13c962fecb13 30 {
humlet 7:04824382eafb 31 osci.write(1);
humlet 2:514105beb343 32 osSignalSet( s_channels[1]->driver, I2C_ISR_DRV_SIG);
humlet 1:90455d5bdd8c 33 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
humlet 1:90455d5bdd8c 34 NVIC_DisableIRQ(I2C2_IRQn);
humlet 1:90455d5bdd8c 35 #elif defined(TARGET_LPC11U24)
humlet 1:90455d5bdd8c 36 NVIC_DisableIRQ(I2C_IRQn);
humlet 1:90455d5bdd8c 37 #endif
humlet 7:04824382eafb 38 osci.write(0);
humlet 0:13c962fecb13 39 }
humlet 0:13c962fecb13 40
humlet 0:13c962fecb13 41
humlet 3:967dde37e712 42 I2CDriver::I2CDriver(PinName sda, PinName scl, int hz, int slaveAdr):m_freq(hz),m_slaveAdr(slaveAdr)
humlet 3:967dde37e712 43 {
humlet 3:967dde37e712 44 // check pins and determine i2c channel
humlet 3:967dde37e712 45 int channel=0;
humlet 3:967dde37e712 46 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
humlet 3:967dde37e712 47 if(sda==c_sdas[0] && scl==c_scls[0]) channel=0; // I2C_1
humlet 3:967dde37e712 48 else
humlet 3:967dde37e712 49 #endif
humlet 3:967dde37e712 50 if (sda==c_sdas[1] && scl==c_scls[1]) channel=1; //I2C_2 or I2C
humlet 3:967dde37e712 51 else error("I2CDriver: Invalid I2C pinns selected");
humlet 3:967dde37e712 52
humlet 3:967dde37e712 53 if(s_channels[channel]==0)
humlet 6:5b98c902a659 54 new Thread(threadFun,(void *)channel,osPriorityRealtime,256);
humlet 3:967dde37e712 55 m_channel = s_channels[channel];
humlet 3:967dde37e712 56 }
humlet 3:967dde37e712 57
humlet 3:967dde37e712 58
humlet 1:90455d5bdd8c 59 void I2CDriver::threadFun(void const *args)
humlet 0:13c962fecb13 60 {
humlet 0:13c962fecb13 61 int channelIdx = (int)args;
humlet 0:13c962fecb13 62 Channel channel;
humlet 0:13c962fecb13 63 s_channels[channelIdx] = &channel;
humlet 2:514105beb343 64 channel.driver = Thread::gettid();
humlet 0:13c962fecb13 65
humlet 1:90455d5bdd8c 66 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
humlet 0:13c962fecb13 67 if(channelIdx==0)NVIC_SetVector(I2C1_IRQn, (uint32_t)I2CDriver::channel_0_ISR);
humlet 0:13c962fecb13 68 if(channelIdx==1)NVIC_SetVector(I2C2_IRQn, (uint32_t)I2CDriver::channel_1_ISR);
humlet 1:90455d5bdd8c 69 #elif defined(TARGET_LPC11U24)
humlet 1:90455d5bdd8c 70 NVIC_SetVector(I2C_IRQn, (uint32_t)I2CDriver::channel_1_ISR);
humlet 1:90455d5bdd8c 71 #endif
humlet 2:514105beb343 72
humlet 3:967dde37e712 73 int freq = 0;
humlet 3:967dde37e712 74 int adrSlave = 0;
humlet 3:967dde37e712 75 int modeSlave = 0;
humlet 3:967dde37e712 76 i2c_t i2c;
humlet 3:967dde37e712 77 i2c_init(&i2c, c_sdas[channelIdx], c_scls[channelIdx]);
humlet 2:514105beb343 78
humlet 1:90455d5bdd8c 79 volatile Transfer& tr = channel.transfer;
humlet 0:13c962fecb13 80 while(1) {
humlet 1:90455d5bdd8c 81 // wait for requests
humlet 1:90455d5bdd8c 82 osSignalWait(DRV_USR_SIG,osWaitForever);
humlet 3:967dde37e712 83
humlet 1:90455d5bdd8c 84 // check and adapt frequency
humlet 3:967dde37e712 85 if(freq != tr.freq) {
humlet 3:967dde37e712 86 freq = tr.freq;
humlet 3:967dde37e712 87 i2c_frequency(&i2c, tr.freq);
humlet 1:90455d5bdd8c 88 }
humlet 3:967dde37e712 89
humlet 3:967dde37e712 90 // check and adapt slave/master mode
humlet 3:967dde37e712 91 if(modeSlave != tr.slv) {
humlet 3:967dde37e712 92 modeSlave = tr.slv;
humlet 3:967dde37e712 93 i2c_slave_mode(&i2c, tr.slv);
humlet 3:967dde37e712 94 }
humlet 3:967dde37e712 95
humlet 3:967dde37e712 96 // check and adapt slave address
humlet 3:967dde37e712 97 int adr = (tr.adr & 0xFF) | 1;
humlet 3:967dde37e712 98 if(tr.slv && adrSlave != adr) {
humlet 3:967dde37e712 99 adrSlave = adr;
humlet 3:967dde37e712 100 i2c_slave_address(&i2c, 0, adr, 0);
humlet 3:967dde37e712 101 }
humlet 3:967dde37e712 102
humlet 1:90455d5bdd8c 103 // just doit
humlet 1:90455d5bdd8c 104 switch(tr.cmd) {
humlet 0:13c962fecb13 105 case START:
humlet 3:967dde37e712 106 i2c_start(&i2c);
humlet 0:13c962fecb13 107 break;
humlet 0:13c962fecb13 108 case STOP:
humlet 3:967dde37e712 109 i2c_stop(&i2c);
humlet 0:13c962fecb13 110 break;
humlet 3:967dde37e712 111 case READ_MST:
humlet 3:967dde37e712 112 tr.ret = i2c_read(&i2c, tr.adr, tr.dta, tr.len, (tr.rep?0:1));
humlet 1:90455d5bdd8c 113 break;
humlet 3:967dde37e712 114 case READ_MST_REG:
humlet 7:04824382eafb 115 //printf("Disco\n");
humlet 3:967dde37e712 116 tr.ret = i2c_write(&i2c, tr.adr,(const char*)&(tr.reg), 1, 0);
humlet 1:90455d5bdd8c 117 if(tr.ret)break; // error => bail out
humlet 3:967dde37e712 118 tr.ret = i2c_read(&i2c, tr.adr, tr.dta, tr.len, (tr.rep?0:1));
humlet 3:967dde37e712 119 break;
humlet 3:967dde37e712 120 case READ_SLV:
humlet 3:967dde37e712 121 tr.ret = i2c_slave_read(&i2c, tr.dta, tr.len);
humlet 1:90455d5bdd8c 122 break;
humlet 1:90455d5bdd8c 123 case READ_BYTE:
humlet 3:967dde37e712 124 tr.ret = i2c_byte_read(&i2c, (tr.ack?0:1));
humlet 1:90455d5bdd8c 125 break;
humlet 3:967dde37e712 126 case WRITE_MST:
humlet 3:967dde37e712 127 tr.ret = i2c_write(&i2c, tr.adr, tr.wdta, tr.len, (tr.rep?0:1));
humlet 3:967dde37e712 128 break;
humlet 3:967dde37e712 129 case WRITE_SLV:
humlet 3:967dde37e712 130 tr.ret = i2c_slave_write(&i2c, tr.wdta, tr.len);
humlet 1:90455d5bdd8c 131 break;
humlet 1:90455d5bdd8c 132 case WRITE_BYTE:
humlet 3:967dde37e712 133 tr.ret = i2c_byte_write(&i2c, tr.ack);
humlet 1:90455d5bdd8c 134 break;
humlet 3:967dde37e712 135 case RECEIVE:
humlet 3:967dde37e712 136 tr.ret = i2c_slave_receive_rtos(&i2c, tr.tmout);
humlet 4:eafa7efcd771 137 break;
humlet 1:90455d5bdd8c 138 default:
humlet 4:eafa7efcd771 139 error("call 911\n");
humlet 0:13c962fecb13 140 }
humlet 1:90455d5bdd8c 141 // inform the caller
humlet 1:90455d5bdd8c 142 osSignalSet( channel.transfer.caller, DRV_USR_SIG);
humlet 0:13c962fecb13 143 }
humlet 0:13c962fecb13 144 }
humlet 0:13c962fecb13 145
humlet 6:5b98c902a659 146 void I2CDriver::lock()
humlet 6:5b98c902a659 147 {
humlet 6:5b98c902a659 148 // One and the same thread can lock twice, but then it needs also to unlock twice.
humlet 6:5b98c902a659 149 // exactly what we need here
humlet 6:5b98c902a659 150 m_callerID = osThreadGetId();
humlet 6:5b98c902a659 151 m_callerPrio = osThreadGetPriority(m_callerID);
humlet 6:5b98c902a659 152 m_channel->mutex.lock(osWaitForever);
humlet 6:5b98c902a659 153 osThreadSetPriority(m_callerID, c_drvPrio); // hopefully not interrupted since the lock
humlet 6:5b98c902a659 154 }
humlet 6:5b98c902a659 155
humlet 6:5b98c902a659 156 void I2CDriver::unlock()
humlet 6:5b98c902a659 157 {
humlet 6:5b98c902a659 158 // free the mtex and restore original prio
humlet 6:5b98c902a659 159 m_channel->mutex.unlock();
humlet 6:5b98c902a659 160 osThreadSetPriority(m_callerID, m_callerPrio);
humlet 6:5b98c902a659 161 }
humlet 6:5b98c902a659 162
humlet 3:967dde37e712 163 int I2CDriver::sendNwait()
humlet 0:13c962fecb13 164 {
humlet 3:967dde37e712 165 m_channel->transfer.freq = m_freq;
humlet 1:90455d5bdd8c 166 m_channel->transfer.caller = Thread::gettid();
humlet 1:90455d5bdd8c 167 osSignalSet( m_channel->driver, DRV_USR_SIG);
humlet 0:13c962fecb13 168 osSignalWait(DRV_USR_SIG,osWaitForever);
humlet 1:90455d5bdd8c 169 int ret = m_channel->transfer.ret;
humlet 1:90455d5bdd8c 170 unlock();
humlet 1:90455d5bdd8c 171 return ret;
humlet 0:13c962fecb13 172 }
humlet 0:13c962fecb13 173
humlet 3:967dde37e712 174 int I2CDriver::readMaster(int address, char *data, int length, bool repeated)
humlet 1:90455d5bdd8c 175 {
humlet 1:90455d5bdd8c 176 lock();
humlet 3:967dde37e712 177 m_channel->transfer.cmd = READ_MST;
humlet 3:967dde37e712 178 m_channel->transfer.slv = false;
humlet 1:90455d5bdd8c 179 m_channel->transfer.adr = address;
humlet 1:90455d5bdd8c 180 m_channel->transfer.dta = data;
humlet 1:90455d5bdd8c 181 m_channel->transfer.len = length;
humlet 1:90455d5bdd8c 182 m_channel->transfer.rep = repeated;
humlet 3:967dde37e712 183 return sendNwait();
humlet 1:90455d5bdd8c 184 }
humlet 1:90455d5bdd8c 185
humlet 3:967dde37e712 186 int I2CDriver::readMaster(int address, uint8_t _register, char *data, int length, bool repeated)
humlet 3:967dde37e712 187 {
humlet 3:967dde37e712 188 lock();
humlet 3:967dde37e712 189 m_channel->transfer.cmd = READ_MST_REG;
humlet 3:967dde37e712 190 m_channel->transfer.slv = false;
humlet 3:967dde37e712 191 m_channel->transfer.adr = address;
humlet 3:967dde37e712 192 m_channel->transfer.reg = _register;
humlet 3:967dde37e712 193 m_channel->transfer.dta = data;
humlet 3:967dde37e712 194 m_channel->transfer.len = length;
humlet 3:967dde37e712 195 m_channel->transfer.rep = repeated;
humlet 3:967dde37e712 196 return sendNwait();
humlet 3:967dde37e712 197 }
humlet 3:967dde37e712 198
humlet 3:967dde37e712 199 int I2CDriver::readMaster(int ack)
humlet 1:90455d5bdd8c 200 {
humlet 1:90455d5bdd8c 201 lock();
humlet 1:90455d5bdd8c 202 m_channel->transfer.cmd = READ_BYTE;
humlet 3:967dde37e712 203 m_channel->transfer.slv = false;
humlet 1:90455d5bdd8c 204 m_channel->transfer.ack = ack;
humlet 3:967dde37e712 205 return sendNwait();
humlet 1:90455d5bdd8c 206 }
humlet 1:90455d5bdd8c 207
humlet 3:967dde37e712 208 int I2CDriver::writeMaster(int address, const char *data, int length, bool repeated)
humlet 1:90455d5bdd8c 209 {
humlet 0:13c962fecb13 210 lock();
humlet 3:967dde37e712 211 m_channel->transfer.cmd = WRITE_MST;
humlet 3:967dde37e712 212 m_channel->transfer.slv = false;
humlet 1:90455d5bdd8c 213 m_channel->transfer.adr = address;
humlet 1:90455d5bdd8c 214 m_channel->transfer.wdta = data;
humlet 1:90455d5bdd8c 215 m_channel->transfer.len = length;
humlet 1:90455d5bdd8c 216 m_channel->transfer.rep = repeated;
humlet 3:967dde37e712 217 return sendNwait();
humlet 1:90455d5bdd8c 218 }
humlet 1:90455d5bdd8c 219
humlet 3:967dde37e712 220 int I2CDriver::writeMaster(int data)
humlet 1:90455d5bdd8c 221 {
humlet 1:90455d5bdd8c 222 lock();
humlet 1:90455d5bdd8c 223 m_channel->transfer.cmd = WRITE_BYTE;
humlet 3:967dde37e712 224 m_channel->transfer.slv = false;
humlet 1:90455d5bdd8c 225 m_channel->transfer.ack = data;
humlet 3:967dde37e712 226 return sendNwait();
humlet 0:13c962fecb13 227 }
humlet 1:90455d5bdd8c 228
humlet 3:967dde37e712 229 void I2CDriver::startMaster(void)
humlet 1:90455d5bdd8c 230 {
humlet 1:90455d5bdd8c 231 lock();
humlet 1:90455d5bdd8c 232 m_channel->transfer.cmd = START;
humlet 3:967dde37e712 233 m_channel->transfer.slv = false;
humlet 1:90455d5bdd8c 234 sendNwait();
humlet 3:967dde37e712 235 }
humlet 3:967dde37e712 236
humlet 3:967dde37e712 237 void I2CDriver::stopMaster(void)
humlet 3:967dde37e712 238 {
humlet 3:967dde37e712 239 lock();
humlet 3:967dde37e712 240 m_channel->transfer.cmd = STOP;
humlet 3:967dde37e712 241 m_channel->transfer.slv = false;
humlet 3:967dde37e712 242 sendNwait();
humlet 3:967dde37e712 243 }
humlet 3:967dde37e712 244
humlet 3:967dde37e712 245 void I2CDriver::stopSlave(void)
humlet 3:967dde37e712 246 {
humlet 3:967dde37e712 247 lock();
humlet 3:967dde37e712 248 m_channel->transfer.cmd = STOP;
humlet 3:967dde37e712 249 m_channel->transfer.slv = true;
humlet 3:967dde37e712 250 m_channel->transfer.adr = m_slaveAdr;
humlet 3:967dde37e712 251 sendNwait();
humlet 3:967dde37e712 252 }
humlet 3:967dde37e712 253
humlet 3:967dde37e712 254 int I2CDriver::receiveSlave(uint32_t timeout_ms)
humlet 3:967dde37e712 255 {
humlet 3:967dde37e712 256 lock();
humlet 3:967dde37e712 257 m_channel->transfer.cmd = RECEIVE;
humlet 3:967dde37e712 258 m_channel->transfer.slv = true;
humlet 3:967dde37e712 259 m_channel->transfer.adr = m_slaveAdr;
humlet 3:967dde37e712 260 m_channel->transfer.tmout = timeout_ms;
humlet 3:967dde37e712 261 return sendNwait();
humlet 3:967dde37e712 262 }
humlet 3:967dde37e712 263
humlet 3:967dde37e712 264 int I2CDriver::readSlave(char* data, int length)
humlet 3:967dde37e712 265 {
humlet 3:967dde37e712 266 lock();
humlet 3:967dde37e712 267 m_channel->transfer.cmd = READ_SLV;
humlet 3:967dde37e712 268 m_channel->transfer.slv = true;
humlet 3:967dde37e712 269 m_channel->transfer.adr = m_slaveAdr;
humlet 3:967dde37e712 270 m_channel->transfer.dta = data;
humlet 3:967dde37e712 271 m_channel->transfer.len = length;
humlet 3:967dde37e712 272 return sendNwait();
humlet 3:967dde37e712 273 }
humlet 3:967dde37e712 274
humlet 3:967dde37e712 275 int I2CDriver::readSlave(void)
humlet 3:967dde37e712 276 {
humlet 3:967dde37e712 277 lock();
humlet 3:967dde37e712 278 m_channel->transfer.cmd = READ_BYTE;
humlet 3:967dde37e712 279 m_channel->transfer.slv = true;
humlet 3:967dde37e712 280 m_channel->transfer.adr = m_slaveAdr;
humlet 3:967dde37e712 281 m_channel->transfer.ack = 1;
humlet 3:967dde37e712 282 return sendNwait();
humlet 3:967dde37e712 283 }
humlet 3:967dde37e712 284
humlet 3:967dde37e712 285 int I2CDriver::writeSlave(const char *data, int length)
humlet 3:967dde37e712 286 {
humlet 3:967dde37e712 287 lock();
humlet 3:967dde37e712 288 m_channel->transfer.cmd = WRITE_SLV;
humlet 3:967dde37e712 289 m_channel->transfer.slv = true;
humlet 3:967dde37e712 290 m_channel->transfer.adr = m_slaveAdr;
humlet 3:967dde37e712 291 m_channel->transfer.wdta = data;
humlet 3:967dde37e712 292 m_channel->transfer.len = length;
humlet 3:967dde37e712 293 return sendNwait();
humlet 3:967dde37e712 294 }
humlet 3:967dde37e712 295
humlet 3:967dde37e712 296 int I2CDriver::writeSlave(int data)
humlet 3:967dde37e712 297 {
humlet 3:967dde37e712 298 lock();
humlet 3:967dde37e712 299 m_channel->transfer.cmd = WRITE_BYTE;
humlet 3:967dde37e712 300 m_channel->transfer.slv = true;
humlet 3:967dde37e712 301 m_channel->transfer.adr = m_slaveAdr;
humlet 3:967dde37e712 302 m_channel->transfer.ack = data;
humlet 3:967dde37e712 303 return sendNwait();
humlet 1:90455d5bdd8c 304 }
humlet 1:90455d5bdd8c 305
humlet 1:90455d5bdd8c 306
humlet 3:967dde37e712 307
humlet 3:967dde37e712 308