cpu_ll.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /*
  2. * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #pragma once
  7. /*
  8. Note: This is a compatibility header. Call the interfaces in esp_cpu.h instead
  9. [refactor-todo]: Mark all API in this header as deprecated
  10. */
  11. #include <stdint.h>
  12. #include <stdbool.h>
  13. #include "soc/soc_caps.h"
  14. #include "esp_attr.h"
  15. #include "esp_cpu.h"
  16. #ifdef __cplusplus
  17. extern "C" {
  18. #endif
  19. FORCE_INLINE_ATTR __attribute__((pure)) uint32_t cpu_ll_get_core_id(void)
  20. {
  21. return esp_cpu_get_core_id();
  22. }
  23. FORCE_INLINE_ATTR uint32_t cpu_ll_get_cycle_count(void)
  24. {
  25. return (uint32_t)esp_cpu_get_ccount();
  26. }
  27. FORCE_INLINE_ATTR void cpu_ll_set_cycle_count(uint32_t val)
  28. {
  29. esp_cpu_set_cycle_count((esp_cpu_ccount_t)val);
  30. }
  31. FORCE_INLINE_ATTR void *cpu_ll_get_sp(void)
  32. {
  33. return esp_cpu_get_sp();
  34. }
  35. FORCE_INLINE_ATTR void cpu_ll_init_hwloop(void)
  36. {
  37. ; // Nothing to do. Contents moved to bootloader directly
  38. }
  39. #if SOC_CPU_BREAKPOINTS_NUM > 0
  40. FORCE_INLINE_ATTR void cpu_ll_set_breakpoint(int id, uint32_t pc)
  41. {
  42. esp_cpu_set_breakpoint(id, (const void *)pc);
  43. }
  44. FORCE_INLINE_ATTR void cpu_ll_clear_breakpoint(int id)
  45. {
  46. esp_cpu_clear_breakpoint(id);
  47. }
  48. #endif // SOC_CPU_BREAKPOINTS_NUM > 0
  49. FORCE_INLINE_ATTR __attribute__((pure)) uint32_t cpu_ll_ptr_to_pc(const void *addr)
  50. {
  51. return ((uint32_t) addr);
  52. }
  53. FORCE_INLINE_ATTR __attribute__((pure)) void *cpu_ll_pc_to_ptr(uint32_t pc)
  54. {
  55. return esp_cpu_pc_to_addr(pc);
  56. }
  57. FORCE_INLINE_ATTR void cpu_ll_set_watchpoint(int id,
  58. const void* addr,
  59. size_t size,
  60. bool on_read,
  61. bool on_write)
  62. {
  63. esp_cpu_watchpoint_trigger_t trigger;
  64. if (on_read && on_write) {
  65. trigger = ESP_CPU_WATCHPOINT_ACCESS;
  66. } else if (on_read) {
  67. trigger = ESP_CPU_WATCHPOINT_LOAD;
  68. } else {
  69. trigger = ESP_CPU_WATCHPOINT_STORE;
  70. }
  71. esp_cpu_set_watchpoint(id, addr, size, trigger);
  72. }
  73. FORCE_INLINE_ATTR void cpu_ll_clear_watchpoint(int id)
  74. {
  75. esp_cpu_clear_watchpoint(id);
  76. }
  77. FORCE_INLINE_ATTR bool cpu_ll_is_debugger_attached(void)
  78. {
  79. return esp_cpu_dbgr_is_attached();
  80. }
  81. FORCE_INLINE_ATTR void cpu_ll_break(void)
  82. {
  83. esp_cpu_dbgr_break();
  84. }
  85. FORCE_INLINE_ATTR void cpu_ll_set_vecbase(const void *base)
  86. {
  87. esp_cpu_intr_set_ivt_addr(base);
  88. }
  89. FORCE_INLINE_ATTR void cpu_ll_waiti(void)
  90. {
  91. esp_cpu_wait_for_intr();
  92. }
  93. FORCE_INLINE_ATTR void cpu_ll_compare_and_set_native(volatile uint32_t *addr, uint32_t compare, uint32_t *set)
  94. {
  95. #ifdef __clang_analyzer__
  96. //Teach clang-tidy that "addr" and "set" cannot be const as they can both be updated by S32C1I instruction
  97. volatile uint32_t temp;
  98. temp = *addr;
  99. *addr = temp;
  100. temp = *set;
  101. *set = temp;
  102. #endif
  103. #ifdef __XTENSA__
  104. #if XCHAL_HAVE_S32C1I
  105. __asm__ __volatile__ (
  106. "WSR %2, SCOMPARE1 \n"
  107. "S32C1I %0, %1, 0 \n"
  108. :"=r"(*set)
  109. :"r"(addr), "r"(compare), "0"(*set)
  110. );
  111. #else // XCHAL_HAVE_S32C1I
  112. uint32_t old_value;
  113. // No S32C1I, so do this by disabling and re-enabling interrupts (slower)
  114. uint32_t intlevel;
  115. __asm__ __volatile__ ("rsil %0, " XTSTR(XCHAL_EXCM_LEVEL) "\n"
  116. : "=r"(intlevel));
  117. old_value = *addr;
  118. if (old_value == compare) {
  119. *addr = *set;
  120. }
  121. __asm__ __volatile__ ("memw \n"
  122. "wsr %0, ps\n"
  123. :: "r"(intlevel));
  124. *set = old_value;
  125. #endif // XCHAL_HAVE_S32C1I
  126. #else
  127. uint32_t old_value;
  128. unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
  129. old_value = *addr;
  130. if (old_value == compare) {
  131. *addr = *set;
  132. }
  133. RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
  134. *set = old_value;
  135. #endif
  136. }
  137. #ifdef __cplusplus
  138. }
  139. #endif