i2c_workaround.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  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 (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, FuriHalI2cBusHandleEventActivate);
  20. }
  21. void furi_hal_i2c_release (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, 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
  44. bool furi_hal_Wi2c_is_device_ready (FuriHalI2cBusHandle* const bus, const uint8_t addr, const uint32_t tmo)
  45. {
  46. furi_hal_i2c_acquire(bus);
  47. bool rv = furi_hal_i2c_is_device_ready(bus, addr, tmo);
  48. furi_hal_i2c_release(bus);
  49. return rv;
  50. }
  51. //+============================================================================
  52. static inline
  53. bool furi_hal_Wi2c_tx ( FuriHalI2cBusHandle* const bus, const uint8_t addr,
  54. const void* buf, const size_t len, const uint32_t tmo )
  55. {
  56. furi_hal_i2c_acquire(bus);
  57. bool rv = furi_hal_i2c_tx(bus, addr, buf, len, tmo);
  58. furi_hal_i2c_release(bus);
  59. return rv;
  60. }
  61. //+============================================================================
  62. static inline
  63. bool furi_hal_Wi2c_rx ( FuriHalI2cBusHandle* const bus, const uint8_t addr,
  64. void* buf, const size_t len, const uint32_t tmo )
  65. {
  66. furi_hal_i2c_acquire(bus);
  67. bool rv = furi_hal_i2c_rx(bus, addr, buf, len, tmo);
  68. furi_hal_i2c_release(bus);
  69. return rv;
  70. }
  71. //+============================================================================
  72. static inline
  73. bool furi_hal_Wi2c_trx ( FuriHalI2cBusHandle* const bus, const uint8_t addr,
  74. const void* tx, const size_t txlen,
  75. void* rx, const size_t rxlen, const uint32_t tmo )
  76. {
  77. bool rv = furi_hal_Wi2c_tx(bus, addr, tx, txlen, tmo);
  78. if (rv) rv = furi_hal_Wi2c_rx(bus, addr, rx, rxlen, tmo);
  79. return rv;
  80. }
  81. //----------------------------------------------------------------------------- ----------------------------------------
  82. # define furi_hal_i2c_is_device_ready(...) furi_hal_Wi2c_is_device_ready(__VA_ARGS__)
  83. # define furi_hal_i2c_tx(...) furi_hal_Wi2c_tx(__VA_ARGS__)
  84. # define furi_hal_i2c_rx(...) furi_hal_Wi2c_rx(__VA_ARGS__)
  85. # define furi_hal_i2c_trx(...) furi_hal_Wi2c_trx(__VA_ARGS__)
  86. #endif //ENABLE_WORKAROUND
  87. //+============================================================================ ========================================
  88. // Some devices take a moment to respond to read requests
  89. // The puts a delay between the address being set and the data being read
  90. //
  91. static inline
  92. bool furi_hal_i2c_trxd ( FuriHalI2cBusHandle* const bus, const uint8_t addr,
  93. const void* tx, const size_t txlen,
  94. void* rx, const size_t rxlen, const uint32_t tmo, const uint32_t us )
  95. {
  96. bool rv = furi_hal_i2c_tx(bus, addr, tx, txlen, tmo);
  97. if (rv) {
  98. furi_delay_us(us);
  99. rv = furi_hal_i2c_rx(bus, addr, rx, rxlen, tmo);
  100. }
  101. return rv;
  102. }
  103. #endif //I2C_WORKAROUND_H_