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:
pHysiX
Date:
Sat May 17 11:56:46 2014 +0000
Revision:
16:2c6432b37cce
Parent:
14:352609d395c1
Modified to make 400kHz default

Who changed what in which revision?

UserRevisionLine numberNew contents of line
humlet 9:65aae53a34de 1 #include "i2cRtos_api.h"
humlet 9:65aae53a34de 2
humlet 9:65aae53a34de 3 #if DEVICE_I2C
humlet 9:65aae53a34de 4
humlet 13:530968937ccb 5 #include "us_ticker_api.h"
humlet 9:65aae53a34de 6 #include "cmsis_os.h"
humlet 9:65aae53a34de 7 #include "error.h"
humlet 9:65aae53a34de 8
humlet 14:352609d395c1 9 // little helpers cloned from official i2c api
humlet 13:530968937ccb 10 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
humlet 9:65aae53a34de 11 #define I2C_CONSET(x) (x->i2c->I2CONSET)
humlet 9:65aae53a34de 12 #define I2C_CONCLR(x) (x->i2c->I2CONCLR)
humlet 9:65aae53a34de 13 #define I2C_STAT(x) (x->i2c->I2STAT)
humlet 9:65aae53a34de 14 #define I2C_DAT(x) (x->i2c->I2DAT)
humlet 13:530968937ccb 15 #elif defined(TARGET_LPC11U24)
humlet 13:530968937ccb 16 #define I2C_CONSET(x) (x->i2c->CONSET)
humlet 13:530968937ccb 17 #define I2C_CONCLR(x) (x->i2c->CONCLR)
humlet 13:530968937ccb 18 #define I2C_STAT(x) (x->i2c->STAT)
humlet 13:530968937ccb 19 #define I2C_DAT(x) (x->i2c->DAT)
humlet 13:530968937ccb 20 #endif
humlet 9:65aae53a34de 21
humlet 14:352609d395c1 22 //#include "gpio_api.h"
humlet 14:352609d395c1 23 //static gpio_t gpio[2]; // evillive
humlet 10:e3d6c92ff222 24
humlet 14:352609d395c1 25 // isr/thread data transfer struct
humlet 9:65aae53a34de 26 enum I2cIsrCmd {
humlet 9:65aae53a34de 27 readMst,
humlet 9:65aae53a34de 28 writeMst,
humlet 9:65aae53a34de 29 readSlv,
humlet 9:65aae53a34de 30 writeSlv,
humlet 9:65aae53a34de 31 waitSI
humlet 9:65aae53a34de 32 };
humlet 9:65aae53a34de 33 struct I2cIsrTransfer {
humlet 9:65aae53a34de 34 i2c_t* obj;
humlet 9:65aae53a34de 35 enum I2cIsrCmd cmd;
humlet 9:65aae53a34de 36 int len;
humlet 9:65aae53a34de 37 int cnt;
humlet 9:65aae53a34de 38 int stat;
humlet 9:65aae53a34de 39 char* rData;
humlet 9:65aae53a34de 40 const char* wData;
humlet 9:65aae53a34de 41 };
humlet 14:352609d395c1 42 // one for each channel
humlet 14:352609d395c1 43 // "volatile" has been omitted since ISR and thread do not run simultaneously, hopefully ok
humlet 14:352609d395c1 44 static struct I2cIsrTransfer i2c_transfer[2];
humlet 9:65aae53a34de 45
humlet 14:352609d395c1 46 // struct holding IRQ and semaphore ID
humlet 14:352609d395c1 47 // needed for thread<->isr communication/activation
humlet 9:65aae53a34de 48 struct IsrIrqSem {
humlet 9:65aae53a34de 49 IRQn_Type irq;
humlet 9:65aae53a34de 50 osSemaphoreId sem;
humlet 9:65aae53a34de 51 };
humlet 14:352609d395c1 52 static struct IsrIrqSem isrIrqSem[2]; // one for each channel
humlet 9:65aae53a34de 53
humlet 9:65aae53a34de 54
humlet 9:65aae53a34de 55 // little helpers cloned from official i2c api
humlet 9:65aae53a34de 56 static inline void i2c_conclr(i2c_t *obj, int start, int stop, int interrupt, int acknowledge)
humlet 9:65aae53a34de 57 {
humlet 9:65aae53a34de 58 I2C_CONCLR(obj) = (start << 5)
humlet 9:65aae53a34de 59 | (stop << 4)
humlet 9:65aae53a34de 60 | (interrupt << 3)
humlet 9:65aae53a34de 61 | (acknowledge << 2);
humlet 9:65aae53a34de 62 }
humlet 9:65aae53a34de 63 static inline void i2c_conset(i2c_t *obj, int start, int stop, int interrupt, int acknowledge)
humlet 9:65aae53a34de 64 {
humlet 9:65aae53a34de 65 I2C_CONSET(obj) = (start << 5)
humlet 9:65aae53a34de 66 | (stop << 4)
humlet 9:65aae53a34de 67 | (interrupt << 3)
humlet 9:65aae53a34de 68 | (acknowledge << 2);
humlet 9:65aae53a34de 69 }
humlet 9:65aae53a34de 70 static inline void i2c_clear_SI(i2c_t *obj)
humlet 9:65aae53a34de 71 {
humlet 9:65aae53a34de 72 i2c_conclr(obj, 0, 0, 1, 0);
humlet 9:65aae53a34de 73 }
humlet 9:65aae53a34de 74 static inline int i2c_status(i2c_t *obj)
humlet 9:65aae53a34de 75 {
humlet 9:65aae53a34de 76 return I2C_STAT(obj);
humlet 9:65aae53a34de 77 }
humlet 9:65aae53a34de 78
humlet 14:352609d395c1 79 // ISR routines
humlet 14:352609d395c1 80 // implements the same read/write sequences as the official i2c lib
humlet 10:e3d6c92ff222 81 static void i2cRtos_isr(uint32_t ch)
humlet 9:65aae53a34de 82 {
humlet 11:8c1d44595620 83 struct I2cIsrTransfer* tr=&(i2c_transfer[ch]);
humlet 12:6ddadcbbdca2 84 if(tr->cmd==waitSI) {
humlet 14:352609d395c1 85 // just waiting for an interrupt after a byte read/write or slave receive call
humlet 9:65aae53a34de 86 osSemaphoreRelease(isrIrqSem[ch].sem);
humlet 9:65aae53a34de 87 NVIC_DisableIRQ(isrIrqSem[ch].irq);
humlet 9:65aae53a34de 88 return;
humlet 9:65aae53a34de 89 }
humlet 9:65aae53a34de 90 int stat=i2c_status(tr->obj);
humlet 9:65aae53a34de 91 int stay = 0;
humlet 9:65aae53a34de 92 switch(tr->cmd) {
humlet 11:8c1d44595620 93 case readMst:
humlet 11:8c1d44595620 94 switch(stat) {
humlet 14:352609d395c1 95 case 0x50: // Data byte has been received; ACK has been returned.
humlet 11:8c1d44595620 96 (tr->rData)[tr->cnt] = (char)(I2C_DAT(tr->obj) & 0xff);
humlet 14:352609d395c1 97 case 0x40: // SLA+R has been transmitted; ACK has been received.
humlet 11:8c1d44595620 98 ++(tr->cnt);
humlet 11:8c1d44595620 99 if(tr->cnt != tr->len-1)
humlet 10:e3d6c92ff222 100 i2c_conset(tr->obj, 0, 0, 0, 1);
humlet 11:8c1d44595620 101 else
humlet 14:352609d395c1 102 i2c_conclr(tr->obj, 0, 0, 0, 1); // do not ack the last byte read
humlet 9:65aae53a34de 103 stay = 1;
humlet 11:8c1d44595620 104 break;
humlet 14:352609d395c1 105 case 0x58: // Data byte has been received; NOT ACK has been returned.
humlet 11:8c1d44595620 106 (tr->rData)[tr->cnt] = (char)(I2C_DAT(tr->obj) & 0xff);
humlet 11:8c1d44595620 107 stat=0;
humlet 11:8c1d44595620 108 break;
humlet 9:65aae53a34de 109 }
humlet 9:65aae53a34de 110 break;
humlet 11:8c1d44595620 111 case writeMst:
humlet 11:8c1d44595620 112 switch(stat) {
humlet 14:352609d395c1 113 case 0x18: // SLA+W has been transmitted; ACK has been received.
humlet 14:352609d395c1 114 case 0x28: // SLA+W has been transmitted; NOT ACK has been received.
humlet 14:352609d395c1 115 if(++(tr->cnt)!=tr->len) {
humlet 11:8c1d44595620 116 I2C_DAT(tr->obj) = (tr->wData)[tr->cnt];
humlet 11:8c1d44595620 117 stay=1;
humlet 11:8c1d44595620 118 } else {
humlet 11:8c1d44595620 119 stat=0;
humlet 11:8c1d44595620 120 }
humlet 9:65aae53a34de 121 }
humlet 9:65aae53a34de 122 break;
humlet 11:8c1d44595620 123 case readSlv:
humlet 11:8c1d44595620 124 ++(tr->cnt);
humlet 14:352609d395c1 125 if(stat==0x80 || stat==0x90) // Previously addressed with own SLA address(0x80) or geberal call (0x90); DATA has been received; ACK has been returned.
humlet 11:8c1d44595620 126 (tr->rData)[tr->cnt] = I2C_DAT(tr->obj) & 0xFF;
humlet 11:8c1d44595620 127 stay = (stat==0x80 || stat==0x90 || stat==0x060 || stat==0x70) && (tr->cnt < tr->len-1);
humlet 14:352609d395c1 128 // 60: Own SLA+W has been received; ACK has been returned. ... SLV+W???
humlet 14:352609d395c1 129 // 70: General Call address (0x00) has been received; ACK has been returned.
humlet 9:65aae53a34de 130 break;
humlet 11:8c1d44595620 131 case writeSlv:
humlet 11:8c1d44595620 132 ++(tr->cnt);
humlet 14:352609d395c1 133 stay = tr->cnt<tr->len && stat==0xb8; // Data byte in I2DAT has been transmitted; ACK has been received.
humlet 14:352609d395c1 134 if(stay) I2C_DAT(tr->obj) = tr->wData[tr->cnt];
humlet 9:65aae53a34de 135 break;
humlet 9:65aae53a34de 136 }
humlet 9:65aae53a34de 137 if(stay) {
humlet 14:352609d395c1 138 // sequence not finished => stay in ISR mode and trigger next i2c by clearing he SI bit
humlet 9:65aae53a34de 139 i2c_clear_SI(tr->obj);
humlet 9:65aae53a34de 140 } else {
humlet 14:352609d395c1 141 // sequence finished or unexpected state has been reported
humlet 14:352609d395c1 142 // => bail out of isr mode and return last status received
humlet 9:65aae53a34de 143 tr->stat = stat;
humlet 9:65aae53a34de 144 osSemaphoreRelease(isrIrqSem[ch].sem);
humlet 9:65aae53a34de 145 NVIC_DisableIRQ(isrIrqSem[ch].irq);
humlet 9:65aae53a34de 146 }
humlet 9:65aae53a34de 147 }
humlet 13:530968937ccb 148 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
humlet 11:8c1d44595620 149 static void i2cRtos_isr_ch0()
humlet 9:65aae53a34de 150 {
humlet 11:8c1d44595620 151 //gpio_write(&gpio[0], 1);
humlet 9:65aae53a34de 152 i2cRtos_isr(0);
humlet 11:8c1d44595620 153 //gpio_write(&gpio[0], 0);
humlet 9:65aae53a34de 154 }
humlet 13:530968937ccb 155 #endif
humlet 11:8c1d44595620 156 static void i2cRtos_isr_ch1()
humlet 9:65aae53a34de 157 {
humlet 11:8c1d44595620 158 //gpio_write(&gpio[1], 1);
humlet 9:65aae53a34de 159 i2cRtos_isr(1);
humlet 11:8c1d44595620 160 //gpio_write(&gpio[1], 0);
humlet 9:65aae53a34de 161 }
humlet 9:65aae53a34de 162
humlet 9:65aae53a34de 163
humlet 9:65aae53a34de 164 // determine channel
humlet 11:8c1d44595620 165 static inline uint32_t i2c_get_channel(const i2c_t *obj)
humlet 9:65aae53a34de 166 {
humlet 9:65aae53a34de 167 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
humlet 9:65aae53a34de 168 switch((I2CName)(obj->i2c)) {
humlet 9:65aae53a34de 169 case I2C_1:
humlet 9:65aae53a34de 170 return 0;
humlet 9:65aae53a34de 171 case I2C_2:
humlet 9:65aae53a34de 172 return 1;
humlet 9:65aae53a34de 173 default:
humlet 9:65aae53a34de 174 error("Dial911 i2c_get_channel: Invaid I2CName \n");
humlet 9:65aae53a34de 175 }
humlet 9:65aae53a34de 176 #endif
humlet 10:e3d6c92ff222 177 return 1;
humlet 9:65aae53a34de 178 }
humlet 9:65aae53a34de 179
humlet 9:65aae53a34de 180
humlet 14:352609d395c1 181 // Enable IRQ and wait for ISR sequence to be finished
humlet 12:6ddadcbbdca2 182 static inline void i2cRtos_wait_and_see(i2c_t *obj, int ch, uint32_t tmOut) //evillive
humlet 9:65aae53a34de 183 {
humlet 11:8c1d44595620 184 struct IsrIrqSem* iis = &(isrIrqSem[ch]);
humlet 14:352609d395c1 185 __disable_irq(); // evil, but don't want the next three lines to be interrupted
humlet 9:65aae53a34de 186 i2c_clear_SI(obj);
humlet 11:8c1d44595620 187 NVIC_ClearPendingIRQ(iis->irq);
humlet 9:65aae53a34de 188 NVIC_EnableIRQ(iis->irq);
humlet 10:e3d6c92ff222 189 __enable_irq();
humlet 14:352609d395c1 190 if(osSemaphoreWait(iis->sem, tmOut)!=1) NVIC_DisableIRQ(iis->irq); // time out => diable the IRQ
humlet 11:8c1d44595620 191 }
humlet 11:8c1d44595620 192
humlet 14:352609d395c1 193 // just wait for a generic i2c interrupt
humlet 12:6ddadcbbdca2 194 static inline void i2cRtos_waitSI(i2c_t *obj, uint32_t tmOut)
humlet 12:6ddadcbbdca2 195 {
humlet 11:8c1d44595620 196 int ch = i2c_get_channel(obj);
humlet 11:8c1d44595620 197 i2c_transfer[ch].cmd = waitSI;
humlet 11:8c1d44595620 198 i2cRtos_wait_and_see(obj, ch, tmOut);
humlet 9:65aae53a34de 199 }
humlet 9:65aae53a34de 200
humlet 14:352609d395c1 201 // master mode read sequence
humlet 9:65aae53a34de 202 int i2cRtos_read(i2c_t *obj, int address, char *data, int length, int stop)
humlet 9:65aae53a34de 203 {
humlet 12:6ddadcbbdca2 204 //gpio_write(&gpio[1], 1);
humlet 11:8c1d44595620 205 int stat = i2c_start(obj);
humlet 11:8c1d44595620 206 if ((stat != 0x10) && (stat != 0x08)) {
humlet 14:352609d395c1 207 i2cRtos_stop(obj); // use freeze free stop if the start has failed
humlet 11:8c1d44595620 208 return stat;
humlet 9:65aae53a34de 209 }
humlet 12:6ddadcbbdca2 210 //gpio_write(&gpio[1], 0);
humlet 9:65aae53a34de 211 int ch = i2c_get_channel(obj);
humlet 14:352609d395c1 212 struct I2cIsrTransfer* tr = &(i2c_transfer[ch]);
humlet 9:65aae53a34de 213 tr->obj=obj;
humlet 9:65aae53a34de 214 tr->cmd=readMst;
humlet 9:65aae53a34de 215 tr->len=length;
humlet 9:65aae53a34de 216 tr->cnt=-1;
humlet 9:65aae53a34de 217 tr->rData=data;
humlet 14:352609d395c1 218 I2C_DAT(obj) = address | 0x01; // initiate address+R write and enter isr mode
humlet 11:8c1d44595620 219 i2cRtos_wait_and_see(obj, ch,2+(length>>2)); // timeout (2+len/4)ms
humlet 11:8c1d44595620 220 stat = tr->stat;
humlet 12:6ddadcbbdca2 221 //gpio_write(&gpio[1], 1);
humlet 14:352609d395c1 222 if(stat || stop) i2cRtos_stop(obj);
humlet 12:6ddadcbbdca2 223 //gpio_write(&gpio[1], 0);
humlet 11:8c1d44595620 224 return stat;
humlet 9:65aae53a34de 225 }
humlet 9:65aae53a34de 226
humlet 14:352609d395c1 227 // master mode write sequence
humlet 9:65aae53a34de 228 int i2cRtos_write(i2c_t *obj, int address, const char *data, int length, int stop)
humlet 9:65aae53a34de 229 {
humlet 12:6ddadcbbdca2 230 //gpio_write(&gpio[1], 1);
humlet 9:65aae53a34de 231 int status = i2c_start(obj);
humlet 9:65aae53a34de 232 if ((status != 0x10) && (status != 0x08)) {
humlet 14:352609d395c1 233 i2cRtos_stop(obj); // use freeze free stop if the start has failed
humlet 9:65aae53a34de 234 return status;
humlet 9:65aae53a34de 235 }
humlet 12:6ddadcbbdca2 236 //gpio_write(&gpio[1], 0);
humlet 9:65aae53a34de 237 int ch = i2c_get_channel(obj);
humlet 12:6ddadcbbdca2 238 struct I2cIsrTransfer* tr = &(i2c_transfer[ch]); // evilive fill it locally and then copy it in one go to (volatile) mem?
humlet 12:6ddadcbbdca2 239 tr->obj = obj;
humlet 12:6ddadcbbdca2 240 tr->cmd = writeMst;
humlet 12:6ddadcbbdca2 241 tr->len = length;
humlet 12:6ddadcbbdca2 242 tr->cnt = -1;
humlet 12:6ddadcbbdca2 243 tr->wData = data;
humlet 14:352609d395c1 244 I2C_DAT(obj) = address & 0xfe; // initiate address+W write and enter isr mode
humlet 11:8c1d44595620 245 i2cRtos_wait_and_see(obj, ch, 2+(length>>2)); // timeout (2+len/4)ms
humlet 12:6ddadcbbdca2 246 //i2c_clear_SI(obj); // ... why? Also in official lib ... I guess this is the "write instead of start" bug
humlet 9:65aae53a34de 247 status = tr->stat;
humlet 12:6ddadcbbdca2 248 //gpio_write(&gpio[1], 1);
humlet 14:352609d395c1 249 if(status || stop) i2cRtos_stop(obj);
humlet 12:6ddadcbbdca2 250 //gpio_write(&gpio[1], 0);
humlet 9:65aae53a34de 251 return status;
humlet 9:65aae53a34de 252 }
humlet 9:65aae53a34de 253
humlet 14:352609d395c1 254 // read single byte from bus (master/slave)
humlet 9:65aae53a34de 255 int i2cRtos_byte_read(i2c_t *obj, int last)
humlet 9:65aae53a34de 256 {
humlet 9:65aae53a34de 257 if(last) {
humlet 9:65aae53a34de 258 i2c_conclr(obj, 0, 0, 0, 1); // send a NOT ACK
humlet 9:65aae53a34de 259 } else {
humlet 9:65aae53a34de 260 i2c_conset(obj, 0, 0, 0, 1); // send a ACK
humlet 9:65aae53a34de 261 }
humlet 11:8c1d44595620 262 i2cRtos_waitSI(obj, 2);
humlet 9:65aae53a34de 263 return (I2C_DAT(obj) & 0xff);
humlet 9:65aae53a34de 264 }
humlet 9:65aae53a34de 265
humlet 14:352609d395c1 266 // write single byte to bus (master/slave)
humlet 9:65aae53a34de 267 int i2cRtos_byte_write(i2c_t *obj, int data)
humlet 9:65aae53a34de 268 {
humlet 9:65aae53a34de 269 I2C_DAT(obj) = (data & 0xff);
humlet 11:8c1d44595620 270 i2cRtos_waitSI(obj, 2);
humlet 9:65aae53a34de 271 int stat=i2c_status(obj);
humlet 9:65aae53a34de 272 return (stat==0x18 || stat==0x28 || stat==0x40 || stat==0xb8);
humlet 9:65aae53a34de 273 }
humlet 9:65aae53a34de 274
humlet 14:352609d395c1 275 // freeze free i2c stop
humlet 14:352609d395c1 276 // the busy wait without timeout of the official i2c lib
humlet 14:352609d395c1 277 // might freeze the mbed if someone on the bus keeps the clock down
humlet 14:352609d395c1 278 // and prevents LPC's i2c controller to create a stop condition
humlet 14:352609d395c1 279 int i2cRtos_stop(i2c_t *obj)
humlet 14:352609d395c1 280 {
humlet 13:530968937ccb 281 i2c_conset(obj, 0, 1, 0, 0);
humlet 13:530968937ccb 282 i2c_clear_SI(obj);
humlet 13:530968937ccb 283 uint32_t t0=us_ticker_read();
humlet 13:530968937ccb 284 uint32_t dt=0;
humlet 14:352609d395c1 285 while((I2C_CONSET(obj) & (1 << 4)) && dt<23) {
humlet 13:530968937ccb 286 dt = us_ticker_read() - t0;
humlet 13:530968937ccb 287 }
humlet 13:530968937ccb 288 return dt<23;
humlet 13:530968937ccb 289 }
humlet 13:530968937ccb 290
humlet 13:530968937ccb 291
humlet 9:65aae53a34de 292 #if DEVICE_I2CSLAVE
humlet 9:65aae53a34de 293
humlet 14:352609d395c1 294 // determine slave's receive mode. Blocking with timeout
humlet 9:65aae53a34de 295 int i2cRtos_slave_receive(i2c_t *obj, uint32_t tmOut)
humlet 9:65aae53a34de 296 {
humlet 9:65aae53a34de 297 int retval = i2c_slave_receive(obj);
humlet 9:65aae53a34de 298 //check for pending requests
humlet 9:65aae53a34de 299 if(retval)return retval; // there is one => bail out
humlet 14:352609d395c1 300 // No request? Wait for it! ... with time out
humlet 11:8c1d44595620 301 i2cRtos_waitSI(obj, tmOut);
humlet 9:65aae53a34de 302 // check again for pending requests
humlet 9:65aae53a34de 303 return i2c_slave_receive(obj);
humlet 9:65aae53a34de 304 }
humlet 9:65aae53a34de 305
humlet 14:352609d395c1 306 // slave mode read sequence
humlet 9:65aae53a34de 307 int i2cRtos_slave_read(i2c_t *obj, char *data, int length)
humlet 9:65aae53a34de 308 {
humlet 9:65aae53a34de 309 int ch = i2c_get_channel(obj);
humlet 12:6ddadcbbdca2 310 struct I2cIsrTransfer* tr = &(i2c_transfer[ch]); // evilive fill it locally and then copy it in one go to (volatile) mem?
humlet 9:65aae53a34de 311 tr->obj=obj;
humlet 9:65aae53a34de 312 tr->cmd=readSlv;
humlet 9:65aae53a34de 313 tr->len=length;
humlet 9:65aae53a34de 314 tr->cnt=-1;
humlet 9:65aae53a34de 315 tr->rData=data;
humlet 10:e3d6c92ff222 316 i2cRtos_wait_and_see(obj, ch, 2+(length>>2)); // timeout (1+len/4)ms
humlet 9:65aae53a34de 317 if(tr->stat != 0xa0) {
humlet 14:352609d395c1 318 i2cRtos_stop(obj);
humlet 9:65aae53a34de 319 }
humlet 14:352609d395c1 320 i2c_clear_SI(obj); // stop keeping scl low
humlet 9:65aae53a34de 321 return tr->cnt; // same weird return as in official lib
humlet 9:65aae53a34de 322 }
humlet 9:65aae53a34de 323
humlet 14:352609d395c1 324 // slave mode write sequence
humlet 9:65aae53a34de 325 int i2cRtos_slave_write(i2c_t *obj, const char *data, int length)
humlet 9:65aae53a34de 326 {
humlet 9:65aae53a34de 327 if(length <= 0) {
humlet 9:65aae53a34de 328 return(0);
humlet 9:65aae53a34de 329 }
humlet 9:65aae53a34de 330 int ch = i2c_get_channel(obj);
humlet 12:6ddadcbbdca2 331 struct I2cIsrTransfer* tr = &(i2c_transfer[ch]); // evilive fill it locally and then copy it in one go to (volatile) mem?
humlet 9:65aae53a34de 332 tr->obj=obj;
humlet 9:65aae53a34de 333 tr->cmd=writeSlv;
humlet 9:65aae53a34de 334 tr->len=length;
humlet 9:65aae53a34de 335 tr->cnt=0;
humlet 9:65aae53a34de 336 tr->wData=data;
humlet 9:65aae53a34de 337 I2C_DAT(obj) = data[0];
humlet 11:8c1d44595620 338 i2cRtos_wait_and_see(obj, ch, 2+(length>>2)); // timeout (1+len/4)ms
humlet 9:65aae53a34de 339 int status = tr->stat;
humlet 9:65aae53a34de 340 if(status!=0xC0 && status!=0xC8) {
humlet 14:352609d395c1 341 i2cRtos_stop(obj);
humlet 9:65aae53a34de 342 }
humlet 14:352609d395c1 343 i2c_clear_SI(obj); // stops keeping scl low
humlet 9:65aae53a34de 344 return tr->cnt;
humlet 9:65aae53a34de 345 }
humlet 14:352609d395c1 346 #endif
humlet 11:8c1d44595620 347
humlet 11:8c1d44595620 348 // setup semaphores and hook in ISRs
humlet 11:8c1d44595620 349 void i2cRtos_init(i2c_t *obj, PinName sda, PinName scl)
humlet 11:8c1d44595620 350 {
humlet 14:352609d395c1 351 /*static int called=0;
humlet 11:8c1d44595620 352 if(!called) {
humlet 11:8c1d44595620 353 gpio_init(&gpio[0], p15, PIN_OUTPUT);
humlet 11:8c1d44595620 354 gpio_init(&gpio[1], p16, PIN_OUTPUT);
humlet 11:8c1d44595620 355 }
humlet 11:8c1d44595620 356 called = 1;
humlet 11:8c1d44595620 357 gpio_write(&gpio[0], 0);
humlet 14:352609d395c1 358 gpio_write(&gpio[1], 0);*/
humlet 13:530968937ccb 359
humlet 11:8c1d44595620 360 i2c_init(obj,sda,scl);
humlet 11:8c1d44595620 361 uint32_t ch = i2c_get_channel(obj);
humlet 11:8c1d44595620 362 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
humlet 11:8c1d44595620 363 static osSemaphoreDef(i2cIsrDrvSem_ch0);
humlet 11:8c1d44595620 364 static osSemaphoreDef(i2cIsrDrvSem_ch1);
humlet 11:8c1d44595620 365 switch(ch) {
humlet 11:8c1d44595620 366 case 0:
humlet 11:8c1d44595620 367 isrIrqSem[ch].irq = I2C1_IRQn;
humlet 11:8c1d44595620 368 NVIC_SetVector(I2C1_IRQn, (uint32_t)i2cRtos_isr_ch0);
humlet 11:8c1d44595620 369 isrIrqSem[ch].sem = osSemaphoreCreate(osSemaphore(i2cIsrDrvSem_ch0), 1);
humlet 11:8c1d44595620 370 break;
humlet 11:8c1d44595620 371 case 1:
humlet 11:8c1d44595620 372 isrIrqSem[ch].irq = I2C2_IRQn;
humlet 11:8c1d44595620 373 NVIC_SetVector(I2C2_IRQn, (uint32_t)i2cRtos_isr_ch1);
humlet 11:8c1d44595620 374 isrIrqSem[ch].sem = osSemaphoreCreate(osSemaphore(i2cIsrDrvSem_ch1), 1);
humlet 11:8c1d44595620 375 break;
humlet 11:8c1d44595620 376 }
humlet 11:8c1d44595620 377 osSemaphoreWait(isrIrqSem[ch].sem, osWaitForever);
humlet 11:8c1d44595620 378 #elif defined(TARGET_LPC11U24)
humlet 11:8c1d44595620 379 static osSemaphoreDef(i2cIsrDrvSem_ch1);
humlet 11:8c1d44595620 380 isrIrqSem[ch].irq = I2C_IRQn;
humlet 11:8c1d44595620 381 NVIC_SetVector(I2C_IRQn, (uint32_t)i2cRtos_isr_ch1);
humlet 11:8c1d44595620 382 isrIrqSem[ch].sem = osSemaphoreCreate(osSemaphore(i2cIsrDrvSem_ch1), 1);
humlet 11:8c1d44595620 383 osSemaphoreWait(isrIrqSem[ch].sem, osWaitForever);
humlet 11:8c1d44595620 384 #else
humlet 11:8c1d44595620 385 #error "Dial911 i2cRtos_init: Unsupported HW"
humlet 11:8c1d44595620 386 #endif
humlet 11:8c1d44595620 387 }
humlet 9:65aae53a34de 388 #endif