test_gpio.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792
  1. /**
  2. * About test environment UT_T1_GPIO:
  3. * Please connect GPIO18 and GPIO19
  4. */
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include "esp_system.h"
  8. #include "esp_sleep.h"
  9. #include "unity.h"
  10. #include "driver/gpio.h"
  11. #include "freertos/FreeRTOS.h"
  12. #include "freertos/task.h"
  13. #include "freertos/queue.h"
  14. #include "sdkconfig.h"
  15. #include "esp_rom_uart.h"
  16. #include "esp_rom_sys.h"
  17. #define WAKE_UP_IGNORE 1 // gpio_wakeup function development is not completed yet, set it deprecated.
  18. #if CONFIG_IDF_TARGET_ESP32
  19. #define TEST_GPIO_EXT_OUT_IO 18 // default output GPIO
  20. #define TEST_GPIO_EXT_IN_IO 19 // default input GPIO
  21. #define TEST_GPIO_OUTPUT_PIN 23
  22. #define TEST_GPIO_INPUT_ONLY_PIN 34
  23. #define TEST_GPIO_OUTPUT_MAX GPIO_NUM_34
  24. #elif CONFIG_IDF_TARGET_ESP32S2
  25. // ESP32_S2 DEVKIC uses IO19 and IO20 as USB functions, so it is necessary to avoid using IO19, otherwise GPIO io pull up/down function cannot pass
  26. // Also the first version of ESP32-S2-Saola has pullup issue on GPIO18, which is tied to 3V3 on the
  27. // runner. Also avoid using GPIO18.
  28. #define TEST_GPIO_EXT_OUT_IO 17 // default output GPIO
  29. #define TEST_GPIO_EXT_IN_IO 21 // default input GPIO
  30. #define TEST_GPIO_OUTPUT_PIN 12
  31. #define TEST_GPIO_INPUT_ONLY_PIN 46
  32. #define TEST_GPIO_OUTPUT_MAX GPIO_NUM_46
  33. #elif CONFIG_IDF_TARGET_ESP32S3
  34. #define TEST_GPIO_EXT_OUT_IO 19 // default output GPIO
  35. #define TEST_GPIO_EXT_IN_IO 20 // default input GPIO
  36. #define TEST_GPIO_OUTPUT_PIN 12
  37. #define TEST_GPIO_INPUT_ONLY_PIN 46
  38. #define TEST_GPIO_OUTPUT_MAX GPIO_NUM_47
  39. #elif CONFIG_IDF_TARGET_ESP32C3
  40. #define TEST_GPIO_EXT_OUT_IO 2 // default output GPIO
  41. #define TEST_GPIO_EXT_IN_IO 3 // default input GPIO
  42. #define TEST_GPIO_OUTPUT_PIN 1
  43. #define TEST_GPIO_OUTPUT_MAX GPIO_NUM_21
  44. #endif
  45. // define public test io on all boards(esp32, esp32s2, esp32s3, esp32c3)
  46. #define TEST_IO_9 GPIO_NUM_9
  47. #define TEST_IO_10 GPIO_NUM_10
  48. static volatile int disable_intr_times = 0; // use this to calculate how many times it go into interrupt
  49. static volatile int level_intr_times = 0; // use this to get how many times the level interrupt happened
  50. static volatile int edge_intr_times = 0; // use this to get how many times the edge interrupt happened
  51. #if !WAKE_UP_IGNORE
  52. static bool wake_up_result = false; // use this to judge the wake up event happen or not
  53. #endif
  54. /**
  55. * do some initialization operation in this function
  56. * @param num: it is the destination GPIO wanted to be initialized
  57. *
  58. */
  59. static gpio_config_t init_io(gpio_num_t num)
  60. {
  61. TEST_ASSERT(num < TEST_GPIO_OUTPUT_MAX);
  62. gpio_config_t io_conf;
  63. io_conf.intr_type = GPIO_INTR_DISABLE;
  64. io_conf.mode = GPIO_MODE_OUTPUT;
  65. io_conf.pin_bit_mask = (1ULL << num);
  66. io_conf.pull_down_en = 0;
  67. io_conf.pull_up_en = 0;
  68. return io_conf;
  69. }
  70. #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3, ESP32C3)
  71. //No runners
  72. // edge interrupt event
  73. static void gpio_isr_edge_handler(void* arg)
  74. {
  75. uint32_t gpio_num = (uint32_t) arg;
  76. esp_rom_printf("GPIO[%d] intr, val: %d\n", gpio_num, gpio_get_level(gpio_num));
  77. edge_intr_times++;
  78. }
  79. // level interrupt event with "gpio_intr_disable"
  80. static void gpio_isr_level_handler(void* arg)
  81. {
  82. uint32_t gpio_num = (uint32_t) arg;
  83. disable_intr_times++;
  84. esp_rom_printf("GPIO[%d] intr, val: %d, disable_intr_times = %d\n", gpio_num, gpio_get_level(gpio_num), disable_intr_times);
  85. gpio_intr_disable(gpio_num);
  86. }
  87. // level interrupt event
  88. static void gpio_isr_level_handler2(void* arg)
  89. {
  90. uint32_t gpio_num = (uint32_t) arg;
  91. level_intr_times++;
  92. esp_rom_printf("GPIO[%d] intr, val: %d\n", gpio_num, gpio_get_level(gpio_num));
  93. if(gpio_get_level(gpio_num)) {
  94. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 0);
  95. }else{
  96. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 1);
  97. }
  98. esp_rom_printf("GPIO[%d] intr, val: %d, level_intr_times = %d\n", TEST_GPIO_EXT_OUT_IO, gpio_get_level(TEST_GPIO_EXT_OUT_IO), level_intr_times);
  99. esp_rom_printf("GPIO[%d] intr, val: %d, level_intr_times = %d\n", gpio_num, gpio_get_level(gpio_num), level_intr_times);
  100. }
  101. #endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3, ESP32C3)
  102. #if !WAKE_UP_IGNORE
  103. // get result of waking up or not
  104. static void sleep_wake_up(void *arg)
  105. {
  106. gpio_config_t io_config = init_io(TEST_GPIO_EXT_IN_IO);
  107. io_config.mode = GPIO_MODE_INPUT;
  108. gpio_config(&io_config);
  109. TEST_ESP_OK(gpio_wakeup_enable(TEST_GPIO_EXT_IN_IO, GPIO_INTR_HIGH_LEVEL));
  110. esp_light_sleep_start();
  111. wake_up_result = true;
  112. }
  113. // wake up light sleep event
  114. static void trigger_wake_up(void *arg)
  115. {
  116. gpio_config_t io_config = init_io(TEST_GPIO_EXT_OUT_IO);
  117. gpio_config(&io_config);
  118. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 0);
  119. gpio_install_isr_service(0);
  120. gpio_isr_handler_add(TEST_GPIO_EXT_OUT_IO, gpio_isr_level_handler, (void*) TEST_GPIO_EXT_IN_IO);
  121. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 1);
  122. vTaskDelay(100 / portTICK_RATE_MS);
  123. }
  124. #endif //!WAKE_UP_IGNORE
  125. static void prompt_to_continue(const char* str)
  126. {
  127. printf("%s , please press \"Enter\" to go on!\n", str);
  128. char sign[5] = {0};
  129. while(strlen(sign) == 0) {
  130. /* Flush anything already in the RX buffer */
  131. while(esp_rom_uart_rx_one_char((uint8_t *) sign) == ETS_OK) {
  132. }
  133. /* Read line */
  134. esp_rom_uart_rx_string((uint8_t*) sign, sizeof(sign) - 1);
  135. }
  136. }
  137. static void drive_capability_set_get(gpio_num_t num, gpio_drive_cap_t capability)
  138. {
  139. gpio_config_t pad_io = init_io(num);
  140. TEST_ESP_OK(gpio_config(&pad_io));
  141. TEST_ASSERT(gpio_set_drive_capability(num, GPIO_DRIVE_CAP_MAX) == ESP_ERR_INVALID_ARG);
  142. gpio_drive_cap_t cap;
  143. TEST_ESP_OK(gpio_set_drive_capability(num, capability));
  144. TEST_ESP_OK(gpio_get_drive_capability(num, &cap));
  145. TEST_ASSERT_EQUAL_INT(cap, capability);
  146. }
  147. // test the basic configuration function with right parameters and error parameters
  148. TEST_CASE("GPIO config parameters test", "[gpio]")
  149. {
  150. //error param test
  151. //ESP32 test 41 bit, ESP32-S2 test 48 bit
  152. gpio_config_t io_config = { 0 };
  153. io_config.intr_type = GPIO_INTR_DISABLE;
  154. io_config.pin_bit_mask = ((uint64_t)1<<(GPIO_NUM_MAX+1));
  155. TEST_ASSERT(gpio_config(&io_config) == ESP_ERR_INVALID_ARG);
  156. // test 0
  157. io_config.pin_bit_mask = 0;
  158. TEST_ASSERT(gpio_config(&io_config) == ESP_ERR_INVALID_ARG);
  159. //ESP32 test 40 bit, ESP32-S2 test 47 bit
  160. io_config.pin_bit_mask = ((uint64_t)1<<GPIO_NUM_MAX);
  161. TEST_ASSERT(gpio_config(&io_config) == ESP_ERR_INVALID_ARG);
  162. io_config.pin_bit_mask = ((uint64_t)1<<TEST_GPIO_OUTPUT_PIN);
  163. TEST_ESP_OK(gpio_config(&io_config));
  164. //This IO is just used for input, C3 doesn't have input only pin.
  165. #if !CONFIG_IDF_TARGET_ESP32C3
  166. io_config.pin_bit_mask = ((uint64_t)1 << TEST_GPIO_INPUT_ONLY_PIN);
  167. io_config.mode = GPIO_MODE_INPUT;
  168. TEST_ESP_OK(gpio_config(&io_config));
  169. io_config.mode = GPIO_MODE_OUTPUT;
  170. // The pin is input only, once set as output should log something
  171. TEST_ASSERT(gpio_config(&io_config) == ESP_ERR_INVALID_ARG);
  172. #endif //!CONFIG_IDF_TARGET_ESP32C3
  173. }
  174. #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3, ESP32C3)
  175. //No runners
  176. TEST_CASE("GPIO rising edge interrupt test", "[gpio][test_env=UT_T1_GPIO]")
  177. {
  178. edge_intr_times = 0; // set it as 0 prepare to test
  179. //init input and output gpio
  180. gpio_config_t output_io = init_io(TEST_GPIO_EXT_OUT_IO);
  181. gpio_config_t input_io = init_io(TEST_GPIO_EXT_IN_IO);
  182. input_io.intr_type = GPIO_INTR_POSEDGE;
  183. input_io.mode = GPIO_MODE_INPUT;
  184. input_io.pull_up_en = 1;
  185. TEST_ESP_OK(gpio_config(&output_io));
  186. TEST_ESP_OK(gpio_config(&input_io));
  187. TEST_ESP_OK(gpio_set_level(TEST_GPIO_EXT_OUT_IO, 0));
  188. //rising edge intr
  189. TEST_ESP_OK(gpio_set_intr_type(TEST_GPIO_EXT_IN_IO, GPIO_INTR_POSEDGE));
  190. TEST_ESP_OK(gpio_install_isr_service(0));
  191. gpio_isr_handler_add(TEST_GPIO_EXT_IN_IO, gpio_isr_edge_handler, (void*)TEST_GPIO_EXT_IN_IO);
  192. TEST_ESP_OK(gpio_set_level(TEST_GPIO_EXT_OUT_IO, 1));
  193. TEST_ASSERT_EQUAL_INT(edge_intr_times, 1);
  194. vTaskDelay(100 / portTICK_RATE_MS);
  195. gpio_isr_handler_remove(TEST_GPIO_EXT_IN_IO);
  196. gpio_uninstall_isr_service();
  197. }
  198. TEST_CASE("GPIO falling edge interrupt test", "[gpio][test_env=UT_T1_GPIO]")
  199. {
  200. edge_intr_times = 0;
  201. gpio_config_t output_io = init_io(TEST_GPIO_EXT_OUT_IO);
  202. gpio_config_t input_io = init_io(TEST_GPIO_EXT_IN_IO);
  203. input_io.intr_type = GPIO_INTR_POSEDGE;
  204. input_io.mode = GPIO_MODE_INPUT;
  205. input_io.pull_up_en = 1;
  206. TEST_ESP_OK(gpio_config(&output_io));
  207. TEST_ESP_OK(gpio_config(&input_io));
  208. TEST_ESP_OK(gpio_set_level(TEST_GPIO_EXT_OUT_IO, 1));
  209. gpio_set_intr_type(TEST_GPIO_EXT_IN_IO, GPIO_INTR_NEGEDGE);
  210. gpio_install_isr_service(0);
  211. gpio_isr_handler_add(TEST_GPIO_EXT_IN_IO, gpio_isr_edge_handler, (void*) TEST_GPIO_EXT_IN_IO);
  212. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 0);
  213. vTaskDelay(100 / portTICK_RATE_MS);
  214. TEST_ASSERT_EQUAL_INT(edge_intr_times, 1);
  215. vTaskDelay(100 / portTICK_RATE_MS);
  216. gpio_isr_handler_remove(TEST_GPIO_EXT_IN_IO);
  217. gpio_uninstall_isr_service();
  218. }
  219. TEST_CASE("GPIO both rising and falling edge interrupt test", "[gpio][test_env=UT_T1_GPIO]")
  220. {
  221. edge_intr_times = 0;
  222. gpio_config_t output_io = init_io(TEST_GPIO_EXT_OUT_IO);
  223. gpio_config_t input_io = init_io(TEST_GPIO_EXT_IN_IO);
  224. input_io.intr_type = GPIO_INTR_POSEDGE;
  225. input_io.mode = GPIO_MODE_INPUT;
  226. input_io.pull_up_en = 1;
  227. TEST_ESP_OK(gpio_config(&output_io));
  228. TEST_ESP_OK(gpio_config(&input_io));
  229. TEST_ESP_OK(gpio_set_level(TEST_GPIO_EXT_OUT_IO, 0));
  230. int level = 0;
  231. gpio_set_intr_type(TEST_GPIO_EXT_IN_IO, GPIO_INTR_ANYEDGE);
  232. gpio_install_isr_service(0);
  233. gpio_isr_handler_add(TEST_GPIO_EXT_IN_IO, gpio_isr_edge_handler, (void*) TEST_GPIO_EXT_IN_IO);
  234. // for rising edge in GPIO_INTR_ANYEDGE
  235. while(1) {
  236. level = level + 1;
  237. gpio_set_level(TEST_GPIO_EXT_OUT_IO, level*0.2);
  238. if(level > 10) {
  239. break;
  240. }
  241. vTaskDelay(100 / portTICK_RATE_MS);
  242. }
  243. vTaskDelay(100 / portTICK_RATE_MS);
  244. // for falling rdge in GPIO_INTR_ANYEDGE
  245. while(1) {
  246. level = level - 1;
  247. gpio_set_level(TEST_GPIO_EXT_OUT_IO, level/5);
  248. if(level < 0) {
  249. break;
  250. }
  251. vTaskDelay(100 / portTICK_RATE_MS);
  252. }
  253. vTaskDelay(100 / portTICK_RATE_MS);
  254. TEST_ASSERT_EQUAL_INT(edge_intr_times, 2);
  255. vTaskDelay(100 / portTICK_RATE_MS);
  256. gpio_isr_handler_remove(TEST_GPIO_EXT_IN_IO);
  257. gpio_uninstall_isr_service();
  258. }
  259. TEST_CASE("GPIO input high level trigger, cut the interrupt source exit interrupt test", "[gpio][test_env=UT_T1_GPIO]")
  260. {
  261. level_intr_times=0;
  262. gpio_config_t output_io = init_io(TEST_GPIO_EXT_OUT_IO);
  263. gpio_config_t input_io = init_io(TEST_GPIO_EXT_IN_IO);
  264. input_io.intr_type = GPIO_INTR_POSEDGE;
  265. input_io.mode = GPIO_MODE_INPUT;
  266. input_io.pull_up_en = 1;
  267. TEST_ESP_OK(gpio_config(&output_io));
  268. TEST_ESP_OK(gpio_config(&input_io));
  269. TEST_ESP_OK(gpio_set_level(TEST_GPIO_EXT_OUT_IO, 0));
  270. gpio_set_intr_type(TEST_GPIO_EXT_IN_IO, GPIO_INTR_HIGH_LEVEL);
  271. gpio_install_isr_service(0);
  272. gpio_isr_handler_add(TEST_GPIO_EXT_IN_IO, gpio_isr_level_handler2, (void*) TEST_GPIO_EXT_IN_IO);
  273. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 1);
  274. vTaskDelay(100 / portTICK_RATE_MS);
  275. TEST_ASSERT_EQUAL_INT_MESSAGE(level_intr_times, 1, "go into high-level interrupt more than once with cur interrupt source way");
  276. gpio_isr_handler_remove(TEST_GPIO_EXT_IN_IO);
  277. gpio_uninstall_isr_service();
  278. }
  279. TEST_CASE("GPIO low level interrupt test", "[gpio][test_env=UT_T1_GPIO]")
  280. {
  281. disable_intr_times=0;
  282. gpio_config_t output_io = init_io(TEST_GPIO_EXT_OUT_IO);
  283. gpio_config_t input_io = init_io(TEST_GPIO_EXT_IN_IO);
  284. input_io.intr_type = GPIO_INTR_POSEDGE;
  285. input_io.mode = GPIO_MODE_INPUT;
  286. input_io.pull_up_en = 1;
  287. TEST_ESP_OK(gpio_config(&output_io));
  288. TEST_ESP_OK(gpio_config(&input_io));
  289. TEST_ESP_OK(gpio_set_level(TEST_GPIO_EXT_OUT_IO, 1));
  290. gpio_set_intr_type(TEST_GPIO_EXT_IN_IO, GPIO_INTR_LOW_LEVEL);
  291. gpio_install_isr_service(0);
  292. gpio_isr_handler_add(TEST_GPIO_EXT_IN_IO, gpio_isr_level_handler, (void*) TEST_GPIO_EXT_IN_IO);
  293. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 0);
  294. printf("get level:%d\n",gpio_get_level(TEST_GPIO_EXT_IN_IO));
  295. vTaskDelay(100 / portTICK_RATE_MS);
  296. TEST_ASSERT_EQUAL_INT_MESSAGE(disable_intr_times, 1, "go into low-level interrupt more than once with disable way");
  297. gpio_isr_handler_remove(TEST_GPIO_EXT_IN_IO);
  298. gpio_uninstall_isr_service();
  299. }
  300. TEST_CASE("GPIO multi-level interrupt test, to cut the interrupt source exit interrupt ", "[gpio][test_env=UT_T1_GPIO]")
  301. {
  302. level_intr_times=0;
  303. gpio_config_t output_io = init_io(TEST_GPIO_EXT_OUT_IO);
  304. gpio_config_t input_io = init_io(TEST_GPIO_EXT_IN_IO);
  305. input_io.intr_type = GPIO_INTR_POSEDGE;
  306. input_io.mode = GPIO_MODE_INPUT;
  307. input_io.pull_up_en = 1;
  308. TEST_ESP_OK(gpio_config(&output_io));
  309. TEST_ESP_OK(gpio_config(&input_io));
  310. TEST_ESP_OK(gpio_set_level(TEST_GPIO_EXT_OUT_IO, 0));
  311. gpio_set_intr_type(TEST_GPIO_EXT_IN_IO, GPIO_INTR_HIGH_LEVEL);
  312. gpio_install_isr_service(0);
  313. gpio_isr_handler_add(TEST_GPIO_EXT_IN_IO, gpio_isr_level_handler2, (void*) TEST_GPIO_EXT_IN_IO);
  314. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 1);
  315. vTaskDelay(100 / portTICK_RATE_MS);
  316. TEST_ASSERT_EQUAL_INT_MESSAGE(level_intr_times, 1, "go into high-level interrupt more than once with cur interrupt source way");
  317. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 1);
  318. vTaskDelay(200 / portTICK_RATE_MS);
  319. TEST_ASSERT_EQUAL_INT_MESSAGE(level_intr_times, 2, "go into high-level interrupt more than once with cur interrupt source way");
  320. gpio_isr_handler_remove(TEST_GPIO_EXT_IN_IO);
  321. gpio_uninstall_isr_service();
  322. }
  323. TEST_CASE("GPIO enable and disable interrupt test", "[gpio][test_env=UT_T1_GPIO]")
  324. {
  325. disable_intr_times = 0;
  326. gpio_config_t output_io = init_io(TEST_GPIO_EXT_OUT_IO);
  327. gpio_config_t input_io = init_io(TEST_GPIO_EXT_IN_IO);
  328. input_io.intr_type = GPIO_INTR_POSEDGE;
  329. input_io.mode = GPIO_MODE_INPUT;
  330. input_io.pull_up_en = 1;
  331. TEST_ESP_OK(gpio_config(&output_io));
  332. TEST_ESP_OK(gpio_config(&input_io));
  333. TEST_ESP_OK(gpio_set_level(TEST_GPIO_EXT_OUT_IO, 0)); // Because of GPIO_INTR_HIGH_LEVEL interrupt, 0 must be set first
  334. TEST_ESP_OK(gpio_set_intr_type(TEST_GPIO_EXT_IN_IO, GPIO_INTR_HIGH_LEVEL));
  335. TEST_ESP_OK(gpio_install_isr_service(0));
  336. TEST_ESP_OK(gpio_isr_handler_add(TEST_GPIO_EXT_IN_IO, gpio_isr_level_handler, (void*) TEST_GPIO_EXT_IN_IO));
  337. TEST_ESP_OK(gpio_set_level(TEST_GPIO_EXT_OUT_IO, 1));
  338. TEST_ESP_OK(gpio_isr_handler_remove(TEST_GPIO_EXT_IN_IO));
  339. TEST_ESP_OK(gpio_set_level(TEST_GPIO_EXT_OUT_IO, 0));
  340. TEST_ASSERT_EQUAL_INT_MESSAGE(disable_intr_times, 1, "go into high-level interrupt more than once with disable way");
  341. // not install service now
  342. vTaskDelay(100 / portTICK_RATE_MS);
  343. TEST_ESP_OK(gpio_intr_disable(TEST_GPIO_EXT_IN_IO));
  344. TEST_ESP_OK(gpio_set_level(TEST_GPIO_EXT_OUT_IO, 1));
  345. TEST_ASSERT_EQUAL_INT_MESSAGE(disable_intr_times, 1, "disable interrupt does not work, still go into interrupt!");
  346. gpio_uninstall_isr_service(); //uninstall the service
  347. TEST_ASSERT(gpio_isr_handler_add(TEST_GPIO_EXT_IN_IO, gpio_isr_level_handler, (void*) TEST_GPIO_EXT_IN_IO) == ESP_ERR_INVALID_STATE);
  348. TEST_ASSERT(gpio_isr_handler_remove(TEST_GPIO_EXT_IN_IO) == ESP_ERR_INVALID_STATE);
  349. }
  350. #endif //DISABLED_FOR_TARGETS(ESP32S2, ESP32S3, ESP32C3)
  351. // ESP32 Connect GPIO18 with GPIO19, ESP32-S2 Connect GPIO17 with GPIO21,
  352. // ESP32-S3 Connect GPIO19 with GPIO20, ESP32C3 Connect GPIO2 with GPIO3
  353. // use multimeter to test the voltage, so it is ignored in CI
  354. TEST_CASE("GPIO set gpio output level test", "[gpio][ignore]")
  355. {
  356. gpio_config_t io_conf;
  357. io_conf.intr_type = GPIO_INTR_DISABLE;
  358. io_conf.mode = GPIO_MODE_OUTPUT;
  359. io_conf.pin_bit_mask = (1<<TEST_GPIO_EXT_OUT_IO);
  360. io_conf.pull_down_en = 0;
  361. io_conf.pull_up_en = 0;
  362. gpio_config(&io_conf);
  363. io_conf.pin_bit_mask = (1<<TEST_GPIO_EXT_IN_IO);
  364. io_conf.mode = GPIO_MODE_INPUT;
  365. gpio_config(&io_conf);
  366. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 0);
  367. // tested voltage is around 0v
  368. TEST_ASSERT_EQUAL_INT_MESSAGE(gpio_get_level(TEST_GPIO_EXT_IN_IO), 0, "get level error! the level should be low!");
  369. vTaskDelay(1000 / portTICK_RATE_MS);
  370. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 1);
  371. // tested voltage is around 3.3v
  372. TEST_ASSERT_EQUAL_INT_MESSAGE(gpio_get_level(TEST_GPIO_EXT_IN_IO), 1, "get level error! the level should be high!");
  373. //This IO is just used for input, C3 doesn't have input only pin.
  374. #if !CONFIG_IDF_TARGET_ESP32C3
  375. io_conf.pin_bit_mask = ((uint64_t)1<<TEST_GPIO_INPUT_ONLY_PIN);
  376. io_conf.mode = GPIO_MODE_OUTPUT;
  377. gpio_config(&io_conf);
  378. TEST_ASSERT(gpio_config(&io_conf) == ESP_ERR_INVALID_ARG);
  379. #endif //!CONFIG_IDF_TARGET_ESP32C3
  380. }
  381. // gpio17 connects to 3.3v pin, gpio19 connects to the GND pin
  382. // use multimeter to test the voltage, so it is ignored in CI
  383. TEST_CASE("GPIO get input level test", "[gpio][ignore]")
  384. {
  385. gpio_num_t num = 17;
  386. int level = gpio_get_level(num);
  387. printf("gpio17's level is: %d\n", level);
  388. TEST_ASSERT_EQUAL_INT_MESSAGE(level, 1, "get level error! the level should be high!");
  389. gpio_num_t num2 = 19;
  390. int level2 = gpio_get_level(num2);
  391. printf("gpio19's level is: %d\n", level2);
  392. TEST_ASSERT_EQUAL_INT_MESSAGE(level2, 0, "get level error! the level should be low!");
  393. printf("the memory get: %d\n", esp_get_free_heap_size());
  394. gpio_num_t num3 = 34; // connect with 3.3v
  395. int level3 = gpio_get_level(num3);
  396. printf("gpio19's level is: %d\n", level3);
  397. TEST_ASSERT_EQUAL_INT_MESSAGE(level3, 0, "get level error! the level should be low!");
  398. printf("the memory get: %d\n", esp_get_free_heap_size());
  399. //when case finish, get the result from multimeter, the pin17 is 3.3v, the pin19 is 0.00v
  400. }
  401. TEST_CASE("GPIO io pull up/down function", "[gpio]")
  402. {
  403. // First, ensure that the output IO will not affect the level
  404. gpio_config_t io_conf = init_io(TEST_GPIO_EXT_OUT_IO);
  405. gpio_config(&io_conf);
  406. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_INPUT);
  407. io_conf = init_io(TEST_GPIO_EXT_IN_IO);
  408. gpio_config(&io_conf);
  409. gpio_set_direction(TEST_GPIO_EXT_IN_IO, GPIO_MODE_INPUT);
  410. TEST_ESP_OK(gpio_pullup_en(TEST_GPIO_EXT_IN_IO)); // pull up first
  411. vTaskDelay(100 / portTICK_RATE_MS);
  412. TEST_ASSERT_EQUAL_INT_MESSAGE(gpio_get_level(TEST_GPIO_EXT_IN_IO), 1, "gpio_pullup_en error, it can't pull up");
  413. TEST_ESP_OK(gpio_pulldown_dis(TEST_GPIO_EXT_IN_IO)); //can't be pull down
  414. vTaskDelay(100 / portTICK_RATE_MS);
  415. TEST_ASSERT_EQUAL_INT_MESSAGE(gpio_get_level(TEST_GPIO_EXT_IN_IO), 1, "gpio_pulldown_dis error, it can pull down");
  416. TEST_ESP_OK(gpio_pulldown_en(TEST_GPIO_EXT_IN_IO)); // can be pull down now
  417. vTaskDelay(100 / portTICK_RATE_MS);
  418. TEST_ASSERT_EQUAL_INT_MESSAGE(gpio_get_level(TEST_GPIO_EXT_IN_IO), 0, "gpio_pulldown_en error, it can't pull down");
  419. TEST_ESP_OK(gpio_pullup_dis(TEST_GPIO_EXT_IN_IO)); // can't be pull up
  420. vTaskDelay(100 / portTICK_RATE_MS);
  421. TEST_ASSERT_EQUAL_INT_MESSAGE(gpio_get_level(TEST_GPIO_EXT_IN_IO), 0, "gpio_pullup_dis error, it can pull up");
  422. }
  423. #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3, ESP32C3)
  424. //No runners
  425. TEST_CASE("GPIO output and input mode test", "[gpio][test_env=UT_T1_GPIO]")
  426. {
  427. //ESP32 connect io18 and io19, ESP32-S2 connect io17 and io21, ESP32-S3 connect io19 and io20, ESP32C3 Connect GPIO2 with GPIO3
  428. gpio_config_t output_io = init_io(TEST_GPIO_EXT_OUT_IO);
  429. gpio_config_t input_io = init_io(TEST_GPIO_EXT_IN_IO);
  430. gpio_config(&output_io);
  431. gpio_config(&input_io);
  432. int level = gpio_get_level(TEST_GPIO_EXT_IN_IO);
  433. //disable mode
  434. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_DISABLE);
  435. gpio_set_direction(TEST_GPIO_EXT_IN_IO, GPIO_MODE_OUTPUT);
  436. gpio_set_level(TEST_GPIO_EXT_OUT_IO, !level);
  437. TEST_ASSERT_EQUAL_INT_MESSAGE(gpio_get_level(TEST_GPIO_EXT_IN_IO), level, "direction GPIO_MODE_DISABLE set error, it can output");
  438. //input mode and output mode
  439. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_OUTPUT);
  440. gpio_set_direction(TEST_GPIO_EXT_IN_IO, GPIO_MODE_INPUT);
  441. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 1);
  442. TEST_ASSERT_EQUAL_INT_MESSAGE(gpio_get_level(TEST_GPIO_EXT_IN_IO), 1, "direction GPIO_MODE_OUTPUT set error, it can't output");
  443. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 0);
  444. TEST_ASSERT_EQUAL_INT_MESSAGE(gpio_get_level(TEST_GPIO_EXT_IN_IO), 0, "direction GPIO_MODE_OUTPUT set error, it can't output");
  445. // open drain mode(output), can just output low level
  446. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_OUTPUT_OD);
  447. gpio_set_direction(TEST_GPIO_EXT_IN_IO, GPIO_MODE_INPUT);
  448. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 1);
  449. TEST_ASSERT_EQUAL_INT_MESSAGE(gpio_get_level(TEST_GPIO_EXT_IN_IO), 0, "direction GPIO_MODE_OUTPUT set error, it can't output");
  450. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 0);
  451. TEST_ASSERT_EQUAL_INT_MESSAGE(gpio_get_level(TEST_GPIO_EXT_IN_IO), 0, "direction GPIO_MODE_OUTPUT set error, it can't output");
  452. // open drain mode(output and input), can just output low level
  453. // output test
  454. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_INPUT_OUTPUT_OD);
  455. gpio_set_direction(TEST_GPIO_EXT_IN_IO, GPIO_MODE_INPUT);
  456. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 1);
  457. TEST_ASSERT_EQUAL_INT_MESSAGE(gpio_get_level(TEST_GPIO_EXT_IN_IO), 0, "direction GPIO_MODE_OUTPUT set error, it can't output");
  458. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 0);
  459. TEST_ASSERT_EQUAL_INT_MESSAGE(gpio_get_level(TEST_GPIO_EXT_IN_IO), 0, "direction GPIO_MODE_OUTPUT set error, it can't output");
  460. // GPIO_MODE_INPUT_OUTPUT mode
  461. // output test
  462. level = gpio_get_level(TEST_GPIO_EXT_IN_IO);
  463. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_INPUT_OUTPUT);
  464. gpio_set_direction(TEST_GPIO_EXT_IN_IO, GPIO_MODE_INPUT);
  465. gpio_set_level(TEST_GPIO_EXT_OUT_IO, !level);
  466. TEST_ASSERT_EQUAL_INT_MESSAGE(gpio_get_level(TEST_GPIO_EXT_IN_IO), !level, "direction set error, it can't output");
  467. }
  468. TEST_CASE("GPIO repeate call service and isr has no memory leak test","[gpio][test_env=UT_T1_GPIO][timeout=90]")
  469. {
  470. gpio_config_t output_io = init_io(TEST_GPIO_EXT_OUT_IO);
  471. gpio_config_t input_io = init_io(TEST_GPIO_EXT_IN_IO);
  472. input_io.intr_type = GPIO_INTR_POSEDGE;
  473. input_io.mode = GPIO_MODE_INPUT;
  474. input_io.pull_up_en = 1;
  475. TEST_ESP_OK(gpio_config(&output_io));
  476. TEST_ESP_OK(gpio_config(&input_io));
  477. TEST_ESP_OK(gpio_set_level(TEST_GPIO_EXT_OUT_IO, 0));
  478. //rising edge
  479. uint32_t size = esp_get_free_heap_size();
  480. for(int i=0;i<1000;i++) {
  481. TEST_ESP_OK(gpio_set_intr_type(TEST_GPIO_EXT_IN_IO, GPIO_INTR_POSEDGE));
  482. TEST_ESP_OK(gpio_install_isr_service(0));
  483. TEST_ESP_OK(gpio_isr_handler_add(TEST_GPIO_EXT_IN_IO, gpio_isr_edge_handler, (void*)TEST_GPIO_EXT_IN_IO));
  484. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 1);
  485. TEST_ESP_OK(gpio_isr_handler_remove(TEST_GPIO_EXT_IN_IO));
  486. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 0);
  487. gpio_uninstall_isr_service();
  488. }
  489. TEST_ASSERT_INT32_WITHIN(size, esp_get_free_heap_size(), 100);
  490. }
  491. #endif //DISABLED_FOR_TARGETS(ESP32S2, ESP32S3, ESP32C3)
  492. #if !WAKE_UP_IGNORE
  493. //this function development is not completed yet, set it ignored
  494. TEST_CASE("GPIO wake up enable and disenable test", "[gpio][ignore]")
  495. {
  496. xTaskCreate(sleep_wake_up, "sleep_wake_up", 4096, NULL, 5, NULL);
  497. xTaskCreate(trigger_wake_up, "trigger_wake_up", 4096, NULL, 5, NULL);
  498. vTaskDelay(100 / portTICK_RATE_MS);
  499. TEST_ASSERT_TRUE(wake_up_result);
  500. wake_up_result = false;
  501. TEST_ESP_OK(gpio_wakeup_disable(TEST_GPIO_EXT_IN_IO));
  502. gpio_set_level(TEST_GPIO_EXT_OUT_IO, 1);
  503. vTaskDelay(100 / portTICK_RATE_MS);
  504. TEST_ASSERT_FALSE(wake_up_result);
  505. }
  506. #endif // !WAKE_UP_IGNORE
  507. // this case need the resistance to pull up the voltage or pull down the voltage
  508. // ignored because the voltage needs to be tested with multimeter
  509. TEST_CASE("GPIO verify only the gpio with input ability can be set pull/down", "[gpio][ignore]")
  510. {
  511. gpio_config_t output_io = init_io(TEST_GPIO_EXT_OUT_IO);
  512. gpio_config_t input_io = init_io(TEST_GPIO_EXT_IN_IO);
  513. gpio_config(&output_io);
  514. input_io.mode = GPIO_MODE_INPUT;
  515. gpio_config(&input_io);
  516. printf("pull up test!\n");
  517. // pull up test
  518. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_OUTPUT);
  519. TEST_ESP_OK(gpio_set_pull_mode(TEST_GPIO_EXT_OUT_IO, GPIO_PULLUP_ONLY));
  520. prompt_to_continue("mode: GPIO_MODE_OUTPUT");
  521. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_OUTPUT_OD);
  522. TEST_ESP_OK(gpio_set_pull_mode(TEST_GPIO_EXT_OUT_IO, GPIO_PULLUP_ONLY));
  523. // open drain just can output low level
  524. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_INPUT_OUTPUT_OD);
  525. TEST_ESP_OK(gpio_set_pull_mode(TEST_GPIO_EXT_OUT_IO, GPIO_PULLUP_ONLY));
  526. prompt_to_continue("mode: GPIO_MODE_OUTPUT_OD");
  527. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_INPUT_OUTPUT);
  528. TEST_ESP_OK(gpio_set_pull_mode(TEST_GPIO_EXT_OUT_IO, GPIO_PULLUP_ONLY));
  529. prompt_to_continue("mode: GPIO_MODE_INPUT_OUTPUT");
  530. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_INPUT);
  531. TEST_ESP_OK(gpio_set_pull_mode(TEST_GPIO_EXT_OUT_IO, GPIO_PULLUP_ONLY));
  532. prompt_to_continue("mode: GPIO_MODE_INPUT");
  533. // after pull up the level is high now
  534. // pull down test
  535. printf("pull down test!\n");
  536. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_OUTPUT);
  537. TEST_ESP_OK(gpio_set_pull_mode(TEST_GPIO_EXT_OUT_IO, GPIO_PULLDOWN_ONLY));
  538. prompt_to_continue("mode: GPIO_MODE_OUTPUT");
  539. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_OUTPUT_OD);
  540. TEST_ESP_OK(gpio_set_pull_mode(TEST_GPIO_EXT_OUT_IO, GPIO_PULLDOWN_ONLY));
  541. prompt_to_continue("mode: GPIO_MODE_OUTPUT_OD");
  542. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_INPUT_OUTPUT_OD);
  543. TEST_ESP_OK(gpio_set_pull_mode(TEST_GPIO_EXT_OUT_IO, GPIO_PULLDOWN_ONLY));
  544. prompt_to_continue("mode: GPIO_MODE_INPUT_OUTPUT_OD");
  545. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_INPUT_OUTPUT);
  546. TEST_ESP_OK(gpio_set_pull_mode(TEST_GPIO_EXT_OUT_IO, GPIO_PULLDOWN_ONLY));
  547. prompt_to_continue("mode: GPIO_MODE_INPUT_OUTPUT");
  548. gpio_set_direction(TEST_GPIO_EXT_OUT_IO, GPIO_MODE_INPUT);
  549. TEST_ESP_OK(gpio_set_pull_mode(TEST_GPIO_EXT_OUT_IO, GPIO_PULLDOWN_ONLY));
  550. prompt_to_continue("mode: GPIO_MODE_INPUT");
  551. }
  552. /**
  553. * There are 5 situation for the GPIO drive capability:
  554. * 1. GPIO drive weak capability test
  555. * 2. GPIO drive stronger capability test
  556. * 3. GPIO drive default capability test
  557. * 4. GPIO drive default capability test2
  558. * 5. GPIO drive strongest capability test
  559. *
  560. * How to test:
  561. * when testing, use the sliding resistor and a multimeter
  562. * adjust the resistor from low to high, 0-10k
  563. * watch the current change
  564. * the current test result:
  565. * weak capability: (0.32-10.1)mA
  566. * stronger capability: (0.32-20.0)mA
  567. * default capability: (0.33-39.8)mA
  568. * default capability2: (0.33-39.9)mA
  569. * strongest capability: (0.33-64.2)mA
  570. *
  571. * the data shows:
  572. * weak capability<stronger capability<default capability=default capability2<strongest capability
  573. *
  574. * all of these cases should be ignored that it will not run in CI
  575. */
  576. // drive capability test
  577. TEST_CASE("GPIO drive capability test", "[gpio][ignore]")
  578. {
  579. printf("weak capability test! please view the current change!\n");
  580. drive_capability_set_get(TEST_GPIO_EXT_OUT_IO, GPIO_DRIVE_CAP_0);
  581. prompt_to_continue("If this test finishes");
  582. printf("stronger capability test! please view the current change!\n");
  583. drive_capability_set_get(TEST_GPIO_EXT_OUT_IO, GPIO_DRIVE_CAP_1);
  584. prompt_to_continue("If this test finishes");
  585. printf("default capability test! please view the current change!\n");
  586. drive_capability_set_get(TEST_GPIO_EXT_OUT_IO, GPIO_DRIVE_CAP_2);
  587. prompt_to_continue("If this test finishes");
  588. printf("default capability2 test! please view the current change!\n");
  589. drive_capability_set_get(TEST_GPIO_EXT_OUT_IO, GPIO_DRIVE_CAP_DEFAULT);
  590. prompt_to_continue("If this test finishes");
  591. printf("strongest capability test! please view the current change!\n");
  592. drive_capability_set_get(TEST_GPIO_EXT_OUT_IO, GPIO_DRIVE_CAP_3);
  593. prompt_to_continue("If this test finishes");
  594. }
  595. #if !CONFIG_FREERTOS_UNICORE
  596. #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
  597. void gpio_enable_task(void *param)
  598. {
  599. int gpio_num = (int)param;
  600. TEST_ESP_OK(gpio_intr_enable(gpio_num));
  601. vTaskDelete(NULL);
  602. }
  603. /** Test the GPIO Interrupt Enable API with dual core enabled. The GPIO ISR service routine is registered on one core.
  604. * When the GPIO interrupt on another core is enabled, the GPIO interrupt will be lost.
  605. * First on the core 0, Do the following steps:
  606. * 1. Configure the GPIO9 input_output mode, and enable the rising edge interrupt mode.
  607. * 2. Trigger the GPIO9 interrupt and check if the interrupt responds correctly.
  608. * 3. Disable the GPIO9 interrupt
  609. * Then on the core 1, Do the following steps:
  610. * 1. Enable the GPIO9 interrupt again.
  611. * 2. Trigger the GPIO9 interrupt and check if the interrupt responds correctly.
  612. *
  613. */
  614. TEST_CASE("GPIO Enable/Disable interrupt on multiple cores", "[gpio][ignore]")
  615. {
  616. gpio_config_t io_conf;
  617. io_conf.intr_type = GPIO_INTR_NEGEDGE;
  618. io_conf.mode = GPIO_MODE_INPUT_OUTPUT;
  619. io_conf.pin_bit_mask = (1ULL << TEST_IO_9);
  620. io_conf.pull_down_en = 0;
  621. io_conf.pull_up_en = 1;
  622. TEST_ESP_OK(gpio_config(&io_conf));
  623. TEST_ESP_OK(gpio_set_level(TEST_IO_9, 0));
  624. TEST_ESP_OK(gpio_install_isr_service(0));
  625. TEST_ESP_OK(gpio_isr_handler_add(TEST_IO_9, gpio_isr_edge_handler, (void*) TEST_IO_9));
  626. vTaskDelay(1000 / portTICK_RATE_MS);
  627. TEST_ESP_OK(gpio_set_level(TEST_IO_9, 1));
  628. vTaskDelay(100 / portTICK_RATE_MS);
  629. TEST_ESP_OK(gpio_set_level(TEST_IO_9, 0));
  630. vTaskDelay(100 / portTICK_RATE_MS);
  631. TEST_ESP_OK(gpio_intr_disable(TEST_IO_9));
  632. TEST_ASSERT(edge_intr_times == 1);
  633. xTaskCreatePinnedToCore(gpio_enable_task, "gpio_enable_task", 1024*4, (void*)TEST_IO_9, 8, NULL, (xPortGetCoreID() == 0));
  634. vTaskDelay(1000 / portTICK_RATE_MS);
  635. TEST_ESP_OK(gpio_set_level(TEST_IO_9, 1));
  636. vTaskDelay(100 / portTICK_RATE_MS);
  637. TEST_ESP_OK(gpio_set_level(TEST_IO_9, 0));
  638. vTaskDelay(100 / portTICK_RATE_MS);
  639. TEST_ESP_OK(gpio_intr_disable(TEST_IO_9));
  640. TEST_ESP_OK(gpio_isr_handler_remove(TEST_IO_9));
  641. gpio_uninstall_isr_service();
  642. TEST_ASSERT(edge_intr_times == 2);
  643. }
  644. #endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
  645. #endif //!CONFIG_FREERTOS_UNICORE
  646. typedef struct {
  647. int gpio_num;
  648. int isr_cnt;
  649. } gpio_isr_param_t;
  650. static void gpio_isr_handler(void* arg)
  651. {
  652. gpio_isr_param_t *param = (gpio_isr_param_t *)arg;
  653. esp_rom_printf("GPIO[%d] intr, val: %d\n", param->gpio_num, gpio_get_level(param->gpio_num));
  654. param->isr_cnt++;
  655. }
  656. /** The previous GPIO interrupt service routine polls the interrupt raw status register to find the GPIO that triggered the interrupt.
  657. * But this will incorrectly handle the interrupt disabled GPIOs, because the raw interrupt status register can still be set when
  658. * the trigger signal arrives, even if the interrupt is disabled.
  659. * First on the core 0:
  660. * 1. Configure the GPIO9 and GPIO10(ESP32, ESP32C3)/GPIO21(ESP32-S2) input_output mode.
  661. * 2. Enable GPIO9 dual edge triggered interrupt, enable GPIO10(ESP32, ESP32C3)/GPIO21(ESP32-S2) falling edge triggered interrupt.
  662. * 3. Trigger GPIO9 interrupt, than disable the GPIO18 interrupt, and than trigger GPIO18 again(This time will not respond to the interrupt).
  663. * 4. Trigger GPIO10(ESP32, ESP32C3)/GPIO21(ESP32-S2) interrupt.
  664. * If the bug is not fixed, you will see, in the step 4, the interrupt of GPIO9 will also respond.
  665. */
  666. TEST_CASE("GPIO ISR service test", "[gpio][ignore]")
  667. {
  668. static gpio_isr_param_t io9_param = {
  669. .gpio_num = TEST_IO_9,
  670. .isr_cnt = 0,
  671. };
  672. static gpio_isr_param_t io10_param = {
  673. .gpio_num = TEST_IO_10,
  674. .isr_cnt = 0,
  675. };
  676. gpio_config_t io_conf;
  677. io_conf.intr_type = GPIO_INTR_DISABLE;
  678. io_conf.mode = GPIO_MODE_INPUT_OUTPUT;
  679. io_conf.pin_bit_mask = (1ULL << TEST_IO_9) | (1ULL << TEST_IO_10);
  680. io_conf.pull_down_en = 0;
  681. io_conf.pull_up_en = 1;
  682. TEST_ESP_OK(gpio_config(&io_conf));
  683. TEST_ESP_OK(gpio_set_level(TEST_IO_9, 0));
  684. TEST_ESP_OK(gpio_set_level(TEST_IO_10, 0));
  685. TEST_ESP_OK(gpio_install_isr_service(0));
  686. TEST_ESP_OK(gpio_set_intr_type(TEST_IO_9, GPIO_INTR_ANYEDGE));
  687. TEST_ESP_OK(gpio_set_intr_type(TEST_IO_10, GPIO_INTR_NEGEDGE));
  688. TEST_ESP_OK(gpio_isr_handler_add(TEST_IO_9, gpio_isr_handler, (void*)&io9_param));
  689. TEST_ESP_OK(gpio_isr_handler_add(TEST_IO_10, gpio_isr_handler, (void*)&io10_param));
  690. printf("Triggering the interrupt of GPIO9\n");
  691. vTaskDelay(1000 / portTICK_RATE_MS);
  692. //Rising edge
  693. TEST_ESP_OK(gpio_set_level(TEST_IO_9, 1));
  694. printf("Disable the interrupt of GPIO9\n");
  695. vTaskDelay(100 / portTICK_RATE_MS);
  696. //Disable GPIO9 interrupt, GPIO18 will not respond to the next falling edge interrupt.
  697. TEST_ESP_OK(gpio_intr_disable(TEST_IO_9));
  698. vTaskDelay(100 / portTICK_RATE_MS);
  699. //Falling edge
  700. TEST_ESP_OK(gpio_set_level(TEST_IO_9, 0));
  701. printf("Triggering the interrupt of GPIO10\n");
  702. vTaskDelay(100 / portTICK_RATE_MS);
  703. TEST_ESP_OK(gpio_set_level(TEST_IO_10, 1));
  704. vTaskDelay(100 / portTICK_RATE_MS);
  705. //Falling edge
  706. TEST_ESP_OK(gpio_set_level(TEST_IO_10, 0));
  707. vTaskDelay(100 / portTICK_RATE_MS);
  708. TEST_ESP_OK(gpio_isr_handler_remove(TEST_IO_9));
  709. TEST_ESP_OK(gpio_isr_handler_remove(TEST_IO_10));
  710. gpio_uninstall_isr_service();
  711. TEST_ASSERT((io9_param.isr_cnt == 1) && (io10_param.isr_cnt == 1));
  712. }