i2c_workaround.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /*
  2. As of the date of releasing this code, there is (seemingly) a bug in the FZ i2c library code
  3. It is described here: https://github.com/flipperdevices/flipperzero-firmware/issues/1670
  4. This is a short-term workaround so I can keep developing while we get to the bottom of the issue
  5. FYI. *something* in the following code is the fix
  6. void furi_hal_i2c_acquire (const FuriHalI2cBusHandle* handle)
  7. {
  8. // 1. Disable the power/backlight (it uses i2c)
  9. furi_hal_power_insomnia_enter();
  10. // 2. Lock bus access
  11. handle->bus->callback(handle->bus, FuriHalI2cBusEventLock);
  12. // 3. Ensuree that no active handle set
  13. furi_check(handle->bus->current_handle == NULL);
  14. // 4. Set current handle
  15. handle->bus->current_handle = handle;
  16. // 5. Activate bus
  17. handle->bus->callback(handle->bus, FuriHalI2cBusEventActivate);
  18. // 6. Activate handle
  19. handle->callback(handle, const FuriHalI2cBusHandleEventActivate);
  20. }
  21. void furi_hal_i2c_release (const FuriHalI2cBusHandle* handle)
  22. {
  23. // Ensure that current handle is our handle
  24. furi_check(handle->bus->current_handle == handle);
  25. // 6. Deactivate handle
  26. handle->callback(handle, const FuriHalI2cBusHandleEventDeactivate);
  27. // 5. Deactivate bus
  28. handle->bus->callback(handle->bus, FuriHalI2cBusEventDeactivate);
  29. // 3,4. Reset current handle
  30. handle->bus->current_handle = NULL;
  31. // 2. Unlock bus
  32. handle->bus->callback(handle->bus, FuriHalI2cBusEventUnlock);
  33. // 1. Re-enable the power system
  34. furi_hal_power_insomnia_exit();
  35. }
  36. */
  37. #ifndef I2C_WORKAROUND_H_
  38. #define I2C_WORKAROUND_H_
  39. #include <furi_hal.h>
  40. #define ENABLE_WORKAROUND 1
  41. #if ENABLE_WORKAROUND == 1
  42. //+============================================================================ ========================================
  43. static inline bool furi_hal_Wi2c_is_device_ready(
  44. const FuriHalI2cBusHandle* const bus,
  45. const uint8_t addr,
  46. const uint32_t tmo) {
  47. furi_hal_i2c_acquire(bus);
  48. bool rv = furi_hal_i2c_is_device_ready(bus, addr, tmo);
  49. furi_hal_i2c_release(bus);
  50. return rv;
  51. }
  52. //+============================================================================
  53. static inline bool furi_hal_Wi2c_tx(
  54. const FuriHalI2cBusHandle* const bus,
  55. const uint8_t addr,
  56. const void* buf,
  57. const size_t len,
  58. const uint32_t tmo) {
  59. furi_hal_i2c_acquire(bus);
  60. bool rv = furi_hal_i2c_tx(bus, addr, buf, len, tmo);
  61. furi_hal_i2c_release(bus);
  62. return rv;
  63. }
  64. //+============================================================================
  65. static inline bool furi_hal_Wi2c_rx(
  66. const FuriHalI2cBusHandle* const bus,
  67. const uint8_t addr,
  68. void* buf,
  69. const size_t len,
  70. const uint32_t tmo) {
  71. furi_hal_i2c_acquire(bus);
  72. bool rv = furi_hal_i2c_rx(bus, addr, buf, len, tmo);
  73. furi_hal_i2c_release(bus);
  74. return rv;
  75. }
  76. //+============================================================================
  77. static inline bool furi_hal_Wi2c_trx(
  78. const FuriHalI2cBusHandle* const bus,
  79. const uint8_t addr,
  80. const void* tx,
  81. const size_t txlen,
  82. void* rx,
  83. const size_t rxlen,
  84. const uint32_t tmo) {
  85. bool rv = furi_hal_Wi2c_tx(bus, addr, tx, txlen, tmo);
  86. if(rv) rv = furi_hal_Wi2c_rx(bus, addr, rx, rxlen, tmo);
  87. return rv;
  88. }
  89. //----------------------------------------------------------------------------- ----------------------------------------
  90. #define furi_hal_i2c_is_device_ready(...) furi_hal_Wi2c_is_device_ready(__VA_ARGS__)
  91. #define furi_hal_i2c_tx(...) furi_hal_Wi2c_tx(__VA_ARGS__)
  92. #define furi_hal_i2c_rx(...) furi_hal_Wi2c_rx(__VA_ARGS__)
  93. #define furi_hal_i2c_trx(...) furi_hal_Wi2c_trx(__VA_ARGS__)
  94. #endif //ENABLE_WORKAROUND
  95. //+============================================================================ ========================================
  96. // Some devices take a moment to respond to read requests
  97. // The puts a delay between the address being set and the data being read
  98. //
  99. static inline bool furi_hal_i2c_trxd(
  100. const FuriHalI2cBusHandle* const bus,
  101. const uint8_t addr,
  102. const void* tx,
  103. const size_t txlen,
  104. void* rx,
  105. const size_t rxlen,
  106. const uint32_t tmo,
  107. const uint32_t us) {
  108. bool rv = furi_hal_i2c_tx(bus, addr, tx, txlen, tmo);
  109. if(rv) {
  110. furi_delay_us(us);
  111. rv = furi_hal_i2c_rx(bus, addr, rx, rxlen, tmo);
  112. }
  113. return rv;
  114. }
  115. #endif //I2C_WORKAROUND_H_