diff --git a/arch/cpu/arm/arm-def.h b/arch/cpu/arm/arm-def.h index 2cd31604c..92b19048d 100644 --- a/arch/cpu/arm/arm-def.h +++ b/arch/cpu/arm/arm-def.h @@ -60,6 +60,25 @@ typedef uint32_t uip_stats_t; typedef uint32_t rtimer_clock_t; #define RTIMER_CLOCK_DIFF(a, b) ((int32_t)((a) - (b))) /** @} */ + +/* + * The stdio.h that ships with the arm-gcc toolchain does this: + * + * int _EXFUN(putchar, (int)); + * [...] + * #define putchar(x) putc(x, stdout) + * + * This causes us a lot of trouble: For platforms using this toolchain, every + * time we use putchar we need to first #undef putchar. What we do here is to + * #undef putchar across the board. The resulting code will cause the linker + * to search for a symbol named putchar and this allows us to use the + * implementation under os/lib/dbg-io. + * + * This will fail if stdio.h is included before contiki.h, but it is common + * practice to include contiki.h first + */ +#include +#undef putchar /*---------------------------------------------------------------------------*/ #endif /* ARM_DEF_ */ /*---------------------------------------------------------------------------*/ diff --git a/arch/cpu/arm/common/SD-card/cfs-sdcard.c b/arch/cpu/arm/common/SD-card/cfs-sdcard.c index 9be29fd2e..4c44e3e6b 100644 --- a/arch/cpu/arm/common/SD-card/cfs-sdcard.c +++ b/arch/cpu/arm/common/SD-card/cfs-sdcard.c @@ -1,7 +1,6 @@ #include #include #include -#include #include diff --git a/arch/cpu/arm/common/dbg-io/dbg-printf.c b/arch/cpu/arm/common/dbg-io/dbg-printf.c deleted file mode 100644 index 9bd09c1ac..000000000 --- a/arch/cpu/arm/common/dbg-io/dbg-printf.c +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include -#include - -static StrFormatResult -write_str(void *user_data, const char *data, unsigned int len) -{ - if (len > 0) dbg_send_bytes((unsigned char*)data, len); - return STRFORMAT_OK; -} - - -static StrFormatContext ctxt = - { - write_str, - NULL - }; -int -printf(const char *fmt, ...) -{ - int res; - va_list ap; - va_start(ap, fmt); - res = format_str_v(&ctxt, fmt, ap); - va_end(ap); - return res; -} - - diff --git a/arch/cpu/arm/common/dbg-io/dbg-putchar.c b/arch/cpu/arm/common/dbg-io/dbg-putchar.c deleted file mode 100644 index 54f3db53f..000000000 --- a/arch/cpu/arm/common/dbg-io/dbg-putchar.c +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include -#include - -#undef putchar -#undef putc - -int -putchar(int c) -{ - dbg_putchar(c); - return c; -} - -int -putc(int c, FILE *f) -{ - dbg_putchar(c); - return c; -} - -int -__sp(struct _reent *_ptr, int c, FILE *_p) { - dbg_putchar(c); - return c; -} diff --git a/arch/cpu/arm/common/dbg-io/dbg-puts.c b/arch/cpu/arm/common/dbg-io/dbg-puts.c deleted file mode 100644 index fa90d1022..000000000 --- a/arch/cpu/arm/common/dbg-io/dbg-puts.c +++ /dev/null @@ -1,11 +0,0 @@ -#include -#include -#include - -int -puts(const char *str) -{ - dbg_send_bytes((unsigned char*)str, strlen(str)); - dbg_putchar('\n'); - return 0; -} diff --git a/arch/cpu/arm/common/dbg-io/dbg-snprintf.c b/arch/cpu/arm/common/dbg-io/dbg-snprintf.c deleted file mode 100644 index 230d6891a..000000000 --- a/arch/cpu/arm/common/dbg-io/dbg-snprintf.c +++ /dev/null @@ -1,48 +0,0 @@ -#include -#include -#include - -struct FmtBuffer -{ - char *pos; - size_t left; -}; - -static StrFormatResult -buffer_str(void *user_data, const char *data, unsigned int len) -{ - struct FmtBuffer *buffer = (struct FmtBuffer*)user_data; - if (len >= buffer->left) { - len = buffer->left; - len--; - } - - memcpy(buffer->pos, data, len); - buffer->pos += len; - buffer->left -= len; - return STRFORMAT_OK; -} - -int snprintf(char *str, size_t size, const char *format, ...) -{ - int res; - va_list ap; - va_start(ap, format); - res = vsnprintf(str, size, format, ap); - va_end(ap); - return res; -} - -int vsnprintf(char *str, size_t size, const char *format, va_list ap) -{ - struct FmtBuffer buffer; - StrFormatContext ctxt; - int res; - ctxt.write_str = buffer_str; - ctxt.user_data = &buffer; - buffer.pos = str; - buffer.left = size; - res = format_str_v(&ctxt, format, ap); - *buffer.pos = '\0'; - return res; -} diff --git a/arch/cpu/arm/common/dbg-io/dbg-sprintf.c b/arch/cpu/arm/common/dbg-io/dbg-sprintf.c deleted file mode 100644 index 8124fc363..000000000 --- a/arch/cpu/arm/common/dbg-io/dbg-sprintf.c +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include -#include - -static StrFormatResult -buffer_str(void *user_data, const char *data, unsigned int len) -{ - memcpy(*(char**)user_data, data, len); - (*(char**)user_data) += len; - return STRFORMAT_OK; -} - -int -sprintf(char *str, const char *format, ...) -{ - StrFormatContext ctxt; - int res; - va_list ap; - va_start(ap, format); - ctxt.write_str = buffer_str; - ctxt.user_data = &str; - res = format_str_v(&ctxt, format, ap); - *str = '\0'; - va_end(ap); - return res; -} diff --git a/arch/cpu/arm/common/dbg-io/strformat.c b/arch/cpu/arm/common/dbg-io/strformat.c deleted file mode 100644 index 13b91a563..000000000 --- a/arch/cpu/arm/common/dbg-io/strformat.c +++ /dev/null @@ -1,617 +0,0 @@ -#include - -#define HAVE_DOUBLE - -#define HAVE_LONGLONG -#ifndef LARGEST_SIGNED -#ifdef HAVE_LONGLONG -#define LARGEST_SIGNED long long int -#else -#define LARGEST_UNSIGNED long int -#endif -#endif - -#ifndef LARGEST_UNSIGNED -#ifdef HAVE_LONGLONG -#define LARGEST_UNSIGNED unsigned long long int -#else -#define LARGEST_UNSIGNED unsigned long int -#endif -#endif - -#ifndef POINTER_INT -#define POINTER_INT unsigned long -#endif - -typedef unsigned int FormatFlags; - -#define MAKE_MASK(shift,size) (((1 << size) - 1) << (shift)) - -#define JUSTIFY_SHIFT 0 -#define JUSTIFY_SIZE 1 -#define JUSTIFY_RIGHT 0x0000 -#define JUSTIFY_LEFT 0x0001 -#define JUSTIFY_MASK MAKE_MASK(JUSTIFY_SHIFT,JUSTIFY_SIZE) - - -/* How a positive number is prefixed */ -#define POSITIVE_SHIFT (JUSTIFY_SHIFT + JUSTIFY_SIZE) -#define POSITIVE_NONE (0x0000 << POSITIVE_SHIFT) -#define POSITIVE_SPACE (0x0001 << POSITIVE_SHIFT) -#define POSITIVE_PLUS (0x0003 << POSITIVE_SHIFT) -#define POSITIVE_MASK MAKE_MASK(POSITIVE_SHIFT, POSITIVE_SIZE) - -#define POSITIVE_SIZE 2 - -#define ALTERNATE_FORM_SHIFT (POSITIVE_SHIFT + POSITIVE_SIZE) -#define ALTERNATE_FORM_SIZE 1 -#define ALTERNATE_FORM (0x0001 << ALTERNATE_FORM_SHIFT) - - -#define PAD_SHIFT (ALTERNATE_FORM_SHIFT + ALTERNATE_FORM_SIZE) -#define PAD_SIZE 1 -#define PAD_SPACE (0x0000 << PAD_SHIFT) -#define PAD_ZERO (0x0001 << PAD_SHIFT) - -#define SIZE_SHIFT (PAD_SHIFT + PAD_SIZE) -#define SIZE_SIZE 3 -#define SIZE_CHAR (0x0001 << SIZE_SHIFT) -#define SIZE_SHORT (0x0002 << SIZE_SHIFT) -#define SIZE_INT (0x0000 << SIZE_SHIFT) -#define SIZE_LONG (0x0003 << SIZE_SHIFT) -#define SIZE_LONGLONG (0x0004 << SIZE_SHIFT) -#define SIZE_MASK MAKE_MASK(SIZE_SHIFT,SIZE_SIZE) - -#define CONV_SHIFT (SIZE_SHIFT + SIZE_SIZE) -#define CONV_SIZE 3 -#define CONV_INTEGER (0x0001 << CONV_SHIFT) -#define CONV_FLOAT (0x0002 << CONV_SHIFT) -#define CONV_POINTER (0x0003 << CONV_SHIFT) -#define CONV_STRING (0x0004 << CONV_SHIFT) -#define CONV_CHAR (0x0005 << CONV_SHIFT) -#define CONV_PERCENT (0x0006 << CONV_SHIFT) -#define CONV_WRITTEN (0x0007 << CONV_SHIFT) -#define CONV_MASK MAKE_MASK(CONV_SHIFT, CONV_SIZE) - -#define RADIX_SHIFT (CONV_SHIFT + CONV_SIZE) -#define RADIX_SIZE 2 -#define RADIX_DECIMAL (0x0001 << RADIX_SHIFT) -#define RADIX_OCTAL (0x0002 << RADIX_SHIFT) -#define RADIX_HEX (0x0003 << RADIX_SHIFT) -#define RADIX_MASK MAKE_MASK(RADIX_SHIFT,RADIX_SIZE) - -#define SIGNED_SHIFT (RADIX_SHIFT + RADIX_SIZE) -#define SIGNED_SIZE 1 -#define SIGNED_NO (0x0000 << SIGNED_SHIFT) -#define SIGNED_YES (0x0001 << SIGNED_SHIFT) -#define SIGNED_MASK MAKE_MASK(SIGNED_SHIFT,SIGNED_SIZE) - -#define CAPS_SHIFT (SIGNED_SHIFT + SIGNED_SIZE) -#define CAPS_SIZE 1 -#define CAPS_NO (0x0000 << CAPS_SHIFT) -#define CAPS_YES (0x0001 << CAPS_SHIFT) -#define CAPS_MASK MAKE_MASK(CAPS_SHIFT,CAPS_SIZE) - -#define FLOAT_SHIFT (CAPS_SHIFT + CAPS_SIZE) -#define FLOAT_SIZE 2 -#define FLOAT_NORMAL (0x0000 << FLOAT_SHIFT) -#define FLOAT_EXPONENT (0x0001 << FLOAT_SHIFT) -#define FLOAT_DEPENDANT (0x0002 << FLOAT_SHIFT) -#define FLOAT_HEX (0x0003 << FLOAT_SHIFT) -#define FLOAT_MASK MAKE_MASK(FLOAT_SHIFT, FLOAT_SIZE) - -static FormatFlags -parse_flags(const char **posp) -{ - FormatFlags flags = 0; - const char *pos = *posp; - while (1) { - switch(*pos) { - case '-': - flags |= JUSTIFY_LEFT; - break; - case '+': - flags |= POSITIVE_PLUS; - break; - case ' ': - flags |= POSITIVE_SPACE; - break; - case '#': - flags |= ALTERNATE_FORM; - break; - case '0': - flags |= PAD_ZERO; - break; - default: - *posp = pos; - return flags; - } - pos++; - } - -} - -static unsigned int -parse_uint(const char **posp) -{ - unsigned v = 0; - const char *pos = *posp; - char ch; - while((ch = *pos) >= '0' && ch <= '9') { - v = v * 10 + (ch - '0'); - pos++; - } - *posp = pos; - return v; -} - -#define MAXCHARS_HEX ((sizeof(LARGEST_UNSIGNED) * 8) / 4 ) - -/* Largest number of characters needed for converting an unsigned integer. - */ -#define MAXCHARS ((sizeof(LARGEST_UNSIGNED) * 8 + 2) / 3 ) - -static unsigned int -output_uint_decimal(char **posp, LARGEST_UNSIGNED v) -{ - unsigned int len; - char *pos = *posp; - while (v > 0) { - *--pos = (v % 10) + '0'; - v /= 10; - } - len = *posp - pos; - *posp = pos; - return len; -} - -static unsigned int -output_uint_hex(char **posp, LARGEST_UNSIGNED v, unsigned int flags) -{ - unsigned int len; - const char *hex = (flags & CAPS_YES) ?"0123456789ABCDEF":"0123456789abcdef"; - char *pos = *posp; - while (v > 0) { - *--pos = hex[(v % 16)]; - v /= 16; - } - len = *posp - pos; - *posp = pos; - return len; -} - -static unsigned int -output_uint_octal(char **posp, LARGEST_UNSIGNED v) -{ - unsigned int len; - char *pos = *posp; - while (v > 0) { - *--pos = (v % 8) + '0'; - v /= 8; - } - len = *posp - pos; - *posp = pos; - return len; -} - -static StrFormatResult -fill_space(const StrFormatContext *ctxt, unsigned int len) -{ - StrFormatResult res; - static const char buffer[16] = " "; - while(len > 16) { - res = ctxt->write_str(ctxt->user_data, buffer, 16); - if (res != STRFORMAT_OK) return res; - len -= 16; - } - if (len == 0) return STRFORMAT_OK; - return ctxt->write_str(ctxt->user_data, buffer, len); -} - -static StrFormatResult -fill_zero(const StrFormatContext *ctxt, unsigned int len) -{ - StrFormatResult res; - static const char buffer[16] = "0000000000000000"; - while(len > 16) { - res = ctxt->write_str(ctxt->user_data, buffer, 16); - if (res != STRFORMAT_OK) return res; - len -= 16; - } - if (len == 0) return STRFORMAT_OK; - return ctxt->write_str(ctxt->user_data, buffer, len); -} - -#define CHECKCB(res) {if ((res) != STRFORMAT_OK) {va_end(ap); return -1;}} - -int -format_str(const StrFormatContext *ctxt, const char *format, ...) -{ - int ret; - va_list ap; - va_start(ap, format); - ret = format_str_v(ctxt, format, ap); - va_end(ap); - return ret; -} - -int -format_str_v(const StrFormatContext *ctxt, const char *format, va_list ap) -{ - unsigned int written = 0; - const char *pos = format; - while(*pos != '\0') { - FormatFlags flags; - unsigned int minwidth = 0; - int precision = -1; /* Negative means no precision */ - char ch; - const char *start = pos; - while( (ch = *pos) != '\0' && ch != '%') pos++; - if (pos != start) { - CHECKCB(ctxt->write_str(ctxt->user_data, start, pos - start)); - written += pos - start; - } - if (*pos == '\0') { - va_end(ap); - return written; - } - pos++; - if (*pos == '\0') { - va_end(ap); - return written; - } - flags = parse_flags(&pos); - - /* parse width */ - if (*pos >= '1' && *pos <= '9') { - minwidth = parse_uint(&pos); - } else if (*pos == '*') { - int w = va_arg(ap,int); - if (w < 0) { - flags |= JUSTIFY_LEFT; - minwidth = w; - } else { - minwidth = w; - } - pos ++; - } - - /* parse precision */ - if (*pos == '.') { - pos++; - if (*pos >= '0' && *pos <= '9') { - precision = parse_uint(&pos); - } else if (*pos == '*') { - pos++; - precision = va_arg(ap,int); - } - } - if (*pos == 'l') { - pos++; - if (*pos == 'l') { - flags |= SIZE_LONGLONG; - pos++; - } else { - flags |= SIZE_LONG; - } - } else if (*pos == 'h') { - pos++; - if (*pos == 'h') { - flags |= SIZE_CHAR; - pos++; - } else { - flags |= SIZE_SHORT; - } - } - - /* parse conversion specifier */ - switch(*pos) { - case 'd': - case 'i': - flags |= CONV_INTEGER | RADIX_DECIMAL | SIGNED_YES; - break; - case 'u': - flags |= CONV_INTEGER | RADIX_DECIMAL | SIGNED_NO; - break; - case 'o': - flags |= CONV_INTEGER | RADIX_OCTAL | SIGNED_NO; - break; - case 'x': - flags |= CONV_INTEGER | RADIX_HEX | SIGNED_NO; - break; - case 'X': - flags |= CONV_INTEGER | RADIX_HEX | SIGNED_NO | CAPS_YES; - break; -#ifdef HAVE_DOUBLE - case 'f': - flags |= CONV_FLOAT | FLOAT_NORMAL; - break; - case 'F': - flags |= CONV_FLOAT | FLOAT_NORMAL | CAPS_YES; - break; - case 'e': - flags |= CONV_FLOAT | FLOAT_EXPONENT; - break; - case 'E': - flags |= CONV_FLOAT | FLOAT_EXPONENT | CAPS_YES; - break; - case 'g': - flags |= CONV_FLOAT | FLOAT_DEPENDANT; - break; - case 'G': - flags |= CONV_FLOAT | FLOAT_DEPENDANT | CAPS_YES; - break; - case 'a': - flags |= CONV_FLOAT | FLOAT_HEX; - break; - case 'A': - flags |= CONV_FLOAT | FLOAT_HEX | CAPS_YES; - break; -#endif - case 'c': - flags |= CONV_CHAR; - break; - case 's': - flags |= CONV_STRING; - break; - case 'p': - flags |= CONV_POINTER; - break; - case 'n': - flags |= CONV_WRITTEN; - break; - case '%': - flags |= CONV_PERCENT; - break; - case '\0': - va_end(ap); - return written; - } - pos++; - switch(flags & CONV_MASK) { - case CONV_PERCENT: - CHECKCB(ctxt->write_str(ctxt->user_data, "%", 1)); - written++; - break; - case CONV_INTEGER: - { - /* unsigned integers */ - char *prefix = 0; /* sign, "0x" or "0X" */ - unsigned int prefix_len = 0; - char buffer[MAXCHARS]; - char *conv_pos = buffer + MAXCHARS; - unsigned int conv_len = 0; - unsigned int width = 0; - unsigned int precision_fill; - unsigned int field_fill; - LARGEST_UNSIGNED uvalue = 0; - int negative = 0; - - if (precision < 0) precision = 1; - else flags &= ~PAD_ZERO; - - if (flags & SIGNED_YES) { - /* signed integers */ - LARGEST_SIGNED value = 0; - switch(flags & SIZE_MASK) { - case SIZE_CHAR: - value = (signed char)va_arg(ap, int); - break; - case SIZE_SHORT: - value = (short)va_arg(ap, int); - break; - case SIZE_INT: - value = va_arg(ap, int); - break; -#ifndef HAVE_LONGLONG - case SIZE_LONGLONG: /* Treat long long the same as long */ -#endif - case SIZE_LONG: - value = va_arg(ap, long); - break; -#ifdef HAVE_LONGLONG - case SIZE_LONGLONG: - value = va_arg(ap, long long); - break; -#endif - } - if (value < 0) { - uvalue = -value; - negative = 1; - } else { - uvalue = value; - } - } else { - - switch(flags & SIZE_MASK) { - case SIZE_CHAR: - uvalue = (unsigned char)va_arg(ap,unsigned int); - break; - case SIZE_SHORT: - uvalue = (unsigned short)va_arg(ap,unsigned int); - break; - case SIZE_INT: - uvalue = va_arg(ap,unsigned int); - break; -#ifndef HAVE_LONGLONG - case SIZE_LONGLONG: /* Treat long long the same as long */ -#endif - case SIZE_LONG: - uvalue = va_arg(ap,unsigned long); - break; -#ifdef HAVE_LONGLONG - case SIZE_LONGLONG: - uvalue = va_arg(ap,unsigned long long); - break; -#endif - } - } - - switch(flags & (RADIX_MASK)) { - case RADIX_DECIMAL: - conv_len = output_uint_decimal(&conv_pos,uvalue); - break; - case RADIX_OCTAL: - conv_len = output_uint_octal(&conv_pos,uvalue); - break; - case RADIX_HEX: - conv_len = output_uint_hex(&conv_pos,uvalue, flags); - break; - } - - width += conv_len; - precision_fill = (precision > conv_len) ? precision - conv_len : 0; - if ((flags & (RADIX_MASK | ALTERNATE_FORM)) - == (RADIX_OCTAL | ALTERNATE_FORM)) { - if (precision_fill < 1) precision_fill = 1; - } - - width += precision_fill; - - if ((flags & (RADIX_MASK | ALTERNATE_FORM)) - == (RADIX_HEX | ALTERNATE_FORM) && uvalue != 0) { - prefix_len = 2; - if (flags & CAPS_YES) { - prefix = "0X"; - } else { - prefix = "0x"; - } - } - - if (flags & SIGNED_YES) { - if (negative) { - prefix = "-"; - prefix_len = 1; - } else { - switch(flags & POSITIVE_MASK) { - case POSITIVE_SPACE: - prefix = " "; - prefix_len = 1; - break; - case POSITIVE_PLUS: - prefix = "+"; - prefix_len = 1; - break; - } - } - } - - width += prefix_len; - - field_fill = (minwidth > width) ? minwidth - width : 0; - - if ((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) { - if (flags & PAD_ZERO) { - precision_fill += field_fill; - field_fill = 0; /* Do not double count padding */ - } else { - CHECKCB(fill_space(ctxt,field_fill)); - } - } - - if (prefix_len > 0) - CHECKCB(ctxt->write_str(ctxt->user_data, prefix, prefix_len)); - written += prefix_len; - - CHECKCB(fill_zero(ctxt,precision_fill)); - written += precision_fill; - - CHECKCB(ctxt->write_str(ctxt->user_data, conv_pos,conv_len)); - written += conv_len; - - if ((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) { - CHECKCB(fill_space(ctxt,field_fill)); - } - written += field_fill; - } - break; - case CONV_STRING: - { - unsigned int field_fill; - unsigned int len; - char *str = va_arg(ap,char *); - if (str) { - char *pos = str; - while(*pos != '\0') pos++; - len = pos - str; - } else { - str = "(null)"; - len = 6; - } - if (precision >= 0 && precision < len) len = precision; - field_fill = (minwidth > len) ? minwidth - len : 0; - if ((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) { - CHECKCB(fill_space(ctxt,field_fill)); - } - CHECKCB(ctxt->write_str(ctxt->user_data, str,len)); - written += len; - if ((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) { - CHECKCB(fill_space(ctxt,field_fill)); - } - written += field_fill; - } - break; - case CONV_POINTER: - { - LARGEST_UNSIGNED uvalue = - (LARGEST_UNSIGNED)(POINTER_INT)va_arg(ap,void *); - char buffer[MAXCHARS_HEX + 3]; - char *conv_pos = buffer + MAXCHARS_HEX+3; - unsigned int conv_len; - unsigned int field_fill; - - conv_len = output_uint_hex(&conv_pos,uvalue,flags); - if (conv_len == 0) { - *--conv_pos = '0'; - conv_len++; - } - *--conv_pos = 'x'; - *--conv_pos = '0'; - *--conv_pos = '#'; - conv_len += 3; - - field_fill = (minwidth > conv_len) ? minwidth - conv_len : 0; - - if ((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) { - CHECKCB(fill_space(ctxt,field_fill)); - } - - CHECKCB(ctxt->write_str(ctxt->user_data, conv_pos,conv_len)); - written += conv_len; - - if ((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) { - CHECKCB(fill_space(ctxt,field_fill)); - } - written += field_fill; - } - break; - case CONV_CHAR: - { - char ch = va_arg(ap,int); - unsigned int field_fill = (minwidth > 1) ? minwidth - 1 : 0; - if ((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) { - CHECKCB(fill_space(ctxt,field_fill)); - written += field_fill; - } - - CHECKCB(ctxt->write_str(ctxt->user_data, &ch, 1)); - written++; - - if ((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) { - CHECKCB(fill_space(ctxt,field_fill)); - } - written+= field_fill; - } - break; - case CONV_WRITTEN: - { - int *p = va_arg(ap,int*); - *p = written; - } - break; - - } - } - - return written; -} diff --git a/arch/cpu/arm/common/dbg-io/strformat.h b/arch/cpu/arm/common/dbg-io/strformat.h deleted file mode 100644 index c32eed670..000000000 --- a/arch/cpu/arm/common/dbg-io/strformat.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef STRFORMAT_H_ -#define STRFORMAT_H_ - -#include - -#define STRFORMAT_OK 0 -#define STRFORMAT_FAILED 1 -typedef unsigned int StrFormatResult; - -/* The data argument may only be considered valid during the function call */ -typedef StrFormatResult (*StrFormatWrite)(void *user_data, const char *data, unsigned int len); - -typedef struct _StrFormatContext -{ - StrFormatWrite write_str; - void *user_data; -} StrFormatContext; - -int format_str(const StrFormatContext *ctxt, const char *format, ...) - __attribute__ ((__format__ (__printf__, 2,3))); - -int -format_str_v(const StrFormatContext *ctxt, const char *format, va_list ap); - -#endif /* STRFORMAT_H_ */ diff --git a/arch/cpu/cc2538/Makefile.cc2538 b/arch/cpu/cc2538/Makefile.cc2538 index f6e76f571..03758aa9b 100644 --- a/arch/cpu/cc2538/Makefile.cc2538 +++ b/arch/cpu/cc2538/Makefile.cc2538 @@ -27,14 +27,13 @@ CONTIKI_CPU_SOURCEFILES += slip-arch.c slip.c CONTIKI_CPU_SOURCEFILES += i2c.c cc2538-temp-sensor.c vdd3-sensor.c CONTIKI_CPU_SOURCEFILES += cfs-coffee.c cfs-coffee-arch.c pwm.c -DEBUG_IO_SOURCEFILES += dbg-printf.c dbg-snprintf.c dbg-sprintf.c strformat.c +MODULES += os/lib/dbg-io USB_SOURCEFILES += usb-core.c cdc-acm.c usb-arch.c usb-serial.c cdc-acm-descriptors.c CPU_START_SOURCEFILES = startup-gcc.c -CONTIKI_SOURCEFILES += $(CONTIKI_CPU_SOURCEFILES) $(DEBUG_IO_SOURCEFILES) -CONTIKI_SOURCEFILES += $(USB_SOURCEFILES) +CONTIKI_SOURCEFILES += $(CONTIKI_CPU_SOURCEFILES) $(USB_SOURCEFILES) ### Always re-build ieee-addr.o in case the command line passes a new NODEID FORCE: diff --git a/arch/cpu/cc2538/dbg.c b/arch/cpu/cc2538/dbg.c index b97936feb..7b33bc471 100644 --- a/arch/cpu/cc2538/dbg.c +++ b/arch/cpu/cc2538/dbg.c @@ -28,16 +28,9 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** \addtogroup cc2538-char-io - * @{ */ -/** - * \file - * Implementation of arch-specific functions required by the dbg_io API in - * cpu/arm/common/dbg-io - */ +/*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "dbg.h" #include "dev/uart.h" #include "usb/usb-serial.h" @@ -55,13 +48,10 @@ #define flush() #endif /*---------------------------------------------------------------------------*/ -#undef putchar -#undef puts - #define SLIP_END 0300 /*---------------------------------------------------------------------------*/ int -putchar(int c) +dbg_putchar(int c) { #if DBG_CONF_SLIP_MUX static char debug_frame = 0; @@ -80,7 +70,7 @@ putchar(int c) write_byte(SLIP_END); debug_frame = 0; #endif - dbg_flush(); + flush(); } return c; } @@ -100,18 +90,3 @@ dbg_send_bytes(const unsigned char *s, unsigned int len) return i; } /*---------------------------------------------------------------------------*/ -int -puts(const char *s) -{ - unsigned int i = 0; - - while(s && *s != 0) { - putchar(*s++); - i++; - } - putchar('\n'); - return i; -} -/*---------------------------------------------------------------------------*/ - -/** @} */ diff --git a/arch/cpu/cc2538/dbg.h b/arch/cpu/cc2538/dbg.h deleted file mode 100644 index d5ab51f9d..000000000 --- a/arch/cpu/cc2538/dbg.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/** - * \addtogroup cc2538 - * @{ - * - * \defgroup cc2538-char-io cc2538 Character I/O - * - * CPU-specific functions for debugging and SLIP I/O - * - * On the cc2538, character I/O can be directed over USB or UART. This is - * controlled by a series of configuration directives: - * - SLIP_ARCH_CONF_USB: Controls the operation of slip-arch. - * - DBG_CONF_USB: Controls all debugging output - * - * Defaults for those defines are set in contiki-conf.h - * @{ - * - * \file - * Header file for the cc2538 Debug I/O module - */ -#ifndef DBG_H_ -#define DBG_H_ - -#include "contiki.h" - -#include "usb/usb-serial.h" -/** - * \brief Print a stream of bytes - * \param seq A pointer to the stream - * \param len The number of bytes to print - * \return The number of printed bytes - * - * This function is an arch-specific implementation required by the dbg-io - * API in cpu/arm/common/dbg-io. It prints a stream of bytes over the - * peripheral used by the platform. - */ -unsigned int dbg_send_bytes(const unsigned char *seq, unsigned int len); - -/** - * \brief Flushes character output - * - * When debugging is sent over USB, this functions causes the USB - * driver to immediately TX the content of output buffers. When - * debugging is over UART, this function does nothing. - * - * There is nothing stopping you from using this macro in your code but - * normally, you won't have to. - */ -#if DBG_CONF_USB -#define dbg_flush() usb_serial_flush() -#else -#define dbg_flush() -#endif - -#endif /* DBG_H_ */ - -/** - * @} - * @} - */ diff --git a/arch/cpu/cc2538/slip-arch.c b/arch/cpu/cc2538/slip-arch.c index 58aec9f84..dee023a4f 100644 --- a/arch/cpu/cc2538/slip-arch.c +++ b/arch/cpu/cc2538/slip-arch.c @@ -28,21 +28,12 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * \addtogroup cc2538-char-io - * @{ - * - * \file - * Arch-specific SLIP functions for the cc2538 - * - * SLIP can be configured to operate over UART or over USB-Serial, depending - * on the value of SLIP_ARCH_CONF_USB - */ +/*---------------------------------------------------------------------------*/ #include "contiki.h" #include "dev/slip.h" #include "dev/uart.h" #include "usb/usb-serial.h" - +/*---------------------------------------------------------------------------*/ #ifndef SLIP_ARCH_CONF_USB #define SLIP_ARCH_CONF_USB 0 #endif @@ -59,10 +50,6 @@ #define SLIP_END 0300 /*---------------------------------------------------------------------------*/ -/** - * \brief Write a byte over SLIP - * \param c the byte - */ void slip_arch_writeb(unsigned char c) { @@ -72,14 +59,9 @@ slip_arch_writeb(unsigned char c) } } /*---------------------------------------------------------------------------*/ -/** - * \brief Initialise the arch-specific SLIP driver - */ void slip_arch_init() { set_input(slip_input_byte); } /*---------------------------------------------------------------------------*/ - -/** @} */ diff --git a/arch/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx b/arch/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx index 979d7f5e4..75dbad7ad 100644 --- a/arch/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx +++ b/arch/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx @@ -30,16 +30,16 @@ CONTIKI_CPU_DIRS += . dev rf-core rf-core/api rf-core/ble-hal $(TI_XXWARE_STARTU ### CPU-dependent source files CONTIKI_CPU_SOURCEFILES += clock.c rtimer-arch.c soc-rtc.c uart.c CONTIKI_CPU_SOURCEFILES += contiki-watchdog.c aux-ctrl.c -CONTIKI_CPU_SOURCEFILES += putchar.c ieee-addr.c batmon-sensor.c adc-sensor.c +CONTIKI_CPU_SOURCEFILES += dbg.c ieee-addr.c batmon-sensor.c adc-sensor.c CONTIKI_CPU_SOURCEFILES += slip-arch.c slip.c cc26xx-uart.c lpm.c CONTIKI_CPU_SOURCEFILES += gpio-interrupt.c gpio-hal-arch.c oscillators.c CONTIKI_CPU_SOURCEFILES += rf-core.c rf-ble.c ieee-mode.c CONTIKI_CPU_SOURCEFILES += ble-cc2650.c ble-hal-cc26xx.c ble-addr.c rf-ble-cmd.c CONTIKI_CPU_SOURCEFILES += random.c soc-trng.c int-master.c -DEBUG_IO_SOURCEFILES += dbg-printf.c dbg-snprintf.c dbg-sprintf.c strformat.c +MODULES += os/lib/dbg-io -CONTIKI_SOURCEFILES += $(CONTIKI_CPU_SOURCEFILES) $(DEBUG_IO_SOURCEFILES) +CONTIKI_SOURCEFILES += $(CONTIKI_CPU_SOURCEFILES) CPU_START_SOURCEFILES += fault-handlers.c $(TI_XXWARE_STARTUP_SRCS) diff --git a/arch/cpu/cc26xx-cc13xx/putchar.c b/arch/cpu/cc26xx-cc13xx/dbg.c similarity index 84% rename from arch/cpu/cc26xx-cc13xx/putchar.c rename to arch/cpu/cc26xx-cc13xx/dbg.c index 7cbd1901a..bf03aade4 100644 --- a/arch/cpu/cc26xx-cc13xx/putchar.c +++ b/arch/cpu/cc26xx-cc13xx/dbg.c @@ -34,33 +34,12 @@ #include /*---------------------------------------------------------------------------*/ int -putchar(int c) +dbg_putchar(int c) { cc26xx_uart_write_byte(c); return c; } /*---------------------------------------------------------------------------*/ -int -puts(const char *str) -{ - int i; - if(str == NULL) { - return 0; - } - for(i = 0; i < strlen(str); i++) { - cc26xx_uart_write_byte(str[i]); - } - cc26xx_uart_write_byte('\n'); - - /* - * Wait for the line to go out. This is to prevent garbage when used between - * UART on/off cycles - */ - while(cc26xx_uart_busy() == UART_BUSY); - - return i; -} -/*---------------------------------------------------------------------------*/ unsigned int dbg_send_bytes(const unsigned char *s, unsigned int len) { diff --git a/arch/cpu/cc26xx-cc13xx/slip-arch.c b/arch/cpu/cc26xx-cc13xx/slip-arch.c index 6c6914363..f4141e11d 100644 --- a/arch/cpu/cc26xx-cc13xx/slip-arch.c +++ b/arch/cpu/cc26xx-cc13xx/slip-arch.c @@ -29,31 +29,16 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /*---------------------------------------------------------------------------*/ -/** - * \addtogroup cc26xx-char-io - * @{ - * - * \file - * Arch-specific SLIP functions for the CC13xx/CC26xx - */ -/*---------------------------------------------------------------------------*/ #include "contiki.h" #include "dev/cc26xx-uart.h" #include "dev/slip.h" /*---------------------------------------------------------------------------*/ -/** - * \brief Write a byte over SLIP - * \param c the byte - */ void slip_arch_writeb(unsigned char c) { cc26xx_uart_write_byte(c); } /*---------------------------------------------------------------------------*/ -/** - * \brief Initialise the arch-specific SLIP driver - */ void slip_arch_init() { @@ -64,5 +49,3 @@ slip_arch_init() cc26xx_uart_set_input(slip_input_byte); } /*---------------------------------------------------------------------------*/ - -/** @} */ diff --git a/arch/cpu/nrf52832/Makefile.nrf52832 b/arch/cpu/nrf52832/Makefile.nrf52832 index c2bdbbf81..5e0db414d 100644 --- a/arch/cpu/nrf52832/Makefile.nrf52832 +++ b/arch/cpu/nrf52832/Makefile.nrf52832 @@ -54,7 +54,7 @@ remduplicates = $(strip $(if $1,$(firstword $1) $(call remduplicates,$(filter-ou CONTIKI_CPU_DIRS += . dev ble #compat ### CPU-dependent source files -CONTIKI_CPU_SOURCEFILES += clock.c rtimer-arch.c uart0.c putchar.c watchdog.c +CONTIKI_CPU_SOURCEFILES += clock.c rtimer-arch.c uart0.c dbg.c watchdog.c CONTIKI_CPU_SOURCEFILES += int-master.c ifneq ($(NRF52_WITHOUT_SOFTDEVICE),1) diff --git a/arch/platform/nrf52dk/dbg-io/dbg.c b/arch/cpu/nrf52832/dbg.c similarity index 94% rename from arch/platform/nrf52dk/dbg-io/dbg.c rename to arch/cpu/nrf52832/dbg.c index db9bb63c0..8f7be5cfc 100644 --- a/arch/platform/nrf52dk/dbg-io/dbg.c +++ b/arch/cpu/nrf52832/dbg.c @@ -27,16 +27,12 @@ * SUCH DAMAGE. * */ - /** - * \addtogroup nrf52dk - * @{ - * - * \addtogroup nrf52dk-dbg-io Debug IO over UART + * \addtogroup nrf52832 * @{ * * \file - * Function implementations for debug io module. + * Hardware specific implementation of putchar() and puts() functions. * \author * Wojciech Bober * diff --git a/arch/cpu/nrf52832/putchar.c b/arch/cpu/nrf52832/putchar.c deleted file mode 100644 index c4163ba3d..000000000 --- a/arch/cpu/nrf52832/putchar.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2015, Nordic Semiconductor - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ -/** - * \addtogroup nrf52832 - * @{ - * - * \file - * Hardware specific implementation of putchar() and puts() functions. - * \author - * Wojciech Bober - * - */ -/*---------------------------------------------------------------------------*/ -#include -#include "dev/uart0.h" -/*---------------------------------------------------------------------------*/ -int -putchar(int c) -{ - uart0_writeb(c); - return c; -} -/*---------------------------------------------------------------------------*/ -int -puts(const char *str) -{ - int i; - - if (str == NULL) { - return 0; - } - - for (i = 0; i < strlen(str); i++) { - uart0_writeb(str[i]); - } - - uart0_writeb('\n'); - return i; -} -/*---------------------------------------------------------------------------*/ -/** - * @} - */ diff --git a/arch/platform/nrf52dk/Makefile.nrf52dk b/arch/platform/nrf52dk/Makefile.nrf52dk index 6187fc532..6561de980 100644 --- a/arch/platform/nrf52dk/Makefile.nrf52dk +++ b/arch/platform/nrf52dk/Makefile.nrf52dk @@ -13,10 +13,8 @@ ifeq ($(NRF52_USE_RTT),1) CONTIKI_TARGET_DIRS += rtt CONTIKI_SOURCEFILES += rtt-printf.c segger-rtt.c segger-rtt-printf.c else -CONTIKI_TARGET_DIRS += dbg-io CONTIKI_SOURCEFILES += dbg.c -CONTIKI_CPU_DIRS += ../arm/common/dbg-io -CONTIKI_CPU_SOURCEFILES += dbg-printf.c dbg-putchar.c dbg-snprintf.c dbg-sprintf.c strformat.c +MODULES += os/lib/dbg-io endif CLEAN += *.nrf52dk diff --git a/arch/platform/nrf52dk/dbg-io/dbg.h b/arch/platform/nrf52dk/dbg-io/dbg.h deleted file mode 100644 index 5d9568270..000000000 --- a/arch/platform/nrf52dk/dbg-io/dbg.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2015, Nordic Semiconductor - * All rights reserved. - * -3 * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ -/** - * \addtogroup nrf52dk - * @{ - * - * \addtogroup nrf52dk-dbg-io Debug IO over UART - * @{ - * - * \file - * Header file for the debug module. - * \author - * Wojciech Bober - * - */ -#ifndef DBG_H_ -#define DBG_H_ -/*---------------------------------------------------------------------------*/ -#include "contiki.h" -/*---------------------------------------------------------------------------*/ -/** - * \brief Print a stream of bytes - * \param seq A pointer to the stream - * \param len The number of bytes to print - * \return The number of printed bytes - */ -unsigned int dbg_send_bytes(const unsigned char *seq, unsigned int len); -/** - * \brief Print a character to debug output - * \param c Character to print - * \return Printed character - */ -int dbg_putchar(int c); -/*---------------------------------------------------------------------------*/ -#endif /* DBG_H_ */ -/*---------------------------------------------------------------------------*/ -/** - * @} - * @} - */ diff --git a/arch/platform/nrf52dk/dbg-io/debug-uart.h b/arch/platform/nrf52dk/dbg-io/debug-uart.h deleted file mode 100644 index b52d2fb50..000000000 --- a/arch/platform/nrf52dk/dbg-io/debug-uart.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2015, Nordic Semiconductor - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ -/** - * \addtogroup nrf52dk - * @{ - * - * \addtogroup nrf52dk-dbg-io Debug IO over UART - * @{ - * - * \file - * A header file to maintain compatibility with DBG I/O. - * \author - * Wojciech Bober - * - */ -/*---------------------------------------------------------------------------*/ -#ifndef DEBUG_UART_H_ -#define DEBUG_UART_H_ -/*---------------------------------------------------------------------------*/ -#include "dbg.h" -/*---------------------------------------------------------------------------*/ -#endif /* DEBUG_UART_H_ */ -/*---------------------------------------------------------------------------*/ -/** - * @} - * @} - */ diff --git a/arch/cpu/cc26xx-cc13xx/dbg.h b/os/lib/dbg-io/dbg.h similarity index 83% rename from arch/cpu/cc26xx-cc13xx/dbg.h rename to os/lib/dbg-io/dbg.h index 4460b6eb4..6440b5eca 100644 --- a/arch/cpu/cc26xx-cc13xx/dbg.h +++ b/os/lib/dbg-io/dbg.h @@ -1,10 +1,11 @@ /* - * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2015, Nordic Semiconductor * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright @@ -29,16 +30,17 @@ */ /*---------------------------------------------------------------------------*/ /** - * \addtogroup cc26xx + * \addtogroup lib * @{ * - * \defgroup cc26xx-char-io CC13xx/CC26xx Character I/O - * - * CC13xx/CC26xx CPU-specific functions for debugging and SLIP I/O + * \addtogroup dbg-io Portable debugging output functons * @{ * * \file - * Header file for the CC13xx/CC26xx Debug I/O module + * Header file for the dbg-io module. + * \author + * Wojciech Bober + * */ #ifndef DBG_H_ #define DBG_H_ @@ -50,12 +52,14 @@ * \param seq A pointer to the stream * \param len The number of bytes to print * \return The number of printed bytes - * - * This function is an arch-specific implementation required by the dbg-io - * API in cpu/arm/common/dbg-io. It prints a stream of bytes over the - * peripheral used by the platform. */ unsigned int dbg_send_bytes(const unsigned char *seq, unsigned int len); +/** + * \brief Print a character to debug output + * \param c Character to print + * \return Printed character + */ +int dbg_putchar(int c); /*---------------------------------------------------------------------------*/ #endif /* DBG_H_ */ /*---------------------------------------------------------------------------*/ diff --git a/arch/cpu/cc26xx-cc13xx/debug-uart.h b/os/lib/dbg-io/printf.c similarity index 78% rename from arch/cpu/cc26xx-cc13xx/debug-uart.h rename to os/lib/dbg-io/printf.c index c2d9b0ffb..9749f1f7d 100644 --- a/arch/cpu/cc26xx-cc13xx/debug-uart.h +++ b/os/lib/dbg-io/printf.c @@ -1,16 +1,16 @@ /* - * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2009, Simon Berg * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. @@ -29,21 +29,36 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /*---------------------------------------------------------------------------*/ -/** - * \addtogroup cc26xx-char-io - * @{ - * - * \file - * This file is here because DBG I/O expects it to be. It just includes - * our own dbg.h which has a non-misleading name and which also adheres - * to Contiki's naming convention - */ +#include "contiki.h" +#include "lib/dbg-io/dbg.h" + +#include +#include +#include /*---------------------------------------------------------------------------*/ -#ifndef DEBUG_UART_H_ -#define DEBUG_UART_H_ +static strformat_result +write_str(void *user_data, const char *data, unsigned int len) +{ + if(len > 0) { + dbg_send_bytes((unsigned char *)data, len); + } + return STRFORMAT_OK; +} /*---------------------------------------------------------------------------*/ -#include "dbg.h" +static strformat_context_t ctxt = +{ + write_str, + NULL +}; /*---------------------------------------------------------------------------*/ -#endif /* DEBUG_UART_H_ */ +int +printf(const char *fmt, ...) +{ + int res; + va_list ap; + va_start(ap, fmt); + res = format_str_v(&ctxt, fmt, ap); + va_end(ap); + return res; +} /*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/arch/cpu/cc2538/debug-uart.h b/os/lib/dbg-io/putchar.c similarity index 78% rename from arch/cpu/cc2538/debug-uart.h rename to os/lib/dbg-io/putchar.c index 88a2fc3e0..26a35446d 100644 --- a/arch/cpu/cc2538/debug-uart.h +++ b/os/lib/dbg-io/putchar.c @@ -1,16 +1,16 @@ /* - * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2009, Simon Berg * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. @@ -28,20 +28,17 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * \addtogroup cc2538-char-io - * @{ - * - * \file - * This file is here because DBG I/O expects it to be. It just includes - * our own dbg.h which has a non-misleading name and which also adheres - * to Contiki's naming convention - */ -#ifndef DEBUG_UART_H_ -#define DEBUG_UART_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "lib/dbg-io/dbg.h" -#include "dbg.h" - -#endif /* DEBUG_UART_H_ */ - -/** @} */ +#include +#include +/*---------------------------------------------------------------------------*/ +int +putchar(int c) +{ + dbg_putchar(c); + return c; +} +/*---------------------------------------------------------------------------*/ diff --git a/os/lib/dbg-io/puts.c b/os/lib/dbg-io/puts.c new file mode 100644 index 000000000..93d73d3a5 --- /dev/null +++ b/os/lib/dbg-io/puts.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2009, Simon Berg + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "lib/dbg-io/dbg.h" + +#include +#include +/*---------------------------------------------------------------------------*/ +int +puts(const char *str) +{ + dbg_send_bytes((unsigned char *)str, strlen(str)); + dbg_putchar('\n'); + return 0; +} +/*---------------------------------------------------------------------------*/ diff --git a/os/lib/dbg-io/snprintf.c b/os/lib/dbg-io/snprintf.c new file mode 100644 index 000000000..96f99e568 --- /dev/null +++ b/os/lib/dbg-io/snprintf.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2009, Simon Berg + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" + +#include +#include +#include +/*---------------------------------------------------------------------------*/ +struct fmt_buffer { + char *pos; + size_t left; +}; +/*---------------------------------------------------------------------------*/ +static strformat_result +buffer_str(void *user_data, const char *data, unsigned int len) +{ + struct fmt_buffer *buffer = (struct fmt_buffer *)user_data; + if(len >= buffer->left) { + len = buffer->left; + len--; + } + + memcpy(buffer->pos, data, len); + buffer->pos += len; + buffer->left -= len; + return STRFORMAT_OK; +} +/*---------------------------------------------------------------------------*/ +int +snprintf(char *str, size_t size, const char *format, ...) +{ + int res; + va_list ap; + va_start(ap, format); + res = vsnprintf(str, size, format, ap); + va_end(ap); + return res; +} +/*---------------------------------------------------------------------------*/ +int +vsnprintf(char *str, size_t size, const char *format, va_list ap) +{ + struct fmt_buffer buffer; + strformat_context_t ctxt; + int res; + ctxt.write_str = buffer_str; + ctxt.user_data = &buffer; + buffer.pos = str; + buffer.left = size; + res = format_str_v(&ctxt, format, ap); + *buffer.pos = '\0'; + return res; +} +/*---------------------------------------------------------------------------*/ diff --git a/os/lib/dbg-io/sprintf.c b/os/lib/dbg-io/sprintf.c new file mode 100644 index 000000000..4ecf5b540 --- /dev/null +++ b/os/lib/dbg-io/sprintf.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2009, Simon Berg + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" + +#include +#include +#include +/*---------------------------------------------------------------------------*/ +static strformat_result +buffer_str(void *user_data, const char *data, unsigned int len) +{ + memcpy(*(char **)user_data, data, len); + (*(char **)user_data) += len; + return STRFORMAT_OK; +} +/*---------------------------------------------------------------------------*/ +int +sprintf(char *str, const char *format, ...) +{ + strformat_context_t ctxt; + int res; + va_list ap; + va_start(ap, format); + ctxt.write_str = buffer_str; + ctxt.user_data = &str; + res = format_str_v(&ctxt, format, ap); + *str = '\0'; + va_end(ap); + return res; +} +/*---------------------------------------------------------------------------*/ diff --git a/os/lib/dbg-io/strformat.c b/os/lib/dbg-io/strformat.c new file mode 100644 index 000000000..b5ad18f89 --- /dev/null +++ b/os/lib/dbg-io/strformat.c @@ -0,0 +1,707 @@ +/* + * Copyright (c) 2009, Simon Berg + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" + +#include +/*---------------------------------------------------------------------------*/ +#define HAVE_DOUBLE +#define HAVE_LONGLONG + +#ifndef LARGEST_SIGNED +#ifdef HAVE_LONGLONG +#define LARGEST_SIGNED long long int +#else +#define LARGEST_UNSIGNED long int +#endif /* HAVE_LONGLONG */ +#endif /* LARGEST_SIGNED */ + +#ifndef LARGEST_UNSIGNED +#ifdef HAVE_LONGLONG +#define LARGEST_UNSIGNED unsigned long long int +#else +#define LARGEST_UNSIGNED unsigned long int +#endif /* HAVE_LONGLONG */ +#endif /* LARGEST_UNSIGNED */ + +#ifndef POINTER_INT +#define POINTER_INT unsigned long +#endif +/*---------------------------------------------------------------------------*/ +typedef unsigned int FormatFlags; +/*---------------------------------------------------------------------------*/ +#define MAKE_MASK(shift, size) (((1 << size) - 1) << (shift)) +/*---------------------------------------------------------------------------*/ +#define JUSTIFY_SHIFT 0 +#define JUSTIFY_SIZE 1 +#define JUSTIFY_RIGHT 0x0000 +#define JUSTIFY_LEFT 0x0001 +#define JUSTIFY_MASK MAKE_MASK(JUSTIFY_SHIFT, JUSTIFY_SIZE) +/*---------------------------------------------------------------------------*/ +/* How a positive number is prefixed */ +#define POSITIVE_SHIFT (JUSTIFY_SHIFT + JUSTIFY_SIZE) +#define POSITIVE_NONE (0x0000 << POSITIVE_SHIFT) +#define POSITIVE_SPACE (0x0001 << POSITIVE_SHIFT) +#define POSITIVE_PLUS (0x0003 << POSITIVE_SHIFT) +#define POSITIVE_MASK MAKE_MASK(POSITIVE_SHIFT, POSITIVE_SIZE) + +#define POSITIVE_SIZE 2 +/*---------------------------------------------------------------------------*/ +#define ALTERNATE_FORM_SHIFT (POSITIVE_SHIFT + POSITIVE_SIZE) +#define ALTERNATE_FORM_SIZE 1 +#define ALTERNATE_FORM (0x0001 << ALTERNATE_FORM_SHIFT) +/*---------------------------------------------------------------------------*/ +#define PAD_SHIFT (ALTERNATE_FORM_SHIFT + ALTERNATE_FORM_SIZE) +#define PAD_SIZE 1 +#define PAD_SPACE (0x0000 << PAD_SHIFT) +#define PAD_ZERO (0x0001 << PAD_SHIFT) +/*---------------------------------------------------------------------------*/ +#define SIZE_SHIFT (PAD_SHIFT + PAD_SIZE) +#define SIZE_SIZE 3 +#define SIZE_CHAR (0x0001 << SIZE_SHIFT) +#define SIZE_SHORT (0x0002 << SIZE_SHIFT) +#define SIZE_INT (0x0000 << SIZE_SHIFT) +#define SIZE_LONG (0x0003 << SIZE_SHIFT) +#define SIZE_LONGLONG (0x0004 << SIZE_SHIFT) +#define SIZE_MASK MAKE_MASK(SIZE_SHIFT, SIZE_SIZE) +/*---------------------------------------------------------------------------*/ +#define CONV_SHIFT (SIZE_SHIFT + SIZE_SIZE) +#define CONV_SIZE 3 +#define CONV_INTEGER (0x0001 << CONV_SHIFT) +#define CONV_FLOAT (0x0002 << CONV_SHIFT) +#define CONV_POINTER (0x0003 << CONV_SHIFT) +#define CONV_STRING (0x0004 << CONV_SHIFT) +#define CONV_CHAR (0x0005 << CONV_SHIFT) +#define CONV_PERCENT (0x0006 << CONV_SHIFT) +#define CONV_WRITTEN (0x0007 << CONV_SHIFT) +#define CONV_MASK MAKE_MASK(CONV_SHIFT, CONV_SIZE) +/*---------------------------------------------------------------------------*/ +#define RADIX_SHIFT (CONV_SHIFT + CONV_SIZE) +#define RADIX_SIZE 2 +#define RADIX_DECIMAL (0x0001 << RADIX_SHIFT) +#define RADIX_OCTAL (0x0002 << RADIX_SHIFT) +#define RADIX_HEX (0x0003 << RADIX_SHIFT) +#define RADIX_MASK MAKE_MASK(RADIX_SHIFT, RADIX_SIZE) +/*---------------------------------------------------------------------------*/ +#define SIGNED_SHIFT (RADIX_SHIFT + RADIX_SIZE) +#define SIGNED_SIZE 1 +#define SIGNED_NO (0x0000 << SIGNED_SHIFT) +#define SIGNED_YES (0x0001 << SIGNED_SHIFT) +#define SIGNED_MASK MAKE_MASK(SIGNED_SHIFT, SIGNED_SIZE) +/*---------------------------------------------------------------------------*/ +#define CAPS_SHIFT (SIGNED_SHIFT + SIGNED_SIZE) +#define CAPS_SIZE 1 +#define CAPS_NO (0x0000 << CAPS_SHIFT) +#define CAPS_YES (0x0001 << CAPS_SHIFT) +#define CAPS_MASK MAKE_MASK(CAPS_SHIFT, CAPS_SIZE) +/*---------------------------------------------------------------------------*/ +#define FLOAT_SHIFT (CAPS_SHIFT + CAPS_SIZE) +#define FLOAT_SIZE 2 +#define FLOAT_NORMAL (0x0000 << FLOAT_SHIFT) +#define FLOAT_EXPONENT (0x0001 << FLOAT_SHIFT) +#define FLOAT_DEPENDANT (0x0002 << FLOAT_SHIFT) +#define FLOAT_HEX (0x0003 << FLOAT_SHIFT) +#define FLOAT_MASK MAKE_MASK(FLOAT_SHIFT, FLOAT_SIZE) +/*---------------------------------------------------------------------------*/ +#define CHECKCB(res) { if((res) != STRFORMAT_OK) { va_end(ap); return -1; } } +/*---------------------------------------------------------------------------*/ +#define MAXCHARS_HEX ((sizeof(LARGEST_UNSIGNED) * 8) / 4) + +/* Largest number of characters needed for converting an unsigned integer. */ +#define MAXCHARS ((sizeof(LARGEST_UNSIGNED) * 8 + 2) / 3) +/*---------------------------------------------------------------------------*/ +static FormatFlags +parse_flags(const char **posp) +{ + FormatFlags flags = 0; + const char *pos = *posp; + + while(1) { + switch(*pos) { + case '-': + flags |= JUSTIFY_LEFT; + break; + case '+': + flags |= POSITIVE_PLUS; + break; + case ' ': + flags |= POSITIVE_SPACE; + break; + case '#': + flags |= ALTERNATE_FORM; + break; + case '0': + flags |= PAD_ZERO; + break; + default: + *posp = pos; + return flags; + } + + pos++; + } +} +/*---------------------------------------------------------------------------*/ +static unsigned int +parse_uint(const char **posp) +{ + unsigned v = 0; + const char *pos = *posp; + char ch; + + while((ch = *pos) >= '0' && ch <= '9') { + v = v * 10 + (ch - '0'); + pos++; + } + + *posp = pos; + + return v; +} +/*---------------------------------------------------------------------------*/ +static unsigned int +output_uint_decimal(char **posp, LARGEST_UNSIGNED v) +{ + unsigned int len; + char *pos = *posp; + + while(v > 0) { + *--pos = (v % 10) + '0'; + v /= 10; + } + + len = *posp - pos; + *posp = pos; + + return len; +} +/*---------------------------------------------------------------------------*/ +static unsigned int +output_uint_hex(char **posp, LARGEST_UNSIGNED v, unsigned int flags) +{ + unsigned int len; + const char *hex = (flags & CAPS_YES) ? "0123456789ABCDEF" : "0123456789abcdef"; + char *pos = *posp; + + while(v > 0) { + *--pos = hex[(v % 16)]; + v /= 16; + } + + len = *posp - pos; + *posp = pos; + + return len; +} +/*---------------------------------------------------------------------------*/ +static unsigned int +output_uint_octal(char **posp, LARGEST_UNSIGNED v) +{ + unsigned int len; + char *pos = *posp; + + while(v > 0) { + *--pos = (v % 8) + '0'; + v /= 8; + } + + len = *posp - pos; + *posp = pos; + + return len; +} +/*---------------------------------------------------------------------------*/ +static strformat_result +fill_space(const strformat_context_t *ctxt, unsigned int len) +{ + strformat_result res; + static const char buffer[16] = " "; + + while(len > 16) { + res = ctxt->write_str(ctxt->user_data, buffer, 16); + if(res != STRFORMAT_OK) { + return res; + } + len -= 16; + } + + if(len == 0) { + return STRFORMAT_OK; + } + + return ctxt->write_str(ctxt->user_data, buffer, len); +} +/*---------------------------------------------------------------------------*/ +static strformat_result +fill_zero(const strformat_context_t *ctxt, unsigned int len) +{ + strformat_result res; + static const char buffer[16] = "0000000000000000"; + + while(len > 16) { + res = ctxt->write_str(ctxt->user_data, buffer, 16); + if(res != STRFORMAT_OK) { + return res; + } + len -= 16; + } + + if(len == 0) { + return STRFORMAT_OK; + } + return ctxt->write_str(ctxt->user_data, buffer, len); +} +/*---------------------------------------------------------------------------*/ +int +format_str(const strformat_context_t *ctxt, const char *format, ...) +{ + int ret; + va_list ap; + va_start(ap, format); + ret = format_str_v(ctxt, format, ap); + va_end(ap); + return ret; +} +/*---------------------------------------------------------------------------*/ +int +format_str_v(const strformat_context_t *ctxt, const char *format, va_list ap) +{ + unsigned int written = 0; + const char *pos = format; + + while(*pos != '\0') { + FormatFlags flags; + unsigned int minwidth = 0; + int precision = -1; /* Negative means no precision */ + char ch; + const char *start = pos; + + while((ch = *pos) != '\0' && ch != '%') { + pos++; + } + + if(pos != start) { + CHECKCB(ctxt->write_str(ctxt->user_data, start, pos - start)); + written += pos - start; + } + + if(*pos == '\0') { + va_end(ap); + return written; + } + + pos++; + + if(*pos == '\0') { + va_end(ap); + return written; + } + + flags = parse_flags(&pos); + + /* parse width */ + if(*pos >= '1' && *pos <= '9') { + minwidth = parse_uint(&pos); + } else if(*pos == '*') { + int w = va_arg(ap, int); + + if(w < 0) { + flags |= JUSTIFY_LEFT; + minwidth = w; + } else { + minwidth = w; + } + + pos++; + } + + /* parse precision */ + if(*pos == '.') { + pos++; + + if(*pos >= '0' && *pos <= '9') { + precision = parse_uint(&pos); + } else if(*pos == '*') { + pos++; + precision = va_arg(ap, int); + } + } + + if(*pos == 'l') { + pos++; + + if(*pos == 'l') { + flags |= SIZE_LONGLONG; + pos++; + } else { + flags |= SIZE_LONG; + } + } else if(*pos == 'h') { + pos++; + + if(*pos == 'h') { + flags |= SIZE_CHAR; + pos++; + } else { + flags |= SIZE_SHORT; + } + } + + /* parse conversion specifier */ + switch(*pos) { + case 'd': + case 'i': + flags |= CONV_INTEGER | RADIX_DECIMAL | SIGNED_YES; + break; + case 'u': + flags |= CONV_INTEGER | RADIX_DECIMAL | SIGNED_NO; + break; + case 'o': + flags |= CONV_INTEGER | RADIX_OCTAL | SIGNED_NO; + break; + case 'x': + flags |= CONV_INTEGER | RADIX_HEX | SIGNED_NO; + break; + case 'X': + flags |= CONV_INTEGER | RADIX_HEX | SIGNED_NO | CAPS_YES; + break; +#ifdef HAVE_DOUBLE + case 'f': + flags |= CONV_FLOAT | FLOAT_NORMAL; + break; + case 'F': + flags |= CONV_FLOAT | FLOAT_NORMAL | CAPS_YES; + break; + case 'e': + flags |= CONV_FLOAT | FLOAT_EXPONENT; + break; + case 'E': + flags |= CONV_FLOAT | FLOAT_EXPONENT | CAPS_YES; + break; + case 'g': + flags |= CONV_FLOAT | FLOAT_DEPENDANT; + break; + case 'G': + flags |= CONV_FLOAT | FLOAT_DEPENDANT | CAPS_YES; + break; + case 'a': + flags |= CONV_FLOAT | FLOAT_HEX; + break; + case 'A': + flags |= CONV_FLOAT | FLOAT_HEX | CAPS_YES; + break; +#endif + case 'c': + flags |= CONV_CHAR; + break; + case 's': + flags |= CONV_STRING; + break; + case 'p': + flags |= CONV_POINTER; + break; + case 'n': + flags |= CONV_WRITTEN; + break; + case '%': + flags |= CONV_PERCENT; + break; + case '\0': + va_end(ap); + return written; + } + pos++; + + switch(flags & CONV_MASK) { + case CONV_PERCENT: + CHECKCB(ctxt->write_str(ctxt->user_data, "%", 1)); + written++; + break; + case CONV_INTEGER: + { + /* unsigned integers */ + char *prefix = 0; /* sign, "0x" or "0X" */ + unsigned int prefix_len = 0; + char buffer[MAXCHARS]; + char *conv_pos = buffer + MAXCHARS; + unsigned int conv_len = 0; + unsigned int width = 0; + unsigned int precision_fill; + unsigned int field_fill; + LARGEST_UNSIGNED uvalue = 0; + int negative = 0; + + if(precision < 0) { + precision = 1; + } else { + flags &= ~PAD_ZERO; + } + + if(flags & SIGNED_YES) { + /* signed integers */ + LARGEST_SIGNED value = 0; + switch(flags & SIZE_MASK) { + case SIZE_CHAR: + value = (signed char)va_arg(ap, int); + break; + case SIZE_SHORT: + value = (short)va_arg(ap, int); + break; + case SIZE_INT: + value = va_arg(ap, int); + break; +#ifndef HAVE_LONGLONG + case SIZE_LONGLONG: /* Treat long long the same as long */ +#endif + case SIZE_LONG: + value = va_arg(ap, long); + break; +#ifdef HAVE_LONGLONG + case SIZE_LONGLONG: + value = va_arg(ap, long long); + break; +#endif + } + if(value < 0) { + uvalue = -value; + negative = 1; + } else { + uvalue = value; + } + } else { + + switch(flags & SIZE_MASK) { + case SIZE_CHAR: + uvalue = (unsigned char)va_arg(ap, unsigned int); + break; + case SIZE_SHORT: + uvalue = (unsigned short)va_arg(ap, unsigned int); + break; + case SIZE_INT: + uvalue = va_arg(ap, unsigned int); + break; +#ifndef HAVE_LONGLONG + case SIZE_LONGLONG: /* Treat long long the same as long */ +#endif + case SIZE_LONG: + uvalue = va_arg(ap, unsigned long); + break; +#ifdef HAVE_LONGLONG + case SIZE_LONGLONG: + uvalue = va_arg(ap, unsigned long long); + break; +#endif + } + } + + switch(flags & (RADIX_MASK)) { + case RADIX_DECIMAL: + conv_len = output_uint_decimal(&conv_pos, uvalue); + break; + case RADIX_OCTAL: + conv_len = output_uint_octal(&conv_pos, uvalue); + break; + case RADIX_HEX: + conv_len = output_uint_hex(&conv_pos, uvalue, flags); + break; + } + + width += conv_len; + precision_fill = (precision > conv_len) ? precision - conv_len : 0; + if((flags & (RADIX_MASK | ALTERNATE_FORM)) + == (RADIX_OCTAL | ALTERNATE_FORM)) { + if(precision_fill < 1) { + precision_fill = 1; + } + } + + width += precision_fill; + + if((flags & (RADIX_MASK | ALTERNATE_FORM)) + == (RADIX_HEX | ALTERNATE_FORM) && uvalue != 0) { + prefix_len = 2; + if(flags & CAPS_YES) { + prefix = "0X"; + } else { + prefix = "0x"; + } + } + + if(flags & SIGNED_YES) { + if(negative) { + prefix = "-"; + prefix_len = 1; + } else { + switch(flags & POSITIVE_MASK) { + case POSITIVE_SPACE: + prefix = " "; + prefix_len = 1; + break; + case POSITIVE_PLUS: + prefix = "+"; + prefix_len = 1; + break; + } + } + } + + width += prefix_len; + + field_fill = (minwidth > width) ? minwidth - width : 0; + + if((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) { + if(flags & PAD_ZERO) { + precision_fill += field_fill; + field_fill = 0; /* Do not double count padding */ + } else { + CHECKCB(fill_space(ctxt, field_fill)); + } + } + + if(prefix_len > 0) { + CHECKCB(ctxt->write_str(ctxt->user_data, prefix, prefix_len)); + } + written += prefix_len; + + CHECKCB(fill_zero(ctxt, precision_fill)); + written += precision_fill; + + CHECKCB(ctxt->write_str(ctxt->user_data, conv_pos, conv_len)); + written += conv_len; + + if((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) { + CHECKCB(fill_space(ctxt, field_fill)); + } + written += field_fill; + } + break; + case CONV_STRING: + { + unsigned int field_fill; + unsigned int len; + char *str = va_arg(ap, char *); + + if(str) { + char *pos = str; + while(*pos != '\0') pos++; + len = pos - str; + } else { + str = "(null)"; + len = 6; + } + + if(precision >= 0 && precision < len) { + len = precision; + } + + field_fill = (minwidth > len) ? minwidth - len : 0; + + if((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) { + CHECKCB(fill_space(ctxt, field_fill)); + } + + CHECKCB(ctxt->write_str(ctxt->user_data, str, len)); + written += len; + + if((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) { + CHECKCB(fill_space(ctxt, field_fill)); + } + written += field_fill; + } + break; + case CONV_POINTER: + { + LARGEST_UNSIGNED uvalue = + (LARGEST_UNSIGNED)(POINTER_INT)va_arg(ap, void *); + char buffer[MAXCHARS_HEX + 3]; + char *conv_pos = buffer + MAXCHARS_HEX + 3; + unsigned int conv_len; + unsigned int field_fill; + + conv_len = output_uint_hex(&conv_pos, uvalue, flags); + + if(conv_len == 0) { + *--conv_pos = '0'; + conv_len++; + } + + *--conv_pos = 'x'; + *--conv_pos = '0'; + *--conv_pos = '#'; + conv_len += 3; + + field_fill = (minwidth > conv_len) ? minwidth - conv_len : 0; + + if((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) { + CHECKCB(fill_space(ctxt, field_fill)); + } + + CHECKCB(ctxt->write_str(ctxt->user_data, conv_pos, conv_len)); + written += conv_len; + + if((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) { + CHECKCB(fill_space(ctxt, field_fill)); + } + + written += field_fill; + } + break; + case CONV_CHAR: + { + char ch = va_arg(ap, int); + unsigned int field_fill = (minwidth > 1) ? minwidth - 1 : 0; + + if((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) { + CHECKCB(fill_space(ctxt, field_fill)); + written += field_fill; + } + + CHECKCB(ctxt->write_str(ctxt->user_data, &ch, 1)); + written++; + + if((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) { + CHECKCB(fill_space(ctxt, field_fill)); + } + written += field_fill; + } + break; + case CONV_WRITTEN: + { + int *p = va_arg(ap, int *); + *p = written; + } + break; + } + } + + return written; +} +/*---------------------------------------------------------------------------*/ diff --git a/os/lib/dbg-io/strformat.h b/os/lib/dbg-io/strformat.h new file mode 100644 index 000000000..62d99b303 --- /dev/null +++ b/os/lib/dbg-io/strformat.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2009, Simon Berg + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#ifndef STRFORMAT_H_ +#define STRFORMAT_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" + +#include +/*---------------------------------------------------------------------------*/ +#define STRFORMAT_OK 0 +#define STRFORMAT_FAILED 1 +/*---------------------------------------------------------------------------*/ +typedef unsigned int strformat_result; +/*---------------------------------------------------------------------------*/ +/* The data argument may only be considered valid during the function call */ +typedef strformat_result (*strformat_write)(void *user_data, + const char *data, + unsigned int len); + +typedef struct strformat_context_s { + strformat_write write_str; + void *user_data; +} strformat_context_t; +/*---------------------------------------------------------------------------*/ +int format_str(const strformat_context_t *ctxt, const char *format, ...) + __attribute__ ((__format__ (__printf__, 2,3))); + +int +format_str_v(const strformat_context_t *ctxt, const char *format, va_list ap); +/*---------------------------------------------------------------------------*/ +#endif /* STRFORMAT_H_ */ +/*---------------------------------------------------------------------------*/