1 /*
2  * Copyright (c) 2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_INCLUDE_LOGGING_LOG_FRONTEND_STMESP_DEMUX_H_
8 #define ZEPHYR_INCLUDE_LOGGING_LOG_FRONTEND_STMESP_DEMUX_H_
9 
10 #include <zephyr/kernel.h>
11 #include <zephyr/sys/mpsc_packet.h>
12 
13 #ifdef __cplusplus
14 extern "C" {
15 #endif
16 
17 /**
18  * @defgroup log_frontend_stmesp_apis Trace and Debug Domain APIs
19  * @{
20  * @}
21  * @defgroup log_frontend_stpesp_demux_apis Logging frontend STMESP Demultiplexer API
22  * @ingroup log_frontend_stmesp_apis
23  * @{
24  */
25 
26 /** @brief Bits used to store major index. */
27 #define LOG_FRONTEND_STMESP_DEMUX_MAJOR_BITS 3
28 
29 /** @brief Bits used to store severity level. */
30 #define LOG_FRONTEND_STMESP_DEMUX_LEVEL_BITS 3
31 
32 /** @brief Bits used to store total length. */
33 #define LOG_FRONTEND_STMESP_DEMUX_TLENGTH_BITS 16
34 
35 /** @brief Bits used to store package length. */
36 #define LOG_FRONTEND_STMESP_DEMUX_PLENGTH_BITS 10
37 
38 /** @brief Maximum number of supported majors. */
39 #define LOG_FRONTEND_STMESP_DEMUX_MAJOR_MAX BIT(LOG_FRONTEND_STMESP_DEMUX_MAJOR_BITS)
40 
41 /** @brief Log message type. */
42 #define LOG_FRONTEND_STMESP_DEMUX_TYPE_LOG 0
43 
44 /** @brief Trace point message type. */
45 #define LOG_FRONTEND_STMESP_DEMUX_TYPE_TRACE_POINT 1
46 
47 /** @brief HW event message type. */
48 #define LOG_FRONTEND_STMESP_DEMUX_TYPE_HW_EVENT 2
49 
50 /** @brief Logging message header. */
51 struct log_frontend_stmesp_demux_log_header {
52 	/** Major index. */
53 	uint32_t major : LOG_FRONTEND_STMESP_DEMUX_MAJOR_BITS;
54 
55 	/** Severity level. */
56 	uint32_t level : LOG_FRONTEND_STMESP_DEMUX_LEVEL_BITS;
57 
58 	/** Total length excluding this header. */
59 	uint32_t total_len : LOG_FRONTEND_STMESP_DEMUX_TLENGTH_BITS;
60 
61 	/** Hexdump data length. */
62 	uint32_t package_len : LOG_FRONTEND_STMESP_DEMUX_PLENGTH_BITS;
63 };
64 
65 /** @brief Union for writing raw data to the logging message header. */
66 union log_frontend_stmesp_demux_header {
67 	/** Log header structure. */
68 	struct log_frontend_stmesp_demux_log_header log;
69 
70 	/** Raw word. */
71 	uint32_t raw;
72 };
73 
74 /** @brief Generic STP demux packet. */
75 struct log_frontend_stmesp_demux_packet_generic {
76 	/** Data for MPSC packet handling. */
77 	MPSC_PBUF_HDR;
78 
79 	/** Type. */
80 	uint64_t type: 2;
81 
82 	/** Flag indicating if packet is valid. */
83 	uint64_t content_invalid: 1;
84 };
85 
86 /** @brief Packet with logging message. */
87 struct log_frontend_stmesp_demux_log {
88 	/** Data for MPSC packet handling. */
89 	MPSC_PBUF_HDR;
90 
91 	/** Type. */
92 	uint64_t type: 2;
93 
94 	/** Flag indicating if packet is valid. */
95 	uint64_t content_invalid: 1;
96 
97 	/** Timestamp. */
98 	uint64_t timestamp: 59;
99 
100 	/** Logging header. */
101 	struct log_frontend_stmesp_demux_log_header hdr;
102 
103 	/** Padding so that data is 8 bytes aligned. */
104 	uint32_t padding;
105 
106 	/** Content. */
107 	uint8_t data[];
108 };
109 
110 /** @brief Packet with trace point. */
111 struct log_frontend_stmesp_demux_trace_point {
112 	/** Data for MPSC packet handling. */
113 	MPSC_PBUF_HDR;
114 
115 	/** Type. */
116 	uint64_t type: 2;
117 
118 	/** Flag indicating if packet is valid. */
119 	uint64_t content_invalid: 1;
120 
121 	/** Flag indicating if trace point includes data. */
122 	uint64_t has_data: 1;
123 
124 	/** Timestamp. 54 bits at 40MHz is >14 years. */
125 	uint64_t timestamp: 54;
126 
127 	/** Major ID. */
128 	uint64_t major: 4;
129 
130 	/** Source ID - used for compressed logging. */
131 	uint16_t source_id;
132 
133 	/** ID */
134 	uint16_t id;
135 
136 	/** Content. */
137 	uint32_t data;
138 };
139 
140 /** @brief Packet with HW event. */
141 struct log_frontend_stmesp_demux_hw_event {
142 	/** Data for MPSC packet handling. */
143 	MPSC_PBUF_HDR;
144 
145 	/** Type. */
146 	uint64_t type: 2;
147 
148 	/** Flag indicating if packet is valid. */
149 	uint64_t content_invalid: 1;
150 
151 	/** Timestamp. */
152 	uint64_t timestamp: 59;
153 
154 	/** HW event ID. */
155 	uint8_t evt;
156 };
157 
158 /** @brief Union of all packet types. */
159 union log_frontend_stmesp_demux_packet {
160 	/** Pointer to generic mpsc_pbuf const packet. */
161 	const union mpsc_pbuf_generic *rgeneric;
162 
163 	/** Pointer to generic mpsc_pbuf packet. */
164 	union mpsc_pbuf_generic *generic;
165 
166 	/** Pointer to the log message. */
167 	struct log_frontend_stmesp_demux_log *log;
168 
169 	/** Pointer to the trace point message. */
170 	struct log_frontend_stmesp_demux_trace_point *trace_point;
171 
172 	/** Pointer to the HW event message. */
173 	struct log_frontend_stmesp_demux_hw_event *hw_event;
174 
175 	/** Pointer to the generic log_frontend_stmesp_demux packet. */
176 	struct log_frontend_stmesp_demux_packet_generic *generic_packet;
177 };
178 
179 /** @brief Demultiplexer configuration. */
180 struct log_frontend_stmesp_demux_config {
181 	/** Array with expected major ID's. */
182 	const uint16_t *m_ids;
183 
184 	/** Array length. Must be not bigger than @ref LOG_FRONTEND_STMESP_DEMUX_MAJOR_MAX. */
185 	uint32_t m_ids_cnt;
186 
187 	/** Buffer for storing source ID's. Used for turbo logging. */
188 	uint32_t *source_id_buf;
189 
190 	/** It must be multiple of number of major ID's count. */
191 	size_t source_id_buf_len;
192 };
193 
194 /** @brief Initialize the demultiplexer.
195  *
196  * @param config Configuration.
197  *
198  * @retval 0 on success.
199  * @retval -EINVAL on invalid configuration.
200  */
201 int log_frontend_stmesp_demux_init(const struct log_frontend_stmesp_demux_config *config);
202 
203 /** @brief Indicate major opcode in the STPv2 stream.
204  *
205  * @param id	Master ID.
206  */
207 void log_frontend_stmesp_demux_major(uint16_t id);
208 
209 /** @brief Indicate channel opcode in the STPv2 stream.
210  *
211  * @param id	Channel ID.
212  */
213 void log_frontend_stmesp_demux_channel(uint16_t id);
214 
215 /** @brief Indicate detected packet start (DMTS).
216  *
217  * @param data	Data. Can be NULL which indicates trace point without data.
218  * @param ts	Timestamp. Can be NULL.
219  */
220 int log_frontend_stmesp_demux_packet_start(uint32_t *data, uint64_t *ts);
221 
222 /** @brief Indicate optimized log message with no arguments.
223  *
224  * @param source_id Source ID.
225  * @param ts	Timestamp. Can be NULL.
226  */
227 int log_frontend_stmesp_demux_log0(uint16_t source_id, uint64_t *ts);
228 
229 /** @brief Indicate source ID.
230  *
231  * @param source_id Source ID.
232  */
233 void log_frontend_stmesp_demux_source_id(uint16_t source_id);
234 
235 /** @brief Indicate timestamp.
236  *
237  * Timestamp is separated from packet start because according to STM spec (3.2.2)
238  * it is possible that timestamp is assigned to a later packet.
239  *
240  * @param ts	Timestamp.
241  */
242 void log_frontend_stmesp_demux_timestamp(uint64_t ts);
243 
244 /** @brief Indicate data.
245  *
246  * @param data	Data buffer.
247  * @param len	Length.
248  */
249 void log_frontend_stmesp_demux_data(uint8_t *data, size_t len);
250 
251 /** @brief Indicate packet end (Flag). */
252 void log_frontend_stmesp_demux_packet_end(void);
253 
254 /** @brief Get number of dropped messages and reset the counter.
255  *
256  * Message can be dropped if there is no room in the packet buffer.
257  *
258  * @return Number of dropped messages.
259  */
260 uint32_t log_frontend_stmesp_demux_get_dropped(void);
261 
262 /** @brief Claim packet.
263  *
264  * Get pointer to the pending packet with logging message. Packet must be freed
265  * using @ref log_frontend_stmesp_demux_free.
266  *
267  * @return Pointer to the packet or NULL.
268  */
269 union log_frontend_stmesp_demux_packet log_frontend_stmesp_demux_claim(void);
270 
271 /** @brief Free previously claimed packet.
272  *
273  * See @ref log_frontend_stmesp_demux_claim.
274  *
275  * @param packet Packet.
276  */
277 void log_frontend_stmesp_demux_free(union log_frontend_stmesp_demux_packet packet);
278 
279 /** @brief Get source name for a turbo log message.
280  *
281  * During a boot cooprocessors (FLPR and PPR) are sending location in memory where
282  * their source data is stored. If application core is an owner of those cores
283  * it has access to that memory and based on chip ID and source ID it can retrieve
284  * the source name.
285  *
286  * @param m_id Major ID.
287  * @param s_id Source ID.
288  *
289  * @return Pointer to a string which is a source name or unknown name if source name
290  *         cannot be retrieved.
291  */
292 const char *log_frontend_stmesp_demux_sname_get(uint32_t m_id, uint16_t s_id);
293 
294 /** @brief Check if there are any started but not completed log messages.
295  *
296  * @retval True There is no pending started log message.
297  * @retval False There is pending message.
298  */
299 bool log_frontend_stmesp_demux_is_idle(void);
300 
301 /** @brief Close any opened messages and mark them as invalid. */
302 void log_frontend_stmesp_demux_reset(void);
303 
304 /** @brief Get maximum buffer utilization.
305  *
306  * @retval Non-negative Maximum buffer utilization.
307  * @retval -ENOTSUP Feature not enabled.
308  */
309 int log_frontend_stmesp_demux_max_utilization(void);
310 
311 /**
312  * @}
313  */
314 
315 #ifdef __cplusplus
316 }
317 #endif
318 
319 #endif /* ZEPHYR_INCLUDE_LOGGING_LOG_FRONTEND_STMESP_DEMUX_H_ */
320