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:
Fri Apr 19 21:33:29 2013 +0000
Revision:
3:967dde37e712
Parent:
2:514105beb343
Child:
4:eafa7efcd771
refactored, compiles and crashes

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