[PATCH 1/1] RFC Add USB download capability.

190 views
Skip to first unread message

Rick Bronson

unread,
Nov 21, 2011, 1:30:54 AM11/21/11
to x-lo...@googlegroups.com
OMAP USB loader. Using the version of x-loader with CONFIG_USB, you can
now boot up the BeagleBoard completely into Linux with a ramdisk via USB.

Steps:

1. You will need libusb-dev on your host box:

sudo apt-get install libusb-dev

2. Modify u-boot to boot directly if it can't find mmc:

change "run nandboot;" to "run ramboot;"

and add:

"ramboot=setenv bootargs console=ttyO2,115200n8 mem=256M no_console_suspend ramdisk_size=80000 root=/dev/ram0; bootm\0"

in this file u-boot/include/configs/omap3_beagle.h

3. Run minicom to the serial port, unplug USB OTG and brick power to
the BeagleBoard, remove the SD Card and then run this program like this:

cd scripts
sudo omap3_usbload/omap3_usbload -f ../tftpboot/x-load.bin \
-a 0x80008000 -f ../tftpboot/u-boot.bin \
-a 0x82000000 -f ../tftpboot/uMulti -j 0x80008000 -v

Then plug in the USB OTG cable to your host to power the board.

Usage: omap3_usbload -f file1 [-a addr2 -f file2] [-a addr3 -f file3] [etc] [-j addr] [-v]

NOTE: first file (file1) has no addr
Load address MUST come before each file2-N

uMulti is a combined kernel/filesystem. You can substitute
uImage for uMulti and it will at least boot into the kernel,
but you won't have a filesystem.

Tested on BeagleBoardXM Rev C and Beagleboard Rev B4

The Rev B4 Beagleboard saves u-boot environment var's in NAND so you will have to interrupt u-boot
and correct them. Also on Rev B4 you will have to use an older kernel, this one won't work, then
interrupt u-boot and do:

setenv bootargs console=ttyS2,115200n8 mem=128M no_console_suspend ramdisk_size=80000 root=/dev/ram0; bootm 0x82000000

You could load uImage at one address, then the ramdisk file at yet another address (at say 0x830000000) and do:

setenv bootargs console=ttyS2,115200n8 mem=128M no_console_suspend ramdisk_size=80000 root=/dev/ram0 initrd=0x830000000,8M; bootm 0x82000000

http://members.efn.org/~rick/pub/0001-Add-USB-download-capability.patch

From 719f9d4d4bb09fee612abae97b28d630b6d7cfdc Mon Sep 17 00:00:00 2001
From: Rick Bronson <ri...@efn.org>
Date: Sun, 20 Nov 2011 22:22:56 -0800
Subject: [PATCH 1/1] Add USB download capability.

Signed-off-by: Rick Bronson <ri...@efn.org>
---
board/igep00x0/config.mk | 4 +-
board/omap3530beagle/config.mk | 6 +-
board/omap3evm/config.mk | 4 +-
board/overo/config.mk | 4 +-
cpu/omap3/start.S | 17 ++-
drivers/Makefile | 2 +-
drivers/usb.c | 141 ++++++++++++
drivers/usb.h | 63 ++++++
include/common.h | 1 +
include/configs/omap3530beagle.h | 2 +
lib/board.c | 5 +
scripts/Makefile | 18 ++
scripts/omap3_usbload.c | 442 ++++++++++++++++++++++++++++++++++++++
scripts/signGP.c | 2 +-
14 files changed, 696 insertions(+), 15 deletions(-)
create mode 100644 drivers/usb.c
create mode 100644 drivers/usb.h
create mode 100644 scripts/Makefile
create mode 100644 scripts/omap3_usbload.c

diff --git a/board/igep00x0/config.mk b/board/igep00x0/config.mk
index 864b7d0..48f1f4b 100644
--- a/board/igep00x0/config.mk
+++ b/board/igep00x0/config.mk
@@ -14,6 +14,6 @@
# For XIP in 64K of SRAM or debug (GP device has it all availabe)
# SRAM 40200000-4020FFFF base
# initial stack at 0x4020fffc used in s_init (below xloader).
-# The run time stack is (above xloader, 2k below)
+# The run time stack is within xloader (2k)
# If any globals exist there needs to be room for them also
-TEXT_BASE = 0x40200800
+TEXT_BASE = 0x40200000
diff --git a/board/omap3530beagle/config.mk b/board/omap3530beagle/config.mk
index f271b14..c7100cb 100644
--- a/board/omap3530beagle/config.mk
+++ b/board/omap3530beagle/config.mk
@@ -10,11 +10,11 @@
# 8000'0000 (bank0)

# For use if you want X-Loader to relocate from SRAM to DDR
-#TEXT_BASE = 0x80e80000
+#TEXT_BASE = 0x40200000

# For XIP in 64K of SRAM or debug (GP device has it all availabe)
# SRAM 40200000-4020FFFF base
# initial stack at 0x4020fffc used in s_init (below xloader).
-# The run time stack is (above xloader, 2k below)
+# The run time stack is within xloader (2k)
# If any globals exist there needs to be room for them also
-TEXT_BASE = 0x40200800
+TEXT_BASE = 0x40200000
diff --git a/board/omap3evm/config.mk b/board/omap3evm/config.mk
index a45ec22..7b4d870 100644
--- a/board/omap3evm/config.mk
+++ b/board/omap3evm/config.mk
@@ -14,6 +14,6 @@
# For XIP in 64K of SRAM or debug (GP device has it all availabe)
# SRAM 40200000-4020FFFF base
# initial stack at 0x4020fffc used in s_init (below xloader).
-# The run time stack is (above xloader, 2k below)
+# The run time stack is within xloader (2k)
# If any globals exist there needs to be room for them also
-TEXT_BASE = 0x40200800
+TEXT_BASE = 0x40200000
diff --git a/board/overo/config.mk b/board/overo/config.mk
index 7ee3014..3ce87c3 100644
--- a/board/overo/config.mk
+++ b/board/overo/config.mk
@@ -15,6 +15,6 @@
# For XIP in 64K of SRAM or debug (GP device has it all availabe)
# SRAM 40200000-4020FFFF base
# initial stack at 0x4020fffc used in s_init (below xloader).
-# The run time stack is (above xloader, 2k below)
+# The run time stack is within xloader (2k)
# If any globals exist there needs to be room for them also
-TEXT_BASE = 0x40200800
+TEXT_BASE = 0x40200000
diff --git a/cpu/omap3/start.S b/cpu/omap3/start.S
index 4cbf437..983b065 100644
--- a/cpu/omap3/start.S
+++ b/cpu/omap3/start.S
@@ -142,9 +142,7 @@ copy_loop:

/* Set up the stack */
stack_setup:
- ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
- sub sp, r0, #128 /* leave 32 words for abort-stack */
- and sp, sp, #~7 /* 8 byte alinged for (ldr/str)d */
+ ldr sp, _abort_stack

/* Clear BSS (if any). Is below tx (watch load addr - need space) */
clear_bss:
@@ -161,7 +159,18 @@ clbss_l:

_start_armboot: .word start_armboot

-
+/* we can't have the stack at the beginning of SRAM, reset needs to be there */
+ .align 3
+ .octa 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* 256 bytes */
+ .octa 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* 256 bytes */
+ .octa 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* 256 bytes */
+ .octa 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* 256 bytes */
+ .octa 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* 256 bytes */
+ .octa 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* 256 bytes */
+ .octa 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* 256 bytes */
+ .octa 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* 256 bytes */
+abort_stack:
+_abort_stack: .word abort_stack
/*
*************************************************************************
*
diff --git a/drivers/Makefile b/drivers/Makefile
index bd620c2..807beb5 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -37,7 +37,7 @@ COBJS += k9f1g08r0a.o
endif

ifeq ($(BOARD), omap3530beagle)
-COBJS += k9f1g08r0a.o
+COBJS += k9f1g08r0a.o usb.o
endif

ifeq ($(BOARD), omap3evm)
diff --git a/drivers/usb.c b/drivers/usb.c
new file mode 100644
index 0000000..cd77f17
--- /dev/null
+++ b/drivers/usb.c
@@ -0,0 +1,141 @@
+/*
+ * USB bootloader
+ *
+ * Copyright (C) 2011 Rick Bronson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/arch/cpu.h> /* get chip and board defs */
+#include "usb.h"
+
+extern void udelay (unsigned long usecs);
+
+typedef int boot_os_fn (void);
+
+/* send a buffer via USB */
+int usb_send(unsigned char *buffer, unsigned int buffer_size)
+ {
+ int ret = 0;
+
+ if (!(*peri_txcsr & MUSB_TXCSR_TXPKTRDY))
+ {
+ unsigned int cntr;
+
+ for (cntr = 0; cntr < buffer_size; cntr++)
+ *bulk_fifo = buffer[cntr];
+
+ *peri_txcsr |= MUSB_TXCSR_TXPKTRDY;
+
+ ret = buffer_size;
+ }
+ return ret;
+ }
+
+////////////////////
+
+static int usb_recv (u8 *buffer, int size)
+{
+ int cntr;
+ u16 count = 0;
+
+ if (*peri_rxcsr & MUSB_RXCSR_RXPKTRDY)
+ {
+ count = *rxcount;
+ for (cntr = 0; cntr < count; cntr++)
+ {
+ *buffer++ = *bulk_fifo;
+ }
+ /* Clear the RXPKTRDY bit */
+ *peri_rxcsr &= ~MUSB_RXCSR_RXPKTRDY;
+ }
+ return count; /* FIXME */
+}
+
+static unsigned char usb_outbuffer[64];
+
+static void usb_msg (unsigned int cmd, const char *msg)
+ {
+ unsigned char *p_char = usb_outbuffer;
+
+ * (int *) p_char = cmd;
+ p_char += sizeof (cmd);
+ if (msg)
+ {
+ while (*msg)
+ *p_char++= *msg++;
+ *p_char++= 0;
+ }
+ usb_send (usb_outbuffer, p_char - usb_outbuffer);
+ }
+
+static void usb_code (unsigned int cmd, u32 code)
+ {
+ unsigned int *p_int = (unsigned int *) usb_outbuffer;
+
+ *p_int++ = cmd;
+ *p_int++ = code;
+ usb_send (usb_outbuffer, ((unsigned char *) p_int) - usb_outbuffer);
+ }
+
+void do_usb (void)
+ {
+ boot_os_fn *boot_fn;
+ int res;
+ u32 usb_inbuffer[16];
+ u32 total;
+ u8 *addr;
+ u32 bytes;
+ int size;
+ int cntr;
+
+ usb_msg (USBLOAD_CMD_FILE_REQ, "file req");
+ for (cntr = 0; cntr < 100000; cntr++) /* try for 1 second then bail out */
+ {
+ res = usb_recv ((u8 *) usb_inbuffer, sizeof (usb_inbuffer));
+ switch (usb_inbuffer[0])
+ {
+ case USBLOAD_CMD_FILE:
+ printf ("USBLOAD_CMD_FILE total = %d addr = 0x%x val = 0x%x val = 0x%x\n", res, usb_inbuffer[0], usb_inbuffer[1], usb_inbuffer[2]);
+ total = usb_inbuffer[1]; /* get size and address */
+ addr = (u8 *) usb_inbuffer[2];
+ usb_code (USBLOAD_CMD_ECHO_SZ, total);
+
+ bytes = 0;
+ while (bytes < total)
+ {
+ size = usb_recv ((u8 *) usb_inbuffer, sizeof (usb_inbuffer));
+ memcpy(addr, usb_inbuffer, size);
+ addr += size;
+ bytes += size;
+ }
+ usb_code (USBLOAD_CMD_REPORT_SZ, total); /* tell him we got this many bytes */
+ printf ("got file addr = 0x%x\n", addr);
+ usb_msg (USBLOAD_CMD_FILE_REQ, "file req"); /* see if they have another file for us */
+ break;
+ case USBLOAD_CMD_JUMP:
+ printf ("USBLOAD_CMD_JUMP total = %d addr = 0x%x val = 0x%x\n", res, usb_inbuffer[0], usb_inbuffer[1]);
+ boot_fn = (boot_os_fn *) usb_inbuffer[1];
+ boot_fn(); /* go to u-boot and maybe kernel */
+ break;
+ default:
+ break;
+ }
+ udelay(10); /* delay 10 us */
+ }
+ }
diff --git a/drivers/usb.h b/drivers/usb.h
new file mode 100644
index 0000000..ba8f495
--- /dev/null
+++ b/drivers/usb.h
@@ -0,0 +1,63 @@
+/*
+ * USB bootloader
+ *
+ * Copyright (C) 2011 Rick Bronson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _USB_H_
+#define _USB_H_
+
+#define OMAP34XX_USB_BASE (OMAP34XX_CORE_L4_IO_BASE + 0xAB000)
+
+#define OMAP34XX_USB_EP(n) (OMAP34XX_USB_BASE + 0x100 + 0x10*(n))
+
+#define MUSB_RXCSR 0x06
+#define MUSB_RXCOUNT 0x08
+#define MUSB_TXCSR 0x02
+#define MUSB_FIFOSIZE 0x0F
+#define OMAP34XX_USB_RXCSR(n) (OMAP34XX_USB_EP(n) + MUSB_RXCSR)
+#define OMAP34XX_USB_RXCOUNT(n) (OMAP34XX_USB_EP(n) + MUSB_RXCOUNT)
+#define OMAP34XX_USB_TXCSR(n) (OMAP34XX_USB_EP(n) + MUSB_TXCSR)
+#define OMAP34XX_USB_FIFOSIZE(n) (OMAP34XX_USB_EP(n) + MUSB_FIFOSIZE)
+#define OMAP34XX_USB_FIFO(n) (OMAP34XX_USB_BASE + 0x20 + ((n) * 4))
+
+/* memory mapped registers */
+#define BULK_ENDPOINT 1
+static volatile u16 *peri_rxcsr = (volatile u16 *) OMAP34XX_USB_RXCSR(BULK_ENDPOINT);
+#define MUSB_RXCSR_RXPKTRDY 0x0001
+static volatile u16 *rxcount = (volatile u16 *) OMAP34XX_USB_RXCOUNT(BULK_ENDPOINT);
+static volatile u16 *peri_txcsr = (volatile u16 *) OMAP34XX_USB_TXCSR(BULK_ENDPOINT);
+#define MUSB_TXCSR_TXPKTRDY 0x0001
+static volatile u8 *bulk_fifo = (volatile u8 *) OMAP34XX_USB_FIFO(BULK_ENDPOINT);
+
+/* In high speed mode packets are 512
+ In full speed mode packets are 64 */
+#define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_2_0 (0x0200)
+#define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_1_1 (0x0040)
+
+#define MIN(a,b) ( ((a) < (b)) ? (a) : (b))
+
+#define PACK4(a,b,c,d) (((d)<<24) | ((c)<<16) | ((b)<<8) | (a))
+#define USBLOAD_CMD_FILE PACK4('U', 'S', 'B', 's') /* send file size */
+#define USBLOAD_CMD_JUMP PACK4('U', 'S', 'B', 'j') /* go where I tell you */
+#define USBLOAD_CMD_FILE_REQ PACK4('U', 'S', 'B', 'f') /* file request */
+#define USBLOAD_CMD_ECHO_SZ PACK4('U', 'S', 'B', 'n') /* echo file size */
+#define USBLOAD_CMD_REPORT_SZ PACK4('U', 'S', 'B', 'o') /* report file size */
+#define USBLOAD_CMD_MESSAGE PACK4('U', 'S', 'B', 'm') /* message for debug */
+
+#endif
diff --git a/include/common.h b/include/common.h
index a3c5092..e21cc23 100644
--- a/include/common.h
+++ b/include/common.h
@@ -111,6 +111,7 @@ void hang (void) __attribute__ ((noreturn));
extern int do_load_serial_bin (ulong offset, int baudrate);
extern u32 get_mem_type(void);
extern int mmc_init(int verbose);
+extern void do_usb(void);
extern int misc_init_r(void);

extern int sprintf (char *__s, const char *__format, ...);
diff --git a/include/configs/omap3530beagle.h b/include/configs/omap3530beagle.h
index 5625417..76e3261 100644
--- a/include/configs/omap3530beagle.h
+++ b/include/configs/omap3530beagle.h
@@ -42,6 +42,8 @@

#define CONFIG_BEAGLE_REV2 1

+/* Enable the below macro if you want to use omap3_usbload to download u-boot and linux via USB */
+#define CONFIG_USB 1
/* Enable the below macro if MMC boot support is required */
#define CONFIG_MMC 1
#if defined(CONFIG_MMC)
diff --git a/lib/board.c b/lib/board.c
index 0f6b960..2f1d288 100644
--- a/lib/board.c
+++ b/lib/board.c
@@ -93,6 +93,11 @@ void start_armboot (void)

misc_init_r();

+#ifdef CONFIG_USB
+ printf("Trying load from USB\n");
+ do_usb(); /* check for usb download */
+#endif
+
buf = (uchar*) CFG_LOADADDR;
*(int *)buf = 0xffffffff;

diff --git a/scripts/Makefile b/scripts/Makefile
new file mode 100644
index 0000000..04c1e55
--- /dev/null
+++ b/scripts/Makefile
@@ -0,0 +1,18 @@
+CC = gcc
+INCLUDES =
+CFLAGS = -Wall -O2 -g $(INCLUDES)
+LIBS = -lusb
+LDFLAGS = -g $(LIBS)
+APP_NAME = omap3_usbload
+
+OBJS = omap3_usbload.o
+
+all: $(APP_NAME)
+
+$(APP_NAME): $(OBJS)
+ $(CC) $(LDFLAGS) -o $@ $^
+
+clean:
+ rm -r $(APP_NAME) *.o
+
+.PHONY: all clean
diff --git a/scripts/omap3_usbload.c b/scripts/omap3_usbload.c
new file mode 100644
index 0000000..4666111
--- /dev/null
+++ b/scripts/omap3_usbload.c
@@ -0,0 +1,442 @@
+/* $Id: Exp $
+ *
+ * omap3_usbload, an USB download application for OMAP3 processors
+ * Copyright (C) 2008 Martin Mueller <mart...@pfump.org>
+ * Modified by Rick Bronson 2011
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with paparazzi; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/*
+
+ OMAP USB loader. Using the version of x-loader with CONFIG_USB, you can
+now boot up the BeagleBoard completely into Linux with a ramdisk via USB.
+
+ Steps:
+
+1. You will need libusb-dev on your host box:
+
+sudo apt-get install libusb-dev
+
+2. Modify u-boot to boot directly if it can't find mmc:
+
+change "run nandboot;" to "run ramboot;"
+
+and add:
+
+"ramboot=setenv bootargs console=ttyO2,115200n8 mem=256M no_console_suspend ramdisk_size=80000 root=/dev/ram0; bootm\0"
+
+ in this file u-boot/include/configs/omap3_beagle.h
+
+3. Run minicom to the serial port, unplug USB OTG and brick power to
+ the BeagleBoard, remove the SD Card and then run this program like this:
+
+cd scripts
+sudo omap3_usbload/omap3_usbload -f ../tftpboot/x-load.bin \
+ -a 0x80008000 -f ../tftpboot/u-boot.bin \
+ -a 0x82000000 -f ../tftpboot/uMulti -j 0x80008000 -v
+
+ Then plug in the USB OTG cable to your host to power the board.
+
+Usage: omap3_usbload -f file1 [-a addr2 -f file2] [-a addr3 -f file3] [etc] [-j addr] [-v]
+
+ NOTE: first file (file1) has no addr
+ Load address MUST come before each file2-N
+
+ uMulti is a combined kernel/filesystem. You can substitute
+uImage for uMulti and it will at least boot into the kernel,
+but you won't have a filesystem.
+
+ Tested on BeagleBoardXM Rev C and Beagleboard Rev B4
+
+ The Rev B4 Beagleboard saves u-boot environment var's in NAND so you will have to interrupt u-boot
+and correct them. Also on Rev B4 you will have to use an older kernel, this one won't work, then
+interrupt u-boot and do:
+
+setenv bootargs console=ttyS2,115200n8 mem=128M no_console_suspend ramdisk_size=80000 root=/dev/ram0; bootm 0x82000000
+
+ You could load uImage at one address, then the ramdisk file at yet another address (at say 0x830000000) and do:
+
+setenv bootargs console=ttyS2,115200n8 mem=128M no_console_suspend ramdisk_size=80000 root=/dev/ram0 initrd=0x830000000,8M; bootm 0x82000000
+
+*/
+
+#include <getopt.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <usb.h>
+
+#define VERSION "1.1"
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# define cpu_to_le32(x) (x)
+# define le32_to_cpu(x) (x)
+#else
+# define cpu_to_le32(x) bswap_32 (x)
+# define le32_to_cpu(x) bswap_32 (x)
+#endif
+
+#define VENDOR_ID_TI 0x0451
+#define DEVICE_ID 0xD000
+#define DEVICE_ID_MASK 0xff00
+
+#define OMAP3_BOOT_CMD 0xF0030002 /* see page 3515 sprugn4c.pdf */
+
+#define PACK4(a,b,c,d) (((d)<<24) | ((c)<<16) | ((b)<<8) | (a))
+#define USBLOAD_CMD_FILE PACK4('U', 'S', 'B', 's') /* send file size */
+#define USBLOAD_CMD_JUMP PACK4('U', 'S', 'B', 'j') /* go where I tell you */
+#define USBLOAD_CMD_FILE_REQ PACK4('U', 'S', 'B', 'f') /* file request */
+#define USBLOAD_CMD_ECHO_SZ PACK4('U', 'S', 'B', 'n') /* echo file size */
+#define USBLOAD_CMD_REPORT_SZ PACK4('U', 'S', 'B', 'o') /* report file size */
+#define USBLOAD_CMD_MESSAGE PACK4('U', 'S', 'B', 'm') /* message for debug */
+
+#define EP_BULK_IN 0x81
+#define EP_BULK_OUT 0x01
+#define BUF_LEN 128
+#define BUF_LEN_SM 256 /* we seem to need this exact size ?? */
+
+#define USB_TIMEOUT 1000 /* time in ms */
+
+#define MAX_FILES 10 /* the max addr/file pairs */
+struct UPLOAD_DATA
+ {
+ int file_cntr;
+ unsigned long addrs[MAX_FILES];
+ int fd[MAX_FILES];
+ int filesize[MAX_FILES];
+ const char *filename[MAX_FILES]; /* file names */
+ unsigned long jump_addr;
+ usb_dev_handle *udev;
+ int verbose; /* be verbose? */
+ char *p_file;
+ };
+
+struct UPLOAD_DATA upload_data =
+ {
+ .verbose = 0, /* be verbose? */
+ .filename[0] = NULL,
+ .jump_addr = 0x80008000,
+ .p_file = NULL,
+ };
+
+
+ /* A string listing valid short options letters. */
+const char* const short_options = "a:f:j:v";
+ /* An array describing valid long options. */
+const struct option long_options[] = {
+ { "load_addr", 1, NULL, 'a' },
+ { "file", 1, NULL, 'f' },
+ { "jump", 1, NULL, 'j' },
+ { "verbose", 0, NULL, 'v' },
+ { NULL, 0, NULL, 0 } /* Required at end of array. */
+ };
+
+/* send a value to x-loader */
+static int send_val (struct UPLOAD_DATA *p_data, unsigned int code, unsigned int val1, unsigned int val2)
+{
+ int res;
+ int buffer[3];
+
+ buffer[0]= code;
+ buffer[1] = cpu_to_le32 (val1);
+ buffer[2] = cpu_to_le32 (val2);
+
+ if (p_data->verbose)
+ printf ("send_val code = 0x%x, val1 = 0x%x, val2 = 0x%x\n",(int) buffer[0], (int) buffer[1], (int) buffer[2]);
+ res= usb_bulk_write (p_data->udev, EP_BULK_OUT, (const char *) buffer, sizeof (buffer), USB_TIMEOUT);
+ if (res < sizeof (buffer))
+ {
+ printf ("Error in usb_bulk_write1: %d/8\n", res);
+ return 1;
+ }
+
+ return 0;
+}
+
+void print_usage (FILE* stream, int exit_code)
+ {
+ fprintf (stream, "Usage: omap3_usbload -f file1 [-a addr2 -f file2] [-a addr3 -f file3] [etc] [-j addr] [-v]\n");
+ fprintf (stream,
+ " -f --file file File to load, first file (file1) has no addr\n"
+ " -a --load_addr addr Load address, MUST come before each file2-N\n"
+ " -j --jump addr Jump address[0x80008000]\n");
+ exit (exit_code);
+}
+
+enum { /* subroutine return codes */
+ RET_OK,
+ RET_ERR,
+ RET_IN_LOOP
+};
+
+int do_files(struct UPLOAD_DATA *p_data)
+ {
+ int res, sz, file_cnt, file_len, size, usb_cnt;
+ int dat_buf[BUF_LEN];
+ unsigned int command;
+ int this_file = 1; /* start with the 2nd file */
+ char *p_file;
+
+ file_cnt = usb_bulk_read(p_data->udev, EP_BULK_IN, (char *) dat_buf, sizeof (dat_buf), USB_TIMEOUT);
+ if (file_cnt <= 0)
+ {
+ printf("could not get ASIC ID\n");
+ return(-1);
+ }
+
+ command = OMAP3_BOOT_CMD;
+ if (sizeof(command) != usb_bulk_write(p_data->udev, EP_BULK_OUT, (char*) &command, sizeof(command), USB_TIMEOUT))
+ {
+ printf("could not send peripheral boot command\n");
+ return(-1);
+ }
+
+ file_len = p_data->filesize[0];
+ if (sizeof(file_len) != usb_bulk_write(p_data->udev, EP_BULK_OUT, (char*) &file_len, sizeof(file_len), USB_TIMEOUT))
+ {
+ printf("could not send length\n");
+ return(-1);
+ }
+
+ do
+ {
+ file_cnt = read(p_data->fd[0], dat_buf, sizeof (dat_buf));
+ if (file_cnt > 0)
+ {
+ usb_cnt = usb_bulk_write(p_data->udev, EP_BULK_OUT, (char *) dat_buf, file_cnt, USB_TIMEOUT);
+
+ if (usb_cnt != file_cnt)
+ {
+ printf("could not write to usb usb_cnt = %d file_cnt = %d\n", usb_cnt, file_cnt );
+ return(-1);
+ }
+ }
+ } while (file_cnt > 0);
+
+ if (p_data->verbose)
+ printf("download ok\n");
+ close(p_data->fd[0]);
+ p_data->fd[0] = 0; /* mark as closed */
+
+ /* now wait for x-loader */
+ while ((size = p_data->filesize[this_file]) > 0)
+ {
+ if (p_data->verbose)
+ printf ("while loop size = %d\n", size);
+ p_file = p_data->p_file = malloc (p_data->filesize[this_file]);
+ if (p_file == NULL)
+ {
+ printf ("Out of memory requesting %d bytes\n", p_data->filesize[this_file]);
+ return 1;
+ }
+ /* read whole file in */
+ if ((p_data->filesize[this_file] = read (p_data->fd[this_file], p_file, p_data->filesize[this_file])) < 0)
+ {
+ perror ("read file");
+ return 1;
+ }
+ if (p_data->verbose)
+ printf ("filesize = %d\n", p_data->filesize[this_file]);
+ close (p_data->fd[this_file]);
+
+ while (size > 0)
+ {
+ res= usb_bulk_read (p_data->udev, EP_BULK_IN, (char *) dat_buf, sizeof (dat_buf), USB_TIMEOUT);
+ if (res < 0)
+ {
+ printf("Error in usb_bulk_read: %d\n", res);
+ return 1;
+ }
+ if (res < 8)
+ continue;
+
+ switch (dat_buf[0])
+ {
+ case USBLOAD_CMD_FILE_REQ:
+ if (p_data->verbose)
+ printf("f: size = %d, addr = 0x%x\n", size, (int) p_data->addrs[this_file]);
+ if (send_val (p_data, USBLOAD_CMD_FILE, size, p_data->addrs[this_file]))
+ size= -1;
+ break;
+
+ case USBLOAD_CMD_REPORT_SZ: /* he tells us how many btyes are left */
+ size -= le32_to_cpu (dat_buf[1]);
+ if (size > 0)
+ size= -1;
+ break;
+
+ case USBLOAD_CMD_ECHO_SZ: /* he echo's the file size */
+ sz = le32_to_cpu (dat_buf[1]);
+ if (p_data->verbose)
+ printf("sending file, size %d %d\n", sz, res);
+ while (sz > 0)
+ {
+ res = usb_bulk_write(p_data->udev, EP_BULK_OUT, p_file, BUF_LEN_SM, USB_TIMEOUT);
+ if (res != BUF_LEN_SM) {
+ printf("Error in usb_bulk_write3: %d/%d\n", res, sz);
+ size = -1;
+ break;
+ }
+ p_file += res;
+ sz -= res;
+ }
+ break;
+
+ case USBLOAD_CMD_MESSAGE:
+ printf("Message: %s\n", (char *) &dat_buf[1]);
+ break;
+
+ default:
+ printf("Unknown packet type '%s'\n", (char *) dat_buf[1]);
+ break;
+ }
+ }
+ if (size == 0 && p_data->verbose)
+ printf("Program stored in memory: %d bytes\n", p_data->filesize[this_file]);
+ this_file++; /* next */
+ free (p_data->p_file);
+ p_data->p_file = NULL; /* mark as freed */
+ }
+ if (p_data->jump_addr)
+ {
+ send_val (p_data, USBLOAD_CMD_JUMP, p_data->jump_addr, 0); /* go to address */
+ if (p_data->verbose)
+ printf("Sending jump 0x%x\n", (int) p_data->jump_addr);
+ }
+ return 0;
+ }
+
+enum { /* need to have at least one file to load */
+ ARG_PROGNAME,
+ ARG_BINFILE,
+ NUM_ARGS
+};
+
+int main(int argc, char **argv)
+ {
+ struct UPLOAD_DATA *p_data;
+ int next_option;
+ struct usb_bus *bus;
+ int file_cntr = 0, res = RET_IN_LOOP;
+
+ p_data = &upload_data;
+ do
+ {
+ next_option = getopt_long (argc, argv, short_options,
+ long_options, NULL);
+ switch (next_option)
+ {
+ case 'a': /* -a or --load_addr */
+ /* This option takes an argument, the address to load the file into. */
+ p_data->addrs[file_cntr] = strtoul (optarg, NULL, 0);
+ break;
+ case 'f': /* -f or --file */
+ /* This option takes an argument, the name of the file. */
+ p_data->filename[file_cntr] = optarg;
+ p_data->fd[file_cntr] = open(p_data->filename[file_cntr], O_RDONLY);
+ if (p_data->fd[file_cntr] < 0)
+ {
+ perror("Can't open file");
+ return 1;
+ }
+ p_data->filesize[file_cntr] = lseek (p_data->fd[file_cntr], 0, SEEK_END);
+ if (p_data->filesize[file_cntr] < 0 || lseek (p_data->fd[file_cntr], 0, SEEK_SET) < 0)
+ {
+ perror ("lseek binfile");
+ close (p_data->fd[file_cntr]);
+ return 1;
+ }
+ if (p_data->verbose)
+ printf("Opening %s fd = %d, size = %d\n", p_data->filename[file_cntr], p_data->fd[file_cntr], p_data->filesize[file_cntr]);
+ file_cntr++; /* go to next file */
+ break;
+ case 'j': /* -j or --jump */
+ /* This option takes an argument, the jump address. */
+ p_data->jump_addr = strtoul (optarg, NULL, 0);
+ break;
+ case 'v': /* -v or --verbose */
+ p_data->verbose = 1;
+ break;
+ case '?': /* The user specified an invalid option. */
+ /* Print usage information to standard error, and exit with exit
+ code one (indicating abonormal termination). */
+ print_usage (stderr, 1);
+ break;
+ case -1: /* Done with options. */
+ break;
+ default: /* Something else: unexpected. */
+ print_usage (stderr, 1);
+ }
+ }
+ while (next_option != -1);
+
+ if (argc < NUM_ARGS) {
+ print_usage (stderr, 1);
+ return(-1);
+ }
+
+ usb_init();
+ usb_find_busses();
+
+ while (res == RET_IN_LOOP)
+ {
+ printf(".");
+ fflush(stdout);
+
+ if (usb_find_devices())
+ {
+ for (bus = usb_get_busses(); bus; bus = bus->next)
+ {
+ struct usb_device *dev;
+
+ for (dev = bus->devices; dev; dev = dev->next)
+ {
+ if (dev->descriptor.idVendor == VENDOR_ID_TI &&
+ (dev->descriptor.idProduct & DEVICE_ID_MASK) == DEVICE_ID)
+ {
+ p_data->udev = usb_open(dev);
+
+ if (p_data->udev)
+ {
+ if (p_data->verbose)
+ printf("\n\nfound device 0x%04x:0x%04x\n", dev->descriptor.idVendor, dev->descriptor.idProduct);
+
+ if (usb_set_configuration(p_data->udev, 1) < 0)
+ {
+ printf("could not set configuration\n");
+ res = RET_ERR;
+ }
+ if (do_files(p_data)) /* if an error occurred */
+ res = RET_ERR;
+ else
+ res = RET_OK;
+ }
+ }
+ }
+ }
+ }
+ usleep(500 * 1000); /* wait until we put another dot */
+ }
+ for (file_cntr = 0; file_cntr < MAX_FILES; file_cntr++) /* close all files */
+ if (p_data->fd[file_cntr])
+ close(p_data->fd[file_cntr]);
+ if (p_data->p_file)
+ free (p_data->p_file);
+ usb_close(p_data->udev);
+ return(res);
+ }
diff --git a/scripts/signGP.c b/scripts/signGP.c
index ab4715c..a11b533 100644
--- a/scripts/signGP.c
+++ b/scripts/signGP.c
@@ -255,7 +255,7 @@ int main(int argc, char *argv[])

/* Default to x-load.bin and 0x40200800. */
strcpy(ifname, "x-load.bin");
- loadaddr = 0x40200800;
+ loadaddr = 0x40200000;

if ((argc == 2) || (argc == 3) || (argc == 4))
strcpy(ifname, argv[1]);
--
1.7.7.3

chris...@gentex.com

unread,
Mar 30, 2012, 5:35:16 PM3/30/12
to x-lo...@googlegroups.com
Might I ask where you obtained the X-loader source you built with this patch? I'm running on the head from git://gitorious.org/x-loader/x-loader.git and my builds hang when I boot them via USB while your precompiled x-load.bin runs fine. I'm running on the BeagleBoard.

Thanks!

chris...@gentex.com

unread,
Apr 2, 2012, 8:11:16 AM4/2/12
to x-lo...@googlegroups.com
Never mind. It works with the PandaBoard, and upon further inspection, it just had to do with the BeagleBoard init sequence. Like the PandaBoard, Beagle must have the clocks enabled and prcm_init() called before the pin mux is configured, or it will hang.
Reply all
Reply to author
Forward
0 new messages