adc_share_hw_ctrl.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /*
  2. * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * ADC is shared by multiple components, including:
  8. * - esp_phy
  9. * - esp_wifi
  10. * - driver
  11. *
  12. * However, usages of above components are different.
  13. * Therefore, we put the common used parts into `esp_hw_support`, including:
  14. * - adc power maintainance
  15. * - adc hw calibration settings
  16. * - adc locks, to prevent concurrently using adc hw
  17. */
  18. #include <esp_types.h>
  19. #include "sdkconfig.h"
  20. #include "sys/lock.h"
  21. #include "esp_log.h"
  22. #include "esp_check.h"
  23. #include "freertos/FreeRTOS.h"
  24. #include "hal/adc_types.h"
  25. #include "hal/adc_hal.h"
  26. #include "hal/adc_hal_common.h"
  27. #include "hal/adc_hal_conf.h"
  28. #include "esp_private/adc_share_hw_ctrl.h"
  29. //For calibration
  30. #if CONFIG_IDF_TARGET_ESP32S2
  31. #include "esp_efuse_rtc_table.h"
  32. #elif SOC_ADC_CALIBRATION_V1_SUPPORTED
  33. #include "esp_efuse_rtc_calib.h"
  34. #endif
  35. static const char *TAG = "adc_share_hw_ctrl";
  36. extern portMUX_TYPE rtc_spinlock;
  37. /*------------------------------------------------------------------------------
  38. * ADC Power
  39. *----------------------------------------------------------------------------*/
  40. // This gets incremented when adc_power_acquire() is called, and decremented when
  41. // adc_power_release() is called. ADC is powered down when the value reaches zero.
  42. // Should be modified within critical section (ADC_ENTER/EXIT_CRITICAL).
  43. static int s_adc_power_on_cnt;
  44. static void adc_power_on_internal(void)
  45. {
  46. /* Set the power always on to increase precision. */
  47. adc_hal_set_power_manage(ADC_POWER_SW_ON);
  48. }
  49. void adc_power_acquire(void)
  50. {
  51. portENTER_CRITICAL(&rtc_spinlock);
  52. s_adc_power_on_cnt++;
  53. if (s_adc_power_on_cnt == 1) {
  54. adc_power_on_internal();
  55. }
  56. portEXIT_CRITICAL(&rtc_spinlock);
  57. }
  58. static void adc_power_off_internal(void)
  59. {
  60. #if CONFIG_IDF_TARGET_ESP32
  61. adc_hal_set_power_manage(ADC_POWER_SW_OFF);
  62. #else
  63. adc_hal_set_power_manage(ADC_POWER_BY_FSM);
  64. #endif
  65. }
  66. void adc_power_release(void)
  67. {
  68. portENTER_CRITICAL(&rtc_spinlock);
  69. s_adc_power_on_cnt--;
  70. /* Sanity check */
  71. if (s_adc_power_on_cnt < 0) {
  72. portEXIT_CRITICAL(&rtc_spinlock);
  73. ESP_LOGE(TAG, "%s called, but s_adc_power_on_cnt == 0", __func__);
  74. abort();
  75. } else if (s_adc_power_on_cnt == 0) {
  76. adc_power_off_internal();
  77. }
  78. portEXIT_CRITICAL(&rtc_spinlock);
  79. }
  80. #if SOC_ADC_CALIBRATION_V1_SUPPORTED
  81. /*---------------------------------------------------------------
  82. ADC Hardware Calibration
  83. ---------------------------------------------------------------*/
  84. #if CONFIG_IDF_TARGET_ESP32S2
  85. #define esp_efuse_rtc_calib_get_ver() esp_efuse_rtc_table_read_calib_version()
  86. static inline uint32_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int atten)
  87. {
  88. int tag = esp_efuse_rtc_table_get_tag(version, adc_unit + 1, atten, RTCCALIB_V2_PARAM_VINIT);
  89. return esp_efuse_rtc_table_get_parsed_efuse_value(tag, false);
  90. }
  91. #endif
  92. static uint32_t s_adc_cali_param[SOC_ADC_PERIPH_NUM][SOC_ADC_ATTEN_NUM] = {};
  93. void adc_calc_hw_calibration_code(adc_unit_t adc_n, adc_atten_t atten)
  94. {
  95. if (s_adc_cali_param[adc_n][atten]) {
  96. ESP_EARLY_LOGV(TAG, "Use calibrated val ADC%d atten=%d: %04X", adc_n + 1, atten, s_adc_cali_param[adc_n][atten]);
  97. return ;
  98. }
  99. // check if we can fetch the values from eFuse.
  100. int version = esp_efuse_rtc_calib_get_ver();
  101. uint32_t init_code = 0;
  102. if (version == ESP_EFUSE_ADC_CALIB_VER) {
  103. init_code = esp_efuse_rtc_calib_get_init_code(version, adc_n, atten);
  104. } else {
  105. ESP_EARLY_LOGD(TAG, "Calibration eFuse is not configured, use self-calibration for ICode");
  106. adc_power_acquire();
  107. portENTER_CRITICAL(&rtc_spinlock);
  108. adc_ll_pwdet_set_cct(ADC_HAL_PWDET_CCT_DEFAULT);
  109. const bool internal_gnd = true;
  110. init_code = adc_hal_self_calibration(adc_n, atten, internal_gnd);
  111. portEXIT_CRITICAL(&rtc_spinlock);
  112. adc_power_release();
  113. }
  114. s_adc_cali_param[adc_n][atten] = init_code;
  115. ESP_EARLY_LOGV(TAG, "Calib(V%d) ADC%d atten=%d: %04X", version, adc_n + 1, atten, init_code);
  116. }
  117. void IRAM_ATTR adc_set_hw_calibration_code(adc_unit_t adc_n, adc_atten_t atten)
  118. {
  119. adc_hal_set_calibration_param(adc_n, s_adc_cali_param[adc_n][atten]);
  120. }
  121. #endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED
  122. /*---------------------------------------------------------------
  123. ADC Hardware Locks
  124. ---------------------------------------------------------------*/
  125. static _lock_t adc1_lock;
  126. static _lock_t adc2_lock;
  127. esp_err_t adc_lock_acquire(adc_unit_t adc_unit)
  128. {
  129. if (adc_unit == ADC_UNIT_1) {
  130. _lock_acquire(&adc1_lock);
  131. }
  132. if (adc_unit == ADC_UNIT_2) {
  133. _lock_acquire(&adc2_lock);
  134. }
  135. return ESP_OK;
  136. }
  137. esp_err_t adc_lock_release(adc_unit_t adc_unit)
  138. {
  139. if (adc_unit == ADC_UNIT_2) {
  140. ESP_RETURN_ON_FALSE(((uint32_t *)adc2_lock != NULL), ESP_ERR_INVALID_STATE, TAG, "adc2 lock release without acquiring");
  141. _lock_release(&adc2_lock);
  142. }
  143. if (adc_unit == ADC_UNIT_1) {
  144. ESP_RETURN_ON_FALSE(((uint32_t *)adc1_lock != NULL), ESP_ERR_INVALID_STATE, TAG, "adc1 lock release without acquiring");
  145. _lock_release(&adc1_lock);
  146. }
  147. return ESP_OK;
  148. }
  149. esp_err_t adc_lock_try_acquire(adc_unit_t adc_unit)
  150. {
  151. if (adc_unit == ADC_UNIT_1) {
  152. if (_lock_try_acquire(&adc1_lock) == -1) {
  153. return ESP_ERR_TIMEOUT;
  154. }
  155. }
  156. if (adc_unit == ADC_UNIT_2) {
  157. if (_lock_try_acquire(&adc2_lock) == -1) {
  158. return ESP_ERR_TIMEOUT;
  159. }
  160. }
  161. return ESP_OK;
  162. }
  163. esp_err_t adc2_wifi_acquire(void)
  164. {
  165. #if CONFIG_IDF_TARGET_ESP32
  166. /* Wi-Fi module will use adc2. Use locks to avoid conflicts. */
  167. adc_lock_acquire(ADC_UNIT_2);
  168. ESP_LOGD(TAG, "Wi-Fi takes adc2 lock.");
  169. #endif
  170. return ESP_OK;
  171. }
  172. esp_err_t adc2_wifi_release(void)
  173. {
  174. #if CONFIG_IDF_TARGET_ESP32
  175. return adc_lock_release(ADC_UNIT_2);
  176. #endif
  177. return ESP_OK;
  178. }