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