test_ledc.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. /*
  2. * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /* LEDC tested by PCNT in some case
  7. * PCNT can get the LEDC waveform frequency
  8. *
  9. * some calculation related with duty:
  10. * real duty = duty/2^duty_resolution
  11. */
  12. #include <esp_types.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <malloc.h>
  16. #include <string.h>
  17. #include "freertos/FreeRTOS.h"
  18. #include "freertos/task.h"
  19. #include "freertos/semphr.h"
  20. #include "freertos/queue.h"
  21. #include "unity.h"
  22. #include "soc/ledc_periph.h"
  23. #include "soc/gpio_periph.h"
  24. #include "soc/io_mux_reg.h"
  25. #include "esp_system.h"
  26. #include "driver/ledc.h"
  27. #include "hal/ledc_ll.h"
  28. #include "driver/gpio.h"
  29. #define PULSE_IO 18
  30. #define TEST_PWM_FREQ 2000
  31. #if SOC_LEDC_SUPPORT_HS_MODE
  32. #define TEST_SPEED_MODE LEDC_HIGH_SPEED_MODE
  33. #define SPEED_MODE_LIST {LEDC_HIGH_SPEED_MODE, LEDC_LOW_SPEED_MODE}
  34. #else
  35. #define TEST_SPEED_MODE LEDC_LOW_SPEED_MODE
  36. #define SPEED_MODE_LIST {LEDC_LOW_SPEED_MODE}
  37. #endif
  38. #if SOC_LEDC_SUPPORT_APB_CLOCK
  39. #define TEST_DEFAULT_CLK_CFG LEDC_USE_APB_CLK
  40. #elif SOC_LEDC_SUPPORT_PLL_DIV_CLOCK
  41. #define TEST_DEFAULT_CLK_CFG LEDC_USE_PLL_DIV_CLK
  42. #endif
  43. static ledc_channel_config_t initialize_channel_config(void)
  44. {
  45. ledc_channel_config_t config;
  46. memset(&config, 0, sizeof(ledc_channel_config_t));
  47. config.gpio_num = PULSE_IO;
  48. config.speed_mode = TEST_SPEED_MODE;
  49. config.channel = LEDC_CHANNEL_0;
  50. config.intr_type = LEDC_INTR_DISABLE;
  51. config.timer_sel = LEDC_TIMER_0;
  52. config.duty = 4000;
  53. config.hpoint = 0;
  54. return config;
  55. }
  56. static ledc_timer_config_t create_default_timer_config(void)
  57. {
  58. ledc_timer_config_t ledc_time_config;
  59. memset(&ledc_time_config, 0, sizeof(ledc_timer_config_t));
  60. ledc_time_config.speed_mode = TEST_SPEED_MODE;
  61. ledc_time_config.duty_resolution = LEDC_TIMER_13_BIT;
  62. ledc_time_config.timer_num = LEDC_TIMER_0;
  63. ledc_time_config.freq_hz = TEST_PWM_FREQ;
  64. ledc_time_config.clk_cfg = TEST_DEFAULT_CLK_CFG;
  65. return ledc_time_config;
  66. }
  67. static void fade_setup(void)
  68. {
  69. ledc_channel_config_t ledc_ch_config = initialize_channel_config();
  70. ledc_ch_config.duty = 0;
  71. ledc_timer_config_t ledc_time_config = create_default_timer_config();
  72. TEST_ESP_OK(ledc_channel_config(&ledc_ch_config));
  73. TEST_ESP_OK(ledc_timer_config(&ledc_time_config));
  74. vTaskDelay(5 / portTICK_PERIOD_MS);
  75. //initialize fade service
  76. TEST_ESP_OK(ledc_fade_func_install(0));
  77. }
  78. static void timer_duty_set_get(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty)
  79. {
  80. TEST_ESP_OK(ledc_set_duty(speed_mode, channel, duty));
  81. TEST_ESP_OK(ledc_update_duty(speed_mode, channel));
  82. vTaskDelay(100 / portTICK_PERIOD_MS);
  83. TEST_ASSERT_EQUAL_INT32(duty, ledc_get_duty(speed_mode, channel));
  84. }
  85. // use logic analyzer to view
  86. static void timer_duty_test(ledc_channel_t channel, ledc_timer_bit_t timer_bit, ledc_timer_t timer, ledc_mode_t speed_mode)
  87. {
  88. ledc_channel_config_t ledc_ch_config = initialize_channel_config();
  89. ledc_ch_config.speed_mode = speed_mode;
  90. ledc_ch_config.channel = channel;
  91. ledc_ch_config.timer_sel = timer;
  92. ledc_timer_config_t ledc_time_config = create_default_timer_config();
  93. ledc_time_config.speed_mode = speed_mode;
  94. ledc_time_config.duty_resolution = timer_bit;
  95. ledc_time_config.timer_num = timer;
  96. TEST_ESP_OK(ledc_channel_config(&ledc_ch_config));
  97. TEST_ESP_OK(ledc_timer_config(&ledc_time_config));
  98. // duty ratio: (2^duty)/(2^timer_bit)
  99. timer_duty_set_get(ledc_ch_config.speed_mode, ledc_ch_config.channel, 0);
  100. timer_duty_set_get(ledc_ch_config.speed_mode, ledc_ch_config.channel, 1);
  101. timer_duty_set_get(ledc_ch_config.speed_mode, ledc_ch_config.channel, 1 << 12); // 50% duty
  102. timer_duty_set_get(ledc_ch_config.speed_mode, ledc_ch_config.channel, (1 << 13) - 1);
  103. timer_duty_set_get(ledc_ch_config.speed_mode, ledc_ch_config.channel, (1 << 13) - 2);
  104. }
  105. TEST_CASE("LEDC channel config wrong gpio", "[ledc]")
  106. {
  107. ledc_channel_config_t ledc_ch_config = initialize_channel_config();
  108. ledc_ch_config.gpio_num = GPIO_NUM_MAX;
  109. TEST_ASSERT(ledc_channel_config(&ledc_ch_config) == ESP_ERR_INVALID_ARG);
  110. }
  111. TEST_CASE("LEDC channel config wrong speed", "[ledc]")
  112. {
  113. ledc_channel_config_t ledc_ch_config = initialize_channel_config();
  114. ledc_ch_config.speed_mode = LEDC_SPEED_MODE_MAX;
  115. TEST_ASSERT(ledc_channel_config(&ledc_ch_config) == ESP_ERR_INVALID_ARG);
  116. }
  117. TEST_CASE("LEDC channel config wrong channel", "[ledc]")
  118. {
  119. ledc_channel_config_t ledc_ch_config = initialize_channel_config();
  120. ledc_ch_config.channel = LEDC_CHANNEL_MAX;
  121. TEST_ASSERT(ledc_channel_config(&ledc_ch_config) == ESP_ERR_INVALID_ARG);
  122. }
  123. TEST_CASE("LEDC channel config wrong interrupt type", "[ledc]")
  124. {
  125. ledc_channel_config_t ledc_ch_config = initialize_channel_config();
  126. ledc_ch_config.intr_type = 2;
  127. TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, ledc_channel_config(&ledc_ch_config));
  128. }
  129. TEST_CASE("LEDC wrong timer", "[ledc]")
  130. {
  131. ledc_channel_config_t ledc_ch_config = initialize_channel_config();
  132. ledc_ch_config.timer_sel = LEDC_TIMER_MAX;
  133. TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, ledc_channel_config(&ledc_ch_config));
  134. }
  135. TEST_CASE("LEDC channel config basic parameter test", "[ledc]")
  136. {
  137. ledc_channel_config_t ledc_ch_config = initialize_channel_config();
  138. TEST_ASSERT_EQUAL(ESP_OK, ledc_channel_config(&ledc_ch_config));
  139. }
  140. TEST_CASE("LEDC wrong duty resolution", "[ledc]")
  141. {
  142. ledc_timer_config_t ledc_time_config = create_default_timer_config();
  143. ledc_time_config.duty_resolution = LEDC_TIMER_BIT_MAX;
  144. TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, ledc_timer_config(&ledc_time_config));
  145. }
  146. TEST_CASE("LEDC timer config wrong timer", "[ledc]")
  147. {
  148. ledc_timer_config_t ledc_time_config = create_default_timer_config();
  149. ledc_time_config.timer_num = LEDC_TIMER_MAX;
  150. TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, ledc_timer_config(&ledc_time_config));
  151. }
  152. TEST_CASE("LEDC timer config wrong speed mode", "[ledc]")
  153. {
  154. ledc_timer_config_t ledc_time_config = create_default_timer_config();
  155. ledc_time_config.speed_mode = LEDC_SPEED_MODE_MAX;
  156. TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, ledc_timer_config(&ledc_time_config));
  157. }
  158. TEST_CASE("LEDC timer config basic parameter test", "[ledc]")
  159. {
  160. ledc_timer_config_t ledc_time_config = create_default_timer_config();
  161. TEST_ESP_OK(ledc_timer_config(&ledc_time_config));
  162. }
  163. TEST_CASE("LEDC output idle level test", "[ledc]")
  164. {
  165. const ledc_mode_t test_speed_mode = TEST_SPEED_MODE;
  166. ledc_channel_config_t ledc_ch_config = initialize_channel_config();
  167. ledc_timer_config_t ledc_time_config = create_default_timer_config();
  168. TEST_ESP_OK(ledc_timer_config(&ledc_time_config));
  169. TEST_ESP_OK(ledc_channel_config(&ledc_ch_config));
  170. uint32_t current_level = LEDC.channel_group[test_speed_mode].channel[LEDC_CHANNEL_0].conf0.idle_lv;
  171. TEST_ESP_OK(ledc_stop(test_speed_mode, LEDC_CHANNEL_0, !current_level));
  172. vTaskDelay(1000 / portTICK_PERIOD_MS);
  173. TEST_ASSERT_EQUAL_INT32(LEDC.channel_group[test_speed_mode].channel[LEDC_CHANNEL_0].conf0.idle_lv, !current_level);
  174. }
  175. TEST_CASE("LEDC iterate over all channel and timer configs", "[ledc]")
  176. {
  177. ledc_channel_config_t ledc_ch_config = initialize_channel_config();
  178. ledc_timer_config_t ledc_time_config = create_default_timer_config();
  179. // use all kinds of speed mode, channel, timer combination to test all of possible configuration
  180. ledc_mode_t speed_mode[LEDC_SPEED_MODE_MAX] = SPEED_MODE_LIST;
  181. ledc_channel_t channels[8] = {LEDC_CHANNEL_0, LEDC_CHANNEL_1, LEDC_CHANNEL_2, LEDC_CHANNEL_3, LEDC_CHANNEL_4, LEDC_CHANNEL_5};
  182. ledc_timer_t timer_select[4] = {LEDC_TIMER_0, LEDC_TIMER_1, LEDC_TIMER_2, LEDC_TIMER_3};
  183. for (int i = 0; i < LEDC_SPEED_MODE_MAX; i++) {
  184. ledc_ch_config.speed_mode = speed_mode[i];
  185. ledc_time_config.speed_mode = speed_mode[i];
  186. for (int j = 0; j < 8; j++) {
  187. ledc_ch_config.channel = channels[j];
  188. for (int k = 0; k < 4; k++) {
  189. ledc_ch_config.timer_sel = timer_select[k];
  190. ledc_time_config.timer_num = timer_select[k];
  191. TEST_ESP_OK(ledc_channel_config(&ledc_ch_config));
  192. TEST_ESP_OK(ledc_timer_config(&ledc_time_config));
  193. }
  194. }
  195. }
  196. }
  197. TEST_CASE("LEDC memory leak test", "[ledc]")
  198. {
  199. ledc_channel_config_t ledc_ch_config = initialize_channel_config();
  200. TEST_ESP_OK(ledc_channel_config(&ledc_ch_config));
  201. ledc_timer_config_t ledc_time_config = create_default_timer_config();
  202. TEST_ESP_OK(ledc_timer_config(&ledc_time_config));
  203. uint32_t size = esp_get_free_heap_size();
  204. uint32_t i;
  205. // install and uninstall for 1000 times to test whether memory leaking exists
  206. for (i = 0; i <= 1000; i++) {
  207. TEST_ESP_OK(ledc_fade_func_install(0));
  208. ledc_fade_func_uninstall();
  209. }
  210. TEST_ASSERT_INT32_WITHIN(100, size, esp_get_free_heap_size());
  211. TEST_ESP_OK(ledc_stop(ledc_time_config.speed_mode, LEDC_CHANNEL_0, 0));
  212. }
  213. // duty should be manually checked from the waveform using a logic analyzer
  214. // this test is enabled only for testting the settings
  215. TEST_CASE("LEDC set and get duty", "[ledc]")
  216. {
  217. ledc_timer_t timer_list[4] = {LEDC_TIMER_0, LEDC_TIMER_1, LEDC_TIMER_2, LEDC_TIMER_3};
  218. ledc_mode_t speed_mode_list[LEDC_SPEED_MODE_MAX] = SPEED_MODE_LIST;
  219. for (int i = 0; i < LEDC_TIMER_MAX - 1; i++) {
  220. for (int j = 0; j < LEDC_SPEED_MODE_MAX; j++) {
  221. timer_duty_test(LEDC_CHANNEL_0, LEDC_TIMER_13_BIT, timer_list[i], speed_mode_list[j]);
  222. }
  223. }
  224. }
  225. TEST_CASE("LEDC fade with time", "[ledc]")
  226. {
  227. const ledc_mode_t test_speed_mode = TEST_SPEED_MODE;
  228. fade_setup();
  229. TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 4000, 200));
  230. TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_WAIT_DONE));
  231. TEST_ASSERT_EQUAL_INT32(4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
  232. TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 0, 200));
  233. TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT));
  234. // duty should not be too far from initial value
  235. TEST_ASSERT_INT32_WITHIN(20, 4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
  236. vTaskDelay(210 / portTICK_PERIOD_MS);
  237. TEST_ASSERT_EQUAL_INT32(0, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
  238. //deinitialize fade service
  239. ledc_fade_func_uninstall();
  240. }
  241. TEST_CASE("LEDC fade with step", "[ledc]")
  242. {
  243. const ledc_mode_t test_speed_mode = TEST_SPEED_MODE;
  244. fade_setup();
  245. TEST_ESP_OK(ledc_set_fade_with_step(test_speed_mode, LEDC_CHANNEL_0, 4000, 4, 1));
  246. TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_WAIT_DONE));
  247. TEST_ASSERT_EQUAL_INT32(4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
  248. TEST_ESP_OK(ledc_set_fade_with_step(test_speed_mode, LEDC_CHANNEL_0, 0, 4, 1));
  249. TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT));
  250. // duty should not be too far from initial value
  251. TEST_ASSERT_INT32_WITHIN(20, 4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
  252. vTaskDelay(525 / portTICK_PERIOD_MS);
  253. TEST_ASSERT_EQUAL_INT32(0, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
  254. //scaler=0 check
  255. TEST_ASSERT(ledc_set_fade_with_step(test_speed_mode, LEDC_CHANNEL_0, 4000, 0, 1) == ESP_ERR_INVALID_ARG);
  256. //deinitialize fade service
  257. ledc_fade_func_uninstall();
  258. }
  259. TEST_CASE("LEDC fast switching duty with fade_wait_done", "[ledc]")
  260. {
  261. const ledc_mode_t test_speed_mode = TEST_SPEED_MODE;
  262. fade_setup();
  263. // fade function will block until fading to the target duty
  264. int64_t fade_start, fade_stop;
  265. fade_start = esp_timer_get_time();
  266. TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 4000, 200));
  267. TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_WAIT_DONE));
  268. TEST_ASSERT_EQUAL_INT32(4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
  269. TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 1000, 150));
  270. TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_WAIT_DONE));
  271. TEST_ASSERT_EQUAL_INT32(1000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
  272. fade_stop = esp_timer_get_time();
  273. int time_ms = (fade_stop - fade_start) / 1000;
  274. TEST_ASSERT_TRUE(fabs(time_ms - 350) < 20);
  275. // next duty update will not take place until last fade reaches its target duty
  276. TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 4000, 200));
  277. TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_WAIT_DONE));
  278. TEST_ASSERT_EQUAL_INT32(4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
  279. TEST_ESP_OK(ledc_set_duty(test_speed_mode, LEDC_CHANNEL_0, 500));
  280. TEST_ESP_OK(ledc_update_duty(test_speed_mode, LEDC_CHANNEL_0));
  281. vTaskDelay(5 / portTICK_PERIOD_MS);
  282. TEST_ASSERT_EQUAL_INT32(500, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
  283. //deinitialize fade service
  284. ledc_fade_func_uninstall();
  285. }
  286. TEST_CASE("LEDC fast switching duty with fade_no_wait", "[ledc]")
  287. {
  288. const ledc_mode_t test_speed_mode = TEST_SPEED_MODE;
  289. fade_setup();
  290. // fade function returns immediately, but next fade still needs to wait for last fade ends
  291. int64_t fade_start, first_fade_complete;
  292. fade_start = esp_timer_get_time();
  293. TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 4000, 200));
  294. TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT));
  295. TEST_ASSERT_LESS_THAN(4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
  296. TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 1000, 150));
  297. TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT));
  298. first_fade_complete = esp_timer_get_time();
  299. // duty should not be too far from first fade target duty
  300. TEST_ASSERT_INT32_WITHIN(20, 4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
  301. int time_ms = (first_fade_complete - fade_start) / 1000;
  302. TEST_ASSERT_TRUE(fabs(time_ms - 200) < 20);
  303. vTaskDelay(158 / portTICK_PERIOD_MS);
  304. TEST_ASSERT_EQUAL_INT32(1000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
  305. // next duty update will not take place until last fade reaches its target duty
  306. TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 4000, 200));
  307. TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT));
  308. TEST_ASSERT_LESS_THAN(4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
  309. TEST_ESP_OK(ledc_set_duty(test_speed_mode, LEDC_CHANNEL_0, 500));
  310. TEST_ESP_OK(ledc_update_duty(test_speed_mode, LEDC_CHANNEL_0));
  311. vTaskDelay(5 / portTICK_PERIOD_MS);
  312. TEST_ASSERT_EQUAL_INT32(500, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
  313. //deinitialize fade service
  314. ledc_fade_func_uninstall();
  315. }
  316. #if SOC_LEDC_SUPPORT_FADE_STOP
  317. TEST_CASE("LEDC fade stop test", "[ledc]")
  318. {
  319. const ledc_mode_t test_speed_mode = TEST_SPEED_MODE;
  320. fade_setup();
  321. int64_t fade_start, fade_stop;
  322. int time_ms = 0;
  323. fade_start = esp_timer_get_time();
  324. TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 4000, 500));
  325. TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT));
  326. // Add some delay before stopping the fade
  327. vTaskDelay(127 / portTICK_PERIOD_MS);
  328. // Get duty value right before stopping the fade
  329. uint32_t duty_before_stop = ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0);
  330. TEST_ESP_OK(ledc_fade_stop(test_speed_mode, LEDC_CHANNEL_0));
  331. fade_stop = esp_timer_get_time();
  332. time_ms = (fade_stop - fade_start) / 1000;
  333. TEST_ASSERT_TRUE(fabs(time_ms - 127) < 20);
  334. // Get duty value after fade_stop returns (give at least one cycle for the duty set in fade_stop to take effective)
  335. uint32_t duty_after_stop = ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0);
  336. TEST_ASSERT_INT32_WITHIN(4, duty_before_stop, duty_after_stop); // 4 is the scale for one step in the last fade
  337. vTaskDelay(300 / portTICK_PERIOD_MS);
  338. // Duty should not change any more after ledc_fade_stop returns
  339. TEST_ASSERT_EQUAL_INT32(duty_after_stop, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
  340. TEST_ASSERT_NOT_EQUAL(4000, duty_after_stop);
  341. //deinitialize fade service
  342. ledc_fade_func_uninstall();
  343. }
  344. #endif // SOC_LEDC_SUPPORT_FADE_STOP
  345. #if SOC_PCNT_SUPPORTED // Note. C3, C2, H2 do not have PCNT peripheral, the following test cases cannot be tested
  346. #include "driver/pulse_cnt.h"
  347. #define HIGHEST_LIMIT 10000
  348. #define LOWEST_LIMIT -10000
  349. static pcnt_unit_handle_t pcnt_unit;
  350. static pcnt_channel_handle_t pcnt_chan;
  351. static void setup_testbench(void)
  352. {
  353. pcnt_unit_config_t unit_config = {
  354. .high_limit = HIGHEST_LIMIT,
  355. .low_limit = LOWEST_LIMIT,
  356. };
  357. TEST_ESP_OK(pcnt_new_unit(&unit_config, &pcnt_unit));
  358. pcnt_chan_config_t chan_config = {
  359. .edge_gpio_num = PULSE_IO,
  360. .level_gpio_num = -1,
  361. };
  362. TEST_ESP_OK(pcnt_new_channel(pcnt_unit, &chan_config, &pcnt_chan));
  363. TEST_ESP_OK(pcnt_channel_set_level_action(pcnt_chan, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP));
  364. TEST_ESP_OK(pcnt_channel_set_edge_action(pcnt_chan, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
  365. }
  366. static void tear_testbench(void)
  367. {
  368. TEST_ESP_OK(pcnt_del_channel(pcnt_chan));
  369. TEST_ESP_OK(pcnt_del_unit(pcnt_unit));
  370. }
  371. // use PCNT to test the waveform of LEDC
  372. static int wave_count(int last_time)
  373. {
  374. // The input ability of PULSE_IO is disabled after ledc driver install, so we need to reenable it again
  375. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[PULSE_IO]);
  376. int test_counter = 0;
  377. TEST_ESP_OK(pcnt_unit_clear_count(pcnt_unit));
  378. TEST_ESP_OK(pcnt_unit_start(pcnt_unit));
  379. vTaskDelay(pdMS_TO_TICKS(last_time));
  380. TEST_ESP_OK(pcnt_unit_stop(pcnt_unit));
  381. TEST_ESP_OK(pcnt_unit_get_count(pcnt_unit, &test_counter));
  382. return test_counter;
  383. }
  384. // the PCNT will count the frequency of it
  385. static void frequency_set_get(ledc_mode_t speed_mode, ledc_timer_t timer, uint32_t freq_hz, int16_t real_freq, int16_t error)
  386. {
  387. int count;
  388. TEST_ESP_OK(ledc_set_freq(speed_mode, timer, freq_hz));
  389. count = wave_count(1000);
  390. TEST_ASSERT_INT16_WITHIN(error, count, real_freq);
  391. TEST_ASSERT_EQUAL_INT32(real_freq, ledc_get_freq(speed_mode, timer));
  392. }
  393. static void timer_frequency_test(ledc_channel_t channel, ledc_timer_bit_t timer_bit, ledc_timer_t timer, ledc_mode_t speed_mode)
  394. {
  395. ledc_channel_config_t ledc_ch_config = {
  396. .gpio_num = PULSE_IO,
  397. .speed_mode = speed_mode,
  398. .channel = channel,
  399. .intr_type = LEDC_INTR_DISABLE,
  400. .timer_sel = timer,
  401. .duty = 4000,
  402. .hpoint = 0,
  403. };
  404. ledc_timer_config_t ledc_time_config = {
  405. .speed_mode = speed_mode,
  406. .duty_resolution = timer_bit,
  407. .timer_num = timer,
  408. .freq_hz = 5000,
  409. .clk_cfg = LEDC_USE_APB_CLK,
  410. };
  411. TEST_ESP_OK(ledc_channel_config(&ledc_ch_config));
  412. TEST_ESP_OK(ledc_timer_config(&ledc_time_config));
  413. frequency_set_get(ledc_ch_config.speed_mode, ledc_ch_config.timer_sel, 100, 100, 20);
  414. frequency_set_get(ledc_ch_config.speed_mode, ledc_ch_config.timer_sel, 5000, 5000, 50);
  415. frequency_set_get(ledc_ch_config.speed_mode, ledc_ch_config.timer_sel, 9000, 8992, 50);
  416. }
  417. TEST_CASE("LEDC set and get frequency", "[ledc][timeout=60][ignore]")
  418. {
  419. setup_testbench();
  420. #if SOC_LEDC_SUPPORT_HS_MODE
  421. timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_13_BIT, LEDC_TIMER_0, LEDC_HIGH_SPEED_MODE);
  422. timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_13_BIT, LEDC_TIMER_1, LEDC_HIGH_SPEED_MODE);
  423. timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_13_BIT, LEDC_TIMER_2, LEDC_HIGH_SPEED_MODE);
  424. timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_13_BIT, LEDC_TIMER_3, LEDC_HIGH_SPEED_MODE);
  425. #endif // SOC_LEDC_SUPPORT_HS_MODE
  426. timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_13_BIT, LEDC_TIMER_0, LEDC_LOW_SPEED_MODE);
  427. timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_13_BIT, LEDC_TIMER_1, LEDC_LOW_SPEED_MODE);
  428. timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_13_BIT, LEDC_TIMER_2, LEDC_LOW_SPEED_MODE);
  429. timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_13_BIT, LEDC_TIMER_3, LEDC_LOW_SPEED_MODE);
  430. tear_testbench();
  431. }
  432. static void timer_set_clk_src_and_freq_test(ledc_mode_t speed_mode, ledc_clk_cfg_t clk_src, uint32_t duty_res,
  433. uint32_t freq_hz)
  434. {
  435. ledc_timer_config_t ledc_time_config = {
  436. .speed_mode = speed_mode,
  437. .duty_resolution = duty_res,
  438. .timer_num = LEDC_TIMER_0,
  439. .freq_hz = freq_hz,
  440. .clk_cfg = clk_src,
  441. };
  442. TEST_ESP_OK(ledc_timer_config(&ledc_time_config));
  443. vTaskDelay(100 / portTICK_PERIOD_MS);
  444. if (clk_src == LEDC_USE_RTC8M_CLK) {
  445. // RTC8M_CLK freq is get from calibration, it is reasonable that divider calculation does a rounding
  446. TEST_ASSERT_UINT32_WITHIN(5, ledc_get_freq(speed_mode, LEDC_TIMER_0), freq_hz);
  447. } else {
  448. TEST_ASSERT_EQUAL_INT32(ledc_get_freq(speed_mode, LEDC_TIMER_0), freq_hz);
  449. }
  450. int count = wave_count(1000);
  451. TEST_ASSERT_UINT32_WITHIN(10, count, freq_hz);
  452. }
  453. TEST_CASE("LEDC timer select specific clock source", "[ledc]")
  454. {
  455. setup_testbench();
  456. const ledc_mode_t test_speed_mode = TEST_SPEED_MODE;
  457. ledc_channel_config_t ledc_ch_config = {
  458. .gpio_num = PULSE_IO,
  459. .speed_mode = test_speed_mode,
  460. .channel = LEDC_CHANNEL_0,
  461. .intr_type = LEDC_INTR_DISABLE,
  462. .timer_sel = LEDC_TIMER_0,
  463. .duty = 800,
  464. .hpoint = 0,
  465. };
  466. TEST_ESP_OK(ledc_channel_config(&ledc_ch_config));
  467. if (test_speed_mode == LEDC_LOW_SPEED_MODE) {
  468. printf("Check LEDC_USE_RTC8M_CLK for a 100Hz signal\n");
  469. timer_set_clk_src_and_freq_test(test_speed_mode, LEDC_USE_RTC8M_CLK, 10, 100);
  470. #if SOC_LEDC_SUPPORT_XTAL_CLOCK
  471. printf("Check LEDC_USE_XTAL_CLK for a 400Hz signal\n");
  472. timer_set_clk_src_and_freq_test(test_speed_mode, LEDC_USE_XTAL_CLK, 13, 400);
  473. #endif
  474. }
  475. #if SOC_LEDC_SUPPORT_REF_TICK
  476. printf("Check LEDC_USE_REF_TICK for a 250Hz signal\n");
  477. timer_set_clk_src_and_freq_test(test_speed_mode, LEDC_USE_REF_TICK, 10, 250);
  478. #endif
  479. #if SOC_LEDC_SUPPORT_APB_CLOCK
  480. printf("Check LEDC_USE_APB_CLK for a 500Hz signal\n");
  481. timer_set_clk_src_and_freq_test(test_speed_mode, LEDC_USE_APB_CLK, 13, 500);
  482. #endif
  483. #if SOC_LEDC_SUPPORT_PLL_DIV_CLOCK
  484. printf("Check LEDC_USE_PLL_DIV_CLK for a 500Hz signal\n");
  485. timer_set_clk_src_and_freq_test(test_speed_mode, LEDC_USE_PLL_DIV_CLK, 13, 500);
  486. #endif
  487. printf("Bind channel 0 to timer 0\n");
  488. TEST_ESP_OK(ledc_bind_channel_timer(test_speed_mode, LEDC_CHANNEL_0, LEDC_TIMER_0));
  489. vTaskDelay(1000 / portTICK_PERIOD_MS);
  490. TEST_ASSERT_EQUAL_INT32(ledc_get_freq(test_speed_mode, LEDC_TIMER_0), 500);
  491. tear_testbench();
  492. }
  493. TEST_CASE("LEDC timer pause and resume", "[ledc]")
  494. {
  495. setup_testbench();
  496. const ledc_mode_t test_speed_mode = TEST_SPEED_MODE;
  497. int count;
  498. ledc_channel_config_t ledc_ch_config = {
  499. .gpio_num = PULSE_IO,
  500. .speed_mode = test_speed_mode,
  501. .channel = LEDC_CHANNEL_0,
  502. .intr_type = LEDC_INTR_DISABLE,
  503. .timer_sel = LEDC_TIMER_0,
  504. .duty = 4000,
  505. .hpoint = 0,
  506. };
  507. TEST_ESP_OK(ledc_channel_config(&ledc_ch_config));
  508. ledc_timer_config_t ledc_time_config = {
  509. .speed_mode = test_speed_mode,
  510. .duty_resolution = LEDC_TIMER_13_BIT,
  511. .timer_num = LEDC_TIMER_0,
  512. .freq_hz = 5000,
  513. .clk_cfg = TEST_DEFAULT_CLK_CFG,
  514. };
  515. TEST_ESP_OK(ledc_timer_config(&ledc_time_config));
  516. vTaskDelay(10 / portTICK_PERIOD_MS);
  517. count = wave_count(1000);
  518. TEST_ASSERT_INT16_WITHIN(5, count, 5000);
  519. //pause ledc timer, when pause it, will get no waveform count
  520. printf("Pause ledc timer\n");
  521. TEST_ESP_OK(ledc_timer_pause(test_speed_mode, LEDC_TIMER_0));
  522. vTaskDelay(10 / portTICK_PERIOD_MS);
  523. count = wave_count(1000);
  524. TEST_ASSERT_INT16_WITHIN(5, count, 0);
  525. TEST_ASSERT_EQUAL_UINT32(count, 0);
  526. //resume ledc timer
  527. printf("Resume ledc timer\n");
  528. TEST_ESP_OK(ledc_timer_resume(test_speed_mode, LEDC_TIMER_0));
  529. vTaskDelay(10 / portTICK_PERIOD_MS);
  530. count = wave_count(1000);
  531. TEST_ASSERT_UINT32_WITHIN(5, count, 5000);
  532. //reset ledc timer
  533. printf("reset ledc timer\n");
  534. TEST_ESP_OK(ledc_timer_rst(test_speed_mode, LEDC_TIMER_0));
  535. vTaskDelay(100 / portTICK_PERIOD_MS);
  536. TEST_ASSERT_UINT32_WITHIN(5, count, 5000);
  537. tear_testbench();
  538. }
  539. static void ledc_cpu_reset_test_first_stage(void)
  540. {
  541. ledc_channel_config_t ledc_ch_config = initialize_channel_config();
  542. TEST_ESP_OK(ledc_channel_config(&ledc_ch_config));
  543. ledc_timer_config_t ledc_time_config = create_default_timer_config();
  544. TEST_ESP_OK(ledc_timer_config(&ledc_time_config));
  545. vTaskDelay(50 / portTICK_PERIOD_MS);
  546. esp_restart();
  547. }
  548. static void ledc_cpu_reset_test_second_stage(void)
  549. {
  550. int count;
  551. TEST_ASSERT_EQUAL(ESP_RST_SW, esp_reset_reason());
  552. setup_testbench();
  553. // reconfigure the GPIO again, as the GPIO output ability has been disabled during initialize pcnt peripheral
  554. ledc_set_pin(PULSE_IO, TEST_SPEED_MODE, LEDC_CHANNEL_0);
  555. count = wave_count(1000);
  556. TEST_ASSERT_UINT32_WITHIN(5, TEST_PWM_FREQ, count);
  557. tear_testbench();
  558. }
  559. TEST_CASE_MULTIPLE_STAGES("LEDC continue work after software reset", "[ledc]",
  560. ledc_cpu_reset_test_first_stage,
  561. ledc_cpu_reset_test_second_stage);
  562. #endif // SOC_PCNT_SUPPORTED