test_ulp_riscv.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <inttypes.h>
  9. #include "esp_sleep.h"
  10. #include "soc/rtc_cntl_reg.h"
  11. #include "soc/sens_reg.h"
  12. #include "soc/rtc_periph.h"
  13. #include "ulp_riscv.h"
  14. #include "ulp_riscv_lock.h"
  15. #include "ulp_test_app.h"
  16. #include "ulp_test_shared.h"
  17. #include "unity.h"
  18. #include <sys/time.h>
  19. #include "freertos/FreeRTOS.h"
  20. #include "freertos/task.h"
  21. #define ULP_WAKEUP_PERIOD 1000000 // 1 second
  22. extern const uint8_t ulp_main_bin_start[] asm("_binary_ulp_test_app_bin_start");
  23. extern const uint8_t ulp_main_bin_end[] asm("_binary_ulp_test_app_bin_end");
  24. static bool firmware_loaded = false;
  25. static void load_and_start_ulp_firmware(void)
  26. {
  27. if (!firmware_loaded) {
  28. TEST_ASSERT(ulp_riscv_load_binary(ulp_main_bin_start,
  29. (ulp_main_bin_end - ulp_main_bin_start)) == ESP_OK);
  30. TEST_ASSERT(ulp_set_wakeup_period(0, ULP_WAKEUP_PERIOD) == ESP_OK);
  31. TEST_ASSERT(ulp_riscv_run() == ESP_OK);
  32. firmware_loaded = true;
  33. }
  34. }
  35. TEST_CASE("ULP-RISC-V and main CPU are able to exchange data", "[ulp]")
  36. {
  37. const uint32_t test_data = 0x12345678;
  38. struct timeval start, end;
  39. /* Load ULP RISC-V firmware and start the ULP RISC-V Coprocessor */
  40. load_and_start_ulp_firmware();
  41. /* Setup wakeup triggers */
  42. TEST_ASSERT(esp_sleep_enable_ulp_wakeup() == ESP_OK);
  43. /* Setup test data */
  44. ulp_riscv_test_data_in = test_data ^ XOR_MASK;
  45. ulp_main_cpu_command = RISCV_READ_WRITE_TEST;
  46. /* Enter Light Sleep */
  47. esp_light_sleep_start();
  48. /* Wait till we receive the correct command response */
  49. gettimeofday(&start, NULL);
  50. while (ulp_command_resp != RISCV_READ_WRITE_TEST)
  51. ;
  52. gettimeofday(&end, NULL);
  53. printf("Response time %jd ms\n", ((intmax_t)end.tv_sec - (intmax_t)start.tv_sec) * 1000 + (end.tv_usec - start.tv_usec) / 1000);
  54. /* Verify test data */
  55. TEST_ASSERT(ulp_command_resp == RISCV_READ_WRITE_TEST);
  56. TEST_ASSERT(ulp_main_cpu_reply == RISCV_COMMAND_OK);
  57. printf("data out: 0x%" PRIx32 ", expected: 0x%" PRIx32 " \n", ulp_riscv_test_data_out, test_data);
  58. TEST_ASSERT(test_data == ulp_riscv_test_data_out);
  59. /* Clear test data */
  60. ulp_main_cpu_command = RISCV_NO_COMMAND;
  61. }
  62. TEST_CASE("ULP-RISC-V is able to wakeup main CPU from light sleep", "[ulp]")
  63. {
  64. struct timeval start, end;
  65. /* Load ULP RISC-V firmware and start the ULP RISC-V Coprocessor */
  66. load_and_start_ulp_firmware();
  67. /* Setup wakeup triggers */
  68. TEST_ASSERT(esp_sleep_enable_ulp_wakeup() == ESP_OK);
  69. /* Setup test data */
  70. ulp_main_cpu_command = RISCV_LIGHT_SLEEP_WAKEUP_TEST;
  71. /* Enter Light Sleep */
  72. esp_light_sleep_start();
  73. /* Wait till we receive the correct command response */
  74. gettimeofday(&start, NULL);
  75. while (ulp_command_resp != RISCV_LIGHT_SLEEP_WAKEUP_TEST)
  76. ;
  77. gettimeofday(&end, NULL);
  78. printf("Response time 1st: %jd ms\n", ((intmax_t)end.tv_sec - (intmax_t)start.tv_sec) * 1000 + (end.tv_usec - start.tv_usec) / 1000);
  79. /* Verify test data */
  80. TEST_ASSERT(ulp_command_resp == RISCV_LIGHT_SLEEP_WAKEUP_TEST);
  81. TEST_ASSERT(ulp_main_cpu_reply == RISCV_COMMAND_OK);
  82. /* Enter Light Sleep again */
  83. esp_light_sleep_start();
  84. /* Wait till we receive the correct command response */
  85. gettimeofday(&start, NULL);
  86. while (ulp_command_resp != RISCV_LIGHT_SLEEP_WAKEUP_TEST)
  87. ;
  88. gettimeofday(&end, NULL);
  89. printf("Response time 2nd: %jd ms\n", ((intmax_t)end.tv_sec - (intmax_t)start.tv_sec) * 1000 + (end.tv_usec - start.tv_usec) / 1000);
  90. /* Verify test data */
  91. TEST_ASSERT(ulp_command_resp == RISCV_LIGHT_SLEEP_WAKEUP_TEST);
  92. TEST_ASSERT(ulp_main_cpu_reply == RISCV_COMMAND_OK);
  93. /* Clear test data */
  94. ulp_main_cpu_command = RISCV_NO_COMMAND;
  95. }
  96. static bool ulp_riscv_is_running(void)
  97. {
  98. uint32_t start_cnt = ulp_riscv_counter;
  99. /* Wait a few ULP wakeup cycles to ensure ULP has run */
  100. vTaskDelay((5 * ULP_WAKEUP_PERIOD / 1000) / portTICK_PERIOD_MS);
  101. uint32_t end_cnt = ulp_riscv_counter;
  102. printf("start run count: %" PRIu32 ", end run count %" PRIu32 "\n", start_cnt, end_cnt);
  103. /* If the ulp is running the counter should have been incremented */
  104. return (start_cnt != end_cnt);
  105. }
  106. TEST_CASE("ULP-RISC-V can be stopped and resumed from main CPU", "[ulp]")
  107. {
  108. /* Load ULP RISC-V firmware and start the ULP RISC-V Coprocessor */
  109. load_and_start_ulp_firmware();
  110. TEST_ASSERT(ulp_riscv_is_running());
  111. printf("Stopping the ULP\n");
  112. ulp_riscv_timer_stop();
  113. ulp_riscv_halt();
  114. TEST_ASSERT(!ulp_riscv_is_running());
  115. printf("Resuming the ULP\n");
  116. ulp_riscv_timer_resume();
  117. TEST_ASSERT(ulp_riscv_is_running());
  118. }
  119. TEST_CASE("ULP-RISC-V can stop itself and be resumed from the main CPU", "[ulp]")
  120. {
  121. volatile riscv_test_commands_t *command_resp = (riscv_test_commands_t*)&ulp_command_resp;
  122. /* Load ULP RISC-V firmware and start the ULP RISC-V Coprocessor */
  123. load_and_start_ulp_firmware();
  124. TEST_ASSERT(ulp_riscv_is_running());
  125. printf("Stopping the ULP\n");
  126. /* Setup test data */
  127. ulp_main_cpu_command = RISCV_STOP_TEST;
  128. while (*command_resp != RISCV_STOP_TEST) {
  129. }
  130. /* Wait a bit to ensure ULP finished shutting down */
  131. vTaskDelay(100 / portTICK_PERIOD_MS);
  132. TEST_ASSERT(!ulp_riscv_is_running());
  133. printf("Resuming the ULP\n");
  134. ulp_main_cpu_command = RISCV_NO_COMMAND;
  135. ulp_riscv_timer_resume();
  136. TEST_ASSERT(ulp_riscv_is_running());
  137. }
  138. /*
  139. * Keep this test case as the last test case in this suite as a CPU reset occurs.
  140. * Add new test cases above in order to ensure they run when all test cases are run together.
  141. */
  142. TEST_CASE("ULP-RISC-V is able to wakeup main CPU from deep sleep", "[ulp][reset=SW_CPU_RESET][ignore]")
  143. {
  144. /* Load ULP RISC-V firmware and start the ULP RISC-V Coprocessor */
  145. load_and_start_ulp_firmware();
  146. /* Setup wakeup triggers */
  147. TEST_ASSERT(esp_sleep_enable_ulp_wakeup() == ESP_OK);
  148. /* Setup test data */
  149. ulp_main_cpu_command = RISCV_DEEP_SLEEP_WAKEUP_TEST;
  150. /* Enter Deep Sleep */
  151. esp_deep_sleep_start();
  152. UNITY_TEST_FAIL(__LINE__, "Should not get here!");
  153. }
  154. TEST_CASE("ULP-RISC-V mutex", "[ulp]")
  155. {
  156. /* Load ULP RISC-V firmware and start the ULP RISC-V Coprocessor */
  157. load_and_start_ulp_firmware();
  158. /* Setup test data */
  159. ulp_riscv_incrementer = 0;
  160. ulp_main_cpu_reply = RISCV_NO_COMMAND;
  161. ulp_main_cpu_command = RISCV_MUTEX_TEST;
  162. ulp_riscv_lock_t *lock = (ulp_riscv_lock_t*)&ulp_lock;
  163. for (int i = 0; i < MUTEX_TEST_ITERATIONS; i++) {
  164. ulp_riscv_lock_acquire(lock);
  165. ulp_riscv_incrementer++;
  166. ulp_riscv_lock_release(lock);
  167. }
  168. while(ulp_main_cpu_reply != RISCV_COMMAND_OK) {
  169. // Wait for ULP to finish
  170. }
  171. /* If the variable is protected there should be no race conditions
  172. results should be the sum of increments made by ULP and by main CPU
  173. */
  174. TEST_ASSERT_EQUAL(2*MUTEX_TEST_ITERATIONS, ulp_riscv_incrementer);
  175. }