Skip to content

Commit 9d478d7

Browse files
nordic-krchkartben
authored andcommitted
logging: frontends: stmesp_demux: Add support for turbo logs
Add support for handling optimized short log messages (aka turbo logs). There are 2 types of turbo log messages: - No arguments. D16MTS is used for that on channel > 32768 - One numeric argument. DM16 followed by D32MTS is used. Additionally, in order to be able to get source name for log messages coming from owned by cpuapp co-processors (PPR and FLPR) there must be a way of passing location of constant source data from PPR/FLPR to cpuapp which handles ETR data. This method is added in the commit as well. PPR/FLPR sends D32M during the boot with address of constant source data section. Demultiplexer stores those addresses and it is able to retrieve source name for log messages from PPR/FLPR. Signed-off-by: Krzysztof Chruściński <[email protected]>
1 parent 752f8b0 commit 9d478d7

File tree

3 files changed

+232
-18
lines changed

3 files changed

+232
-18
lines changed

include/zephyr/logging/log_frontend_stmesp_demux.h

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,14 @@ struct log_frontend_stmesp_demux_trace_point {
121121
/** Flag indicating if trace point includes data. */
122122
uint64_t has_data: 1;
123123

124-
/** Timestamp. */
125-
uint64_t timestamp: 58;
124+
/** Timestamp. 54 bits at 40MHz is >14 years. */
125+
uint64_t timestamp: 54;
126126

127127
/** Major ID. */
128-
uint16_t major;
128+
uint64_t major: 4;
129+
130+
/** Source ID - used for compressed logging. */
131+
uint16_t source_id;
129132

130133
/** ID */
131134
uint16_t id;
@@ -180,6 +183,12 @@ struct log_frontend_stmesp_demux_config {
180183

181184
/** Array length. Must be not bigger than @ref LOG_FRONTEND_STMESP_DEMUX_MAJOR_MAX. */
182185
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;
183192
};
184193

185194
/** @brief Initialize the demultiplexer.
@@ -210,6 +219,19 @@ void log_frontend_stmesp_demux_channel(uint16_t id);
210219
*/
211220
int log_frontend_stmesp_demux_packet_start(uint32_t *data, uint64_t *ts);
212221

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+
213235
/** @brief Indicate timestamp.
214236
*
215237
* Timestamp is separated from packet start because according to STM spec (3.2.2)
@@ -254,6 +276,21 @@ union log_frontend_stmesp_demux_packet log_frontend_stmesp_demux_claim(void);
254276
*/
255277
void log_frontend_stmesp_demux_free(union log_frontend_stmesp_demux_packet packet);
256278

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+
257294
/** @brief Check if there are any started but not completed log messages.
258295
*
259296
* @retval True There is no pending started log message.

subsys/logging/frontends/log_frontend_stmesp_demux.c

Lines changed: 186 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66

77
#include <zephyr/logging/log_frontend_stmesp_demux.h>
8+
#include <zephyr/logging/log_ctrl.h>
89
#include <zephyr/sys/mpsc_pbuf.h>
910
#include <zephyr/sys/__assert.h>
1011
#include <zephyr/logging/log_msg.h>
@@ -14,6 +15,14 @@ LOG_MODULE_REGISTER(stmesp_demux);
1415
BUILD_ASSERT(sizeof(struct log_frontend_stmesp_demux_log_header) == sizeof(uint32_t),
1516
"Must fit in a word");
1617

18+
#ifndef CONFIG_LOG_FRONTEND_STPESP_TURBO_SOURCE_PORT_ID
19+
#define CONFIG_LOG_FRONTEND_STPESP_TURBO_SOURCE_PORT_ID 0
20+
#endif
21+
22+
#ifndef CONFIG_LOG_FRONTEND_STMESP_TURBO_LOG_BASE
23+
#define CONFIG_LOG_FRONTEND_STMESP_TURBO_LOG_BASE 0x8000
24+
#endif
25+
1726
#define NUM_OF_ACTIVE CONFIG_LOG_FRONTEND_STMESP_DEMUX_ACTIVE_PACKETS
1827
#define M_ID_OFF 16
1928
#define M_ID_MASK (BIT_MASK(16) << M_ID_OFF)
@@ -22,6 +31,10 @@ BUILD_ASSERT(sizeof(struct log_frontend_stmesp_demux_log_header) == sizeof(uint3
2231
#define M_CH_HW_EVENT 0x00800000
2332
#define M_CH_INVALID 0xFFFFFFFF
2433

34+
#define APP_M_ID 0x22
35+
#define FLPR_M_ID 0x2D
36+
#define PPR_M_ID 0x2E
37+
2538
struct log_frontend_stmesp_demux_active_entry {
2639
sys_snode_t node;
2740
uint32_t m_ch;
@@ -30,6 +43,11 @@ struct log_frontend_stmesp_demux_active_entry {
3043
int off;
3144
};
3245

46+
struct log_frontend_stmesp_coop_sources {
47+
uint32_t m_id;
48+
const struct log_source_const_data *log_const;
49+
};
50+
3351
struct log_frontend_stmesp_demux {
3452
/* Pool for active entries. */
3553
struct k_mem_slab mslab;
@@ -46,9 +64,20 @@ struct log_frontend_stmesp_demux {
4664

4765
const uint16_t *m_ids;
4866

49-
uint32_t m_ids_cnt;
67+
uint32_t *source_ids;
68+
69+
uint16_t m_ids_cnt;
70+
71+
uint16_t source_id_len;
5072

5173
uint32_t dropped;
74+
75+
struct log_frontend_stmesp_coop_sources coop_sources[2];
76+
};
77+
78+
struct log_frontend_stmesp_entry_source_pair {
79+
uint16_t entry_id;
80+
uint16_t source_id;
5281
};
5382

5483
static uint32_t buffer[CONFIG_LOG_FRONTEND_STMESP_DEMUX_BUFFER_SIZE]
@@ -64,6 +93,40 @@ static void notify_drop(const struct mpsc_pbuf_buffer *buffer,
6493
demux.dropped++;
6594
}
6695

96+
static void store_source_id(uint16_t m_id, uint16_t entry_id, uint16_t source_id)
97+
{
98+
uint32_t *source_ids_data = &demux.source_ids[m_id * (demux.source_id_len + 1)];
99+
uint32_t *wr_idx = source_ids_data;
100+
struct log_frontend_stmesp_entry_source_pair *source_ids =
101+
(struct log_frontend_stmesp_entry_source_pair *)&source_ids_data[1];
102+
103+
source_ids[*wr_idx].entry_id = entry_id;
104+
source_ids[*wr_idx].source_id = source_id;
105+
*wr_idx = *wr_idx + 1;
106+
if (*wr_idx == (demux.source_id_len)) {
107+
*wr_idx = 0;
108+
}
109+
}
110+
111+
static uint16_t get_source_id(uint16_t m_id, uint16_t entry_id)
112+
{
113+
uint32_t *source_ids_data = &demux.source_ids[m_id * (demux.source_id_len + 1)];
114+
int32_t rd_idx = source_ids_data[0];
115+
uint32_t cnt = demux.source_id_len;
116+
struct log_frontend_stmesp_entry_source_pair *source_ids =
117+
(struct log_frontend_stmesp_entry_source_pair *)&source_ids_data[1];
118+
119+
do {
120+
rd_idx = (rd_idx == 0) ? (demux.source_id_len - 1) : (rd_idx - 1);
121+
if (source_ids[rd_idx].entry_id == entry_id) {
122+
return source_ids[rd_idx].source_id;
123+
}
124+
cnt--;
125+
} while (cnt);
126+
127+
return 0;
128+
}
129+
67130
static uint32_t calc_wlen(uint32_t total_len)
68131
{
69132
return DIV_ROUND_UP(ROUND_UP(total_len, Z_LOG_MSG_ALIGNMENT), sizeof(uint32_t));
@@ -116,6 +179,8 @@ int log_frontend_stmesp_demux_init(const struct log_frontend_stmesp_demux_config
116179
demux.dropped = 0;
117180
demux.curr_m_ch = M_CH_INVALID;
118181
demux.curr = NULL;
182+
demux.source_ids = config->source_id_buf;
183+
demux.source_id_len = config->source_id_buf_len / config->m_ids_cnt - 1;
119184

120185
err = k_mem_slab_init(&demux.mslab, slab_buf,
121186
sizeof(struct log_frontend_stmesp_demux_active_entry),
@@ -194,8 +259,41 @@ static uint8_t get_major_id(uint16_t m_id)
194259
return 0;
195260
}
196261

197-
static void log_frontend_stmesp_demux_trace_point(uint16_t m_id, uint16_t id, uint64_t *ts,
198-
uint32_t *data)
262+
static void store_turbo_log0(uint16_t m_id, uint16_t id, uint64_t *ts, uint16_t source_id)
263+
{
264+
struct log_frontend_stmesp_demux_trace_point packet = {
265+
.valid = 1,
266+
.type = LOG_FRONTEND_STMESP_DEMUX_TYPE_TRACE_POINT,
267+
.content_invalid = 0,
268+
.has_data = 0,
269+
.timestamp = ts ? *ts : 0,
270+
.major = m_id,
271+
.source_id = source_id,
272+
.id = id,
273+
.data = 0};
274+
static const size_t wlen = sizeof(packet) / sizeof(uint32_t);
275+
276+
mpsc_pbuf_put_data(&demux.pbuf, (const uint32_t *)&packet, wlen);
277+
}
278+
279+
static void store_turbo_log1(uint16_t m_id, uint16_t id, uint64_t *ts, uint32_t data)
280+
{
281+
struct log_frontend_stmesp_demux_trace_point packet = {
282+
.valid = 1,
283+
.type = LOG_FRONTEND_STMESP_DEMUX_TYPE_TRACE_POINT,
284+
.content_invalid = 0,
285+
.has_data = 0,
286+
.timestamp = ts ? *ts : 0,
287+
.major = m_id,
288+
.source_id = get_source_id(m_id, id),
289+
.id = id,
290+
.data = data};
291+
static const size_t wlen = sizeof(packet) / sizeof(uint32_t);
292+
293+
mpsc_pbuf_put_data(&demux.pbuf, (const uint32_t *)&packet, wlen);
294+
}
295+
296+
static void store_tracepoint(uint16_t m_id, uint16_t id, uint64_t *ts, uint32_t *data)
199297
{
200298
struct log_frontend_stmesp_demux_trace_point packet = {.valid = 1,
201299
.type = LOG_FRONTEND_STMESP_DEMUX_TYPE_TRACE_POINT,
@@ -252,6 +350,69 @@ static void garbage_collector(uint32_t now)
252350
}
253351
}
254352

353+
int log_frontend_stmesp_demux_log0(uint16_t source_id, uint64_t *ts)
354+
{
355+
if (skip) {
356+
return 0;
357+
}
358+
359+
if (demux.curr_m_ch == M_CH_INVALID) {
360+
return -EINVAL;
361+
}
362+
363+
if (demux.curr != NULL) {
364+
/* Previous package was incompleted. Finish it and potentially
365+
* mark as incompleted if not all data is received.
366+
*/
367+
log_frontend_stmesp_demux_packet_end();
368+
return -EINVAL;
369+
}
370+
371+
uint16_t ch = demux.curr_m_ch & C_ID_MASK;
372+
uint16_t m = get_major_id(demux.curr_m_ch >> M_ID_OFF);
373+
374+
if (ch < CONFIG_LOG_FRONTEND_STMESP_TURBO_LOG_BASE) {
375+
return -EINVAL;
376+
}
377+
378+
store_turbo_log0(m, ch, ts, source_id);
379+
380+
return 1;
381+
}
382+
383+
void log_frontend_stmesp_demux_source_id(uint16_t data)
384+
{
385+
if (skip) {
386+
return;
387+
}
388+
389+
if (demux.curr_m_ch == M_CH_INVALID) {
390+
return;
391+
}
392+
393+
uint16_t ch = demux.curr_m_ch & C_ID_MASK;
394+
uint16_t m = get_major_id(demux.curr_m_ch >> M_ID_OFF);
395+
396+
store_source_id(m, ch, data);
397+
}
398+
399+
const char *log_frontend_stmesp_demux_sname_get(uint32_t m_id, uint16_t s_id)
400+
{
401+
if (!IS_ENABLED(CONFIG_LOG_FRONTEND_STMESP_TURBO_LOG)) {
402+
return "";
403+
}
404+
405+
if (demux.m_ids[m_id] == APP_M_ID) {
406+
return log_source_name_get(0, s_id);
407+
} else if (m_id == demux.coop_sources[0].m_id) {
408+
return demux.coop_sources[0].log_const[s_id].name;
409+
} else if (m_id == demux.coop_sources[1].m_id) {
410+
return demux.coop_sources[1].log_const[s_id].name;
411+
}
412+
413+
return "unknown";
414+
}
415+
255416
int log_frontend_stmesp_demux_packet_start(uint32_t *data, uint64_t *ts)
256417
{
257418
if (skip) {
@@ -273,6 +434,23 @@ int log_frontend_stmesp_demux_packet_start(uint32_t *data, uint64_t *ts)
273434
return 1;
274435
}
275436

437+
uint16_t ch = demux.curr_m_ch & C_ID_MASK;
438+
uint16_t m = get_major_id(demux.curr_m_ch >> M_ID_OFF);
439+
440+
if (IS_ENABLED(CONFIG_LOG_FRONTEND_STMESP_TURBO_LOG) &&
441+
(ch == CONFIG_LOG_FRONTEND_STPESP_TURBO_SOURCE_PORT_ID)) {
442+
if (demux.m_ids[m] == FLPR_M_ID) {
443+
demux.coop_sources[0].m_id = m;
444+
demux.coop_sources[0].log_const =
445+
(const struct log_source_const_data *)(uintptr_t)*data;
446+
} else if (demux.m_ids[m] == PPR_M_ID) {
447+
demux.coop_sources[1].m_id = m;
448+
demux.coop_sources[1].log_const =
449+
(const struct log_source_const_data *)(uintptr_t)*data;
450+
}
451+
return 0;
452+
}
453+
276454
if (demux.curr != NULL) {
277455
/* Previous package was incompleted. Finish it and potentially
278456
* mark as incompleted if not all data is received.
@@ -281,14 +459,13 @@ int log_frontend_stmesp_demux_packet_start(uint32_t *data, uint64_t *ts)
281459
return -EINVAL;
282460
}
283461

284-
uint16_t ch = demux.curr_m_ch & C_ID_MASK;
285-
uint16_t m = get_major_id(demux.curr_m_ch >> M_ID_OFF);
286-
287462
if (ch >= CONFIG_LOG_FRONTEND_STMESP_TP_CHAN_BASE) {
288-
uint32_t id = (uint32_t)ch - CONFIG_LOG_FRONTEND_STMESP_TP_CHAN_BASE;
289-
290463
/* Trace point */
291-
log_frontend_stmesp_demux_trace_point(m, id, ts, data);
464+
if (ch >= CONFIG_LOG_FRONTEND_STMESP_TURBO_LOG_BASE) {
465+
store_turbo_log1(m, ch, ts, *data);
466+
} else {
467+
store_tracepoint(m, ch, ts, data);
468+
}
292469

293470
return 1;
294471
}

tests/subsys/logging/log_frontend_stmesp_demux/src/main.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -408,12 +408,12 @@ ZTEST(log_frontend_stmesp_demux_test, test_trace_point)
408408
err = write_trace_point(&m_id1, &c_id1, NULL, t1);
409409
zassert_equal(err, 1);
410410

411-
CLAIM_TRACE_POINT(m_id0, id0, t0, NULL);
412-
CLAIM_TRACE_POINT(m_id0, id0, t0, NULL);
413-
CLAIM_TRACE_POINT(m_id0, id0, t0, &data);
414-
CLAIM_TRACE_POINT(m_id0, id1, t1, &data);
415-
CLAIM_TRACE_POINT(m_id1, id0, t0, NULL);
416-
CLAIM_TRACE_POINT(m_id1, id1, t1, NULL);
411+
CLAIM_TRACE_POINT(m_id0, c_id0, t0, NULL);
412+
CLAIM_TRACE_POINT(m_id0, c_id0, t0, NULL);
413+
CLAIM_TRACE_POINT(m_id0, c_id0, t0, &data);
414+
CLAIM_TRACE_POINT(m_id0, c_id1, t1, &data);
415+
CLAIM_TRACE_POINT(m_id1, c_id0, t0, NULL);
416+
CLAIM_TRACE_POINT(m_id1, c_id1, t1, NULL);
417417

418418
DEMUX_EMPTY();
419419
}

0 commit comments

Comments
 (0)