summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Schodet2016-11-17 14:38:19 +0100
committerNicolas Schodet2019-10-09 23:05:51 +0200
commite28de03c88d396d2dc45afbc720c5e555d480526 (patch)
treefb596dfebbbcce3844366b0f397eb40f75feef0e
parent54971d4b01b927a8b29a16a13c2708730bc209f9 (diff)
ucoo/utils: add trace dump without debuger
-rw-r--r--ucoo/hal/i2c/i2c_hard.stm32.cc2
-rw-r--r--ucoo/hal/timer/timer.hh5
-rw-r--r--ucoo/hal/usb/test/Makefile2
-rw-r--r--ucoo/hal/usb/usb_driver.cc2
-rw-r--r--ucoo/utils/Module2
-rw-r--r--ucoo/utils/trace.cc79
-rw-r--r--ucoo/utils/trace.hh51
-rw-r--r--ucoo/utils/trace.tcc48
8 files changed, 183 insertions, 8 deletions
diff --git a/ucoo/hal/i2c/i2c_hard.stm32.cc b/ucoo/hal/i2c/i2c_hard.stm32.cc
index 22567c9..fa0266b 100644
--- a/ucoo/hal/i2c/i2c_hard.stm32.cc
+++ b/ucoo/hal/i2c/i2c_hard.stm32.cc
@@ -30,7 +30,7 @@
namespace ucoo {
/// Local trace.
-static Trace<CONFIG_UCOO_HAL_I2C_TRACE> i2c_trace;
+static Trace<CONFIG_UCOO_HAL_I2C_TRACE> i2c_trace ("i2c");
/// Information on I2C hardware structure.
struct i2c_hardware_t
diff --git a/ucoo/hal/timer/timer.hh b/ucoo/hal/timer/timer.hh
index ab0fa18..31f785f 100644
--- a/ucoo/hal/timer/timer.hh
+++ b/ucoo/hal/timer/timer.hh
@@ -23,6 +23,7 @@
// DEALINGS IN THE SOFTWARE.
//
// }}}
+#include <cstdio>
#if defined TARGET_stm32
# include "timer.stm32.hh"
@@ -44,6 +45,10 @@ struct TimerTraceTimestamp
{
e.timestamp = Timer::get_value ();
}
+ int dump (const Entry &e, const Entry &eprev, char *buf) const
+ {
+ return sprintf (buf, "[%+8d] ", static_cast<int> (e.timestamp - eprev.timestamp));
+ }
};
} // namespace ucoo
diff --git a/ucoo/hal/usb/test/Makefile b/ucoo/hal/usb/test/Makefile
index d4849df..cac90d8 100644
--- a/ucoo/hal/usb/test/Makefile
+++ b/ucoo/hal/usb/test/Makefile
@@ -4,6 +4,6 @@ TARGETS = stm32f4
PROGS = test_usb
test_usb_SOURCES = test_usb.cc
-MODULES = ucoo/hal/usb ucoo/hal/gpio
+MODULES = ucoo/hal/usb ucoo/hal/gpio ucoo/utils
include $(BASE)/build/top.mk
diff --git a/ucoo/hal/usb/usb_driver.cc b/ucoo/hal/usb/usb_driver.cc
index efd8e6c..e53fe2f 100644
--- a/ucoo/hal/usb/usb_driver.cc
+++ b/ucoo/hal/usb/usb_driver.cc
@@ -26,7 +26,7 @@
namespace ucoo {
-Trace<CONFIG_UCOO_HAL_USB_TRACE> usb_trace;
+Trace<CONFIG_UCOO_HAL_USB_TRACE> usb_trace ("usb");
void
UsbDriver::register_application (UsbApplication &app)
diff --git a/ucoo/utils/Module b/ucoo/utils/Module
index 1d101e4..4da0530 100644
--- a/ucoo/utils/Module
+++ b/ucoo/utils/Module
@@ -1 +1 @@
-ucoo_utils_SOURCES := delay.arm.cc crc.cc
+ucoo_utils_SOURCES := delay.arm.cc crc.cc trace.cc
diff --git a/ucoo/utils/trace.cc b/ucoo/utils/trace.cc
new file mode 100644
index 0000000..27a99a8
--- /dev/null
+++ b/ucoo/utils/trace.cc
@@ -0,0 +1,79 @@
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2016 Nicolas Schodet
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// }}}
+#include "ucoo/utils/trace.hh"
+#include <cstring>
+
+namespace ucoo {
+
+void
+TraceRegistry::register_trace_buffer (TraceBufferBase &b)
+{
+ TraceRegistry &self = get_instance ();
+ b.next_ = self.first;
+ self.first = &b;
+}
+
+bool
+TraceRegistry::dump_all (std::function<bool (const char *str, int str_size)>
+ dump_callback)
+{
+ return dump (nullptr, dump_callback);
+}
+
+bool
+TraceRegistry::dump (const char *name,
+ std::function<bool (const char *str, int str_size)>
+ dump_callback)
+{
+ bool ok = true;
+ TraceRegistry &self = get_instance ();
+ TraceBufferBase *b = self.first;
+ while (b)
+ {
+ if (!name || std::strcmp (name, b->name_) == 0)
+ {
+ {
+ char buf[128];
+ int r = snprintf (buf, sizeof (buf) - 1, "---[%s]---", b->name_);
+ if (r >= static_cast<int> (sizeof (buf) - 1))
+ r = sizeof (buf) - 2;
+ buf[r++] = '\n';
+ buf[r++] = '\0';
+ ok = ok && dump_callback (buf, r);
+ }
+ ok = ok && b->dump (dump_callback);
+ }
+ b = b->next_;
+ }
+ return ok;
+}
+
+TraceRegistry &
+TraceRegistry::get_instance ()
+{
+ static TraceRegistry instance;
+ return instance;
+}
+
+} // namespace ucoo
diff --git a/ucoo/utils/trace.hh b/ucoo/utils/trace.hh
index 7cae33d..6c73593 100644
--- a/ucoo/utils/trace.hh
+++ b/ucoo/utils/trace.hh
@@ -23,6 +23,7 @@
// DEALINGS IN THE SOFTWARE.
//
// }}}
+#include <functional>
namespace ucoo {
@@ -33,11 +34,28 @@ struct NoTimestamp
struct Entry { };
/// Fill an entry with current timestamp.
void operator () (Entry &) { }
+ /// Dump an entry timestamp, there is room for 32 characters, return the
+ /// dumped text length.
+ int dump (const Entry &e, const Entry &eprev, char *buf) const { return 0; }
+};
+
+/// Trace buffer common base.
+class TraceBufferBase
+{
+ public:
+ /// Dump as text, call dump_callback several time with text dump.
+ virtual bool dump (std::function<bool (
+ const char *str, int str_size)> dump_callback) const = 0;
+ protected:
+ constexpr TraceBufferBase (const char *name) : name_ (name) { }
+ friend class TraceRegistry;
+ const char *name_;
+ TraceBufferBase *next_ = nullptr;
};
/// Trace buffer to be read with debugger.
template<typename Timestamp = NoTimestamp>
-class TraceBuffer
+class TraceBuffer : public TraceBufferBase
{
/// Maximum number of arguments.
static const int args_nb = 4;
@@ -45,7 +63,7 @@ class TraceBuffer
static const int entries_nb = 512;
public:
/// Constructor.
- TraceBuffer (const Timestamp &timestamp = Timestamp ());
+ TraceBuffer (const char *name, const Timestamp &timestamp = Timestamp ());
/// Trace without argument.
inline void operator() (const char *str);
/// Trace with N arguments...
@@ -53,6 +71,9 @@ class TraceBuffer
inline void operator() (const char *str, int a0, int a1);
inline void operator() (const char *str, int a0, int a1, int a2);
inline void operator() (const char *str, int a0, int a1, int a2, int a3);
+ /// See TraceBufferBase::dump.
+ bool dump (std::function<bool (
+ const char *str, int str_size)> dump_callback) const override;
private:
/// Trace entry, contains all given parameters.
struct Entry : public Timestamp::Entry
@@ -72,11 +93,15 @@ class TraceBuffer
class TraceDummy
{
public:
+ TraceDummy (const char *name) { }
inline void operator() (const char *str) { }
inline void operator() (const char *str, int a0) { }
inline void operator() (const char *str, int a0, int a1) { }
inline void operator() (const char *str, int a0, int a1, int a2) { }
inline void operator() (const char *str, int a0, int a1, int a2, int a3) { }
+ bool dump (std::function<bool (
+ const char *str, int str_size)> dump_callback) const
+ { return true; }
};
/// Conditional trace, whether it trace or not depends on the template
@@ -89,11 +114,33 @@ class Trace
template<typename Timestamp>
class Trace<true, Timestamp> : public TraceBuffer<Timestamp>
{
+ public:
+ constexpr Trace (const char *name) : TraceBuffer<Timestamp> (name) { }
};
template<typename Timestamp>
class Trace<false, Timestamp> : public TraceDummy
{
+ public:
+ constexpr Trace (const char *name) : TraceDummy (name) { }
+};
+
+/// Registry of all active traces.
+class TraceRegistry
+{
+ public:
+ /// Register a trace buffer (called automatically on trace buffer
+ /// construction).
+ static void register_trace_buffer (TraceBufferBase &b);
+ /// Dump all active traces as text.
+ static bool dump_all (std::function<bool (
+ const char *str, int str_size)> dump_callback);
+ /// Dump specified trace as text.
+ static bool dump (const char *name, std::function<bool (
+ const char *str, int str_size)> dump_callback);
+ private:
+ static TraceRegistry &get_instance ();
+ TraceBufferBase *first = nullptr;
};
} // namespace ucoo
diff --git a/ucoo/utils/trace.tcc b/ucoo/utils/trace.tcc
index 8d1fc29..1a64e8c 100644
--- a/ucoo/utils/trace.tcc
+++ b/ucoo/utils/trace.tcc
@@ -23,13 +23,17 @@
// DEALINGS IN THE SOFTWARE.
//
// }}}
+#include <cstdio>
namespace ucoo {
template<typename Timestamp>
-TraceBuffer<Timestamp>::TraceBuffer (const Timestamp &timestamp)
- : entries{}, index (0), timestamp_ (timestamp)
+TraceBuffer<Timestamp>::TraceBuffer (const char *name,
+ const Timestamp &timestamp)
+ : TraceBufferBase (name),
+ entries{}, index (0), timestamp_ (timestamp)
{
+ TraceRegistry::register_trace_buffer (*this);
}
template<typename Timestamp>
@@ -88,6 +92,46 @@ TraceBuffer<Timestamp>::operator() (const char *str, int a0, int a1, int a2,
index = (index + 1) % entries_nb;
}
+template<typename Timestamp>
+bool
+TraceBuffer<Timestamp>::dump (std::function<bool (
+ const char *str, int str_size)> dump_callback) const
+{
+ bool ok = true;
+ unsigned int i = index;
+ if (!entries[i].str)
+ i = 0;
+ if (entries[i].str)
+ {
+ unsigned int iprev = i;
+ do
+ {
+ char buf[128];
+ int buf_size;
+ buf_size = timestamp_.dump (entries[i], entries[iprev], buf);
+ int r = snprintf (buf + buf_size, sizeof (buf) - buf_size - 1,
+ entries[i].str,
+ entries[i].args[0], entries[i].args[1],
+ entries[i].args[2], entries[i].args[3]);
+ if (r >= static_cast<int> (sizeof (buf) - buf_size - 1))
+ {
+ buf_size = sizeof (buf - 5);
+ buf[buf_size++] = '.';
+ buf[buf_size++] = '.';
+ buf[buf_size++] = '.';
+ }
+ else
+ buf_size += r;
+ buf[buf_size++] = '\n';
+ buf[buf_size++] = '\0';
+ ok = ok && dump_callback (buf, buf_size);
+ iprev = i;
+ i = (i + 1) % entries_nb;
+ } while (i != index && ok);
+ }
+ return ok;
+}
+
} // namespace ucoo
#endif // ucoo_utils_trace_tcc