From 70eae1d242a9530cab4efa927bd1331b099fdd00 Mon Sep 17 00:00:00 2001 From: Thomas Tsou Date: Thu, 5 Aug 2010 11:48:41 -0700 Subject: usrp1: Add FX2 firmware files These firmware files for the usrp1 are imported from GNURadio. --- firmware/fx2/src/common/.gitignore | 17 ++ firmware/fx2/src/common/Makefile.am | 50 +++++ firmware/fx2/src/common/_startup.a51 | 80 ++++++++ firmware/fx2/src/common/_startup.a51.brittle | 78 +++++++ firmware/fx2/src/common/blink_leds.c | 36 ++++ firmware/fx2/src/common/build_eeprom.py | 182 +++++++++++++++++ firmware/fx2/src/common/check_mdelay.c | 37 ++++ firmware/fx2/src/common/check_udelay.c | 37 ++++ firmware/fx2/src/common/edit-gpif | 114 +++++++++++ firmware/fx2/src/common/fpga.h | 31 +++ firmware/fx2/src/common/fpga_load.c | 193 ++++++++++++++++++ firmware/fx2/src/common/fpga_load.h | 28 +++ firmware/fx2/src/common/gpif.c | 292 +++++++++++++++++++++++++++ firmware/fx2/src/common/gpif.gpf | Bin 0 -> 5281 bytes firmware/fx2/src/common/init_gpif.c | 59 ++++++ firmware/fx2/src/common/usrp_common.c | 109 ++++++++++ firmware/fx2/src/common/usrp_globals.h | 32 +++ firmware/fx2/src/common/vectors.a51 | 180 +++++++++++++++++ 18 files changed, 1555 insertions(+) create mode 100644 firmware/fx2/src/common/.gitignore create mode 100644 firmware/fx2/src/common/Makefile.am create mode 100644 firmware/fx2/src/common/_startup.a51 create mode 100644 firmware/fx2/src/common/_startup.a51.brittle create mode 100644 firmware/fx2/src/common/blink_leds.c create mode 100755 firmware/fx2/src/common/build_eeprom.py create mode 100644 firmware/fx2/src/common/check_mdelay.c create mode 100644 firmware/fx2/src/common/check_udelay.c create mode 100755 firmware/fx2/src/common/edit-gpif create mode 100644 firmware/fx2/src/common/fpga.h create mode 100644 firmware/fx2/src/common/fpga_load.c create mode 100644 firmware/fx2/src/common/fpga_load.h create mode 100755 firmware/fx2/src/common/gpif.c create mode 100755 firmware/fx2/src/common/gpif.gpf create mode 100644 firmware/fx2/src/common/init_gpif.c create mode 100644 firmware/fx2/src/common/usrp_common.c create mode 100644 firmware/fx2/src/common/usrp_globals.h create mode 100644 firmware/fx2/src/common/vectors.a51 (limited to 'firmware/fx2/src/common') diff --git a/firmware/fx2/src/common/.gitignore b/firmware/fx2/src/common/.gitignore new file mode 100644 index 000000000..d46c52c00 --- /dev/null +++ b/firmware/fx2/src/common/.gitignore @@ -0,0 +1,17 @@ +/*.ihx +/*.lnk +/*.lst +/*.map +/*.mem +/*.rel +/*.rst +/*.sym +/blink_leds.asm +/usrp_common.asm +/command_loop.asm +/fpga.asm +/*.asm +/usrp_gpif.c +/usrp_gpif_inline.h +/Makefile +/Makefile.in diff --git a/firmware/fx2/src/common/Makefile.am b/firmware/fx2/src/common/Makefile.am new file mode 100644 index 000000000..95232324d --- /dev/null +++ b/firmware/fx2/src/common/Makefile.am @@ -0,0 +1,50 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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 3, or (at your option) +# any later version. +# +# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +EXTRA_DIST = \ + _startup.a51 \ + blink_leds.c \ + check_mdelay.c \ + check_udelay.c \ + edit-gpif \ + fpga.h \ + fpga_load.h \ + fpga_load.c \ + gpif.c \ + gpif.gpf \ + init_gpif.c \ + usrp_common.c \ + usrp_globals.h \ + vectors.a51 \ + build_eeprom.py + +all: usrp_gpif.c + +usrp_gpif.c usrp_gpif_inline.h : gpif.c + srcdir=$(srcdir) $(PYTHON) $(srcdir)/edit-gpif $(srcdir)/gpif.c usrp_gpif.c usrp_gpif_inline.h + +CLEANFILES = \ + *.ihx *.lnk *.lst *.map *.mem *.rel *.rst *.sym *.asm *.lib \ + usrp_gpif.c usrp_gpif_inline.h + +DISTCLEANFILES = \ + *.ihx *.lnk *.lst *.map *.mem *.rel *.rst *.sym *.asm *.lib \ + usrp_gpif.c usrp_gpif_inline.h diff --git a/firmware/fx2/src/common/_startup.a51 b/firmware/fx2/src/common/_startup.a51 new file mode 100644 index 000000000..30a907857 --- /dev/null +++ b/firmware/fx2/src/common/_startup.a51 @@ -0,0 +1,80 @@ +;;; -*- asm -*- +;;; +;;; Copyright 2003,2004 Free Software Foundation, Inc. +;;; +;;; This file is part of GNU Radio +;;; +;;; GNU Radio 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 3, or (at your option) +;;; any later version. +;;; +;;; GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +;;; the Free Software Foundation, Inc., 51 Franklin Street, +;;; Boston, MA 02110-1301, USA. + + +;;; The default external memory initialization provided by sdcc is not +;;; appropriate to the FX2. This is derived from the sdcc code, but uses +;;; the FX2 specific _MPAGE sfr. + + + ;; .area XISEG (XDATA) ; the initialized external data area + ;; .area XINIT (CODE) ; the code space consts to init XISEG + .area XSEG (XDATA) ; zero initialized xdata + .area USBDESCSEG (XDATA) ; usb descriptors + + + .area CSEG (CODE) + + ;; sfr that sets upper address byte of MOVX using @r0 or @r1 + _MPAGE = 0x0092 + +__sdcc_external_startup:: + ;; This system is now compiled with the --no-xinit-opt + ;; which means that any initialized XDATA is handled + ;; inline by code in the GSINIT segs emitted for each file. + ;; + ;; We zero XSEG and all of the internal ram to ensure + ;; a known good state for uninitialized variables. + +; _mcs51_genRAMCLEAR() start + mov r0,#l_XSEG + mov a,r0 + orl a,#(l_XSEG >> 8) + jz 00002$ + mov r1,#((l_XSEG + 255) >> 8) + mov dptr,#s_XSEG + clr a + +00001$: movx @dptr,a + inc dptr + djnz r0,00001$ + djnz r1,00001$ + + ;; We're about to clear internal memory. This will overwrite + ;; the stack which contains our return address. + ;; Pop our return address into DPH, DPL +00002$: pop dph + pop dpl + + ;; R0 and A contain 0. This loop will execute 256 times. + ;; + ;; FWIW the first iteration writes direct address 0x00, + ;; which is the location of r0. We get lucky, we're + ;; writing the correct value (0) + +00003$: mov @r0,a + djnz r0,00003$ + + push dpl ; restore our return address + push dph + + mov dpl,#0 ; indicate that data init is still required + ret diff --git a/firmware/fx2/src/common/_startup.a51.brittle b/firmware/fx2/src/common/_startup.a51.brittle new file mode 100644 index 000000000..2996275cf --- /dev/null +++ b/firmware/fx2/src/common/_startup.a51.brittle @@ -0,0 +1,78 @@ +;;; -*- asm -*- +;;; +;;; Copyright 2003 Free Software Foundation, Inc. +;;; +;;; This file is part of GNU Radio +;;; +;;; GNU Radio 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 3, or (at your option) +;;; any later version. +;;; +;;; GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +;;; the Free Software Foundation, Inc., 51 Franklin Street, +;;; Boston, MA 02110-1301, USA. + + +;;; The default external memory initialization provided by sdcc is not +;;; appropriate to the FX2. This is derived from the sdcc code, but uses +;;; the FX2 specific _MPAGE sfr. + + + .area XISEG (XDATA) ; the initialized external data area + .area XINIT (CODE) ; the code space consts to init XISEG + .area XSEG (XDATA) ; zero initialized xdata + .area USBDESCSEG (XDATA); usb descriptors + + + ;; BIG TIME KLUDGE! + ;; Look at usrp_main.rst and count the bytes from our + ;; "normal return location" to the first instruction following + ;; the comment: "_mcs51_getRAMCLEAR () start" + + INSTRUCTION_BYTES_TO_SKIP = 0x29 ; valid for sdcc 2.4.0 + + + .area CSEG (CODE) + + ;; sfr that sets upper address byte of MOVX using @r0 or @r1 + _MPAGE = 0x0092 + +__sdcc_external_startup:: +; _mcs51_genXINIT() start + mov r1,#l_XINIT + mov a,r1 + orl a,#(l_XINIT >> 8) + jz 00003$ + mov r2,#((l_XINIT+255) >> 8) + mov dptr,#s_XINIT + mov r0,#s_XISEG + mov _MPAGE,#(s_XISEG >> 8) +00001$: clr a + movc a,@a+dptr + movx @r0,a + inc dptr + inc r0 + cjne r0,#0,00002$ + inc _MPAGE +00002$: djnz r1,00001$ + djnz r2,00001$ + mov _MPAGE,#0xFF +00003$: + + ;; Danger! Total KLUDGE! + ;; We pop the return address, add a magic number to it + ;; then jump to that address. Believe it or not, this + ;; looks like the least kludgy way to handle this, + ;; short of patching the compiler... + + pop dph + pop dpl + mov a,#INSTRUCTION_BYTES_TO_SKIP + jmp @a+dptr diff --git a/firmware/fx2/src/common/blink_leds.c b/firmware/fx2/src/common/blink_leds.c new file mode 100644 index 000000000..255c69733 --- /dev/null +++ b/firmware/fx2/src/common/blink_leds.c @@ -0,0 +1,36 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003 Free Software Foundation, Inc. + * + * 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 3 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., 51 Franklin Street, Boston, MA 02110-1301 USA + */ + +#include "usrp_common.h" + +void +main (void) +{ + unsigned short counter = 0; + + init_usrp (); + + while (1){ + unsigned char counter_high = counter >> 8; + set_led_0 (counter_high & 0x40); + set_led_1 (counter_high & 0x80); + counter++; + } +} diff --git a/firmware/fx2/src/common/build_eeprom.py b/firmware/fx2/src/common/build_eeprom.py new file mode 100755 index 000000000..023c4b3f5 --- /dev/null +++ b/firmware/fx2/src/common/build_eeprom.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python +# +# Copyright 2004,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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 3, or (at your option) +# any later version. +# +# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +import re +import sys +import os, os.path +from optparse import OptionParser + +# USB Vendor and Product ID's + +VID = 0xfffe # Free Software Folks +PID = 0x0002 # Universal Software Radio Peripheral + + +def hex_to_bytes (s): + if len (s) & 0x1: + raise ValueError, "Length must be even" + r = [] + for i in range (0, len(s), 2): + r.append (int (s[i:i+2], 16)) + return r + +def msb (x): + return (x >> 8) & 0xff + +def lsb (x): + return x & 0xff + +class ihx_rec (object): + def __init__ (self, addr, type, data): + self.addr = addr + self.type = type + self.data = data + +class ihx_file (object): + def __init__ (self): + self.pat = re.compile (r':[0-9A-F]{10,}') + def read (self, file): + r = [] + for line in file: + line = line.strip().upper () + if not self.pat.match (line): + raise ValueError, "Invalid hex record format" + bytes = hex_to_bytes (line[1:]) + sum = reduce (lambda x, y: x + y, bytes, 0) % 256 + if sum != 0: + raise ValueError, "Bad hex checksum" + lenx = bytes[0] + addr = (bytes[1] << 8) + bytes[2] + type = bytes[3] + data = bytes[4:-1] + if lenx != len (data): + raise ValueError, "Invalid hex record (bad length)" + if type != 0: + break; + r.append (ihx_rec (addr, type, data)) + + return r + +def get_code (filename): + """Read the intel hex format file FILENAME and return a tuple + of the code starting address and a list of bytes to load there. + """ + f = open (filename, 'r') + ifx = ihx_file () + r = ifx.read (f) + r.sort (lambda a,b: a.addr - b.addr) + code_start = r[0].addr + code_end = r[-1].addr + len (r[-1].data) + code_len = code_end - code_start + code = [0] * code_len + for x in r: + a = x.addr + l = len (x.data) + code[a-code_start:a-code_start+l] = x.data + return (code_start, code) + + +def build_eeprom_image (filename, rev): + """Build a ``C2 Load'' EEPROM image. + + For details on this format, see section 3.4.3 of + the EZ-USB FX2 Technical Reference Manual + """ + # get the code we want to run + (start_addr, bytes) = get_code (filename) + + devid = rev + + rom_header = [ + 0xC2, # boot from EEPROM + lsb (VID), + msb (VID), + lsb (PID), + msb (PID), + lsb (devid), + msb (devid), + 0 # configuration byte + ] + + # 4 byte header that indicates where to load + # the immediately follow code bytes. + code_header = [ + msb (len (bytes)), + lsb (len (bytes)), + msb (start_addr), + lsb (start_addr) + ] + + # writes 0 to CPUCS reg (brings FX2 out of reset) + trailer = [ + 0x80, + 0x01, + 0xe6, + 0x00, + 0x00 + ] + + image = rom_header + code_header + bytes + trailer + + assert (len (image) <= 256) + return image + +def build_shell_script (out, ihx_filename, rev): + + image = build_eeprom_image (ihx_filename, rev) + + out.write ('#!/bin/sh\n') + out.write ('usrper -x load_firmware /usr/local/share/usrp/rev%d/std.ihx\n' % rev) + out.write ('sleep 1\n') + + # print "len(image) =", len(image) + + i2c_addr = 0x50 + rom_addr = 0x00 + + hex_image = map (lambda x : "%02x" % (x,), image) + + while (len (hex_image) > 0): + l = min (len (hex_image), 16) + out.write ('usrper i2c_write 0x%02x %02x%s\n' % + (i2c_addr, rom_addr, ''.join (hex_image[0:l]))) + hex_image = hex_image[l:] + rom_addr = rom_addr + l + out.write ('sleep 1\n') + +if __name__ == '__main__': + usage = "usage: %prog -r REV [options] bootfile.ihx" + parser = OptionParser (usage=usage) + parser.add_option ("-r", "--rev", type="int", default=-1, + help="Specify USRP revision number REV (2 or 4)") + (options, args) = parser.parse_args () + if len (args) != 1: + parser.print_help () + sys.exit (1) + if options.rev < 0: + sys.stderr.write ( + "You must specify the USRP revision number (2 or 4) with -r REV\n") + sys.exit (1) + + ihx_filename = args[0] + + build_shell_script (sys.stdout, ihx_filename, options.rev) diff --git a/firmware/fx2/src/common/check_mdelay.c b/firmware/fx2/src/common/check_mdelay.c new file mode 100644 index 000000000..de1af47f6 --- /dev/null +++ b/firmware/fx2/src/common/check_mdelay.c @@ -0,0 +1,37 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003 Free Software Foundation, Inc. + * + * 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 3 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., 51 Franklin Street, Boston, MA 02110-1301 USA + */ + +#include "usrp_common.h" +#include "delay.h" + +void +main (void) +{ + init_usrp (); + + // CPUCS = 0; // 12 MHz + // CPUCS = bmCLKSPD0; // 24 MHz + CPUCS = bmCLKSPD1; // 48 MHz + + while (1){ + USRP_LED_REG ^= bmLED0; + mdelay (10); + } +} diff --git a/firmware/fx2/src/common/check_udelay.c b/firmware/fx2/src/common/check_udelay.c new file mode 100644 index 000000000..46885a067 --- /dev/null +++ b/firmware/fx2/src/common/check_udelay.c @@ -0,0 +1,37 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003 Free Software Foundation, Inc. + * + * 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 3 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., 51 Franklin Street, Boston, MA 02110-1301 USA + */ + +#include "usrp_common.h" +#include "delay.h" + +void +main (void) +{ + init_usrp (); + + // CPUCS = 0; // 12 MHz + // CPUCS = bmCLKSPD0; // 24 MHz + CPUCS = bmCLKSPD1; // 48 MHz + + while (1){ + USRP_LED_REG ^= bmLED0; + udelay (250); + } +} diff --git a/firmware/fx2/src/common/edit-gpif b/firmware/fx2/src/common/edit-gpif new file mode 100755 index 000000000..5367b75a5 --- /dev/null +++ b/firmware/fx2/src/common/edit-gpif @@ -0,0 +1,114 @@ +#!/usr/bin/env python +# -*- Python -*- +# +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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 3, or (at your option) +# any later version. +# +# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + + +# Edit the gpif.c file generated by the Cypress GPIF Designer Tool and +# produce usrp_gpif.c, and usrp_gpif_inline.h, files suitable for our +# uses. + +import re +import string +import sys + +def check_flow_state (line, flow_state_dict): + mo = re.match (r'/\* Wave (\d) FlowStates \*/ (.*),', line) + if mo: + wave = int (mo.group (1)) + data = mo.group (2) + split = data.split (',', 8) + v = map (lambda x : int (x, 16), split) + # print "%s, %s" % (wave, data) + # print "split: ", split + # print "v : ", v + flow_state_dict[wave] = v + + +def delta (xseq, yseq): + # set subtraction + z = [] + for x in xseq: + if x not in yseq: + z.append (x) + return z + + +def write_define (output, name, pairs): + output.write ('#define %s()\t\\\n' % name) + output.write ('do {\t\t\t\t\t\\\n') + for reg, val in pairs: + output.write ('%14s = 0x%02x;\t\t\t\\\n' % (reg, val)) + output.write ('} while (0)\n\n') + +def write_inlines (output, dict): + regs = ['FLOWSTATE', 'FLOWLOGIC', 'FLOWEQ0CTL', 'FLOWEQ1CTL', 'FLOWHOLDOFF', + 'FLOWSTB', 'FLOWSTBEDGE', 'FLOWSTBHPERIOD', 'GPIFHOLDAMOUNT'] + + READ_FLOW_STATE = 2 + WRITE_FLOW_STATE = 3 + + read_info = zip (regs, dict[READ_FLOW_STATE]) + write_info = zip (regs, dict[WRITE_FLOW_STATE]) + + output.write ('''/* + * Machine generated by "edit-gpif". Do not edit by hand. + */ + +''') + write_define (output, 'setup_flowstate_common', read_info) + write_define (output, 'setup_flowstate_read', delta (read_info, write_info)) + write_define (output, 'setup_flowstate_write', delta (write_info, read_info)) + + +def edit_gpif (input_name, output_name, inline_name): + input = open (input_name, 'r') + output = open (output_name, 'w') + inline = open (inline_name, 'w') + flow_state_dict = {} + + output.write ('''/* + * Machine generated by "edit-gpif". Do not edit by hand. + */ + +''') + + while 1: + line = input.readline () + line = string.replace (line, '\r','') + line = re.sub (r' *$', r'', line) + + check_flow_state (line, flow_state_dict) + + line = re.sub (r'#include', r'// #include', line) + line = re.sub (r'xdata ', r'', line) + if re.search (r'GpifInit', line): + break + + output.write (line) + + output.close () + write_inlines (inline, flow_state_dict) + inline.close () + + +# gpif.c usrp_gpif.c usrp_gpif_inline.h +edit_gpif (sys.argv[1], sys.argv[2], sys.argv[3]) diff --git a/firmware/fx2/src/common/fpga.h b/firmware/fx2/src/common/fpga.h new file mode 100644 index 000000000..6cd5de8e2 --- /dev/null +++ b/firmware/fx2/src/common/fpga.h @@ -0,0 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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 3, or (at your option) + * any later version. + * + * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ +#ifndef INCLUDED_FPGA_H +#define INCLUDED_FPGA_H + +#include "fpga_load.h" + +#if defined(HAVE_USRP2) +#include "fpga_rev2.h" +#endif + +#endif /* INCLUDED_FPGA_H */ diff --git a/firmware/fx2/src/common/fpga_load.c b/firmware/fx2/src/common/fpga_load.c new file mode 100644 index 000000000..c3ae9e707 --- /dev/null +++ b/firmware/fx2/src/common/fpga_load.c @@ -0,0 +1,193 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003 Free Software Foundation, Inc. + * + * 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 3 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., 51 Franklin Street, Boston, MA 02110-1301 USA + */ + +#include "usrp_common.h" +#include "fpga_load.h" +#include "delay.h" + +/* + * setup altera FPGA serial load (PS). + * + * On entry: + * don't care + * + * On exit: + * ALTERA_DCLK = 0 + * ALTERA_NCONFIG = 1 + * ALTERA_NSTATUS = 1 (input) + */ +unsigned char +fpga_load_begin (void) +{ + USRP_ALTERA_CONFIG &= ~bmALTERA_BITS; // clear all bits (NCONFIG low) + udelay (40); // wait 40 us + USRP_ALTERA_CONFIG |= bmALTERA_NCONFIG; // set NCONFIG high + + if (UC_BOARD_HAS_FPGA){ + // FIXME should really cap this loop with a counter so we + // don't hang forever on a hardware failure. + while ((USRP_ALTERA_CONFIG & bmALTERA_NSTATUS) == 0) // wait for NSTATUS to go high + ; + } + + // ready to xfer now + + return 1; +} + +/* + * clock out the low bit of bits. + * + * On entry: + * ALTERA_DCLK = 0 + * ALTERA_NCONFIG = 1 + * ALTERA_NSTATUS = 1 (input) + * + * On exit: + * ALTERA_DCLK = 0 + * ALTERA_NCONFIG = 1 + * ALTERA_NSTATUS = 1 (input) + */ + + +#if 0 + +static void +clock_out_config_byte (unsigned char bits) +{ + unsigned char i; + + // clock out configuration byte, least significant bit first + + for (i = 0; i < 8; i++){ + + USRP_ALTERA_CONFIG = ((USRP_ALTERA_CONFIG & ~bmALTERA_DATA0) | ((bits & 1) ? bmALTERA_DATA0 : 0)); + USRP_ALTERA_CONFIG |= bmALTERA_DCLK; /* set DCLK to 1 */ + USRP_ALTERA_CONFIG &= ~bmALTERA_DCLK; /* set DCLK to 0 */ + + bits = bits >> 1; + } +} + +#else + +static void +clock_out_config_byte (unsigned char bits) _naked +{ + _asm + mov a, dpl + + rrc a + mov _bitALTERA_DATA0,c + setb _bitALTERA_DCLK + clr _bitALTERA_DCLK + + rrc a + mov _bitALTERA_DATA0,c + setb _bitALTERA_DCLK + clr _bitALTERA_DCLK + + rrc a + mov _bitALTERA_DATA0,c + setb _bitALTERA_DCLK + clr _bitALTERA_DCLK + + rrc a + mov _bitALTERA_DATA0,c + setb _bitALTERA_DCLK + clr _bitALTERA_DCLK + + rrc a + mov _bitALTERA_DATA0,c + setb _bitALTERA_DCLK + clr _bitALTERA_DCLK + + rrc a + mov _bitALTERA_DATA0,c + setb _bitALTERA_DCLK + clr _bitALTERA_DCLK + + rrc a + mov _bitALTERA_DATA0,c + setb _bitALTERA_DCLK + clr _bitALTERA_DCLK + + rrc a + mov _bitALTERA_DATA0,c + setb _bitALTERA_DCLK + clr _bitALTERA_DCLK + + ret + + _endasm; +} + +#endif + +static void +clock_out_bytes (unsigned char bytecount, + unsigned char xdata *p) +{ + while (bytecount-- > 0) + clock_out_config_byte (*p++); +} + +/* + * Transfer block of bytes from packet to FPGA serial configuration port + * + * On entry: + * ALTERA_DCLK = 0 + * ALTERA_NCONFIG = 1 + * ALTERA_NSTATUS = 1 (input) + * + * On exit: + * ALTERA_DCLK = 0 + * ALTERA_NCONFIG = 1 + * ALTERA_NSTATUS = 1 (input) + */ +unsigned char +fpga_load_xfer (xdata unsigned char *p, unsigned char bytecount) +{ + clock_out_bytes (bytecount, p); + return 1; +} + +/* + * check for successful load... + */ +unsigned char +fpga_load_end (void) +{ + unsigned char status = USRP_ALTERA_CONFIG; + + if (!UC_BOARD_HAS_FPGA) // always true if we don't have FPGA + return 1; + + if ((status & bmALTERA_NSTATUS) == 0) // failed to program + return 0; + + if ((status & bmALTERA_CONF_DONE) == bmALTERA_CONF_DONE) + return 1; // everything's cool + + // I don't think this should happen. It indicates that + // programming is still in progress. + + return 0; +} diff --git a/firmware/fx2/src/common/fpga_load.h b/firmware/fx2/src/common/fpga_load.h new file mode 100644 index 000000000..7c36a04c8 --- /dev/null +++ b/firmware/fx2/src/common/fpga_load.h @@ -0,0 +1,28 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003 Free Software Foundation, Inc. + * + * 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 3 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., 51 Franklin Street, Boston, MA 02110-1301 USA + */ + +#ifndef INCLUDED_FPGA_LOAD_H +#define INCLUDED_FPGA_LOAD_H + +unsigned char fpga_load_begin (void); +unsigned char fpga_load_xfer (xdata unsigned char *p, unsigned char len); +unsigned char fpga_load_end (void); + +#endif /* INCLUDED_FPGA_LOAD_H */ diff --git a/firmware/fx2/src/common/gpif.c b/firmware/fx2/src/common/gpif.c new file mode 100755 index 000000000..489e6e81a --- /dev/null +++ b/firmware/fx2/src/common/gpif.c @@ -0,0 +1,292 @@ +// This program configures the General Programmable Interface (GPIF) for FX2. +// Please do not modify sections of text which are marked as "DO NOT EDIT ...". +// +// DO NOT EDIT ... +// GPIF Initialization +// Interface Timing Async +// Internal Ready Init IntRdy=1 +// CTL Out Tristate-able Binary +// SingleWrite WF Select 1 +// SingleRead WF Select 0 +// FifoWrite WF Select 3 +// FifoRead WF Select 2 +// Data Bus Idle Drive Tristate +// END DO NOT EDIT + +// DO NOT EDIT ... +// GPIF Wave Names +// Wave 0 = singlerd +// Wave 1 = singlewr +// Wave 2 = FIFORd +// Wave 3 = FIFOWr + +// GPIF Ctrl Outputs Level +// CTL 0 = WEN# CMOS +// CTL 1 = REN# CMOS +// CTL 2 = OE# CMOS +// CTL 3 = CLRST CMOS +// CTL 4 = unused CMOS +// CTL 5 = BOGUS CMOS + +// GPIF Rdy Inputs +// RDY0 = EF# +// RDY1 = FF# +// RDY2 = unused +// RDY3 = unused +// RDY4 = unused +// RDY5 = TCXpire +// FIFOFlag = FIFOFlag +// IntReady = IntReady +// END DO NOT EDIT +// DO NOT EDIT ... +// +// GPIF Waveform 0: singlerd +// +// Interval 0 1 2 3 4 5 6 Idle (7) +// _________ _________ _________ _________ _________ _________ _________ _________ +// +// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val +// DataMode NO Data NO Data NO Data NO Data NO Data NO Data NO Data +// NextData SameData SameData SameData SameData SameData SameData SameData +// Int Trig No Int No Int No Int No Int No Int No Int No Int +// IF/Wait Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 +// Term A +// LFunc +// Term B +// Branch1 +// Branch0 +// Re-Exec +// Sngl/CRC Default Default Default Default Default Default Default +// WEN# 0 0 0 0 0 0 0 0 +// REN# 0 0 0 0 0 0 0 0 +// OE# 0 0 0 0 0 0 0 0 +// CLRST 0 0 0 0 0 0 0 0 +// unused 0 0 0 0 0 0 0 0 +// BOGUS 0 0 0 0 0 0 0 0 +// +// END DO NOT EDIT +// DO NOT EDIT ... +// +// GPIF Waveform 1: singlewr +// +// Interval 0 1 2 3 4 5 6 Idle (7) +// _________ _________ _________ _________ _________ _________ _________ _________ +// +// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val +// DataMode Activate Activate Activate Activate Activate Activate Activate +// NextData SameData SameData SameData SameData SameData SameData SameData +// Int Trig No Int No Int No Int No Int No Int No Int No Int +// IF/Wait Wait 1 IF Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 +// Term A EF# +// LFunc AND +// Term B EF# +// Branch1 ThenIdle +// Branch0 ElseIdle +// Re-Exec No +// Sngl/CRC Default Default Default Default Default Default Default +// WEN# 0 1 1 1 1 1 1 0 +// REN# 0 0 0 0 0 0 0 0 +// OE# 0 0 0 0 0 0 0 0 +// CLRST 0 0 0 0 0 0 0 0 +// unused 0 0 0 0 0 0 0 0 +// BOGUS 0 0 0 0 0 0 0 0 +// +// END DO NOT EDIT +// DO NOT EDIT ... +// +// GPIF Waveform 2: FIFORd +// +// Interval 0 1 2 3 4 5 6 Idle (7) +// _________ _________ _________ _________ _________ _________ _________ _________ +// +// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val +// DataMode NO Data Activate NO Data NO Data NO Data NO Data NO Data +// NextData SameData SameData SameData SameData SameData SameData SameData +// Int Trig No Int No Int No Int No Int No Int No Int No Int +// IF/Wait Wait 1 IF Wait 1 IF Wait 1 Wait 1 Wait 1 +// Term A TCXpire TCXpire +// LFunc AND AND +// Term B TCXpire TCXpire +// Branch1 Then 2 ThenIdle +// Branch0 Else 1 ElseIdle +// Re-Exec No No +// Sngl/CRC Default Default Default Default Default Default Default +// WEN# 0 0 0 0 0 0 0 0 +// REN# 0 0 0 0 0 0 0 0 +// OE# 1 1 1 0 0 0 0 0 +// CLRST 0 0 0 0 0 0 0 0 +// unused 0 0 0 0 0 0 0 0 +// BOGUS 0 0 0 0 0 0 0 0 +// +// END DO NOT EDIT +// DO NOT EDIT ... +// +// GPIF Waveform 3: FIFOWr +// +// Interval 0 1 2 3 4 5 6 Idle (7) +// _________ _________ _________ _________ _________ _________ _________ _________ +// +// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val +// DataMode NO Data Activate Activate Activate Activate Activate Activate +// NextData SameData SameData SameData SameData SameData SameData SameData +// Int Trig No Int No Int No Int No Int No Int No Int No Int +// IF/Wait Wait 1 IF Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 +// Term A TCXpire +// LFunc AND +// Term B TCXpire +// Branch1 ThenIdle +// Branch0 Else 1 +// Re-Exec No +// Sngl/CRC Default Default Default Default Default Default Default +// WEN# 0 0 0 0 0 0 0 0 +// REN# 0 0 0 0 0 0 0 0 +// OE# 0 0 0 0 0 0 0 0 +// CLRST 0 0 0 0 0 0 0 0 +// unused 0 0 0 0 0 0 0 0 +// BOGUS 0 0 0 0 0 0 0 0 +// +// END DO NOT EDIT + +// GPIF Program Code + +// DO NOT EDIT ... +#include "fx2.h" +#include "fx2regs.h" +#include "fx2sdly.h" // SYNCDELAY macro +// END DO NOT EDIT + +// DO NOT EDIT ... +const char xdata WaveData[128] = +{ +// Wave 0 +/* LenBr */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, +/* Opcode*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* Output*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* LFun */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, +// Wave 1 +/* LenBr */ 0x01, 0x3F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, +/* Opcode*/ 0x22, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, +/* Output*/ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, +/* LFun */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, +// Wave 2 +/* LenBr */ 0x01, 0x11, 0x01, 0x3F, 0x01, 0x01, 0x01, 0x07, +/* Opcode*/ 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, +/* Output*/ 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, +/* LFun */ 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x3F, +// Wave 3 +/* LenBr */ 0x01, 0x39, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, +/* Opcode*/ 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, +/* Output*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* LFun */ 0x00, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, +}; +// END DO NOT EDIT + +// DO NOT EDIT ... +const char xdata FlowStates[36] = +{ +/* Wave 0 FlowStates */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* Wave 1 FlowStates */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* Wave 2 FlowStates */ 0x81,0x2D,0x26,0x00,0x04,0x04,0x03,0x02,0x00, +/* Wave 3 FlowStates */ 0x81,0x2D,0x21,0x00,0x04,0x04,0x03,0x02,0x00, +}; +// END DO NOT EDIT + +// DO NOT EDIT ... +const char xdata InitData[7] = +{ +/* Regs */ 0xA0,0x00,0x00,0x00,0xEE,0x4E,0x00 +}; +// END DO NOT EDIT + +// TO DO: You may add additional code below. + +void GpifInit( void ) +{ + BYTE i; + + // Registers which require a synchronization delay, see section 15.14 + // FIFORESET FIFOPINPOLAR + // INPKTEND OUTPKTEND + // EPxBCH:L REVCTL + // GPIFTCB3 GPIFTCB2 + // GPIFTCB1 GPIFTCB0 + // EPxFIFOPFH:L EPxAUTOINLENH:L + // EPxFIFOCFG EPxGPIFFLGSEL + // PINFLAGSxx EPxFIFOIRQ + // EPxFIFOIE GPIFIRQ + // GPIFIE GPIFADRH:L + // UDMACRCH:L EPxGPIFTRIG + // GPIFTRIG + + // Note: The pre-REVE EPxGPIFTCH/L register are affected, as well... + // ...these have been replaced by GPIFTC[B3:B0] registers + + // 8051 doesn't have access to waveform memories 'til + // the part is in GPIF mode. + + IFCONFIG = 0xEE; + // IFCLKSRC=1 , FIFOs executes on internal clk source + // xMHz=1 , 48MHz internal clk rate + // IFCLKOE=0 , Don't drive IFCLK pin signal at 48MHz + // IFCLKPOL=0 , Don't invert IFCLK pin signal from internal clk + // ASYNC=1 , master samples asynchronous + // GSTATE=1 , Drive GPIF states out on PORTE[2:0], debug WF + // IFCFG[1:0]=10, FX2 in GPIF master mode + + GPIFABORT = 0xFF; // abort any waveforms pending + + GPIFREADYCFG = InitData[ 0 ]; + GPIFCTLCFG = InitData[ 1 ]; + GPIFIDLECS = InitData[ 2 ]; + GPIFIDLECTL = InitData[ 3 ]; + GPIFWFSELECT = InitData[ 5 ]; + GPIFREADYSTAT = InitData[ 6 ]; + + // use dual autopointer feature... + AUTOPTRSETUP = 0x07; // inc both pointers, + // ...warning: this introduces pdata hole(s) + // ...at E67B (XAUTODAT1) and E67C (XAUTODAT2) + + // source + AUTOPTRH1 = MSB( &WaveData ); + AUTOPTRL1 = LSB( &WaveData ); + + // destination + AUTOPTRH2 = 0xE4; + AUTOPTRL2 = 0x00; + + // transfer + for ( i = 0x00; i < 128; i++ ) + { + EXTAUTODAT2 = EXTAUTODAT1; + } + +// Configure GPIF Address pins, output initial value, + PORTCCFG = 0xFF; // [7:0] as alt. func. GPIFADR[7:0] + OEC = 0xFF; // and as outputs + PORTECFG |= 0x80; // [8] as alt. func. GPIFADR[8] + OEE |= 0x80; // and as output + +// ...OR... tri-state GPIFADR[8:0] pins +// PORTCCFG = 0x00; // [7:0] as port I/O +// OEC = 0x00; // and as inputs +// PORTECFG &= 0x7F; // [8] as port I/O +// OEE &= 0x7F; // and as input + +// GPIF address pins update when GPIFADRH/L written + SYNCDELAY; // + GPIFADRH = 0x00; // bits[7:1] always 0 + SYNCDELAY; // + GPIFADRL = 0x00; // point to PERIPHERAL address 0x0000 + +// Configure GPIF FlowStates registers for Wave 0 of WaveData + FLOWSTATE = FlowStates[ 0 ]; + FLOWLOGIC = FlowStates[ 1 ]; + FLOWEQ0CTL = FlowStates[ 2 ]; + FLOWEQ1CTL = FlowStates[ 3 ]; + FLOWHOLDOFF = FlowStates[ 4 ]; + FLOWSTB = FlowStates[ 5 ]; + FLOWSTBEDGE = FlowStates[ 6 ]; + FLOWSTBHPERIOD = FlowStates[ 7 ]; +} + diff --git a/firmware/fx2/src/common/gpif.gpf b/firmware/fx2/src/common/gpif.gpf new file mode 100755 index 000000000..a954ac193 Binary files /dev/null and b/firmware/fx2/src/common/gpif.gpf differ diff --git a/firmware/fx2/src/common/init_gpif.c b/firmware/fx2/src/common/init_gpif.c new file mode 100644 index 000000000..edde919be --- /dev/null +++ b/firmware/fx2/src/common/init_gpif.c @@ -0,0 +1,59 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003 Free Software Foundation, Inc. + * + * 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 3 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., 51 Franklin Street, Boston, MA 02110-1301 USA + */ + +#include "usrp_common.h" + +// These are the tables generated by the Cypress GPIF Designer + +extern const char WaveData[128]; +extern const char FlowStates[36]; +extern const char InitData[7]; + +// The tool is kind of screwed up, in that it doesn't configure some +// of the ports correctly. We just use their tables and handle the +// initialization ourselves. They also declare that their static +// initialized data is in xdata, which screws us too. + +void +init_gpif (void) +{ + // we've already setup IFCONFIG before calling this... + + GPIFABORT = 0xFF; // abort any waveforms pending + SYNCDELAY; + + GPIFREADYCFG = InitData[ 0 ]; + GPIFCTLCFG = InitData[ 1 ]; + GPIFIDLECS = InitData[ 2 ]; + GPIFIDLECTL = InitData[ 3 ]; + // Hmmm, what's InitData[ 4 ] ... + GPIFWFSELECT = InitData[ 5 ]; + // GPIFREADYSTAT = InitData[ 6 ]; // I think this register is read only... + + { + BYTE i; + + for (i = 0; i < 128; i++){ + GPIF_WAVE_DATA[i] = WaveData[i]; + } + } + + FLOWSTATE = 0; /* ensure it's off */ +} diff --git a/firmware/fx2/src/common/usrp_common.c b/firmware/fx2/src/common/usrp_common.c new file mode 100644 index 000000000..0998653c2 --- /dev/null +++ b/firmware/fx2/src/common/usrp_common.c @@ -0,0 +1,109 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003 Free Software Foundation, Inc. + * + * 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 3 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., 51 Franklin Street, Boston, MA 02110-1301 USA + */ + +/* + * common code for USRP + */ + +#include "usrp_common.h" + +void init_board (void); + +void +init_usrp (void) +{ + CPUCS = bmCLKSPD1; // CPU runs @ 48 MHz + CKCON = 0; // MOVX takes 2 cycles + + // IFCLK is generated internally and runs at 48 MHz; GPIF "master mode" + + IFCONFIG = bmIFCLKSRC | bm3048MHZ | bmIFCLKOE | bmIFCLKPOL | bmIFGPIF; + SYNCDELAY; + + // configure IO ports (B and D are used by GPIF) + + IOA = bmPORT_A_INITIAL; // Port A initial state + OEA = bmPORT_A_OUTPUTS; // Port A direction register + + IOC = bmPORT_C_INITIAL; // Port C initial state + OEC = bmPORT_C_OUTPUTS; // Port C direction register + + IOE = bmPORT_E_INITIAL; // Port E initial state + OEE = bmPORT_E_OUTPUTS; // Port E direction register + + + // REVCTL = bmDYN_OUT | bmENH_PKT; // highly recommended by docs + // SYNCDELAY; + + // configure end points + + EP1OUTCFG = bmVALID | bmBULK; SYNCDELAY; + EP1INCFG = bmVALID | bmBULK | bmIN; SYNCDELAY; + + EP2CFG = bmVALID | bmBULK | bmQUADBUF; SYNCDELAY; // 512 quad bulk OUT + EP4CFG = 0; SYNCDELAY; // disabled + EP6CFG = bmVALID | bmBULK | bmQUADBUF | bmIN; SYNCDELAY; // 512 quad bulk IN + EP8CFG = 0; SYNCDELAY; // disabled + + // reset FIFOs + + FIFORESET = bmNAKALL; SYNCDELAY; + FIFORESET = 2; SYNCDELAY; + // FIFORESET = 4; SYNCDELAY; + FIFORESET = 6; SYNCDELAY; + // FIFORESET = 8; SYNCDELAY; + FIFORESET = 0; SYNCDELAY; + + // configure end point FIFOs + + // let core see 0 to 1 transistion of autoout bit + + EP2FIFOCFG = bmWORDWIDE; SYNCDELAY; + EP2FIFOCFG = bmAUTOOUT | bmWORDWIDE; SYNCDELAY; + EP6FIFOCFG = bmAUTOIN | bmWORDWIDE; SYNCDELAY; + + + // prime the pump + +#if 0 + EP2BCL = 0x80; SYNCDELAY; + EP2BCL = 0x80; SYNCDELAY; + EP2BCL = 0x80; SYNCDELAY; + EP2BCL = 0x80; SYNCDELAY; +#endif + + EP0BCH = 0; SYNCDELAY; + + // arm EP1OUT so we can receive "out" packets (TRM pg 8-8) + + EP1OUTBC = 0; SYNCDELAY; + + EP2GPIFFLGSEL = 0x01; SYNCDELAY; // For EP2OUT, GPIF uses EF flag + EP6GPIFFLGSEL = 0x02; SYNCDELAY; // For EP6IN, GPIF uses FF flag + + // set autoin length for EP6 + // FIXME should be f(enumeration) + + EP6AUTOINLENH = (512) >> 8; SYNCDELAY; // this is the length for high speed + EP6AUTOINLENL = (512) & 0xff; SYNCDELAY; + + init_board (); +} + diff --git a/firmware/fx2/src/common/usrp_globals.h b/firmware/fx2/src/common/usrp_globals.h new file mode 100644 index 000000000..445e9e6b4 --- /dev/null +++ b/firmware/fx2/src/common/usrp_globals.h @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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 3, or (at your option) + * any later version. + * + * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ +#ifndef _USRP_GLOBALS_H_ +#define _USRP_GLOBALS_H_ + +extern unsigned char g_tx_enable; +extern unsigned char g_rx_enable; +extern unsigned char g_fpga_reset; +extern unsigned char g_rx_overrun; +extern unsigned char g_tx_underrun; + + +#endif /* _USRP_GLOBALS_H_ */ diff --git a/firmware/fx2/src/common/vectors.a51 b/firmware/fx2/src/common/vectors.a51 new file mode 100644 index 000000000..e9382ab84 --- /dev/null +++ b/firmware/fx2/src/common/vectors.a51 @@ -0,0 +1,180 @@ +;;; -*- asm -*- +;;; +;;; Copyright 2003 Free Software Foundation, Inc. +;;; +;;; This file is part of GNU Radio +;;; +;;; GNU Radio 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 3, or (at your option) +;;; any later version. +;;; +;;; GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +;;; the Free Software Foundation, Inc., 51 Franklin Street, +;;; Boston, MA 02110-1301, USA. +;;; + +;;; Interrupt vectors. + +;;; N.B. This object module must come first in the list of modules + + .module vectors + +;;; ---------------------------------------------------------------- +;;; standard FX2 interrupt vectors +;;; ---------------------------------------------------------------- + + .area CSEG (CODE) + .area GSINIT (CODE) + .area CSEG (CODE) +__standard_interrupt_vector:: +__reset_vector:: + ljmp s_GSINIT + + ;; 13 8-byte entries. We point them all at __isr_nop + ljmp __isr_nop ; 3 bytes + .ds 5 ; + 5 = 8 bytes for vector slot + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + +__isr_nop:: + reti + +;;; ---------------------------------------------------------------- +;;; the FIFO/GPIF autovector. 14 4-byte entries. +;;; must start on a 128 byte boundary. +;;; ---------------------------------------------------------------- + + . = __reset_vector + 0x0080 + +__fifo_gpif_autovector:: + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + + +;;; ---------------------------------------------------------------- +;;; the USB autovector. 32 4-byte entries. +;;; must start on a 256 byte boundary. +;;; ---------------------------------------------------------------- + + . = __reset_vector + 0x0100 + +__usb_autovector:: + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop -- cgit v1.2.3 From b96088b692a5c44974919ee36e253b6ea8c51972 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Tue, 31 Aug 2010 16:44:30 -0700 Subject: EEPROM burning in UHD. Changed some USB device handle stuff. Added usrp_init_eeprom.cpp. Hacked up the firmware makefile to behave and to generate .bin EEPROM images instead of IHX. --- firmware/fx2/src/common/build_eeprom.py | 103 +++-------------------- firmware/fx2/src/usrp1/Makefile.am | 58 +++---------- host/include/uhd/transport/usb_device_handle.hpp | 4 +- host/lib/transport/libusb1_base.cpp | 52 ++---------- host/lib/transport/libusb1_base.hpp | 10 --- host/lib/transport/libusb1_device_handle.cpp | 18 ++-- host/lib/usrp/usrp1/mboard_impl.cpp | 11 +++ host/lib/usrp/usrp1/usrp1_ctrl.cpp | 63 +++++++++++++- host/lib/usrp/usrp1/usrp1_ctrl.hpp | 31 +++++++ host/lib/usrp/usrp1/usrp1_iface.cpp | 21 +++-- host/lib/usrp/usrp1/usrp1_impl.cpp | 34 ++++---- host/utils/CMakeLists.txt | 4 + host/utils/usrp_init_eeprom.cpp | 69 +++++++++++++++ 13 files changed, 255 insertions(+), 223 deletions(-) create mode 100644 host/utils/usrp_init_eeprom.cpp (limited to 'firmware/fx2/src/common') diff --git a/firmware/fx2/src/common/build_eeprom.py b/firmware/fx2/src/common/build_eeprom.py index 023c4b3f5..ae62587db 100755 --- a/firmware/fx2/src/common/build_eeprom.py +++ b/firmware/fx2/src/common/build_eeprom.py @@ -29,15 +29,6 @@ from optparse import OptionParser VID = 0xfffe # Free Software Folks PID = 0x0002 # Universal Software Radio Peripheral - - -def hex_to_bytes (s): - if len (s) & 0x1: - raise ValueError, "Length must be even" - r = [] - for i in range (0, len(s), 2): - r.append (int (s[i:i+2], 16)) - return r def msb (x): return (x >> 8) & 0xff @@ -45,56 +36,6 @@ def msb (x): def lsb (x): return x & 0xff -class ihx_rec (object): - def __init__ (self, addr, type, data): - self.addr = addr - self.type = type - self.data = data - -class ihx_file (object): - def __init__ (self): - self.pat = re.compile (r':[0-9A-F]{10,}') - def read (self, file): - r = [] - for line in file: - line = line.strip().upper () - if not self.pat.match (line): - raise ValueError, "Invalid hex record format" - bytes = hex_to_bytes (line[1:]) - sum = reduce (lambda x, y: x + y, bytes, 0) % 256 - if sum != 0: - raise ValueError, "Bad hex checksum" - lenx = bytes[0] - addr = (bytes[1] << 8) + bytes[2] - type = bytes[3] - data = bytes[4:-1] - if lenx != len (data): - raise ValueError, "Invalid hex record (bad length)" - if type != 0: - break; - r.append (ihx_rec (addr, type, data)) - - return r - -def get_code (filename): - """Read the intel hex format file FILENAME and return a tuple - of the code starting address and a list of bytes to load there. - """ - f = open (filename, 'r') - ifx = ihx_file () - r = ifx.read (f) - r.sort (lambda a,b: a.addr - b.addr) - code_start = r[0].addr - code_end = r[-1].addr + len (r[-1].data) - code_len = code_end - code_start - code = [0] * code_len - for x in r: - a = x.addr - l = len (x.data) - code[a-code_start:a-code_start+l] = x.data - return (code_start, code) - - def build_eeprom_image (filename, rev): """Build a ``C2 Load'' EEPROM image. @@ -102,9 +43,11 @@ def build_eeprom_image (filename, rev): the EZ-USB FX2 Technical Reference Manual """ # get the code we want to run - (start_addr, bytes) = get_code (filename) + f = open(filename, 'rb') + bytes = f.read() devid = rev + start_addr = 0 #prove me wrong rom_header = [ 0xC2, # boot from EEPROM @@ -135,41 +78,18 @@ def build_eeprom_image (filename, rev): 0x00 ] - image = rom_header + code_header + bytes + trailer + image = rom_header + code_header + [ord(c) for c in bytes] + trailer assert (len (image) <= 256) - return image - -def build_shell_script (out, ihx_filename, rev): - - image = build_eeprom_image (ihx_filename, rev) - - out.write ('#!/bin/sh\n') - out.write ('usrper -x load_firmware /usr/local/share/usrp/rev%d/std.ihx\n' % rev) - out.write ('sleep 1\n') - - # print "len(image) =", len(image) - - i2c_addr = 0x50 - rom_addr = 0x00 - - hex_image = map (lambda x : "%02x" % (x,), image) - - while (len (hex_image) > 0): - l = min (len (hex_image), 16) - out.write ('usrper i2c_write 0x%02x %02x%s\n' % - (i2c_addr, rom_addr, ''.join (hex_image[0:l]))) - hex_image = hex_image[l:] - rom_addr = rom_addr + l - out.write ('sleep 1\n') + return image if __name__ == '__main__': - usage = "usage: %prog -r REV [options] bootfile.ihx" + usage = "usage: %prog -r REV [options] bootfile.bin outfile.bin" parser = OptionParser (usage=usage) parser.add_option ("-r", "--rev", type="int", default=-1, help="Specify USRP revision number REV (2 or 4)") (options, args) = parser.parse_args () - if len (args) != 1: + if len (args) != 2: parser.print_help () sys.exit (1) if options.rev < 0: @@ -177,6 +97,11 @@ if __name__ == '__main__': "You must specify the USRP revision number (2 or 4) with -r REV\n") sys.exit (1) - ihx_filename = args[0] + infile = args[0] + outfile = args[1] + + image = "".join(chr(c) for c in build_eeprom_image(infile, options.rev)) - build_shell_script (sys.stdout, ihx_filename, options.rev) + f = open(outfile, 'wb') + f.write(str(image)) + f.close() diff --git a/firmware/fx2/src/usrp1/Makefile.am b/firmware/fx2/src/usrp1/Makefile.am index 5586e83a3..a964f9198 100644 --- a/firmware/fx2/src/usrp1/Makefile.am +++ b/firmware/fx2/src/usrp1/Makefile.am @@ -19,12 +19,12 @@ # Boston, MA 02110-1301, USA. # -firmware2dir = $(prefix)/share/usrp/rev2 -firmware2_DATA = std.ihx +#firmwaredir = $(prefix)/share/uhd/images +#firmware_DATA = usrp1_fw.ihx -# we put the same stuff in the rev4 directory -firmware4dir = $(prefix)/share/usrp/rev4 -firmware4_DATA = std.ihx +#eepromdir = $(firmwaredir) +#eepromfile = eeprom_boot.ihx +#eeprom_DATA = usrp1_eeprom.bin EXTRA_DIST = \ edit-gpif \ @@ -85,11 +85,6 @@ EXECUTABLES = \ STARTUP = _startup.rel -noinst_SCRIPTS = \ - burn-usrp2-eeprom \ - burn-usrp4-eeprom - - .c.rel: $(XCC) $(FW_INCLUDES) $(DEFINES) \ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< @@ -107,34 +102,11 @@ EEPROM_BOOT_OBJS = eeprom_boot.rel eeprom_init.rel $(STARTUP) eeprom_boot.ihx: $(EEPROM_BOOT_OBJS) $(LIBDEP) $(XCC) $(LINKOPTS) -o $@ $(EEPROM_BOOT_OBJS) -burn-usrp2-eeprom: eeprom_boot.ihx - $(PYTHON) $(srcdir)/../common/build_eeprom.py -r2 eeprom_boot.ihx > $@ - chmod +x $@ - -burn-usrp4-eeprom: eeprom_boot.ihx - $(PYTHON) $(srcdir)/../common/build_eeprom.py -r4 eeprom_boot.ihx > $@ - chmod +x $@ - - -BLINK_LEDS_OBJS = blink_leds.rel usrp_common.rel board_specific.rel spi.rel $(STARTUP) - -blink_leds.ihx: $(BLINK_LEDS_OBJS) $(LIBDEP) - $(XCC) $(LINKOPTS) -o $@ $(BLINK_LEDS_OBJS) - - -CHECK_MDELAY_OBJS = check_mdelay.rel usrp_common.rel board_specific.rel spi.rel $(STARTUP) - -check_mdelay.ihx: $(CHECK_MDELAY_OBJS) $(LIBDEP) - $(XCC) $(LINKOPTS) -o $@ $(CHECK_MDELAY_OBJS) - - - -CHECK_UDELAY_OBJS = check_udelay.rel usrp_common.rel board_specific.rel spi.rel $(STARTUP) - -check_udelay.ihx: $(CHECK_UDELAY_OBJS) $(LIBDEP) - $(XCC) $(LINKOPTS) -o $@ $(CHECK_UDELAY_OBJS) - +usrp1_eeprom.bin: eeprom_boot.bin + $(PYTHON) ../common/build_eeprom.py -r4 $< $@ +eeprom_boot.bin: eeprom_boot.ihx + objcopy -I ihex -O binary $< $@ USRP_OBJS = \ vectors.rel \ @@ -146,25 +118,23 @@ std.ihx: $(USRP_OBJS) $(LIBDEP) $(XCC) $(LINKOPTS) -o $@ $(USRP_OBJS) CLEANFILES = \ - *.ihx *.lnk *.lst *.map *.mem *.rel *.rst *.sym *.asm *.lib \ - usrp_gpif.c usrp_gpif_inline.h \ - burn-usrp2-eeprom \ - burn-usrp4-eeprom + *.ihx *.lnk *.lst *.map *.mem *.rel *.rst *.sym *.asm *.lib *.bin \ + usrp_gpif.c usrp_gpif_inline.h DISTCLEANFILES = \ - *.ihx *.lnk *.lst *.map *.mem *.rel *.rst *.sym *.asm *.lib + *.ihx *.lnk *.lst *.map *.mem *.rel *.rst *.sym *.asm *.lib *.bin # build gpif stuff -all: usrp_gpif.c +all: usrp_gpif.c std.ihx usrp1_eeprom.bin usrp_gpif.c usrp_gpif_inline.h : gpif.c srcdir=$(srcdir) $(PYTHON) $(srcdir)/edit-gpif $(srcdir)/gpif.c usrp_gpif.c usrp_gpif_inline.h - # dependencies usrp_main.rel: usrp_gpif_inline.h + #usrp_main.rel: fpga.h usrp_common.h ../../include/usrp_commands.h usrp_gpif_inline.h ../../include/usrp_config.h usrp_rev2_regs.h ../../include/fx2regs.h #usrp_common.rel: usrp_common.h ../../include/usrp_commands.h ../../include/usrp_config.h usrp_rev2_regs.h ../../include/fx2regs.h #fpga.rel: usrp_common.h ../../include/usrp_commands.h fpga.h ../../include/usrp_config.h usrp_rev2_regs.h ../../include/fx2regs.h diff --git a/host/include/uhd/transport/usb_device_handle.hpp b/host/include/uhd/transport/usb_device_handle.hpp index 78c78f6b5..c3eb72b00 100644 --- a/host/include/uhd/transport/usb_device_handle.hpp +++ b/host/include/uhd/transport/usb_device_handle.hpp @@ -68,9 +68,9 @@ public: /*! * Return a vector of USB devices on this host - * \return a vector of USB device handles + * \return a vector of USB device handles that match vid and pid */ - static UHD_API std::vector get_device_list(); + static UHD_API std::vector get_device_list(boost::uint16_t vid, boost::uint16_t pid); }; //namespace usb diff --git a/host/lib/transport/libusb1_base.cpp b/host/lib/transport/libusb1_base.cpp index 92dcd969f..e21c39aa3 100644 --- a/host/lib/transport/libusb1_base.cpp +++ b/host/lib/transport/libusb1_base.cpp @@ -24,22 +24,6 @@ using namespace uhd::transport; /********************************************************** * Helper Methods **********************************************************/ -/* - * Check for FSF device - * Compare the device's descriptor Vendor ID - * \param dev pointer to libusb_device - * \return true if Vendor ID matches 0xfffe - */ -bool check_fsf_device(libusb_device *dev) -{ - libusb_device_descriptor desc; - - if (libusb_get_device_descriptor(dev, &desc) < 0) { - UHD_ASSERT_THROW("USB: failed to get device descriptor"); - } - - return desc.idVendor == 0xfffe; -} /********************************************************** * libusb namespace @@ -52,37 +36,16 @@ void libusb::init(libusb_context **ctx, int debug_level) libusb_set_debug(*ctx, debug_level); } -std::vector libusb::get_fsf_device_list(libusb_context *ctx) -{ - libusb_device **libusb_dev_list; - std::vector fsf_dev_list; - - ssize_t dev_cnt = libusb_get_device_list(ctx, &libusb_dev_list); - - //find the FSF devices - for (ssize_t i = 0; i < dev_cnt; i++) { - libusb_device *dev = libusb_dev_list[i]; - - if (check_fsf_device(dev)) - fsf_dev_list.push_back(dev); - else - libusb_unref_device(dev); - } - - libusb_free_device_list(libusb_dev_list, 0); - - return fsf_dev_list; -} - libusb_device_handle *libusb::open_device(libusb_context *ctx, usb_device_handle::sptr handle) { libusb_device_handle *dev_handle = NULL; - std::vector fsf_dev_list = get_fsf_device_list(ctx); + libusb_device **libusb_dev_list; + size_t dev_cnt = libusb_get_device_list(ctx, &libusb_dev_list); //find and open the USB device - for (size_t i = 0; i < fsf_dev_list.size(); i++) { - libusb_device *dev = fsf_dev_list[i]; + for (size_t i = 0; i < dev_cnt; i++) { + libusb_device *dev = libusb_dev_list[i]; if (compare_device(dev, handle)) { libusb_open(dev, &dev_handle); @@ -96,7 +59,8 @@ libusb_device_handle *libusb::open_device(libusb_context *ctx, return dev_handle; } - +//note: changed order of checks so it only tries to get_serial and get_device_address if vid and pid match +//doing this so it doesn't try to open the device if it's not ours bool libusb::compare_device(libusb_device *dev, usb_device_handle::sptr handle) { @@ -108,12 +72,12 @@ bool libusb::compare_device(libusb_device *dev, libusb_device_descriptor libusb_desc; if (libusb_get_device_descriptor(dev, &libusb_desc) < 0) return false; - if (serial != get_serial(dev)) - return false; if (vendor_id != libusb_desc.idVendor) return false; if (product_id != libusb_desc.idProduct) return false; + if (serial != get_serial(dev)) + return false; if (device_addr != libusb_get_device_address(dev)) return false; diff --git a/host/lib/transport/libusb1_base.hpp b/host/lib/transport/libusb1_base.hpp index 442f89ded..abe5e22a2 100644 --- a/host/lib/transport/libusb1_base.hpp +++ b/host/lib/transport/libusb1_base.hpp @@ -41,16 +41,6 @@ namespace libusb { */ void init(libusb_context **ctx, int debug_level); - /* - * Get a list of Free Software Foundation devices (Vendor ID 0xfffe) - * As opposed to the public USB device handle interface, which returns - * generic identifiers, this call returns device pointers speficic - * to libusb. - * \param ctx the libusb context used for init - * \return a vector of libusb devices - */ - std::vector get_fsf_device_list(libusb_context *ctx); - /* * Open the device specified by a generic handle * Find the libusb_device cooresponding to the generic handle diff --git a/host/lib/transport/libusb1_device_handle.cpp b/host/lib/transport/libusb1_device_handle.cpp index 5d9d8faf0..43d0f0e26 100644 --- a/host/lib/transport/libusb1_device_handle.cpp +++ b/host/lib/transport/libusb1_device_handle.cpp @@ -17,6 +17,7 @@ #include "libusb1_base.hpp" #include +#include using namespace uhd::transport; @@ -91,19 +92,24 @@ usb_device_handle::sptr make_usb_device_handle(libusb_device *dev) device_addr)); } -std::vector usb_device_handle::get_device_list() +std::vector usb_device_handle::get_device_list(boost::uint16_t vid, boost::uint16_t pid) { libusb_context *ctx = NULL; - std::vector libusb_device_list; + libusb_device** libusb_device_list; std::vector device_handle_list; + libusb_device_descriptor desc; libusb::init(&ctx, libusb_debug_level); - libusb_device_list = libusb::get_fsf_device_list(ctx); - - for (size_t i = 0; i < libusb_device_list.size(); i++) { + size_t dev_size = libusb_get_device_list(ctx, &libusb_device_list); + for (size_t i = 0; i < dev_size; i++) { libusb_device *dev = libusb_device_list[i]; - device_handle_list.push_back(make_usb_device_handle(dev)); + if(libusb_get_device_descriptor(dev, &desc) < 0) { + UHD_ASSERT_THROW("USB: failed to get device descriptor"); + } + if(desc.idVendor == vid && desc.idProduct == pid) { + device_handle_list.push_back(make_usb_device_handle(dev)); + } } libusb_exit(ctx); diff --git a/host/lib/usrp/usrp1/mboard_impl.cpp b/host/lib/usrp/usrp1/mboard_impl.cpp index 75129c32f..1409855cb 100644 --- a/host/lib/usrp/usrp1/mboard_impl.cpp +++ b/host/lib/usrp/usrp1/mboard_impl.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -318,6 +319,16 @@ void usrp1_impl::mboard_get(const wax::obj &key_, wax::obj &val) **********************************************************************/ void usrp1_impl::mboard_set(const wax::obj &key, const wax::obj &val) { + if(key.type() == typeid(std::string)) { + if(key.as() == "load_eeprom") { + std::string usrp1_fpga_image = val.as(); + std::cout << "USRP1 EEPROM image: " << usrp1_fpga_image << std::endl; + _ctrl_transport->usrp_load_eeprom(val.as()); + } + + return; + } + //handle the get request conditioned on the key switch(key.as()){ diff --git a/host/lib/usrp/usrp1/usrp1_ctrl.cpp b/host/lib/usrp/usrp1/usrp1_ctrl.cpp index 98226b738..451129ef5 100644 --- a/host/lib/usrp/usrp1/usrp1_ctrl.cpp +++ b/host/lib/usrp/usrp1/usrp1_ctrl.cpp @@ -25,6 +25,7 @@ #include #include #include +#include using namespace uhd; @@ -203,7 +204,7 @@ public: return -1; } } - //type 0x00 is end + //type 0x01 is end else if (type == 0x01) { usrp_control_write(FX2_FIRMWARE_LOAD, 0xe600, 0, &reset_n, 1); @@ -283,6 +284,55 @@ public: return 0; } + int usrp_load_eeprom(std::string filestring) + { + const char *filename = filestring.c_str(); + const uint16_t i2c_addr = 0x50; + + //FIXME: verify types + int len; + unsigned int addr; + unsigned char data[256]; + unsigned char sendbuf[17]; + + int ret; + std::ifstream file; + file.open(filename, std::ifstream::in); + + if (!file.good()) { + std::cerr << "cannot open EEPROM input file" << std::endl; + return -1; + } + + file.read((char *)data, 256); + len = file.gcount(); + + if(len == 256) { + std::cerr << "error: image size too large" << std::endl; + file.close(); + return -1; + } + + const int pagesize = 16; + addr = 0; + while(len > 0) { + sendbuf[0] = addr; + memcpy(sendbuf+1, &data[addr], len > pagesize ? pagesize : len); + ret = usrp_i2c_write(i2c_addr, sendbuf, (len > pagesize ? pagesize : len)+1); + if (ret < 0) { + std::cerr << "error: usrp_i2c_write failed: "; + std::cerr << ret << std::endl; + file.close(); + return -1; + } + addr += pagesize; + len -= pagesize; + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + } + file.close(); + return 0; + } + int usrp_set_led(int led_num, bool on) { @@ -371,6 +421,17 @@ public: return usrp_control_write(request, value, index, 0, 0); } + int usrp_i2c_write(boost::uint16_t i2c_addr, unsigned char *buf, boost::uint16_t len) + { + return usrp_control_write(VRQ_I2C_WRITE, i2c_addr, 0, buf, len); + } + + int usrp_i2c_read(boost::uint16_t i2c_addr, unsigned char *buf, boost::uint16_t len) + { + return usrp_control_read(VRQ_I2C_READ, i2c_addr, 0, buf, len); + } + + private: uhd::transport::usb_control::sptr _ctrl_transport; diff --git a/host/lib/usrp/usrp1/usrp1_ctrl.hpp b/host/lib/usrp/usrp1/usrp1_ctrl.hpp index deedec4e8..a02d9f96c 100644 --- a/host/lib/usrp/usrp1/usrp1_ctrl.hpp +++ b/host/lib/usrp/usrp1/usrp1_ctrl.hpp @@ -49,6 +49,13 @@ public: */ virtual int usrp_load_fpga(std::string filename) = 0; + /*! + * Load USB descriptor file in Intel HEX format into EEPROM + * \param filename name of EEPROM image + * \return 0 on success, error code otherwise + */ + virtual int usrp_load_eeprom(std::string filestring) = 0; + /*! * Set led usrp * \param led_num which LED to control (0 or 1) @@ -127,6 +134,30 @@ public: unsigned char *buff, boost::uint16_t length) = 0; + /*! + * Perform an I2C write + * \param i2c_addr I2C device address + * \param buf data to be written + * \param len length of data in bytes + * \return number of bytes written or error + */ + + virtual int usrp_i2c_write(boost::uint16_t i2c_addr, + unsigned char *buf, + boost::uint16_t len) = 0; + + /*! + * Perform an I2C read + * \param i2c_addr I2C device address + * \param buf data to be read + * \param len length of data in bytes + * \return number of bytes read or error + */ + + virtual int usrp_i2c_read(boost::uint16_t i2c_addr, + unsigned char *buf, + boost::uint16_t len) = 0; + }; #endif /* INCLUDED_USRP_CTRL_HPP */ diff --git a/host/lib/usrp/usrp1/usrp1_iface.cpp b/host/lib/usrp/usrp1/usrp1_iface.cpp index 8756a21c9..4bc18dd16 100644 --- a/host/lib/usrp/usrp1/usrp1_iface.cpp +++ b/host/lib/usrp/usrp1/usrp1_iface.cpp @@ -109,18 +109,19 @@ public: ******************************************************************/ static const size_t max_i2c_data_bytes = 64; + //TODO: make this handle EEPROM page sizes. right now you can't write over a 16-byte boundary. + //to accomplish this you'll have to have addr offset as a separate parameter. + void write_i2c(boost::uint8_t addr, const byte_vector_t &bytes) { UHD_ASSERT_THROW(bytes.size() < max_i2c_data_bytes); unsigned char buff[max_i2c_data_bytes]; - std::copy(bytes.begin(), bytes.end(), buff); + std::copy(bytes.begin(), bytes.end(), buff); - int ret = _ctrl_transport->usrp_control_write(VRQ_I2C_WRITE, - addr & 0xff, - 0, - buff, - bytes.size()); + int ret = _ctrl_transport->usrp_i2c_write(addr & 0xff, + buff, + bytes.size()); // TODO throw and catch i2c failures during eeprom read if (iface_debug && (ret < 0)) @@ -132,11 +133,9 @@ public: UHD_ASSERT_THROW(num_bytes < max_i2c_data_bytes); unsigned char buff[max_i2c_data_bytes]; - int ret = _ctrl_transport->usrp_control_read(VRQ_I2C_READ, - addr & 0xff, - 0, - buff, - num_bytes); + int ret = _ctrl_transport->usrp_i2c_read(addr & 0xff, + buff, + num_bytes); // TODO throw and catch i2c failures during eeprom read if (iface_debug && ((ret < 0) || (unsigned)ret < (num_bytes))) { diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 3c3306525..8ad148274 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -34,6 +34,11 @@ using namespace uhd; using namespace uhd::usrp; using namespace uhd::transport; +const boost::uint16_t USRP1_VENDOR_ID = 0xfffe; +const boost::uint16_t USRP1_PRODUCT_ID = 0x0002; +const boost::uint16_t FX2_VENDOR_ID = 0x04b4; +const boost::uint16_t FX2_PRODUCT_ID = 0x8613; + const std::vector usrp1_impl::_dboard_slots = boost::assign::list_of (usrp1_impl::DBOARD_SLOT_A)(usrp1_impl::DBOARD_SLOT_B) ; @@ -54,33 +59,32 @@ static device_addrs_t usrp1_find(const device_addr_t &hint) ); std::cout << "USRP1 firmware image: " << usrp1_fw_image << std::endl; + boost::uint16_t vid = hint.has_key("uninit") ? FX2_VENDOR_ID : USRP1_VENDOR_ID; + boost::uint16_t pid = hint.has_key("uninit") ? FX2_PRODUCT_ID : USRP1_PRODUCT_ID; + //see what we got on the USB bus std::vector device_list = - usb_device_handle::get_device_list(); + usb_device_handle::get_device_list(vid, pid); + + if(device_list.size() == 0) return usrp1_addrs; //return nothing if no USRPs found //find the usrps and load firmware BOOST_FOREACH(usb_device_handle::sptr handle, device_list) { - if (handle->get_vendor_id() == 0xfffe && - handle->get_product_id() == 0x0002) { - usb_control::sptr ctrl_transport = usb_control::make(handle); usrp_ctrl::sptr usrp_ctrl = usrp_ctrl::make(ctrl_transport); usrp_ctrl->usrp_load_firmware(usrp1_fw_image); - } } - //get descriptors again with serial number - device_list = usb_device_handle::get_device_list(); + //get descriptors again with serial number, but using the initialized VID/PID now since we have firmware + vid = USRP1_VENDOR_ID; + pid = USRP1_PRODUCT_ID; + device_list = usb_device_handle::get_device_list(vid, pid); BOOST_FOREACH(usb_device_handle::sptr handle, device_list) { - if (handle->get_vendor_id() == 0xfffe && - handle->get_product_id() == 0x0002) { - device_addr_t new_addr; new_addr["type"] = "usrp1"; new_addr["serial"] = handle->get_serial(); usrp1_addrs.push_back(new_addr); - } } return usrp1_addrs; @@ -99,17 +103,15 @@ static device::sptr usrp1_make(const device_addr_t &device_addr) //try to match the given device address with something on the USB bus std::vector device_list = - usb_device_handle::get_device_list(); + usb_device_handle::get_device_list(USRP1_VENDOR_ID, USRP1_PRODUCT_ID); //create data and control transports usb_zero_copy::sptr data_transport; usrp_ctrl::sptr usrp_ctrl; - BOOST_FOREACH(usb_device_handle::sptr handle, device_list) { - if (handle->get_vendor_id() == 0xfffe && - handle->get_product_id() == 0x0002 && - handle->get_serial() == device_addr["serial"]) { + BOOST_FOREACH(usb_device_handle::sptr handle, device_list) { + if (handle->get_serial() == device_addr["serial"]) { usb_control::sptr ctrl_transport = usb_control::make(handle); usrp_ctrl = usrp_ctrl::make(ctrl_transport); usrp_ctrl->usrp_load_fpga(usrp1_fpga_image); diff --git a/host/utils/CMakeLists.txt b/host/utils/CMakeLists.txt index c349a9018..9d788b06c 100644 --- a/host/utils/CMakeLists.txt +++ b/host/utils/CMakeLists.txt @@ -39,9 +39,13 @@ TARGET_LINK_LIBRARIES(usrp2_addr_burner uhd) ADD_EXECUTABLE(usrp_burn_db_eeprom usrp_burn_db_eeprom.cpp) TARGET_LINK_LIBRARIES(usrp_burn_db_eeprom uhd) +ADD_EXECUTABLE(usrp_init_eeprom usrp_init_eeprom.cpp) +TARGET_LINK_LIBRARIES(usrp_init_eeprom uhd) + INSTALL(TARGETS usrp2_addr_burner usrp_burn_db_eeprom + usrp_init_eeprom RUNTIME DESTINATION ${PKG_DATA_DIR}/utils ) diff --git a/host/utils/usrp_init_eeprom.cpp b/host/utils/usrp_init_eeprom.cpp new file mode 100644 index 000000000..28c7c5745 --- /dev/null +++ b/host/utils/usrp_init_eeprom.cpp @@ -0,0 +1,69 @@ +// +// Copyright 2010 Ettus Research LLC +// +// 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 3 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, see . +// + +#include +#include +#include +#include +#include +#include + +namespace po = boost::program_options; + +int UHD_SAFE_MAIN(int argc, char *argv[]){ + po::options_description desc("Allowed options"); + desc.add_options() + ("help", "help message") + ("image", po::value(), "IHX image file") + ; + + po::variables_map vm; + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + + //print the help message + if (vm.count("help")){ + std::cout << boost::format("USRP EEPROM initialization %s") % desc << std::endl; + return ~0; + } + + //load the options into the address + uhd::device_addr_t device_addr; + device_addr["type"] = "usrp1"; + device_addr["uninit"] = "yeah"; //tell find to look for an uninitialized FX2 + + //find and create a control transport to do the writing. + + uhd::device_addrs_t found_addrs = uhd::device::find(device_addr); + + if (found_addrs.size() == 0){ + std::cerr << "No uninitialized USRP devices found" << std::endl; + return ~0; + } + + for (size_t i = 0; i < found_addrs.size(); i++){ + std::cout << "Writing EEPROM data..." << std::endl; + //uhd::device_addrs_t devs = uhd::device::find(found_addrs[i]); + uhd::device::sptr dev = uhd::device::make(found_addrs[i]); + wax::obj mb = (*dev)[uhd::usrp::DEVICE_PROP_MBOARD]; + mb[std::string("load_eeprom")] = vm["image"].as(); + } + + + std::cout << "Power-cycle the usrp for the changes to take effect." << std::endl; + return 0; +} -- cgit v1.2.3