kdebug.c

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