1 /*
2  * Copyright (c) 2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #ifndef ZEPHYR_INCLUDE_LOGGING_LOG_FRONTEND_STMESP_H_
7 #define ZEPHYR_INCLUDE_LOGGING_LOG_FRONTEND_STMESP_H_
8 
9 #include <errno.h>
10 #include <zephyr/types.h>
11 #ifdef CONFIG_LOG_FRONTEND_STMESP
12 #include <zephyr/drivers/misc/coresight/stmesp.h>
13 #endif
14 
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 
19 /** @brief Notify frontend that ETR/STM is ready.
20  *
21  * Log frontend optionally dumps buffered data and start to write to the STM
22  * stimulus port.
23  *
24  * @note Function is applicable only for the domain that performs initial ETR/STM setup.
25  *
26  * @retval 0	on success.
27  * @retval -EIO	if there was an internal failure.
28  */
29 int log_frontend_stmesp_etr_ready(void);
30 
31 /** @brief Hook to be called before going to sleep.
32  *
33  * Hook writes dummy data to the STM Stimulus Port to ensure that all logging
34  * data is flushed.
35  */
36 void log_frontend_stmesp_pre_sleep(void);
37 
38 /** @brief Perform a dummy write to STMESP.
39  *
40  * It can be used to force flushing STM data.
41  */
42 void log_frontend_stmesp_dummy_write(void);
43 
44 /** @brief Trace point
45  *
46  * Write a trace point information using STM. Number of unique trace points is limited
47  * to 32768 - CONFIG_LOG_FRONTEND_STMESP_TP_CHAN_BASE per core.
48  *
49  * @param x Trace point ID.
50  */
log_frontend_stmesp_tp(uint16_t x)51 static inline void log_frontend_stmesp_tp(uint16_t x)
52 {
53 #ifdef CONFIG_LOG_FRONTEND_STMESP
54 	STMESP_Type *port;
55 	int err = stmesp_get_port((uint32_t)x + CONFIG_LOG_FRONTEND_STMESP_TP_CHAN_BASE, &port);
56 
57 	__ASSERT_NO_MSG(err == 0);
58 	if (err == 0) {
59 		stmesp_flag(port, 1, true,
60 			    IS_ENABLED(CONFIG_LOG_FRONTEND_STMESP_GUARANTEED_ACCESS));
61 	}
62 #endif
63 }
64 
65 /** @brief Trace point with 32 bit data.
66  *
67  * Write a trace point information using STM. Number of unique trace points is limited
68  * to 32768 - CONFIG_LOG_FRONTEND_STMESP_TP_CHAN_BASE per core.
69  *
70  * @param x Trace point ID.
71  * @param d Data. 32 bit word.
72  */
log_frontend_stmesp_tp_d32(uint16_t x,uint32_t d)73 static inline void log_frontend_stmesp_tp_d32(uint16_t x, uint32_t d)
74 {
75 #ifdef CONFIG_LOG_FRONTEND_STMESP
76 	STMESP_Type *port;
77 	int err = stmesp_get_port((uint32_t)x + CONFIG_LOG_FRONTEND_STMESP_TP_CHAN_BASE, &port);
78 
79 	__ASSERT_NO_MSG(err == 0);
80 	if (err == 0) {
81 		stmesp_data32(port, d, true, true,
82 			      IS_ENABLED(CONFIG_LOG_FRONTEND_STMESP_GUARANTEED_ACCESS));
83 	}
84 #endif
85 }
86 
87 /** @brief Function called for log message with no arguments when turbo logging is enabled.
88  *
89  * @param source Pointer to the source structure.
90  * @param x Index of the string used for the log message.
91  */
92 void log_frontend_stmesp_log0(const void *source, uint32_t x);
93 
94 /** @brief Function called for log message with one argument when turbo logging is enabled.
95  *
96  * @param source Pointer to the source structure.
97  * @param x Index of the string used for the log message.
98  * @param arg Argument.
99  */
100 void log_frontend_stmesp_log1(const void *source, uint32_t x, uint32_t arg);
101 
102 TYPE_SECTION_START_EXTERN(const char *, log_stmesp_ptr);
103 
104 /** @brief Macro for handling a turbo log message with no arguments.
105  *
106  * @param _source Pointer to the source structure.
107  * @param ... String.
108  */
109 #define LOG_FRONTEND_STMESP_LOG0(_source, ...)                                                     \
110 	do {                                                                                       \
111 		static const char _str[] __in_section(_log_stmesp_str, static, _)                  \
112 			__used __noasan __aligned(sizeof(uint32_t)) = GET_ARG_N(1, __VA_ARGS__);   \
113 		static const char *_str_ptr __in_section(_log_stmesp_ptr, static, _)               \
114 			__used __noasan = _str;                                                    \
115 		uint32_t idx =                                                                     \
116 			((uintptr_t)&_str_ptr - (uintptr_t)TYPE_SECTION_START(log_stmesp_ptr)) /   \
117 			sizeof(void *);                                                            \
118 		log_frontend_stmesp_log0(_source, idx);                                            \
119 	} while (0)
120 
121 /** @brief Macro for handling a turbo log message with one argument.
122  *
123  * @param _source Pointer to the source structure.
124  * @param ... String with one numeric argument.
125  */
126 #define LOG_FRONTEND_STMESP_LOG1(_source, ...)                                                     \
127 	do {                                                                                       \
128 		static const char _str[] __in_section(_log_stmesp_str, static, _)                  \
129 			__used __noasan __aligned(sizeof(uint32_t)) = GET_ARG_N(1, __VA_ARGS__);   \
130 		static const char *_str_ptr __in_section(_log_stmesp_ptr, static, _)               \
131 			__used __noasan = _str;                                                    \
132 		uint32_t idx =                                                                     \
133 			((uintptr_t)&_str_ptr - (uintptr_t)TYPE_SECTION_START(log_stmesp_ptr)) /   \
134 			sizeof(void *);                                                            \
135 		log_frontend_stmesp_log1(_source, idx, (uintptr_t)(GET_ARG_N(2, __VA_ARGS__)));    \
136 	} while (0)
137 
138 #ifdef __cplusplus
139 }
140 #endif
141 
142 #endif /* ZEPHYR_INCLUDE_LOGGING_LOG_FRONTEND_STMESP_H_ */
143