test_adc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. /*
  2. * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "sdkconfig.h"
  7. #include <sys/param.h>
  8. #include <string.h>
  9. #include "esp_log.h"
  10. #include "test_utils.h"
  11. #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP8684)
  12. // TODO: Support ADC IDF-3908
  13. #include "esp_adc_cal.h"
  14. #include "driver/adc.h"
  15. static const char *TAG = "ADC";
  16. #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32, ESP32S2, ESP32S3, ESP32C3) //TODO: IDF-3160
  17. //API only supported for C3 now.
  18. #include "esp_adc_cal.h"
  19. #include "esp_log.h"
  20. #define TEST_COUNT 4096
  21. #define MAX_ARRAY_SIZE 4096
  22. #define TEST_ATTEN ADC_ATTEN_MAX //Set to ADC_ATTEN_*db to test a single attenuation only
  23. static int s_adc_count[MAX_ARRAY_SIZE]={};
  24. static int s_adc_offset = -1;
  25. static int insert_point(uint32_t value)
  26. {
  27. const bool fixed_size = true;
  28. if (s_adc_offset < 0) {
  29. if (fixed_size) {
  30. TEST_ASSERT_GREATER_OR_EQUAL(4096, MAX_ARRAY_SIZE);
  31. s_adc_offset = 0; //Fixed to 0 because the array can hold all the data in 12 bits
  32. } else {
  33. s_adc_offset = MAX((int)value - MAX_ARRAY_SIZE/2, 0);
  34. }
  35. }
  36. if (!fixed_size && (value < s_adc_offset || value >= s_adc_offset + MAX_ARRAY_SIZE)) {
  37. TEST_ASSERT_GREATER_OR_EQUAL(s_adc_offset, value);
  38. TEST_ASSERT_LESS_THAN(s_adc_offset + MAX_ARRAY_SIZE, value);
  39. }
  40. s_adc_count[value - s_adc_offset] ++;
  41. return value - s_adc_offset;
  42. }
  43. static void reset_array(void)
  44. {
  45. memset(s_adc_count, 0, sizeof(s_adc_count));
  46. s_adc_offset = -1;
  47. }
  48. static uint32_t get_average(void)
  49. {
  50. uint32_t sum = 0;
  51. int count = 0;
  52. for (int i = 0; i < MAX_ARRAY_SIZE; i++) {
  53. sum += s_adc_count[i] * (s_adc_offset+i);
  54. count += s_adc_count[i];
  55. }
  56. return sum/count;
  57. }
  58. static void print_summary(bool figure)
  59. {
  60. const int MAX_WIDTH=20;
  61. int max_count = 0;
  62. int start = -1;
  63. int end = -1;
  64. uint32_t sum = 0;
  65. int count = 0;
  66. for (int i = 0; i < MAX_ARRAY_SIZE; i++) {
  67. if (s_adc_count[i] > max_count) {
  68. max_count = s_adc_count[i];
  69. }
  70. if (s_adc_count[i] > 0 && start < 0) {
  71. start = i;
  72. }
  73. if (s_adc_count[i] > 0) {
  74. end = i;
  75. }
  76. count += s_adc_count[i];
  77. sum += s_adc_count[i] * (s_adc_offset+i);
  78. }
  79. if (figure) {
  80. for (int i = start; i <= end; i++) {
  81. printf("%4d ", i+s_adc_offset);
  82. int count = s_adc_count[i] * MAX_WIDTH / max_count;
  83. for (int j = 0; j < count; j++) {
  84. putchar('|');
  85. }
  86. printf(" %d\n", s_adc_count[i]);
  87. }
  88. }
  89. float average = (float)sum/count;
  90. float variation_square = 0;
  91. for (int i = start; i <= end; i ++) {
  92. if (s_adc_count[i] == 0) {
  93. continue;
  94. }
  95. float delta = i + s_adc_offset - average;
  96. variation_square += (delta * delta) * s_adc_count[i];
  97. }
  98. printf("%d points.\n", count);
  99. printf("average: %.1f\n", (float)sum/count);
  100. printf("std: %.2f\n", sqrt(variation_square/count));
  101. }
  102. static void continuous_adc_init(uint16_t adc1_chan_mask, uint16_t adc2_chan_mask, adc_channel_t *channel, uint8_t channel_num, adc_atten_t atten)
  103. {
  104. adc_digi_init_config_t adc_dma_config = {
  105. .max_store_buf_size = TEST_COUNT*2,
  106. .conv_num_each_intr = 128,
  107. .adc1_chan_mask = adc1_chan_mask,
  108. .adc2_chan_mask = adc2_chan_mask,
  109. };
  110. TEST_ESP_OK(adc_digi_initialize(&adc_dma_config));
  111. adc_digi_pattern_table_t adc_pattern[10] = {0};
  112. adc_digi_config_t dig_cfg = {
  113. .conv_limit_en = 0,
  114. .conv_limit_num = 250,
  115. .sample_freq_hz = 83333,
  116. };
  117. dig_cfg.adc_pattern_len = channel_num;
  118. for (int i = 0; i < channel_num; i++) {
  119. uint8_t unit = ((channel[i] >> 3) & 0x1);
  120. uint8_t ch = channel[i] & 0x7;
  121. adc_pattern[i].atten = atten;
  122. adc_pattern[i].channel = ch;
  123. adc_pattern[i].unit = unit;
  124. }
  125. dig_cfg.adc_pattern = adc_pattern;
  126. TEST_ESP_OK(adc_digi_controller_config(&dig_cfg));
  127. }
  128. TEST_CASE("test_adc_dma", "[adc][ignore][manual]")
  129. {
  130. uint16_t adc1_chan_mask = BIT(2);
  131. uint16_t adc2_chan_mask = 0;
  132. adc_channel_t channel[1] = {ADC1_CHANNEL_2};
  133. adc_atten_t target_atten = TEST_ATTEN;
  134. const int output_data_size = sizeof(adc_digi_output_data_t);
  135. int buffer_size = TEST_COUNT*output_data_size;
  136. uint8_t* read_buf = malloc(buffer_size);
  137. TEST_ASSERT_NOT_NULL(read_buf);
  138. adc_atten_t atten;
  139. bool print_figure;
  140. if (target_atten == ADC_ATTEN_MAX) {
  141. atten = ADC_ATTEN_DB_0;
  142. target_atten = ADC_ATTEN_DB_11;
  143. print_figure = false;
  144. } else {
  145. atten = target_atten;
  146. print_figure = true;
  147. }
  148. while (1) {
  149. ESP_LOGI("TEST_ADC", "Test with atten: %d", atten);
  150. memset(read_buf, 0xce, buffer_size);
  151. bool do_calibration = false;
  152. esp_adc_cal_characteristics_t chan1_char = {};
  153. esp_adc_cal_value_t cal_ret = esp_adc_cal_characterize(ADC_UNIT_1, atten, ADC_WIDTH_12Bit, 0, &chan1_char);
  154. if (cal_ret == ESP_ADC_CAL_VAL_EFUSE_TP) {
  155. do_calibration = true;
  156. }
  157. continuous_adc_init(adc1_chan_mask, adc2_chan_mask, channel, sizeof(channel) / sizeof(adc_channel_t), atten);
  158. adc_digi_start();
  159. int remain_count = TEST_COUNT;
  160. while (remain_count) {
  161. int already_got = TEST_COUNT - remain_count;
  162. uint32_t ret_num;
  163. TEST_ESP_OK(adc_digi_read_bytes(read_buf + already_got*output_data_size,
  164. remain_count*output_data_size, &ret_num, ADC_MAX_DELAY));
  165. TEST_ASSERT((ret_num % output_data_size) == 0);
  166. remain_count -= ret_num / output_data_size;
  167. }
  168. adc_digi_output_data_t *p = (void*)read_buf;
  169. reset_array();
  170. for (int i = 0; i < TEST_COUNT; i++) {
  171. insert_point(p[i].type2.data);
  172. }
  173. print_summary(print_figure);
  174. if (do_calibration) {
  175. uint32_t raw = get_average();
  176. uint32_t voltage_mv = esp_adc_cal_raw_to_voltage(raw, &chan1_char);
  177. printf("Voltage = %d mV\n", voltage_mv);
  178. }
  179. adc_digi_stop();
  180. TEST_ESP_OK(adc_digi_deinitialize());
  181. if (atten == target_atten) {
  182. break;
  183. }
  184. atten++;
  185. }
  186. free(read_buf);
  187. }
  188. TEST_CASE("test_adc_single", "[adc][ignore][manual]")
  189. {
  190. adc_atten_t target_atten = TEST_ATTEN;
  191. adc_atten_t atten;
  192. bool print_figure;
  193. if (target_atten == ADC_ATTEN_MAX) {
  194. atten = ADC_ATTEN_DB_0;
  195. target_atten = ADC_ATTEN_DB_11;
  196. print_figure = false;
  197. } else {
  198. atten = target_atten;
  199. print_figure = true;
  200. }
  201. adc1_config_width(ADC_WIDTH_BIT_12);
  202. while (1) {
  203. ESP_LOGI("TEST_ADC", "Test with atten: %d", atten);
  204. adc1_config_channel_atten(ADC1_CHANNEL_2, atten);
  205. bool do_calibration = false;
  206. esp_adc_cal_characteristics_t chan1_char = {};
  207. esp_adc_cal_value_t cal_ret = esp_adc_cal_characterize(ADC_UNIT_1, atten, ADC_WIDTH_12Bit, 0, &chan1_char);
  208. if (cal_ret == ESP_ADC_CAL_VAL_EFUSE_TP) {
  209. do_calibration = true;
  210. }
  211. const int test_count = TEST_COUNT;
  212. adc1_channel_t channel = ADC1_CHANNEL_2;
  213. while (1) {
  214. reset_array();
  215. for (int i = 0; i < test_count; i++) {
  216. uint32_t raw = adc1_get_raw(channel);
  217. insert_point(raw);
  218. }
  219. print_summary(print_figure);
  220. break;
  221. }
  222. if (do_calibration) {
  223. uint32_t raw = get_average();
  224. uint32_t voltage_mv = esp_adc_cal_raw_to_voltage(raw, &chan1_char);
  225. printf("Voltage = %d mV\n", voltage_mv);
  226. }
  227. if (atten == target_atten) {
  228. break;
  229. }
  230. atten++;
  231. }
  232. }
  233. #endif //#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32, ESP32S2, ESP32S3)
  234. /********************************************************************************
  235. * ADC Speed Related Tests
  236. ********************************************************************************/
  237. #ifdef CONFIG_IDF_TARGET_ESP32
  238. #define CPU_FREQ_MHZ CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ
  239. #elif CONFIG_IDF_TARGET_ESP32S2
  240. #define CPU_FREQ_MHZ CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ
  241. #elif CONFIG_IDF_TARGET_ESP32S3
  242. #define CPU_FREQ_MHZ CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ
  243. #elif CONFIG_IDF_TARGET_ESP32C3
  244. #define CPU_FREQ_MHZ CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ
  245. #endif
  246. #define RECORD_TIME_PREPARE() uint32_t __t1, __t2
  247. #define RECORD_TIME_START() do {__t1 = esp_cpu_get_ccount();}while(0)
  248. #define RECORD_TIME_END(p_time) do{__t2 = esp_cpu_get_ccount(); *p_time = (__t2-__t1);}while(0)
  249. #define GET_US_BY_CCOUNT(t) ((double)t/CPU_FREQ_MHZ)
  250. //ADC Channels
  251. #if CONFIG_IDF_TARGET_ESP32
  252. #define ADC1_CALI_TEST_CHAN0 ADC1_CHANNEL_6
  253. #define ADC2_CALI_TEST_CHAN0 ADC2_CHANNEL_0
  254. #else
  255. #define ADC1_CALI_TEST_CHAN0 ADC1_CHANNEL_2
  256. #define ADC2_CALI_TEST_CHAN0 ADC2_CHANNEL_0
  257. #endif
  258. //ADC Calibration
  259. #if CONFIG_IDF_TARGET_ESP32
  260. #define ADC_TEST_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_VREF
  261. #elif CONFIG_IDF_TARGET_ESP32S2
  262. #define ADC_TEST_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_TP
  263. #elif CONFIG_IDF_TARGET_ESP32C3
  264. #define ADC_TEST_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_TP
  265. #elif CONFIG_IDF_TARGET_ESP32S3
  266. #define ADC_TEST_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_TP_FIT
  267. #endif
  268. #define TIMES_PER_ATTEN 10
  269. static esp_adc_cal_characteristics_t adc1_chars;
  270. static esp_adc_cal_characteristics_t adc2_chars;
  271. static void adc_single_cali_init(adc_unit_t adc_n, adc_channel_t chan, uint32_t atten)
  272. {
  273. esp_err_t ret;
  274. esp_adc_cal_value_t ret_val = ESP_ADC_CAL_VAL_NOT_SUPPORTED;
  275. ret = esp_adc_cal_check_efuse(ADC_TEST_CALI_SCHEME);
  276. if (ret == ESP_ERR_NOT_SUPPORTED) {
  277. ESP_LOGE(TAG, "Cali scheme not supported!");
  278. TEST_ASSERT(ret != ESP_ERR_NOT_SUPPORTED);
  279. } else if (ret != ESP_OK) {
  280. ESP_LOGW(TAG, "No cali eFuse, but will run the test");
  281. }
  282. if (adc_n == ADC_UNIT_1) {
  283. ret_val = esp_adc_cal_characterize(adc_n, atten, ADC_WIDTH_BIT_DEFAULT, 0, &adc1_chars);
  284. TEST_ESP_OK(adc1_config_width(ADC_WIDTH_BIT_DEFAULT));
  285. TEST_ESP_OK(adc1_config_channel_atten((adc1_channel_t)chan, atten));
  286. } else if (adc_n == ADC_UNIT_2) {
  287. TEST_ESP_OK(adc2_config_channel_atten((adc2_channel_t)chan, atten));
  288. ret_val = esp_adc_cal_characterize(adc_n, atten, ADC_WIDTH_BIT_DEFAULT, 0, &adc2_chars);
  289. }
  290. if (ret_val == ESP_ADC_CAL_VAL_NOT_SUPPORTED) {
  291. ESP_LOGW(TAG, "No cali eFuse, or invalid arg, but will run the test");
  292. }
  293. ESP_LOGI(TAG, "ADC%d, channel%d, atten%d", adc_n, chan, atten);
  294. }
  295. static IRAM_ATTR NOINLINE_ATTR uint32_t get_cali_time_in_ccount(uint32_t adc_raw, esp_adc_cal_characteristics_t *chars)
  296. {
  297. uint32_t time;
  298. RECORD_TIME_PREPARE();
  299. RECORD_TIME_START();
  300. esp_adc_cal_raw_to_voltage(adc_raw, chars);
  301. RECORD_TIME_END(&time);
  302. return time;
  303. }
  304. TEST_CASE("test_adc_single_cali_time", "[adc][ignore][manual]")
  305. {
  306. ESP_LOGI(TAG, "CPU FREQ is %dMHz", CPU_FREQ_MHZ);
  307. uint32_t adc1_time_record[4][TIMES_PER_ATTEN] = {};
  308. uint32_t adc2_time_record[4][TIMES_PER_ATTEN] = {};
  309. int adc1_raw = 0;
  310. int adc2_raw = 0;
  311. //atten0 ~ atten3
  312. for (int i = 0; i < 4; i++) {
  313. ESP_LOGI(TAG, "----------------atten%d----------------", i);
  314. adc_single_cali_init(ADC_UNIT_1, ADC1_CALI_TEST_CHAN0, i);
  315. adc_single_cali_init(ADC_UNIT_2, ADC2_CALI_TEST_CHAN0, i);
  316. for (int j = 0; j < TIMES_PER_ATTEN; j++) {
  317. adc1_raw = adc1_get_raw(ADC1_CALI_TEST_CHAN0);
  318. TEST_ESP_OK(adc2_get_raw(ADC2_CALI_TEST_CHAN0, ADC_WIDTH_BIT_DEFAULT, &adc2_raw));
  319. adc1_time_record[i][j] = get_cali_time_in_ccount(adc1_raw, &adc1_chars);
  320. adc2_time_record[i][j] = get_cali_time_in_ccount(adc2_raw, &adc2_chars);
  321. IDF_LOG_PERFORMANCE("ADC1 Cali time", "%d us", (int)GET_US_BY_CCOUNT(adc1_time_record[i][j]));
  322. IDF_LOG_PERFORMANCE("ADC2 Cali time", "%d us", (int)GET_US_BY_CCOUNT(adc2_time_record[i][j]));
  323. }
  324. }
  325. }
  326. #endif //#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP8684)