Merge pull request #88 from akloniex/unify-logger
logger/rmbox: unify implementation of new logger tool with old rmbox
This commit is contained in:
commit
e37aa3f422
|
@ -1,4 +1,4 @@
|
|||
SUBDIRS = logger rmbox topology eqctl
|
||||
SUBDIRS = rmbox topology eqctl
|
||||
TESTDIR = topology/test
|
||||
|
||||
tests:
|
||||
|
|
|
@ -18,7 +18,6 @@ AC_PROG_CC
|
|||
|
||||
AC_OUTPUT([
|
||||
Makefile
|
||||
logger/Makefile
|
||||
rmbox/Makefile
|
||||
eqctl/Makefile
|
||||
topology/Makefile
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
bin_PROGRAMS = sof_logger
|
||||
|
||||
sof_logger_SOURCES = \
|
||||
logger.c
|
316
logger/logger.c
316
logger/logger.c
|
@ -1,316 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sof/uapi/logging.h>
|
||||
|
||||
#define CEIL(a, b) ((a+b-1)/b)
|
||||
|
||||
/* elf signature params */
|
||||
#define SND_SOF_LOGS_SIG_SIZE 4
|
||||
#define SND_SOF_LOGS_SIG "Logs"
|
||||
|
||||
struct snd_sof_logs_header {
|
||||
/* "Logs" */
|
||||
unsigned char sig[SND_SOF_LOGS_SIG_SIZE];
|
||||
/* address of log entries section */
|
||||
uint32_t base_address;
|
||||
/* amount of bytes following this header */
|
||||
uint32_t data_length;
|
||||
/* offset to first entry in this file */
|
||||
uint32_t data_offset;
|
||||
};
|
||||
|
||||
struct ldc_entry_header {
|
||||
uint32_t level;
|
||||
uint32_t component_id;
|
||||
uint32_t params_num;
|
||||
uint32_t line_idx;
|
||||
uint32_t file_name_len;
|
||||
};
|
||||
|
||||
struct ldc_entry {
|
||||
struct ldc_entry_header header;
|
||||
char *file_name;
|
||||
uint32_t text_len;
|
||||
char *text;
|
||||
uint32_t *params;
|
||||
};
|
||||
|
||||
struct dma_log {
|
||||
struct log_entry_header header;
|
||||
uint32_t address;
|
||||
};
|
||||
|
||||
static int fetch_entry(FILE *f_ldc, FILE *f_in, uint32_t base_address,
|
||||
uint32_t data_offset, struct dma_log dma_log);
|
||||
static void print_table_header(void);
|
||||
static void print_entry_params(struct dma_log dma_log, struct ldc_entry);
|
||||
static void usage(char *name);
|
||||
|
||||
static inline void print_table_header(void)
|
||||
{
|
||||
fprintf(stdout, "%10s %8s %8s %14s %16s %24s\t%s\n",
|
||||
"ADDRESS",
|
||||
"CORE_ID",
|
||||
"LEVEL",
|
||||
"COMPONENT_ID",
|
||||
"TIMESTAMP",
|
||||
"FILE_NAME",
|
||||
"CONTENT");
|
||||
}
|
||||
|
||||
static void print_entry_params(struct dma_log dma_log,
|
||||
struct ldc_entry entry)
|
||||
{
|
||||
fprintf(stdout, "%10x %8u %8u %14u %16lu %20s:%u\t",
|
||||
dma_log.address,
|
||||
dma_log.header.core_id,
|
||||
entry.header.level,
|
||||
entry.header.component_id,
|
||||
dma_log.header.timestamp,
|
||||
entry.file_name,
|
||||
entry.header.line_idx);
|
||||
|
||||
switch (entry.header.params_num){
|
||||
case 0:
|
||||
fprintf(stdout, "%s", entry.text);
|
||||
break;
|
||||
case 1:
|
||||
fprintf(stdout, entry.text, entry.params[0]);
|
||||
break;
|
||||
case 2:
|
||||
fprintf(stdout, entry.text, entry.params[0],
|
||||
entry.params[1]);
|
||||
break;
|
||||
case 3:
|
||||
fprintf(stdout, entry.text, entry.params[0], entry.params[1],
|
||||
entry.params[2]);
|
||||
break;
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
static void usage(char *name)
|
||||
{
|
||||
fprintf(stdout, "Usage %s <option(s)> <file(s)>\n", name);
|
||||
fprintf(stdout, "%s:\t \t\t\tParse traces logs\n", name);
|
||||
fprintf(stdout, "%s:\t -l *.ldc_file\t-i in_file\n", name);
|
||||
fprintf(stdout, "%s:\t -t\t\t\tDisplay dma trace data\n", name);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
static int fetch_entry(FILE *f_ldc, FILE *f_in, uint32_t base_address,
|
||||
uint32_t data_offset, struct dma_log dma_log)
|
||||
{
|
||||
|
||||
struct ldc_entry entry;
|
||||
long int padding;
|
||||
|
||||
uint32_t entry_offset;
|
||||
uint32_t text_len;
|
||||
|
||||
int ret;
|
||||
|
||||
entry.file_name = NULL;
|
||||
entry.text = NULL;
|
||||
entry.params = NULL;
|
||||
|
||||
/* evaluate entry offset in input file */
|
||||
entry_offset = dma_log.address - base_address;
|
||||
|
||||
/* set file position to beginning of processed entry */
|
||||
fseek(f_ldc, entry_offset + data_offset, SEEK_SET);
|
||||
|
||||
/* fetching elf header params */
|
||||
ret = fread(&entry.header, sizeof(entry.header), 1, f_ldc);
|
||||
if (!ret) {
|
||||
ret = -ferror(f_ldc);
|
||||
goto out;
|
||||
}
|
||||
|
||||
entry.file_name = (char *) malloc(entry.header.file_name_len);
|
||||
if (!entry.file_name){
|
||||
fprintf(stderr, "error: can't allocate %d byte for "
|
||||
"entry.file_name\n", entry.header.file_name_len);
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = fread(entry.file_name, sizeof(char), entry.header.file_name_len,
|
||||
f_ldc);
|
||||
if (ret != entry.header.file_name_len) {
|
||||
ret = -ferror(f_ldc);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* padding - sequences of chars are aligned to DWORDS */
|
||||
fseek(f_ldc, CEIL(entry.header.file_name_len, sizeof(uint32_t)) *
|
||||
sizeof(uint32_t) - entry.header.file_name_len, SEEK_CUR);
|
||||
|
||||
/* fetching text length */
|
||||
ret = fread(&entry.text_len, sizeof(entry.text_len), 1, f_ldc);
|
||||
if (!ret) {
|
||||
ret = -ferror(f_ldc);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* fetching text */
|
||||
entry.text = (char *) malloc(entry.text_len);
|
||||
if (entry.text == NULL) {
|
||||
fprintf(stderr, "error: can't allocate %d byte for "
|
||||
"entry.text\n", entry.text_len);
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = fread(entry.text, sizeof(char), entry.text_len, f_ldc);
|
||||
if (ret != entry.text_len) {
|
||||
ret = -ferror(f_ldc);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* fetching entry params from dma dump */
|
||||
entry.params = (uint32_t *) malloc(sizeof(uint32_t) *
|
||||
entry.header.params_num);
|
||||
ret = fread(entry.params, sizeof(uint32_t), entry.header.params_num,
|
||||
f_in);
|
||||
if (ret != entry.header.params_num) {
|
||||
ret = -ferror(f_in);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* printing entry content */
|
||||
print_entry_params(dma_log, entry);
|
||||
|
||||
/* set f_ldc file position to the beginning */
|
||||
rewind(f_ldc);
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
/* free alocated memory */
|
||||
free(entry.params);
|
||||
free(entry.text);
|
||||
free(entry.file_name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int logger_read(const char *in_file, FILE *f_ldc, struct snd_sof_logs_header *snd)
|
||||
{
|
||||
struct dma_log dma_log;
|
||||
FILE *f_in = NULL;
|
||||
int ret = 0;
|
||||
|
||||
f_in = fopen(in_file, "r");
|
||||
|
||||
if (f_in == NULL) {
|
||||
fprintf(stderr, "Error while opening %s. \n", in_file);
|
||||
ret = errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
print_table_header();
|
||||
|
||||
while (!feof(f_in)) {
|
||||
|
||||
/* getting entry parameters from dma dump */
|
||||
ret = fread(&dma_log, sizeof(dma_log), 1, f_in);
|
||||
if (!ret) {
|
||||
ret = -ferror(f_in);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* checking log address */
|
||||
if ((dma_log.address < snd->base_address) ||
|
||||
(dma_log.address > (snd->base_address + snd->data_length)))
|
||||
continue;
|
||||
|
||||
/* fetching entry from elf dump*/
|
||||
ret = fetch_entry(f_ldc, f_in, snd->base_address,
|
||||
snd->data_offset, dma_log);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
if (f_ldc) fclose(f_ldc);
|
||||
if (f_in) fclose(f_in);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct snd_sof_logs_header snd;
|
||||
const char *ldc_file = NULL;
|
||||
const char *in_file = NULL;
|
||||
int opt, trace = 0, ret = 0;
|
||||
FILE *f_ldc = NULL;
|
||||
|
||||
while ((opt = getopt(argc, argv, "l:i:th")) != -1) {
|
||||
switch (opt) {
|
||||
case 'l':
|
||||
ldc_file = optarg;
|
||||
break;
|
||||
case 'i':
|
||||
in_file = optarg;
|
||||
break;
|
||||
case 't':
|
||||
trace = 1;
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
usage(argv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ldc_file) {
|
||||
fprintf(stderr, "error: invalid ldc file.\n");
|
||||
usage(argv[0]);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
f_ldc = fopen(ldc_file, "r");
|
||||
|
||||
if (f_ldc == NULL) {
|
||||
fprintf(stderr, "Error while opening %s. \n", ldc_file);
|
||||
ret = errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* set file positions to the beginning */
|
||||
rewind(f_ldc);
|
||||
|
||||
/* veryfing ldc signature */
|
||||
ret = fread(&snd, sizeof(snd), 1, f_ldc);
|
||||
if (!ret) {
|
||||
ret = -ferror(f_ldc);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (strncmp(snd.sig, SND_SOF_LOGS_SIG, SND_SOF_LOGS_SIG_SIZE)) {
|
||||
fprintf(stderr, "Error: Invalid ldc file signature. \n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* dma trace requested */
|
||||
if (trace)
|
||||
return logger_read("/sys/kernel/debug/sof/trace", f_ldc, &snd);
|
||||
|
||||
/* default option with no infile is to dump errors/debug data */
|
||||
if (!in_file)
|
||||
return logger_read("/sys/kernel/debug/sof/etrace", f_ldc, &snd);
|
||||
|
||||
return logger_read(in_file, f_ldc, &snd);
|
||||
|
||||
out:
|
||||
if (f_ldc) fclose(f_ldc);
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -1,4 +1,12 @@
|
|||
bin_PROGRAMS = rmbox
|
||||
bin_PROGRAMS = rmbox logger
|
||||
|
||||
rmbox_SOURCES = \
|
||||
rmbox.c
|
||||
rmbox.c \
|
||||
rmbox_convert.c
|
||||
|
||||
logger_SOURCES = \
|
||||
rmbox.c \
|
||||
logger_convert.c
|
||||
|
||||
logger_CFLAGS = \
|
||||
-DLOGGER_FORMAT
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* debug log converter interface.
|
||||
*
|
||||
* Copyright (c) 2018, Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <sof/uapi/logging.h>
|
||||
|
||||
#define KNRM "\x1B[0m"
|
||||
#define KRED "\x1B[31m"
|
||||
|
||||
static double to_usecs(uint64_t time, double clk)
|
||||
{
|
||||
/* trace timestamp uses CPU system clock at default 25MHz ticks */
|
||||
// TODO: support variable clock rates
|
||||
return (double)time / clk;
|
||||
}
|
||||
|
||||
struct convert_config {
|
||||
const char *out_file;
|
||||
const char *in_file;
|
||||
FILE *out_fd;
|
||||
FILE *in_fd;
|
||||
double clock;
|
||||
int trace;
|
||||
#ifdef LOGGER_FORMAT
|
||||
const char *ldc_file;
|
||||
FILE* ldc_fd;
|
||||
#endif
|
||||
};
|
||||
|
||||
int convert(struct convert_config *config);
|
|
@ -0,0 +1,286 @@
|
|||
/*
|
||||
* debug log converter, using new logger format.
|
||||
*
|
||||
* Copyright (c) 2018, Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "convert.h"
|
||||
|
||||
#define CEIL(a, b) ((a+b-1)/b)
|
||||
|
||||
/* logs file signature */
|
||||
#define SND_SOF_LOGS_SIG_SIZE 4
|
||||
#define SND_SOF_LOGS_SIG "Logs"
|
||||
|
||||
struct snd_sof_logs_header {
|
||||
/* "Logs" */
|
||||
unsigned char sig[SND_SOF_LOGS_SIG_SIZE];
|
||||
/* address of log entries section */
|
||||
uint32_t base_address;
|
||||
/* amount of bytes following this header */
|
||||
uint32_t data_length;
|
||||
/* offset to first entry in this file */
|
||||
uint32_t data_offset;
|
||||
};
|
||||
|
||||
struct ldc_entry_header {
|
||||
uint32_t level;
|
||||
uint32_t component_id;
|
||||
uint32_t params_num;
|
||||
uint32_t line_idx;
|
||||
uint32_t file_name_len;
|
||||
};
|
||||
|
||||
struct ldc_entry {
|
||||
struct ldc_entry_header header;
|
||||
char *file_name;
|
||||
uint32_t text_len;
|
||||
char *text;
|
||||
uint32_t *params;
|
||||
};
|
||||
|
||||
struct dma_log {
|
||||
struct log_entry_header header;
|
||||
uint32_t address;
|
||||
};
|
||||
|
||||
static inline void print_table_header(FILE *out_fd)
|
||||
{
|
||||
fprintf(out_fd, "%5s %6s %8s %16s %16s %24s\t%s\n",
|
||||
"CORE",
|
||||
"LEVEL",
|
||||
"COMP_ID",
|
||||
"TIMESTAMP",
|
||||
"DELTA",
|
||||
"FILE_NAME",
|
||||
"CONTENT");
|
||||
}
|
||||
|
||||
#define CASE(x) \
|
||||
case(TRACE_CLASS_##x): return #x
|
||||
|
||||
static const char * get_component_name(uint32_t component_id) {
|
||||
switch (component_id) {
|
||||
CASE(IRQ);
|
||||
CASE(IPC);
|
||||
CASE(PIPE);
|
||||
CASE(HOST);
|
||||
CASE(DAI);
|
||||
CASE(DMA);
|
||||
CASE(SSP);
|
||||
CASE(COMP);
|
||||
CASE(WAIT);
|
||||
CASE(LOCK);
|
||||
CASE(MEM);
|
||||
CASE(MIXER);
|
||||
CASE(BUFFER);
|
||||
CASE(VOLUME);
|
||||
CASE(SWITCH);
|
||||
CASE(MUX);
|
||||
CASE(SRC);
|
||||
CASE(TONE);
|
||||
CASE(EQ_FIR);
|
||||
CASE(EQ_IIR);
|
||||
CASE(SA);
|
||||
CASE(DMIC);
|
||||
CASE(POWER);
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static void print_entry_params(FILE *out_fd, struct dma_log dma_log,
|
||||
struct ldc_entry entry, uint64_t last_timestamp, double clock)
|
||||
{
|
||||
float dt = to_usecs(dma_log.header.timestamp - last_timestamp, clock);
|
||||
if (dt < 0 || dt > 1000.0 * 1000.0 * 1000.0)
|
||||
dt = NAN;
|
||||
|
||||
fprintf(out_fd, "%s%5u %6u %8s %16.6f %16.6f %20s:%u\t",
|
||||
entry.header.level == LOG_LEVEL_CRITICAL ? KRED : KNRM,
|
||||
dma_log.header.core_id,
|
||||
entry.header.level,
|
||||
get_component_name(entry.header.component_id),
|
||||
to_usecs(dma_log.header.timestamp, clock),
|
||||
dt,
|
||||
entry.file_name,
|
||||
entry.header.line_idx);
|
||||
|
||||
switch (entry.header.params_num) {
|
||||
case 0:
|
||||
fprintf(out_fd, "%s", entry.text);
|
||||
break;
|
||||
case 1:
|
||||
fprintf(out_fd, entry.text, entry.params[0]);
|
||||
break;
|
||||
case 2:
|
||||
fprintf(out_fd, entry.text, entry.params[0], entry.params[1]);
|
||||
break;
|
||||
case 3:
|
||||
fprintf(out_fd, entry.text, entry.params[0], entry.params[1],
|
||||
entry.params[2]);
|
||||
break;
|
||||
}
|
||||
fprintf(out_fd, "\n");
|
||||
}
|
||||
|
||||
static int fetch_entry(struct convert_config *config, uint32_t base_address,
|
||||
uint32_t data_offset, struct dma_log dma_log, uint64_t *last_timestamp)
|
||||
{
|
||||
struct ldc_entry entry;
|
||||
long int padding;
|
||||
|
||||
uint32_t entry_offset;
|
||||
uint32_t text_len;
|
||||
|
||||
int ret;
|
||||
|
||||
entry.file_name = NULL;
|
||||
entry.text = NULL;
|
||||
entry.params = NULL;
|
||||
|
||||
/* evaluate entry offset in input file */
|
||||
entry_offset = dma_log.address - base_address;
|
||||
|
||||
/* set file position to beginning of processed entry */
|
||||
fseek(config->ldc_fd, entry_offset + data_offset, SEEK_SET);
|
||||
|
||||
/* fetching elf header params */
|
||||
ret = fread(&entry.header, sizeof(entry.header), 1, config->ldc_fd);
|
||||
if (!ret) {
|
||||
ret = -ferror(config->ldc_fd);
|
||||
goto out;
|
||||
}
|
||||
|
||||
entry.file_name = (char *)malloc(entry.header.file_name_len);
|
||||
if (!entry.file_name) {
|
||||
fprintf(stderr, "error: can't allocate %d byte for "
|
||||
"entry.file_name\n", entry.header.file_name_len);
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = fread(entry.file_name, sizeof(char), entry.header.file_name_len,
|
||||
config->ldc_fd);
|
||||
if (ret != entry.header.file_name_len) {
|
||||
ret = -ferror(config->ldc_fd);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* padding - sequences of chars are aligned to DWORDS */
|
||||
fseek(config->ldc_fd, CEIL(entry.header.file_name_len, sizeof(uint32_t)) *
|
||||
sizeof(uint32_t) - entry.header.file_name_len, SEEK_CUR);
|
||||
|
||||
/* fetching text length */
|
||||
ret = fread(&entry.text_len, sizeof(entry.text_len), 1, config->ldc_fd);
|
||||
if (!ret) {
|
||||
ret = -ferror(config->ldc_fd);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* fetching text */
|
||||
entry.text = (char *)malloc(entry.text_len);
|
||||
if (entry.text == NULL) {
|
||||
fprintf(stderr, "error: can't allocate %d byte for "
|
||||
"entry.text\n", entry.text_len);
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = fread(entry.text, sizeof(char), entry.text_len, config->ldc_fd);
|
||||
if (ret != entry.text_len) {
|
||||
ret = -ferror(config->ldc_fd);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* fetching entry params from dma dump */
|
||||
entry.params = (uint32_t *)malloc(sizeof(uint32_t) *
|
||||
entry.header.params_num);
|
||||
ret = fread(entry.params, sizeof(uint32_t), entry.header.params_num,
|
||||
config->in_fd);
|
||||
if (ret != entry.header.params_num) {
|
||||
ret = -ferror(config->in_fd);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* printing entry content */
|
||||
print_entry_params(config->out_fd, dma_log, entry, *last_timestamp,
|
||||
config->clock);
|
||||
*last_timestamp = dma_log.header.timestamp;
|
||||
|
||||
/* set f_ldc file position to the beginning */
|
||||
rewind(config->ldc_fd);
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
/* free alocated memory */
|
||||
free(entry.params);
|
||||
free(entry.text);
|
||||
free(entry.file_name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int logger_read(struct convert_config *config,
|
||||
struct snd_sof_logs_header *snd)
|
||||
{
|
||||
struct dma_log dma_log;
|
||||
int ret = 0;
|
||||
|
||||
print_table_header(config->out_fd);
|
||||
uint64_t last_timestamp = 0;
|
||||
|
||||
while (!feof(config->in_fd)) {
|
||||
/* getting entry parameters from dma dump */
|
||||
ret = fread(&dma_log, sizeof(dma_log), 1, config->in_fd);
|
||||
if (!ret) {
|
||||
return -ferror(config->in_fd);
|
||||
}
|
||||
|
||||
/* checking log address */
|
||||
if ((dma_log.address < snd->base_address) ||
|
||||
dma_log.address > snd->base_address + snd->data_length)
|
||||
continue;
|
||||
|
||||
/* fetching entry from elf dump */
|
||||
ret = fetch_entry(config, snd->base_address, snd->data_offset,
|
||||
dma_log, &last_timestamp);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int convert(struct convert_config *config) {
|
||||
struct snd_sof_logs_header snd;
|
||||
int count, ret = 0;
|
||||
|
||||
count = fread(&snd, sizeof(snd), 1, config->ldc_fd);
|
||||
if (!count) {
|
||||
fprintf(stderr, "Error while reading %s. \n", config->ldc_file);
|
||||
return -ferror(config->ldc_fd);
|
||||
}
|
||||
|
||||
if (strncmp(snd.sig, SND_SOF_LOGS_SIG, SND_SOF_LOGS_SIG_SIZE)) {
|
||||
fprintf(stderr, "Error: Invalid ldc file signature. \n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return logger_read(config, &snd);
|
||||
}
|
399
rmbox/rmbox.c
399
rmbox/rmbox.c
|
@ -12,259 +12,43 @@
|
|||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define KNRM "\x1B[0m"
|
||||
#define KRED "\x1B[31m"
|
||||
|
||||
// TODO: include all this stuff
|
||||
|
||||
#define TRACE_CLASS_IRQ (1 << 24)
|
||||
#define TRACE_CLASS_IPC (2 << 24)
|
||||
#define TRACE_CLASS_PIPE (3 << 24)
|
||||
#define TRACE_CLASS_HOST (4 << 24)
|
||||
#define TRACE_CLASS_DAI (5 << 24)
|
||||
#define TRACE_CLASS_DMA (6 << 24)
|
||||
#define TRACE_CLASS_SSP (7 << 24)
|
||||
#define TRACE_CLASS_COMP (8 << 24)
|
||||
#define TRACE_CLASS_WAIT (9 << 24)
|
||||
#define TRACE_CLASS_LOCK (10 << 24)
|
||||
#define TRACE_CLASS_MEM (11 << 24)
|
||||
#define TRACE_CLASS_MIXER (12 << 24)
|
||||
#define TRACE_CLASS_BUFFER (13 << 24)
|
||||
#define TRACE_CLASS_VOLUME (14 << 24)
|
||||
#define TRACE_CLASS_SWITCH (15 << 24)
|
||||
#define TRACE_CLASS_MUX (16 << 24)
|
||||
#define TRACE_CLASS_SRC (17 << 24)
|
||||
#define TRACE_CLASS_TONE (18 << 24)
|
||||
#define TRACE_CLASS_EQ_FIR (19 << 24)
|
||||
#define TRACE_CLASS_EQ_IIR (20 << 24)
|
||||
#define TRACE_CLASS_SA (21 << 24)
|
||||
#define TRACE_CLASS_DMIC (22 << 24)
|
||||
#define TRACE_CLASS_POWER (23 << 24)
|
||||
#include "convert.h"
|
||||
|
||||
#ifdef LOGGER_FORMAT
|
||||
#define APP_NAME "logger"
|
||||
#else
|
||||
#define APP_NAME "rmbox"
|
||||
#endif
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
|
||||
|
||||
|
||||
#define TRACE_BLOCK_SIZE 8
|
||||
|
||||
static inline char get_char(uint32_t val, int idx)
|
||||
{
|
||||
char c = (val >> (idx * 8)) & 0xff;
|
||||
if (c < '0' || c > 'z')
|
||||
return '.';
|
||||
else
|
||||
return c;
|
||||
}
|
||||
|
||||
static void usage(char *name)
|
||||
{
|
||||
fprintf(stdout, "Usage %s <option(s)> <file(s)>\n", name);
|
||||
fprintf(stdout, "%s:\t \t\t\tDisplay mailbox contents\n", name);
|
||||
fprintf(stdout, "%s:\t -i infile -o outfile\tDump infile contents to outfile\n", name);
|
||||
fprintf(stdout, "%s:\t -c\t\t\tSet timestamp clock in MHz\n", name);
|
||||
fprintf(stdout, "%s:\t -s\t\t\tTake a snapshot of state\n", name);
|
||||
fprintf(stdout, "%s:\t -t\t\t\tDisplay trace data\n", name);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static double to_usecs(uint64_t time, double clk)
|
||||
{
|
||||
/* trace timestamp uses CPU system clock at default 25MHz ticks */
|
||||
// TODO: support variable clock rates
|
||||
return (double)time / clk;
|
||||
}
|
||||
|
||||
static void show_trace(uint64_t val, uint64_t addr, uint64_t *timestamp, double clk)
|
||||
{
|
||||
const char *trace;
|
||||
uint32_t class;
|
||||
uint64_t delta = val - *timestamp;
|
||||
double fdelta = to_usecs(delta, clk);
|
||||
double us = 0.0f;
|
||||
|
||||
/* timestamp or value ? */
|
||||
if ((addr % (TRACE_BLOCK_SIZE * 2)) == 0) {
|
||||
|
||||
delta = val - *timestamp;
|
||||
fdelta = to_usecs(delta, clk);
|
||||
|
||||
/* 64-bit timestamp */
|
||||
us = to_usecs(val, clk);
|
||||
|
||||
/* empty data ? */
|
||||
if (val == 0) {
|
||||
*timestamp = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* detect wrap around */
|
||||
if (fdelta < 1000.0 * 1000.0 * 1000.0)
|
||||
printf("0x%lx [%6.6f]\tdelta [%6.6f]\t", addr,
|
||||
us / 1000000.0 , fdelta / 1000000.0);
|
||||
else
|
||||
printf("0x%lx [%6.6f]\tdelta [********]\t", addr,
|
||||
us / 1000000.0);
|
||||
|
||||
*timestamp = val;
|
||||
return;
|
||||
} else if (*timestamp == 0)
|
||||
return;
|
||||
|
||||
/* check for printable values - otherwise it's a value */
|
||||
if (!isprint((char)(val >> 16)) || !isprint((char)(val >> 8)) || !isprint((char)val)) {
|
||||
printf("value 0x%16.16lx\n", val);
|
||||
return;
|
||||
}
|
||||
|
||||
class = val & 0xff000000;
|
||||
if (class == TRACE_CLASS_IRQ)
|
||||
trace = "irq";
|
||||
else if (class == TRACE_CLASS_IPC)
|
||||
trace = "ipc";
|
||||
else if (class == TRACE_CLASS_PIPE)
|
||||
trace = "pipe";
|
||||
else if (class == TRACE_CLASS_HOST)
|
||||
trace = "host";
|
||||
else if (class == TRACE_CLASS_DAI)
|
||||
trace = "dai";
|
||||
else if (class == TRACE_CLASS_DMA)
|
||||
trace = "dma";
|
||||
else if (class == TRACE_CLASS_SSP)
|
||||
trace = "ssp";
|
||||
else if (class == TRACE_CLASS_COMP)
|
||||
trace = "comp";
|
||||
else if (class == TRACE_CLASS_WAIT)
|
||||
trace = "wait";
|
||||
else if (class == TRACE_CLASS_LOCK)
|
||||
trace = "lock";
|
||||
else if (class == TRACE_CLASS_MEM)
|
||||
trace = "mem";
|
||||
else if (class == TRACE_CLASS_MIXER)
|
||||
trace = "mixer";
|
||||
else if (class == TRACE_CLASS_BUFFER)
|
||||
trace = "buffer";
|
||||
else if (class == TRACE_CLASS_VOLUME)
|
||||
trace = "volume";
|
||||
else if (class == TRACE_CLASS_SWITCH)
|
||||
trace = "switch";
|
||||
else if (class == TRACE_CLASS_MUX)
|
||||
trace = "mux";
|
||||
else if (class == TRACE_CLASS_SRC)
|
||||
trace = "src";
|
||||
else if (class == TRACE_CLASS_TONE)
|
||||
trace = "tone";
|
||||
else if (class == TRACE_CLASS_EQ_FIR)
|
||||
trace = "eq-fir";
|
||||
else if (class == TRACE_CLASS_EQ_IIR)
|
||||
trace = "eq-iir";
|
||||
else if (class == TRACE_CLASS_SA)
|
||||
trace = "sa";
|
||||
else if (class == TRACE_CLASS_DMIC)
|
||||
trace = "dmic";
|
||||
else if (class == TRACE_CLASS_POWER)
|
||||
trace = "pm";
|
||||
else {
|
||||
printf("value 0x%8.8x\n", (uint32_t)val);
|
||||
return;
|
||||
}
|
||||
|
||||
switch ((char)(val >> 16)) {
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'x':
|
||||
case 'X':
|
||||
printf("%s%s %c%c%c%s\n", KRED, trace,
|
||||
(char)(val >> 16), (char)(val >> 8), (char)val, KNRM);
|
||||
break;
|
||||
default:
|
||||
printf("%s %c%c%c\n", trace,
|
||||
(char)(val >> 16), (char)(val >> 8), (char)val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int trace_read(const char *in_file, const char *out_file, double clk)
|
||||
{
|
||||
int count, i;
|
||||
FILE *in_fd = NULL, *out_fd = NULL;
|
||||
char c, tmp[TRACE_BLOCK_SIZE] = {0};
|
||||
uint64_t addr = 0, val, timestamp = 0;
|
||||
|
||||
in_fd = fopen(in_file, "r");
|
||||
if (in_fd == NULL) {
|
||||
fprintf(stderr, "error: unable to open %s for reading %d\n",
|
||||
in_file, errno);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (out_file == NULL)
|
||||
goto trace;
|
||||
|
||||
out_fd = fopen(out_file, "w");
|
||||
if (out_fd == NULL) {
|
||||
fprintf(stderr, "error: unable to open %s for writing %d\n",
|
||||
out_file, errno);
|
||||
}
|
||||
|
||||
trace:
|
||||
fprintf(stdout, "using %2.2fMHz timestamp clock\n", clk);
|
||||
|
||||
while (1) {
|
||||
count = fread(&tmp[0], 1, TRACE_BLOCK_SIZE, in_fd);
|
||||
if (count != TRACE_BLOCK_SIZE)
|
||||
break;
|
||||
|
||||
val = *((uint64_t*)tmp);
|
||||
|
||||
for (i = 0; i < TRACE_BLOCK_SIZE / 2; i++) {
|
||||
c = tmp[i];
|
||||
tmp[i] = tmp[TRACE_BLOCK_SIZE - i - 1];
|
||||
tmp[TRACE_BLOCK_SIZE - i - 1] = c;
|
||||
}
|
||||
|
||||
show_trace(val, addr, ×tamp, clk);
|
||||
|
||||
if (out_fd) {
|
||||
count = fwrite(&tmp[0], 1, TRACE_BLOCK_SIZE, out_fd);
|
||||
if (count != TRACE_BLOCK_SIZE)
|
||||
break;
|
||||
}
|
||||
|
||||
addr += TRACE_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
fclose(in_fd);
|
||||
if (out_fd)
|
||||
fclose(out_fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void show_data(uint32_t val, uint32_t addr)
|
||||
{
|
||||
printf("data: 0x%x = \t0x%8.8x \t(%8.8d) \t|%c%c%c%c|\n",
|
||||
(unsigned int)addr,
|
||||
val, val,
|
||||
get_char(val, 3), get_char(val, 2),
|
||||
get_char(val, 1), get_char(val, 0));
|
||||
}
|
||||
|
||||
|
||||
static const char *debugfs[] = {
|
||||
"dmac0", "dmac1", "ssp0", "ssp1",
|
||||
"ssp2", "iram", "dram", "shim",
|
||||
"mbox", "etrace",
|
||||
};
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
fprintf(stdout, "Usage %s <option(s)> <file(s)>\n", APP_NAME);
|
||||
fprintf(stdout, "%s:\t \t\t\tDisplay mailbox contents\n", APP_NAME);
|
||||
fprintf(stdout, "%s:\t -i infile -o outfile\tDump infile contents to outfile\n", APP_NAME);
|
||||
#ifdef LOGGER_FORMAT
|
||||
fprintf(stdout, "%s:\t -l *.ldc_file\t-i in_file\n", APP_NAME);
|
||||
#endif
|
||||
fprintf(stdout, "%s:\t -c\t\t\tSet timestamp clock in MHz\n", APP_NAME);
|
||||
fprintf(stdout, "%s:\t -s\t\t\tTake a snapshot of state\n", APP_NAME);
|
||||
fprintf(stdout, "%s:\t -t\t\t\tDisplay trace data\n", APP_NAME);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static int snapshot(const char *name)
|
||||
{
|
||||
const char *path = "/sys/kernel/debug/sof";
|
||||
|
@ -324,99 +108,112 @@ static int snapshot(const char *name)
|
|||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int opt, count, trace = 0;
|
||||
const char * out_file = NULL, *in_file = NULL;
|
||||
struct convert_config config;
|
||||
int opt, count, ret = 0;
|
||||
FILE *in_fd = NULL, *out_fd = NULL;
|
||||
char c, tmp[8] = {0};
|
||||
uint64_t addr = 0, val, timestamp = 0, align = 4, i;
|
||||
double clk = 19.2;
|
||||
|
||||
config.trace = 0;
|
||||
config.clock = 19.2;
|
||||
config.in_file = NULL;
|
||||
config.out_file = NULL;
|
||||
config.out_fd = NULL;
|
||||
config.in_fd = NULL;
|
||||
#ifdef LOGGER_FORMAT
|
||||
config.ldc_file = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef LOGGER_FORMAT
|
||||
while ((opt = getopt(argc, argv, "ho:i:l:s:m:c:t")) != -1) {
|
||||
#else
|
||||
while ((opt = getopt(argc, argv, "ho:i:s:m:c:t")) != -1) {
|
||||
#endif
|
||||
switch (opt) {
|
||||
case 'o':
|
||||
out_file = optarg;
|
||||
config.out_file = optarg;
|
||||
break;
|
||||
case 'i':
|
||||
in_file = optarg;
|
||||
config.in_file = optarg;
|
||||
break;
|
||||
case 't':
|
||||
trace = 1;
|
||||
config.trace = 1;
|
||||
break;
|
||||
case 'c':
|
||||
clk = atof(optarg);
|
||||
config.clock = atof(optarg);
|
||||
break;
|
||||
case 's':
|
||||
return snapshot(optarg);
|
||||
#ifdef LOGGER_FORMAT
|
||||
case 'l':
|
||||
config.ldc_file = optarg;
|
||||
break;
|
||||
#endif
|
||||
case 'h':
|
||||
default: /* '?' */
|
||||
usage(argv[0]);
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LOGGER_FORMAT
|
||||
if (!config.ldc_file) {
|
||||
fprintf(stderr, "error: Missing ldc file");
|
||||
usage();
|
||||
}
|
||||
|
||||
config.ldc_fd = fopen(config.ldc_file, "r");
|
||||
if (!config.ldc_fd) {
|
||||
fprintf(stderr, "error: Unable to open ldc file %s\n",
|
||||
config.ldc_file);
|
||||
ret = -errno;
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (config.out_file) {
|
||||
config.out_fd = fopen(config.out_file, "w");
|
||||
if (!config.out_fd) {
|
||||
fprintf(stderr, "error: Unable to open out file %s\n",
|
||||
config.out_file);
|
||||
ret = -errno;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
config.out_fd = stdout;
|
||||
}
|
||||
|
||||
/* trace requested ? */
|
||||
if (trace)
|
||||
return trace_read("/sys/kernel/debug/sof/trace",
|
||||
out_file, clk);
|
||||
if (config.trace)
|
||||
config.in_file = "/sys/kernel/debug/sof/trace";
|
||||
|
||||
/* default option with no infile is to dump errors/debug data */
|
||||
if (in_file == NULL) {
|
||||
fprintf(stdout, "\nError log:\n");
|
||||
return trace_read("/sys/kernel/debug/sof/etrace",
|
||||
out_file, clk);
|
||||
}
|
||||
if (!config.in_file)
|
||||
config.in_file = "/sys/kernel/debug/sof/etrace";
|
||||
|
||||
/* open infile for reading */
|
||||
in_fd = fopen(in_file, "r");
|
||||
if (in_fd == NULL) {
|
||||
fprintf(stderr, "error: unable to open %s for reading %d\n",
|
||||
in_file, errno);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* open outfile for writing */
|
||||
if (out_file == NULL)
|
||||
goto convert;
|
||||
|
||||
out_fd = fopen(out_file, "w");
|
||||
if (out_fd == NULL) {
|
||||
fprintf(stderr, "error: unable to open %s for writing %d\n",
|
||||
out_file, errno);
|
||||
fclose(in_fd);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* start to converting mailbox */
|
||||
convert:
|
||||
fprintf(stdout, "using %2.2fMHz timestamp clock\n", clk);
|
||||
|
||||
while (1) {
|
||||
count = fread(&tmp[0], 1, align, in_fd);
|
||||
if (count != align)
|
||||
break;
|
||||
|
||||
val = *((uint64_t*)tmp);
|
||||
|
||||
for (i = 0; i < align / 2; i++) {
|
||||
c = tmp[i];
|
||||
tmp[i] = tmp[align - i - 1];
|
||||
tmp[align - i - 1] = c;
|
||||
if (config.in_file) {
|
||||
config.in_fd = fopen(config.in_file, "r");
|
||||
if (!config.in_fd) {
|
||||
fprintf(stderr, "error: Unable to open in file %s\n",
|
||||
config.in_file);
|
||||
ret = -errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
show_data(val, addr);
|
||||
|
||||
if (out_fd) {
|
||||
count = fwrite(&tmp[0], 1, align, out_fd);
|
||||
if (count != align)
|
||||
break;
|
||||
}
|
||||
|
||||
addr += align;
|
||||
}
|
||||
|
||||
convert(&config);
|
||||
|
||||
out:
|
||||
/* close files */
|
||||
fclose(in_fd);
|
||||
if (out_fd)
|
||||
fclose(out_fd);
|
||||
if (config.out_file)
|
||||
fclose(config.out_fd);
|
||||
|
||||
return 0;
|
||||
if (config.in_fd)
|
||||
fclose(config.in_fd);
|
||||
|
||||
#ifdef LOGGER_FORMAT
|
||||
if (config.ldc_fd)
|
||||
fclose(config.ldc_fd);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* debug log converter, using old rmbox format.
|
||||
*
|
||||
* Copyright (c) 2018, Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "convert.h"
|
||||
|
||||
#define TRACE_BLOCK_SIZE 8
|
||||
|
||||
#define CASE(x) case(TRACE_CLASS_##x): trace = #x; break
|
||||
|
||||
static void show_trace(FILE *out_fd, uint64_t val, uint64_t addr,
|
||||
uint64_t *timestamp, double clk)
|
||||
{
|
||||
const char *trace;
|
||||
uint32_t class;
|
||||
uint64_t delta = val - *timestamp;
|
||||
double fdelta = to_usecs(delta, clk);
|
||||
double us = 0.0f;
|
||||
|
||||
/* timestamp or value ? */
|
||||
if ((addr % (TRACE_BLOCK_SIZE * 2)) == 0) {
|
||||
|
||||
delta = val - *timestamp;
|
||||
fdelta = to_usecs(delta, clk);
|
||||
|
||||
/* 64-bit timestamp */
|
||||
us = to_usecs(val, clk);
|
||||
|
||||
/* empty data ? */
|
||||
if (val == 0) {
|
||||
*timestamp = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* detect wrap around */
|
||||
if (fdelta < 1000.0 * 1000.0 * 1000.0)
|
||||
fprintf(out_fd, "0x%lx [%6.6f]\tdelta [%6.6f]\t", addr,
|
||||
us / 1000000.0, fdelta / 1000000.0);
|
||||
else
|
||||
fprintf(out_fd, "0x%lx [%6.6f]\tdelta [********]\t", addr,
|
||||
us / 1000000.0);
|
||||
|
||||
*timestamp = val;
|
||||
return;
|
||||
}
|
||||
else if (*timestamp == 0)
|
||||
return;
|
||||
|
||||
/* check for printable values - otherwise it's a value */
|
||||
if (!isprint((char)(val >> 16)) || !isprint((char)(val >> 8)) || !isprint((char)val)) {
|
||||
fprintf(out_fd, "value 0x%16.16lx\n", val);
|
||||
return;
|
||||
}
|
||||
|
||||
class = val & 0xff000000;
|
||||
switch (class)
|
||||
{
|
||||
CASE(IRQ);
|
||||
CASE(IPC);
|
||||
CASE(PIPE);
|
||||
CASE(HOST);
|
||||
CASE(DAI);
|
||||
CASE(DMA);
|
||||
CASE(SSP);
|
||||
CASE(COMP);
|
||||
CASE(WAIT);
|
||||
CASE(LOCK);
|
||||
CASE(MEM);
|
||||
CASE(MIXER);
|
||||
CASE(BUFFER);
|
||||
CASE(VOLUME);
|
||||
CASE(SWITCH);
|
||||
CASE(MUX);
|
||||
CASE(SRC);
|
||||
CASE(TONE);
|
||||
CASE(EQ_FIR);
|
||||
CASE(EQ_IIR);
|
||||
CASE(SA);
|
||||
CASE(DMIC);
|
||||
CASE(POWER);
|
||||
default:
|
||||
fprintf(out_fd, "value 0x%8.8x\n", (uint32_t)val);
|
||||
return;
|
||||
}
|
||||
|
||||
switch ((char)(val >> 16)) {
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'x':
|
||||
case 'X':
|
||||
fprintf(out_fd, "%s%s %c%c%c%s\n", KRED, trace,
|
||||
(char)(val >> 16), (char)(val >> 8), (char)val, KNRM);
|
||||
break;
|
||||
default:
|
||||
fprintf(out_fd, "%s %c%c%c\n", trace,
|
||||
(char)(val >> 16), (char)(val >> 8), (char)val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int convert(struct convert_config *config)
|
||||
{
|
||||
int count, i;
|
||||
char c, tmp[TRACE_BLOCK_SIZE] = { 0 };
|
||||
uint64_t addr = 0, val, timestamp = 0;
|
||||
|
||||
fprintf(stdout, "using %2.2fMHz timestamp clock\n", config->clock);
|
||||
|
||||
while (1) {
|
||||
count = fread(&tmp[0], 1, TRACE_BLOCK_SIZE, config->in_fd);
|
||||
if (count != TRACE_BLOCK_SIZE)
|
||||
break;
|
||||
|
||||
val = *((uint64_t*)tmp);
|
||||
|
||||
for (i = 0; i < TRACE_BLOCK_SIZE / 2; i++) {
|
||||
c = tmp[i];
|
||||
tmp[i] = tmp[TRACE_BLOCK_SIZE - i - 1];
|
||||
tmp[TRACE_BLOCK_SIZE - i - 1] = c;
|
||||
}
|
||||
|
||||
show_trace(config->out_fd, val, addr, ×tamp, config->clock);
|
||||
|
||||
addr += TRACE_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Intel Corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file include/uapi/abi.h
|
||||
* \brief ABI definitions
|
||||
* \author Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
*/
|
||||
|
||||
#ifndef __INCLUDE_UAPI_ABI_H__
|
||||
#define __INCLUDE_UAPI_ABI_H__
|
||||
|
||||
/** \brief SOF ABI version number. */
|
||||
#define SOF_ABI_VER(major, minor, micro) \
|
||||
(((major)<<8)|((minor)<<4)|(micro))
|
||||
#define SOF_ABI_VERSION_MAJOR(version) (((version)>>8) & 0xff)
|
||||
#define SOF_ABI_VERSION_MINOR(version) (((version)>>4) & 0xf)
|
||||
#define SOF_ABI_VERSION_MICRO(version) ((version) & 0xf)
|
||||
#define SOF_ABI_VERSION_INCOMPATIBLE(sof_ver, client_ver) \
|
||||
(SOF_ABI_VERSION_MAJOR(sof_ver) != SOF_ABI_VERSION_MAJOR(client_ver) ||\
|
||||
(SOF_ABI_VERSION_MAJOR(sof_ver) == SOF_ABI_VERSION_MAJOR(client_ver) &&\
|
||||
SOF_ABI_VERSION_MINOR(sof_ver) != SOF_ABI_VERSION_MINOR(client_ver)))
|
||||
|
||||
#define SOF_ABI_MAJOR 1
|
||||
#define SOF_ABI_MINOR 0
|
||||
#define SOF_ABI_MICRO 0
|
||||
|
||||
#define SOF_ABI_VERSION SOF_ABI_VER(SOF_ABI_MAJOR, SOF_ABI_MINOR, SOF_ABI_MICRO)
|
||||
|
||||
/** \brief SOF ABI magic number "SOF\0". */
|
||||
#define SOF_ABI_MAGIC 0x00464F53
|
||||
|
||||
/**
|
||||
* \brief Header for all non IPC ABI data.
|
||||
*
|
||||
* Identifies data type, size and ABI.
|
||||
* Used by any bespoke component data structures or binary blobs.
|
||||
*/
|
||||
struct sof_abi_hdr {
|
||||
uint32_t magic; /**< 'S', 'O', 'F', '\0' */
|
||||
uint32_t type; /**< component specific type */
|
||||
uint32_t size; /**< size in bytes of data excl. this struct */
|
||||
uint32_t abi; /**< SOF ABI version */
|
||||
uint32_t comp_abi; /**< component specific ABI version */
|
||||
char data[0]; /**< data */
|
||||
} __attribute__((packed));
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Intel Corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Author: Bartosz Kokoszko <bartoszx.kokoszko@linux.intel.com>
|
||||
* Artur Kloniecki <arturx.kloniecki@linux.intel.com>
|
||||
*/
|
||||
|
||||
#ifndef __INCLUDE_LOGGING__
|
||||
#define __INCLUDE_LOGGING__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Host system time.
|
||||
*
|
||||
* This property is used by the driver to pass down information about
|
||||
* current system time. It is expressed in us.
|
||||
* FW translates timestamps (in log entries, probe pockets) to this time
|
||||
* domain.
|
||||
*
|
||||
* (cavs: SystemTime).
|
||||
*/
|
||||
struct system_time {
|
||||
uint32_t val_l; /* Lower dword of current host time value */
|
||||
uint32_t val_u; /* Upper dword of current host time value */
|
||||
};
|
||||
|
||||
/* trace event classes - high 8 bits*/
|
||||
#define TRACE_CLASS_IRQ (1 << 24)
|
||||
#define TRACE_CLASS_IPC (2 << 24)
|
||||
#define TRACE_CLASS_PIPE (3 << 24)
|
||||
#define TRACE_CLASS_HOST (4 << 24)
|
||||
#define TRACE_CLASS_DAI (5 << 24)
|
||||
#define TRACE_CLASS_DMA (6 << 24)
|
||||
#define TRACE_CLASS_SSP (7 << 24)
|
||||
#define TRACE_CLASS_COMP (8 << 24)
|
||||
#define TRACE_CLASS_WAIT (9 << 24)
|
||||
#define TRACE_CLASS_LOCK (10 << 24)
|
||||
#define TRACE_CLASS_MEM (11 << 24)
|
||||
#define TRACE_CLASS_MIXER (12 << 24)
|
||||
#define TRACE_CLASS_BUFFER (13 << 24)
|
||||
#define TRACE_CLASS_VOLUME (14 << 24)
|
||||
#define TRACE_CLASS_SWITCH (15 << 24)
|
||||
#define TRACE_CLASS_MUX (16 << 24)
|
||||
#define TRACE_CLASS_SRC (17 << 24)
|
||||
#define TRACE_CLASS_TONE (18 << 24)
|
||||
#define TRACE_CLASS_EQ_FIR (19 << 24)
|
||||
#define TRACE_CLASS_EQ_IIR (20 << 24)
|
||||
#define TRACE_CLASS_SA (21 << 24)
|
||||
#define TRACE_CLASS_DMIC (22 << 24)
|
||||
#define TRACE_CLASS_POWER (23 << 24)
|
||||
#define TRACE_CLASS_IDC (24 << 24)
|
||||
#define TRACE_CLASS_CPU (25 << 24)
|
||||
|
||||
#define LOG_ENABLE 1 /* Enable logging */
|
||||
#define LOG_DISABLE 0 /* Disable logging */
|
||||
|
||||
#define LOG_LEVEL_CRITICAL 1 /* (FDK fatal) */
|
||||
#define LOG_LEVEL_VERBOSE 2
|
||||
|
||||
/*
|
||||
* Layout of a log fifo.
|
||||
*/
|
||||
struct log_buffer_layout {
|
||||
uint32_t read_ptr; /*read pointer */
|
||||
uint32_t write_ptr; /* write pointer */
|
||||
uint32_t buffer[0]; /* buffer */
|
||||
};
|
||||
|
||||
/*
|
||||
* Log buffer status reported by FW.
|
||||
*/
|
||||
struct log_buffer_status {
|
||||
uint32_t core_id; /* ID of core that logged to other half */
|
||||
};
|
||||
|
||||
/*
|
||||
* Log entry header.
|
||||
*
|
||||
* The header is followed by an array of arguments (uint32_t[]).
|
||||
* Number of arguments is specified by the params_num field of log_entry,
|
||||
* and is 0-based value (entry_len=0 means there is 1 argument).
|
||||
*/
|
||||
struct log_entry_header {
|
||||
uint32_t rsvd : 24; /* Unused */
|
||||
uint32_t core_id : 8; /* Reporting core's id */
|
||||
|
||||
uint64_t timestamp; /* Timestamp (in dsp ticks) */
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#endif //#ifndef __INCLUDE_LOGGING__
|
Loading…
Reference in New Issue