Trammell Hudson avatar Trammell Hudson committed 9ef5043

Split xmodem into separate file

Comments (0)

Files changed (4)

 # List C source files here. (C dependencies are automatically generated.)
 SRC =	$(TARGET).c \
 	bits.c \
+	xmodem.c \
 	usb_serial.c \
 
 
 #include <string.h>
 #include <util/delay.h>
 #include "usb_serial.h"
+#include "xmodem.h"
 #include "bits.h"
 
 void send_str(const char *s);
 }
 
 
-typedef struct
-{
-	uint8_t soh;
-	uint8_t block_num;
-	uint8_t block_num_complement;
-	uint8_t data[128];
-	uint8_t cksum;
-} __attribute__((__packed__))
-xmodem_block_t;
 
-#define XMODEM_SOH 0x01
-#define XMODEM_EOT 0x04
-#define XMODEM_ACK 0x06
-#define XMODEM_CAN 0x18
-#define XMODEM_C 0x43
-#define XMODEM_NAK 0x15
-#define XMODEM_EOF 0x1a
-
-
-/** Send a block.
- * Compute the checksum and complement.
- *
- * \return 0 if all is ok, -1 if a cancel is requested or more
- * than 10 retries occur.
- */
-static int
-xmodem_send_block(
-	xmodem_block_t * const block
-)
-{
-	// Compute the checksum and complement
-	uint8_t cksum = 0;
-	for (uint8_t i = 0 ; i < sizeof(block->data) ; i++)
-		cksum += block->data[i];
-	block->cksum = cksum;
-	block->block_num_complement = 0xFF - block->block_num;
-
-	// Send the block, and wait for an ACK
-	uint8_t retry_count = 0;
-	goto send_block;
-
-	while (retry_count++ < 10)
-	{
-		uint8_t c = usb_serial_getchar_block();
-		if (c == XMODEM_ACK)
-			return 0;
-		if (c == XMODEM_CAN)
-			return -1;
-		if (c != XMODEM_NAK)
-			continue;
-
-		send_block:
-		usb_serial_write((void*) block, sizeof(*block));
-	}
-
-	// Failure or cancel
-	return -1;
-}
-
-
-/** Send the entire PROM memory */
+/** Send the entire PROM memory via xmodem */
 static void
-xmodem_send(void)
+prom_send(void)
 {
 	uint8_t c;
 	static xmodem_block_t block;
 
-	block.soh = 0x01;
-	block.block_num = 0x00;
-
-	// wait for initial nak
-	while (1)
-	{
-		c = usb_serial_getchar_block();
-		if (c == XMODEM_NAK)
-			break;
-		if (c == XMODEM_CAN)
-			return;
-	}
+	if (xmodem_init(&block) < 0)
+		return;
 
 	// Ending address
 	const uint32_t end_addr = (((uint32_t) 1) << prom->addr_width) - 1;
 	uint32_t addr = 0;
 	while (1)
 	{
-		block.block_num++;
 		for (uint8_t off = 0 ; off < sizeof(block.data) ; off++)
 			block.data[off] = prom_read(addr++);
 
-		if (xmodem_send_block(&block) < 0)
+		if (xmodem_send(&block) < 0)
 			return;
 
 		// If we have wrapped the address, we are done
 			break;
 	}
 
-#if 0
-/* Don't send EOF?  rx adds it to the file? */
-	block.block_num++;
-	memset(block.data, XMODEM_EOF, sizeof(block.data));
-	if (xmodem_send_block(&block) < 0)
-		return;
-#endif
+	xmodem_fini(&block);
+}
 
-	// File transmission complete.  send an EOT
-	while (1)
-	{
-		usb_serial_putchar(XMODEM_EOT);
-		c = usb_serial_getchar_block();
-		if (c == XMODEM_ACK
-		||  c == XMODEM_CAN)
-			break;
-	}
-}
 
 
 
 		char c = usb_serial_getchar_echo();
 		switch (c)
 		{
-		case XMODEM_NAK: xmodem_send(); break;
+		case XMODEM_NAK: prom_send(); break;
 		case 'r': read_addr(); break;
 		case 'l': prom_list(); break;
 		case 'm': prom_mode(); break;
+/**
+ * \file xmodem protocol
+ *
+ * Using USB serial
+ */
+
+#include <avr/io.h>
+#include <avr/pgmspace.h>
+#include <avr/interrupt.h>
+#include <stdint.h>
+#include <string.h>
+#include <util/delay.h>
+#include "usb_serial.h"
+#include "xmodem.h"
+
+
+
+/** Send a block.
+ * Compute the checksum and complement.
+ *
+ * \return 0 if all is ok, -1 if a cancel is requested or more
+ * than 10 retries occur.
+ */
+int
+xmodem_send(
+	xmodem_block_t * const block
+)
+{
+	// Compute the checksum and complement
+	uint8_t cksum = 0;
+	for (uint8_t i = 0 ; i < sizeof(block->data) ; i++)
+		cksum += block->data[i];
+
+	block->cksum = cksum;
+	block->block_num++;
+	block->block_num_complement = 0xFF - block->block_num;
+
+	// Send the block, and wait for an ACK
+	uint8_t retry_count = 0;
+
+	while (retry_count++ < 10)
+	{
+		usb_serial_write((void*) block, sizeof(*block));
+
+		// Wait for an ACK (done), CAN (abort) or NAK (retry)
+		while (1)
+		{
+			uint8_t c = usb_serial_getchar();
+			if (c == XMODEM_ACK)
+				return 0;
+			if (c == XMODEM_CAN)
+				return -1;
+			if (c == XMODEM_NAK)
+				break;
+		}
+	}
+
+	// Failure or cancel
+	return -1;
+}
+
+
+int
+xmodem_init(
+	xmodem_block_t * const block
+)
+{
+	block->soh = 0x01;
+	block->block_num = 0x00;
+
+	// wait for initial nak
+	while (1)
+	{
+		uint8_t c = usb_serial_getchar();
+		if (c == XMODEM_NAK)
+			return 0;
+		if (c == XMODEM_CAN)
+			return -1;
+	}
+}
+
+
+int
+xmodem_fini(
+	xmodem_block_t * const block
+)
+{
+#if 0
+/* Don't send EOF?  rx adds it to the file? */
+	block->block_num++;
+	memset(block->data, XMODEM_EOF, sizeof(block->data));
+	if (xmodem_send_block(block) < 0)
+		return;
+#endif
+
+	// File transmission complete.  send an EOT
+	// wait for an ACK or CAN
+	while (1)
+	{
+		usb_serial_putchar(XMODEM_EOT);
+
+		while (1)
+		{
+			uint16_t c = usb_serial_getchar();
+			if (c == -1)
+				continue;
+			if (c == XMODEM_ACK)
+				return 0;
+			if (c == XMODEM_CAN)
+				return -1;
+		}
+	}
+}
+/** \file
+ * xmodem file transfer protocol.
+ */
+#ifndef _xmodem_h_
+#define _xmodem_h_
+
+#include <avr/io.h>
+#include <stdint.h>
+
+
+typedef struct
+{
+	uint8_t soh;
+	uint8_t block_num;
+	uint8_t block_num_complement;
+	uint8_t data[128];
+	uint8_t cksum;
+} __attribute__((__packed__))
+xmodem_block_t;
+
+#define XMODEM_SOH 0x01
+#define XMODEM_EOT 0x04
+#define XMODEM_ACK 0x06
+#define XMODEM_CAN 0x18
+#define XMODEM_C 0x43
+#define XMODEM_NAK 0x15
+#define XMODEM_EOF 0x1a
+
+
+int
+xmodem_init(
+	xmodem_block_t * const block
+);
+
+
+int
+xmodem_send(
+	xmodem_block_t * const block
+);
+
+
+int xmodem_fini(
+	xmodem_block_t * const block
+);
+
+
+#endif
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.