/*!
* \file
* <!--
- * Copyright 2003, 2004 Develer S.r.l. (http://www.develer.com/)
- * This file is part of DevLib - See devlib/README for information.
+ * Copyright 2003, 2004, 2005 Develer S.r.l. (http://www.develer.com/)
+ * This file is part of DevLib - See README.devlib for information.
* -->
*
- * \brief Simple debug facilities for hosted and embedded C/C++ applications
+ * \brief Simple debug facilities for hosted and embedded C/C++ applications.
*
- * Debug output goes to stderr in hosted applications. Freestanding (AKA embedded)
- * applications use drv/kdebug.c to output diagnostic messages to a serial terminal
- * or a JTAG debugger.
+ * Debug output goes to stderr in hosted applications.
+ * Freestanding (AKA embedded) applications use \c drv/kdebug.c to output
+ * diagnostic messages to a serial terminal or a JTAG debugger.
*
* \version $Id$
* \author Bernardo Innocenti <bernie@develer.com>
/*#*
*#* $Log$
- *#* Revision 1.2 2004/09/14 21:01:46 bernie
- *#* Mark assertions as LIKELY().
+ *#* Revision 1.12 2005/02/18 11:18:33 bernie
+ *#* Fixes for Harvard processors from project_ks.
*#*
- *#* Revision 1.1 2004/09/14 20:19:47 bernie
- *#* Unified debug macros.
+ *#* Revision 1.11 2005/02/16 20:29:48 bernie
+ *#* TRACE(), TRACEMSG(): Reduce code and data footprint.
*#*
- *#* Revision 1.3 2004/09/06 12:11:29 bernie
- *#* Merge debug.h with DevLib.
+ *#* Revision 1.10 2005/02/09 21:50:28 bernie
+ *#* Declare dummy ASSERT* macros as ((void)0) to work around a warning I can't remember any more.
*#*
- *#* Revision 1.2 2004/08/13 03:22:07 bernie
- *#* Resurrect some debug macros from old projects.
+ *#* Revision 1.9 2005/01/25 08:36:40 bernie
+ *#* kputnum(): Export.
*#*
- *#* Revision 1.1 2004/08/12 06:56:35 bernie
- *#* Move debug.h from device/ to util/.
+ *#* Revision 1.8 2005/01/11 18:08:08 aleph
+ *#* Add empty kdump definition for debug off
*#*
- *#* Revision 1.1 2004/08/12 06:52:26 bernie
- *#* Factor out a few simple debug macros.
+ *#* Revision 1.7 2004/12/31 17:43:09 bernie
+ *#* Use UNUSED_ARG instead of obsolete UNUSED macro.
*#*
+ *#* Revision 1.6 2004/12/08 08:52:00 bernie
+ *#* Save some more RAM on AVR.
*#*/
#ifndef DEVLIB_DEBUG_H
#define DEVLIB_DEBUG_H
#ifndef INLINE
#define INLINE static inline
#endif
- #ifndef UNUSED
- #define UNUSED(type,name) type
+ #ifndef UNUSED_ARG
+ #ifdef __cplusplus
+ #define UNUSED_ARG(type,name) type
+ #else
+ #define UNUSED_ARG(type,name) type name
+ #endif
#endif
#else /* !OS_HOSTED */
#include <compiler.h>
#endif /* !OS_HOSTED */
-/*!
- * \def _DEBUG
- *
+/*
* This preprocessor symbol is defined only in debug builds.
*
* The build infrastructure must arrange for _DEBUG to
* statements conditioned on \c _DEBUG, avoiding the clutter
* of #ifdef/#endif pairs.
*
- * \example
+ * \code
* struct FooBar
* {
* int foo;
* DB(--ref_count;)
* }
* };
- *
- * \endexample
+ * \endcode
*/
#define DB(x) x
#if OS_HOSTED
#include <stdio.h>
#include <stdarg.h>
+
INLINE void kdbg_init(void) { /* nop */ }
INLINE void kputchar(char c)
{
#define ASSERT_VALID_PTR_OR_NULL(p) ASSERT((((p) == NULL) || ((unsigned long)(p) >= 0x200)))
#else /* !OS_HOSTED */
+ #include <config.h> /* CONFIG_KDEBUG_ASSERT_NO_TEXT */
+ #include <cpu.h> /* CPU_HARVARD */
+
/* These are implemented in drv/kdebug.c */
void kdbg_init(void);
void kputchar(char c);
+ int kputnum(int num);
void kdump(const void *buf, size_t len);
+ void __init_wall(long *wall, int size);
- #ifdef __AVR__
- #include <avr/pgmspace.h>
+ #if CPU_HARVARD
+ #include <mware/pgm.h>
void kputs_P(const char *PROGMEM str);
void kprintf_P(const char *PROGMEM fmt, ...) FORMAT(__printf__, 1, 2);
int __assert_P(const char *PROGMEM cond, const char *PROGMEM file, int line);
+ void __trace_P(const char *func);
+ void __tracemsg_P(const char *func, const char *PROGMEM fmt, ...);
int __invalid_ptr_P(void *p, const char *PROGMEM name, const char *PROGMEM file, int line);
+ int __check_wall_P(long *wall, int size, const char * PGM_ATTR name, const char * PGM_ATTR file, int line);
#define kputs(str) kputs_P(PSTR(str))
#define kprintf(fmt, ...) kprintf_P(PSTR(fmt) ,## __VA_ARGS__)
#define __assert(cond, file, line) __assert_P(PSTR(cond), PSTR(file), (line))
+ #define __trace(func) __trace_P(func)
+ #define __tracemsg(func, fmt, ...) __tracemsg_P(func, PSTR(fmt), ## __VA_ARGS__)
#define __invalid_ptr(p, name, file, line) __invalid_ptr_P((p), PSTR(name), PSTR(file), (line))
- #else /* !__AVR__ */
+ #define __check_wall(wall, size, name, file, line) __check_wall_P(wall, size, PSTR(name), PSTR(file), (line))
+ #else /* !CPU_HARVARD */
void kputs(const char *str);
- void kprintf(const char * fmt, ...) FORMAT(__printf__, 1, 2);
+ void kprintf(const char *fmt, ...) FORMAT(__printf__, 1, 2);
int __assert(const char *cond, const char *file, int line);
+ void __trace(const char *func);
+ void __tracemsg(const char *func, const char *fmt, ...) FORMAT(__printf__, 2, 3);
int __invalid_ptr(void *p, const char *name, const char *file, int line);
- #endif /* !__AVR__ */
-
- void __init_wall(long *wall, int size);
- int __check_wall(long *wall, int size, const char *name, const char *file, int line);
+ int __check_wall(long *wall, int size, const char *name, const char *file, int line);
+ #endif /* !CPU_HARVARD */
#ifndef CONFIG_KDEBUG_ASSERT_NO_TEXT
- #define ASSERT(x) (LIKELY(x) ? 0 : __assert(#x, THIS_FILE, __LINE__))
- #define ASSERT2(x, help) (LIKELY(x) ? 0 : __assert(help " (" #x ")", THIS_FILE, __LINE__))
+ #define ASSERT(x) ((void)(LIKELY(x) ? 0 : __assert(#x, THIS_FILE, __LINE__)))
+ #define ASSERT2(x, help) ((void)(LIKELY(x) ? 0 : __assert(help " (" #x ")", THIS_FILE, __LINE__)))
#else
- #define ASSERT(x) (LIKELY(x) ? 0 : __assert("", THIS_FILE, __LINE__))
- #define ASSERT2(x, help) ASSERT(x)
+ #define ASSERT(x) ((void)(LIKELY(x) ? 0 : __assert("", THIS_FILE, __LINE__)))
+ #define ASSERT2(x, help) ((void)ASSERT(x))
#endif
- #define ASSERT_VALID_PTR(p) (LIKELY((p) >= 0x200) ? 0 : __invalid_ptr(p, #p, THIS_FILE, __LINE__))
- #define ASSERT_VALID_PTR_OR_NULL(p) (LIKELY((p == NULL) || ((p) >= 0x200)) ? 0 : __invalid_ptr((p), #p, THIS_FILE, __LINE__))
- #define TRACE kprintf("%s()\n", __FUNCTION__)
- #define TRACEMSG(msg,...) kprintf("%s(): " msg "\n", __FUNCTION__, ## __VA_ARGS__)
+ #define ASSERT_VALID_PTR(p) ((void)(LIKELY((p) >= 0x200) ? 0 : __invalid_ptr(p, #p, THIS_FILE, __LINE__)))
+ #define ASSERT_VALID_PTR_OR_NULL(p) ((void)(LIKELY((p == NULL) || ((p) >= 0x200)) ? 0 : __invalid_ptr((p), #p, THIS_FILE, __LINE__)))
+
+ #ifndef CONFIG_KDEBUG_DISABLE_TRACE
+ #define TRACE __trace(__func__)
+ #define TRACEMSG(msg,...) __tracemsg(__func__, msg, ## __VA_ARGS__)
+ #else
+ #define TRACE do {} while(0)
+ #define TRACEMSG(...) do {} while(0)
+ #endif
#endif /* !OS_HOSTED */
* These macros help track some kinds of leaks in C++ programs.
* Usage is as follows:
*
- * \example
+ * \code
* class Foo
* {
* DECLARE_INSTANCE_TRACKING(Foo)
* delete foo;
* ASSERT_ZERO_INSTANCES(Foo); // OK
* }
- *
- * \end example
+ * \endcode
+ * \{
*/
#define NEW_INSTANCE(CLASS) do { ++CLASS::__instances } while (0)
#define DELETE_INSTANCE(CLASS) do { --CLASS::__instances } while (0)
#define GET_INSTANCE_COUNT(CLASS) (CLASS::__instances)
#define DECLARE_INSTANCE_TRACKING(CLASS) static int __instances
#define IMPLEMENT_INSTANCE_TRACKING(CLASS) int CLASS::__instances = 0
+ /*\}*/
#else /* !_DEBUG */
#define DB(x) /* nothing */
#ifndef ASSERT
- #define ASSERT(x) do {} while (0)
+ #define ASSERT(x) ((void)0)
#endif /* ASSERT */
- #define ASSERT2(x, help) do {} while (0)
- #define ASSERT_VALID_PTR(p) do {} while (0)
- #define ASSERT_VALID_PTR_OR_NULL(p) do {} while (0)
- #define ASSERT_VALID_OBJ(_t, _o) do {} while (0)
+ #define ASSERT2(x, help) ((void)0)
+ #define ASSERT_VALID_PTR(p) ((void)0)
+ #define ASSERT_VALID_PTR_OR_NULL(p) ((void)0)
+ #define ASSERT_VALID_OBJ(_t, _o) ((void)0)
#define TRACE do {} while (0)
#define TRACEMSG(x,...) do {} while (0)
#define IMPLEMENT_INSTANCE_TRACKING(CLASS)
INLINE void kdbg_init(void) { /* nop */ }
- INLINE void kputchar(UNUSED(char, c)) { /* nop */ }
- INLINE void kputs(UNUSED(const char*, str)) { /* nop */ }
- INLINE void kprintf(UNUSED(const char*, fmt), ...) { /* nop */ }
+ INLINE void kputchar(UNUSED_ARG(char, c)) { /* nop */ }
+ INLINE int kputnum(UNUSED_ARG(int, num)) { return 0; }
+ INLINE void kputs(UNUSED_ARG(const char *, str)) { /* nop */ }
+ INLINE void kdump(UNUSED_ARG(const void *, buf), UNUSED_ARG(size_t, len)) { /* nop */ }
+
+ #ifdef __cplusplus
+ /* G++ can't inline functions with variable arguments... */
+ #define kprintf(fmt,...) do { (void)(fmt); } while(0)
+ #else
+ /* ...but GCC can. */
+ INLINE void kprintf(UNUSED_ARG(const char *, fmt), ...) { /* nop */ }
+ #endif
#endif /* _DEBUG */