test_rtc_clk.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. #include <stdio.h>
  2. #include "unity.h"
  3. #include "soc/rtc.h"
  4. #include "soc/rtc_periph.h"
  5. #include "soc/sens_periph.h"
  6. #include "soc/gpio_periph.h"
  7. #include "driver/rtc_io.h"
  8. #include "test_utils.h"
  9. #include "freertos/FreeRTOS.h"
  10. #include "freertos/task.h"
  11. #include "freertos/semphr.h"
  12. #include "../esp_clk_internal.h"
  13. #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2)
  14. #include "esp32/clk.h"
  15. #include "esp32/rom/ets_sys.h"
  16. #include "esp32/rom/uart.h"
  17. #define CALIBRATE_ONE(cali_clk) calibrate_one(cali_clk, #cali_clk)
  18. static uint32_t calibrate_one(rtc_cal_sel_t cal_clk, const char* name)
  19. {
  20. const uint32_t cal_count = 1000;
  21. const float factor = (1 << 19) * 1000.0f;
  22. uint32_t cali_val;
  23. printf("%s:\n", name);
  24. for (int i = 0; i < 5; ++i) {
  25. printf("calibrate (%d): ", i);
  26. cali_val = rtc_clk_cal(cal_clk, cal_count);
  27. printf("%.3f kHz\n", factor / (float) cali_val);
  28. }
  29. return cali_val;
  30. }
  31. TEST_CASE("RTC_SLOW_CLK sources calibration", "[rtc_clk]")
  32. {
  33. rtc_clk_32k_enable(true);
  34. rtc_clk_8m_enable(true, true);
  35. CALIBRATE_ONE(RTC_CAL_RTC_MUX);
  36. CALIBRATE_ONE(RTC_CAL_8MD256);
  37. uint32_t cal_32k = CALIBRATE_ONE(RTC_CAL_32K_XTAL);
  38. if (cal_32k == 0) {
  39. printf("32K XTAL OSC has not started up");
  40. } else {
  41. printf("switching to RTC_SLOW_FREQ_32K_XTAL: ");
  42. rtc_clk_slow_freq_set(RTC_SLOW_FREQ_32K_XTAL);
  43. printf("done\n");
  44. CALIBRATE_ONE(RTC_CAL_RTC_MUX);
  45. CALIBRATE_ONE(RTC_CAL_8MD256);
  46. CALIBRATE_ONE(RTC_CAL_32K_XTAL);
  47. }
  48. printf("switching to RTC_SLOW_FREQ_8MD256: ");
  49. rtc_clk_slow_freq_set(RTC_SLOW_FREQ_8MD256);
  50. printf("done\n");
  51. CALIBRATE_ONE(RTC_CAL_RTC_MUX);
  52. CALIBRATE_ONE(RTC_CAL_8MD256);
  53. CALIBRATE_ONE(RTC_CAL_32K_XTAL);
  54. }
  55. /* The following two are not unit tests, but are added here to make it easy to
  56. * check the frequency of 150k/32k oscillators. The following two "tests" will
  57. * output either 32k or 150k clock to GPIO25.
  58. */
  59. static void pull_out_clk(int sel)
  60. {
  61. REG_SET_BIT(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_MUX_SEL_M);
  62. REG_CLR_BIT(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_RDE_M | RTC_IO_PDAC1_RUE_M);
  63. REG_SET_FIELD(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_FUN_SEL, 1);
  64. REG_SET_FIELD(SENS_SAR_DAC_CTRL1_REG, SENS_DEBUG_BIT_SEL, 0);
  65. REG_SET_FIELD(RTC_IO_RTC_DEBUG_SEL_REG, RTC_IO_DEBUG_SEL0, sel);
  66. }
  67. TEST_CASE("Output 150k clock to GPIO25", "[rtc_clk][ignore]")
  68. {
  69. pull_out_clk(RTC_IO_DEBUG_SEL0_150K_OSC);
  70. }
  71. TEST_CASE("Output 32k XTAL clock to GPIO25", "[rtc_clk][ignore]")
  72. {
  73. rtc_clk_32k_enable(true);
  74. pull_out_clk(RTC_IO_DEBUG_SEL0_32K_XTAL);
  75. }
  76. TEST_CASE("Output 8M XTAL clock to GPIO25", "[rtc_clk][ignore]")
  77. {
  78. rtc_clk_8m_enable(true, true);
  79. SET_PERI_REG_MASK(RTC_IO_RTC_DEBUG_SEL_REG, RTC_IO_DEBUG_12M_NO_GATING);
  80. pull_out_clk(RTC_IO_DEBUG_SEL0_8M);
  81. }
  82. static void test_clock_switching(void (*switch_func)(const rtc_cpu_freq_config_t* config))
  83. {
  84. uart_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM);
  85. const int test_duration_sec = 10;
  86. ref_clock_init();
  87. uint64_t t_start = ref_clock_get();
  88. rtc_cpu_freq_config_t cur_config;
  89. rtc_clk_cpu_freq_get_config(&cur_config);
  90. rtc_cpu_freq_config_t xtal_config;
  91. rtc_clk_cpu_freq_mhz_to_config((uint32_t) rtc_clk_xtal_freq_get(), &xtal_config);
  92. int count = 0;
  93. while (ref_clock_get() - t_start < test_duration_sec * 1000000) {
  94. switch_func(&xtal_config);
  95. switch_func(&cur_config);
  96. ++count;
  97. }
  98. uint64_t t_end = ref_clock_get();
  99. printf("Switch count: %d. Average time to switch PLL -> XTAL -> PLL: %d us\n", count, (int) ((t_end - t_start) / count));
  100. ref_clock_deinit();
  101. }
  102. TEST_CASE("Calculate 8M clock frequency", "[rtc_clk]")
  103. {
  104. // calibrate 8M/256 clock against XTAL, get 8M/256 clock period
  105. uint32_t rtc_8md256_period = rtc_clk_cal(RTC_CAL_8MD256, 100);
  106. uint32_t rtc_fast_freq_hz = 1000000ULL * (1 << RTC_CLK_CAL_FRACT) * 256 / rtc_8md256_period;
  107. printf("RTC_FAST_CLK=%d Hz\n", rtc_fast_freq_hz);
  108. TEST_ASSERT_INT32_WITHIN(650000, RTC_FAST_CLK_FREQ_APPROX, rtc_fast_freq_hz);
  109. }
  110. TEST_CASE("Test switching between PLL and XTAL", "[rtc_clk]")
  111. {
  112. test_clock_switching(rtc_clk_cpu_freq_set_config);
  113. }
  114. TEST_CASE("Test fast switching between PLL and XTAL", "[rtc_clk]")
  115. {
  116. test_clock_switching(rtc_clk_cpu_freq_set_config_fast);
  117. }
  118. #define COUNT_TEST 3
  119. #define TIMEOUT_TEST_MS (5 + CONFIG_ESP32_RTC_CLK_CAL_CYCLES / 16)
  120. void stop_rtc_external_quartz(void){
  121. const uint8_t pin_32 = 32;
  122. const uint8_t pin_33 = 33;
  123. const uint8_t mask_32 = (1 << (pin_32 - 32));
  124. const uint8_t mask_33 = (1 << (pin_33 - 32));
  125. rtc_clk_32k_enable(false);
  126. gpio_pad_select_gpio(pin_32);
  127. gpio_pad_select_gpio(pin_33);
  128. gpio_output_set_high(0, mask_32 | mask_33, mask_32 | mask_33, 0);
  129. ets_delay_us(500000);
  130. gpio_output_set_high(0, 0, 0, mask_32 | mask_33); // disable pins
  131. }
  132. static void start_freq(rtc_slow_freq_t required_src_freq, uint32_t start_delay_ms)
  133. {
  134. int i = 0, fail = 0;
  135. uint32_t start_time;
  136. uint32_t end_time;
  137. rtc_slow_freq_t selected_src_freq;
  138. stop_rtc_external_quartz();
  139. #ifdef CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS
  140. uint32_t bootstrap_cycles = CONFIG_ESP32_RTC_XTAL_BOOTSTRAP_CYCLES;
  141. printf("Test is started. Kconfig settings:\n External 32K crystal is selected,\n Oscillation cycles = %d,\n Calibration cycles = %d.\n",
  142. bootstrap_cycles,
  143. CONFIG_ESP32_RTC_CLK_CAL_CYCLES);
  144. #else
  145. uint32_t bootstrap_cycles = 5;
  146. printf("Test is started. Kconfig settings:\n Internal RC is selected,\n Oscillation cycles = %d,\n Calibration cycles = %d.\n",
  147. bootstrap_cycles,
  148. CONFIG_ESP32_RTC_CLK_CAL_CYCLES);
  149. #endif
  150. if (start_delay_ms == 0 && CONFIG_ESP32_RTC_CLK_CAL_CYCLES < 1500){
  151. start_delay_ms = 50;
  152. printf("Recommended increase Number of cycles for RTC_SLOW_CLK calibration to 3000!\n");
  153. }
  154. while(i < COUNT_TEST){
  155. start_time = xTaskGetTickCount() * (1000 / configTICK_RATE_HZ);
  156. i++;
  157. printf("attempt #%d/%d...", i, COUNT_TEST);
  158. rtc_clk_32k_bootstrap(bootstrap_cycles);
  159. ets_delay_us(start_delay_ms * 1000);
  160. rtc_clk_select_rtc_slow_clk();
  161. selected_src_freq = rtc_clk_slow_freq_get();
  162. end_time = xTaskGetTickCount() * (1000 / configTICK_RATE_HZ);
  163. printf(" [time=%d] ", (end_time - start_time) - start_delay_ms);
  164. if(selected_src_freq != required_src_freq){
  165. printf("FAIL. Time measurement...");
  166. fail = 1;
  167. } else {
  168. printf("PASS. Time measurement...");
  169. }
  170. uint64_t clk_rtc_time;
  171. uint32_t fail_measure = 0;
  172. for (int j = 0; j < 3; ++j) {
  173. clk_rtc_time = esp_clk_rtc_time();
  174. ets_delay_us(1000000);
  175. uint64_t delta = esp_clk_rtc_time() - clk_rtc_time;
  176. if (delta < 900000LL || delta > 1100000){
  177. printf("FAIL");
  178. fail = 1;
  179. fail_measure = 1;
  180. break;
  181. }
  182. }
  183. if(fail_measure == 0) {
  184. printf("PASS");
  185. }
  186. printf(" [calibration val = %d] \n", esp_clk_slowclk_cal_get());
  187. stop_rtc_external_quartz();
  188. ets_delay_us(500000);
  189. }
  190. TEST_ASSERT_MESSAGE(fail == 0, "Test failed");
  191. printf("Test passed successfully\n");
  192. }
  193. TEST_CASE("Test starting external RTC quartz", "[rtc_clk][test_env=UT_T1_32kXTAL]")
  194. {
  195. int i = 0, fail = 0;
  196. uint32_t start_time;
  197. uint32_t end_time;
  198. stop_rtc_external_quartz();
  199. #ifdef CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS
  200. uint32_t bootstrap_cycles = CONFIG_ESP32_RTC_XTAL_BOOTSTRAP_CYCLES;
  201. printf("Test is started. Kconfig settings:\n External 32K crystal is selected,\n Oscillation cycles = %d,\n Calibration cycles = %d.\n",
  202. bootstrap_cycles,
  203. CONFIG_ESP32_RTC_CLK_CAL_CYCLES);
  204. #else
  205. uint32_t bootstrap_cycles = 5;
  206. printf("Test is started. Kconfig settings:\n Internal RC is selected,\n Oscillation cycles = %d,\n Calibration cycles = %d.\n",
  207. bootstrap_cycles,
  208. CONFIG_ESP32_RTC_CLK_CAL_CYCLES);
  209. #endif
  210. if (CONFIG_ESP32_RTC_CLK_CAL_CYCLES < 1500){
  211. printf("Recommended increase Number of cycles for RTC_SLOW_CLK calibration to 3000!\n");
  212. }
  213. while(i < COUNT_TEST){
  214. start_time = xTaskGetTickCount() * (1000 / configTICK_RATE_HZ);
  215. i++;
  216. printf("attempt #%d/%d...", i, COUNT_TEST);
  217. rtc_clk_32k_bootstrap(bootstrap_cycles);
  218. rtc_clk_select_rtc_slow_clk();
  219. end_time = xTaskGetTickCount() * (1000 / configTICK_RATE_HZ);
  220. printf(" [time=%d] ", end_time - start_time);
  221. if((end_time - start_time) > TIMEOUT_TEST_MS){
  222. printf("FAIL\n");
  223. fail = 1;
  224. } else {
  225. printf("PASS\n");
  226. }
  227. stop_rtc_external_quartz();
  228. ets_delay_us(100000);
  229. }
  230. TEST_ASSERT_MESSAGE(fail == 0, "Test failed");
  231. printf("Test passed successfully\n");
  232. }
  233. TEST_CASE("Test starting 'External 32kHz XTAL' on the board with it.", "[rtc_clk][test_env=UT_T1_32kXTAL]")
  234. {
  235. start_freq(RTC_SLOW_FREQ_32K_XTAL, 200);
  236. start_freq(RTC_SLOW_FREQ_32K_XTAL, 0);
  237. }
  238. TEST_CASE("Test starting 'External 32kHz XTAL' on the board without it.", "[rtc_clk][test_env=UT_T1_no32kXTAL]")
  239. {
  240. printf("Tries to start the 'External 32kHz XTAL' on the board without it. "
  241. "Clock switching to 'Internal 150 kHz RC oscillator'.\n");
  242. printf("This test will be successful for boards without an external crystal or non-working crystal. "
  243. "First, there will be an attempt to start from the external crystal after a failure "
  244. "will switch to the internal RC circuit. If the switch to the internal RC circuit "
  245. "was successful then the test succeeded.\n");
  246. start_freq(RTC_SLOW_FREQ_RTC, 200);
  247. start_freq(RTC_SLOW_FREQ_RTC, 0);
  248. }
  249. #endif