1 // Copyright 2020 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #pragma once
15
16 #include <stdint.h>
17
18 #include "esp_attr.h"
19
20 #include "soc/soc_caps.h"
21
22 #include "xt_instr_macros.h"
23 #include "xtensa/config/specreg.h"
24 #include "xtensa/config/extreg.h"
25 #include "esp_bit_defs.h"
26 #include "xtensa/config/core.h"
27
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31
cpu_ll_get_core_id(void)32 static inline uint32_t IRAM_ATTR cpu_ll_get_core_id(void)
33 {
34 uint32_t id;
35 asm volatile (
36 "rsr.prid %0\n"
37 "extui %0,%0,13,1"
38 :"=r"(id));
39 return id;
40 }
41
cpu_ll_get_cycle_count(void)42 static inline uint32_t cpu_ll_get_cycle_count(void)
43 {
44 uint32_t result;
45 RSR(CCOUNT, result);
46 return result;
47 }
48
cpu_ll_set_cycle_count(uint32_t val)49 static inline void IRAM_ATTR cpu_ll_set_cycle_count(uint32_t val)
50 {
51 WSR(CCOUNT, val);
52 }
53
cpu_ll_get_sp(void)54 static inline void* cpu_ll_get_sp(void)
55 {
56 void *sp;
57 asm volatile ("mov %0, sp;" : "=r" (sp));
58 return sp;
59 }
60
cpu_ll_init_hwloop(void)61 static inline void cpu_ll_init_hwloop(void)
62 {
63 #if XCHAL_ERRATUM_572
64 uint32_t memctl = XCHAL_CACHE_MEMCTL_DEFAULT;
65 WSR(MEMCTL, memctl);
66 #endif // XCHAL_ERRATUM_572
67 }
68
cpu_ll_set_breakpoint(int id,uint32_t pc)69 static inline void cpu_ll_set_breakpoint(int id, uint32_t pc)
70 {
71 uint32_t en;
72
73 // Set the break address register to the appropriate PC
74 if (id) {
75 WSR(IBREAKA_1, pc);
76 } else {
77 WSR(IBREAKA_0, pc);
78 }
79
80 // Enable the breakpoint using the break enable register
81 RSR(IBREAKENABLE, en);
82 en |= BIT(id);
83 WSR(IBREAKENABLE, en);
84 }
85
cpu_ll_clear_breakpoint(int id)86 static inline void cpu_ll_clear_breakpoint(int id)
87 {
88 uint32_t en = 0;
89 uint32_t pc = 0;
90
91 // Set the break address register to the appropriate PC
92 if (id) {
93 WSR(IBREAKA_1, pc);
94 } else {
95 WSR(IBREAKA_0, pc);
96 }
97
98 // Enable the breakpoint using the break enable register
99 RSR(IBREAKENABLE, en);
100 en &= ~BIT(id);
101 WSR(IBREAKENABLE, en);
102 }
103
cpu_ll_ptr_to_pc(const void * addr)104 static inline uint32_t cpu_ll_ptr_to_pc(const void* addr)
105 {
106 return ((uint32_t) addr);
107 }
108
cpu_ll_pc_to_ptr(uint32_t pc)109 static inline void* cpu_ll_pc_to_ptr(uint32_t pc)
110 {
111 return (void*) ((pc & 0x3fffffffU) | 0x40000000U);
112 }
113
cpu_ll_set_watchpoint(int id,const void * addr,size_t size,bool on_read,bool on_write)114 static inline void cpu_ll_set_watchpoint(int id,
115 const void* addr,
116 size_t size,
117 bool on_read,
118 bool on_write)
119 {
120 uint32_t dbreakc = 0x3F;
121
122 //We support watching 2^n byte values, from 1 to 64. Calculate the mask for that.
123 for (int x = 0; x < 7; x++) {
124 if (size == (size_t)(1U << x)) {
125 break;
126 }
127 dbreakc <<= 1;
128 }
129
130 dbreakc = (dbreakc & 0x3F);
131
132 if (on_read) {
133 dbreakc |= BIT(30);
134 }
135
136 if (on_write) {
137 dbreakc |= BIT(31);
138 }
139
140 // Write the break address register and the size to control
141 // register.
142 if (id) {
143 WSR(DBREAKA_1, (uint32_t) addr);
144 WSR(DBREAKC_1, dbreakc);
145 } else {
146 WSR(DBREAKA_0, (uint32_t) addr);
147 WSR(DBREAKC_0, dbreakc);
148 }
149 }
150
cpu_ll_clear_watchpoint(int id)151 static inline void cpu_ll_clear_watchpoint(int id)
152 {
153 // Clear both break address register and control register
154 if (id) {
155 WSR(DBREAKA_1, 0);
156 WSR(DBREAKC_1, 0);
157 } else {
158 WSR(DBREAKA_0, 0);
159 WSR(DBREAKC_0, 0);
160 }
161 }
162
cpu_ll_is_debugger_attached(void)163 static inline bool cpu_ll_is_debugger_attached(void)
164 {
165 uint32_t dcr = 0;
166 uint32_t reg = DSRSET;
167 RER(reg, dcr);
168 return (dcr&0x1);
169 }
170
cpu_ll_break(void)171 static inline void cpu_ll_break(void)
172 {
173 __asm__ ("break 0,0");
174 }
175
cpu_ll_set_vecbase(const void * vecbase)176 static inline void cpu_ll_set_vecbase(const void* vecbase)
177 {
178 asm volatile ("wsr %0, vecbase" :: "r" (vecbase));
179 }
180
cpu_ll_waiti(void)181 static inline void cpu_ll_waiti(void)
182 {
183 asm volatile ("waiti 0\n");
184 }
185
186 #ifdef __cplusplus
187 }
188 #endif
189