1 /*********************************************************************
2 * SEGGER Microcontroller GmbH & Co. KG *
3 * The Embedded Experts *
4 **********************************************************************
5 * *
6 * (c) 2015 - 2017 SEGGER Microcontroller GmbH & Co. KG *
7 * *
8 * www.segger.com Support: support@segger.com *
9 * *
10 **********************************************************************
11 * *
12 * SEGGER SystemView * Real-time application analysis *
13 * *
14 **********************************************************************
15 * *
16 * All rights reserved. *
17 * *
18 * SEGGER strongly recommends to not make any changes *
19 * to or modify the source code of this software in order to stay *
20 * compatible with the RTT protocol and J-Link. *
21 * *
22 * Redistribution and use in source and binary forms, with or *
23 * without modification, are permitted provided that the following *
24 * conditions are met: *
25 * *
26 * o Redistributions of source code must retain the above copyright *
27 * notice, this list of conditions and the following disclaimer. *
28 * *
29 * o Redistributions in binary form must reproduce the above *
30 * copyright notice, this list of conditions and the following *
31 * disclaimer in the documentation and/or other materials provided *
32 * with the distribution. *
33 * *
34 * o Neither the name of SEGGER Microcontroller GmbH & Co. KG *
35 * nor the names of its contributors may be used to endorse or *
36 * promote products derived from this software without specific *
37 * prior written permission. *
38 * *
39 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
40 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
41 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
42 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
43 * DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
44 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
45 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
46 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
47 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
48 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
49 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
50 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
51 * DAMAGE. *
52 * *
53 **********************************************************************
54 * *
55 * SystemView version: V2.42 *
56 * *
57 **********************************************************************
58 -------------------------- END-OF-HEADER -----------------------------
59
60 File : SEGGER_SYSVIEW_Config_FreeRTOS.c
61 Purpose : Sample setup configuration of SystemView with FreeRTOS.
62 Revision: $Rev: 3734 $
63 */
64 #include "sdkconfig.h"
65 #include "freertos/FreeRTOS.h"
66 #include "SEGGER_SYSVIEW.h"
67 #include "esp_app_trace.h"
68 #include "esp_app_trace_util.h"
69 #include "esp_intr_alloc.h"
70 #include "soc/soc.h"
71 #include "soc/interrupts.h"
72 #if CONFIG_IDF_TARGET_ESP32
73 #include "esp32/clk.h"
74 #elif CONFIG_IDF_TARGET_ESP32S2
75 #include "esp32s2/clk.h"
76 #elif CONFIG_IDF_TARGET_ESP32S3
77 #include "esp32s3/clk.h"
78 #elif CONFIG_IDF_TARGET_ESP32C3
79 #include "esp32c3/clk.h"
80 #endif
81
82
83 extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI;
84
85 /*********************************************************************
86 *
87 * Defines, configurable
88 *
89 **********************************************************************
90 */
91 // The application name to be displayed in SystemViewer
92 #define SYSVIEW_APP_NAME "FreeRTOS Application"
93
94 // The target device name
95 #define SYSVIEW_DEVICE_NAME CONFIG_IDF_TARGET
96 // The target core name
97 #if CONFIG_IDF_TARGET_ARCH_XTENSA
98 #define SYSVIEW_CORE_NAME "xtensa"
99 #elif CONFIG_IDF_TARGET_ARCH_RISCV
100 #define SYSVIEW_CORE_NAME "riscv"
101 #endif
102
103 // Determine which timer to use as timestamp source
104 #if CONFIG_APPTRACE_SV_TS_SOURCE_CCOUNT
105 #define TS_USE_CCOUNT 1
106 #elif CONFIG_APPTRACE_SV_TS_SOURCE_ESP_TIMER
107 #define TS_USE_ESP_TIMER 1
108 #else
109 #define TS_USE_TIMERGROUP 1
110 #endif
111
112 #if TS_USE_TIMERGROUP
113 #include "driver/timer.h"
114
115 // Timer group timer divisor
116 #define SYSVIEW_TIMER_DIV 2
117
118 // Frequency of the timestamp.
119 #define SYSVIEW_TIMESTAMP_FREQ (esp_clk_apb_freq() / SYSVIEW_TIMER_DIV)
120
121 // Timer ID and group ID
122 #if defined(CONFIG_APPTRACE_SV_TS_SOURCE_TIMER_00) || defined(CONFIG_APPTRACE_SV_TS_SOURCE_TIMER_10)
123 #define TS_TIMER_ID 0
124 #else
125 #define TS_TIMER_ID 1
126 #endif // TIMER_00 || TIMER_01
127
128 #if defined(CONFIG_APPTRACE_SV_TS_SOURCE_TIMER_00) || defined(CONFIG_APPTRACE_SV_TS_SOURCE_TIMER_01)
129 #define TS_TIMER_GROUP 0
130 #else
131 #define TS_TIMER_GROUP 1
132 #endif // TIMER_00 || TIMER_10
133
134 #endif // TS_USE_TIMERGROUP
135
136 #if TS_USE_ESP_TIMER
137 // esp_timer provides 1us resolution
138 #define SYSVIEW_TIMESTAMP_FREQ (1000000)
139 #endif // TS_USE_ESP_TIMER
140
141 #if TS_USE_CCOUNT
142 // CCOUNT is incremented at CPU frequency
143 #if CONFIG_IDF_TARGET_ESP32
144 #define SYSVIEW_TIMESTAMP_FREQ (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ * 1000000)
145 #elif CONFIG_IDF_TARGET_ESP32S2
146 #define SYSVIEW_TIMESTAMP_FREQ (CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ * 1000000)
147 #elif CONFIG_IDF_TARGET_ESP32S3
148 #define SYSVIEW_TIMESTAMP_FREQ (CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ * 1000000)
149 #endif
150 #endif // TS_USE_CCOUNT
151
152 // System Frequency.
153 #define SYSVIEW_CPU_FREQ (esp_clk_cpu_freq())
154
155 // The lowest RAM address used for IDs (pointers)
156 #define SYSVIEW_RAM_BASE (SOC_DROM_LOW)
157
158 #ifdef CONFIG_FREERTOS_TICK_SUPPORT_CORETIMER
159 #if CONFIG_FREERTOS_CORETIMER_0
160 #define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER0_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF)
161 #endif
162 #if CONFIG_FREERTOS_CORETIMER_1
163 #define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER1_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF)
164 #endif
165
166 #elif CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER
167 #define SYSTICK_INTR_ID (ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE)
168 #endif // CONFIG_FREERTOS_TICK_SUPPORT_CORETIMER
169
170 // SystemView is single core specific: it implies that SEGGER_SYSVIEW_LOCK()
171 // disables IRQs (disables rescheduling globally). So we can not use finite timeouts for locks and return error
172 // in case of expiration, because error will not be handled and SEGGER's code will go further implying that
173 // everything is fine, so for multi-core env we have to wait on underlying lock forever
174 #define SEGGER_LOCK_WAIT_TMO ESP_APPTRACE_TMO_INFINITE
175
176 static esp_apptrace_lock_t s_sys_view_lock = {.mux = portMUX_INITIALIZER_UNLOCKED, .int_state = 0};
177
178 /*********************************************************************
179 *
180 * _cbSendSystemDesc()
181 *
182 * Function description
183 * Sends SystemView description strings.
184 */
_cbSendSystemDesc(void)185 static void _cbSendSystemDesc(void) {
186 char irq_str[32];
187 SEGGER_SYSVIEW_SendSysDesc("N="SYSVIEW_APP_NAME",D="SYSVIEW_DEVICE_NAME",C="SYSVIEW_CORE_NAME",O=FreeRTOS");
188 snprintf(irq_str, sizeof(irq_str), "I#%d=SysTick", SYSTICK_INTR_ID);
189 SEGGER_SYSVIEW_SendSysDesc(irq_str);
190 size_t isr_count = sizeof(esp_isr_names)/sizeof(esp_isr_names[0]);
191 for (size_t i = 0; i < isr_count; ++i) {
192 if (esp_isr_names[i] == NULL || (ETS_INTERNAL_INTR_SOURCE_OFF + i) == SYSTICK_INTR_ID)
193 continue;
194 snprintf(irq_str, sizeof(irq_str), "I#%d=%s", ETS_INTERNAL_INTR_SOURCE_OFF + i, esp_isr_names[i]);
195 SEGGER_SYSVIEW_SendSysDesc(irq_str);
196 }
197 }
198
199 /*********************************************************************
200 *
201 * Global functions
202 *
203 **********************************************************************
204 */
SEGGER_SYSVIEW_TS_Init(void)205 static void SEGGER_SYSVIEW_TS_Init(void)
206 {
207 /* We only need to initialize something if we use Timer Group.
208 * esp_timer and ccount can be used as is.
209 */
210 #if TS_USE_TIMERGROUP
211 timer_config_t config = {
212 .alarm_en = 0,
213 .auto_reload = 0,
214 .counter_dir = TIMER_COUNT_UP,
215 .divider = SYSVIEW_TIMER_DIV,
216 .counter_en = 0
217 };
218 /* Configure timer */
219 timer_init(TS_TIMER_GROUP, TS_TIMER_ID, &config);
220 /* Load counter value */
221 timer_set_counter_value(TS_TIMER_GROUP, TS_TIMER_ID, 0x00000000ULL);
222 /* Start counting */
223 timer_start(TS_TIMER_GROUP, TS_TIMER_ID);
224 #endif // TS_USE_TIMERGROUP
225 }
226
SEGGER_SYSVIEW_Conf(void)227 void SEGGER_SYSVIEW_Conf(void) {
228 U32 disable_evts = 0;
229
230 SEGGER_SYSVIEW_TS_Init();
231 SEGGER_SYSVIEW_Init(SYSVIEW_TIMESTAMP_FREQ, SYSVIEW_CPU_FREQ,
232 &SYSVIEW_X_OS_TraceAPI, _cbSendSystemDesc);
233 SEGGER_SYSVIEW_SetRAMBase(SYSVIEW_RAM_BASE);
234
235 #if !CONFIG_APPTRACE_SV_EVT_OVERFLOW_ENABLE
236 disable_evts |= SYSVIEW_EVTMASK_OVERFLOW;
237 #endif
238 #if !CONFIG_APPTRACE_SV_EVT_ISR_ENTER_ENABLE
239 disable_evts |= SYSVIEW_EVTMASK_ISR_ENTER;
240 #endif
241 #if !CONFIG_APPTRACE_SV_EVT_ISR_EXIT_ENABLE
242 disable_evts |= SYSVIEW_EVTMASK_ISR_EXIT;
243 #endif
244 #if !CONFIG_APPTRACE_SV_EVT_TASK_START_EXEC_ENABLE
245 disable_evts |= SYSVIEW_EVTMASK_TASK_START_EXEC;
246 #endif
247 #if !CONFIG_APPTRACE_SV_EVT_TASK_STOP_EXEC_ENABLE
248 disable_evts |= SYSVIEW_EVTMASK_TASK_STOP_EXEC;
249 #endif
250 #if !CONFIG_APPTRACE_SV_EVT_TASK_START_READY_ENABLE
251 disable_evts |= SYSVIEW_EVTMASK_TASK_START_READY;
252 #endif
253 #if !CONFIG_APPTRACE_SV_EVT_TASK_STOP_READY_ENABLE
254 disable_evts |= SYSVIEW_EVTMASK_TASK_STOP_READY;
255 #endif
256 #if !CONFIG_APPTRACE_SV_EVT_TASK_CREATE_ENABLE
257 disable_evts |= SYSVIEW_EVTMASK_TASK_CREATE;
258 #endif
259 #if !CONFIG_APPTRACE_SV_EVT_TASK_TERMINATE_ENABLE
260 disable_evts |= SYSVIEW_EVTMASK_TASK_TERMINATE;
261 #endif
262 #if !CONFIG_APPTRACE_SV_EVT_IDLE_ENABLE
263 disable_evts |= SYSVIEW_EVTMASK_IDLE;
264 #endif
265 #if !CONFIG_APPTRACE_SV_EVT_ISR_TO_SCHED_ENABLE
266 disable_evts |= SYSVIEW_EVTMASK_ISR_TO_SCHEDULER;
267 #endif
268 #if !CONFIG_APPTRACE_SV_EVT_TIMER_ENTER_ENABLE
269 disable_evts |= SYSVIEW_EVTMASK_TIMER_ENTER;
270 #endif
271 #if !CONFIG_APPTRACE_SV_EVT_TIMER_EXIT_ENABLE
272 disable_evts |= SYSVIEW_EVTMASK_TIMER_EXIT;
273 #endif
274 SEGGER_SYSVIEW_DisableEvents(disable_evts);
275 }
276
SEGGER_SYSVIEW_X_GetTimestamp(void)277 U32 SEGGER_SYSVIEW_X_GetTimestamp(void)
278 {
279 #if TS_USE_TIMERGROUP
280 uint64_t ts = 0;
281 timer_get_counter_value(TS_TIMER_GROUP, TS_TIMER_ID, &ts);
282 return (U32) ts; // return lower part of counter value
283 #elif TS_USE_CCOUNT
284 return portGET_RUN_TIME_COUNTER_VALUE();
285 #elif TS_USE_ESP_TIMER
286 return (U32) esp_timer_get_time(); // return lower part of counter value
287 #endif
288 }
289
SEGGER_SYSVIEW_X_RTT_Lock(void)290 void SEGGER_SYSVIEW_X_RTT_Lock(void)
291 {
292 }
293
SEGGER_SYSVIEW_X_RTT_Unlock(void)294 void SEGGER_SYSVIEW_X_RTT_Unlock(void)
295 {
296 }
297
SEGGER_SYSVIEW_X_SysView_Lock(void)298 unsigned SEGGER_SYSVIEW_X_SysView_Lock(void)
299 {
300 esp_apptrace_tmo_t tmo;
301 esp_apptrace_tmo_init(&tmo, SEGGER_LOCK_WAIT_TMO);
302 esp_apptrace_lock_take(&s_sys_view_lock, &tmo);
303 // to be recursive save IRQ status on the stack of the caller to keep it from overwriting
304 return s_sys_view_lock.int_state;
305 }
306
SEGGER_SYSVIEW_X_SysView_Unlock(unsigned int_state)307 void SEGGER_SYSVIEW_X_SysView_Unlock(unsigned int_state)
308 {
309 s_sys_view_lock.int_state = int_state;
310 esp_apptrace_lock_give(&s_sys_view_lock);
311 }
312
313 /*************************** End of file ****************************/
314