furi_hal_i2c_config.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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. osMutexId_t 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 = osMutexNew(NULL);
  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_check(osMutexDelete(furi_hal_i2c_bus_power_mutex) == osOK);
  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(osMutexAcquire(furi_hal_i2c_bus_power_mutex, osWaitForever) == osOK);
  33. } else if(event == FuriHalI2cBusEventUnlock) {
  34. furi_check(osMutexRelease(furi_hal_i2c_bus_power_mutex) == osOK);
  35. } else if(event == FuriHalI2cBusEventActivate) {
  36. FURI_CRITICAL_ENTER();
  37. LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C1);
  38. FURI_CRITICAL_EXIT();
  39. } else if(event == FuriHalI2cBusEventDeactivate) {
  40. FURI_CRITICAL_ENTER();
  41. LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C1);
  42. FURI_CRITICAL_EXIT();
  43. }
  44. }
  45. FuriHalI2cBus furi_hal_i2c_bus_power = {
  46. .i2c = I2C1,
  47. .callback = furi_hal_i2c_bus_power_event,
  48. };
  49. osMutexId_t furi_hal_i2c_bus_external_mutex = NULL;
  50. static void furi_hal_i2c_bus_external_event(FuriHalI2cBus* bus, FuriHalI2cBusEvent event) {
  51. if(event == FuriHalI2cBusEventInit) {
  52. furi_hal_i2c_bus_external_mutex = osMutexNew(NULL);
  53. FURI_CRITICAL_ENTER();
  54. LL_RCC_SetI2CClockSource(LL_RCC_I2C3_CLKSOURCE_PCLK1);
  55. LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C3);
  56. FURI_CRITICAL_EXIT();
  57. bus->current_handle = NULL;
  58. } else if(event == FuriHalI2cBusEventDeinit) {
  59. furi_check(osMutexDelete(furi_hal_i2c_bus_external_mutex) == osOK);
  60. FURI_CRITICAL_ENTER();
  61. LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C3);
  62. LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C3);
  63. FURI_CRITICAL_EXIT();
  64. } else if(event == FuriHalI2cBusEventLock) {
  65. furi_check(osMutexAcquire(furi_hal_i2c_bus_external_mutex, osWaitForever) == osOK);
  66. } else if(event == FuriHalI2cBusEventUnlock) {
  67. furi_check(osMutexRelease(furi_hal_i2c_bus_external_mutex) == osOK);
  68. } else if(event == FuriHalI2cBusEventActivate) {
  69. FURI_CRITICAL_ENTER();
  70. LL_RCC_SetI2CClockSource(LL_RCC_I2C3_CLKSOURCE_PCLK1);
  71. LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C3);
  72. FURI_CRITICAL_EXIT();
  73. } else if(event == FuriHalI2cBusEventDeactivate) {
  74. FURI_CRITICAL_ENTER();
  75. LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C3);
  76. FURI_CRITICAL_EXIT();
  77. }
  78. }
  79. FuriHalI2cBus furi_hal_i2c_bus_external = {
  80. .i2c = I2C3,
  81. .callback = furi_hal_i2c_bus_external_event,
  82. };
  83. void furi_hal_i2c_bus_handle_power_event(
  84. FuriHalI2cBusHandle* handle,
  85. FuriHalI2cBusHandleEvent event) {
  86. if(event == FuriHalI2cBusHandleEventActivate) {
  87. furi_hal_gpio_init_ex(
  88. &gpio_i2c_power_sda,
  89. GpioModeAltFunctionOpenDrain,
  90. GpioPullNo,
  91. GpioSpeedLow,
  92. GpioAltFn4I2C1);
  93. furi_hal_gpio_init_ex(
  94. &gpio_i2c_power_scl,
  95. GpioModeAltFunctionOpenDrain,
  96. GpioPullNo,
  97. GpioSpeedLow,
  98. GpioAltFn4I2C1);
  99. LL_I2C_InitTypeDef I2C_InitStruct = {0};
  100. I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;
  101. I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;
  102. I2C_InitStruct.DigitalFilter = 0;
  103. I2C_InitStruct.OwnAddress1 = 0;
  104. I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
  105. I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
  106. if(furi_hal_version_get_hw_version() > 10) {
  107. I2C_InitStruct.Timing = FURI_HAL_I2C_CONFIG_POWER_I2C_TIMINGS_400;
  108. } else {
  109. I2C_InitStruct.Timing = FURI_HAL_I2C_CONFIG_POWER_I2C_TIMINGS_100;
  110. }
  111. LL_I2C_Init(handle->bus->i2c, &I2C_InitStruct);
  112. // I2C is enabled at this point
  113. LL_I2C_EnableAutoEndMode(handle->bus->i2c);
  114. LL_I2C_SetOwnAddress2(handle->bus->i2c, 0, LL_I2C_OWNADDRESS2_NOMASK);
  115. LL_I2C_DisableOwnAddress2(handle->bus->i2c);
  116. LL_I2C_DisableGeneralCall(handle->bus->i2c);
  117. LL_I2C_EnableClockStretching(handle->bus->i2c);
  118. } else if(event == FuriHalI2cBusHandleEventDeactivate) {
  119. LL_I2C_Disable(handle->bus->i2c);
  120. furi_hal_gpio_write(&gpio_i2c_power_sda, 1);
  121. furi_hal_gpio_write(&gpio_i2c_power_scl, 1);
  122. furi_hal_gpio_init_ex(
  123. &gpio_i2c_power_sda, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused);
  124. furi_hal_gpio_init_ex(
  125. &gpio_i2c_power_scl, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused);
  126. }
  127. }
  128. FuriHalI2cBusHandle furi_hal_i2c_handle_power = {
  129. .bus = &furi_hal_i2c_bus_power,
  130. .callback = furi_hal_i2c_bus_handle_power_event,
  131. };
  132. void furi_hal_i2c_bus_handle_external_event(
  133. FuriHalI2cBusHandle* handle,
  134. FuriHalI2cBusHandleEvent event) {
  135. if(event == FuriHalI2cBusHandleEventActivate) {
  136. furi_hal_gpio_init_ex(
  137. &gpio_ext_pc0, GpioModeAltFunctionOpenDrain, GpioPullNo, GpioSpeedLow, GpioAltFn4I2C3);
  138. furi_hal_gpio_init_ex(
  139. &gpio_ext_pc1, GpioModeAltFunctionOpenDrain, GpioPullNo, GpioSpeedLow, GpioAltFn4I2C3);
  140. LL_I2C_InitTypeDef I2C_InitStruct = {0};
  141. I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;
  142. I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;
  143. I2C_InitStruct.DigitalFilter = 0;
  144. I2C_InitStruct.OwnAddress1 = 0;
  145. I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
  146. I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
  147. I2C_InitStruct.Timing = FURI_HAL_I2C_CONFIG_POWER_I2C_TIMINGS_100;
  148. LL_I2C_Init(handle->bus->i2c, &I2C_InitStruct);
  149. // I2C is enabled at this point
  150. LL_I2C_EnableAutoEndMode(handle->bus->i2c);
  151. LL_I2C_SetOwnAddress2(handle->bus->i2c, 0, LL_I2C_OWNADDRESS2_NOMASK);
  152. LL_I2C_DisableOwnAddress2(handle->bus->i2c);
  153. LL_I2C_DisableGeneralCall(handle->bus->i2c);
  154. LL_I2C_EnableClockStretching(handle->bus->i2c);
  155. } else if(event == FuriHalI2cBusHandleEventDeactivate) {
  156. LL_I2C_Disable(handle->bus->i2c);
  157. furi_hal_gpio_write(&gpio_ext_pc0, 1);
  158. furi_hal_gpio_write(&gpio_ext_pc1, 1);
  159. furi_hal_gpio_init_ex(
  160. &gpio_ext_pc0, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused);
  161. furi_hal_gpio_init_ex(
  162. &gpio_ext_pc1, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused);
  163. }
  164. }
  165. FuriHalI2cBusHandle furi_hal_i2c_handle_external = {
  166. .bus = &furi_hal_i2c_bus_external,
  167. .callback = furi_hal_i2c_bus_handle_external_event,
  168. };