projects
/
bertos.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Update Doxyfile to avoid warnings.
[bertos.git]
/
mware
/
xmodem.c
diff --git
a/mware/xmodem.c
b/mware/xmodem.c
index 559a0c5df331609be6287dd13209f008450ca802..c3410cafed8db3b8581d248100ac816d73c00c34 100755
(executable)
--- a/
mware/xmodem.c
+++ b/
mware/xmodem.c
@@
-1,33
+1,36
@@
-#error This module has not been revised for the API changes in several DevLib modules
-/*!
+/**
* \file
* <!--
* \file
* <!--
- * Copyright 2004 Develer S.r.l. (http://www.develer.com/)
+ * Copyright 2004
, 2005, 2006, 2007
Develer S.r.l. (http://www.develer.com/)
* Copyright 1999, 2001 Bernardo Innocenti <bernie@develer.com>
* Copyright 1999, 2001 Bernardo Innocenti <bernie@develer.com>
- * This file is part of DevLib - See
devlib/README
for information.
+ * This file is part of DevLib - See
README.devlib
for information.
* -->
* \brief X-Modem serial transmission protocol (implementation)
*
* -->
* \brief X-Modem serial transmission protocol (implementation)
*
- * Suppots the CRC-16 and 1K-blocks variants of the standard.
+ * Suppo
r
ts the CRC-16 and 1K-blocks variants of the standard.
* \see ymodem.txt for the protocol description.
*
* \see ymodem.txt for the protocol description.
*
- * \todo Decouple this code from the LCD, buzzer and timer drivers
- * introducing user hooks or macros like CHECK_ABORT.
- *
* \todo Break xmodem_send() and xmodem_recv() in smaller functions.
*
* \todo Break xmodem_send() and xmodem_recv() in smaller functions.
*
- * \todo Add CONFIG_* vars to exclude either the receiver or the sender,
- * to reduce the footprint for applications that don't need both.
- *
* \todo Maybe convert drv/ser.c to the KFile interface for symmetry and
* flexibility.
*
* \version $Id$
* \author Bernardo Innocenti <bernie@develer.com>
* \todo Maybe convert drv/ser.c to the KFile interface for symmetry and
* flexibility.
*
* \version $Id$
* \author Bernardo Innocenti <bernie@develer.com>
+ * \author Francesco Sacchi <batt@develer.com>
*/
/*#*
*#* $Log$
*/
/*#*
*#* $Log$
+ *#* Revision 1.11 2007/06/07 09:10:44 batt
+ *#* Fix some todos.
+ *#*
+ *#* Revision 1.10 2006/07/19 12:56:28 bernie
+ *#* Convert to new Doxygen style.
+ *#*
+ *#* Revision 1.9 2005/11/04 16:20:02 bernie
+ *#* Fix reference to README.devlib in header.
+ *#*
*#* Revision 1.8 2004/08/25 14:12:09 rasky
*#* Aggiornato il comment block dei log RCS
*#*
*#* Revision 1.8 2004/08/25 14:12:09 rasky
*#* Aggiornato il comment block dei log RCS
*#*
@@
-60,81
+63,41
@@
#include "xmodem.h"
#include <drv/ser.h>
#include "xmodem.h"
#include <drv/ser.h>
-#include <drv/lcd.h>
-#include <drv/buzzer.h>
-#include <mware/crc.h>
-#include <mware/kfile.h>
-
#include <string.h> /* for memset() */
#include <string.h> /* for memset() */
+#include <algos/crc.h>
-/*
!
+/*
*
* \name Protocol control codes
* \{
*/
* \name Protocol control codes
* \{
*/
-#define XM_SOH 0x01 /*
!
< Start Of Header (128-byte block) */
-#define XM_STX 0x02 /*
!
< Start Of Header (1024-byte block) */
-#define XM_EOT 0x04 /*
!
< End Of Transmission */
-#define XM_ACK 0x06 /*
!
< Acknowledge block */
-#define XM_NAK 0x15 /*
!
< Negative Acknowledge */
-#define XM_C 0x43 /*
!
< Request CRC-16 transmission */
-#define XM_CAN 0x18 /*
!
< CANcel transmission */
+#define XM_SOH 0x01 /*
*
< Start Of Header (128-byte block) */
+#define XM_STX 0x02 /*
*
< Start Of Header (1024-byte block) */
+#define XM_EOT 0x04 /*
*
< End Of Transmission */
+#define XM_ACK 0x06 /*
*
< Acknowledge block */
+#define XM_NAK 0x15 /*
*
< Negative Acknowledge */
+#define XM_C 0x43 /*
*
< Request CRC-16 transmission */
+#define XM_CAN 0x18 /*
*
< CANcel transmission */
/*\}*/
/*\}*/
-#define XM_MAXRETRIES 15 /*!< Max retries before giving up */
-#define XM_MAXCRCRETRIES 7 /*!< Max retries before switching to BCC */
-#define XM_BUFSIZE 1024 /*!< Size of block buffer */
+#define XM_MAXRETRIES 15 /**< Max retries before giving up */
+#define XM_MAXCRCRETRIES 7 /**< Max retries before switching to BCC */
-
-#if (ARCH & ARCH_BOOT)
- #include "kbdhw.h"
- #if (ARCH & ARCH_SLIM)
- #define CHECK_ABORT KEYPRESSED_STOP
- #elif (ARCH & ARCH_SARF)
- #define CHECK_ABORT KEYPRESSED_ESC
- #endif
+#if CONFIG_XMODEM_1KCRC == 1
+ #define XM_BUFSIZE 1024 /**< 1024 bytes of block buffer */
#else
#else
- #include "kbd.h"
- #if (ARCH & ARCH_SLIM)
- #define CHECK_ABORT (kbd_getchar() == K_STOP)
- #elif (ARCH & ARCH_SARF)
- #define CHECK_ABORT (kbd_getchar() == K_ESC)
- #endif
-#endif /* ARCH_BOOT */
-
-
-/*!
- * Decode serial driver errors and print them on the display.
- */
-static void print_serial_error(struct Serial *port, int retries)
-{
- serstatus_t err, status;
+ #define XM_BUFSIZE 128 /**< 128 bytes of block buffer */
+#endif
- /* Get serial error code and reset it */
- status = ser_getstatus(port);
- ser_setstatus(port, 0);
- /* Mostra tutti gli errori in sequenza */
- for (err = 0; status != 0; status >>= 1, err++)
- {
- /* Se il bit dell'errore e' settato */
- if (status & 1)
- {
- lcd_printf(0, 3, LCD_FILL, "%s %d", serial_errors[err], retries);
- buz_beep(200);
- timer_delay(500);
- }
- }
-}
-
-
-/*!
+#if CONFIG_XMODEM_RECV
+/**
* \brief Receive a file using the XModem protocol.
*
* \param port Serial port to use for transfer
* \param fd Destination file
*
* \brief Receive a file using the XModem protocol.
*
* \param port Serial port to use for transfer
* \param fd Destination file
*
- * \note This function allocates a large amount of stack (
>1KB
).
+ * \note This function allocates a large amount of stack (
\see XM_BUFSIZE
).
*/
bool xmodem_recv(struct Serial *port, KFile *fd)
{
*/
bool xmodem_recv(struct Serial *port, KFile *fd)
{
@@
-148,20
+111,18
@@
bool xmodem_recv(struct Serial *port, KFile *fd)
bool usecrc = true;
bool usecrc = true;
- lcd_printf(0, 2, LCD_FILL, "Starting Transfer...");
- lcd_clear();
+ XMODEM_PROGRESS("Starting Transfer...\n");
purge = true;
purge = true;
- ser_settimeouts(port, SER_DEFRXTIMEOUT, SER_DEFTXTIMEOUT);
ser_setstatus(port, 0);
/* Send initial NAK to start transmission */
for(;;)
{
ser_setstatus(port, 0);
/* Send initial NAK to start transmission */
for(;;)
{
- if (CHECK_ABORT)
+ if (
XMODEM_
CHECK_ABORT)
{
ser_putchar(XM_CAN, port);
ser_putchar(XM_CAN, port);
{
ser_putchar(XM_CAN, port);
ser_putchar(XM_CAN, port);
-
lcd_printf(0, 2, LCD_FILL, "Transfer aborted
");
+
XMODEM_PROGRESS("Transfer aborted\n
");
return false;
}
return false;
}
@@
-173,8
+134,8
@@
bool xmodem_recv(struct Serial *port, KFile *fd)
{
purge = false;
{
purge = false;
- if (ser_getstatus())
-
SerialError(
retries);
+ if (ser_getstatus(
port
))
+
XMODEM_PROGRESS("Retries %d\n",
retries);
ser_resync(port, 200);
retries++;
ser_resync(port, 200);
retries++;
@@
-183,7
+144,7
@@
bool xmodem_recv(struct Serial *port, KFile *fd)
{
ser_putchar(XM_CAN, port);
ser_putchar(XM_CAN, port);
{
ser_putchar(XM_CAN, port);
ser_putchar(XM_CAN, port);
-
lcd_printf(0, 2, LCD_FILL, "Transfer aborted
");
+
XMODEM_PROGRESS("Transfer aborted\n
");
return false;
}
return false;
}
@@
-192,14
+153,14
@@
bool xmodem_recv(struct Serial *port, KFile *fd)
{
if (retries < XM_MAXCRCRETRIES)
{
{
if (retries < XM_MAXCRCRETRIES)
{
-
lcd_printf(0, 2, LCD_FILL, "Request Tx (CRC)
");
+
XMODEM_PROGRESS("Request Tx (CRC)\n
");
ser_putchar(XM_C, port);
}
else
{
/* Give up with CRC and fall back to checksum */
usecrc = false;
ser_putchar(XM_C, port);
}
else
{
/* Give up with CRC and fall back to checksum */
usecrc = false;
-
lcd_printf(0, 2, LCD_FILL,
"Request Tx (BCC)");
+
XMODEM_PROGRESS(
"Request Tx (BCC)");
ser_putchar(XM_NAK, port);
}
}
ser_putchar(XM_NAK, port);
}
}
@@
-209,9
+170,11
@@
bool xmodem_recv(struct Serial *port, KFile *fd)
switch (ser_getchar(port))
{
switch (ser_getchar(port))
{
+ #if XM_BUFSIZE >= 1024
case XM_STX: /* Start of header (1024-byte block) */
blocksize = 1024;
goto getblock;
case XM_STX: /* Start of header (1024-byte block) */
blocksize = 1024;
goto getblock;
+ #endif
case XM_SOH: /* Start of header (128-byte block) */
blocksize = 128;
case XM_SOH: /* Start of header (128-byte block) */
blocksize = 128;
@@
-223,7
+186,7
@@
bool xmodem_recv(struct Serial *port, KFile *fd)
/* Check complemented block number */
if ((~c & 0xff) != ser_getchar(port))
{
/* Check complemented block number */
if ((~c & 0xff) != ser_getchar(port))
{
-
lcd_printf(0, 3, LCD_FILL, "Bad blk (%d)
", c);
+
XMODEM_PROGRESS("Bad blk (%d)\n
", c);
purge = true;
break;
}
purge = true;
break;
}
@@
-231,14
+194,14
@@
bool xmodem_recv(struct Serial *port, KFile *fd)
/* Determine which block is being sent */
if (c == (blocknr & 0xff))
/* Last block repeated */
/* Determine which block is being sent */
if (c == (blocknr & 0xff))
/* Last block repeated */
-
lcd_printf(0, 2, LCD_FILL, "Repeat blk %d
", blocknr);
+
XMODEM_PROGRESS("Repeat blk %d\n
", blocknr);
else if (c == ((blocknr + 1) & 0xff))
/* Next block */
else if (c == ((blocknr + 1) & 0xff))
/* Next block */
-
lcd_printf(0, 2, LCD_FILL, "Recv blk %d
", ++blocknr);
+
XMODEM_PROGRESS("Recv blk %d\n
", ++blocknr);
else
{
/* Sync lost */
else
{
/* Sync lost */
-
lcd_printf(0, 3, LCD_FILL, "Sync lost (%d/%d)
", c, blocknr);
+
XMODEM_PROGRESS("Sync lost (%d/%d)\n
", c, blocknr);
purge = true;
break;
}
purge = true;
break;
}
@@
-289,7
+252,7
@@
bool xmodem_recv(struct Serial *port, KFile *fd)
if (crc)
{
if (crc)
{
-
lcd_printf(0, 3, LCD_FILL, "Bad CRC: %04x
", crc);
+
XMODEM_PROGRESS("Bad CRC: %04x\n
", crc);
purge = true;
break;
}
purge = true;
break;
}
@@
-297,7
+260,7
@@
bool xmodem_recv(struct Serial *port, KFile *fd)
/* Compare the checksum */
else if (c != checksum)
{
/* Compare the checksum */
else if (c != checksum)
{
-
lcd_printf(0, 3, LCD_FILL, "Bad sum: %04x/%04x
", checksum, c);
+
XMODEM_PROGRESS("Bad sum: %04x/%04x\n
", checksum, c);
purge = true;
break;
}
purge = true;
break;
}
@@
-328,7
+291,7
@@
bool xmodem_recv(struct Serial *port, KFile *fd)
case XM_EOT: /* End of transmission */
ser_putchar(XM_ACK, port);
case XM_EOT: /* End of transmission */
ser_putchar(XM_ACK, port);
-
lcd_printf(0, 2, LCD_FILL,
"Transfer completed");
+
XMODEM_PROGRESS(
"Transfer completed");
return true;
case EOF: /* Timeout or serial error */
return true;
case EOF: /* Timeout or serial error */
@@
-336,22
+299,24
@@
bool xmodem_recv(struct Serial *port, KFile *fd)
break;
default:
break;
default:
-
lcd_printf(0, 3, LCD_FILL,
"Skipping garbage");
+
XMODEM_PROGRESS(
"Skipping garbage");
purge = true;
break;
}
} /* End forever */
}
purge = true;
break;
}
} /* End forever */
}
+#endif
-/*!
- * \brief Transmit a file using the XModem protocol.
+#if CONFIG_XMODEM_SEND
+/**
+ * \brief Transmit some data using the XModem protocol.
*
* \param port Serial port to use for transfer
* \param fd Source file
*
* \note This function allocates a large amount of stack for
*
* \param port Serial port to use for transfer
* \param fd Source file
*
* \note This function allocates a large amount of stack for
- * the XModem transfer buffer (
1KB
).
+ * the XModem transfer buffer (
\see XM_BUFSIZE
).
*/
bool xmodem_send(struct Serial *port, KFile *fd)
{
*/
bool xmodem_send(struct Serial *port, KFile *fd)
{
@@
-362,39
+327,43
@@
bool xmodem_send(struct Serial *port, KFile *fd)
uint16_t crc;
uint8_t sum;
uint16_t crc;
uint8_t sum;
+ /*
+ * Reading a block can be very slow, so we read the first block early
+ * to avoid receiving double XM_C char.
+ * This could happen if we check for XM_C and then read the block, giving
+ * the receiving device time to send another XM_C char misinterpretating
+ * the blocks sent.
+ */
+ size = fd->read(fd, block_buffer, XM_BUFSIZE);
- ser_settimeouts(port, SER_DEFRXTIMEOUT, SER_DEFTXTIMEOUT);
ser_setstatus(port, 0);
ser_purge(port);
ser_setstatus(port, 0);
ser_purge(port);
-
lcd_printf(0, 2, LCD_FILL, "Wait remote host
");
+
XMODEM_PROGRESS("Wait remote host\n
");
for(;;)
{
proceed = false;
do
{
for(;;)
{
proceed = false;
do
{
- if (CHECK_ABORT)
+ if (
XMODEM_
CHECK_ABORT)
return false;
switch (c = ser_getchar(port))
{
case XM_NAK:
return false;
switch (c = ser_getchar(port))
{
case XM_NAK:
+ XMODEM_PROGRESS("Resend blk %d\n", blocknr);
+ proceed = true;
+ break;
+
case XM_C:
case XM_C:
- if (
blocknr == 1
)
+ if (
c == XM_C
)
{
{
- if (c == XM_C)
- {
- lcd_printf(0, 2, LCD_FILL, "Tx start (CRC)");
- usecrc = true;
- }
- else
- lcd_printf(0, 2, LCD_FILL, "Tx start (BCC)");
-
- /* Call user function to read in one block */
- size = fd->read(fd, block_buffer, XM_BUFSIZE);
+ XMODEM_PROGRESS("Tx start (CRC)\n");
+ usecrc = true;
}
else
}
else
- lcd_printf(0, 2, LCD_FILL, "Resend blk %d", blocknr);
+ XMODEM_PROGRESS("Tx start (BCC)\n");
+
proceed = true;
break;
proceed = true;
break;
@@
-405,25
+374,26
@@
bool xmodem_send(struct Serial *port, KFile *fd)
/* Call user function to read in one block */
size = fd->read(fd, block_buffer, XM_BUFSIZE);
/* Call user function to read in one block */
size = fd->read(fd, block_buffer, XM_BUFSIZE);
+ XMODEM_PROGRESS("Send blk %d\n", blocknr);
blocknr++;
retries = 0;
proceed = true;
blocknr++;
retries = 0;
proceed = true;
- lcd_printf(0, 2, LCD_FILL, "Send blk %d", blocknr);
break;
case EOF:
break;
case EOF:
+ ser_setstatus(port, 0);
retries++;
retries++;
-
SerialError(
retries);
+
XMODEM_PROGRESS("Retries %d\n",
retries);
if (retries <= XM_MAXRETRIES)
break;
/* falling through! */
case XM_CAN:
if (retries <= XM_MAXRETRIES)
break;
/* falling through! */
case XM_CAN:
-
lcd_printf(0, 2, LCD_FILL, "Transfer aborted
");
+
XMODEM_PROGRESS("Transfer aborted\n
");
return false;
default:
return false;
default:
-
lcd_printf(0, 3, LCD_FILL, "Skipping garbage
");
+
XMODEM_PROGRESS("Skipping garbage\n
");
break;
}
}
break;
}
}
@@
-439,7
+409,11
@@
bool xmodem_send(struct Serial *port, KFile *fd)
memset(block_buffer + size, 0xFF, XM_BUFSIZE - size);
/* Send block header (STX, blocknr, ~blocknr) */
memset(block_buffer + size, 0xFF, XM_BUFSIZE - size);
/* Send block header (STX, blocknr, ~blocknr) */
- ser_putchar(XM_STX, port);
+ #if XM_BUFSIZE == 128
+ ser_putchar(XM_SOH, port);
+ #else
+ ser_putchar(XM_STX, port);
+ #endif
ser_putchar(blocknr & 0xFF, port);
ser_putchar(~blocknr & 0xFF, port);
ser_putchar(blocknr & 0xFF, port);
ser_putchar(~blocknr & 0xFF, port);
@@
-465,3
+439,4
@@
bool xmodem_send(struct Serial *port, KFile *fd)
ser_putchar(sum, port);
}
}
ser_putchar(sum, port);
}
}
+#endif