1 /*
2  * Trace Recorder for Tracealyzer v4.9.2
3  * Copyright 2023 Percepio AB
4  * www.percepio.com
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  *
8  * The interface definitions for trace streaming ("stream ports").
9  * This "stream port" sets up the recorder to use ARM ITM as streaming channel.
10  *
11  * To setup Keil uVision for ITM tracing with a Keil ULINKpro (or ULINKplus),
12  * see Percepio Application Note PA-021, available at
13  * https://percepio.com/2018/05/04/keil-itm-support/
14  *
15  * To setup IAR Embedded Workbench for ITM tracing with an IAR I-Jet,
16  * see Percepio Application Note PA-023, https://percepio.com/iar
17  *
18  * NOTE: This stream port may block the application in case the ITM port
19  * is not ready for more data (the TPIU FIFO has become full). This is
20  * necessary to avoid data loss, as the TPIU FIFO is often quite small.
21  *
22  * --- Direct vs. Indirect ITM streaming ---
23  * Direct streaming: By default, this stream port writes directly to the ITM
24  * register mode without any RAM buffer. This assumes you have a fast debug
25  * probe, like aKeil ULINKpro or IAR I-Jet, to avoid excessive blocking.
26  * In case the ITM blocking appears to disturb your application, make sure your
27  * debugger is configured for maximum performance, as described in the above
28  * Application Nodes.
29  *
30  * Indirect streaming: If direct streaming gives too much overhead, you may
31  * instead try indirect ITM streaming. This is done by enabling the internal
32  * RAM buffer, like below. This reconfigures the recorder to store the events
33  * in the internal RAM buffer instead of writing them directly to the ITM port.
34  *
35  * Set TRC_STREAM_PORT_USE_INTERNAL_BUFFER to 1 to use the indirect mode.
36  *
37  * This increases RAM usage but eliminates peaks in the trace data rate.
38  * Moreover, the ITM writes are then performed in a separate task (TzCtrl).
39  * You find relevant settings (buffer size etc.) in trcStreamingConfig.h.
40  *
41  * See also https://percepio.com/2018/10/11/tuning-your-custom-trace-streaming
42  *
43  * --- One-way vs. Two-way Communication ---
44  * The ITM port only provides one-way communication, from target to host.
45  * This is sufficient if you start the tracing from the target application,
46  * using vTraceEnable(TRC_START). Just make sure to start the Tracealyzer
47  * recording before you start the target system.
48  *
49  * In case you prefer to interactively start and stop the tracing from the host
50  * computer, you need two-way communication to send commands to the recorder.
51  * This is possible by writing such "start" and "stop" commands to a special
52  * buffer, monitored by the recorder library, using the debugger IDE.
53  * See trcStreamingPort.c and also the example macro for Keil uVision
54  * (Keil-uVision-Tracealyzer-ITM-Exporter.ini).
55  */
56 
57 #ifndef TRC_STREAM_PORT_H
58 #define TRC_STREAM_PORT_H
59 
60 #if (TRC_USE_TRACEALYZER_RECORDER == 1)
61 
62 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
63 
64 #include <stdint.h>
65 #include <trcTypes.h>
66 #include <trcStreamPortConfig.h>
67 
68 #ifdef __cplusplus
69 extern "C" {
70 #endif
71 
72 #if (!defined(TRC_CFG_STREAM_PORT_ITM_PORT) || (TRC_CFG_STREAM_PORT_ITM_PORT) < 0) || ((TRC_CFG_STREAM_PORT_ITM_PORT) > 31)
73 #error "Invalid ITM port defined in trcStreamPortConfig.h."
74 #endif
75 
76 /* Important for the ITM port - no RAM buffer, direct writes. In most other ports this can be skipped (default is 1) */
77 #define TRC_USE_INTERNAL_BUFFER (TRC_CFG_STREAM_PORT_USE_INTERNAL_BUFFER)
78 
79 #define TRC_INTERNAL_EVENT_BUFFER_WRITE_MODE (TRC_CFG_STREAM_PORT_INTERNAL_BUFFER_WRITE_MODE)
80 
81 #define TRC_INTERNAL_EVENT_BUFFER_TRANSFER_MODE (TRC_CFG_STREAM_PORT_INTERNAL_BUFFER_TRANSFER_MODE)
82 
83 #define TRC_INTERNAL_BUFFER_CHUNK_SIZE (TRC_CFG_STREAM_PORT_INTERNAL_BUFFER_CHUNK_SIZE)
84 
85 #define TRC_INTERNAL_BUFFER_CHUNK_TRANSFER_AGAIN_SIZE_LIMIT (TRC_CFG_STREAM_PORT_INTERNAL_BUFFER_CHUNK_TRANSFER_AGAIN_SIZE_LIMIT)
86 
87 #define TRC_INTERNAL_BUFFER_CHUNK_TRANSFER_AGAIN_COUNT_LIMIT (TRC_CFG_STREAM_PORT_INTERNAL_BUFFER_CHUNK_TRANSFER_AGAIN_COUNT_LIMIT)
88 
89 /* Aligned */
90 #define TRC_STREAM_PORT_INTERNAL_BUFFER_SIZE ((((TRC_CFG_STREAM_PORT_INTERNAL_BUFFER_SIZE) + sizeof(TraceUnsignedBaseType_t) - 1) / sizeof(TraceUnsignedBaseType_t)) * sizeof(TraceUnsignedBaseType_t))
91 
92 typedef struct TraceStreamPortBuffer	/* Aligned */
93 {
94 #if (TRC_USE_INTERNAL_BUFFER == 1)
95 	uint8_t bufferInternal[TRC_STREAM_PORT_INTERNAL_BUFFER_SIZE];
96 #endif
97 	uint8_t buffer[sizeof(TraceUnsignedBaseType_t)];
98 } TraceStreamPortBuffer_t;
99 
100 /**
101  *
102  */
103 traceResult prvTraceItmWrite(void* ptrData, uint32_t size, int32_t* ptrBytesWritten);
104 
105 /**
106  *
107  */
108 traceResult prvTraceItmRead(void* ptrData, uint32_t uiSize, int32_t* piBytesRead);
109 
110 /**
111  *
112  */
113 traceResult xTraceStreamPortInitialize(TraceStreamPortBuffer_t* pxBuffer);
114 
115 /**
116  * @brief Allocates data from the stream port.
117  *
118  * @param[in] uiSize Allocation size
119  * @param[out] ppvData Allocation data pointer
120  *
121  * @retval TRC_FAIL Allocate failed
122  * @retval TRC_SUCCESS Success
123  */
124 #if (TRC_USE_INTERNAL_BUFFER == 1)
125 	#if (TRC_INTERNAL_EVENT_BUFFER_WRITE_MODE == TRC_INTERNAL_EVENT_BUFFER_OPTION_WRITE_MODE_COPY)
126 		#define xTraceStreamPortAllocate(uiSize, ppvData) ((void)(uiSize), xTraceStaticBufferGet(ppvData))
127 	#else
128 		#define xTraceStreamPortAllocate(uiSize, ppvData) ((void)(uiSize), xTraceInternalEventBufferAlloc(uiSize, ppvData))
129 	#endif
130 #else
131 	#define xTraceStreamPortAllocate(uiSize, ppvData) ((void)(uiSize), xTraceStaticBufferGet(ppvData))
132 #endif
133 
134 /**
135  * @brief Commits data to the stream port, depending on the implementation/configuration of the
136  * stream port this data might be directly written to the stream port interface, buffered, or
137  * something else.
138  *
139  * @param[in] pvData Data to commit
140  * @param[in] uiSize Data to commit size
141  * @param[out] piBytesCommitted Bytes committed
142  *
143  * @retval TRC_FAIL Commit failed
144  * @retval TRC_SUCCESS Success
145  */
146 #if (TRC_USE_INTERNAL_BUFFER == 1)
147 	#if (TRC_INTERNAL_EVENT_BUFFER_WRITE_MODE == TRC_INTERNAL_EVENT_BUFFER_OPTION_WRITE_MODE_COPY)
148 		#define xTraceStreamPortCommit xTraceInternalEventBufferPush
149 	#else
150 		#define xTraceStreamPortCommit xTraceInternalEventBufferAllocCommit
151 	#endif
152 #else
153 	#define xTraceStreamPortCommit xTraceStreamPortWriteData
154 #endif
155 
156 /**
157  * @brief Writes data through the stream port interface.
158  *
159  * @param[in] pvData Data to write
160  * @param[in] uiSize Data to write size
161  * @param[out] piBytesWritten Bytes written
162  *
163  * @retval TRC_FAIL Write failed
164  * @retval TRC_SUCCESS Success
165  */
166 #define xTraceStreamPortWriteData(pvData, uiSize, piBytesWritten) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(prvTraceItmWrite(pvData, uiSize, piBytesWritten), TRC_SUCCESS)
167 
168 #define xTraceStreamPortReadData(pvData, uiSize, piBytesRead) prvTraceItmRead(pvData, uiSize, piBytesRead)
169 
170 #define xTraceStreamPortOnEnable(uiStartOption) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2((void)(uiStartOption), TRC_SUCCESS)
171 
172 #define xTraceStreamPortOnDisable() TRC_COMMA_EXPR_TO_STATEMENT_EXPR_1(TRC_SUCCESS)
173 
174 #define xTraceStreamPortOnTraceBegin() TRC_COMMA_EXPR_TO_STATEMENT_EXPR_1(TRC_SUCCESS)
175 
176 #define xTraceStreamPortOnTraceEnd() TRC_COMMA_EXPR_TO_STATEMENT_EXPR_1(TRC_SUCCESS)
177 
178 #ifdef __cplusplus
179 }
180 #endif
181 
182 #endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/
183 
184 #endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/
185 
186 #endif /* TRC_STREAM_PORT_H */
187