From 04c0d5071e1eb7a0f6c92df9058941d9058cfa5b Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 20 Sep 2016 11:25:01 +0200 Subject: [PATCH] Use DWT support of libswo --- src/Makefile.am | 1 - src/dwt.c | 347 -------------------------------------------------------- src/main.c | 185 +++++++++++++++++++++++++----- src/swodec.h | 45 -------- 4 files changed, 159 insertions(+), 419 deletions(-) delete mode 100644 src/dwt.c delete mode 100644 src/swodec.h diff --git a/src/Makefile.am b/src/Makefile.am index 75f788e..ee64246 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -20,5 +20,4 @@ bin_PROGRAMS = swodec swodec_SOURCES = \ - dwt.c \ main.c diff --git a/src/dwt.c b/src/dwt.c deleted file mode 100644 index e24e255..0000000 --- a/src/dwt.c +++ /dev/null @@ -1,347 +0,0 @@ -/* - * This file is part of the swodec project. - * - * Copyright (C) 2014-2015 Marc Schink - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that 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. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "swodec.h" - -/* Event counter packet discriminator ID. */ -#define EVCNT_ID 0 - -/* Size of an event counter packet in bytes. */ -#define EVCNT_SIZE 2 - -/* Bitmask for the CPI flag of an event counter packet. */ -#define EVCNT_CPI_MASK 0x01 - -/* Bitmask for the Exc flag of an event counter packet. */ -#define EVCNT_EXC_MASK 0x02 - -/* Bitmask for the Sleep flag of an event counter packet. */ -#define EVCNT_SLEEP_MASK 0x04 - -/* Bitmask for the LSU flag of an event counter packet. */ -#define EVCNT_LSU_MASK 0x08 - -/* Bitmask for the Fold flag of an event counter packet. */ -#define EVCNT_FOLD_MASK 0x10 - -/* Bitmask for the Cyc flag of an event counter packet. */ -#define EVCNT_CYC_MASK 0x20 - -/* Exception trace packet discriminator ID. */ -#define EXTRACE_ID 1 - -/* Size of an exception trace packet in bytes. */ -#define EXTRACE_SIZE 3 - -/* Bitmask for the exception number of an exception trace packet. */ -#define EXTRACE_EX_MASK 0x01 - -/* Offset of the exception number of an exception trace packet. */ -#define EXTRACE_EX_OFFSET 8 - -/* Bitmask for the function of an exception trace packet. */ -#define EXTRACE_FN_MASK 0x30 - -/* Offset of the function of an exception trace packet. */ -#define EXTRACE_FN_OFFSET 4 - -/* Periodic PC sample packet discriminator ID. */ -#define PC_SAMPLE_ID 2 - -/* Size of a periodic PC sleep packet in bytes. */ -#define PC_SAMPLE_SLEEP_SIZE 2 - -/* Size of a periodic PC sample packet in bytes. */ -#define PC_SAMPLE_SIZE 5 - -/* Bitmask for the comparator number of a data trace packet. */ -#define CMPN_MASK 0x06 - -/* Offset of the comparator number of a data trace packet. */ -#define CMPN_OFFSET 1 - -/* Bitmask for the WnR flag of a data trace data value packet. */ -#define WNR_MASK 0x01 - -/* Bitmask for the data trace PC value packet header. */ -#define PC_VALUE_HEADER_MASK 0x19 - -/* Data trace PC value packet header. */ -#define PC_VALUE_HEADER 0x08 - -/* Size of a data trace PC value packet in bytes. */ -#define PC_VALUE_SIZE 5 - -/* Bitmask for the data trace address offset packet header. */ -#define ADDR_OFFSET_HEADER_MASK 0x19 - -/* Data trace address offset packet header. */ -#define ADDR_OFFSET_HEADER 0x09 - -/* Size of a data trace address offset packet in bytes. */ -#define ADDR_OFFSET_SIZE 3 - -/* Bitmask for the data trace data value packet header. */ -#define DATA_VALUE_HEADER_MASK 0x18 - -/* Data trace data value packet header. */ -#define DATA_VALUE_HEADER 0x10 - -/* - * Exception names according to section B1.5 of ARMv7-M Architecture Reference - * Manual. - */ -static const char *exception_names[] = { - "Thread", - "Reset", - "NMI", - "HardFault", - "MemManage", - "BusFault", - "UsageFault", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "SVCall", - "Debug Monitor", - "Reserved", - "PendSV", - "SysTick" -}; - -/* Number of exception names. */ -#define NUM_EXCEPTION_NAMES 16 - -/* Exception trace functions. */ -enum extrace_function { - /* Enter exception. */ - EXTRACE_FN_ENTER = 1, - /* Exit exception. */ - EXTRACE_FN_EXIT = 2, - /* Return to exception. */ - EXTRACE_FN_RETURN = 3 -}; - -static void handle_evcnt_packet(const struct libswo_packet_hw *packet) -{ - unsigned int cpi; - unsigned int exc; - unsigned int sleep; - unsigned int lsu; - unsigned int fold; - unsigned int cyc; - - if (!(packet_type_filter & (1 << DWT_PACKET_TYPE_EVENT_COUNTER))) - return; - - if (packet->size != EVCNT_SIZE) { - g_warning("Event counter packet with invalid size of " - "%zu bytes.", packet->size); - return; - } - - if (packet->payload[0] & EVCNT_CPI_MASK) - cpi = 1; - else - cpi = 0; - - if (packet->payload[0] & EVCNT_EXC_MASK) - exc = 1; - else - exc = 0; - - if (packet->payload[0] & EVCNT_SLEEP_MASK) - sleep = 1; - else - sleep = 0; - - if (packet->payload[0] & EVCNT_LSU_MASK) - lsu = 1; - else - lsu = 0; - - if (packet->payload[0] & EVCNT_FOLD_MASK) - fold = 1; - else - fold = 0; - - if (packet->payload[0] & EVCNT_CYC_MASK) - cyc = 1; - else - cyc = 0; - - printf("Event counter (CPI = %u, exc = %u, sleep = %u, LSU = %u, " - "fold = %u, cyc = %u)\n", cpi, exc, sleep, lsu, fold, cyc); -} - -static void handle_extrace_packet(const struct libswo_packet_hw *packet) -{ - uint16_t exception; - uint8_t tmp; - const char *func; - const char *name; - char buf[23]; - - if (!(packet_type_filter & (1 << DWT_PACKET_TYPE_EXCEPTION_TRACE))) - return; - - if (packet->size != EXTRACE_SIZE) { - g_warning("Exception trace packet with invalid size of " - "%zu bytes.", packet->size); - return; - } - - exception = packet->payload[0]; - exception |= (packet->payload[1] & EXTRACE_EX_MASK) << \ - EXTRACE_EX_OFFSET; - tmp = (packet->payload[1] & EXTRACE_FN_MASK) >> EXTRACE_FN_OFFSET; - - switch (tmp) { - case EXTRACE_FN_ENTER: - func = "enter"; - break; - case EXTRACE_FN_EXIT: - func = "exit"; - break; - case EXTRACE_FN_RETURN: - func = "return"; - break; - default: - func = "reserved"; - } - - if (exception < NUM_EXCEPTION_NAMES) { - name = exception_names[exception]; - } else { - snprintf(buf, sizeof(buf), "External interrupt %u", - exception - NUM_EXCEPTION_NAMES); - name = buf; - } - - printf("Exception trace (function = %s, exception = %s)\n", func, name); -} - -static void handle_pc_sample_packet(const struct libswo_packet_hw *packet) -{ - - if (!(packet_type_filter & (1 << DWT_PACKET_TYPE_PC_SAMPLE))) - return; - - if (packet->size == PC_SAMPLE_SLEEP_SIZE) { - if (packet->value > 0) { - g_warning("Periodic PC sleep packet contains invalid " - "value: %x.", packet->value); - return; - } - - printf("Periodic PC sleep\n"); - } else if (packet->size == PC_SAMPLE_SIZE) { - printf("Periodic PC sample (value = %x)\n", packet->value); - } else { - g_warning("Periodic PC sample packet with invalid size of " - "%zu bytes.", packet->size); - } -} - -static void handle_pc_value_packet(const struct libswo_packet_hw *packet) -{ - unsigned int cmpn; - - if (!(packet_type_filter & (1 << DWT_PACKET_TYPE_DT_PC_VALUE))) - return; - - if (packet->size != PC_VALUE_SIZE) { - g_warning("Data trace PC value packet with invalid size of " - "%zu bytes.", packet->size); - return; - } - - cmpn = (packet->address & CMPN_MASK) >> CMPN_OFFSET; - - printf("Data trace PC value (comparator = %u, value = %x)\n", cmpn, - packet->value); -} - -static void handle_address_offset_packet(const struct libswo_packet_hw *packet) -{ - unsigned int cmpn; - - if (!(packet_type_filter & (1 << DWT_PACKET_TYPE_DT_ADDR_OFFSET))) - return; - - if (packet->size != ADDR_OFFSET_SIZE) { - g_warning("Data trace address offset packet with invalid size " - "of %zu bytes.", packet->size); - return; - } - - cmpn = (packet->address & CMPN_MASK) >> CMPN_OFFSET; - - printf("Data trace address offset (comparator = %u, value = %x)\n", - cmpn, packet->value); -} - -static void handle_data_value_packet(const struct libswo_packet_hw *packet) -{ - unsigned int wnr; - unsigned int cmpn; - - if (!(packet_type_filter & (1 << DWT_PACKET_TYPE_DT_DATA_VALUE))) - return; - - wnr = packet->address & WNR_MASK; - cmpn = (packet->address & CMPN_MASK) >> CMPN_OFFSET; - - printf("Data trace data value (comparator = %u, WnR = %u, value = %x, " - "size = %zu bytes)\n", cmpn, wnr, packet->value, - packet->size - 1); -} - -gboolean dwt_handle_packet(const struct libswo_packet_hw *packet) -{ - uint8_t addr; - - addr = packet->address; - - if (addr == EVCNT_ID) - handle_evcnt_packet(packet); - else if (addr == EXTRACE_ID) - handle_extrace_packet(packet); - else if (addr == PC_SAMPLE_ID) - handle_pc_sample_packet(packet); - else if ((addr & PC_VALUE_HEADER_MASK) == PC_VALUE_HEADER) - handle_pc_value_packet(packet); - else if ((addr & ADDR_OFFSET_HEADER_MASK) == ADDR_OFFSET_HEADER) - handle_address_offset_packet(packet); - else if ((addr & DATA_VALUE_HEADER_MASK) == DATA_VALUE_HEADER) - handle_data_value_packet(packet); - else - return FALSE; - - return TRUE; -} diff --git a/src/main.c b/src/main.c index 62b3886..ab352bc 100644 --- a/src/main.c +++ b/src/main.c @@ -1,7 +1,7 @@ /* * This file is part of the swodec project. * - * Copyright (C) 2014-2015 Marc Schink + * Copyright (C) 2014-2016 Marc Schink * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,13 +27,39 @@ #include #include -#include "swodec.h" +#include + +/* + * Exception names according to section B1.5 of ARMv7-M Architecture Reference + * Manual. + */ +static const char *exception_names[] = { + "Thread", + "Reset", + "NMI", + "HardFault", + "MemManage", + "BusFault", + "UsageFault", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "SVCall", + "Debug Monitor", + "Reserved", + "PendSV", + "SysTick" +}; + +/* Number of exception names. */ +#define NUM_EXCEPTION_NAMES 16 #define BUFFER_SIZE 1024 static gboolean opt_version; static gchar *input_file = NULL; -uint16_t packet_type_filter; +static uint32_t packet_type_filter; static uint32_t inst_address_filter; static gboolean opt_dump_inst; @@ -42,7 +68,7 @@ static gboolean parse_filter_option(const gchar *option_name, { gchar **tokens; unsigned int i; - uint16_t tmp; + uint32_t tmp; gboolean invert; (void)option_name; @@ -61,7 +87,7 @@ static gboolean parse_filter_option(const gchar *option_name, i = 0; tokens = g_strsplit(value, ",", -1); - tmp = 0x0000; + tmp = 0x00000000; while (tokens[i]) { g_strstrip(tokens[i]); @@ -93,24 +119,24 @@ static gboolean parse_filter_option(const gchar *option_name, } else if (!g_ascii_strcasecmp(tokens[i], "hw")) { tmp |= (1 << LIBSWO_PACKET_TYPE_HW); } else if (!g_ascii_strcasecmp(tokens[i], "dwt")) { - tmp |= (1 << DWT_PACKET_TYPE_EVENT_COUNTER); - tmp |= (1 << DWT_PACKET_TYPE_EXCEPTION_TRACE); - tmp |= (1 << DWT_PACKET_TYPE_PC_SAMPLE); - tmp |= (1 << DWT_PACKET_TYPE_DT_PC_VALUE); - tmp |= (1 << DWT_PACKET_TYPE_DT_ADDR_OFFSET); - tmp |= (1 << DWT_PACKET_TYPE_DT_DATA_VALUE); + tmp |= (1 << LIBSWO_PACKET_TYPE_DWT_EVTCNT); + tmp |= (1 << LIBSWO_PACKET_TYPE_DWT_EXCTRACE); + tmp |= (1 << LIBSWO_PACKET_TYPE_DWT_PC_SAMPLE); + tmp |= (1 << LIBSWO_PACKET_TYPE_DWT_PC_VALUE); + tmp |= (1 << LIBSWO_PACKET_TYPE_DWT_ADDR_OFFSET); + tmp |= (1 << LIBSWO_PACKET_TYPE_DWT_DATA_VALUE); } else if (!g_ascii_strcasecmp(tokens[i], "evcnt")) { - tmp |= (1 << DWT_PACKET_TYPE_EVENT_COUNTER); + tmp |= (1 << LIBSWO_PACKET_TYPE_DWT_EVTCNT); } else if (!g_ascii_strcasecmp(tokens[i], "exc")) { - tmp |= (1 << DWT_PACKET_TYPE_EXCEPTION_TRACE); + tmp |= (1 << LIBSWO_PACKET_TYPE_DWT_EXCTRACE); } else if (!g_ascii_strcasecmp(tokens[i], "pc")) { - tmp |= (1 << DWT_PACKET_TYPE_PC_SAMPLE); + tmp |= (1 << LIBSWO_PACKET_TYPE_DWT_PC_SAMPLE); } else if (!g_ascii_strcasecmp(tokens[i], "dtpc")) { - tmp |= (1 << DWT_PACKET_TYPE_DT_PC_VALUE); + tmp |= (1 << LIBSWO_PACKET_TYPE_DWT_PC_VALUE); } else if (!g_ascii_strcasecmp(tokens[i], "dtaddr")) { - tmp |= (1 << DWT_PACKET_TYPE_DT_ADDR_OFFSET); + tmp |= (1 << LIBSWO_PACKET_TYPE_DWT_ADDR_OFFSET); } else if (!g_ascii_strcasecmp(tokens[i], "dtval")) { - tmp |= (1 << DWT_PACKET_TYPE_DT_DATA_VALUE); + tmp |= (1 << LIBSWO_PACKET_TYPE_DWT_DATA_VALUE); } else { g_critical("Invalid packet type: %s.", tokens[i]); g_strfreev(tokens); @@ -221,9 +247,6 @@ static GOptionEntry entries[] = { static void handle_hw_packet(const union libswo_packet *packet) { - if (dwt_handle_packet(&packet->hw)) - return; - if (!(packet_type_filter & (1 << LIBSWO_PACKET_TYPE_HW))) return; @@ -351,6 +374,98 @@ static void handle_gts2_packet(const union libswo_packet *packet) printf("Global timestamp (GTS2) (value = %x)\n", packet->gts2.value); } +static void handle_dwt_evtcnt_packet(const union libswo_packet *packet) +{ + if (!(packet_type_filter & (1 << LIBSWO_PACKET_TYPE_DWT_EVTCNT))) + return; + + printf("Event counter (CPI = %u, exc = %u, sleep = %u, LSU = %u, " + "fold = %u, cyc = %u)\n", packet->evtcnt.cpi, + packet->evtcnt.exc, packet->evtcnt.sleep, packet->evtcnt.lsu, + packet->evtcnt.fold, packet->evtcnt.cyc); +} + +static void handle_dwt_exctrace_packet(const union libswo_packet *packet) +{ + uint16_t exception; + const char *func; + const char *name; + char buf[23]; + + if (!(packet_type_filter & (1 << LIBSWO_PACKET_TYPE_DWT_EXCTRACE))) + return; + + switch (packet->exctrace.function) { + case LIBSWO_EXCTRACE_FUNC_ENTER: + func = "enter"; + break; + case LIBSWO_EXCTRACE_FUNC_EXIT: + func = "exit"; + break; + case LIBSWO_EXCTRACE_FUNC_RETURN: + func = "return"; + break; + default: + func = "reserved"; + } + + exception = packet->exctrace.exception; + + if (exception < NUM_EXCEPTION_NAMES) { + name = exception_names[exception]; + } else { + snprintf(buf, sizeof(buf), "External interrupt %u", + exception - NUM_EXCEPTION_NAMES); + name = buf; + } + + printf("Exception trace (function = %s, exception = %s)\n", func, + name); +} + +static void handle_dwt_pc_sample_packet(const union libswo_packet *packet) +{ + if (!(packet_type_filter & (1 << LIBSWO_PACKET_TYPE_DWT_PC_SAMPLE))) + return; + + if (packet->pc_sample.sleep) + printf("Periodic PC sleep\n"); + else + printf("Periodic PC sample (value = %x)\n", + packet->pc_sample.pc); +} + +static void handle_dwt_pc_value_packet(const union libswo_packet *packet) +{ + if (!(packet_type_filter & (1 << LIBSWO_PACKET_TYPE_DWT_PC_VALUE))) + return; + + printf("Data trace PC value (comparator = %u, value = %x)\n", + packet->pc_value.cmpn, packet->pc_value.pc); +} + +static void handle_dwt_addr_offset_packet(const union libswo_packet *packet) +{ + if (!(packet_type_filter & \ + (1 << LIBSWO_PACKET_TYPE_DWT_ADDR_OFFSET))) + return; + + printf("Data trace address offset (comparator = %u, value = %x)\n", + packet->addr_offset.cmpn, packet->addr_offset.offset); +} + +static void handle_dwt_data_value_packet(const union libswo_packet *packet) +{ + if (!(packet_type_filter & \ + (1 << LIBSWO_PACKET_TYPE_DWT_DATA_VALUE))) + return; + + printf("Data trace data value (comparator = %u, WnR = %u, value = %x, " + "size = %zu bytes)\n", packet->data_value.cmpn, + packet->data_value.wnr, packet->data_value.data_value, + packet->data_value.size - 1); +} + static int packet_cb(struct libswo_context *ctx, const union libswo_packet *packet, void *user_data) { @@ -385,6 +500,24 @@ static int packet_cb(struct libswo_context *ctx, case LIBSWO_PACKET_TYPE_HW: handle_hw_packet(packet); break; + case LIBSWO_PACKET_TYPE_DWT_EVTCNT: + handle_dwt_evtcnt_packet(packet); + break; + case LIBSWO_PACKET_TYPE_DWT_EXCTRACE: + handle_dwt_exctrace_packet(packet); + break; + case LIBSWO_PACKET_TYPE_DWT_PC_SAMPLE: + handle_dwt_pc_sample_packet(packet); + break; + case LIBSWO_PACKET_TYPE_DWT_PC_VALUE: + handle_dwt_pc_value_packet(packet); + break; + case LIBSWO_PACKET_TYPE_DWT_ADDR_OFFSET: + handle_dwt_addr_offset_packet(packet); + break; + case LIBSWO_PACKET_TYPE_DWT_DATA_VALUE: + handle_dwt_data_value_packet(packet); + break; default: g_warning("Invalid packet type: %u.", packet->type); break; @@ -457,12 +590,12 @@ int main(int argc, char **argv) (1 << LIBSWO_PACKET_TYPE_EXT) | \ (1 << LIBSWO_PACKET_TYPE_INST) | \ (1 << LIBSWO_PACKET_TYPE_HW) | \ - (1 << DWT_PACKET_TYPE_EVENT_COUNTER) | \ - (1 << DWT_PACKET_TYPE_EXCEPTION_TRACE) | \ - (1 << DWT_PACKET_TYPE_PC_SAMPLE) | \ - (1 << DWT_PACKET_TYPE_DT_PC_VALUE) | \ - (1 << DWT_PACKET_TYPE_DT_ADDR_OFFSET) | \ - (1 << DWT_PACKET_TYPE_DT_DATA_VALUE); + (1 << LIBSWO_PACKET_TYPE_DWT_EVTCNT) | \ + (1 << LIBSWO_PACKET_TYPE_DWT_EXCTRACE) | \ + (1 << LIBSWO_PACKET_TYPE_DWT_PC_SAMPLE) | \ + (1 << LIBSWO_PACKET_TYPE_DWT_PC_VALUE) | \ + (1 << LIBSWO_PACKET_TYPE_DWT_ADDR_OFFSET) | \ + (1 << LIBSWO_PACKET_TYPE_DWT_DATA_VALUE); /* Disable instrumentation source address filtering by default. */ inst_address_filter = 0xffffffff; diff --git a/src/swodec.h b/src/swodec.h deleted file mode 100644 index 08eed3f..0000000 --- a/src/swodec.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This file is part of the swodec project. - * - * Copyright (C) 2015 Marc Schink - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that 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. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef SWODEC_SWODEC_H -#define SWODEC_SWODEC_H - -#include - -/* Data Watchpoint and Trace (DWT) packet types. */ -enum dwt_packet_type { - /* Event counter packet. */ - DWT_PACKET_TYPE_EVENT_COUNTER = LIBSWO_PACKET_TYPE_HW + 1, - /* Exception trace packet. */ - DWT_PACKET_TYPE_EXCEPTION_TRACE, - /* Periodic PC sample packet. */ - DWT_PACKET_TYPE_PC_SAMPLE, - /* Data trace PC value packet. */ - DWT_PACKET_TYPE_DT_PC_VALUE, - /* Data trace address offset packet. */ - DWT_PACKET_TYPE_DT_ADDR_OFFSET, - /* Data trace data value packet. */ - DWT_PACKET_TYPE_DT_DATA_VALUE -}; - -extern uint16_t packet_type_filter; - -gboolean dwt_handle_packet(const struct libswo_packet_hw *packet); - -#endif /* SWODEC_SWODEC_H */ -- 2.11.4.GIT