This page is a collection of utility functions which I did not find easily on the net. Either because the source code was not available, or there were part of a big library not easy to extract from. The source code is released under LGPL (Lesser GNU Public License) or under the BSD license (BSD 3-Clause "New" or "Revised" License) for the xmodem functions.
This page contains the source code for:
This small printf
function is a tiny implementation of the
standard C library function, it does not include all the capabilities of
the standard one. It has been designed to have a small footprint and to be
easy to include in an embedded software. The only external dependency is
the putchar()
functions which output a single character to the
output device. Once you provide this putchar
function, you may
link your code with this printf
and use it. This code is released
under the LGPL license.
The xmodem functions has been tested with several terminal emulators on GNU/Linux and windows. I did use the following xmodem specification to write them. This code is released under the BSD license (BSD 3-Clause "New" or "Revised" License).
The xmodem functions depends on memcpy
and
memset
which are standard C library functions, they are
builtin function in gcc. The last two dependencies are _inbyte
and _outbyte
. The _outbyte
function is the one
shown before; on my 68VZ328 board, I am using the following code for
_inbyte
:
int _inbyte(unsigned short timeout) // msec timeout { unsigned short c; int delay = timeout << 4; while (((c=readw(URX1)) & 0x2000) == 0) { usleep(60); /* 60 us * 16 = 960 us (~ 1 ms) */ if (timeout) { if (--delay == 0) return -2; } } return c & 0x0FF; }
_inbyte
has a timeout parameter with 1 msec resolution, the
timeout is build using a usleep
function which is a busy
loop of 1 µsec resolution.
As an alternative to the code using a table contained in crc16.c
, you might use the
following function. This is specially useful in case of memory constraints.
(contributed by Steve Checkoway, thanks !)
unsigned short crc16_ccitt( const void *buf, int len ) { unsigned short crc = 0; while( len-- ) { int i; crc ^= *(char *)buf++ << 8; for( i = 0; i < 8; ++i ) { if( crc & 0x8000 ) crc = (crc << 1) ^ 0x1021; else crc = crc << 1; } } return crc; }
A nice contribution from Pat Carr: the transmit function may be passed a function to fetch the data. This is used to read the data from a memory card with 512 bytes blocks and transmit each of them as a stream instead of getting the full data in memory before transmission. Here is the patch, thanks to Pat !
--- xmodem.c 2017-11-05 11:34:48.000000000 +0100 +++ xmodem-pat.c 2017-11-05 11:37:01.000000000 +0100 @@ -157,13 +157,14 @@ } } -int xmodemTransmit(unsigned char *src, int srcsz) +int xmodemTransmit(unsigned char *src, int srcsz, int tmpsz, void (*getsrc)()) { unsigned char xbuff[1030]; /* 1024 for XModem 1k + 3 head chars + 2 crc + nul */ int bufsz, crc = -1; unsigned char packetno = 1; int i, c, len = 0; int retry; + int offset; for(;;) { for( retry = 0; retry < 16; ++retry) { @@ -206,7 +207,11 @@ xbuff[3] = CTRLZ; } else { - memcpy (&xbuff[3], &src[len], c); + offset = len % tmpsz; + if (offset == 0) { + getsrc(); + } + memcpy (&xbuff[3], &src[offset], c); if (c < bufsz) xbuff[3+c] = CTRLZ; } if (crc) {
Thanks to Gergely Budai (Thuffir), another great contribution: XMODEM-1K improvement, chunked transfert on both transmit and receive and binary transfer mode.