test_adc.c 12 KB

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