furi_hal_i2c_config.c 6.4 KB

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