test_dedicated_gpio.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /*
  2. * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "freertos/FreeRTOS.h"
  7. #include "freertos/task.h"
  8. #include "freertos/semphr.h"
  9. #include "unity.h"
  10. #include "unity_test_utils.h"
  11. #include "esp_rom_sys.h"
  12. #include "soc/soc_caps.h"
  13. #include "hal/dedic_gpio_cpu_ll.h"
  14. #include "driver/gpio.h"
  15. #include "driver/dedic_gpio.h"
  16. TEST_CASE("Dedicated_GPIO_bundle_install/uninstall", "[dedic_gpio]")
  17. {
  18. const int test_gpios[SOC_DEDIC_GPIO_OUT_CHANNELS_NUM / 2] = {0};
  19. const int test2_gpios[SOC_DEDIC_GPIO_OUT_CHANNELS_NUM / 2 + 1] = {0};
  20. const int test3_gpios[SOC_DEDIC_GPIO_OUT_CHANNELS_NUM + 1] = {0};
  21. dedic_gpio_bundle_handle_t test_bundle, test_bundle2, test_bundle3 = NULL;
  22. dedic_gpio_bundle_config_t bundle_config = {
  23. .gpio_array = test_gpios,
  24. .array_size = sizeof(test_gpios) / sizeof(test_gpios[0]),
  25. };
  26. dedic_gpio_bundle_config_t bundle_config2 = {
  27. .gpio_array = test2_gpios,
  28. .array_size = sizeof(test2_gpios) / sizeof(test2_gpios[0]),
  29. .flags = {
  30. .out_en = 1,
  31. },
  32. };
  33. dedic_gpio_bundle_config_t bundle_config3 = {
  34. .gpio_array = test3_gpios,
  35. .array_size = sizeof(test3_gpios) / sizeof(test3_gpios[0]),
  36. .flags = {
  37. .out_en = 1,
  38. },
  39. };
  40. TEST_ASSERT_EQUAL_MESSAGE(ESP_ERR_INVALID_ARG, dedic_gpio_new_bundle(&bundle_config, &test_bundle), "shouldn't create bundle if no mode is specified");
  41. bundle_config.flags.out_en = 1;
  42. TEST_ASSERT_EQUAL_MESSAGE(ESP_OK, dedic_gpio_new_bundle(&bundle_config, &test_bundle), "create bundle with half channels failed");
  43. uint32_t mask = 0;
  44. TEST_ESP_OK(dedic_gpio_get_out_mask(test_bundle, &mask));
  45. TEST_ASSERT_EQUAL_MESSAGE((1 << (SOC_DEDIC_GPIO_OUT_CHANNELS_NUM / 2)) - 1, mask, "wrong out mask");
  46. TEST_ESP_OK(dedic_gpio_get_in_mask(test_bundle, &mask));
  47. TEST_ASSERT_EQUAL_MESSAGE(0, mask, "wrong in mask");
  48. TEST_ASSERT_EQUAL_MESSAGE(ESP_ERR_NOT_FOUND, dedic_gpio_new_bundle(&bundle_config2, &test_bundle2), "shouldn't create bundle if there's no enough channels");
  49. TEST_ASSERT_EQUAL_MESSAGE(ESP_OK, dedic_gpio_del_bundle(test_bundle), "delete bundle failed");
  50. TEST_ASSERT_EQUAL_MESSAGE(ESP_ERR_INVALID_ARG, dedic_gpio_new_bundle(&bundle_config3, &test_bundle3), "shouldn't create bundle if the array size exceeds maximum");
  51. }
  52. #define TEST_GPIO_GROUP_SIZE (4)
  53. typedef struct {
  54. SemaphoreHandle_t sem;
  55. const int gpios[TEST_GPIO_GROUP_SIZE];
  56. } test_dedic_task_context_t;
  57. static void test_dedic_gpio_on_specific_core(void *args)
  58. {
  59. test_dedic_task_context_t *ctx = (test_dedic_task_context_t *)args;
  60. uint32_t value = 0;
  61. dedic_gpio_cpu_ll_write_all(0x0); // clear all out channels
  62. // configure a group of GPIOs, output only
  63. const int bundleA_gpios[] = {ctx->gpios[0], ctx->gpios[1]};
  64. gpio_config_t io_conf = {
  65. .mode = GPIO_MODE_OUTPUT,
  66. };
  67. for (int i = 0; i < sizeof(bundleA_gpios) / sizeof(bundleA_gpios[0]); i++) {
  68. io_conf.pin_bit_mask = 1ULL << bundleA_gpios[i];
  69. gpio_config(&io_conf);
  70. }
  71. // Create bundleA, output only
  72. dedic_gpio_bundle_handle_t bundleA = NULL;
  73. dedic_gpio_bundle_config_t bundleA_config = {
  74. .gpio_array = bundleA_gpios,
  75. .array_size = sizeof(bundleA_gpios) / sizeof(bundleA_gpios[0]),
  76. .flags = {
  77. .out_en = 1,
  78. },
  79. };
  80. TEST_ESP_OK(dedic_gpio_new_bundle(&bundleA_config, &bundleA));
  81. // configure another group of GPIOs, input and output
  82. const int bundleB_gpios[] = {ctx->gpios[2], ctx->gpios[3]};
  83. io_conf.mode = GPIO_MODE_INPUT_OUTPUT;
  84. for (int i = 0; i < sizeof(bundleB_gpios) / sizeof(bundleB_gpios[0]); i++) {
  85. io_conf.pin_bit_mask = 1ULL << bundleB_gpios[i];
  86. gpio_config(&io_conf);
  87. }
  88. // GPIO bundleB, input and output
  89. dedic_gpio_bundle_handle_t bundleB = NULL;
  90. dedic_gpio_bundle_config_t bundleB_config = {
  91. .gpio_array = bundleB_gpios,
  92. .array_size = sizeof(bundleB_gpios) / sizeof(bundleB_gpios[0]),
  93. .flags = {
  94. .in_en = 1,
  95. .out_en = 1,
  96. },
  97. };
  98. TEST_ESP_OK(dedic_gpio_new_bundle(&bundleB_config, &bundleB));
  99. dedic_gpio_bundle_write(bundleA, 0x01, 0x01);
  100. dedic_gpio_bundle_write(bundleB, 0x03, 0x03);
  101. value = dedic_gpio_cpu_ll_read_out();
  102. TEST_ASSERT_EQUAL(0x0D, value); // 1101
  103. value = dedic_gpio_cpu_ll_read_in();
  104. TEST_ASSERT_EQUAL(0x03, value); // 11
  105. dedic_gpio_bundle_write(bundleB, 0x02, 0x0);
  106. value = dedic_gpio_cpu_ll_read_out();
  107. TEST_ASSERT_EQUAL(0x05, value); // 0101
  108. value = dedic_gpio_cpu_ll_read_in();
  109. TEST_ASSERT_EQUAL(0x01, value); // 01
  110. dedic_gpio_cpu_ll_write_all(0x0F); // Set all out channels
  111. value = dedic_gpio_cpu_ll_read_out();
  112. TEST_ASSERT_EQUAL(0x0F, value);
  113. value = dedic_gpio_cpu_ll_read_in();
  114. TEST_ASSERT_EQUAL(0x03, value); // 11
  115. TEST_ASSERT_EQUAL(0x03, dedic_gpio_bundle_read_out(bundleA)); // 11
  116. TEST_ASSERT_EQUAL(0x00, dedic_gpio_bundle_read_in(bundleA)); // input is not enabled for bundleA
  117. TEST_ASSERT_EQUAL(0x03, dedic_gpio_bundle_read_out(bundleB)); // 11
  118. TEST_ASSERT_EQUAL(0x03, dedic_gpio_bundle_read_in(bundleB)); // 11
  119. TEST_ESP_OK(dedic_gpio_del_bundle(bundleA));
  120. TEST_ESP_OK(dedic_gpio_del_bundle(bundleB));
  121. xSemaphoreGive(ctx->sem);
  122. vTaskSuspend(NULL);
  123. }
  124. TEST_CASE("Dedicated_GPIO_run_on_multiple_CPU_cores", "[dedic_gpio]")
  125. {
  126. SemaphoreHandle_t sem = xSemaphoreCreateCounting(SOC_CPU_CORES_NUM, 0);
  127. TaskHandle_t task_handle[SOC_CPU_CORES_NUM];
  128. for (int i = 0; i < SOC_CPU_CORES_NUM; i++) {
  129. int start_gpio = i * TEST_GPIO_GROUP_SIZE;
  130. test_dedic_task_context_t isr_ctx = {
  131. .sem = sem,
  132. .gpios = {start_gpio, start_gpio + 1, start_gpio + 2, start_gpio + 3}
  133. };
  134. xTaskCreatePinnedToCore(test_dedic_gpio_on_specific_core, "dedic_gpio_test_tsk", 4096, &isr_ctx, 1,
  135. &task_handle[i], i);
  136. }
  137. for (int i = 0; i < SOC_CPU_CORES_NUM; i++) {
  138. xSemaphoreTake(sem, pdMS_TO_TICKS(1000));
  139. }
  140. vSemaphoreDelete(sem);
  141. for (int i = 0; i < SOC_CPU_CORES_NUM; i++) {
  142. unity_utils_task_delete(task_handle[i]);
  143. }
  144. }
  145. IRAM_ATTR static void test_dedic_gpio_isr_callback(void *args)
  146. {
  147. SemaphoreHandle_t sem = (SemaphoreHandle_t)args;
  148. BaseType_t high_task_wakeup = pdFALSE;
  149. esp_rom_printf("GPIO event\r\n");
  150. xSemaphoreGiveFromISR(sem, &high_task_wakeup);
  151. if (high_task_wakeup) {
  152. esp_rom_printf("high priority task wake up\r\n");
  153. }
  154. }
  155. TEST_CASE("Dedicated_GPIO_interrupt_and_callback", "[dedic_gpio]")
  156. {
  157. SemaphoreHandle_t sem = xSemaphoreCreateBinary();
  158. // configure GPIO
  159. const int bundle_gpios[] = {0, 1};
  160. gpio_config_t io_conf = {
  161. .mode = GPIO_MODE_INPUT_OUTPUT,
  162. };
  163. for (int i = 0; i < sizeof(bundle_gpios) / sizeof(bundle_gpios[0]); i++) {
  164. io_conf.pin_bit_mask = 1ULL << bundle_gpios[i];
  165. gpio_config(&io_conf);
  166. }
  167. dedic_gpio_bundle_handle_t bundle = NULL;
  168. dedic_gpio_bundle_config_t bundle_config = {
  169. .gpio_array = bundle_gpios,
  170. .array_size = sizeof(bundle_gpios) / sizeof(bundle_gpios[0]),
  171. .flags = {
  172. .in_en = 1,
  173. .out_en = 1,
  174. },
  175. };
  176. TEST_ESP_OK(dedic_gpio_new_bundle(&bundle_config, &bundle));
  177. // enable interrupt on GPIO1
  178. TEST_ESP_OK(gpio_set_intr_type(1, GPIO_INTR_POSEDGE));
  179. // install gpio isr service
  180. TEST_ESP_OK(gpio_install_isr_service(0));
  181. // hook isr handler for specific gpio pin
  182. TEST_ESP_OK(gpio_isr_handler_add(1, test_dedic_gpio_isr_callback, sem));
  183. // trigger a posedge on GPIO1
  184. dedic_gpio_bundle_write(bundle, BIT(1), 0x00);
  185. dedic_gpio_bundle_write(bundle, BIT(1), 0xFF);
  186. // wait for done semaphore
  187. TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(sem, pdMS_TO_TICKS(1000)));
  188. // remove isr handler for gpio number
  189. TEST_ESP_OK(gpio_isr_handler_remove(1));
  190. // uninstall GPIO interrupt service
  191. gpio_uninstall_isr_service();
  192. TEST_ESP_OK(dedic_gpio_del_bundle(bundle));
  193. vSemaphoreDelete(sem);
  194. }