kdebug.c

Go to the documentation of this file.
00001 
00041 #include <cpu/irq.h>
00042 #include <cpu/attr.h>
00043 #include <cpu/types.h>
00044 
00045 #include <cfg/macros.h> /* for BV() */
00046 #include <cfg/debug.h>
00047 
00048 #include <appconfig.h>
00049 
00050 #include <mware/formatwr.h> /* for _formatted_write() */
00051 #include <mware/pgm.h>
00052 
00053 #ifdef _DEBUG
00054 
00055 #if CPU_HARVARD && !defined(_PROGMEM)
00056     #error This module build correctly only in program memory!
00057 #endif
00058 
00059 
00060 #if OS_HOSTED
00061     #include <stdio.h>
00062     #define KDBG_WAIT_READY()      do { /*nop*/ } while(0)
00063     #define KDBG_WRITE_CHAR(c)     putc((c), stderr)
00064     #define KDBG_MASK_IRQ(old)     do { (void)(old); } while(0)
00065     #define KDBG_RESTORE_IRQ(old)  do { /*nop*/ } while(0)
00066     typedef char kdbg_irqsave_t; /* unused */
00067 
00068     #define kdbg_hw_init() do {} while (0) 
00069 
00070     #if CONFIG_KDEBUG_PORT == 666
00071         #error BITBANG debug console missing for this platform
00072     #endif
00073 #else
00074     #include CPU_CSOURCE(kdebug)
00075 #endif
00076 
00077 
00078 void kdbg_init(void)
00079 {
00080     /* Init debug hw */
00081     kdbg_hw_init();
00082     kputs("\n\n*** BeRTOS DBG START ***\n");
00083 }
00084 
00085 
00089 static void __kputchar(char c, UNUSED_ARG(void *, unused))
00090 {
00091     /* Poll while serial buffer is still busy */
00092     KDBG_WAIT_READY();
00093 
00094     /* Send '\n' as '\r\n' for dumb terminals */
00095     if (c == '\n')
00096     {
00097         KDBG_WRITE_CHAR('\r');
00098         KDBG_WAIT_READY();
00099     }
00100 
00101     KDBG_WRITE_CHAR(c);
00102 }
00103 
00104 
00105 void kputchar(char c)
00106 {
00107     /* Mask serial TX intr */
00108     kdbg_irqsave_t irqsave;
00109     KDBG_MASK_IRQ(irqsave);
00110 
00111     __kputchar(c, 0);
00112 
00113     /* Restore serial TX intr */
00114     KDBG_RESTORE_IRQ(irqsave);
00115 }
00116 
00117 
00118 static void PGM_FUNC(kvprintf)(const char * PGM_ATTR fmt, va_list ap)
00119 {
00120 #if CONFIG_PRINTF
00121     /* Mask serial TX intr */
00122     kdbg_irqsave_t irqsave;
00123     KDBG_MASK_IRQ(irqsave);
00124 
00125     PGM_FUNC(_formatted_write)(fmt, __kputchar, 0, ap);
00126 
00127     /* Restore serial TX intr */
00128     KDBG_RESTORE_IRQ(irqsave);
00129 #else
00130     /* A better than nothing printf() surrogate. */
00131     PGM_FUNC(kputs)(fmt);
00132 #endif /* CONFIG_PRINTF */
00133 }
00134 
00135 void PGM_FUNC(kprintf)(const char * PGM_ATTR fmt, ...)
00136 {
00137     va_list ap;
00138 
00139     va_start(ap, fmt);
00140     PGM_FUNC(kvprintf)(fmt, ap);
00141     va_end(ap);
00142 }
00143 
00144 void PGM_FUNC(kputs)(const char * PGM_ATTR str)
00145 {
00146     char c;
00147 
00148     /* Mask serial TX intr */
00149     kdbg_irqsave_t irqsave;
00150     KDBG_MASK_IRQ(irqsave);
00151 
00152     while ((c = PGM_READ_CHAR(str++)))
00153         __kputchar(c, 0);
00154 
00155     KDBG_RESTORE_IRQ(irqsave);
00156 }
00157 
00158 
00162 int kputnum(int num)
00163 {
00164     int output_len = 0;
00165     int divisor = 10000;
00166     int digit;
00167 
00168     do
00169     {
00170         digit = num / divisor;
00171         num %= divisor;
00172 
00173         if (digit || output_len || divisor == 1)
00174         {
00175             kputchar(digit + '0');
00176             ++output_len;
00177         }
00178     }
00179     while (divisor /= 10);
00180 
00181     return output_len;
00182 }
00183 
00184 
00185 static void klocation(const char * PGM_ATTR file, int line)
00186 {
00187     PGM_FUNC(kputs)(file);
00188     kputchar(':');
00189     kputnum(line);
00190     PGM_FUNC(kputs)(PGM_STR(": "));
00191 }
00192 
00193 int PGM_FUNC(__assert)(const char * PGM_ATTR cond, const char * PGM_ATTR file, int line)
00194 {
00195     klocation(file, line);
00196     PGM_FUNC(kputs)(PGM_STR("Assertion failed: "));
00197     PGM_FUNC(kputs)(cond);
00198     kputchar('\n');
00199     BREAKPOINT;
00200     return 1;
00201 }
00202 
00203 /*
00204  * Unfortunately, there's no way to get __func__ in
00205  * program memory, so we waste quite a lot of RAM in
00206  * AVR and other Harvard processors.
00207  */
00208 void PGM_FUNC(__trace)(const char *name)
00209 {
00210     PGM_FUNC(kprintf)(PGM_STR("%s()\n"), name);
00211 }
00212 
00213 void PGM_FUNC(__tracemsg)(const char *name, const char * PGM_ATTR fmt, ...)
00214 {
00215     va_list ap;
00216 
00217     PGM_FUNC(kprintf)(PGM_STR("%s(): "), name);
00218     va_start(ap, fmt);
00219     PGM_FUNC(kvprintf)(fmt, ap);
00220     va_end(ap);
00221     kputchar('\n');
00222 }
00223 
00224 int PGM_FUNC(__invalid_ptr)(void *value, const char * PGM_ATTR name, const char * PGM_ATTR file, int line)
00225 {
00226     klocation(file, line);
00227     PGM_FUNC(kputs)(PGM_STR("Invalid ptr: "));
00228     PGM_FUNC(kputs)(name);
00229     #if CONFIG_PRINTF
00230         PGM_FUNC(kprintf)(PGM_STR(" = 0x%p\n"), value);
00231     #else
00232         (void)value;
00233         kputchar('\n');
00234     #endif
00235     return 1;
00236 }
00237 
00238 
00239 void __init_wall(long *wall, int size)
00240 {
00241     while(size--)
00242         *wall++ = WALL_VALUE;
00243 }
00244 
00245 
00246 int PGM_FUNC(__check_wall)(long *wall, int size, const char * PGM_ATTR name, const char * PGM_ATTR file, int line)
00247 {
00248     int i, fail = 0;
00249 
00250     for (i = 0; i < size; i++)
00251     {
00252         if (wall[i] != WALL_VALUE)
00253         {
00254             klocation(file, line);
00255             PGM_FUNC(kputs)(PGM_STR("Wall broken: "));
00256             PGM_FUNC(kputs)(name);
00257             #if CONFIG_PRINTF
00258                 PGM_FUNC(kprintf)(PGM_STR("[%d] (0x%p) = 0x%lx\n"), i, wall + i, wall[i]);
00259             #else
00260                 kputchar('\n');
00261             #endif
00262             fail = 1;
00263         }
00264     }
00265 
00266     return fail;
00267 }
00268 
00269 
00270 #if CONFIG_PRINTF
00271 
00275 void kdump(const void *_buf, size_t len)
00276 {
00277     const unsigned char *buf = (const unsigned char *)_buf;
00278 
00279     while (len--)
00280         kprintf("%02X", *buf++);
00281     kputchar('\n');
00282 }
00283 
00284 #endif /* CONFIG_PRINTF */
00285 
00286 #endif /* _DEBUG */