test_ledc.c 25 KB

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