A smaller printf ...
jazzed
Posts: 11,803
The printf function is probably the most used in a C library.
The standard, full featured printf can eat 12KB or more HUB memory.
Attached is a version of Eric's COG printf that can be used with LMM, CMM, or XMM modes.
This is a result of questions regarding reducing memory footprint.
The actual compiled size of this file in CMM mode is 648 bytes, and LMM mode is 1152 bytes (compiler from the default branch).
Advantages:
* No COG usage.
* Just drop contents below into your project to save KBs of memory.
Caveats:
* Only suitable for serial output up to 57600 baud.
* No stdio devices, no file IO.
* No floating point specifier like %f.
* Only %d, %x, %c, and %s specifies available.
The standard, full featured printf can eat 12KB or more HUB memory.
Attached is a version of Eric's COG printf that can be used with LMM, CMM, or XMM modes.
This is a result of questions regarding reducing memory footprint.
The actual compiled size of this file in CMM mode is 648 bytes, and LMM mode is 1152 bytes (compiler from the default branch).
Advantages:
* No COG usage.
* Just drop contents below into your project to save KBs of memory.
Caveats:
* Only suitable for serial output up to 57600 baud.
* No stdio devices, no file IO.
* No floating point specifier like %f.
* Only %d, %x, %c, and %s specifies available.
/* * very simple printf, adapted from one written by me * for the MiNT OS long ago * placed in the public domain * - Eric Smith */ #include <ctype.h> #include <stdarg.h> #include "propeller.h" /* globals that the loader may change; these represent the default * pins to use */ unsigned int _rxpin = 31; unsigned int _txpin = 30; unsigned int _baud = 57600; unsigned int _bitcycles; HUBTEXT int putchar(int origval) { int value = origval; int i; int txmask = (1<<_txpin); int bitcycles; int waitcycles; _DIRA |= txmask; _OUTA |= txmask; if (origval == '\n') putchar('\r'); if (_bitcycles == 0) _bitcycles = _clkfreq / _baud; bitcycles = _bitcycles; waitcycles = _CNT + bitcycles; value = (value | 256) << 1; for (i = 0; i < 10; i++) { waitcycles = waitcnt2(waitcycles, bitcycles); if (value & 1) _OUTA |= txmask; else _OUTA &= ~txmask; value >>= 1; } return origval; } /* * very simple printf -- just understands a few format features */ static HUBTEXT int PUTC(int c) { putchar(c); return 1; } static HUBTEXT int PUTS(const char *s) { int r = 0; while (*s) { putchar(*s++); r++; } return r; } static HUBTEXT int PUTL(unsigned long u, int base, int width, int fill_char) { int r = 0; static char obuf[32]; char *t; t = obuf; do { *t++ = "0123456789abcdef"[u % base]; u /= base; width--; } while (u > 0); while (width-- > 0) { putchar(fill_char); r++; } while (t != obuf) { putchar(*--t); r++; } return r; } static HUBTEXT int _doprnt( const char *fmt, va_list args ) { int outbytes = 0; char c, fill_char; char *s_arg; int i_arg; long l_arg; int width; while( (c = *fmt++) != 0 ) { if (c != '%') { outbytes += PUTC(c); continue; } c = *fmt++; width = 0; fill_char = ' '; if (c == '0') fill_char = '0'; while (c && isdigit(c)) { width = 10*width + (c-'0'); c = *fmt++; } if (!c) break; switch (c) { case '%': outbytes += PUTC(c); break; case 'c': i_arg = va_arg(args, int); outbytes += PUTC(i_arg); break; case 's': s_arg = va_arg(args, char *); outbytes += PUTS(s_arg); break; case 'd': case 'u': l_arg = va_arg(args, int); if (l_arg < 0 && c == 'd') { outbytes += PUTC('-'); width--; l_arg = -l_arg; } outbytes += PUTL(l_arg, 10, width, fill_char); break; case 'x': l_arg = va_arg(args, unsigned int); outbytes += PUTL(l_arg, 16, width, fill_char); break; } } return outbytes; } HUBTEXT int printf(const char *fmt, ...) { va_list args; int r; va_start(args, fmt); r = _doprnt(fmt, args); va_end(args); return r; }
Comments
The note I have says "inlude a smaller standard I/O library with no floating point".
I suppose to use this, you add this file and remove all the "#include <stdio.h>" lines in your code, right?
The difference is relatively small, but sometimes just a little bit helps.
#include <stdio.h> doesn't make any difference here because there is no file IO.
Carrying the LMM/CMM kernels in the image costs about 2KB.
Not having those would eliminate parallel LMM/CMM COG functions.