1 /*
2 * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "string.h"
8 #include "freertos/FreeRTOS.h"
9 #include "SEGGER_RTT.h"
10 #include "SEGGER_SYSVIEW.h"
11 #include "SEGGER_SYSVIEW_Conf.h"
12
13 #include "esp_app_trace.h"
14 #include "esp_log.h"
15
16 const static char *TAG = "segger_rtt";
17
18 #define SYSVIEW_EVENTS_BUF_SZ 255U
19
20 // size of down channel data buf
21 #define SYSVIEW_DOWN_BUF_SIZE 32
22 #define SEGGER_STOP_WAIT_TMO 1000000 //us
23 #if CONFIG_APPTRACE_SV_BUF_WAIT_TMO == -1
24 #define SEGGER_HOST_WAIT_TMO ESP_APPTRACE_TMO_INFINITE
25 #else
26 #define SEGGER_HOST_WAIT_TMO CONFIG_APPTRACE_SV_BUF_WAIT_TMO
27 #endif
28
29 static uint8_t s_events_buf[SYSVIEW_EVENTS_BUF_SZ];
30 static uint16_t s_events_buf_filled;
31 static uint8_t s_down_buf[SYSVIEW_DOWN_BUF_SIZE];
32
33 /*********************************************************************
34 *
35 * Public code
36 *
37 **********************************************************************
38 */
39
40 /*********************************************************************
41 *
42 * SEGGER_RTT_ESP_FlushNoLock()
43 *
44 * Function description
45 * Flushes buffered events.
46 *
47 * Parameters
48 * min_sz Threshold for flushing data. If current filling level is above this value, data will be flushed. TRAX destinations only.
49 * tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
50 *
51 * Return value
52 * None.
53 */
SEGGER_RTT_ESP_FlushNoLock(unsigned long min_sz,unsigned long tmo)54 void SEGGER_RTT_ESP_FlushNoLock(unsigned long min_sz, unsigned long tmo)
55 {
56 esp_err_t res;
57 if (s_events_buf_filled > 0) {
58 res = esp_apptrace_write(ESP_APPTRACE_DEST_TRAX, s_events_buf, s_events_buf_filled, tmo);
59 if (res != ESP_OK) {
60 ESP_LOGE(TAG, "Failed to flush buffered events (%d)!\n", res);
61 }
62 }
63 // flush even if we failed to write buffered events, because no new events will be sent after STOP
64 res = esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, min_sz, tmo);
65 if (res != ESP_OK) {
66 ESP_LOGE(TAG, "Failed to flush apptrace data (%d)!\n", res);
67 }
68 s_events_buf_filled = 0;
69 }
70
71 /*********************************************************************
72 *
73 * SEGGER_RTT_ESP_Flush()
74 *
75 * Function description
76 * Flushes buffered events.
77 *
78 * Parameters
79 * min_sz Threshold for flushing data. If current filling level is above this value, data will be flushed. TRAX destinations only.
80 * tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
81 *
82 * Return value
83 * None.
84 */
SEGGER_RTT_ESP_Flush(unsigned long min_sz,unsigned long tmo)85 void SEGGER_RTT_ESP_Flush(unsigned long min_sz, unsigned long tmo)
86 {
87 SEGGER_SYSVIEW_LOCK();
88 SEGGER_RTT_ESP_FlushNoLock(min_sz, tmo);
89 SEGGER_SYSVIEW_UNLOCK();
90 }
91
92 /*********************************************************************
93 *
94 * SEGGER_RTT_ReadNoLock()
95 *
96 * Function description
97 * Reads characters from SEGGER real-time-terminal control block
98 * which have been previously stored by the host.
99 * Do not lock against interrupts and multiple access.
100 *
101 * Parameters
102 * BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal").
103 * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to.
104 * BufferSize Size of the target application buffer.
105 *
106 * Return value
107 * Number of bytes that have been read.
108 */
SEGGER_RTT_ReadNoLock(unsigned BufferIndex,void * pData,unsigned BufferSize)109 unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) {
110 uint32_t size = BufferSize;
111 esp_err_t res = esp_apptrace_read(ESP_APPTRACE_DEST_TRAX, pData, &size, 0);
112 if (res != ESP_OK) {
113 return 0;
114 }
115 return size;
116 }
117
118 /*********************************************************************
119 *
120 * SEGGER_RTT_WriteSkipNoLock
121 *
122 * Function description
123 * Stores a specified number of characters in SEGGER RTT
124 * control block which is then read by the host.
125 * SEGGER_RTT_WriteSkipNoLock does not lock the application and
126 * skips all data, if the data does not fit into the buffer.
127 *
128 * Parameters
129 * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
130 * pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
131 * NumBytes Number of bytes to be stored in the SEGGER RTT control block.
132 *
133 * Return value
134 * Number of bytes which have been stored in the "Up"-buffer.
135 *
136 * Notes
137 * (1) If there is not enough space in the "Up"-buffer, all data is dropped.
138 * (2) For performance reasons this function does not call Init()
139 * and may only be called after RTT has been initialized.
140 * Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
141 */
SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex,const void * pBuffer,unsigned NumBytes)142 unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
143 uint8_t *pbuf = (uint8_t *)pBuffer;
144 uint8_t event_id = *pbuf;
145
146 if (NumBytes > SYSVIEW_EVENTS_BUF_SZ) {
147 ESP_LOGE(TAG, "Too large event %u bytes!", NumBytes);
148 return 0;
149 }
150 if (cpu_hal_get_core_id()) { // dual core specific code
151 // use the highest - 1 bit of event ID to indicate core ID
152 // the highest bit can not be used due to event ID encoding method
153 // this reduces supported ID range to [0..63] (for 1 byte IDs) plus [128..16383] (for 2 bytes IDs)
154 if (*pbuf & 0x80) { // 2 bytes ID
155 *(pbuf + 1) |= (1 << 6);
156 } else if (NumBytes != 10 || *pbuf != 0) { // ignore sync sequence
157 *pbuf |= (1 << 6);
158 }
159 }
160 if (s_events_buf_filled + NumBytes > SYSVIEW_EVENTS_BUF_SZ) {
161 esp_err_t res = esp_apptrace_write(ESP_APPTRACE_DEST_TRAX, s_events_buf, s_events_buf_filled, SEGGER_HOST_WAIT_TMO);
162 if (res != ESP_OK) {
163 return 0; // skip current data buffer only, accumulated events are kept
164 }
165 s_events_buf_filled = 0;
166 }
167 memcpy(&s_events_buf[s_events_buf_filled], pBuffer, NumBytes);
168 s_events_buf_filled += NumBytes;
169 if (event_id == SYSVIEW_EVTID_TRACE_STOP) {
170 SEGGER_RTT_ESP_FlushNoLock(0, SEGGER_STOP_WAIT_TMO);
171 }
172 return NumBytes;
173 }
174
175 /*********************************************************************
176 *
177 * SEGGER_RTT_ConfigUpBuffer
178 *
179 * Function description
180 * Run-time configuration of a specific up-buffer (T->H).
181 * Buffer to be configured is specified by index.
182 * This includes: Buffer address, size, name, flags, ...
183 *
184 * Parameters
185 * BufferIndex Index of the buffer to configure.
186 * sName Pointer to a constant name string.
187 * pBuffer Pointer to a buffer to be used.
188 * BufferSize Size of the buffer.
189 * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message).
190 *
191 * Return value
192 * >= 0 - O.K.
193 * < 0 - Error
194 *
195 * Additional information
196 * Buffer 0 is configured on compile-time.
197 * May only be called once per buffer.
198 * Buffer name and flags can be reconfigured using the appropriate functions.
199 */
SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex,const char * sName,void * pBuffer,unsigned BufferSize,unsigned Flags)200 int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
201 s_events_buf_filled = 0;
202 return 0;
203 }
204
205 /*********************************************************************
206 *
207 * SEGGER_RTT_ConfigDownBuffer
208 *
209 * Function description
210 * Run-time configuration of a specific down-buffer (H->T).
211 * Buffer to be configured is specified by index.
212 * This includes: Buffer address, size, name, flags, ...
213 *
214 * Parameters
215 * BufferIndex Index of the buffer to configure.
216 * sName Pointer to a constant name string.
217 * pBuffer Pointer to a buffer to be used.
218 * BufferSize Size of the buffer.
219 * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message).
220 *
221 * Return value
222 * >= 0 O.K.
223 * < 0 Error
224 *
225 * Additional information
226 * Buffer 0 is configured on compile-time.
227 * May only be called once per buffer.
228 * Buffer name and flags can be reconfigured using the appropriate functions.
229 */
SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex,const char * sName,void * pBuffer,unsigned BufferSize,unsigned Flags)230 int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
231 esp_apptrace_down_buffer_config(s_down_buf, sizeof(s_down_buf));
232 return 0;
233 }
234
235 /*************************** End of file ****************************/
236