• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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