|
37 | 37 | #include "pinmap.h"
|
38 | 38 | #include "PeripheralPins.h"
|
39 | 39 |
|
40 |
| -/* Timeout values for flags and events waiting loops. These timeouts are |
41 |
| - not based on accurate values, they just guarantee that the application will |
42 |
| - not remain stuck if the I2C communication is corrupted. */ |
43 |
| -#define FLAG_TIMEOUT ((int)0x1000) |
44 |
| -#define LONG_TIMEOUT ((int)0x8000) |
45 | 40 | /* Timeout values are based on core clock and I2C clock.
|
46 | 41 | The BYTE_TIMEOUT is computed as twice the number of cycles it would
|
47 | 42 | take to send 10 bits over I2C. Most Flags should take less than that.
|
@@ -260,10 +255,9 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
|
260 | 255 | obj_s->pending_slave_rx_maxter_tx = 0;
|
261 | 256 | #endif
|
262 | 257 |
|
263 |
| -#if DEVICE_I2C_ASYNCH |
264 | 258 | // I2C Xfer operation init
|
| 259 | + obj_s->event = 0; |
265 | 260 | obj_s->XferOperation = I2C_FIRST_AND_LAST_FRAME;
|
266 |
| -#endif |
267 | 261 |
|
268 | 262 | /* Activate default IRQ handlers for sync mode
|
269 | 263 | * which would be overwritten in async mode
|
@@ -354,95 +348,83 @@ inline int i2c_stop(i2c_t *obj) {
|
354 | 348 | }
|
355 | 349 |
|
356 | 350 | int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
|
357 |
| - |
358 |
| - int timeout; |
359 |
| - int count; |
360 |
| - int value; |
361 | 351 | struct i2c_s *obj_s = I2C_S(obj);
|
362 | 352 | I2C_HandleTypeDef *handle = &(obj_s->handle);
|
| 353 | + int count = 0, ret = 0; |
| 354 | + uint32_t timeout = 0; |
363 | 355 |
|
364 |
| - i2c_start(obj); |
365 |
| - |
366 |
| - // Wait until SB flag is set |
367 |
| - timeout = FLAG_TIMEOUT; |
368 |
| - while (__HAL_I2C_GET_FLAG(handle, I2C_FLAG_SB) == RESET) { |
369 |
| - timeout--; |
370 |
| - if (timeout == 0) { |
371 |
| - return -1; |
372 |
| - } |
| 356 | + if ((obj_s->XferOperation == I2C_FIRST_AND_LAST_FRAME) || |
| 357 | + (obj_s->XferOperation == I2C_LAST_FRAME)) { |
| 358 | + if (stop) |
| 359 | + obj_s->XferOperation = I2C_FIRST_AND_LAST_FRAME; |
| 360 | + else |
| 361 | + obj_s->XferOperation = I2C_FIRST_FRAME; |
| 362 | + } else if ((obj_s->XferOperation == I2C_FIRST_FRAME) || |
| 363 | + (obj_s->XferOperation == I2C_NEXT_FRAME)) { |
| 364 | + if (stop) |
| 365 | + obj_s->XferOperation = I2C_LAST_FRAME; |
| 366 | + else |
| 367 | + obj_s->XferOperation = I2C_NEXT_FRAME; |
373 | 368 | }
|
374 | 369 |
|
375 |
| - handle->Instance->DR = __HAL_I2C_7BIT_ADD_READ(address); |
| 370 | + obj_s->event = 0; |
| 371 | + ret = HAL_I2C_Master_Sequential_Receive_IT(handle, address, (uint8_t *) data, length, obj_s->XferOperation); |
376 | 372 |
|
377 |
| - // Wait address is acknowledged |
378 |
| - timeout = FLAG_TIMEOUT; |
379 |
| - while (__HAL_I2C_GET_FLAG(handle, I2C_FLAG_ADDR) == RESET) { |
380 |
| - timeout--; |
381 |
| - if (timeout == 0) { |
382 |
| - return -1; |
| 373 | + if(ret == HAL_OK) { |
| 374 | + timeout = BYTE_TIMEOUT_US * length; |
| 375 | + /* transfer started : wait completion or timeout */ |
| 376 | + while(!(obj_s->event & I2C_EVENT_ALL) && (--timeout != 0)) { |
| 377 | + wait_us(1); |
383 | 378 | }
|
384 |
| - } |
385 |
| - __HAL_I2C_CLEAR_ADDRFLAG(handle); |
386 |
| - |
387 |
| - // Read all bytes except last one |
388 |
| - for (count = 0; count < (length - 1); count++) { |
389 |
| - value = i2c_byte_read(obj, 0); |
390 |
| - data[count] = (char)value; |
391 |
| - } |
392 | 379 |
|
393 |
| - // If not repeated start, send stop. |
394 |
| - // Warning: must be done BEFORE the data is read. |
395 |
| - if (stop) { |
396 |
| - i2c_stop(obj); |
| 380 | + if((timeout == 0) || (obj_s->event != I2C_EVENT_TRANSFER_COMPLETE)) { |
| 381 | + /* re-init IP to try and get back in a working state */ |
| 382 | + i2c_init(obj, obj_s->sda, obj_s->scl); |
| 383 | + } else { |
| 384 | + count = length; |
| 385 | + } |
397 | 386 | }
|
398 | 387 |
|
399 |
| - // Read the last byte |
400 |
| - value = i2c_byte_read(obj, 1); |
401 |
| - data[count] = (char)value; |
402 |
| - |
403 |
| - return length; |
| 388 | + return count; |
404 | 389 | }
|
405 | 390 |
|
406 | 391 | int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
|
407 |
| - |
408 |
| - int timeout; |
409 |
| - int count; |
410 | 392 | struct i2c_s *obj_s = I2C_S(obj);
|
411 | 393 | I2C_HandleTypeDef *handle = &(obj_s->handle);
|
| 394 | + int count = 0, ret = 0; |
| 395 | + uint32_t timeout = 0; |
412 | 396 |
|
413 |
| - i2c_start(obj); |
414 |
| - |
415 |
| - // Wait until SB flag is set |
416 |
| - timeout = FLAG_TIMEOUT; |
417 |
| - while (__HAL_I2C_GET_FLAG(handle, I2C_FLAG_SB) == RESET) { |
418 |
| - timeout--; |
419 |
| - if (timeout == 0) { |
420 |
| - return -1; |
421 |
| - } |
| 397 | + if ((obj_s->XferOperation == I2C_FIRST_AND_LAST_FRAME) || |
| 398 | + (obj_s->XferOperation == I2C_LAST_FRAME)) { |
| 399 | + if (stop) |
| 400 | + obj_s->XferOperation = I2C_FIRST_AND_LAST_FRAME; |
| 401 | + else |
| 402 | + obj_s->XferOperation = I2C_FIRST_FRAME; |
| 403 | + } else if ((obj_s->XferOperation == I2C_FIRST_FRAME) || |
| 404 | + (obj_s->XferOperation == I2C_NEXT_FRAME)) { |
| 405 | + if (stop) |
| 406 | + obj_s->XferOperation = I2C_LAST_FRAME; |
| 407 | + else |
| 408 | + obj_s->XferOperation = I2C_NEXT_FRAME; |
422 | 409 | }
|
423 | 410 |
|
424 |
| - handle->Instance->DR = __HAL_I2C_7BIT_ADD_WRITE(address); |
| 411 | + obj_s->event = 0; |
425 | 412 |
|
426 |
| - // Wait address is acknowledged |
427 |
| - timeout = FLAG_TIMEOUT; |
428 |
| - while (__HAL_I2C_GET_FLAG(handle, I2C_FLAG_ADDR) == RESET) { |
429 |
| - timeout--; |
430 |
| - if (timeout == 0) { |
431 |
| - return -1; |
432 |
| - } |
433 |
| - } |
434 |
| - __HAL_I2C_CLEAR_ADDRFLAG(handle); |
| 413 | + ret = HAL_I2C_Master_Sequential_Transmit_IT(handle, address, (uint8_t *) data, length, obj_s->XferOperation); |
435 | 414 |
|
436 |
| - for (count = 0; count < length; count++) { |
437 |
| - if (i2c_byte_write(obj, data[count]) != 1) { |
438 |
| - i2c_stop(obj); |
439 |
| - return -1; |
| 415 | + if(ret == HAL_OK) { |
| 416 | + timeout = BYTE_TIMEOUT_US * length; |
| 417 | + /* transfer started : wait completion or timeout */ |
| 418 | + while(!(obj_s->event & I2C_EVENT_ALL) && (--timeout != 0)) { |
| 419 | + wait_us(1); |
440 | 420 | }
|
441 |
| - } |
442 | 421 |
|
443 |
| - // If not repeated start, send stop. |
444 |
| - if (stop) { |
445 |
| - i2c_stop(obj); |
| 422 | + if((timeout == 0) || (obj_s->event != I2C_EVENT_TRANSFER_COMPLETE)) { |
| 423 | + /* re-init IP to try and get back in a working state */ |
| 424 | + i2c_init(obj, obj_s->sda, obj_s->scl); |
| 425 | + } else { |
| 426 | + count = length; |
| 427 | + } |
446 | 428 | }
|
447 | 429 |
|
448 | 430 | return count;
|
@@ -673,26 +655,25 @@ int i2c_slave_write(i2c_t *obj, const char *data, int length) {
|
673 | 655 |
|
674 | 656 | #endif // DEVICE_I2CSLAVE
|
675 | 657 |
|
676 |
| -#if DEVICE_I2C_ASYNCH |
677 |
| - |
678 | 658 | void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c){
|
679 | 659 | /* Get object ptr based on handler ptr */
|
680 | 660 | i2c_t *obj = get_i2c_obj(hi2c);
|
681 | 661 | struct i2c_s *obj_s = I2C_S(obj);
|
682 | 662 |
|
| 663 | +#if DEVICE_I2C_ASYNCH |
683 | 664 | /* Handle potential Tx/Rx use case */
|
684 | 665 | if ((obj->tx_buff.length) && (obj->rx_buff.length)) {
|
685 |
| - |
686 |
| - if (obj_s->stop) { |
| 666 | + if (obj_s->stop) { |
687 | 667 | obj_s->XferOperation = I2C_LAST_FRAME;
|
688 |
| - } |
689 |
| - else { |
| 668 | + } else { |
690 | 669 | obj_s->XferOperation = I2C_NEXT_FRAME;
|
691 | 670 | }
|
692 | 671 |
|
693 | 672 | HAL_I2C_Master_Sequential_Receive_IT(hi2c, obj_s->address, (uint8_t*)obj->rx_buff.buffer , obj->rx_buff.length, obj_s->XferOperation);
|
694 | 673 | }
|
695 |
| - else { |
| 674 | + else |
| 675 | +#endif |
| 676 | + { |
696 | 677 | /* Set event flag */
|
697 | 678 | obj_s->event = I2C_EVENT_TRANSFER_COMPLETE;
|
698 | 679 | }
|
@@ -720,6 +701,7 @@ void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c){
|
720 | 701 | obj_s->event = I2C_EVENT_ERROR;
|
721 | 702 | }
|
722 | 703 |
|
| 704 | +#if DEVICE_I2C_ASYNCH |
723 | 705 | void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c){
|
724 | 706 | /* Get object ptr based on handler ptr */
|
725 | 707 | i2c_t *obj = get_i2c_obj(hi2c);
|
|
0 commit comments