furi-hal-i2c-config.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  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. LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
  19. LL_RCC_SetI2CClockSource(LL_RCC_I2C1_CLKSOURCE_PCLK1);
  20. LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C1);
  21. bus->current_handle = NULL;
  22. } else if (event == FuriHalI2cBusEventDeinit) {
  23. osMutexDelete(furi_hal_i2c_bus_power_mutex);
  24. } else if (event == FuriHalI2cBusEventLock) {
  25. furi_check(osMutexAcquire(furi_hal_i2c_bus_power_mutex, osWaitForever) == osOK);
  26. } else if (event == FuriHalI2cBusEventUnlock) {
  27. furi_check(osMutexRelease(furi_hal_i2c_bus_power_mutex) == osOK);
  28. } else if (event == FuriHalI2cBusEventActivate) {
  29. LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C1);
  30. } else if (event == FuriHalI2cBusEventDeactivate) {
  31. LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C1);
  32. }
  33. }
  34. FuriHalI2cBus furi_hal_i2c_bus_power = {
  35. .i2c=I2C1,
  36. .callback=furi_hal_i2c_bus_power_event,
  37. };
  38. osMutexId_t furi_hal_i2c_bus_external_mutex = NULL;
  39. static void furi_hal_i2c_bus_external_event(FuriHalI2cBus* bus, FuriHalI2cBusEvent event) {
  40. if (event == FuriHalI2cBusEventActivate) {
  41. LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C3);
  42. LL_RCC_SetI2CClockSource(LL_RCC_I2C3_CLKSOURCE_PCLK1);
  43. LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C3);
  44. } else if (event == FuriHalI2cBusEventDeactivate) {
  45. LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C3);
  46. }
  47. }
  48. FuriHalI2cBus furi_hal_i2c_bus_external = {
  49. .i2c=I2C3,
  50. .callback=furi_hal_i2c_bus_external_event,
  51. };
  52. void furi_hal_i2c_bus_handle_power_event(FuriHalI2cBusHandle* handle, FuriHalI2cBusHandleEvent event) {
  53. if (event == FuriHalI2cBusHandleEventActivate) {
  54. hal_gpio_init_ex(&gpio_i2c_power_sda, GpioModeAltFunctionOpenDrain, GpioPullNo, GpioSpeedLow, GpioAltFn4I2C1);
  55. hal_gpio_init_ex(&gpio_i2c_power_scl, GpioModeAltFunctionOpenDrain, GpioPullNo, GpioSpeedLow, GpioAltFn4I2C1);
  56. LL_I2C_InitTypeDef I2C_InitStruct = {0};
  57. I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;
  58. I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;
  59. I2C_InitStruct.DigitalFilter = 0;
  60. I2C_InitStruct.OwnAddress1 = 0;
  61. I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
  62. I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
  63. if (furi_hal_version_get_hw_version() > 10) {
  64. I2C_InitStruct.Timing = FURI_HAL_I2C_CONFIG_POWER_I2C_TIMINGS_400;
  65. } else {
  66. I2C_InitStruct.Timing = FURI_HAL_I2C_CONFIG_POWER_I2C_TIMINGS_100;
  67. }
  68. LL_I2C_Init(handle->bus->i2c, &I2C_InitStruct);
  69. LL_I2C_EnableAutoEndMode(handle->bus->i2c);
  70. LL_I2C_SetOwnAddress2(handle->bus->i2c, 0, LL_I2C_OWNADDRESS2_NOMASK);
  71. LL_I2C_DisableOwnAddress2(handle->bus->i2c);
  72. LL_I2C_DisableGeneralCall(handle->bus->i2c);
  73. LL_I2C_EnableClockStretching(handle->bus->i2c);
  74. LL_I2C_Enable(handle->bus->i2c);
  75. } else if (event == FuriHalI2cBusHandleEventDeactivate) {
  76. LL_I2C_Disable(handle->bus->i2c);
  77. hal_gpio_write(&gpio_i2c_power_sda, 1);
  78. hal_gpio_write(&gpio_i2c_power_scl, 1);
  79. hal_gpio_init_ex(&gpio_i2c_power_sda, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused);
  80. hal_gpio_init_ex(&gpio_i2c_power_scl, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused);
  81. }
  82. }
  83. FuriHalI2cBusHandle furi_hal_i2c_handle_power = {
  84. .bus = &furi_hal_i2c_bus_power,
  85. .callback = furi_hal_i2c_bus_handle_power_event,
  86. };
  87. void furi_hal_i2c_bus_handle_external_event(FuriHalI2cBusHandle* handle, FuriHalI2cBusHandleEvent event) {
  88. if (event == FuriHalI2cBusHandleEventActivate) {
  89. hal_gpio_init_ex(&gpio_ext_pc0, GpioModeAltFunctionOpenDrain, GpioPullNo, GpioSpeedLow, GpioAltFn4I2C3);
  90. hal_gpio_init_ex(&gpio_ext_pc1, GpioModeAltFunctionOpenDrain, GpioPullNo, GpioSpeedLow, GpioAltFn4I2C3);
  91. LL_I2C_InitTypeDef I2C_InitStruct = {0};
  92. I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;
  93. I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;
  94. I2C_InitStruct.DigitalFilter = 0;
  95. I2C_InitStruct.OwnAddress1 = 0;
  96. I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
  97. I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
  98. I2C_InitStruct.Timing = FURI_HAL_I2C_CONFIG_POWER_I2C_TIMINGS_100;
  99. LL_I2C_Init(handle->bus->i2c, &I2C_InitStruct);
  100. LL_I2C_EnableAutoEndMode(handle->bus->i2c);
  101. LL_I2C_SetOwnAddress2(handle->bus->i2c, 0, LL_I2C_OWNADDRESS2_NOMASK);
  102. LL_I2C_DisableOwnAddress2(handle->bus->i2c);
  103. LL_I2C_DisableGeneralCall(handle->bus->i2c);
  104. LL_I2C_EnableClockStretching(handle->bus->i2c);
  105. LL_I2C_Enable(handle->bus->i2c);
  106. } else if (event == FuriHalI2cBusHandleEventDeactivate) {
  107. LL_I2C_Disable(handle->bus->i2c);
  108. hal_gpio_write(&gpio_ext_pc0, 1);
  109. hal_gpio_write(&gpio_ext_pc1, 1);
  110. hal_gpio_init_ex(&gpio_ext_pc0, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused);
  111. hal_gpio_init_ex(&gpio_ext_pc1, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused);
  112. }
  113. }
  114. FuriHalI2cBusHandle furi_hal_i2c_handle_external = {
  115. .bus = &furi_hal_i2c_bus_external,
  116. .callback = furi_hal_i2c_bus_handle_external_event,
  117. };