furi_hal_i2c_config.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. #include <furi_hal_i2c_config.h>
  2. #include <furi_hal_resources.h>
  3. #include <furi_hal_version.h>
  4. #include <stm32wbxx_ll_bus.h>
  5. #include <stm32wbxx_ll_rcc.h>
  6. /** Timing register value is computed with the STM32CubeMX Tool,
  7. * Standard Mode @100kHz with I2CCLK = 64 MHz,
  8. * rise time = 0ns, fall time = 0ns
  9. */
  10. #define FURI_HAL_I2C_CONFIG_POWER_I2C_TIMINGS_100 0x10707DBC
  11. /** Timing register value is computed with the STM32CubeMX Tool,
  12. * Fast Mode @400kHz with I2CCLK = 64 MHz,
  13. * rise time = 0ns, fall time = 0ns
  14. */
  15. #define FURI_HAL_I2C_CONFIG_POWER_I2C_TIMINGS_400 0x00602173
  16. FuriMutex* furi_hal_i2c_bus_power_mutex = NULL;
  17. static void furi_hal_i2c_bus_power_event(FuriHalI2cBus* bus, FuriHalI2cBusEvent event) {
  18. if(event == FuriHalI2cBusEventInit) {
  19. furi_hal_i2c_bus_power_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
  20. FURI_CRITICAL_ENTER();
  21. LL_RCC_SetI2CClockSource(LL_RCC_I2C1_CLKSOURCE_PCLK1);
  22. LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C1);
  23. FURI_CRITICAL_EXIT();
  24. bus->current_handle = NULL;
  25. } else if(event == FuriHalI2cBusEventDeinit) {
  26. furi_mutex_free(furi_hal_i2c_bus_power_mutex);
  27. FURI_CRITICAL_ENTER();
  28. LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C1);
  29. LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C1);
  30. FURI_CRITICAL_EXIT();
  31. } else if(event == FuriHalI2cBusEventLock) {
  32. furi_check(
  33. furi_mutex_acquire(furi_hal_i2c_bus_power_mutex, FuriWaitForever) == FuriStatusOk);
  34. } else if(event == FuriHalI2cBusEventUnlock) {
  35. furi_check(furi_mutex_release(furi_hal_i2c_bus_power_mutex) == FuriStatusOk);
  36. } else if(event == FuriHalI2cBusEventActivate) {
  37. FURI_CRITICAL_ENTER();
  38. LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C1);
  39. FURI_CRITICAL_EXIT();
  40. } else if(event == FuriHalI2cBusEventDeactivate) {
  41. FURI_CRITICAL_ENTER();
  42. LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C1);
  43. FURI_CRITICAL_EXIT();
  44. }
  45. }
  46. FuriHalI2cBus furi_hal_i2c_bus_power = {
  47. .i2c = I2C1,
  48. .callback = furi_hal_i2c_bus_power_event,
  49. };
  50. FuriMutex* furi_hal_i2c_bus_external_mutex = NULL;
  51. static void furi_hal_i2c_bus_external_event(FuriHalI2cBus* bus, FuriHalI2cBusEvent event) {
  52. if(event == FuriHalI2cBusEventInit) {
  53. furi_hal_i2c_bus_external_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
  54. FURI_CRITICAL_ENTER();
  55. LL_RCC_SetI2CClockSource(LL_RCC_I2C3_CLKSOURCE_PCLK1);
  56. LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C3);
  57. FURI_CRITICAL_EXIT();
  58. bus->current_handle = NULL;
  59. } else if(event == FuriHalI2cBusEventDeinit) {
  60. furi_mutex_free(furi_hal_i2c_bus_external_mutex);
  61. FURI_CRITICAL_ENTER();
  62. LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C3);
  63. LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C3);
  64. FURI_CRITICAL_EXIT();
  65. } else if(event == FuriHalI2cBusEventLock) {
  66. furi_check(
  67. furi_mutex_acquire(furi_hal_i2c_bus_external_mutex, FuriWaitForever) == FuriStatusOk);
  68. } else if(event == FuriHalI2cBusEventUnlock) {
  69. furi_check(furi_mutex_release(furi_hal_i2c_bus_external_mutex) == FuriStatusOk);
  70. } else if(event == FuriHalI2cBusEventActivate) {
  71. FURI_CRITICAL_ENTER();
  72. LL_RCC_SetI2CClockSource(LL_RCC_I2C3_CLKSOURCE_PCLK1);
  73. LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C3);
  74. FURI_CRITICAL_EXIT();
  75. } else if(event == FuriHalI2cBusEventDeactivate) {
  76. FURI_CRITICAL_ENTER();
  77. LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C3);
  78. FURI_CRITICAL_EXIT();
  79. }
  80. }
  81. FuriHalI2cBus furi_hal_i2c_bus_external = {
  82. .i2c = I2C3,
  83. .callback = furi_hal_i2c_bus_external_event,
  84. };
  85. void furi_hal_i2c_bus_handle_power_event(
  86. FuriHalI2cBusHandle* handle,
  87. FuriHalI2cBusHandleEvent event) {
  88. if(event == FuriHalI2cBusHandleEventActivate) {
  89. furi_hal_gpio_init_ex(
  90. &gpio_i2c_power_sda,
  91. GpioModeAltFunctionOpenDrain,
  92. GpioPullNo,
  93. GpioSpeedLow,
  94. GpioAltFn4I2C1);
  95. furi_hal_gpio_init_ex(
  96. &gpio_i2c_power_scl,
  97. GpioModeAltFunctionOpenDrain,
  98. GpioPullNo,
  99. GpioSpeedLow,
  100. GpioAltFn4I2C1);
  101. LL_I2C_InitTypeDef I2C_InitStruct;
  102. I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;
  103. I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;
  104. I2C_InitStruct.DigitalFilter = 0;
  105. I2C_InitStruct.OwnAddress1 = 0;
  106. I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
  107. I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
  108. if(furi_hal_version_get_hw_version() > 10) {
  109. I2C_InitStruct.Timing = FURI_HAL_I2C_CONFIG_POWER_I2C_TIMINGS_400;
  110. } else {
  111. I2C_InitStruct.Timing = FURI_HAL_I2C_CONFIG_POWER_I2C_TIMINGS_100;
  112. }
  113. LL_I2C_Init(handle->bus->i2c, &I2C_InitStruct);
  114. // I2C is enabled at this point
  115. LL_I2C_EnableAutoEndMode(handle->bus->i2c);
  116. LL_I2C_SetOwnAddress2(handle->bus->i2c, 0, LL_I2C_OWNADDRESS2_NOMASK);
  117. LL_I2C_DisableOwnAddress2(handle->bus->i2c);
  118. LL_I2C_DisableGeneralCall(handle->bus->i2c);
  119. LL_I2C_EnableClockStretching(handle->bus->i2c);
  120. } else if(event == FuriHalI2cBusHandleEventDeactivate) {
  121. LL_I2C_Disable(handle->bus->i2c);
  122. furi_hal_gpio_write(&gpio_i2c_power_sda, 1);
  123. furi_hal_gpio_write(&gpio_i2c_power_scl, 1);
  124. furi_hal_gpio_init_ex(
  125. &gpio_i2c_power_sda, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused);
  126. furi_hal_gpio_init_ex(
  127. &gpio_i2c_power_scl, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused);
  128. }
  129. }
  130. FuriHalI2cBusHandle furi_hal_i2c_handle_power = {
  131. .bus = &furi_hal_i2c_bus_power,
  132. .callback = furi_hal_i2c_bus_handle_power_event,
  133. };
  134. void furi_hal_i2c_bus_handle_external_event(
  135. FuriHalI2cBusHandle* handle,
  136. FuriHalI2cBusHandleEvent event) {
  137. if(event == FuriHalI2cBusHandleEventActivate) {
  138. furi_hal_gpio_init_ex(
  139. &gpio_ext_pc0, GpioModeAltFunctionOpenDrain, GpioPullNo, GpioSpeedLow, GpioAltFn4I2C3);
  140. furi_hal_gpio_init_ex(
  141. &gpio_ext_pc1, GpioModeAltFunctionOpenDrain, GpioPullNo, GpioSpeedLow, GpioAltFn4I2C3);
  142. LL_I2C_InitTypeDef I2C_InitStruct;
  143. I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;
  144. I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;
  145. I2C_InitStruct.DigitalFilter = 0;
  146. I2C_InitStruct.OwnAddress1 = 0;
  147. I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
  148. I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
  149. I2C_InitStruct.Timing = FURI_HAL_I2C_CONFIG_POWER_I2C_TIMINGS_100;
  150. LL_I2C_Init(handle->bus->i2c, &I2C_InitStruct);
  151. // I2C is enabled at this point
  152. LL_I2C_EnableAutoEndMode(handle->bus->i2c);
  153. LL_I2C_SetOwnAddress2(handle->bus->i2c, 0, LL_I2C_OWNADDRESS2_NOMASK);
  154. LL_I2C_DisableOwnAddress2(handle->bus->i2c);
  155. LL_I2C_DisableGeneralCall(handle->bus->i2c);
  156. LL_I2C_EnableClockStretching(handle->bus->i2c);
  157. } else if(event == FuriHalI2cBusHandleEventDeactivate) {
  158. LL_I2C_Disable(handle->bus->i2c);
  159. furi_hal_gpio_write(&gpio_ext_pc0, 1);
  160. furi_hal_gpio_write(&gpio_ext_pc1, 1);
  161. furi_hal_gpio_init_ex(
  162. &gpio_ext_pc0, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused);
  163. furi_hal_gpio_init_ex(
  164. &gpio_ext_pc1, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused);
  165. }
  166. }
  167. FuriHalI2cBusHandle furi_hal_i2c_handle_external = {
  168. .bus = &furi_hal_i2c_bus_external,
  169. .callback = furi_hal_i2c_bus_handle_external_event,
  170. };