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