test_gpio.c 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841
  1. /*
  2. * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * No specific runner required to run GPIO unit test.
  8. * TEST_GPIO_EXT_OUT_IO and TEST_GPIO_EXT_IN_IO are connected internally through gpio matrix.
  9. *
  10. * If wants to externally connect TEST_GPIO_EXT_OUT_IO to TEST_GPIO_EXT_IN_IO (UT_T1_GPIO), please set
  11. * TEST_GPIO_INTERNAL_ROUTING to 0
  12. */
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include "test_gpio.h"
  16. #include "esp_system.h"
  17. #include "esp_cpu.h"
  18. #include "esp_sleep.h"
  19. #include "unity.h"
  20. #include "unity_test_utils.h"
  21. #include "driver/gpio.h"
  22. #include "hal/gpio_ll.h"
  23. #include "soc/gpio_periph.h"
  24. #include "freertos/FreeRTOS.h"
  25. #include "freertos/task.h"
  26. #include "freertos/queue.h"
  27. #include "freertos/semphr.h"
  28. #include "sdkconfig.h"
  29. #include "esp_rom_uart.h"
  30. #include "esp_rom_sys.h"
  31. #include "spi_flash_mmap.h"
  32. #include "esp_attr.h"
  33. #include "esp_private/spi_flash_os.h"
  34. // Enable internal routing for the output and input gpio pins
  35. #define TEST_GPIO_INTERNAL_ROUTING 1
  36. // If there is any input-only pin, enable input-only pin part of some tests.
  37. #define SOC_HAS_INPUT_ONLY_PIN (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2)
  38. static volatile int disable_intr_times = 0; // use this to calculate how many times it go into interrupt
  39. static volatile int level_intr_times = 0; // use this to get how many times the level interrupt happened
  40. static volatile int edge_intr_times = 0; // use this to get how many times the edge interrupt happened
  41. /**
  42. * Do some initialization operation in this function
  43. * @param num it is the destination GPIO wanted to be initialized
  44. */
  45. static gpio_config_t test_init_io(gpio_num_t num)
  46. {
  47. TEST_ASSERT(GPIO_IS_VALID_OUTPUT_GPIO(num));
  48. gpio_config_t io_conf = {
  49. .intr_type = GPIO_INTR_DISABLE,
  50. .mode = GPIO_MODE_OUTPUT,
  51. .pin_bit_mask = (1ULL << num),
  52. .pull_down_en = 0,
  53. .pull_up_en = 0,
  54. };
  55. return io_conf;
  56. }
  57. /**
  58. * Configure gpio pin as GPIO_MODE_INPUT_OUTPUT for all the interrupt related tests to avoid runner requirements
  59. */
  60. static void test_gpio_config_mode_input_output(gpio_num_t num)
  61. {
  62. gpio_config_t input_output_io = test_init_io(num);
  63. input_output_io.mode = GPIO_MODE_INPUT_OUTPUT;
  64. input_output_io.pull_up_en = 1;
  65. TEST_ESP_OK(gpio_config(&input_output_io));
  66. }
  67. // test the basic configuration function with right parameters and error parameters
  68. TEST_CASE("GPIO_config_parameters_test", "[gpio]")
  69. {
  70. gpio_config_t io_config = { 0 };
  71. io_config.intr_type = GPIO_INTR_DISABLE;
  72. // test 0
  73. io_config.pin_bit_mask = 0;
  74. TEST_ASSERT(gpio_config(&io_config) == ESP_ERR_INVALID_ARG);
  75. // test a non-exist pin
  76. io_config.pin_bit_mask = ((uint64_t)1 << GPIO_NUM_MAX);
  77. TEST_ASSERT(gpio_config(&io_config) == ESP_ERR_INVALID_ARG);
  78. // test an available pin
  79. io_config.pin_bit_mask = ((uint64_t)1 << TEST_GPIO_EXT_OUT_IO);
  80. TEST_ESP_OK(gpio_config(&io_config));
  81. //This IO is just used for input, C3 and S3 doesn't have input only pin.
  82. #if SOC_HAS_INPUT_ONLY_PIN
  83. io_config.pin_bit_mask = ((uint64_t)1 << TEST_GPIO_INPUT_ONLY_PIN);
  84. io_config.mode = GPIO_MODE_INPUT;
  85. TEST_ESP_OK(gpio_config(&io_config));
  86. io_config.mode = GPIO_MODE_OUTPUT;
  87. // The pin is input only, once set as output should log something
  88. TEST_ASSERT(gpio_config(&io_config) == ESP_ERR_INVALID_ARG);
  89. #endif // SOC_HAS_INPUT_ONLY_PIN
  90. }
  91. // edge interrupt event
  92. static void gpio_isr_edge_handler(void *arg)
  93. {
  94. uint32_t gpio_num = (uint32_t) arg;
  95. esp_rom_printf("GPIO[%d] intr on core %d, val: %d\n", gpio_num, esp_cpu_get_core_id(), gpio_get_level(gpio_num));
  96. edge_intr_times++;
  97. }
  98. // level interrupt event with "gpio_intr_disable"
  99. static void gpio_isr_level_handler(void *arg)
  100. {
  101. uint32_t gpio_num = (uint32_t) arg;
  102. disable_intr_times++;
  103. esp_rom_printf("GPIO[%d] intr, val: %d, disable_intr_times = %d\n", gpio_num, gpio_get_level(gpio_num), disable_intr_times);
  104. gpio_intr_disable(gpio_num);
  105. }
  106. // level interrupt event with "gpio_set_level(!gpio_get_level)"
  107. static void gpio_isr_level_handler2(void *arg)
  108. {
  109. uint32_t gpio_num = (uint32_t) arg;
  110. level_intr_times++;
  111. esp_rom_printf("GPIO[%d] intr, val: %d, level_intr_times = %d\n", gpio_num, gpio_get_level(gpio_num), level_intr_times);
  112. if (gpio_get_level(gpio_num)) {
  113. gpio_set_level(gpio_num, 0);
  114. } else {
  115. gpio_set_level(gpio_num, 1);
  116. }
  117. }
  118. TEST_CASE("GPIO_rising_edge_interrupt_test", "[gpio]")
  119. {
  120. edge_intr_times = 0; // set it as 0 prepare to test
  121. test_gpio_config_mode_input_output(TEST_GPIO_INPUT_OUTPUT_IO1);
  122. TEST_ESP_OK(gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 0));
  123. // Rising edge intr
  124. TEST_ESP_OK(gpio_set_intr_type(TEST_GPIO_INPUT_OUTPUT_IO1, GPIO_INTR_POSEDGE));
  125. TEST_ESP_OK(gpio_install_isr_service(0));
  126. gpio_isr_handler_add(TEST_GPIO_INPUT_OUTPUT_IO1, gpio_isr_edge_handler, (void *) TEST_GPIO_INPUT_OUTPUT_IO1);
  127. TEST_ESP_OK(gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 1));
  128. vTaskDelay(100 / portTICK_PERIOD_MS);
  129. TEST_ASSERT_EQUAL_INT(1, edge_intr_times);
  130. gpio_isr_handler_remove(TEST_GPIO_INPUT_OUTPUT_IO1);
  131. gpio_uninstall_isr_service();
  132. }
  133. TEST_CASE("GPIO_falling_edge_interrupt_test", "[gpio]")
  134. {
  135. edge_intr_times = 0;
  136. test_gpio_config_mode_input_output(TEST_GPIO_INPUT_OUTPUT_IO1);
  137. TEST_ESP_OK(gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 1));
  138. gpio_set_intr_type(TEST_GPIO_INPUT_OUTPUT_IO1, GPIO_INTR_NEGEDGE);
  139. gpio_install_isr_service(0);
  140. gpio_isr_handler_add(TEST_GPIO_INPUT_OUTPUT_IO1, gpio_isr_edge_handler, (void *) TEST_GPIO_INPUT_OUTPUT_IO1);
  141. gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 0);
  142. vTaskDelay(100 / portTICK_PERIOD_MS);
  143. TEST_ASSERT_EQUAL_INT(1, edge_intr_times);
  144. gpio_isr_handler_remove(TEST_GPIO_INPUT_OUTPUT_IO1);
  145. gpio_uninstall_isr_service();
  146. }
  147. TEST_CASE("GPIO_both_rising_and_falling_edge_interrupt_test", "[gpio]")
  148. {
  149. edge_intr_times = 0;
  150. test_gpio_config_mode_input_output(TEST_GPIO_INPUT_OUTPUT_IO1);
  151. TEST_ESP_OK(gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 0));
  152. int level = 0;
  153. gpio_set_intr_type(TEST_GPIO_INPUT_OUTPUT_IO1, GPIO_INTR_ANYEDGE);
  154. gpio_install_isr_service(0);
  155. gpio_isr_handler_add(TEST_GPIO_INPUT_OUTPUT_IO1, gpio_isr_edge_handler, (void *) TEST_GPIO_INPUT_OUTPUT_IO1);
  156. // For rising edge in GPIO_INTR_ANYEDGE
  157. while (1) {
  158. level = level + 1;
  159. gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, level * 0.2);
  160. if (level > 10) {
  161. break;
  162. }
  163. vTaskDelay(100 / portTICK_PERIOD_MS);
  164. }
  165. vTaskDelay(100 / portTICK_PERIOD_MS);
  166. // For falling edge in GPIO_INTR_ANYEDGE
  167. while (1) {
  168. level = level - 1;
  169. gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, level / 5);
  170. if (level < 0) {
  171. break;
  172. }
  173. vTaskDelay(100 / portTICK_PERIOD_MS);
  174. }
  175. vTaskDelay(100 / portTICK_PERIOD_MS);
  176. TEST_ASSERT_EQUAL_INT(2, edge_intr_times);
  177. gpio_isr_handler_remove(TEST_GPIO_INPUT_OUTPUT_IO1);
  178. gpio_uninstall_isr_service();
  179. }
  180. TEST_CASE("GPIO_input_high_level_trigger_cut_the_interrupt_source_exit_interrupt_test", "[gpio]")
  181. {
  182. level_intr_times = 0;
  183. test_gpio_config_mode_input_output(TEST_GPIO_INPUT_OUTPUT_IO1);
  184. TEST_ESP_OK(gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 0));
  185. gpio_set_intr_type(TEST_GPIO_INPUT_OUTPUT_IO1, GPIO_INTR_HIGH_LEVEL);
  186. gpio_install_isr_service(0);
  187. gpio_isr_handler_add(TEST_GPIO_INPUT_OUTPUT_IO1, gpio_isr_level_handler2, (void *) TEST_GPIO_INPUT_OUTPUT_IO1);
  188. gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 1);
  189. vTaskDelay(100 / portTICK_PERIOD_MS);
  190. TEST_ASSERT_EQUAL_INT_MESSAGE(1, level_intr_times, "go into high-level interrupt more than once with cut interrupt source way");
  191. gpio_isr_handler_remove(TEST_GPIO_INPUT_OUTPUT_IO1);
  192. gpio_uninstall_isr_service();
  193. }
  194. TEST_CASE("GPIO_low_level_interrupt_test", "[gpio]")
  195. {
  196. disable_intr_times = 0;
  197. test_gpio_config_mode_input_output(TEST_GPIO_INPUT_OUTPUT_IO1);
  198. TEST_ESP_OK(gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 1));
  199. gpio_set_intr_type(TEST_GPIO_INPUT_OUTPUT_IO1, GPIO_INTR_LOW_LEVEL);
  200. gpio_install_isr_service(0);
  201. gpio_isr_handler_add(TEST_GPIO_INPUT_OUTPUT_IO1, gpio_isr_level_handler, (void *) TEST_GPIO_INPUT_OUTPUT_IO1);
  202. gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 0);
  203. printf("get level:%d\n", gpio_get_level(TEST_GPIO_INPUT_OUTPUT_IO1));
  204. vTaskDelay(100 / portTICK_PERIOD_MS);
  205. TEST_ASSERT_EQUAL_INT_MESSAGE(1, disable_intr_times, "go into low-level interrupt more than once with disable way");
  206. gpio_isr_handler_remove(TEST_GPIO_INPUT_OUTPUT_IO1);
  207. gpio_uninstall_isr_service();
  208. }
  209. TEST_CASE("GPIO_multi-level_trigger_cut_the_interrupt_source_exit_interrupt_test", "[gpio]")
  210. {
  211. level_intr_times = 0;
  212. test_gpio_config_mode_input_output(TEST_GPIO_INPUT_OUTPUT_IO1);
  213. TEST_ESP_OK(gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 0));
  214. gpio_set_intr_type(TEST_GPIO_INPUT_OUTPUT_IO1, GPIO_INTR_HIGH_LEVEL);
  215. gpio_install_isr_service(0);
  216. gpio_isr_handler_add(TEST_GPIO_INPUT_OUTPUT_IO1, gpio_isr_level_handler2, (void *) TEST_GPIO_INPUT_OUTPUT_IO1);
  217. gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 1);
  218. vTaskDelay(100 / portTICK_PERIOD_MS);
  219. TEST_ASSERT_EQUAL_INT_MESSAGE(1, level_intr_times, "go into high-level interrupt more than once with cut interrupt source way");
  220. gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 1);
  221. vTaskDelay(200 / portTICK_PERIOD_MS);
  222. TEST_ASSERT_EQUAL_INT_MESSAGE(2, level_intr_times, "go into high-level interrupt more than once with cut interrupt source way");
  223. gpio_isr_handler_remove(TEST_GPIO_INPUT_OUTPUT_IO1);
  224. gpio_uninstall_isr_service();
  225. }
  226. TEST_CASE("GPIO_enable_and_disable_interrupt_test", "[gpio]")
  227. {
  228. disable_intr_times = 0;
  229. test_gpio_config_mode_input_output(TEST_GPIO_INPUT_OUTPUT_IO1);
  230. TEST_ESP_OK(gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 0));
  231. TEST_ESP_OK(gpio_set_intr_type(TEST_GPIO_INPUT_OUTPUT_IO1, GPIO_INTR_HIGH_LEVEL));
  232. TEST_ESP_OK(gpio_install_isr_service(0));
  233. TEST_ESP_OK(gpio_isr_handler_add(TEST_GPIO_INPUT_OUTPUT_IO1, gpio_isr_level_handler, (void *) TEST_GPIO_INPUT_OUTPUT_IO1));
  234. TEST_ESP_OK(gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 1));
  235. TEST_ESP_OK(gpio_isr_handler_remove(TEST_GPIO_INPUT_OUTPUT_IO1));
  236. TEST_ESP_OK(gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 0));
  237. vTaskDelay(100 / portTICK_PERIOD_MS);
  238. TEST_ASSERT_EQUAL_INT_MESSAGE(1, disable_intr_times, "go into high-level interrupt more than once with disable way");
  239. // Interrupt disabled now
  240. TEST_ESP_OK(gpio_intr_disable(TEST_GPIO_INPUT_OUTPUT_IO1));
  241. TEST_ESP_OK(gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 1));
  242. vTaskDelay(100 / portTICK_PERIOD_MS);
  243. TEST_ASSERT_EQUAL_INT_MESSAGE(1, disable_intr_times, "disable interrupt does not work, still go into interrupt!");
  244. // Uninstall interrupt service
  245. gpio_uninstall_isr_service();
  246. TEST_ASSERT(gpio_isr_handler_add(TEST_GPIO_INPUT_OUTPUT_IO1, gpio_isr_level_handler, (void *) TEST_GPIO_INPUT_OUTPUT_IO1) == ESP_ERR_INVALID_STATE);
  247. TEST_ASSERT(gpio_isr_handler_remove(TEST_GPIO_INPUT_OUTPUT_IO1) == ESP_ERR_INVALID_STATE);
  248. }
  249. TEST_CASE("GPIO_repeatedly_call_service_and_isr_has_no_memory_leak_test", "[gpio][timeout=90]")
  250. {
  251. test_gpio_config_mode_input_output(TEST_GPIO_INPUT_OUTPUT_IO1);
  252. TEST_ESP_OK(gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 0));
  253. // Rising edge intr
  254. uint32_t size = esp_get_free_heap_size();
  255. for (int i = 0; i < 1000; i++) {
  256. TEST_ESP_OK(gpio_set_intr_type(TEST_GPIO_INPUT_OUTPUT_IO1, GPIO_INTR_POSEDGE));
  257. TEST_ESP_OK(gpio_install_isr_service(0));
  258. TEST_ESP_OK(gpio_isr_handler_add(TEST_GPIO_INPUT_OUTPUT_IO1, gpio_isr_edge_handler, (void *) TEST_GPIO_INPUT_OUTPUT_IO1));
  259. gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 1);
  260. TEST_ESP_OK(gpio_isr_handler_remove(TEST_GPIO_INPUT_OUTPUT_IO1));
  261. gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 0);
  262. gpio_uninstall_isr_service();
  263. }
  264. TEST_ASSERT_INT32_WITHIN(100, size, esp_get_free_heap_size());
  265. }
  266. typedef struct {
  267. int gpio_num;
  268. int isr_cnt;
  269. } gpio_isr_param_t;
  270. static void gpio_isr_per_pin_handler(void *arg)
  271. {
  272. gpio_isr_param_t *param = (gpio_isr_param_t *)arg;
  273. esp_rom_printf("GPIO[%d] intr, val: %d\n", param->gpio_num, gpio_get_level(param->gpio_num));
  274. param->isr_cnt++;
  275. }
  276. /** The old GPIO interrupt service routine used to poll the interrupt raw status register to find the GPIO that
  277. * triggered the interrupt. But this will incorrectly handle the interrupt disabled GPIOs, because the raw interrupt
  278. * status register can still be set when the trigger signal arrives, even if the interrupt is disabled.
  279. *
  280. * Do the following steps:
  281. * 1. Configure TEST_GPIO_INPUT_OUTPUT_IO1 and TEST_GPIO_INPUT_OUTPUT_IO2 input_output mode.
  282. * 2. Enable TEST_GPIO_INPUT_OUTPUT_IO1 dual edge triggered interrupt, enable TEST_GPIO_INPUT_OUTPUT_IO2 falling edge triggered interrupt.
  283. * 3. Trigger TEST_GPIO_INPUT_OUTPUT_IO1 interrupt, then disable TEST_GPIO_INPUT_OUTPUT_IO1 interrupt, and then trigger TEST_GPIO_INPUT_OUTPUT_IO1 interrupt again (This time will not respond to the interrupt).
  284. * 4. Trigger TEST_GPIO_INPUT_OUTPUT_IO2 interrupt.
  285. *
  286. * If the bug is not fixed, you will see, in the step 4, the interrupt of TEST_GPIO_INPUT_OUTPUT_IO1 will also respond.
  287. */
  288. TEST_CASE("GPIO_isr_responses_to_correct_gpios_test", "[gpio]")
  289. {
  290. gpio_isr_param_t io1_param = {
  291. .gpio_num = TEST_GPIO_INPUT_OUTPUT_IO1,
  292. .isr_cnt = 0,
  293. };
  294. gpio_isr_param_t io2_param = {
  295. .gpio_num = TEST_GPIO_INPUT_OUTPUT_IO2,
  296. .isr_cnt = 0,
  297. };
  298. test_gpio_config_mode_input_output(TEST_GPIO_INPUT_OUTPUT_IO1);
  299. test_gpio_config_mode_input_output(TEST_GPIO_INPUT_OUTPUT_IO2);
  300. TEST_ESP_OK(gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 0));
  301. TEST_ESP_OK(gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO2, 0));
  302. TEST_ESP_OK(gpio_install_isr_service(0));
  303. TEST_ESP_OK(gpio_set_intr_type(TEST_GPIO_INPUT_OUTPUT_IO1, GPIO_INTR_ANYEDGE));
  304. TEST_ESP_OK(gpio_set_intr_type(TEST_GPIO_INPUT_OUTPUT_IO2, GPIO_INTR_NEGEDGE));
  305. TEST_ESP_OK(gpio_isr_handler_add(TEST_GPIO_INPUT_OUTPUT_IO1, gpio_isr_per_pin_handler, (void *) &io1_param));
  306. TEST_ESP_OK(gpio_isr_handler_add(TEST_GPIO_INPUT_OUTPUT_IO2, gpio_isr_per_pin_handler, (void *) &io2_param));
  307. printf("Triggering the interrupt of GPIO%d\n", TEST_GPIO_INPUT_OUTPUT_IO1);
  308. // Rising edge
  309. TEST_ESP_OK(gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 1));
  310. vTaskDelay(100 / portTICK_PERIOD_MS);
  311. printf("Disable the interrupt of GPIO%d\n", TEST_GPIO_INPUT_OUTPUT_IO1);
  312. // Disable TEST_GPIO_INPUT_OUTPUT_IO1 interrupt, TEST_GPIO_INPUT_OUTPUT_IO1 will not respond to the next falling edge interrupt
  313. TEST_ESP_OK(gpio_intr_disable(TEST_GPIO_INPUT_OUTPUT_IO1));
  314. vTaskDelay(100 / portTICK_PERIOD_MS);
  315. // Falling edge
  316. TEST_ESP_OK(gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 0));
  317. printf("Triggering the interrupt of GPIO%d\n", TEST_GPIO_INPUT_OUTPUT_IO2);
  318. TEST_ESP_OK(gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO2, 1));
  319. vTaskDelay(100 / portTICK_PERIOD_MS);
  320. // Falling edge
  321. TEST_ESP_OK(gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO2, 0));
  322. vTaskDelay(100 / portTICK_PERIOD_MS);
  323. TEST_ESP_OK(gpio_isr_handler_remove(TEST_GPIO_INPUT_OUTPUT_IO1));
  324. TEST_ESP_OK(gpio_isr_handler_remove(TEST_GPIO_INPUT_OUTPUT_IO2));
  325. gpio_uninstall_isr_service();
  326. TEST_ASSERT((io1_param.isr_cnt == 1) && (io2_param.isr_cnt == 1));
  327. }
  328. #if !CONFIG_FREERTOS_UNICORE
  329. #include "esp_ipc.h"
  330. static void install_isr_service_task(void *arg)
  331. {
  332. uint32_t gpio_num = (uint32_t) arg;
  333. // Rising edge intr
  334. TEST_ESP_OK(gpio_set_intr_type(gpio_num, GPIO_INTR_POSEDGE));
  335. TEST_ESP_OK(gpio_install_isr_service(0));
  336. gpio_isr_handler_add(gpio_num, gpio_isr_edge_handler, (void *) gpio_num);
  337. vTaskSuspend(NULL);
  338. }
  339. TEST_CASE("GPIO_interrupt_on_other_CPUs_test", "[gpio]")
  340. {
  341. TaskHandle_t gpio_task_handle;
  342. test_gpio_config_mode_input_output(TEST_GPIO_INPUT_OUTPUT_IO1);
  343. for (int cpu_num = 1; cpu_num < portNUM_PROCESSORS; ++cpu_num) {
  344. // We assume unit-test task is running on core 0, so we install gpio interrupt on other cores
  345. edge_intr_times = 0;
  346. TEST_ESP_OK(gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 0));
  347. xTaskCreatePinnedToCore(install_isr_service_task, "install_isr_service_task", 2048, (void *) TEST_GPIO_INPUT_OUTPUT_IO1, 1, &gpio_task_handle, cpu_num);
  348. vTaskDelay(200 / portTICK_PERIOD_MS);
  349. TEST_ESP_OK(gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 1));
  350. vTaskDelay(100 / portTICK_PERIOD_MS);
  351. TEST_ASSERT_EQUAL_INT(1, edge_intr_times);
  352. gpio_isr_handler_remove(TEST_GPIO_INPUT_OUTPUT_IO1);
  353. gpio_uninstall_isr_service();
  354. unity_utils_task_delete(gpio_task_handle);
  355. }
  356. }
  357. static void gpio_intr_enable_task(void *param)
  358. {
  359. int gpio_num = (int) param;
  360. TEST_ESP_OK(gpio_intr_enable(gpio_num));
  361. }
  362. /** Test the GPIO Interrupt Enable API with dual core enabled. The GPIO ISR service routine is registered on one core.
  363. * When the GPIO interrupt on another core is enabled, the GPIO interrupt will be lost.
  364. * Note. This is only a problem for ESP32. On ESP32S3, interrupt enable is effective to both cores, therefore, no matter
  365. * which core the interrupt service is installed on, the GPIO interrupt won't be lost.
  366. *
  367. * First on the core 0, do the following steps:
  368. * 1. Configure TEST_GPIO_INPUT_OUTPUT_IO1 input_output mode, and enable the falling edge interrupt mode.
  369. * 2. Trigger TEST_GPIO_INPUT_OUTPUT_IO1 interrupt and check if the interrupt responds correctly.
  370. * 3. Disable TEST_GPIO_INPUT_OUTPUT_IO1 interrupt
  371. * Then on the core 1, do the following steps:
  372. * 1. Enable TEST_GPIO_INPUT_OUTPUT_IO1 interrupt again.
  373. * 2. Trigger TEST_GPIO_INPUT_OUTPUT_IO1 interrupt and check if the interrupt responds correctly.
  374. */
  375. TEST_CASE("GPIO_crosscore_interrupt_test", "[gpio]")
  376. {
  377. edge_intr_times = 0;
  378. test_gpio_config_mode_input_output(TEST_GPIO_INPUT_OUTPUT_IO1);
  379. TEST_ESP_OK(gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 0));
  380. TEST_ESP_OK(gpio_set_intr_type(TEST_GPIO_INPUT_OUTPUT_IO1, GPIO_INTR_NEGEDGE));
  381. // GPIO interrupt service installed on core 0
  382. TEST_ESP_OK(gpio_install_isr_service(0));
  383. TEST_ESP_OK(gpio_isr_handler_add(TEST_GPIO_INPUT_OUTPUT_IO1, gpio_isr_edge_handler, (void *) TEST_GPIO_INPUT_OUTPUT_IO1));
  384. vTaskDelay(1000 / portTICK_PERIOD_MS);
  385. TEST_ESP_OK(gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 1));
  386. vTaskDelay(100 / portTICK_PERIOD_MS);
  387. TEST_ESP_OK(gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 0));
  388. vTaskDelay(100 / portTICK_PERIOD_MS);
  389. TEST_ESP_OK(gpio_intr_disable(TEST_GPIO_INPUT_OUTPUT_IO1));
  390. TEST_ASSERT(edge_intr_times == 1);
  391. // Here, interrupt is enabling from core 1, but since the isr is installed on core 0, core 0 interrupt enable bit
  392. // will still be set instead of core 1 interrupt enable bit
  393. esp_ipc_call_blocking((xPortGetCoreID() == 0), gpio_intr_enable_task, (void *) TEST_GPIO_INPUT_OUTPUT_IO1);
  394. vTaskDelay(1000 / portTICK_PERIOD_MS);
  395. TEST_ESP_OK(gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 1));
  396. vTaskDelay(100 / portTICK_PERIOD_MS);
  397. TEST_ESP_OK(gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 0));
  398. vTaskDelay(100 / portTICK_PERIOD_MS);
  399. TEST_ESP_OK(gpio_intr_disable(TEST_GPIO_INPUT_OUTPUT_IO1));
  400. TEST_ESP_OK(gpio_isr_handler_remove(TEST_GPIO_INPUT_OUTPUT_IO1));
  401. gpio_uninstall_isr_service();
  402. TEST_ASSERT(edge_intr_times == 2);
  403. }
  404. #endif //!CONFIG_FREERTOS_UNICORE
  405. #if CONFIG_GPIO_CTRL_FUNC_IN_IRAM
  406. static volatile DRAM_ATTR bool isr_triggered = false;
  407. static void IRAM_ATTR gpio_isr_level_iram_handler(void *arg)
  408. {
  409. uint32_t gpio_num = (uint32_t) arg;
  410. isr_triggered = true;
  411. gpio_intr_disable(gpio_num);
  412. }
  413. static void IRAM_ATTR gpio_wait_intr_done_task(void *arg)
  414. {
  415. SemaphoreHandle_t sem = (SemaphoreHandle_t) arg;
  416. spi_flash_guard_get()->start(); // Disables flash cache
  417. // Since interrupt service is installed on core 0, we enable the gpio intr on core 0
  418. gpio_ll_intr_enable_on_core(&GPIO, 0, TEST_GPIO_INPUT_OUTPUT_IO1);
  419. // Wait until interrupt triggered
  420. while (!isr_triggered) {
  421. ;
  422. }
  423. spi_flash_guard_get()->end(); // Re-enables flash cache
  424. xSemaphoreGive(sem);
  425. vTaskSuspend(NULL);
  426. }
  427. TEST_CASE("GPIO_iram_interrupt_safe_test", "[gpio]")
  428. {
  429. SemaphoreHandle_t done_sem = xSemaphoreCreateBinary();
  430. TaskHandle_t task_handle;
  431. TEST_ASSERT_NOT_NULL(done_sem);
  432. test_gpio_config_mode_input_output(TEST_GPIO_INPUT_OUTPUT_IO1);
  433. TEST_ESP_OK(gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 0));
  434. TEST_ESP_OK(gpio_set_intr_type(TEST_GPIO_INPUT_OUTPUT_IO1, GPIO_INTR_HIGH_LEVEL));
  435. // We assume unit-test task is running on core 0, so interrupt service is installed on core 0
  436. TEST_ESP_OK(gpio_install_isr_service(ESP_INTR_FLAG_IRAM));
  437. TEST_ESP_OK(gpio_isr_handler_add(TEST_GPIO_INPUT_OUTPUT_IO1, gpio_isr_level_iram_handler, (void *) TEST_GPIO_INPUT_OUTPUT_IO1));
  438. // Disable intr and set pin level high, such that once the intr is re-enabled, it will trigger isr
  439. TEST_ESP_OK(gpio_intr_disable(TEST_GPIO_INPUT_OUTPUT_IO1));
  440. TEST_ESP_OK(gpio_set_level(TEST_GPIO_INPUT_OUTPUT_IO1, 1));
  441. xTaskCreate(gpio_wait_intr_done_task, "gpio_wait_intr_done_task", 2048, done_sem, 1, &task_handle);
  442. xSemaphoreTake(done_sem, portMAX_DELAY);
  443. gpio_isr_handler_remove(TEST_GPIO_INPUT_OUTPUT_IO1);
  444. gpio_uninstall_isr_service();
  445. vSemaphoreDelete(done_sem);
  446. unity_utils_task_delete(task_handle);
  447. }
  448. #endif
  449. #if TEST_GPIO_INTERNAL_ROUTING
  450. // Inter-connect input pin and output pin through an internal signal
  451. static void gpio_interconnect_input_output_pin(uint32_t input_pin, uint32_t output_pin, uint32_t signal_idx)
  452. {
  453. // signal256 -> output pin -> signal_idx -> input_pin
  454. // Set output pin IE to be able to connect to the signal
  455. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[output_pin]);
  456. esp_rom_gpio_connect_in_signal(output_pin, signal_idx, 0);
  457. // Input pin OE to be able to connect to the signal is done by the esp_rom_gpio_connect_out_signal function
  458. esp_rom_gpio_connect_out_signal(input_pin, signal_idx, 0, 0);
  459. }
  460. #endif
  461. TEST_CASE("GPIO_set_output_level_get_input_level_test", "[gpio]")
  462. {
  463. gpio_config_t output_io = test_init_io(TEST_GPIO_EXT_OUT_IO);
  464. gpio_config(&output_io);
  465. gpio_config_t input_io = test_init_io(TEST_GPIO_EXT_IN_IO);
  466. input_io.mode = GPIO_MODE_INPUT;
  467. gpio_config(&input_io);
  468. #if TEST_GPIO_INTERNAL_ROUTING
  469. gpio_interconnect_input_output_pin(TEST_GPIO_EXT_IN_IO, TEST_GPIO_EXT_OUT_IO, TEST_GPIO_SIGNAL_IDX);
  470. #endif
  471. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 0);
  472. vTaskDelay(100 / portTICK_PERIOD_MS);
  473. // tested voltage is around 0v
  474. TEST_ASSERT_EQUAL_INT_MESSAGE(0, gpio_get_level(TEST_GPIO_EXT_IN_IO), "get level error! the level should be low!");
  475. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 1);
  476. vTaskDelay(100 / portTICK_PERIOD_MS);
  477. // tested voltage is around 3.3v
  478. TEST_ASSERT_EQUAL_INT_MESSAGE(1, gpio_get_level(TEST_GPIO_EXT_IN_IO), "get level error! the level should be high!");
  479. }
  480. // This test routes constant-high/low signal to pins, another way is to directly connect TEST_GPIO_EXT_IN_IO to
  481. // 3.3v or GND pin
  482. TEST_CASE("GPIO_get_level_from_fixed_voltage_test", "[gpio]")
  483. {
  484. #if !TEST_GPIO_INTERNAL_ROUTING
  485. // If TEST_GPIO_EXT_OUT_IO is connected to TEST_GPIO_EXT_IN_IO, prevent being affected
  486. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_DISABLE);
  487. #endif
  488. gpio_config_t input_io = test_init_io(TEST_GPIO_EXT_IN_IO);
  489. input_io.mode = GPIO_MODE_INPUT;
  490. gpio_config(&input_io);
  491. esp_rom_gpio_connect_out_signal(TEST_GPIO_EXT_IN_IO, TEST_GPIO_SIGNAL_IDX, 0, 0);
  492. // Connect TEST_GPIO_EXT_IN_IO to a constant-high signal (to simulate connection to 3.3v)
  493. esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, TEST_GPIO_SIGNAL_IDX, 0);
  494. int level1 = gpio_get_level(TEST_GPIO_EXT_IN_IO);
  495. printf("TEST_GPIO_EXT_IN_IO(GPIO%d)'s level is: %d\n", TEST_GPIO_EXT_IN_IO, level1);
  496. TEST_ASSERT_EQUAL_INT_MESSAGE(1, level1, "get level error! the level should be high!");
  497. // Connect TEST_GPIO_EXT_IN_IO to a constant-low signal (to simulate connection to GND)
  498. esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, TEST_GPIO_SIGNAL_IDX, 0);
  499. int level2 = gpio_get_level(TEST_GPIO_EXT_IN_IO);
  500. printf("TEST_GPIO_EXT_IN_IO(GPIO%d)'s level is: %d\n", TEST_GPIO_EXT_IN_IO, level2);
  501. TEST_ASSERT_EQUAL_INT_MESSAGE(0, level2, "get level error! the level should be low!");
  502. }
  503. TEST_CASE("GPIO_io_pull_up/down_function", "[gpio]")
  504. {
  505. // First, ensure that the output IO will not affect the level
  506. gpio_config_t io_conf = test_init_io(TEST_GPIO_EXT_OUT_IO);
  507. gpio_config(&io_conf);
  508. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_INPUT);
  509. io_conf = test_init_io(TEST_GPIO_EXT_IN_IO);
  510. gpio_config(&io_conf);
  511. gpio_set_direction(TEST_GPIO_EXT_IN_IO, GPIO_MODE_INPUT);
  512. TEST_ESP_OK(gpio_pullup_en(TEST_GPIO_EXT_IN_IO)); // pull up first
  513. vTaskDelay(100 / portTICK_PERIOD_MS);
  514. TEST_ASSERT_EQUAL_INT_MESSAGE(1, gpio_get_level(TEST_GPIO_EXT_IN_IO), "gpio_pullup_en error, it can't pull up");
  515. TEST_ESP_OK(gpio_pulldown_dis(TEST_GPIO_EXT_IN_IO)); //can't be pull down
  516. vTaskDelay(100 / portTICK_PERIOD_MS);
  517. TEST_ASSERT_EQUAL_INT_MESSAGE(1, gpio_get_level(TEST_GPIO_EXT_IN_IO), "gpio_pulldown_dis error, it can pull down");
  518. TEST_ESP_OK(gpio_pulldown_en(TEST_GPIO_EXT_IN_IO)); // can be pull down now
  519. vTaskDelay(100 / portTICK_PERIOD_MS);
  520. TEST_ASSERT_EQUAL_INT_MESSAGE(0, gpio_get_level(TEST_GPIO_EXT_IN_IO), "gpio_pulldown_en error, it can't pull down");
  521. TEST_ESP_OK(gpio_pullup_dis(TEST_GPIO_EXT_IN_IO)); // can't be pull up
  522. vTaskDelay(100 / portTICK_PERIOD_MS);
  523. TEST_ASSERT_EQUAL_INT_MESSAGE(0, gpio_get_level(TEST_GPIO_EXT_IN_IO), "gpio_pullup_dis error, it can pull up");
  524. }
  525. // This test case tests whether gpio_set_level() outputs correctly with all gpio modes (gpio_mode_t)
  526. TEST_CASE("GPIO_mode_test", "[gpio]")
  527. {
  528. gpio_config_t output_io = test_init_io(TEST_GPIO_EXT_OUT_IO);
  529. gpio_config_t input_io = test_init_io(TEST_GPIO_EXT_IN_IO);
  530. gpio_config(&output_io);
  531. gpio_config(&input_io);
  532. int level = gpio_get_level(TEST_GPIO_EXT_IN_IO);
  533. // Disable mode
  534. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_DISABLE);
  535. gpio_set_direction(TEST_GPIO_EXT_IN_IO, GPIO_MODE_OUTPUT);
  536. #if TEST_GPIO_INTERNAL_ROUTING
  537. gpio_interconnect_input_output_pin(TEST_GPIO_EXT_IN_IO, TEST_GPIO_EXT_OUT_IO, TEST_GPIO_SIGNAL_IDX);
  538. #endif
  539. gpio_set_level(TEST_GPIO_EXT_OUT_IO, !level);
  540. TEST_ASSERT_EQUAL_INT_MESSAGE(level, gpio_get_level(TEST_GPIO_EXT_IN_IO), "direction GPIO_MODE_DISABLE set error, it can output");
  541. // Output mode
  542. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_OUTPUT);
  543. gpio_set_direction(TEST_GPIO_EXT_IN_IO, GPIO_MODE_INPUT);
  544. #if TEST_GPIO_INTERNAL_ROUTING
  545. gpio_interconnect_input_output_pin(TEST_GPIO_EXT_IN_IO, TEST_GPIO_EXT_OUT_IO, TEST_GPIO_SIGNAL_IDX);
  546. #endif
  547. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 1);
  548. TEST_ASSERT_EQUAL_INT_MESSAGE(1, gpio_get_level(TEST_GPIO_EXT_IN_IO), "direction GPIO_MODE_OUTPUT set error, it can't output");
  549. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 0);
  550. TEST_ASSERT_EQUAL_INT_MESSAGE(0, gpio_get_level(TEST_GPIO_EXT_IN_IO), "direction GPIO_MODE_OUTPUT set error, it can't output");
  551. // Open drain mode(output), can just output low level
  552. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_OUTPUT_OD);
  553. gpio_set_direction(TEST_GPIO_EXT_IN_IO, GPIO_MODE_INPUT);
  554. #if TEST_GPIO_INTERNAL_ROUTING
  555. gpio_interconnect_input_output_pin(TEST_GPIO_EXT_IN_IO, TEST_GPIO_EXT_OUT_IO, TEST_GPIO_SIGNAL_IDX);
  556. #endif
  557. // Outputs high level: w/ pull up, then must read high level; w/ pull down, then must read low level
  558. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 1);
  559. gpio_set_pull_mode(TEST_GPIO_EXT_OUT_IO, GPIO_PULLUP_ONLY);
  560. TEST_ASSERT_EQUAL_INT_MESSAGE(1, gpio_get_level(TEST_GPIO_EXT_IN_IO), "direction GPIO_MODE_OUTPUT_OD with GPIO_PULLUP_ONLY set error, it outputs low level");
  561. gpio_set_pull_mode(TEST_GPIO_EXT_OUT_IO, GPIO_PULLDOWN_ONLY);
  562. TEST_ASSERT_EQUAL_INT_MESSAGE(0, gpio_get_level(TEST_GPIO_EXT_IN_IO), "direction GPIO_MODE_OUTPUT_OD with GPIO_PULLDOWN_ONLY set error, it outputs high level");
  563. // Outputs low level: must read low level
  564. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 0);
  565. gpio_set_pull_mode(TEST_GPIO_EXT_OUT_IO, GPIO_FLOATING);
  566. TEST_ASSERT_EQUAL_INT_MESSAGE(0, gpio_get_level(TEST_GPIO_EXT_IN_IO), "direction GPIO_MODE_OUTPUT_OD set error, it outputs high level");
  567. // Open drain mode(output and input), can just output low level
  568. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_INPUT_OUTPUT_OD);
  569. gpio_set_direction(TEST_GPIO_EXT_IN_IO, GPIO_MODE_INPUT);
  570. #if TEST_GPIO_INTERNAL_ROUTING
  571. gpio_interconnect_input_output_pin(TEST_GPIO_EXT_IN_IO, TEST_GPIO_EXT_OUT_IO, TEST_GPIO_SIGNAL_IDX);
  572. #endif
  573. // Outputs high level: w/ pull up, then must read high level; w/ pull down, then must read low level
  574. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 1);
  575. gpio_set_pull_mode(TEST_GPIO_EXT_OUT_IO, GPIO_PULLUP_ONLY);
  576. TEST_ASSERT_EQUAL_INT_MESSAGE(1, gpio_get_level(TEST_GPIO_EXT_IN_IO), "direction GPIO_MODE_INPUT_OUTPUT_OD with GPIO_PULLUP_ONLY set error, it outputs low level");
  577. gpio_set_pull_mode(TEST_GPIO_EXT_OUT_IO, GPIO_PULLDOWN_ONLY);
  578. TEST_ASSERT_EQUAL_INT_MESSAGE(0, gpio_get_level(TEST_GPIO_EXT_IN_IO), "direction GPIO_MODE_INPUT_OUTPUT_OD with GPIO_PULLDOWN_ONLY set error, it outputs high level");
  579. // Outputs low level: must read low level
  580. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 0);
  581. gpio_set_pull_mode(TEST_GPIO_EXT_OUT_IO, GPIO_FLOATING);
  582. TEST_ASSERT_EQUAL_INT_MESSAGE(0, gpio_get_level(TEST_GPIO_EXT_IN_IO), "direction GPIO_MODE_INPUT_OUTPUT_OD set error, it outputs high level");
  583. // GPIO_MODE_INPUT_OUTPUT mode
  584. level = gpio_get_level(TEST_GPIO_EXT_IN_IO);
  585. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_INPUT_OUTPUT);
  586. gpio_set_direction(TEST_GPIO_EXT_IN_IO, GPIO_MODE_INPUT);
  587. #if TEST_GPIO_INTERNAL_ROUTING
  588. gpio_interconnect_input_output_pin(TEST_GPIO_EXT_IN_IO, TEST_GPIO_EXT_OUT_IO, TEST_GPIO_SIGNAL_IDX);
  589. #endif
  590. gpio_set_level(TEST_GPIO_EXT_OUT_IO, !level);
  591. TEST_ASSERT_EQUAL_INT_MESSAGE(!level, gpio_get_level(TEST_GPIO_EXT_IN_IO), "direction GPIO_MODE_INPUT_OUTPUT set error, it gives incorrect output");
  592. }
  593. static void prompt_to_continue(const char *str)
  594. {
  595. printf("%s , please press \"Enter\" to go on!\n", str);
  596. char sign[5] = {0};
  597. while (strlen(sign) == 0) {
  598. /* Flush anything already in the RX buffer */
  599. while (esp_rom_uart_rx_one_char((uint8_t *) sign) == 0) {
  600. }
  601. /* Read line */
  602. esp_rom_uart_rx_string((uint8_t *) sign, sizeof(sign) - 1);
  603. }
  604. }
  605. // This case needs the resistance to pull up the voltage or pull down the voltage
  606. // Ignored in CI because the voltage needs to be tested with multimeter
  607. TEST_CASE_CI_IGNORE("GPIO_verify_only_the_gpio_with_input_ability_can_be_set_pull/down", "[gpio]")
  608. {
  609. gpio_config_t output_io = test_init_io(TEST_GPIO_EXT_OUT_IO);
  610. gpio_config_t input_io = test_init_io(TEST_GPIO_EXT_IN_IO);
  611. gpio_config(&output_io);
  612. input_io.mode = GPIO_MODE_INPUT;
  613. gpio_config(&input_io);
  614. printf("pull up test!\n");
  615. // pull up test
  616. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_OUTPUT);
  617. TEST_ESP_OK(gpio_set_pull_mode(TEST_GPIO_EXT_OUT_IO, GPIO_PULLUP_ONLY));
  618. prompt_to_continue("mode: GPIO_MODE_OUTPUT");
  619. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_OUTPUT_OD);
  620. TEST_ESP_OK(gpio_set_pull_mode(TEST_GPIO_EXT_OUT_IO, GPIO_PULLUP_ONLY));
  621. // open drain just can output low level
  622. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_INPUT_OUTPUT_OD);
  623. TEST_ESP_OK(gpio_set_pull_mode(TEST_GPIO_EXT_OUT_IO, GPIO_PULLUP_ONLY));
  624. prompt_to_continue("mode: GPIO_MODE_OUTPUT_OD");
  625. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_INPUT_OUTPUT);
  626. TEST_ESP_OK(gpio_set_pull_mode(TEST_GPIO_EXT_OUT_IO, GPIO_PULLUP_ONLY));
  627. prompt_to_continue("mode: GPIO_MODE_INPUT_OUTPUT");
  628. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_INPUT);
  629. TEST_ESP_OK(gpio_set_pull_mode(TEST_GPIO_EXT_OUT_IO, GPIO_PULLUP_ONLY));
  630. prompt_to_continue("mode: GPIO_MODE_INPUT");
  631. // after pull up the level is high now
  632. // pull down test
  633. printf("pull down test!\n");
  634. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_OUTPUT);
  635. TEST_ESP_OK(gpio_set_pull_mode(TEST_GPIO_EXT_OUT_IO, GPIO_PULLDOWN_ONLY));
  636. prompt_to_continue("mode: GPIO_MODE_OUTPUT");
  637. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_OUTPUT_OD);
  638. TEST_ESP_OK(gpio_set_pull_mode(TEST_GPIO_EXT_OUT_IO, GPIO_PULLDOWN_ONLY));
  639. prompt_to_continue("mode: GPIO_MODE_OUTPUT_OD");
  640. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_INPUT_OUTPUT_OD);
  641. TEST_ESP_OK(gpio_set_pull_mode(TEST_GPIO_EXT_OUT_IO, GPIO_PULLDOWN_ONLY));
  642. prompt_to_continue("mode: GPIO_MODE_INPUT_OUTPUT_OD");
  643. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_INPUT_OUTPUT);
  644. TEST_ESP_OK(gpio_set_pull_mode(TEST_GPIO_EXT_OUT_IO, GPIO_PULLDOWN_ONLY));
  645. prompt_to_continue("mode: GPIO_MODE_INPUT_OUTPUT");
  646. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_INPUT);
  647. TEST_ESP_OK(gpio_set_pull_mode(TEST_GPIO_EXT_OUT_IO, GPIO_PULLDOWN_ONLY));
  648. prompt_to_continue("mode: GPIO_MODE_INPUT");
  649. }
  650. static void drive_capability_set_get(gpio_num_t num, gpio_drive_cap_t capability)
  651. {
  652. gpio_config_t pad_io = test_init_io(num);
  653. TEST_ESP_OK(gpio_config(&pad_io));
  654. TEST_ASSERT(gpio_set_drive_capability(num, GPIO_DRIVE_CAP_MAX) == ESP_ERR_INVALID_ARG);
  655. gpio_drive_cap_t cap;
  656. TEST_ESP_OK(gpio_set_drive_capability(num, capability));
  657. TEST_ESP_OK(gpio_get_drive_capability(num, &cap));
  658. TEST_ASSERT_EQUAL_INT(capability, cap);
  659. }
  660. /**
  661. * There are 5 situation for the GPIO drive capability:
  662. * 1. GPIO drive weak capability test
  663. * 2. GPIO drive stronger capability test
  664. * 3. GPIO drive default capability test
  665. * 4. GPIO drive default capability test2
  666. * 5. GPIO drive strongest capability test
  667. *
  668. * How to test:
  669. * when testing, use the sliding resistor and a multimeter
  670. * adjust the resistor from low to high, 0-10k
  671. * watch the current change
  672. * the current test result:
  673. * weak capability: (0.32-10.1)mA
  674. * stronger capability: (0.32-20.0)mA
  675. * default capability: (0.33-39.8)mA
  676. * default capability2: (0.33-39.9)mA
  677. * strongest capability: (0.33-64.2)mA
  678. *
  679. * the data shows:
  680. * weak capability < stronger capability < default capability = default capability2 < strongest capability
  681. *
  682. * all of these cases should be ignored that it will not run in CI
  683. */
  684. TEST_CASE_CI_IGNORE("GPIO_drive_capability_test", "[gpio]")
  685. {
  686. printf("weak capability test! please view the current change!\n");
  687. drive_capability_set_get(TEST_GPIO_EXT_OUT_IO, GPIO_DRIVE_CAP_0);
  688. prompt_to_continue("If this test finishes");
  689. printf("stronger capability test! please view the current change!\n");
  690. drive_capability_set_get(TEST_GPIO_EXT_OUT_IO, GPIO_DRIVE_CAP_1);
  691. prompt_to_continue("If this test finishes");
  692. printf("default capability test! please view the current change!\n");
  693. drive_capability_set_get(TEST_GPIO_EXT_OUT_IO, GPIO_DRIVE_CAP_2);
  694. prompt_to_continue("If this test finishes");
  695. printf("default capability2 test! please view the current change!\n");
  696. drive_capability_set_get(TEST_GPIO_EXT_OUT_IO, GPIO_DRIVE_CAP_DEFAULT);
  697. prompt_to_continue("If this test finishes");
  698. printf("strongest capability test! please view the current change!\n");
  699. drive_capability_set_get(TEST_GPIO_EXT_OUT_IO, GPIO_DRIVE_CAP_3);
  700. prompt_to_continue("If this test finishes");
  701. }
  702. #if SOC_USB_SERIAL_JTAG_SUPPORTED
  703. TEST_CASE("GPIO_input_and_output_of_USB_pins_test", "[gpio]")
  704. {
  705. const int test_pins[] = {USB_DM_GPIO_NUM, USB_DM_GPIO_NUM};
  706. gpio_config_t io_conf = {
  707. .intr_type = GPIO_INTR_DISABLE,
  708. .mode = GPIO_MODE_INPUT_OUTPUT,
  709. .pin_bit_mask = (BIT64(test_pins[0]) | BIT64(test_pins[1])),
  710. .pull_down_en = 0,
  711. .pull_up_en = 0,
  712. };
  713. gpio_config(&io_conf);
  714. for (int i = 0; i < sizeof(test_pins) / sizeof(int); i++) {
  715. int pin = test_pins[i];
  716. // test pin
  717. gpio_set_level(pin, 0);
  718. // tested voltage is around 0v
  719. esp_rom_delay_us(10);
  720. TEST_ASSERT_EQUAL_INT_MESSAGE(0, gpio_get_level(pin), "get level error! the level should be low!");
  721. gpio_set_level(pin, 1);
  722. esp_rom_delay_us(10);
  723. // tested voltage is around 3.3v
  724. TEST_ASSERT_EQUAL_INT_MESSAGE(1, gpio_get_level(pin), "get level error! the level should be high!");
  725. gpio_set_level(pin, 0);
  726. esp_rom_delay_us(10);
  727. // tested voltage is around 0v
  728. TEST_ASSERT_EQUAL_INT_MESSAGE(0, gpio_get_level(pin), "get level error! the level should be low!");
  729. gpio_set_level(pin, 1);
  730. esp_rom_delay_us(10);
  731. // tested voltage is around 3.3v
  732. TEST_ASSERT_EQUAL_INT_MESSAGE(1, gpio_get_level(pin), "get level error! the level should be high!");
  733. }
  734. }
  735. #endif //SOC_USB_SERIAL_JTAG_SUPPORTED
  736. // Ignored in CI because it needs manually connect TEST_GPIO_INPUT_LEVEL_LOW_PIN to 3.3v to wake up from light sleep
  737. TEST_CASE_CI_IGNORE("GPIO_light_sleep_wake_up_test", "[gpio]")
  738. {
  739. gpio_config_t io_config = test_init_io(TEST_GPIO_INPUT_LEVEL_LOW_PIN);
  740. io_config.mode = GPIO_MODE_INPUT;
  741. io_config.pull_down_en = 1;
  742. gpio_config(&io_config);
  743. TEST_ESP_OK(gpio_wakeup_enable(TEST_GPIO_INPUT_LEVEL_LOW_PIN, GPIO_INTR_HIGH_LEVEL));
  744. TEST_ESP_OK(esp_sleep_enable_gpio_wakeup());
  745. printf("Entering light sleep... Please connect GPIO%d to 3.3v to wake up...\n", TEST_GPIO_INPUT_LEVEL_LOW_PIN);
  746. // Wait for the complete line to be printed before entering sleep
  747. vTaskDelay(1000 / portTICK_PERIOD_MS);
  748. esp_light_sleep_start();
  749. printf("Waked up from light sleep\n");
  750. TEST_ASSERT(esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_GPIO);
  751. }