test_coproc.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /*
  2. * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "sdkconfig.h"
  7. #include "soc/soc_caps.h"
  8. #if CONFIG_FREERTOS_SMP && SOC_CPU_HAS_FPU
  9. #include "freertos/FreeRTOS.h"
  10. #include "freertos/task.h"
  11. #include "xtensa/xtensa_api.h"
  12. #include "esp_intr_alloc.h"
  13. #include "unity.h"
  14. #include "test_utils.h"
  15. /*
  16. Note: We need to declare the float here to prevent compiler optimizing float
  17. operations into non-float instructions.
  18. */
  19. static volatile float test_float;
  20. /*
  21. Test coprocessor (CP) usage in task
  22. Purpose:
  23. - Test that CP can be used in a task (e.g., the FPU)
  24. - Test that unpinned tasks are pinned when the CP is used
  25. - Test that CP is properly saved in restored
  26. - Test that CP context is properly cleaned up when task is deleted
  27. */
  28. #define COPROC_TASK_TEST_ITER 10
  29. static void unpinned_task(void *arg)
  30. {
  31. // Test that task gets pinned to the current core when it uses the coprocessor
  32. vTaskPreemptionDisable(NULL); // Disable preemption to make current core ID doesn't change
  33. BaseType_t xCoreID = xPortGetCoreID();
  34. TEST_ASSERT_EQUAL(tskNO_AFFINITY, vTaskCoreAffinityGet(NULL));
  35. test_float = 1.1f;
  36. test_float *= 2.0f;
  37. TEST_ASSERT_EQUAL(2.2f, test_float);
  38. TEST_ASSERT_EQUAL(1 << xCoreID, vTaskCoreAffinityGet(NULL));
  39. vTaskPreemptionEnable(NULL);
  40. // Delay to trigger a solicited context switch
  41. vTaskDelay(1);
  42. // Test that CP context was saved and restored properly
  43. test_float *= 2.0f;
  44. TEST_ASSERT_EQUAL(4.4f, test_float);
  45. // Wait to be deleted
  46. xTaskNotifyGive((TaskHandle_t)arg);
  47. vTaskSuspend(NULL);
  48. }
  49. TEST_CASE("Test coproc usage in task", "[freertos]")
  50. {
  51. TaskHandle_t unity_task_handle = xTaskGetCurrentTaskHandle();
  52. for (int i = 0; i < COPROC_TASK_TEST_ITER; i++) {
  53. TaskHandle_t unpinned_task_handle;
  54. xTaskCreate(unpinned_task, "unpin", 2048, (void *)unity_task_handle, UNITY_FREERTOS_PRIORITY + 1, &unpinned_task_handle);
  55. ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
  56. vTaskDelete(unpinned_task_handle);
  57. vTaskDelay(10); // Short delay to allow task memory to be freed
  58. }
  59. }
  60. #if CONFIG_FREERTOS_FPU_IN_ISR
  61. /*
  62. Test coprocessor (CP) usage in ISR
  63. Purpose:
  64. - Test that CP can be used in an ISR
  65. - Test that an interrupted unpinned task will not be pinned by the ISR using the CP
  66. */
  67. #define SW_ISR_LEVEL_1 7
  68. static void software_isr(void *arg)
  69. {
  70. (void) arg;
  71. xt_set_intclear(1 << SW_ISR_LEVEL_1);
  72. test_float *= 2;
  73. }
  74. static void unpinned_task_isr(void *arg)
  75. {
  76. vTaskPreemptionDisable(NULL); // Disable preemption to make current core ID doesn't change
  77. TEST_ASSERT_EQUAL(tskNO_AFFINITY, vTaskCoreAffinityGet(NULL));
  78. // Allocate ISR on the current core
  79. intr_handle_t handle;
  80. esp_err_t err = esp_intr_alloc(ETS_INTERNAL_SW0_INTR_SOURCE, ESP_INTR_FLAG_LEVEL1, &software_isr, NULL, &handle);
  81. TEST_ASSERT_EQUAL_HEX32(ESP_OK, err);
  82. // Trigger the ISR
  83. xt_set_intset(1 << SW_ISR_LEVEL_1);
  84. // Test that task affinity hasn't changed
  85. TEST_ASSERT_EQUAL(tskNO_AFFINITY, vTaskCoreAffinityGet(NULL));
  86. // Free the ISR
  87. esp_intr_free(handle);
  88. // Wait to be deleted
  89. vTaskPreemptionEnable(NULL);
  90. xTaskNotifyGive((TaskHandle_t)arg);
  91. vTaskSuspend(NULL);
  92. }
  93. TEST_CASE("Test coproc usage in ISR", "[freertos]")
  94. {
  95. TaskHandle_t unity_task_handle = xTaskGetCurrentTaskHandle();
  96. for (int i = 0; i < COPROC_TASK_TEST_ITER; i++) {
  97. // Initialize the test float
  98. test_float = 1.1f;
  99. // Create an unpinned task to trigger the ISR
  100. TaskHandle_t unpinned_task_handle;
  101. xTaskCreate(unpinned_task_isr, "unpin", 2048, (void *)unity_task_handle, UNITY_FREERTOS_PRIORITY + 1, &unpinned_task_handle);
  102. ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
  103. // Check that the test float value
  104. TEST_ASSERT_EQUAL(2.2f, test_float);
  105. // Delete the unpinned task. Short delay to allow task memory to be freed
  106. vTaskDelete(unpinned_task_handle);
  107. vTaskDelay(10);
  108. }
  109. }
  110. #endif // CONFIG_FREERTOS_FPU_IN_ISR
  111. #endif // CONFIG_FREERTOS_SMP && SOC_CPU_HAS_FPU