test_rtc_clk.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. #include <stdio.h>
  2. #include "unity.h"
  3. #include "esp_attr.h"
  4. #include "soc/soc_caps.h"
  5. #include "soc/rtc.h"
  6. #include "soc/rtc_periph.h"
  7. #if SOC_ADC_SUPPORT_RTC_CTRL
  8. #include "soc/sens_periph.h"
  9. #endif
  10. #include "soc/gpio_periph.h"
  11. #include "hal/gpio_ll.h"
  12. #include "driver/rtc_io.h"
  13. #include "test_utils.h"
  14. #include "freertos/FreeRTOS.h"
  15. #include "freertos/task.h"
  16. #include "freertos/semphr.h"
  17. #include "esp_rom_gpio.h"
  18. #include "esp_rom_sys.h"
  19. #include "esp_rom_uart.h"
  20. #include "esp_sleep.h"
  21. #include "esp_system.h"
  22. #if CONFIG_IDF_TARGET_ESP32
  23. #include "esp32/rtc.h"
  24. #include "esp32/clk.h"
  25. #include "esp32/rom/rtc.h"
  26. #elif CONFIG_IDF_TARGET_ESP32S2
  27. #include "esp32s2/rtc.h"
  28. #include "esp32s2/clk.h"
  29. #include "esp32s2/rom/rtc.h"
  30. #elif CONFIG_IDF_TARGET_ESP32S3
  31. #include "esp32s3/rtc.h"
  32. #include "esp32s3/clk.h"
  33. #include "esp32s3/rom/rtc.h"
  34. #elif CONFIG_IDF_TARGET_ESP32C3
  35. #include "esp32c3/rtc.h"
  36. #include "esp32c3/clk.h"
  37. #include "esp32c3/rom/rtc.h"
  38. #endif
  39. extern void rtc_clk_select_rtc_slow_clk(void);
  40. #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3, ESP32C3)
  41. #define CALIBRATE_ONE(cali_clk) calibrate_one(cali_clk, #cali_clk)
  42. static uint32_t calibrate_one(rtc_cal_sel_t cal_clk, const char* name)
  43. {
  44. const uint32_t cal_count = 1000;
  45. const float factor = (1 << 19) * 1000.0f;
  46. uint32_t cali_val;
  47. printf("%s:\n", name);
  48. for (int i = 0; i < 5; ++i) {
  49. printf("calibrate (%d): ", i);
  50. cali_val = rtc_clk_cal(cal_clk, cal_count);
  51. printf("%.3f kHz\n", factor / (float) cali_val);
  52. }
  53. return cali_val;
  54. }
  55. TEST_CASE("RTC_SLOW_CLK sources calibration", "[rtc_clk]")
  56. {
  57. rtc_clk_32k_enable(true);
  58. rtc_clk_8m_enable(true, true);
  59. CALIBRATE_ONE(RTC_CAL_RTC_MUX);
  60. CALIBRATE_ONE(RTC_CAL_8MD256);
  61. uint32_t cal_32k = CALIBRATE_ONE(RTC_CAL_32K_XTAL);
  62. if (cal_32k == 0) {
  63. printf("32K XTAL OSC has not started up");
  64. } else {
  65. printf("switching to RTC_SLOW_FREQ_32K_XTAL: ");
  66. rtc_clk_slow_freq_set(RTC_SLOW_FREQ_32K_XTAL);
  67. printf("done\n");
  68. CALIBRATE_ONE(RTC_CAL_RTC_MUX);
  69. CALIBRATE_ONE(RTC_CAL_8MD256);
  70. CALIBRATE_ONE(RTC_CAL_32K_XTAL);
  71. }
  72. printf("switching to RTC_SLOW_FREQ_8MD256: ");
  73. rtc_clk_slow_freq_set(RTC_SLOW_FREQ_8MD256);
  74. printf("done\n");
  75. CALIBRATE_ONE(RTC_CAL_RTC_MUX);
  76. CALIBRATE_ONE(RTC_CAL_8MD256);
  77. CALIBRATE_ONE(RTC_CAL_32K_XTAL);
  78. }
  79. /* The following two are not unit tests, but are added here to make it easy to
  80. * check the frequency of 150k/32k oscillators. The following two "tests" will
  81. * output either 32k or 150k clock to GPIO25.
  82. */
  83. static void pull_out_clk(int sel)
  84. {
  85. REG_SET_BIT(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_MUX_SEL_M);
  86. REG_CLR_BIT(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_RDE_M | RTC_IO_PDAC1_RUE_M);
  87. REG_SET_FIELD(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_FUN_SEL, 1);
  88. REG_SET_FIELD(SENS_SAR_DAC_CTRL1_REG, SENS_DEBUG_BIT_SEL, 0);
  89. REG_SET_FIELD(RTC_IO_RTC_DEBUG_SEL_REG, RTC_IO_DEBUG_SEL0, sel);
  90. }
  91. TEST_CASE("Output 150k clock to GPIO25", "[rtc_clk][ignore]")
  92. {
  93. pull_out_clk(RTC_IO_DEBUG_SEL0_150K_OSC);
  94. }
  95. TEST_CASE("Output 32k XTAL clock to GPIO25", "[rtc_clk][ignore]")
  96. {
  97. rtc_clk_32k_enable(true);
  98. pull_out_clk(RTC_IO_DEBUG_SEL0_32K_XTAL);
  99. }
  100. TEST_CASE("Output 8M XTAL clock to GPIO25", "[rtc_clk][ignore]")
  101. {
  102. rtc_clk_8m_enable(true, true);
  103. SET_PERI_REG_MASK(RTC_IO_RTC_DEBUG_SEL_REG, RTC_IO_DEBUG_12M_NO_GATING);
  104. pull_out_clk(RTC_IO_DEBUG_SEL0_8M);
  105. }
  106. static void test_clock_switching(void (*switch_func)(const rtc_cpu_freq_config_t* config))
  107. {
  108. esp_rom_uart_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM);
  109. const int test_duration_sec = 10;
  110. ref_clock_init();
  111. uint64_t t_start = ref_clock_get();
  112. rtc_cpu_freq_config_t cur_config;
  113. rtc_clk_cpu_freq_get_config(&cur_config);
  114. rtc_cpu_freq_config_t xtal_config;
  115. rtc_clk_cpu_freq_mhz_to_config((uint32_t) rtc_clk_xtal_freq_get(), &xtal_config);
  116. int count = 0;
  117. while (ref_clock_get() - t_start < test_duration_sec * 1000000) {
  118. switch_func(&xtal_config);
  119. switch_func(&cur_config);
  120. ++count;
  121. }
  122. uint64_t t_end = ref_clock_get();
  123. printf("Switch count: %d. Average time to switch PLL -> XTAL -> PLL: %d us\n", count, (int) ((t_end - t_start) / count));
  124. ref_clock_deinit();
  125. }
  126. TEST_CASE("Calculate 8M clock frequency", "[rtc_clk]")
  127. {
  128. // calibrate 8M/256 clock against XTAL, get 8M/256 clock period
  129. uint32_t rtc_8md256_period = rtc_clk_cal(RTC_CAL_8MD256, 100);
  130. uint32_t rtc_fast_freq_hz = 1000000ULL * (1 << RTC_CLK_CAL_FRACT) * 256 / rtc_8md256_period;
  131. printf("RTC_FAST_CLK=%d Hz\n", rtc_fast_freq_hz);
  132. TEST_ASSERT_INT32_WITHIN(650000, RTC_FAST_CLK_FREQ_APPROX, rtc_fast_freq_hz);
  133. }
  134. TEST_CASE("Test switching between PLL and XTAL", "[rtc_clk]")
  135. {
  136. test_clock_switching(rtc_clk_cpu_freq_set_config);
  137. }
  138. TEST_CASE("Test fast switching between PLL and XTAL", "[rtc_clk]")
  139. {
  140. test_clock_switching(rtc_clk_cpu_freq_set_config_fast);
  141. }
  142. #define COUNT_TEST 3
  143. #define TIMEOUT_TEST_MS (5 + CONFIG_ESP32_RTC_CLK_CAL_CYCLES / 16)
  144. void stop_rtc_external_quartz(void){
  145. const uint8_t pin_32 = 32;
  146. const uint8_t pin_33 = 33;
  147. rtc_clk_32k_enable(false);
  148. esp_rom_gpio_pad_select_gpio(pin_32);
  149. esp_rom_gpio_pad_select_gpio(pin_33);
  150. gpio_ll_output_enable(&GPIO, pin_32);
  151. gpio_ll_output_enable(&GPIO, pin_33);
  152. gpio_ll_set_level(&GPIO, pin_32, 0);
  153. gpio_ll_set_level(&GPIO, pin_33, 0);
  154. esp_rom_delay_us(500000);
  155. gpio_ll_output_disable(&GPIO, pin_32);
  156. gpio_ll_output_disable(&GPIO, pin_33);
  157. }
  158. static void start_freq(rtc_slow_freq_t required_src_freq, uint32_t start_delay_ms)
  159. {
  160. int i = 0, fail = 0;
  161. uint32_t start_time;
  162. uint32_t end_time;
  163. rtc_slow_freq_t selected_src_freq;
  164. stop_rtc_external_quartz();
  165. #ifdef CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS
  166. uint32_t bootstrap_cycles = CONFIG_ESP_SYSTEM_RTC_EXT_XTAL_BOOTSTRAP_CYCLES;
  167. printf("Test is started. Kconfig settings:\n External 32K crystal is selected,\n Oscillation cycles = %d,\n Calibration cycles = %d.\n",
  168. bootstrap_cycles,
  169. CONFIG_ESP32_RTC_CLK_CAL_CYCLES);
  170. #else
  171. uint32_t bootstrap_cycles = 5;
  172. printf("Test is started. Kconfig settings:\n Internal RC is selected,\n Oscillation cycles = %d,\n Calibration cycles = %d.\n",
  173. bootstrap_cycles,
  174. CONFIG_ESP32_RTC_CLK_CAL_CYCLES);
  175. #endif
  176. if (start_delay_ms == 0 && CONFIG_ESP32_RTC_CLK_CAL_CYCLES < 1500){
  177. start_delay_ms = 50;
  178. printf("Recommended increase Number of cycles for RTC_SLOW_CLK calibration to 3000!\n");
  179. }
  180. while(i < COUNT_TEST){
  181. start_time = xTaskGetTickCount() * (1000 / configTICK_RATE_HZ);
  182. i++;
  183. printf("attempt #%d/%d...", i, COUNT_TEST);
  184. rtc_clk_32k_bootstrap(bootstrap_cycles);
  185. esp_rom_delay_us(start_delay_ms * 1000);
  186. rtc_clk_select_rtc_slow_clk();
  187. selected_src_freq = rtc_clk_slow_freq_get();
  188. end_time = xTaskGetTickCount() * (1000 / configTICK_RATE_HZ);
  189. printf(" [time=%d] ", (end_time - start_time) - start_delay_ms);
  190. if(selected_src_freq != required_src_freq){
  191. printf("FAIL. Time measurement...");
  192. fail = 1;
  193. } else {
  194. printf("PASS. Time measurement...");
  195. }
  196. uint64_t clk_rtc_time;
  197. uint32_t fail_measure = 0;
  198. for (int j = 0; j < 3; ++j) {
  199. clk_rtc_time = esp_clk_rtc_time();
  200. esp_rom_delay_us(1000000);
  201. uint64_t delta = esp_clk_rtc_time() - clk_rtc_time;
  202. if (delta < 900000LL || delta > 1100000){
  203. printf("FAIL");
  204. fail = 1;
  205. fail_measure = 1;
  206. break;
  207. }
  208. }
  209. if(fail_measure == 0) {
  210. printf("PASS");
  211. }
  212. printf(" [calibration val = %d] \n", esp_clk_slowclk_cal_get());
  213. stop_rtc_external_quartz();
  214. esp_rom_delay_us(500000);
  215. }
  216. TEST_ASSERT_MESSAGE(fail == 0, "Test failed");
  217. printf("Test passed successfully\n");
  218. }
  219. TEST_CASE("Test starting external RTC quartz", "[rtc_clk][test_env=UT_T1_32kXTAL]")
  220. {
  221. int i = 0, fail = 0;
  222. uint32_t start_time;
  223. uint32_t end_time;
  224. stop_rtc_external_quartz();
  225. #ifdef CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS
  226. uint32_t bootstrap_cycles = CONFIG_ESP_SYSTEM_RTC_EXT_XTAL_BOOTSTRAP_CYCLES;
  227. printf("Test is started. Kconfig settings:\n External 32K crystal is selected,\n Oscillation cycles = %d,\n Calibration cycles = %d.\n",
  228. bootstrap_cycles,
  229. CONFIG_ESP32_RTC_CLK_CAL_CYCLES);
  230. #else
  231. uint32_t bootstrap_cycles = 5;
  232. printf("Test is started. Kconfig settings:\n Internal RC is selected,\n Oscillation cycles = %d,\n Calibration cycles = %d.\n",
  233. bootstrap_cycles,
  234. CONFIG_ESP32_RTC_CLK_CAL_CYCLES);
  235. #endif
  236. if (CONFIG_ESP32_RTC_CLK_CAL_CYCLES < 1500){
  237. printf("Recommended increase Number of cycles for RTC_SLOW_CLK calibration to 3000!\n");
  238. }
  239. while(i < COUNT_TEST){
  240. start_time = xTaskGetTickCount() * (1000 / configTICK_RATE_HZ);
  241. i++;
  242. printf("attempt #%d/%d...", i, COUNT_TEST);
  243. rtc_clk_32k_bootstrap(bootstrap_cycles);
  244. rtc_clk_select_rtc_slow_clk();
  245. end_time = xTaskGetTickCount() * (1000 / configTICK_RATE_HZ);
  246. printf(" [time=%d] ", end_time - start_time);
  247. if((end_time - start_time) > TIMEOUT_TEST_MS){
  248. printf("FAIL\n");
  249. fail = 1;
  250. } else {
  251. printf("PASS\n");
  252. }
  253. stop_rtc_external_quartz();
  254. esp_rom_delay_us(100000);
  255. }
  256. TEST_ASSERT_MESSAGE(fail == 0, "Test failed");
  257. printf("Test passed successfully\n");
  258. }
  259. TEST_CASE("Test starting 'External 32kHz XTAL' on the board with it.", "[rtc_clk][test_env=UT_T1_32kXTAL]")
  260. {
  261. start_freq(RTC_SLOW_FREQ_32K_XTAL, 200);
  262. start_freq(RTC_SLOW_FREQ_32K_XTAL, 0);
  263. }
  264. TEST_CASE("Test starting 'External 32kHz XTAL' on the board without it.", "[rtc_clk][test_env=UT_T1_no32kXTAL]")
  265. {
  266. printf("Tries to start the 'External 32kHz XTAL' on the board without it. "
  267. "Clock switching to 'Internal 150 kHz RC oscillator'.\n");
  268. printf("This test will be successful for boards without an external crystal or non-working crystal. "
  269. "First, there will be an attempt to start from the external crystal after a failure "
  270. "will switch to the internal RC circuit. If the switch to the internal RC circuit "
  271. "was successful then the test succeeded.\n");
  272. start_freq(RTC_SLOW_FREQ_RTC, 200);
  273. start_freq(RTC_SLOW_FREQ_RTC, 0);
  274. }
  275. #endif
  276. static RTC_NOINIT_ATTR int64_t start = 0;
  277. TEST_CASE("Test rtc clk calibration compensation", "[rtc_clk]")
  278. {
  279. int64_t t1 = esp_rtc_get_time_us();
  280. // Modify calibration value
  281. esp_clk_slowclk_cal_set(esp_clk_slowclk_cal_get() / 2);
  282. // Delay for error accumulation.
  283. vTaskDelay(pdMS_TO_TICKS(1000));
  284. // Internally, the origin point of rtc clk has been adjusted
  285. // so that t2 > t1 remains true
  286. int64_t t2 = esp_rtc_get_time_us();
  287. TEST_ASSERT_GREATER_THAN(t1, t2);
  288. // Restore calibration value
  289. esp_clk_slowclk_cal_set(esp_clk_slowclk_cal_get() * 2);
  290. // Delay for error accumulation.
  291. vTaskDelay(pdMS_TO_TICKS(1000));
  292. t2 = esp_rtc_get_time_us();
  293. TEST_ASSERT_GREATER_THAN(t1, t2);
  294. }
  295. static void trigger_deepsleep(void)
  296. {
  297. printf("Trigger deep sleep. Waiting for 10 sec ...\n");
  298. // Simulate the dispersion of the calibration coefficients at start-up.
  299. // Corrupt the calibration factor.
  300. esp_clk_slowclk_cal_set(esp_clk_slowclk_cal_get() / 2);
  301. // Delay for error accumulation.
  302. vTaskDelay(pdMS_TO_TICKS(1000));
  303. // Save start time. Deep sleep.
  304. start = esp_rtc_get_time_us();
  305. esp_sleep_enable_timer_wakeup(1000);
  306. // In function esp_deep_sleep_start() uses function esp_sync_counters_rtc_and_frc()
  307. // to prevent a negative time after wake up.
  308. esp_deep_sleep_start();
  309. }
  310. static void check_time_deepsleep_1(void)
  311. {
  312. RESET_REASON reason = rtc_get_reset_reason(0);
  313. TEST_ASSERT(reason == DEEPSLEEP_RESET);
  314. int64_t end = esp_rtc_get_time_us();
  315. TEST_ASSERT_GREATER_THAN(start, end);
  316. esp_clk_slowclk_cal_set(esp_clk_slowclk_cal_get() * 2);
  317. // Delay for error accumulation.
  318. vTaskDelay(pdMS_TO_TICKS(1000));
  319. start = esp_rtc_get_time_us();
  320. esp_sleep_enable_timer_wakeup(1000);
  321. // In function esp_deep_sleep_start() uses function esp_sync_counters_rtc_and_frc()
  322. // to prevent a negative time after wake up.
  323. esp_deep_sleep_start();
  324. }
  325. static void check_time_deepsleep_2(void)
  326. {
  327. RESET_REASON reason = rtc_get_reset_reason(0);
  328. TEST_ASSERT(reason == DEEPSLEEP_RESET);
  329. int64_t end = esp_rtc_get_time_us();
  330. TEST_ASSERT_GREATER_THAN(start, end);
  331. }
  332. TEST_CASE_MULTIPLE_STAGES("Test rtc clk calibration compensation across deep sleep", "[rtc_clk][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET]", trigger_deepsleep, check_time_deepsleep_1, check_time_deepsleep_2);